Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_shade_of_akama.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/*
7Name: Boss_Shade_of_Akama
8%Complete: 80
9Comment: WIP A few more adds to script, ending script, and bugs.
10Category: Black Temple
11*/
12
13#include "ObjectMgr.h"
14#include "ScriptMgr.h"
15#include "ScriptedCreature.h"
16#include "ScriptedGossip.h"
17#include "GridNotifiers.h"
18#include "black_temple.h"
19
20enum Says
21{
22 // Akama Ending cinematic text
26};
27
29{
30 // Akama
31 SPELL_STEALTH = 34189, // On Spawn
32 SPELL_AKAMA_SOUL_CHANNEL = 40447, // Cast on self hits Shade
33 SPELL_FIXATE = 40607, // Cast on self hits Shade
34 SPELL_CHAIN_LIGHTNING = 39945, // Combat
35 SPELL_DESTRUCTIVE_POISON = 40874, // Combat
36 // Shade
37 SPELL_THREAT = 41602, // self cast hits Akama
38 SPELL_SHADE_OF_AKAMA_TRIGGER = 40955, // Cast on death
39 SPELL_AKAMA_SOUL_EXPEL_CHANNEL = 40927, // must hit shade
40 SPELL_AKAMA_SOUL_EXPEL = 40902, // the one he cast
41 // Ashtongue Channeler
44 SPELL_SHADOWFORM = 40973, // Cast on Shade
45 // Creature Spawner
49 // Ashtongue Defender
54 // Ashtongue Rogue
57 // Ashtongue Elementalist
60 // Ashtongue Spiritbinder
64};
65
77
79{
82};
83
94
131
132struct Location
133{
134 float x, y, z;
135};
136
137static Location ShadeWP = { 512.4877f, 400.7993f, 112.7837f };
138
140{
141 { 517.4877f, 400.7993f, 112.7837f },
142 { 468.4435f, 401.1062f, 118.5379f }
143};
144
145// ########################################################
146// Shade of Akama
147// ########################################################
148
150{
151public:
152 boss_shade_of_akama() : CreatureScript("boss_shade_of_akama") { }
153
155 {
161
163 {
165 {
166 for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr)
167 if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr))
168 Channeler->DespawnOrUnsummon();
169
170 for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
171 if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
172 Spawner->AI()->SetData(SETDATA_DATA, SETDATA_DESPAWN_ALL_SPAWNS);
173
174 events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 3000);
175 events.ScheduleEvent(EVENT_RESET_ENCOUNTER, 5000);
176 }
177
179
180 me->SetWalk(true);
181 combatStarted = false;
182 akamaReached = false;
183 HasKilledAkama = false;
185 }
186
187 void JustDied(Unit* /*killer*/) OVERRIDE
188 {
189 if (instance)
190 instance->SetBossState(DATA_SHADE_OF_AKAMA, DONE);
191 }
192
193 void EnterCombat(Unit* /*who*/) OVERRIDE { }
194
196 {
198 {
200 if (Akama->IsAlive())
202 }
203 else
205 }
206
207 void SetData(uint32 data, uint32 value) OVERRIDE
208 {
209 if (data == SETDATA_DATA && value == SETDATA_CHANNELER_DIED)
210 me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2);
211
212 UpdateSpeed();
213 }
214
215 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
216 {
217 if (spell->Id == SPELL_AKAMA_SOUL_CHANNEL)
218 {
219 combatStarted = true;
220 events.ScheduleEvent(EVENT_START_ATTACK_AKAMA, 500);
221 events.ScheduleEvent(EVENT_SET_CHANNELERS_SPAWNERS, 1000);
224 me->AddThreat(Akama, 10000000.0f);
225 }
226 else if (spell->Id == SPELL_SHADE_SOUL_CHANNEL_2)
227 UpdateSpeed();
228 }
229
231 {
232 float moveSpeed = 0.2f;
233
234 if (me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2) <= 3)
235 {
236 moveSpeed = (2.0 - (0.6 * me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2)));
237 me->SetSpeed(MOVE_WALK, moveSpeed / 2.5);
238 me->SetSpeed(MOVE_RUN, (moveSpeed * 2) / 7);
239 me->ClearUnitState(UNIT_STATE_ROOT);
240 }
241 else
242 me->AddUnitState(UNIT_STATE_ROOT);
243 }
244
246 {
248 return;
249
250 events.Update(diff);
251
252 if (!combatStarted)
253 {
254 while (uint32 eventId = events.ExecuteEvent())
255 {
256 switch (eventId)
257 {
260 if (!Akama->IsAlive())
261 Akama->Respawn();
262 break;
264 {
265 std::list<Creature*> ChannelerList;
266 me->GetCreatureListWithEntryInGrid(ChannelerList, NPC_ASHTONGUE_CHANNELER, 15.0f);
267
268 if (!ChannelerList.empty())
269 for (std::list<Creature*>::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr)
270 {
271 Channelers.push_back((*itr)->GetGUID());
272 if ((*itr)->isDead())
273 (*itr)->Respawn();
274 }
275
276 std::list<Creature*> SpawnerList;
277 me->GetCreatureListWithEntryInGrid(SpawnerList, NPC_CREATURE_SPAWNER_AKAMA, 90.0f);
278
279 if (!SpawnerList.empty())
280 for (std::list<Creature*>::const_iterator itr = SpawnerList.begin(); itr != SpawnerList.end(); ++itr)
281 Spawners.push_back((*itr)->GetGUID());
282
284 break;
285 }
286 default:
287 break;
288 }
289 }
290 }
291 else
292 {
293 while (uint32 eventId = events.ExecuteEvent())
294 {
295 switch (eventId)
296 {
298 {
299 for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr)
300 {
301 if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr))
302 Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
303 }
304
305 for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
306 {
307 if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
308 Spawner->AI()->SetData(SETDATA_DATA, SETDATA_START_SPAWNING);
309 }
310 break;
311 }
313 me->GetMotionMaster()->MovePoint(0, ShadeWP.x, ShadeWP.y, ShadeWP.z, false);
314 events.ScheduleEvent(EVENT_START_ATTACK_AKAMA, 1000);
315 break;
316 case EVENT_ADD_THREAT:
318 events.ScheduleEvent(EVENT_ADD_THREAT, 3500);
319 break;
320 default:
321 break;
322 }
323 }
324
325 if (HasKilledAkama)
326 {
328 {
332 me->RemoveAllAurasExceptType(SPELL_AURA_DUMMY);
333 me->DeleteThreatList();
334 me->CombatStop();
335 me->GetMotionMaster()->MoveTargetedHome();
337 combatStarted = false;
338
340 Akama->DespawnOrUnsummon();
341
342 for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr)
343 if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr))
344 Channeler->DespawnOrUnsummon();
345
346 for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
347 if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
348 Spawner->AI()->SetData(SETDATA_DATA, SETDATA_DESPAWN_ALL_SPAWNS);
349
350 events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 10000);
351 events.ScheduleEvent(EVENT_RESET_ENCOUNTER, 20000);
352 }
353 }
354
355 if (!akamaReached)
356 {
358 {
359 if (me->IsWithinDist(Akama, 2.0f, false))
360 {
361 akamaReached = true;
362 me->GetMotionMaster()->Clear(true);
363 me->GetMotionMaster()->MoveIdle();
364 me->SetWalk(false);
365
367
368 events.CancelEvent(EVENT_START_ATTACK_AKAMA);
369 events.ScheduleEvent(EVENT_ADD_THREAT, 100);
370
371 for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
372 if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
373 Spawner->AI()->SetData(SETDATA_DATA, SETDATA_STOP_SPAWNING);
374 }
375 }
376 }
377 else
379 }
380 }
381
382 public:
384 private:
387 std::list<uint64> Channelers;
388 std::list<uint64> Spawners;
392 };
393
395 {
396 return new boss_shade_of_akamaAI(creature);
397 }
398};
399
400// ########################################################
401// Akama
402// ########################################################
403
405{
406public:
407 npc_akama_shade() : CreatureScript("npc_akama_shade") { }
408
409 struct npc_akamaAI : public ScriptedAI
410 {
411 npc_akamaAI(Creature* creature) : ScriptedAI(creature)
412 {
413 instance = creature->GetInstanceScript();
414 }
415
417 {
418 me->setFaction(FACTION_FRIENDLY);
421 StartChannel = false;
422 StartCombat = false;
423 HasYelledOnce = false;
424 ShadeHasDied = false;
425 }
426
427 void JustDied(Unit* /*killer*/) OVERRIDE
428 {
430 if (Shade->IsAlive())
431 CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true;
432 me->GetMotionMaster()->Clear(true);
433 me->GetMotionMaster()->MoveIdle();
434 }
435
436 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
437 {
438 if (spell->Id == SPELL_THREAT && !StartCombat)
439 {
440 me->ClearUnitState(UNIT_STATE_ROOT);
441 me->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL);
444 Shade->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL);
445 StartCombat = true;
446 }
447 }
448
449 void EnterCombat(Unit* /*who*/) OVERRIDE
450 {
451 events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 2000);
452 events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, 5000);
453 }
454
456 {
457 if (StartChannel)
458 {
459 events.Update(diff);
460
461 while (uint32 eventId = events.ExecuteEvent())
462 {
463 switch (eventId)
464 {
466 if (instance)
467 {
470 me->RemoveAura(SPELL_STEALTH);
471 me->SetWalk(true);
472 me->GetMotionMaster()->MovePoint(0, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z, false);
473 events.ScheduleEvent(EVENT_SHADE_CHANNEL, 10000);
474 break;
475 }
477 me->AddUnitState(UNIT_STATE_ROOT);
478 me->SetFacingTo(3.118662f);
480 me->setFaction(FACTION_COMBAT);
482 events.ScheduleEvent(EVENT_FIXATE, 5000);
483 break;
484 case EVENT_FIXATE:
486 StartChannel = false;
487 break;
488 default:
489 break;
490 }
491 }
492 }
493
494 if (!UpdateVictim())
495 return;
496
497 events.Update(diff);
498
499 while (uint32 eventId = events.ExecuteEvent())
500 {
501 switch (eventId)
502 {
505 events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, std::rand() % 15000 + 10000);
506 break;
509 events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, std::rand() % 5000 + 4000);
510 break;
511 default:
512 break;
513 }
514 }
515
517 }
518
519 void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) OVERRIDE
520 {
521 if (action == 0)
522 {
523 player->CLOSE_GOSSIP_MENU();
524 StartChannel = true;
525 events.ScheduleEvent(EVENT_SHADE_START, 500);
526 }
527 }
528
529 private:
536 };
537
539 {
540 return new npc_akamaAI(creature);
541 }
542};
543
544// ########################################################
545// Ashtongue Channeler
546// ########################################################
547
549{
550public:
551 npc_ashtongue_channeler() : CreatureScript("npc_ashtongue_channeler") { }
552
554 {
556 {
557 instance = creature->GetInstanceScript();
558 }
559
561 {
562 me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
563 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
564
566 events.ScheduleEvent(EVENT_CHANNEL, 2000);
567 }
568
569 void JustDied(Unit* /*killer*/) OVERRIDE
570 {
572 Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
573 }
574
575 void EnterCombat(Unit* /*who*/) OVERRIDE { }
576 void AttackStart(Unit* /*who*/) OVERRIDE { }
577
579 {
580 events.Update(diff);
581
582 while (uint32 eventId = events.ExecuteEvent())
583 {
584 switch (eventId)
585 {
586 case EVENT_CHANNEL:
588 {
589 if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
591 else
592 {
593 me->InterruptSpell(CURRENT_CHANNELED_SPELL);
594 Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
595 }
596 }
597 events.ScheduleEvent(EVENT_CHANNEL, 2000);
598 break;
599 default:
600 break;
601 }
602 }
603 }
604
605 private:
608 };
609
611 {
612 return new npc_ashtongue_channelerAI(creature);
613 }
614};
615
616// ########################################################
617// Creature Generator Akama
618// ########################################################
619
621{
622public:
623 npc_creature_generator_akama() : CreatureScript("npc_creature_generator_akama") { }
624
626 {
628 {
629 instance = creature->GetInstanceScript();
630 }
631
633 {
634 Summons.DespawnAll();
635
636 doSpawning = false;
637 leftSide = false;
638
639 if (me->GetPositionY() < 400.0f)
640 leftSide = true;
641 }
642
644 {
645 Summons.Summon(summon);
646 }
647
648 void SetData(uint32 data, uint32 value) OVERRIDE
649 {
650 if (data == SETDATA_DATA)
651 {
652 doSpawning = true;
653
654 switch (value)
655 {
657 if (leftSide)
658 {
659 events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 100);
660 events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, std::rand() % 5000 + 2000);
661 }
662 else
663 {
664 events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 10000);
665 events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, std::rand() % 5000 + 2000);
666 }
667 break;
669 doSpawning = false;
670 break;
672 doSpawning = false;
673 Summons.DespawnAll();
674 break;
675 default:
676 break;
677 }
678 }
679 }
680
682 {
683 if (doSpawning)
684 {
685 events.Update(diff);
686
687 while (uint32 eventId = events.ExecuteEvent())
688 {
689 switch (eventId)
690 {
693 events.ScheduleEvent(EVENT_SPAWN_WAVE_B, std::rand() % 50000 + 45000);
694 break;
697 events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, std::rand() % 35000 + 30000);
698 break;
701 events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, std::rand() % 35000 + 30000);
702 break;
703 default:
704 break;
705 }
706 }
707 }
708 }
709
710 private:
716 };
717
719 {
720 return new npc_creature_generator_akamaAI(creature);
721 }
722};
723
724// ########################################################
725// Ashtongue Sorcerer
726// ########################################################
727
729{
730public:
731 npc_ashtongue_sorcerer() : CreatureScript("npc_ashtongue_sorcerer") { }
732
734 {
736 {
737 instance = creature->GetInstanceScript();
738 }
739
741 {
742 if (!startedBanishing)
743 {
745 {
746 if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
747 me->GetMotionMaster()->MovePoint(0, Shade->GetPositionX(), Shade->GetPositionY(), Shade->GetPositionZ(), false);
748 else
749 {
750 if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE)))
751 AttackStart(target);
752 }
753 }
754 }
755
756 summonerGuid = 0;
757 startedBanishing = false;
758 switchToCombat = false;
759 }
760
761 void JustDied(Unit* /*killer*/) OVERRIDE
762 {
764 Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
765 me->DespawnOrUnsummon(5000);
766 }
767
768 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
769 {
770 if (Creature* summoner = (Unit::GetCreature((*me), summonerGuid)))
772 }
773
774 void EnterCombat(Unit* /*who*/) OVERRIDE { }
775
777 {
778 if (!switchToCombat)
779 return;
781 }
782
784 {
785 events.Update(diff);
786
787 while (uint32 eventId = events.ExecuteEvent())
788 {
789 switch (eventId)
790 {
793 {
794 if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
795 {
796 me->SetFacingToObject(Shade);
798 events.ScheduleEvent(EVENT_SORCERER_CHANNEL, 2000);
799 }
800 else
801 {
802 me->InterruptSpell(CURRENT_CHANNELED_SPELL);
803 Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
804 switchToCombat = true;
805 if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE)))
806 AttackStart(target);
807 }
808 }
809 break;
810 default:
811 break;
812 }
813 }
814
815 if (!startedBanishing)
816 {
818 if (me->IsWithinDist(Shade, 20.0f, false))
819 {
820 me->StopMoving();
821 me->GetMotionMaster()->Clear(false);
822 me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + frand (-8.0f, 8.0f), me->GetPositionY() + frand (-8.0f, 8.0f), me->GetPositionZ(), false);
823 events.ScheduleEvent(EVENT_SORCERER_CHANNEL, 1500);
824 startedBanishing = true;
825 }
826 }
827
829 }
830
831 private:
837 };
838
840 {
841 return new npc_ashtongue_sorcererAI(creature);
842 }
843};
844
845// ########################################################
846// Ashtongue Defender
847// ########################################################
848
850{
851public:
852 npc_ashtongue_defender() : CreatureScript("npc_ashtongue_defender") { }
853
855 {
857 {
858 instance = creature->GetInstanceScript();
859 }
860
862 {
863 summonerGuid = 0;
864
865 if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE)))
866 AttackStart(target);
867 }
868
869 void JustDied(Unit* /*killer*/) OVERRIDE
870 {
871 me->DespawnOrUnsummon(5000);
872 }
873
874 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
875 {
876 if (Creature* summoner = (Unit::GetCreature((*me), summonerGuid)))
878 }
879
880 void EnterCombat(Unit* /*who*/) OVERRIDE
881 {
882 events.ScheduleEvent(EVENT_HEROIC_STRIKE, 5000);
883 events.ScheduleEvent(EVENT_SHIELD_BASH, std::rand() % 16000 + 10000);
884 events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, std::rand() % 16000 + 10000);
885 events.ScheduleEvent(EVENT_WINDFURY, std::rand() % 12000 + 8000);
886 }
887
889 {
890 if (!UpdateVictim())
891 return;
892
893 events.Update(diff);
894
895 while (uint32 eventId = events.ExecuteEvent())
896 {
897 switch (eventId)
898 {
901 events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, std::rand() % 16000 + 8000);
902 break;
905 events.ScheduleEvent(EVENT_HEROIC_STRIKE, std::rand() % 60000 + 50000);
906 break;
909 events.ScheduleEvent(EVENT_SHIELD_BASH, std::rand() % 16000 + 8000);
910 break;
911 case EVENT_WINDFURY:
913 events.ScheduleEvent(EVENT_WINDFURY, std::rand() % 8000 + 6000);
914 break;
915 default:
916 break;
917 }
918 }
919
921 }
922
923 private:
927 };
928
930 {
931 return new npc_ashtongue_defenderAI(creature);
932 }
933};
934
935// ########################################################
936// Ashtongue Rogue
937// ########################################################
938
940{
941public:
942 npc_ashtongue_rogue() : CreatureScript("npc_ashtongue_rogue") { }
943
945 {
947 {
948 instance = creature->GetInstanceScript();
949 }
950
952 {
953 summonerGuid = 0;
954
955 if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE)))
956 AttackStart(target);
957 }
958
959 void JustDied(Unit* /*killer*/) OVERRIDE
960 {
961 me->DespawnOrUnsummon(5000);
962 }
963
964 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
965 {
966 if (Creature* summoner = (Unit::GetCreature((*me), summonerGuid)))
968 }
969
970 void EnterCombat(Unit* /*who*/) OVERRIDE
971 {
972 events.ScheduleEvent(EVENT_DEBILITATING_POISON, std::rand() % 2000 + 500);
973 events.ScheduleEvent(EVENT_EVISCERATE, std::rand() % 5000 + 2000);
974 }
975
977 {
978 if (!UpdateVictim())
979 return;
980
981 events.Update(diff);
982
983 while (uint32 eventId = events.ExecuteEvent())
984 {
985 switch (eventId)
986 {
989 events.ScheduleEvent(EVENT_DEBILITATING_POISON, std::rand() % 18000 + 14000);
990 break;
991 case EVENT_EVISCERATE:
993 events.ScheduleEvent(EVENT_EVISCERATE, std::rand() % 16000 + 12000);
994 break;
995 default:
996 break;
997 }
998 }
999
1001 }
1002
1003 private:
1007 };
1008
1010 {
1011 return new npc_ashtongue_rogueAI(creature);
1012 }
1013};
1014
1015// ########################################################
1016// Ashtongue Elementalist
1017// ########################################################
1018
1020{
1021public:
1022 npc_ashtongue_elementalist() : CreatureScript("npc_ashtongue_elementalist") { }
1023
1025 {
1027 {
1028 instance = creature->GetInstanceScript();
1029 }
1030
1032 {
1033 summonerGuid = 0;
1034
1035 if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE)))
1036 AttackStart(target);
1037 }
1038
1039 void JustDied(Unit* /*killer*/) OVERRIDE
1040 {
1041 me->DespawnOrUnsummon(5000);
1042 }
1043
1044 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
1045 {
1046 if (Creature* summoner = (Unit::GetCreature((*me), summonerGuid)))
1048 }
1049
1051 {
1052 events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 18000);
1053 events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 6000);
1054 }
1055
1057 {
1058 if (!UpdateVictim())
1059 return;
1060
1061 events.Update(diff);
1062
1063 while (uint32 eventId = events.ExecuteEvent())
1064 {
1065 switch (eventId)
1066 {
1067 case EVENT_RAIN_OF_FIRE:
1069 events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 20000);
1070 break;
1073 events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 15000);
1074 break;
1075 default:
1076 break;
1077 }
1078 }
1079
1081 }
1082
1083 private:
1087 };
1088
1090 {
1091 return new npc_ashtongue_elementalistAI(creature);
1092 }
1093};
1094
1095// ########################################################
1096// Ashtongue Spiritbinder
1097// ########################################################
1098
1100{
1101public:
1102 npc_ashtongue_spiritbinder() : CreatureScript("npc_ashtongue_spiritbinder") { }
1103
1105 {
1107 {
1108 instance = creature->GetInstanceScript();
1109 }
1110
1112 {
1113 spiritMend = false;
1114 chainHeal = false;
1115 summonerGuid = 0;
1116
1117 if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE)))
1118 AttackStart(target);
1119 }
1120
1121 void JustDied(Unit* /*killer*/) OVERRIDE
1122 {
1123 me->DespawnOrUnsummon(5000);
1124 }
1125
1126 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
1127 {
1128 if (Creature* summoner = (Unit::GetCreature((*me), summonerGuid)))
1130 }
1131
1133 {
1134 events.ScheduleEvent(EVENT_SPIRIT_HEAL, std::rand() % 6000 + 5000);
1135 }
1136
1138 {
1139 events.Update(diff);
1140
1141 while (uint32 eventId = events.ExecuteEvent())
1142 {
1143 switch (eventId)
1144 {
1145 case EVENT_SPIRIT_HEAL:
1147 events.ScheduleEvent(EVENT_SPIRIT_HEAL, std::rand() % 16000 + 13000);
1148 break;
1149 default:
1150 break;
1151 }
1152 }
1153
1154 if (!UpdateVictim())
1155 return;
1156
1157 if (!spiritMend)
1158 {
1159 if (HealthBelowPct(25))
1160 {
1162 spiritMend = true;
1163 }
1164 }
1165
1166 if (!chainHeal)
1167 {
1168 if (HealthBelowPct(40))
1169 {
1171 chainHeal = true;
1172 }
1173 }
1174
1176 }
1177
1178 private:
1184 };
1185
1187 {
1188 return new npc_ashtongue_spiritbinderAI(creature);
1189 }
1190};
1191
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
#define CAST_AI(a, b)
@ EMOTE_STATE_STUN
@ EMOTE_STATE_NONE
@ SPELL_EFFECT_ATTACK_ME
@ IMMUNITY_STATE
@ IMMUNITY_EFFECT
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_TAUNT
@ UNIT_NPC_FLAG_GOSSIP
Definition Unit.h:687
@ CURRENT_CHANNELED_SPELL
Definition Unit.h:1110
@ UNIT_STATE_ROOT
Definition Unit.h:522
@ MOVE_RUN
Definition Unit.h:556
@ MOVE_WALK
Definition Unit.h:555
@ UNIT_FLAG_STUNNED
Definition Unit.h:643
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_NPC_EMOTESTATE
float frand(float min, float max)
Definition Util.cpp:39
Creatures
@ DATA_AKAMA_SHADE
@ DATA_SHADE_OF_AKAMA
@ SPELL_WINDFURY
@ SPELL_RAIN_OF_FIRE
@ EVENT_RAIN_OF_FIRE
@ SPELL_LIGHTNING_BOLT
static const Locations AkamaWP[13]
@ SPELL_HEROIC_STRIKE
@ SPELL_SHADOWFORM
@ SAY_BROKEN_FREE_0
@ SAY_BROKEN_FREE_1
@ SAY_BROKEN_FREE_2
@ SETDATA_START_SPAWNING
@ SETDATA_START_ATTACK_AKAMA
@ SETDATA_CHANNELER_DIED
@ SETDATA_DESPAWN_ALL_SPAWNS
@ SETDATA_RESET
@ SETDATA_STOP_SPAWNING
@ NPC_ASHTONGUE_ELEMENTALIST
@ NPC_ASHTONGUE_SORCERER
@ NPC_ASHTONGUE_BROKEN
@ NPC_ASHTONGUE_ROGUE
@ NPC_ASHTONGUE_DEFENDER
@ NPC_ASHTONGUE_SPIRITBINDER
@ NPC_ASHTONGUE_CHANNELER
@ NPC_CREATURE_SPAWNER_AKAMA
@ SPELL_WINDFURY
@ SPELL_SHIELD_BASH
@ SPELL_SUMMON_ASHTONGUE_DEFENDER
@ SPELL_SUMMON_ASHTONGUE_SORCERER
@ SPELL_EVISCERATE
@ SPELL_SHADE_SOUL_CHANNEL
@ SPELL_CHAIN_HEAL
@ SPELL_RAIN_OF_FIRE
@ SPELL_ASHTONGUE_WAVE_B
@ SPELL_AKAMA_SOUL_EXPEL
@ SPELL_DEBILITATING_POISON
@ SPELL_LIGHTNING_BOLT
@ SPELL_HEROIC_STRIKE
@ SPELL_SHADE_OF_AKAMA_TRIGGER
@ SPELL_STEALTH
@ SPELL_SPIRIT_MEND
@ SPELL_SHADE_SOUL_CHANNEL_2
@ SPELL_CHAIN_LIGHTNING
@ SPELL_DESTRUCTIVE_POISON
@ SPELL_DEBILITATING_STRIKE
@ SPELL_AKAMA_SOUL_EXPEL_CHANNEL
@ SPELL_AKAMA_SOUL_CHANNEL
@ SPELL_SPIRITBINDER_SPIRIT_HEAL
void AddSC_boss_shade_of_akama()
static Location AkamaWP[]
@ FACTION_FRIENDLY
@ FACTION_COMBAT
static Location ShadeWP
@ EVENT_CHAIN_LIGHTNING
@ EVENT_SHADE_START
@ EVENT_SPAWN_WAVE_B
@ EVENT_SHIELD_BASH
@ EVENT_ADD_THREAT
@ EVENT_SHADE_CHANNEL
@ EVENT_SUMMON_ASHTONGUE_DEFENDER
@ EVENT_SORCERER_CHANNEL
@ EVENT_EVISCERATE
@ EVENT_RESET_ENCOUNTER
@ EVENT_SPIRIT_HEAL
@ EVENT_RAIN_OF_FIRE
@ EVENT_START_ATTACK_AKAMA
@ EVENT_LIGHTNING_BOLT
@ EVENT_DESTRUCTIVE_POISON
@ EVENT_FIND_CHANNELERS_SPAWNERS
@ EVENT_HEROIC_STRIKE
@ EVENT_DEBILITATING_POISON
@ EVENT_SUMMON_ASHTONGUE_SORCERER
@ EVENT_DEBILITATING_STRIKE
@ EVENT_SET_CHANNELERS_SPAWNERS
@ EVENT_CHAIN_LIGHTNING
@ SPELL_CHAIN_LIGHTNING
@ SPELL_CHAIN_HEAL
Definition chapter5.cpp:204
bool UpdateVictim()
CreatureScript(const char *name)
static Creature * GetCreature(WorldObject const &u, uint64 guid)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
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
@ EVENT_SHIELD_BASH
@ SPELL_STEALTH
float y
Definition chapter5.cpp:210
float z
Definition chapter5.cpp:210
float x
Definition chapter5.cpp:210
Creature * me
bool HealthBelowPct(uint32 pct) const
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
void SetData(uint32 data, uint32 value) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void sGossipSelect(Player *player, uint32, uint32 action) OVERRIDE
void SpellHit(Unit *, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
@ FACTION_FRIENDLY
@ SPELL_SHIELD_BASH
Definition zulfarrak.cpp:43