TrinityCore
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 "ObjectAccessor.h"
29#include "Player.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->SetVisible(true);
214
215 //Reset Phase
217
218 //to avoid having a following void zone
220 if (pPortal)
222 }
223
224 void JustEngagedWith(Unit* /*who*/) override
225 {
228 }
229
230 void SpawnEyeTentacle(float x, float y)
231 {
232 if (Creature* Spawned = DoSpawnCreature(NPC_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500ms))
234 if (Spawned->AI())
235 Spawned->AI()->AttackStart(target);
236 }
237
238 void UpdateAI(uint32 diff) override
239 {
240 //Check if we have a target
241 if (!UpdateVictim())
242 return;
243
244 uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE);
245 if (currentPhase == PHASE_EYE_GREEN_BEAM || currentPhase == PHASE_EYE_RED_BEAM)
246 {
247 // EyeTentacleTimer
248 if (EyeTentacleTimer <= diff)
249 {
250 //Spawn the 8 Eye Tentacles in the corret spots
251 SpawnEyeTentacle(0, 20); //south
252 SpawnEyeTentacle(10, 10); //south west
253 SpawnEyeTentacle(20, 0); //west
254 SpawnEyeTentacle(10, -10); //north west
255
256 SpawnEyeTentacle(0, -20); //north
257 SpawnEyeTentacle(-10, -10); //north east
258 SpawnEyeTentacle(-20, 0); // east
259 SpawnEyeTentacle(-10, 10); // south east
260
261 EyeTentacleTimer = 45000;
262 } else EyeTentacleTimer -= diff;
263 }
264
265 switch (currentPhase)
266 {
268 //BeamTimer
269 if (BeamTimer <= diff)
270 {
271 //SPELL_GREEN_BEAM
273 {
275 DoCast(target, SPELL_GREEN_BEAM);
276
277 //Correctly update our target
278 me->SetTarget(target->GetGUID());
279 }
280
281 //Beam every 3 seconds
282 BeamTimer = 3000;
283 } else BeamTimer -= diff;
284
285 //ClawTentacleTimer
286 if (ClawTentacleTimer <= diff)
287 {
289 {
290 Creature* Spawned = nullptr;
291
292 //Spawn claw tentacle on the random target
294
295 if (Spawned && Spawned->AI())
296 Spawned->AI()->AttackStart(target);
297 }
298
299 //One claw tentacle every 12.5 seconds
300 ClawTentacleTimer = 12500;
301 } else ClawTentacleTimer -= diff;
302
303 //PhaseTimer
304 if (PhaseTimer <= diff)
305 {
306 //Switch to Dark Beam
308
311
312 //Remove any target
314
315 //Select random target for dark beam to start on
317 {
318 //Face our target
320 DarkGlareTickTimer = 1000;
321 DarkGlareTick = 0;
322 ClockWise = RAND(true, false);
323 }
324
325 //Add red coloration to C'thun
327
328 //Freeze animation
331 me->StopMoving();
332
333 //Darkbeam for 35 seconds
334 PhaseTimer = 35000;
335 } else PhaseTimer -= diff;
336
337 break;
338
340 if (DarkGlareTick < 35)
341 {
342 if (DarkGlareTickTimer <= diff)
343 {
344 //Set angle and cast
345 float angle = ClockWise ? DarkGlareAngle + DarkGlareTick * float(M_PI) / 35 : DarkGlareAngle - DarkGlareTick * float(M_PI) / 35;
346
347 me->SetOrientation(angle);
348 me->SetFacingTo(angle);
349
350 me->StopMoving();
351
352 //Actual dark glare cast, maybe something missing here?
353 DoCast(me, SPELL_DARK_GLARE, false);
354
355 //Increase tick
357
358 //1 second per tick
359 DarkGlareTickTimer = 1000;
360 } else DarkGlareTickTimer -= diff;
361 }
362
363 //PhaseTimer
364 if (PhaseTimer <= diff)
365 {
366 //Switch to Eye Beam
368
369 BeamTimer = 3000;
370 ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam)
371
373
374 //Remove Red coloration from c'thun
377
378 //set it back to aggressive
380
381 //Eye Beam for 50 seconds
382 PhaseTimer = 50000;
383 } else PhaseTimer -= diff;
384
385 break;
386
387 //Transition phase
389 //Remove any target
391 me->SetHealth(0);
392 me->SetVisible(false);
393 break;
394
395 //Dead phase
396 case PHASE_CTHUN_DONE:
398 if (pPortal)
399 pPortal->DespawnOrUnsummon();
400
402 break;
403 }
404 }
405
406 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
407 {
409 {
412 //Only if it will kill
413 if (damage < me->GetHealth())
414 return;
415
416 //Fake death in phase 0 or 1 (green beam or dark glare phase)
418
419 //Remove Red coloration from c'thun
421
422 //Reset to normal emote state and prevent select and attack
424
425 //Remove Target field
427
428 //Death animation/respawning;
430
431 me->SetHealth(0);
432 damage = 0;
433
436 break;
437
438 case PHASE_CTHUN_DONE:
439 //Allow death here
440 return;
441
442 default:
443 //Prevent death in these phases
444 damage = 0;
445 return;
446 }
447 }
448 };
449
450};
451
453{
454public:
455 boss_cthun() : CreatureScript("boss_cthun") { }
456
457 CreatureAI* GetAI(Creature* creature) const override
458 {
459 return GetAQ40AI<cthunAI>(creature);
460 }
461
462 struct cthunAI : public BossAI
463 {
464 cthunAI(Creature* creature) : BossAI(creature, DATA_CTHUN)
465 {
466 Initialize();
467 SetCombatMovement(false);
468 }
469
471 {
472 //One random wisper every 90 - 300 seconds
473 WisperTimer = 90000;
474
475 //Phase information
476 PhaseTimer = 10000; //Emerge in 10 seconds
477
478 //No hold player for transition
480
481 //Body Phase
482 EyeTentacleTimer = 30000;
484 GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat)
485 GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat)
486 StomachAcidTimer = 4000; //Every 4 seconds
487 StomachEnterTimer = 10000; //Every 10 seconds
488 StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer
489 StomachEnterTarget.Clear(); //Target to be teleported to stomach
490 }
491
492 //Out of combat whisper timer
494
495 //Global variables
497
498 //-------------------
499
500 //Phase transition
502
503 //Body Phase
512
513 //Stomach map, bool = true then in stomach
514 std::unordered_map<ObjectGuid, bool> Stomach_Map;
515
516 void Reset() override
517 {
518 Initialize();
519 _Reset();
520
521 //Clear players in stomach and outside
522 Stomach_Map.clear();
523
524 //Reset flags
527 me->SetVisible(false);
528
530 }
531
532 void SpawnEyeTentacle(float x, float y)
533 {
535 if (Spawned && Spawned->AI())
536 if (Unit* target = SelectRandomNotStomach())
537 Spawned->AI()->AttackStart(target);
538 }
539
541 {
542 if (Stomach_Map.empty())
543 return nullptr;
544
545 std::unordered_map<ObjectGuid, bool>::const_iterator i = Stomach_Map.begin();
546
547 std::list<Unit*> temp;
548 std::list<Unit*>::const_iterator j;
549
550 //Get all players in map
551 while (i != Stomach_Map.end())
552 {
553 //Check for valid player
554 Unit* unit = ObjectAccessor::GetUnit(*me, i->first);
555
556 //Only units out of stomach
557 if (unit && i->second == false)
558 temp.push_back(unit);
559
560 ++i;
561 }
562
563 if (temp.empty())
564 return nullptr;
565
566 j = temp.begin();
567
568 //Get random but only if we have more than one unit on threat list
569 if (temp.size() > 1)
570 advance(j, rand32() % (temp.size() - 1));
571
572 return (*j);
573 }
574
575 void UpdateAI(uint32 diff) override
576 {
577 //Check if we have a target
578 if (!UpdateVictim())
579 {
580 //No target so we'll use this section to do our random wispers instance wide
581 //WisperTimer
582 if (WisperTimer <= diff)
583 {
584 //Play random sound to the zone
585 Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
586 for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
587 me->PlayDirectSound(RANDOM_SOUND_WHISPER, itr->GetSource());
588
589 //One random wisper every 90 - 300 seconds
590 WisperTimer = urand(90000, 300000);
591 } else WisperTimer -= diff;
592
593 return;
594 }
595
597
598 uint32 currentPhase = instance->GetData(DATA_CTHUN_PHASE);
599 if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK)
600 {
601 // EyeTentacleTimer
602 if (EyeTentacleTimer <= diff)
603 {
604 //Spawn the 8 Eye Tentacles in the corret spots
605 SpawnEyeTentacle(0, 20); //south
606 SpawnEyeTentacle(10, 10); //south west
607 SpawnEyeTentacle(20, 0); //west
608 SpawnEyeTentacle(10, -10); //north west
609
610 SpawnEyeTentacle(0, -20); //north
611 SpawnEyeTentacle(-10, -10); //north east
612 SpawnEyeTentacle(-20, 0); // east
613 SpawnEyeTentacle(-10, 10); // south east
614
615 EyeTentacleTimer = 30000; // every 30sec in phase 2
616 } else EyeTentacleTimer -= diff;
617 }
618
619 switch (currentPhase)
620 {
621 //Transition phase
623 //PhaseTimer
624 if (PhaseTimer <= diff)
625 {
626 //Switch
628
629 //Switch to c'thun model
631 DoCast(me, SPELL_TRANSFORM, false);
632 me->SetFullHealth();
633
634 me->SetVisible(true);
636
637 //Emerging phase
638 //AttackStart(ObjectAccessor::GetUnit(*me, HoldpPlayer));
640
641 //Place all units in threat list on outside of stomach
642 Stomach_Map.clear();
643
645 Stomach_Map[ref->GetVictim()->GetGUID()] = false; //Outside stomach
646
647 //Spawn 2 flesh tentacles
649
650 //Spawn flesh tentacle
651 for (uint8 i = 0; i < 2; i++)
652 {
654 if (!spawned)
656 }
657
658 PhaseTimer = 0;
659 } else PhaseTimer -= diff;
660
661 break;
662
663 //Body Phase
665 //Remove Target field
667
668 //Weaken
669 if (FleshTentaclesKilled > 1)
670 {
672
674 PhaseTimer = 45000;
675
677
678 std::unordered_map<ObjectGuid, bool>::iterator i = Stomach_Map.begin();
679
680 //Kick all players out of stomach
681 while (i != Stomach_Map.end())
682 {
683 //Check for valid player
684 Unit* unit = ObjectAccessor::GetUnit(*me, i->first);
685
686 //Only move units in stomach
687 if (unit && i->second == true)
688 {
689 //Teleport each player out
690 DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand32() % 6));
691
692 //Cast knockback on them
694
695 //Remove the acid debuff
697
698 i->second = false;
699 }
700 ++i;
701 }
702
703 return;
704 }
705
706 //Stomach acid
707 if (StomachAcidTimer <= diff)
708 {
709 //Apply aura to all players in stomach
710 std::unordered_map<ObjectGuid, bool>::iterator i = Stomach_Map.begin();
711
712 while (i != Stomach_Map.end())
713 {
714 //Check for valid player
715 Unit* unit = ObjectAccessor::GetUnit(*me, i->first);
716
717 //Only apply to units in stomach
718 if (unit && i->second == true)
719 {
720 //Cast digestive acid on them
721 DoCast(unit, SPELL_DIGESTIVE_ACID, true);
722
723 //Check if player should be kicked from stomach
724 if (unit->IsWithinDist3d(&KickPos, 15.0f))
725 {
726 //Teleport each player out
727 DoTeleportPlayer(unit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10, float(rand32() % 6));
728
729 //Cast knockback on them
731
732 //Remove the acid debuff
734
735 i->second = false;
736 }
737 }
738 ++i;
739 }
740
741 StomachAcidTimer = 4000;
742 } else StomachAcidTimer -= diff;
743
744 //Stomach Enter Timer
745 if (StomachEnterTimer <= diff)
746 {
747 if (Unit* target = SelectRandomNotStomach())
748 {
749 //Set target in stomach
750 Stomach_Map[target->GetGUID()] = true;
751 target->InterruptNonMeleeSpells(false);
752 target->CastSpell(target, SPELL_MOUTH_TENTACLE, me->GetGUID());
753 StomachEnterTarget = target->GetGUID();
755 }
756
757 StomachEnterTimer = 13800;
758 } else StomachEnterTimer -= diff;
759
761 {
762 if (StomachEnterVisTimer <= diff)
763 {
764 //Check for valid player
766
767 if (unit)
768 {
770 }
771
774 } else StomachEnterVisTimer -= diff;
775 }
776
777 //GientClawTentacleTimer
778 if (GiantClawTentacleTimer <= diff)
779 {
780 if (Unit* target = SelectRandomNotStomach())
781 {
782 //Spawn claw tentacle on the random target
784 if (spawned->AI())
785 spawned->AI()->AttackStart(target);
786 }
787
788 //One giant claw tentacle every minute
790 } else GiantClawTentacleTimer -= diff;
791
792 //GiantEyeTentacleTimer
793 if (GiantEyeTentacleTimer <= diff)
794 {
795 if (Unit* target = SelectRandomNotStomach())
796 {
797 //Spawn claw tentacle on the random target
799 if (spawned->AI())
800 spawned->AI()->AttackStart(target);
801 }
802
803 //One giant eye tentacle every minute
804 GiantEyeTentacleTimer = 60000;
805 } else GiantEyeTentacleTimer -= diff;
806
807 break;
808
809 //Weakened state
810 case PHASE_CTHUN_WEAK:
811 //PhaseTimer
812 if (PhaseTimer <= diff)
813 {
814 //Switch
816
817 //Remove purple coloration
819
820 //Spawn 2 flesh tentacles
822
823 //Spawn flesh tentacle
824 for (uint8 i = 0; i < 2; i++)
825 {
827 if (!spawned)
829 }
830
831 PhaseTimer = 0;
832 } else PhaseTimer -= diff;
833
834 break;
835 }
836 }
837
838 void JustDied(Unit* /*killer*/) override
839 {
841 }
842
843 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
844 {
846 {
848 //Not weakened so reduce damage by 99%
849 damage /= 100;
850 if (damage == 0)
851 damage = 1;
852
853 //Prevent death in non-weakened state
854 if (damage >= me->GetHealth())
855 damage = 0;
856
857 return;
858
859 case PHASE_CTHUN_WEAK:
860 //Weakened - takes normal damage
861 return;
862
863 default:
864 damage = 0;
865 break;
866 }
867 }
868
869 void DoAction(int32 param) override
870 {
871 switch (param)
872 {
875 break;
876 }
877 }
878 };
879
880};
881
883{
884public:
885 npc_eye_tentacle() : CreatureScript("npc_eye_tentacle") { }
886
887 CreatureAI* GetAI(Creature* creature) const override
888 {
889 return GetAQ40AI<eye_tentacleAI>(creature);
890 }
891
893 {
894 eye_tentacleAI(Creature* creature) : ScriptedAI(creature)
895 {
896 MindflayTimer = 500;
897 KillSelfTimer = 35000;
898
900 {
901 pPortal->SetReactState(REACT_PASSIVE);
902 Portal = pPortal->GetGUID();
903 }
904
905 SetCombatMovement(false);
906 }
907
911
912 void JustDied(Unit* /*killer*/) override
913 {
915 p->KillSelf();
916 }
917
918 void Reset() override
919 {
920 //Mind flay half a second after we spawn
921 MindflayTimer = 500;
922
923 //This prevents eyes from overlapping
924 KillSelfTimer = 35000;
925 }
926
927 void JustEngagedWith(Unit* /*who*/) override
928 {
930 }
931
932 void UpdateAI(uint32 diff) override
933 {
934 //Check if we have a target
935 if (!UpdateVictim())
936 return;
937
938 //KillSelfTimer
939 if (KillSelfTimer <= diff)
940 {
941 me->KillSelf();
942 return;
943 } else KillSelfTimer -= diff;
944
945 //MindflayTimer
946 if (MindflayTimer <= diff)
947 {
949 if (target && !target->HasAura(SPELL_DIGESTIVE_ACID))
950 DoCast(target, SPELL_MIND_FLAY);
951
952 //Mindflay every 10 seconds
953 MindflayTimer = 10000;
954 } else MindflayTimer -= diff;
955 }
956 };
957
958};
959
961{
962public:
963 npc_claw_tentacle() : CreatureScript("npc_claw_tentacle") { }
964
965 CreatureAI* GetAI(Creature* creature) const override
966 {
967 return GetAQ40AI<claw_tentacleAI>(creature);
968 }
969
971 {
972 claw_tentacleAI(Creature* creature) : ScriptedAI(creature)
973 {
974 GroundRuptureTimer = 500;
975 HamstringTimer = 2000;
976 EvadeTimer = 5000;
977
978 SetCombatMovement(false);
979
981 {
982 pPortal->SetReactState(REACT_PASSIVE);
983 Portal = pPortal->GetGUID();
984 }
985 }
986
991
992 void JustDied(Unit* /*killer*/) override
993 {
995 p->KillSelf();
996 }
997
998 void Reset() override
999 {
1000 //First rupture should happen half a second after we spawn
1001 GroundRuptureTimer = 500;
1002 HamstringTimer = 2000;
1003 EvadeTimer = 5000;
1004 }
1005
1006 void JustEngagedWith(Unit* /*who*/) override
1007 {
1009 }
1010
1011 void UpdateAI(uint32 diff) override
1012 {
1013 //Check if we have a target
1014 if (!UpdateVictim())
1015 return;
1016
1017 //EvadeTimer
1019 {
1020 if (EvadeTimer <= diff)
1021 {
1023 p->KillSelf();
1024
1025 //Dissapear and reappear at new position
1026 me->SetVisible(false);
1027
1029 if (!target)
1030 {
1031 me->KillSelf();
1032 return;
1033 }
1034
1035 if (!target->HasAura(SPELL_DIGESTIVE_ACID))
1036 {
1037 me->UpdatePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0);
1039 {
1040 pPortal->SetReactState(REACT_PASSIVE);
1041 Portal = pPortal->GetGUID();
1042 }
1043
1044 GroundRuptureTimer = 500;
1045 HamstringTimer = 2000;
1046 EvadeTimer = 5000;
1047 AttackStart(target);
1048 }
1049
1050 me->SetVisible(true);
1051 } else EvadeTimer -= diff;
1052 }
1053
1054 //GroundRuptureTimer
1055 if (GroundRuptureTimer <= diff)
1056 {
1058 GroundRuptureTimer = 30000;
1059 } else GroundRuptureTimer -= diff;
1060
1061 //HamstringTimer
1062 if (HamstringTimer <= diff)
1063 {
1065 HamstringTimer = 5000;
1066 } else HamstringTimer -= diff;
1067
1069 }
1070 };
1071
1072};
1073
1075{
1076public:
1077 npc_giant_claw_tentacle() : CreatureScript("npc_giant_claw_tentacle") { }
1078
1079 CreatureAI* GetAI(Creature* creature) const override
1080 {
1081 return GetAQ40AI<giant_claw_tentacleAI>(creature);
1082 }
1083
1085 {
1087 {
1088 GroundRuptureTimer = 500;
1089 HamstringTimer = 2000;
1090 ThrashTimer = 5000;
1091 EvadeTimer = 5000;
1092
1093 SetCombatMovement(false);
1094
1096 {
1097 pPortal->SetReactState(REACT_PASSIVE);
1098 Portal = pPortal->GetGUID();
1099 }
1100 }
1101
1107
1108 void JustDied(Unit* /*killer*/) override
1109 {
1111 p->KillSelf();
1112 }
1113
1114 void Reset() override
1115 {
1116 //First rupture should happen half a second after we spawn
1117 GroundRuptureTimer = 500;
1118 HamstringTimer = 2000;
1119 ThrashTimer = 5000;
1120 EvadeTimer = 5000;
1121 }
1122
1123 void JustEngagedWith(Unit* /*who*/) override
1124 {
1126 }
1127
1128 void UpdateAI(uint32 diff) override
1129 {
1130 //Check if we have a target
1131 if (!UpdateVictim())
1132 return;
1133
1134 //EvadeTimer
1136 {
1137 if (EvadeTimer <= diff)
1138 {
1140 p->KillSelf();
1141
1142 //Dissapear and reappear at new position
1143 me->SetVisible(false);
1144
1146 if (!target)
1147 {
1148 me->KillSelf();
1149 return;
1150 }
1151
1152 if (!target->HasAura(SPELL_DIGESTIVE_ACID))
1153 {
1154 me->UpdatePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0);
1156 {
1157 pPortal->SetReactState(REACT_PASSIVE);
1158 Portal = pPortal->GetGUID();
1159 }
1160
1161 GroundRuptureTimer = 500;
1162 HamstringTimer = 2000;
1163 ThrashTimer = 5000;
1164 EvadeTimer = 5000;
1165 AttackStart(target);
1166 }
1167 me->SetVisible(true);
1168 } else EvadeTimer -= diff;
1169 }
1170
1171 //GroundRuptureTimer
1172 if (GroundRuptureTimer <= diff)
1173 {
1175 GroundRuptureTimer = 30000;
1176 } else GroundRuptureTimer -= diff;
1177
1178 //ThrashTimer
1179 if (ThrashTimer <= diff)
1180 {
1182 ThrashTimer = 10000;
1183 } else ThrashTimer -= diff;
1184
1185 //HamstringTimer
1186 if (HamstringTimer <= diff)
1187 {
1189 HamstringTimer = 10000;
1190 } else HamstringTimer -= diff;
1191
1193 }
1194 };
1195
1196};
1197
1199{
1200public:
1201 npc_giant_eye_tentacle() : CreatureScript("npc_giant_eye_tentacle") { }
1202
1203 CreatureAI* GetAI(Creature* creature) const override
1204 {
1205 return GetAQ40AI<giant_eye_tentacleAI>(creature);
1206 }
1207
1209 {
1211 {
1212 BeamTimer = 500;
1213
1214 SetCombatMovement(false);
1215
1217 {
1218 pPortal->SetReactState(REACT_PASSIVE);
1219 Portal = pPortal->GetGUID();
1220 }
1221 }
1222
1225
1226 void JustDied(Unit* /*killer*/) override
1227 {
1229 p->KillSelf();
1230 }
1231
1232 void Reset() override
1233 {
1234 //Green Beam half a second after we spawn
1235 BeamTimer = 500;
1236 }
1237
1238 void JustEngagedWith(Unit* /*who*/) override
1239 {
1241 }
1242
1243 void UpdateAI(uint32 diff) override
1244 {
1245 //Check if we have a target
1246 if (!UpdateVictim())
1247 return;
1248
1249 //BeamTimer
1250 if (BeamTimer <= diff)
1251 {
1253 if (target && !target->HasAura(SPELL_DIGESTIVE_ACID))
1254 DoCast(target, SPELL_GREEN_BEAM);
1255
1256 //Beam every 2 seconds
1257 BeamTimer = 2100;
1258 } else BeamTimer -= diff;
1259 }
1260 };
1261
1262};
1263
1265{
1266public:
1267 npc_giant_flesh_tentacle() : CreatureScript("npc_giant_flesh_tentacle") { }
1268
1269 CreatureAI* GetAI(Creature* creature) const override
1270 {
1271 return GetAQ40AI<flesh_tentacleAI>(creature);
1272 }
1273
1275 {
1276 flesh_tentacleAI(Creature* creature) : ScriptedAI(creature)
1277 {
1278 SetCombatMovement(false);
1279 }
1280
1281 void JustDied(Unit* /*killer*/) override
1282 {
1283 if (TempSummon* summon = me->ToTempSummon())
1284 if (Unit* summoner = summon->GetSummonerUnit())
1285 if (summoner->IsAIEnabled())
1286 summoner->GetAI()->DoAction(ACTION_FLESH_TENTACLE_KILLED);
1287 }
1288 };
1289
1290};
1291
1292//GetAIs
1293
1295{
1296 new boss_eye_of_cthun();
1297 new boss_cthun();
1298 new npc_eye_tentacle();
1299 new npc_claw_tentacle();
1303}
Actions
#define M_PI
Definition: Common.h:72
First const & RAND(First const &first, Second const &second, Rest const &... rest)
uint8_t uint8
Definition: Define.h:135
int32_t int32
Definition: Define.h:129
uint32_t uint32
Definition: Define.h:133
@ TEMPSUMMON_CORPSE_DESPAWN
Definition: ObjectDefines.h:65
Spells
Definition: PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
uint32 rand32()
Definition: Random.cpp:70
@ REACT_PASSIVE
Definition: UnitDefines.h:408
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:410
@ UNIT_FLAG_NON_ATTACKABLE
Definition: UnitDefines.h:136
@ UNIT_FLAG_UNINTERACTIBLE
Definition: UnitDefines.h:160
DamageEffectType
Definition: Unit.h:352
#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(Creature *creature=nullptr)
Definition: CreatureAI.cpp:73
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:48
bool UpdateVictim()
Definition: CreatureAI.cpp:240
Creature *const me
Definition: CreatureAI.h:81
void SetReactState(ReactStates st)
Definition: Creature.h:119
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2172
void SetTarget(ObjectGuid guid) override
Definition: Creature.cpp:3150
CreatureAI * AI() const
Definition: Creature.h:154
iterator end()
Definition: MapRefManager.h:35
iterator begin()
Definition: MapRefManager.h:34
PlayerList const & GetPlayers() const
Definition: Map.h:448
static ObjectGuid const Empty
Definition: ObjectGuid.h:132
void Clear()
Definition: ObjectGuid.h:151
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:77
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
void DoMeleeAttackIfReady()
Definition: UnitAI.cpp:62
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:174
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:104
virtual void AttackStart(Unit *)
Definition: UnitAI.cpp:30
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:114
Definition: Unit.h:769
bool IsWithinMeleeRange(Unit const *obj) const
Definition: Unit.h:842
void SetVisible(bool x)
Definition: Unit.cpp:8509
void KillSelf(bool durabilityLoss=true)
Definition: Unit.h:1021
void SetFullHealth()
Definition: Unit.h:925
ThreatManager & GetThreatManager()
Definition: Unit.h:1153
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3093
void StopMoving()
Definition: Unit.cpp:10303
void SetHealth(uint32 val)
Definition: Unit.cpp:9351
TempSummon * ToTempSummon()
Definition: Unit.h:1794
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition: Unit.cpp:4531
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition: Unit.cpp:12924
uint32 GetHealth() const
Definition: Unit.h:911
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3780
Unit * GetVictim() const
Definition: Unit.h:857
void SetFacingTo(float const ori, bool force=true)
Definition: Unit.cpp:13284
void RemoveAllAuras()
Definition: Unit.cpp:4153
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:952
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:953
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition: Object.cpp:1160
Map * GetMap() const
Definition: Object.h:449
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1080
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
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition: Object.cpp:2099
void PlayDirectSound(uint32 soundId, Player *target=nullptr)
Definition: Object.cpp:3432
virtual uint32 GetData(uint32) const
Definition: ZoneScript.h:55
virtual void SetData(uint32, uint32)
Definition: ZoneScript.h:56
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:457
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:157
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:965
CreatureAI * GetAI(Creature *creature) const override
Definition: boss_cthun.cpp:887
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)
float GetPositionZ() const
Definition: Position.h:81
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:128
void SetOrientation(float orientation)
Definition: Position.h:74
float GetPositionX() const
Definition: Position.h:79
float GetPositionY() const
Definition: Position.h:80
void AttackStart(Unit *) override
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:838
cthunAI(Creature *creature)
Definition: boss_cthun.cpp:464
void UpdateAI(uint32 diff) override
Definition: boss_cthun.cpp:575
void DoAction(int32 param) override
Definition: boss_cthun.cpp:869
std::unordered_map< ObjectGuid, bool > Stomach_Map
Definition: boss_cthun.cpp:514
void Reset() override
Definition: boss_cthun.cpp:516
ObjectGuid HoldPlayer
Definition: boss_cthun.cpp:501
uint32 GiantClawTentacleTimer
Definition: boss_cthun.cpp:506
Unit * SelectRandomNotStomach()
Definition: boss_cthun.cpp:540
uint32 GiantEyeTentacleTimer
Definition: boss_cthun.cpp:507
ObjectGuid StomachEnterTarget
Definition: boss_cthun.cpp:511
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
Definition: boss_cthun.cpp:843
void SpawnEyeTentacle(float x, float y)
Definition: boss_cthun.cpp:532
void UpdateAI(uint32 diff) override
Definition: boss_cthun.cpp:238
void JustEngagedWith(Unit *) override
Definition: boss_cthun.cpp:224
void SpawnEyeTentacle(float x, float y)
Definition: boss_cthun.cpp:230
eye_of_cthunAI(Creature *creature)
Definition: boss_cthun.cpp:164
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
Definition: boss_cthun.cpp:406
claw_tentacleAI(Creature *creature)
Definition: boss_cthun.cpp:972
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void JustDied(Unit *) override
Definition: boss_cthun.cpp:992
void UpdateAI(uint32 diff) override
Definition: boss_cthun.cpp:932
void JustEngagedWith(Unit *) override
Definition: boss_cthun.cpp:927
eye_tentacleAI(Creature *creature)
Definition: boss_cthun.cpp:894
void JustDied(Unit *) override
Definition: boss_cthun.cpp:912
@ 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