TrinityCore
boss_cthun.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: Boss_Cthun
20SD%Complete: 95
21SDComment: Darkglare tracking issue
22SDCategory: Temple of Ahn'Qiraj
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "InstanceScript.h"
27#include "Map.h"
28#include "MapReference.h"
29#include "ObjectAccessor.h"
30#include "ScriptedCreature.h"
31#include "temple_of_ahnqiraj.h"
32#include "TemporarySummon.h"
33
34/*
35 * This is a 2 phases events. Here follows an explanation of the main events and transition between phases and sub-phases.
36 *
37 * The first phase is the EYE phase: the Eye of C'Thun is active and C'thun is not active.
38 * During this phase, the "Eye of C'Thun" alternates between 2 sub-phases:
39 * - PHASE_EYE_GREEN_BEAM:
40 * 50 sec phase during which the Eye mainly casts its Green Beam every 3 sec.
41 * - PHASE_EYE_RED_BEAM:
42 * 35 sec phase during which the Eye casts its red beam every sec.
43 * This EYE phase ends when the "Eye of C'Thun" is killed. Then starts the CTHUN phase.
44 *
45 * The second phase is the CTHUN phase. The Eye of C'Thun is not active and C'Thun is active.
46 * This phase starts with the transformation of the Eye into C'Thun (PHASE_CTHUN_TRANSITION).
47 * After the transformation, C'Thun alternates between 2 sub-phases:
48 * - PHASE_CTHUN_STOMACH:
49 * - C'Thun is almost insensible to all damage (99% damage reduction).
50 * - It spawns 2 tentacles in its stomach.
51 * - C'Thun swallows players.
52 * - This sub-phase ends when the 2 tentacles are killed. Swallowed players are regurgitate.
53 *
54 * - PHASE_CTHUN_WEAK:
55 * - weakened C'Thun takes normal damage.
56 * - This sub-phase ends after 45 secs.
57 *
58 * This CTHUN phase ends when C'Thun is killed
59 *
60 * Note:
61 * - the current phase is stored in the instance data to be easily shared between the eye and cthun.
62 */
63
65{
67
68 // Main Phase 1 - EYE
71
72 // Main Phase 2 - CTHUN
76
78};
79
81{
82 // ***** Main Phase 1 ********
83 //Eye Spells
87 SPELL_RED_COLORATION = 22518, //Probably not the right spell but looks similar
88
89 //Eye Tentacles Spells
91
92 //Claw Tentacles Spells
95
96 // ***** Main Phase 2 ******
97 //Body spells
98 //SPELL_CARAPACE_CTHUN = 26156 //Was removed from client dbcs
100 SPELL_PURPLE_COLORATION = 22581, //Probably not the right spell but looks similar
101
102 //Eye Tentacles Spells
103 //SAME AS PHASE1
104
105 //Giant Claw Tentacles
107
108 //Also casts Hamstring
110
111 //Giant Eye Tentacles
112 //CHAIN CASTS "SPELL_GREEN_BEAM"
113
114 //Stomach Spells
118};
119
121{
123};
124
126{
127 //Text emote
129
130 // ****** Out of Combat ******
131 // Random Wispers - No txt only sound
132 // The random sound is chosen by the client.
134};
135
136//Stomach Teleport positions
137#define STOMACH_X -8562.0f
138#define STOMACH_Y 2037.0f
139#define STOMACH_Z -70.0f
140#define STOMACH_O 5.05f
141
142//Flesh tentacle positions
144{
145 { -8571.0f, 1990.0f, -98.0f, 1.22f},
146 { -8525.0f, 1994.0f, -98.0f, 2.12f},
147};
148
149//Kick out position
150const Position KickPos = { -8545.0f, 1984.0f, -96.0f, 0.0f};
151
153{
154public:
155 boss_eye_of_cthun() : CreatureScript("boss_eye_of_cthun") { }
156
157 CreatureAI* GetAI(Creature* creature) const override
158 {
159 return GetAQ40AI<eye_of_cthunAI>(creature);
160 }
161
163 {
164 eye_of_cthunAI(Creature* creature) : ScriptedAI(creature)
165 {
166 Initialize();
167 instance = creature->GetInstanceScript();
168
169 SetCombatMovement(false);
170 }
171
173 {
174 //Phase information
175 PhaseTimer = 50000; //First dark glare in 50 seconds
176
177 //Eye beam phase 50 seconds
178 BeamTimer = 3000;
179 EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam
180 ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam)
181
182 //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks)
183 DarkGlareTick = 0;
184 DarkGlareTickTimer = 1000;
185 DarkGlareAngle = 0;
186 ClockWise = false;
187 }
188
190
191 //Global variables
193
194 //Eye beam phase
198
199 //Dark Glare phase
204
205 void Reset() override
206 {
207 Initialize();
208
209 //Reset flags
213 me->SetUninteractible(false);
214 me->SetVisible(true);
215
216 //Reset Phase
218
219 //to avoid having a following void zone
221 if (pPortal)
223 }
224
225 void JustEngagedWith(Unit* /*who*/) override
226 {
229 }
230
231 void SpawnEyeTentacle(float x, float y)
232 {
233 if (Creature* Spawned = DoSpawnCreature(NPC_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500ms))
235 if (Spawned->AI())
236 Spawned->AI()->AttackStart(target);
237 }
238
239 void UpdateAI(uint32 diff) override
240 {
241 //Check if we have a target
242 if (!UpdateVictim())
243 return;
244
245 uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE);
246 if (currentPhase == PHASE_EYE_GREEN_BEAM || currentPhase == PHASE_EYE_RED_BEAM)
247 {
248 // EyeTentacleTimer
249 if (EyeTentacleTimer <= diff)
250 {
251 //Spawn the 8 Eye Tentacles in the corret spots
252 SpawnEyeTentacle(0, 20); //south
253 SpawnEyeTentacle(10, 10); //south west
254 SpawnEyeTentacle(20, 0); //west
255 SpawnEyeTentacle(10, -10); //north west
256
257 SpawnEyeTentacle(0, -20); //north
258 SpawnEyeTentacle(-10, -10); //north east
259 SpawnEyeTentacle(-20, 0); // east
260 SpawnEyeTentacle(-10, 10); // south east
261
262 EyeTentacleTimer = 45000;
263 } else EyeTentacleTimer -= diff;
264 }
265
266 switch (currentPhase)
267 {
269 //BeamTimer
270 if (BeamTimer <= diff)
271 {
272 //SPELL_GREEN_BEAM
274 {
276 DoCast(target, SPELL_GREEN_BEAM);
277
278 //Correctly update our target
279 me->SetTarget(target->GetGUID());
280 }
281
282 //Beam every 3 seconds
283 BeamTimer = 3000;
284 } else BeamTimer -= diff;
285
286 //ClawTentacleTimer
287 if (ClawTentacleTimer <= diff)
288 {
290 {
291 Creature* Spawned = nullptr;
292
293 //Spawn claw tentacle on the random target
295
296 if (Spawned && Spawned->AI())
297 Spawned->AI()->AttackStart(target);
298 }
299
300 //One claw tentacle every 12.5 seconds
301 ClawTentacleTimer = 12500;
302 } else ClawTentacleTimer -= diff;
303
304 //PhaseTimer
305 if (PhaseTimer <= diff)
306 {
307 //Switch to Dark Beam
309
312
313 //Remove any target
315
316 //Select random target for dark beam to start on
318 {
319 //Face our target
321 DarkGlareTickTimer = 1000;
322 DarkGlareTick = 0;
323 ClockWise = RAND(true, false);
324 }
325
326 //Add red coloration to C'thun
328
329 //Freeze animation
332 me->StopMoving();
333
334 //Darkbeam for 35 seconds
335 PhaseTimer = 35000;
336 } else PhaseTimer -= diff;
337
338 break;
339
341 if (DarkGlareTick < 35)
342 {
343 if (DarkGlareTickTimer <= diff)
344 {
345 //Set angle and cast
346 if (ClockWise)
348 else
350
351 me->StopMoving();
352
353 //Actual dark glare cast, maybe something missing here?
354 DoCast(me, SPELL_DARK_GLARE, false);
355
356 //Increase tick
358
359 //1 second per tick
360 DarkGlareTickTimer = 1000;
361 } else DarkGlareTickTimer -= diff;
362 }
363
364 //PhaseTimer
365 if (PhaseTimer <= diff)
366 {
367 //Switch to Eye Beam
369
370 BeamTimer = 3000;
371 ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam)
372
374
375 //Remove Red coloration from c'thun
378
379 //set it back to aggressive
381
382 //Eye Beam for 50 seconds
383 PhaseTimer = 50000;
384 } else PhaseTimer -= diff;
385
386 break;
387
388 //Transition phase
390 //Remove any target
392 me->SetHealth(0);
393 me->SetVisible(false);
394 break;
395
396 //Dead phase
397 case PHASE_CTHUN_DONE:
399 if (pPortal)
400 pPortal->DespawnOrUnsummon();
401
403 break;
404 }
405 }
406
407 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
408 {
410 {
413 //Only if it will kill
414 if (damage < me->GetHealth())
415 return;
416
417 //Fake death in phase 0 or 1 (green beam or dark glare phase)
419
420 //Remove Red coloration from c'thun
422
423 //Reset to normal emote state and prevent select and attack
425 me->SetUninteractible(true);
426
427 //Remove Target field
429
430 //Death animation/respawning;
432
433 me->SetHealth(0);
434 damage = 0;
435
438 break;
439
440 case PHASE_CTHUN_DONE:
441 //Allow death here
442 return;
443
444 default:
445 //Prevent death in these phases
446 damage = 0;
447 return;
448 }
449 }
450 };
451
452};
453
455{
456public:
457 boss_cthun() : CreatureScript("boss_cthun") { }
458
459 CreatureAI* GetAI(Creature* creature) const override
460 {
461 return GetAQ40AI<cthunAI>(creature);
462 }
463
464 struct cthunAI : public BossAI
465 {
466 cthunAI(Creature* creature) : BossAI(creature, DATA_CTHUN)
467 {
468 Initialize();
469 SetCombatMovement(false);
470 }
471
473 {
474 //One random wisper every 90 - 300 seconds
475 WisperTimer = 90000;
476
477 //Phase information
478 PhaseTimer = 10000; //Emerge in 10 seconds
479
480 //No hold player for transition
482
483 //Body Phase
484 EyeTentacleTimer = 30000;
486 GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat)
487 GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat)
488 StomachAcidTimer = 4000; //Every 4 seconds
489 StomachEnterTimer = 10000; //Every 10 seconds
490 StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer
491 StomachEnterTarget.Clear(); //Target to be teleported to stomach
492 }
493
494 //Out of combat whisper timer
496
497 //Global variables
499
500 //-------------------
501
502 //Phase transition
504
505 //Body Phase
514
515 //Stomach map, bool = true then in stomach
516 std::unordered_map<ObjectGuid, bool> Stomach_Map;
517
518 void Reset() override
519 {
520 Initialize();
521 _Reset();
522
523 //Clear players in stomach and outside
524 Stomach_Map.clear();
525
526 //Reset flags
529 me->SetUninteractible(true);
530 me->SetVisible(false);
531
533 }
534
535 void SpawnEyeTentacle(float x, float y)
536 {
538 if (Spawned && Spawned->AI())
539 if (Unit* target = SelectRandomNotStomach())
540 Spawned->AI()->AttackStart(target);
541 }
542
544 {
545 if (Stomach_Map.empty())
546 return nullptr;
547
548 std::unordered_map<ObjectGuid, bool>::const_iterator i = Stomach_Map.begin();
549
550 std::list<Unit*> temp;
551 std::list<Unit*>::const_iterator j;
552
553 //Get all players in map
554 while (i != Stomach_Map.end())
555 {
556 //Check for valid player
557 Unit* unit = ObjectAccessor::GetUnit(*me, i->first);
558
559 //Only units out of stomach
560 if (unit && i->second == false)
561 temp.push_back(unit);
562
563 ++i;
564 }
565
566 if (temp.empty())
567 return nullptr;
568
569 j = temp.begin();
570
571 //Get random but only if we have more than one unit on threat list
572 if (temp.size() > 1)
573 advance(j, rand32() % (temp.size() - 1));
574
575 return (*j);
576 }
577
578 void UpdateAI(uint32 diff) override
579 {
580 //Check if we have a target
581 if (!UpdateVictim())
582 {
583 //No target so we'll use this section to do our random wispers instance wide
584 //WisperTimer
585 if (WisperTimer <= diff)
586 {
587 //Play random sound to the zone
588 Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
589 for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
590 me->PlayDirectSound(RANDOM_SOUND_WHISPER, itr->GetSource());
591
592 //One random wisper every 90 - 300 seconds
593 WisperTimer = urand(90000, 300000);
594 } else WisperTimer -= diff;
595
596 return;
597 }
598
600
601 uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE);
602 if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK)
603 {
604 // EyeTentacleTimer
605 if (EyeTentacleTimer <= diff)
606 {
607 //Spawn the 8 Eye Tentacles in the corret spots
608 SpawnEyeTentacle(0, 20); //south
609 SpawnEyeTentacle(10, 10); //south west
610 SpawnEyeTentacle(20, 0); //west
611 SpawnEyeTentacle(10, -10); //north west
612
613 SpawnEyeTentacle(0, -20); //north
614 SpawnEyeTentacle(-10, -10); //north east
615 SpawnEyeTentacle(-20, 0); // east
616 SpawnEyeTentacle(-10, 10); // south east
617
618 EyeTentacleTimer = 30000; // every 30sec in phase 2
619 } else EyeTentacleTimer -= diff;
620 }
621
622 switch (currentPhase)
623 {
624 //Transition phase
626 //PhaseTimer
627 if (PhaseTimer <= diff)
628 {
629 //Switch
631
632 //Switch to c'thun model
634 DoCast(me, SPELL_TRANSFORM, false);
635 me->SetFullHealth();
636
637 me->SetVisible(true);
639 me->SetUninteractible(false);
640
641 //Emerging phase
642 //AttackStart(ObjectAccessor::GetUnit(*me, HoldpPlayer));
644
645 //Place all units in threat list on outside of stomach
646 Stomach_Map.clear();
647
649 Stomach_Map[ref->GetVictim()->GetGUID()] = false; //Outside stomach
650
651 //Spawn 2 flesh tentacles
653
654 //Spawn flesh tentacle
655 for (uint8 i = 0; i < 2; i++)
656 {
658 if (!spawned)
660 }
661
662 PhaseTimer = 0;
663 } else PhaseTimer -= diff;
664
665 break;
666
667 //Body Phase
669 //Remove Target field
671
672 //Weaken
673 if (FleshTentaclesKilled > 1)
674 {
676
678 PhaseTimer = 45000;
679
681
682 std::unordered_map<ObjectGuid, bool>::iterator i = Stomach_Map.begin();
683
684 //Kick all players out of stomach
685 while (i != Stomach_Map.end())
686 {
687 //Check for valid player
688 Unit* unit = ObjectAccessor::GetUnit(*me, i->first);
689
690 //Only move units in stomach
691 if (unit && i->second == true)
692 {
693 //Teleport each player out
694 DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand32() % 6));
695
696 //Cast knockback on them
698
699 //Remove the acid debuff
701
702 i->second = false;
703 }
704 ++i;
705 }
706
707 return;
708 }
709
710 //Stomach acid
711 if (StomachAcidTimer <= diff)
712 {
713 //Apply aura to all players in stomach
714 std::unordered_map<ObjectGuid, bool>::iterator i = Stomach_Map.begin();
715
716 while (i != Stomach_Map.end())
717 {
718 //Check for valid player
719 Unit* unit = ObjectAccessor::GetUnit(*me, i->first);
720
721 //Only apply to units in stomach
722 if (unit && i->second == true)
723 {
724 //Cast digestive acid on them
725 DoCast(unit, SPELL_DIGESTIVE_ACID, true);
726
727 //Check if player should be kicked from stomach
728 if (unit->IsWithinDist3d(&KickPos, 15.0f))
729 {
730 //Teleport each player out
731 DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand32() % 6));
732
733 //Cast knockback on them
735
736 //Remove the acid debuff
738
739 i->second = false;
740 }
741 }
742 ++i;
743 }
744
745 StomachAcidTimer = 4000;
746 } else StomachAcidTimer -= diff;
747
748 //Stomach Enter Timer
749 if (StomachEnterTimer <= diff)
750 {
751 if (Unit* target = SelectRandomNotStomach())
752 {
753 //Set target in stomach
754 Stomach_Map[target->GetGUID()] = true;
755 target->InterruptNonMeleeSpells(false);
757 .SetOriginalCaster(me->GetGUID()));
758 StomachEnterTarget = target->GetGUID();
760 }
761
762 StomachEnterTimer = 13800;
763 } else StomachEnterTimer -= diff;
764
766 {
767 if (StomachEnterVisTimer <= diff)
768 {
769 //Check for valid player
771
772 if (unit)
773 {
775 }
776
779 } else StomachEnterVisTimer -= diff;
780 }
781
782 //GientClawTentacleTimer
783 if (GiantClawTentacleTimer <= diff)
784 {
785 if (Unit* target = SelectRandomNotStomach())
786 {
787 //Spawn claw tentacle on the random target
789 if (spawned->AI())
790 spawned->AI()->AttackStart(target);
791 }
792
793 //One giant claw tentacle every minute
795 } else GiantClawTentacleTimer -= diff;
796
797 //GiantEyeTentacleTimer
798 if (GiantEyeTentacleTimer <= diff)
799 {
800 if (Unit* target = SelectRandomNotStomach())
801 {
802 //Spawn claw tentacle on the random target
804 if (spawned->AI())
805 spawned->AI()->AttackStart(target);
806 }
807
808 //One giant eye tentacle every minute
809 GiantEyeTentacleTimer = 60000;
810 } else GiantEyeTentacleTimer -= diff;
811
812 break;
813
814 //Weakened state
815 case PHASE_CTHUN_WEAK:
816 //PhaseTimer
817 if (PhaseTimer <= diff)
818 {
819 //Switch
821
822 //Remove purple coloration
824
825 //Spawn 2 flesh tentacles
827
828 //Spawn flesh tentacle
829 for (uint8 i = 0; i < 2; i++)
830 {
832 if (!spawned)
834 }
835
836 PhaseTimer = 0;
837 } else PhaseTimer -= diff;
838
839 break;
840 }
841 }
842
843 void JustDied(Unit* /*killer*/) override
844 {
846 }
847
848 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
849 {
851 {
853 //Not weakened so reduce damage by 99%
854 damage /= 100;
855 if (damage == 0)
856 damage = 1;
857
858 //Prevent death in non-weakened state
859 if (damage >= me->GetHealth())
860 damage = 0;
861
862 return;
863
864 case PHASE_CTHUN_WEAK:
865 //Weakened - takes normal damage
866 return;
867
868 default:
869 damage = 0;
870 break;
871 }
872 }
873
874 void DoAction(int32 param) override
875 {
876 switch (param)
877 {
880 break;
881 }
882 }
883 };
884
885};
886
888{
889public:
890 npc_eye_tentacle() : CreatureScript("npc_eye_tentacle") { }
891
892 CreatureAI* GetAI(Creature* creature) const override
893 {
894 return GetAQ40AI<eye_tentacleAI>(creature);
895 }
896
898 {
899 eye_tentacleAI(Creature* creature) : ScriptedAI(creature)
900 {
901 MindflayTimer = 500;
902 KillSelfTimer = 35000;
903
905 {
906 pPortal->SetReactState(REACT_PASSIVE);
907 Portal = pPortal->GetGUID();
908 }
909
910 SetCombatMovement(false);
911 }
912
916
917 void JustDied(Unit* /*killer*/) override
918 {
920 p->KillSelf();
921 }
922
923 void Reset() override
924 {
925 //Mind flay half a second after we spawn
926 MindflayTimer = 500;
927
928 //This prevents eyes from overlapping
929 KillSelfTimer = 35000;
930 }
931
932 void JustEngagedWith(Unit* /*who*/) override
933 {
935 }
936
937 void UpdateAI(uint32 diff) override
938 {
939 //Check if we have a target
940 if (!UpdateVictim())
941 return;
942
943 //KillSelfTimer
944 if (KillSelfTimer <= diff)
945 {
946 me->KillSelf();
947 return;
948 } else KillSelfTimer -= diff;
949
950 //MindflayTimer
951 if (MindflayTimer <= diff)
952 {
954 if (target && !target->HasAura(SPELL_DIGESTIVE_ACID))
955 DoCast(target, SPELL_MIND_FLAY);
956
957 //Mindflay every 10 seconds
958 MindflayTimer = 10000;
959 } else MindflayTimer -= diff;
960 }
961 };
962
963};
964
966{
967public:
968 npc_claw_tentacle() : CreatureScript("npc_claw_tentacle") { }
969
970 CreatureAI* GetAI(Creature* creature) const override
971 {
972 return GetAQ40AI<claw_tentacleAI>(creature);
973 }
974
976 {
977 claw_tentacleAI(Creature* creature) : ScriptedAI(creature)
978 {
979 GroundRuptureTimer = 500;
980 HamstringTimer = 2000;
981 EvadeTimer = 5000;
982
983 SetCombatMovement(false);
984
986 {
987 pPortal->SetReactState(REACT_PASSIVE);
988 Portal = pPortal->GetGUID();
989 }
990 }
991
996
997 void JustDied(Unit* /*killer*/) override
998 {
1000 p->KillSelf();
1001 }
1002
1003 void Reset() override
1004 {
1005 //First rupture should happen half a second after we spawn
1006 GroundRuptureTimer = 500;
1007 HamstringTimer = 2000;
1008 EvadeTimer = 5000;
1009 }
1010
1011 void JustEngagedWith(Unit* /*who*/) override
1012 {
1014 }
1015
1016 void UpdateAI(uint32 diff) override
1017 {
1018 //Check if we have a target
1019 if (!UpdateVictim())
1020 return;
1021
1022 //EvadeTimer
1024 {
1025 if (EvadeTimer <= diff)
1026 {
1028 p->KillSelf();
1029
1030 //Dissapear and reappear at new position
1031 me->SetVisible(false);
1032
1034 if (!target)
1035 {
1036 me->KillSelf();
1037 return;
1038 }
1039
1040 if (!target->HasAura(SPELL_DIGESTIVE_ACID))
1041 {
1042 me->UpdatePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0);
1044 {
1045 pPortal->SetReactState(REACT_PASSIVE);
1046 Portal = pPortal->GetGUID();
1047 }
1048
1049 GroundRuptureTimer = 500;
1050 HamstringTimer = 2000;
1051 EvadeTimer = 5000;
1052 AttackStart(target);
1053 }
1054
1055 me->SetVisible(true);
1056 } else EvadeTimer -= diff;
1057 }
1058
1059 //GroundRuptureTimer
1060 if (GroundRuptureTimer <= diff)
1061 {
1063 GroundRuptureTimer = 30000;
1064 } else GroundRuptureTimer -= diff;
1065
1066 //HamstringTimer
1067 if (HamstringTimer <= diff)
1068 {
1070 HamstringTimer = 5000;
1071 } else HamstringTimer -= diff;
1072 }
1073 };
1074
1075};
1076
1078{
1079public:
1080 npc_giant_claw_tentacle() : CreatureScript("npc_giant_claw_tentacle") { }
1081
1082 CreatureAI* GetAI(Creature* creature) const override
1083 {
1084 return GetAQ40AI<giant_claw_tentacleAI>(creature);
1085 }
1086
1088 {
1090 {
1091 GroundRuptureTimer = 500;
1092 HamstringTimer = 2000;
1093 ThrashTimer = 5000;
1094 EvadeTimer = 5000;
1095
1096 SetCombatMovement(false);
1097
1099 {
1100 pPortal->SetReactState(REACT_PASSIVE);
1101 Portal = pPortal->GetGUID();
1102 }
1103 }
1104
1110
1111 void JustDied(Unit* /*killer*/) override
1112 {
1114 p->KillSelf();
1115 }
1116
1117 void Reset() override
1118 {
1119 //First rupture should happen half a second after we spawn
1120 GroundRuptureTimer = 500;
1121 HamstringTimer = 2000;
1122 ThrashTimer = 5000;
1123 EvadeTimer = 5000;
1124 }
1125
1126 void JustEngagedWith(Unit* /*who*/) override
1127 {
1129 }
1130
1131 void UpdateAI(uint32 diff) override
1132 {
1133 //Check if we have a target
1134 if (!UpdateVictim())
1135 return;
1136
1137 //EvadeTimer
1139 {
1140 if (EvadeTimer <= diff)
1141 {
1143 p->KillSelf();
1144
1145 //Dissapear and reappear at new position
1146 me->SetVisible(false);
1147
1149 if (!target)
1150 {
1151 me->KillSelf();
1152 return;
1153 }
1154
1155 if (!target->HasAura(SPELL_DIGESTIVE_ACID))
1156 {
1157 me->UpdatePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0);
1159 {
1160 pPortal->SetReactState(REACT_PASSIVE);
1161 Portal = pPortal->GetGUID();
1162 }
1163
1164 GroundRuptureTimer = 500;
1165 HamstringTimer = 2000;
1166 ThrashTimer = 5000;
1167 EvadeTimer = 5000;
1168 AttackStart(target);
1169 }
1170 me->SetVisible(true);
1171 } else EvadeTimer -= diff;
1172 }
1173
1174 //GroundRuptureTimer
1175 if (GroundRuptureTimer <= diff)
1176 {
1178 GroundRuptureTimer = 30000;
1179 } else GroundRuptureTimer -= diff;
1180
1181 //ThrashTimer
1182 if (ThrashTimer <= diff)
1183 {
1185 ThrashTimer = 10000;
1186 } else ThrashTimer -= diff;
1187
1188 //HamstringTimer
1189 if (HamstringTimer <= diff)
1190 {
1192 HamstringTimer = 10000;
1193 } else HamstringTimer -= diff;
1194 }
1195 };
1196
1197};
1198
1200{
1201public:
1202 npc_giant_eye_tentacle() : CreatureScript("npc_giant_eye_tentacle") { }
1203
1204 CreatureAI* GetAI(Creature* creature) const override
1205 {
1206 return GetAQ40AI<giant_eye_tentacleAI>(creature);
1207 }
1208
1210 {
1212 {
1213 BeamTimer = 500;
1214
1215 SetCombatMovement(false);
1216
1218 {
1219 pPortal->SetReactState(REACT_PASSIVE);
1220 Portal = pPortal->GetGUID();
1221 }
1222 }
1223
1226
1227 void JustDied(Unit* /*killer*/) override
1228 {
1230 p->KillSelf();
1231 }
1232
1233 void Reset() override
1234 {
1235 //Green Beam half a second after we spawn
1236 BeamTimer = 500;
1237 }
1238
1239 void JustEngagedWith(Unit* /*who*/) override
1240 {
1242 }
1243
1244 void UpdateAI(uint32 diff) override
1245 {
1246 //Check if we have a target
1247 if (!UpdateVictim())
1248 return;
1249
1250 //BeamTimer
1251 if (BeamTimer <= diff)
1252 {
1254 if (target && !target->HasAura(SPELL_DIGESTIVE_ACID))
1255 DoCast(target, SPELL_GREEN_BEAM);
1256
1257 //Beam every 2 seconds
1258 BeamTimer = 2100;
1259 } else BeamTimer -= diff;
1260 }
1261 };
1262
1263};
1264
1266{
1267public:
1268 npc_giant_flesh_tentacle() : CreatureScript("npc_giant_flesh_tentacle") { }
1269
1270 CreatureAI* GetAI(Creature* creature) const override
1271 {
1272 return GetAQ40AI<flesh_tentacleAI>(creature);
1273 }
1274
1276 {
1277 flesh_tentacleAI(Creature* creature) : ScriptedAI(creature)
1278 {
1279 SetCombatMovement(false);
1280 }
1281
1282 void JustDied(Unit* /*killer*/) override
1283 {
1284 if (TempSummon* summon = me->ToTempSummon())
1285 if (Unit* summoner = summon->GetSummonerUnit())
1286 if (summoner->IsAIEnabled())
1287 summoner->GetAI()->DoAction(ACTION_FLESH_TENTACLE_KILLED);
1288 }
1289 };
1290
1291};
1292
1293//GetAIs
1294
1296{
1297 new boss_eye_of_cthun();
1298 new boss_cthun();
1299 new npc_eye_tentacle();
1300 new npc_claw_tentacle();
1304}
Actions
#define M_PI
Definition: Common.h:115
First const & RAND(First const &first, Second const &second, Rest const &... rest)
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
@ TEMPSUMMON_CORPSE_DESPAWN
Definition: ObjectDefines.h:67
Spells
Definition: PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
uint32 rand32()
Definition: Random.cpp:70
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
Definition: SpellDefines.h:266
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_FLAG_NON_ATTACKABLE
Definition: UnitDefines.h:145
#define STOMACH_X
Definition: boss_cthun.cpp:137
@ ACTION_FLESH_TENTACLE_KILLED
Definition: boss_cthun.cpp:122
@ RANDOM_SOUND_WHISPER
Definition: boss_cthun.cpp:133
@ EMOTE_WEAKENED
Definition: boss_cthun.cpp:128
#define STOMACH_O
Definition: boss_cthun.cpp:140
@ SPELL_MOUTH_TENTACLE
Definition: boss_cthun.cpp:115
@ SPELL_HAMSTRING
Definition: boss_cthun.cpp:94
@ SPELL_FREEZE_ANIM
Definition: boss_cthun.cpp:84
@ SPELL_RED_COLORATION
Definition: boss_cthun.cpp:87
@ SPELL_TRANSFORM
Definition: boss_cthun.cpp:99
@ SPELL_EXIT_STOMACH_KNOCKBACK
Definition: boss_cthun.cpp:116
@ SPELL_GREEN_BEAM
Definition: boss_cthun.cpp:85
@ SPELL_PURPLE_COLORATION
Definition: boss_cthun.cpp:100
@ SPELL_DIGESTIVE_ACID
Definition: boss_cthun.cpp:117
@ SPELL_MASSIVE_GROUND_RUPTURE
Definition: boss_cthun.cpp:106
@ SPELL_THRASH
Definition: boss_cthun.cpp:109
@ SPELL_MIND_FLAY
Definition: boss_cthun.cpp:90
@ SPELL_GROUND_RUPTURE
Definition: boss_cthun.cpp:93
@ SPELL_DARK_GLARE
Definition: boss_cthun.cpp:86
@ PHASE_EYE_RED_BEAM
Definition: boss_cthun.cpp:70
@ PHASE_CTHUN_TRANSITION
Definition: boss_cthun.cpp:73
@ PHASE_NOT_STARTED
Definition: boss_cthun.cpp:66
@ PHASE_CTHUN_DONE
Definition: boss_cthun.cpp:77
@ PHASE_CTHUN_STOMACH
Definition: boss_cthun.cpp:74
@ PHASE_EYE_GREEN_BEAM
Definition: boss_cthun.cpp:69
@ PHASE_CTHUN_WEAK
Definition: boss_cthun.cpp:75
#define STOMACH_Y
Definition: boss_cthun.cpp:138
void AddSC_boss_cthun()
const Position FleshTentaclePos[2]
Definition: boss_cthun.cpp:143
#define STOMACH_Z
Definition: boss_cthun.cpp:139
const Position KickPos
Definition: boss_cthun.cpp:150
Yells
InstanceScript *const instance
void DoZoneInCombat()
Definition: CreatureAI.h:161
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 SetReactState(ReactStates st)
Definition: Creature.h:160
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
void SetTarget(ObjectGuid const &guid) override
Definition: Creature.cpp:3419
CreatureAI * AI() const
Definition: Creature.h:214
iterator end()
Definition: MapRefManager.h:35
iterator begin()
Definition: MapRefManager.h:34
PlayerList const & GetPlayers() const
Definition: Map.h:367
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
void Clear()
Definition: ObjectGuid.h:286
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
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
bool IsWithinMeleeRange(Unit const *obj) const
Definition: Unit.h:699
void SetVisible(bool x)
Definition: Unit.cpp:8351
void SetHealth(uint64 val)
Definition: Unit.cpp:9346
void SetFullHealth()
Definition: Unit.h:790
ThreatManager & GetThreatManager()
Definition: Unit.h:1063
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3089
void StopMoving()
Definition: Unit.cpp:10049
TempSummon * ToTempSummon()
Definition: Unit.h:1756
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition: Unit.cpp:12392
uint64 GetHealth() const
Definition: Unit.h:776
Unit * GetVictim() const
Definition: Unit.h:715
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
void RemoveAllAuras()
Definition: Unit.cpp:4242
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:833
void KillSelf(bool durabilityLoss=true, bool skipSettingDeathState=false)
Definition: Unit.h:921
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:834
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition: Object.cpp:3592
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition: Object.cpp:1122
Map * GetMap() const
Definition: Object.h:624
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
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
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition: Object.cpp:2148
virtual uint32 GetData(uint32) const
Definition: ZoneScript.h:91
virtual void SetData(uint32, uint32)
Definition: ZoneScript.h:92
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:459
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:157
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:970
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:892
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
constexpr void SetOrientation(float orientation)
Definition: Position.h:71
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:125
constexpr float GetPositionZ() const
Definition: Position.h:78
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void SetCombatMovement(bool allowMovement)
void DoTeleportPlayer(Unit *unit, float x, float y, float z, float o)
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, Milliseconds despawntime)
void JustDied(Unit *) override
Definition: boss_cthun.cpp:843
cthunAI(Creature *creature)
Definition: boss_cthun.cpp:466
void UpdateAI(uint32 diff) override
Definition: boss_cthun.cpp:578
void DoAction(int32 param) override
Definition: boss_cthun.cpp:874
std::unordered_map< ObjectGuid, bool > Stomach_Map
Definition: boss_cthun.cpp:516
void Reset() override
Definition: boss_cthun.cpp:518
ObjectGuid HoldPlayer
Definition: boss_cthun.cpp:503
uint32 GiantClawTentacleTimer
Definition: boss_cthun.cpp:508
Unit * SelectRandomNotStomach()
Definition: boss_cthun.cpp:543
uint32 GiantEyeTentacleTimer
Definition: boss_cthun.cpp:509
ObjectGuid StomachEnterTarget
Definition: boss_cthun.cpp:513
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
Definition: boss_cthun.cpp:848
void SpawnEyeTentacle(float x, float y)
Definition: boss_cthun.cpp:535
void UpdateAI(uint32 diff) override
Definition: boss_cthun.cpp:239
void JustEngagedWith(Unit *) override
Definition: boss_cthun.cpp:225
void SpawnEyeTentacle(float x, float y)
Definition: boss_cthun.cpp:231
eye_of_cthunAI(Creature *creature)
Definition: boss_cthun.cpp:164
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
Definition: boss_cthun.cpp:407
claw_tentacleAI(Creature *creature)
Definition: boss_cthun.cpp:977
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void JustDied(Unit *) override
Definition: boss_cthun.cpp:997
void UpdateAI(uint32 diff) override
Definition: boss_cthun.cpp:937
void JustEngagedWith(Unit *) override
Definition: boss_cthun.cpp:932
eye_tentacleAI(Creature *creature)
Definition: boss_cthun.cpp:899
void JustDied(Unit *) override
Definition: boss_cthun.cpp:917
@ NPC_FLESH_TENTACLE
@ NPC_GIANT_PORTAL
@ NPC_GIANT_CLAW_TENTACLE
@ NPC_GIANT_EYE_TENTACLE
@ NPC_EYE_TENTACLE
@ NPC_SMALL_PORTAL
@ NPC_CTHUN_PORTAL
@ NPC_CLAW_TENTACLE
@ DATA_CTHUN
@ DATA_CTHUN_PHASE