Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_illidan.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/* ScriptData
7SDName: boss_illidan_stormrage
8SD%Complete: 90
9SDComment: Somewhat of a workaround for Parasitic Shadowfiend, unable to summon GOs for Cage Trap.
10SDCategory: Black Temple
11EndScriptData */
12
13#include "ScriptMgr.h"
14#include "ScriptedCreature.h"
15#include "ScriptedGossip.h"
16#include "PassiveAI.h"
17#include "black_temple.h"
18#include "Player.h"
19#include "SpellInfo.h"
20
21#define EMOTE_UNABLE_TO_SUMMON "%s is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter."
22
23// Other defines
24#define CENTER_X 676.740f
25#define CENTER_Y 305.297f
26#define CENTER_Z 353.192f
27
47
49// Normal Form
50{
51 SPELL_SHEAR = 37335, // 41032 is bugged, cannot be block/dodge/parry// Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5f second cast
58 SPELL_ENRAGE = 40683,
59// Flying (Phase 2)
61 SPELL_THROW_GLAIVE2 = 39849, // Animation for the spell above
65// Demon Form
72 SPELL_FLAME_BURST_EFFECT = 41131, // The actual damage. Have each player cast it on itself (workaround)
73// Other Illidan spells
74 SPELL_KNEEL = 39656, // Before beginning encounter, this is how he appears (talking to skully).
76 SPELL_DEATH = 41220,
80// Phase Normal spells
88// Phase Flight spells
89 SPELL_AZZINOTH_CHANNEL = 39857, // Glaives cast it on Flames. Not sure if this is the right spell.
96 SPELL_CHARGE = 41581,
98// Akama spells
101 SPELL_AKAMA_DOOR_FAIL = 41271, // Not sure where this is really used...
104// Maiev spells
105 SPELL_CAGE_TRAP_DUMMY = 40761, // Put this in DB for cage trap GO.
106 SPELL_CAGED = 40695,
107 SPELL_CAGE_TRAP_SUMMON = 40694, // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working)
112 SPELL_FAN_BLADES = 39954 // bugged visual
113};
114
128
129/**** Creature Summon and Recognition IDs ****/
148
149/*** Phase Names ***/
163
174
204
214
227
228
229/* ################## TO DO CONVERT THIS UGLINESS TO CREATURE TEXT ##################
230
231SET @AKAMA := 23089;
232SET @ILLIDAN := 22917;
233SET @MAIEV := 23197;
234DELETE FROM `creature_text` WHERE `entry`=@AKAMA AND `groupid` IN (2,3,4);
235DELETE FROM `creature_text` WHERE `entry`=@ILLIDAN AND `groupid` IN (8,9,10,11,12,13,14);
236DELETE FROM `creature_text` WHERE `entry`=@MAIEV AND `groupid` IN (1,2,3,4);
237INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
238(@ILLIDAN,8,0, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.",14,0,100,0,0,11463, 'Illidan SAY_XXXXXXXXXXX'),
239(@AKAMA,2,0, "We've come to end your reign, Illidan. My people and all of Outland shall be free!",14,0,100,25,0,11389, 'Akama SAY_XXXXXXXXXXX'),
240(@ILLIDAN,9,0, "Boldly said. But I remain unconvinced.",14,0,100,396,0,11464, 'Illidan SAY_XXXXXXXXXXX'),
241(@AKAMA,3,0, "The time has come! The moment is at hand!",14,0,100,22,0,11380, 'Akama SAY_XXXXXXXXXXX'),
242(@ILLIDAN,10,0, "You are not prepared!",14,0,100,406,0,11466, 'Illidan SAY_XXXXXXXXXXX'),
243(@ILLIDAN,11,0, "Is this it, mortals? Is this all the fury you can muster?",14,0,100,0,0,11476, 'Illidan SAY_XXXXXXXXXXX'),
244(@MAIEV,1,0, "Their fury pales before mine, Illidan. We have some unsettled business between us.",14,0,100,5,0,11491, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
245(@ILLIDAN,12,0, "Maiev... How is this even possible?",14,0,100,1,0,11477, 'Illidan SAY_XXXXXXXXXXX'),
246(@MAIEV,2,0, "Ah... my long hunt is finally over. Today, Justice will be done!",14,0,100,15,0,11492, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
247(@ILLIDAN,13,0, "Feel the hatred of ten thousand years!",14,0,100,396,0,11470, 'Illidan SAY_XXXXXXXXXXX'),
248(@MAIEV,3,0, "Ahh... It is finished. You are beaten.",14,0,100,0,0,11496, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
249(@ILLIDAN,14,0, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..",14,0,100,65,0,11478, 'Illidan SAY_XXXXXXXXXXX'),
250(@MAIEV,4,0, "He is right. I feel nothing... I am nothing... Farewell, champions.",14,0,100,0,0,11497, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
251(@AKAMA,4,0, "The Light will fill these dismal halls once again. I swear it.",14,0,100,0,0,11387, 'Akama SAY_XXXXXXXXXXX');
252
253*/
254
255struct Yells
256{
258 std::string text;
260 bool Talk;
261};
262
263static const Yells Conversation[22] =
264{
265 {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true},
266 {0, "", ILLIDAN_STORMRAGE, 5000, 396, true},
267 {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true},
268 {0, "", AKAMA, 5000, 66, true},
269 {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true},
270 {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true},
271 {0, "", AKAMA, 2000, 15, true},
272 {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true},
273 {0, "", EMPTY, 1000, 0, true},
274 {0, "", EMPTY, 0, 0, false}, // 9
275 {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true},
276 {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true},
277 {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 5000, 1, true},
278 {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true},
279 {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false}, // 14
280 {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true}, // 15
281
282 {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 30000, 65, true}, // Emote dead for now. Kill him later
283 {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true},
284 {11498, "", MAIEV_SHADOWSONG, 5000, 0, true},
285 {11498, "", EMPTY, 1000, 0, true}, // 19 Maiev disappear
286 {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true},
287 {0, "", EMPTY, 1000, 0, false} // 21
288};
289
290struct Locations
291{
292 float x, y, z;
293};
294
295static const Locations HoverPosition[4]=
296{
297 {657.0f, 340.0f, 355.0f},
298 {657.0f, 275.0f, 355.0f},
299 {705.0f, 275.0f, 355.0f},
300 {705.0f, 340.0f, 355.0f}
301};
302
303static const Locations GlaivePosition[4]=
304{
305 {695.105f, 305.303f, 354.256f},
306 {659.338f, 305.303f, 354.256f}, // the distance between two glaives is 36
307 {700.105f, 305.303f, 354.256f},
308 {664.338f, 305.303f, 354.256f}
309};
310
311static const Locations EyeBlast[2]=
312{
313 {677.0f, 350.0f, 354.0f}, // start point, pass through glaive point
314 {677.0f, 260.0f, 354.0f}
315};
316
317static const Locations AkamaWP[13]=
318{
319 {770.01f, 304.50f, 312.29f}, // Bottom of the first stairs, at the doors
320 {780.66f, 304.50f, 319.74f}, // Top of the first stairs
321 {790.13f, 319.68f, 319.76f}, // Bottom of the second stairs (left from the entrance)
322 {787.17f, 347.38f, 341.42f}, // Top of the second stairs
323 {781.34f, 350.31f, 341.44f}, // Bottom of the third stairs
324 {762.60f, 361.06f, 353.60f}, // Top of the third stairs
325 {756.35f, 360.52f, 353.27f}, // Before the door-thingy
326 {743.82f, 342.21f, 353.00f}, // Somewhere further
327 {732.69f, 305.13f, 353.00f}, // In front of Illidan - (8)
328 {738.11f, 365.44f, 353.00f}, // in front of the door-thingy (the other one!)
329 {792.18f, 366.62f, 341.42f}, // Down the first flight of stairs
330 {796.84f, 304.89f, 319.76f}, // Down the second flight of stairs
331 {782.01f, 304.55f, 319.76f} // Final location - back at the initial gates. This is where he will fight the minions! (12)
332};
333// 755.762f, 304.0747f, 312.1769f -- This is where Akama should be spawned
334static const Locations SpiritSpawns[2]=
335{
336 {755.5426f, 309.9156f, 312.2129f},
337 {755.5426f, 298.7923f, 312.0834f}
338};
339
340struct Animation // For the demon transformation
341{
343 bool equip;
344};
345
347{
348 {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, true},
349 {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true},
350 {0, 0, 3000, 1073741824, 21322, 6, false}, // stunned, cannot cast demon form
351 {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false},
352 {SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 4, false},
353 {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, false},
354 {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false},
355 {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false},
356 {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true},
357 {0, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 8, true}
358};
359
361{
362public:
363 npc_flame_of_azzinoth() : CreatureScript("npc_flame_of_azzinoth") { }
364
366 {
367 flame_of_azzinothAI(Creature* creature) : ScriptedAI(creature) { }
368
370 {
371 FlameBlastTimer = 15000;
372 CheckTimer = 5000;
373 GlaiveGUID = 0;
374 }
375
376 void EnterCombat(Unit* /*who*/) OVERRIDE
377 {
379 }
380
382 {
383 Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false);
384 if (target && (!me->IsWithinCombatRange(target, FLAME_CHARGE_DISTANCE)))
385 {
386 me->AddThreat(target, 5000000.0f);
387 AttackStart(target);
388 DoCast(target, SPELL_CHARGE);
390 }
391 }
392
394 {
396 {
397 if (!me->IsWithinDistInMap(glaive, FLAME_ENRAGE_DISTANCE))
398 {
399 glaive->InterruptNonMeleeSpells(true);
403 {
404 me->AddThreat(me->GetVictim(), 5000000.0f);
405 AttackStart(me->GetVictim());
406 }
407 }
408 else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL))
409 {
410 glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false);
411 me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE);
412 }
413 }
414 }
415
417 {
418 GlaiveGUID = guid;
419 }
420
422 {
423 if (!UpdateVictim())
424 return;
425
426 if (FlameBlastTimer <= diff)
427 {
428 DoCastVictim(SPELL_BLAZE_SUMMON, true); // appear at victim
430 FlameBlastTimer = 15000; // 10000 is official-like?
431 DoZoneInCombat(); // in case someone is revived
432 } else FlameBlastTimer -= diff;
433
434 if (CheckTimer <= diff)
435 {
436 ChargeCheck();
437 EnrageCheck();
438 CheckTimer = 1000;
439 } else CheckTimer -= diff;
440
442 }
443
444 private:
448 };
449
451 {
452 return new flame_of_azzinothAI(creature);
453 }
454};
455
456/************************************** Illidan's AI* **************************************/
458{
459public:
460 boss_illidan_stormrage() : CreatureScript("boss_illidan_stormrage") { }
461
463 {
465 {
466 instance = creature->GetInstanceScript();
467 DoCast(me, SPELL_DUAL_WIELD, true);
468 AkamaGUID = 0;
469 }
470
471 void Reset() OVERRIDE;
472
473 void JustSummoned(Creature* summon) OVERRIDE;
474
476 {
477 if (summon->GetCreatureTemplate()->Entry == FLAME_OF_AZZINOTH)
478 {
479 for (uint8 i = 0; i < 2; ++i)
480 if (summon->GetGUID() == FlameGUID[i])
481 FlameGUID[i] = 0;
482
483 if (!FlameGUID[0] && !FlameGUID[1] && Phase != PHASE_ILLIDAN_NULL)
484 {
485 me->InterruptNonMeleeSpells(true);
486 EnterPhase(PHASE_FLIGHT_SEQUENCE);
487 }
488 }
489 Summons.Despawn(summon);
490 }
491
492 void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) OVERRIDE
493 {
494 if (FlightCount == 7) // change hover point
495 {
496 if (me->GetVictim())
497 {
498 me->SetInFront(me->GetVictim());
499 me->StopMoving();
500 }
502 }
503 else // handle flight sequence
505 }
506
507 void EnterCombat(Unit* /*who*/) OVERRIDE
508 {
509 me->setActive(true);
511 }
512
514 {
515 if (!who || Phase >= PHASE_TALK_SEQUENCE)
516 return;
517
518 if (Phase == PHASE_FLIGHT || Phase == PHASE_DEMON)
520 else
522 }
523
525
526
527 void JustDied(Unit* /*killer*/) OVERRIDE
528 {
530
531 if (!instance)
532 return;
533
534 instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE);
535
537 instance->HandleGameObject(instance->GetData64(i), true);
538 }
539
541 {
542 if (victim->GetTypeId() != TypeID::TYPEID_PLAYER)
543 return;
544
546 }
547
548 void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
549 {
550 if (damage >= me->GetHealth() && done_by != me)
551 damage = 0;
552 if (done_by->GetGUID() == MaievGUID)
553 done_by->AddThreat(me, -(3*(float)damage)/4); // do not let maiev tank him
554 }
555
556 void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
557 {
558 if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades!
559 {
560 if (!me->GetUInt32Value(UNIT_FIELD_VIRTUAL_ITEM_ID))
562 else
565 }
566 }
567
569 {
570 ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
571 for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
572 {
573 if ((*itr)->getUnitGuid() == TargetGUID)
574 {
575 (*itr)->removeReference();
576 break;
577 }
578 }
579 }
580
581 void Talk(uint32 count)
582 {
583 Timer[EVENT_TALK_SEQUENCE] = Conversation[count].timer;
584
585 Creature* creature = NULL;
586 if (Conversation[count].creature == ILLIDAN_STORMRAGE)
587 creature = me;
588 else if (Conversation[count].creature == AKAMA)
589 creature = (Unit::GetCreature((*me), AkamaGUID));
590 else if (Conversation[count].creature == MAIEV_SHADOWSONG)
591 creature = (Unit::GetCreature((*me), MaievGUID));
592
593 if (creature)
594 {
595 if (Conversation[count].emote)
596 creature->HandleEmoteCommand(Conversation[count].emote); // Make the Creature do some animation!
597 if (Conversation[count].text.size())
598 creature->MonsterYell(Conversation[count].text.c_str(), Language::LANG_UNIVERSAL, 0); // Have the Creature yell out some text
599 if (Conversation[count].sound)
600 DoPlaySoundToSet(creature, Conversation[count].sound); // Play some sound on the creature
601 }
602 }
603
604 void EnterPhase(PhaseIllidan NextPhase)
605 {
607
608 switch (NextPhase)
609 {
610 case PHASE_NORMAL:
611 case PHASE_NORMAL_2:
613 AttackStart(me->GetVictim());
614 Timer[EVENT_TAUNT] = 32000;
615 Timer[EVENT_SHEAR] = std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS);
616 Timer[EVENT_FLAME_CRASH] = 20000;
619 Timer[EVENT_DRAW_SOUL] = 30000;
620 if (NextPhase == PHASE_NORMAL)
621 break;
624 if (NextPhase == PHASE_NORMAL_2)
625 break;
626 Timer[EVENT_ENRAGE] = std::rand() % (50 * IN_MILLISECONDS) + (30 * IN_MILLISECONDS);
627 break;
628 case PHASE_FLIGHT:
629 Timer[EVENT_FIREBALL] = 1000;
630 if (!(rand()%4))
631 Timer[EVENT_DARK_BARRAGE] = 10000;
632 Timer[EVENT_EYE_BLAST] = std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS);
633 Timer[EVENT_MOVE_POINT] = std::rand() % (40 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS);
634 break;
635 case PHASE_DEMON:
637 Timer[EVENT_FLAME_BURST] = 10000;
638 Timer[EVENT_SHADOWDEMON] = 30000;
640 AttackStart(me->GetVictim());
641 break;
644 me->RemoveAllAuras();
645 me->InterruptNonMeleeSpells(false);
647 me->GetMotionMaster()->Clear(false);
648 me->AttackStop();
649 break;
651 if (Phase == PHASE_NORMAL) // lift off
652 {
653 FlightCount = 1;
655 me->RemoveAllAuras();
656 me->InterruptNonMeleeSpells(false);
658 me->GetMotionMaster()->Clear(false);
659 me->AttackStop();
660 }
661 else // land
663 break;
665 if (Phase == PHASE_DEMON)
667 else
668 {
669 TransformCount = 0;
672 }
673 me->GetMotionMaster()->Clear();
674 me->AttackStop();
675 break;
676 default:
677 break;
678 }
679 if (MaievGUID)
680 {
682 if (maiev->IsAlive())
683 maiev->AI()->DoAction(NextPhase);
684 }
685 Phase = NextPhase;
687 }
688
690 {
691 me->InterruptNonMeleeSpells(false);
692
694
695 float distx, disty, dist[2];
696 for (uint8 i = 0; i < 2; ++i)
697 {
698 distx = EyeBlast[i].x - HoverPosition[HoverPoint].x;
699 disty = EyeBlast[i].y - HoverPosition[HoverPoint].y;
700 dist[i] = distx * distx + disty * disty;
701 }
702 Locations initial = EyeBlast[dist[0] < dist[1] ? 0 : 1];
703 for (uint8 i = 0; i < 2; ++i)
704 {
705 distx = GlaivePosition[i].x - HoverPosition[HoverPoint].x;
706 disty = GlaivePosition[i].y - HoverPosition[HoverPoint].y;
707 dist[i] = distx * distx + disty * disty;
708 }
709 Locations final = GlaivePosition[dist[0] < dist[1] ? 0 : 1];
710
711 final.x = 2 * final.x - initial.x;
712 final.y = 2 * final.y - initial.y;
713
714 Creature* Trigger = me->SummonCreature(23069, initial.x, initial.y, initial.z, 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 13000);
715 if (!Trigger)
716 return;
717
718 Trigger->SetSpeed(MOVE_WALK, 3);
719 Trigger->SetWalk(true);
720 Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z);
721
722 // Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
723 me->SetTarget(Trigger->GetGUID());
724 DoCast(Trigger, SPELL_EYE_BLAST);
725 }
726
728 {
730
731 for (uint8 i = 0; i < 2; ++i)
732 {
734 {
736 {
737 flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction
738 flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE);
739 FlameGUID[i] = flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase
740 CAST_AI(npc_flame_of_azzinoth::flame_of_azzinothAI, flame->AI())->SetGlaiveGUID(GlaiveGUID[i]);
741 glaive->CastSpell(flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it.
742 }
743 }
744 }
745 }
746
748 {
751 if (!MaievGUID) // If Maiev cannot be summoned, reset the encounter and post some errors to the console.
752 {
754 me->MonsterTextEmote(EMOTE_UNABLE_TO_SUMMON, 0);
755 SF_LOG_ERROR("scripts", "SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)");
756 }
757 }
758
759 void HandleTalkSequence();
760
762 {
763 switch (FlightCount)
764 {
765 case 1: // lift off
766 me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
767 me->SetDisableGravity(true);
768 me->StopMoving();
771 break;
772 case 2: // move to center
773 me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); // +5, for SPELL_THROW_GLAIVE bug
775 break;
776 case 3: // throw one glaive
777 {
778 uint8 i=1;
780 if (Glaive)
781 {
782 GlaiveGUID[i] = Glaive->GetGUID();
785 Glaive->setFaction(me->getFaction());
787 }
788 }
790 break;
791 case 4: // throw another
793 {
794 uint8 i=0;
796 if (Glaive)
797 {
798 GlaiveGUID[i] = Glaive->GetGUID();
801 Glaive->setFaction(me->getFaction());
802 DoCast(Glaive, SPELL_THROW_GLAIVE, true);
803 }
804 }
806 break;
807 case 5: // summon flames
810 break;
811 case 6: // fly to hover point
812 me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
814 break;
815 case 7: // return to center
816 me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z);
818 break;
819 case 8: // glaive return
820 for (uint8 i = 0; i < 2; ++i)
821 {
822 if (GlaiveGUID[i])
823 {
824 Unit* Glaive = Unit::GetUnit(*me, GlaiveGUID[i]);
825 if (Glaive)
826 {
827 Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us
828 Glaive->SetDisplayId(MODEL_INVISIBLE); // disappear but not die for now
829 }
830 }
831 }
833 break;
834 case 9: // land
835 me->SetDisableGravity(false);
836 me->StopMoving();
837 me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
838 for (uint8 i = 0; i < 2; ++i)
839 {
840 if (GlaiveGUID[i])
841 {
843 glaive->DespawnOrUnsummon();
844
845 GlaiveGUID[i] = 0;
846 }
847 }
849 break;
850 case 10: // attack
855 break;
856 default:
857 break;
858 }
859 ++FlightCount;
860 }
861
863 {
865 me->RemoveAurasDueToSpell(DemonTransformation[TransformCount].unaura);
866
869
870 if (DemonTransformation[TransformCount].displayid)
871 me->SetDisplayId(DemonTransformation[TransformCount].displayid); // It's morphin time!
872
874 {
875 // Requip warglaives if needed
878 }
879 else
880 {
881 // Unequip warglaives if needed
883 }
884
885 switch (TransformCount)
886 {
887 case 2:
889 break;
890 case 4:
892 break;
893 case 7:
895 break;
896 case 9:
897 if (MaievGUID)
898 EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3
899 else
901 break;
902 default:
903 break;
904 }
908 }
909
911 {
913 return;
914
916 for (int32 i = 1; i <= MaxTimer[Phase]; ++i)
917 {
918 if (Timer[i]) // Event is enabled
919 {
920 if (Timer[i] <= diff)
921 {
922 if (!Event) // No event with higher priority
923 Event = (EventIllidan)i;
924 }
925 else Timer[i] -= diff;
926 }
927 }
928
929 switch (Phase)
930 {
931 case PHASE_NORMAL:
932 if (HealthBelowPct(65))
934 break;
935
936 case PHASE_NORMAL_2:
937 if (HealthBelowPct(30))
939 break;
940
942 if (HealthBelowPct(1))
944 break;
945
949 break;
950
954 break;
955
959 break;
960 default:
961 break;
962 }
963
964 if (me->IsNonMeleeSpellCasted(false))
965 return;
966
967 if (Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || (Phase == PHASE_NORMAL_MAIEV && !me->HasAura(SPELL_CAGED)))
968 {
969 switch (Event)
970 {
971 // PHASE_NORMAL
972 case EVENT_BERSERK:
974 DoCast(me, SPELL_BERSERK, true);
975 Timer[EVENT_BERSERK] = 5000; // The buff actually lasts forever.
976 break;
977
978 case EVENT_TAUNT:
980 Timer[EVENT_TAUNT] = std::rand() % 35000 + 25000;
981 break;
982
983 case EVENT_SHEAR:
984 // no longer exists in 3.0f.2
985 // DoCastVictim(SPELL_SHEAR);
986 Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000);
987 break;
988
991 Timer[EVENT_FLAME_CRASH] = std::rand() % 40000 + 30000;
992 break;
993
995 {
996 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true))
997 DoCast(target, SPELL_PARASITIC_SHADOWFIEND, true);
998 Timer[EVENT_PARASITIC_SHADOWFIEND] = std::rand() % 45000 + 35000;
999 }
1000 break;
1001
1004 break;
1005
1006 case EVENT_DRAW_SOUL:
1008 Timer[EVENT_DRAW_SOUL] = std::rand() % 60000 + 50000;
1009 break;
1010
1011 // PHASE_NORMAL_2
1015 break;
1016
1019 break;
1020
1021 // PHASE_NORMAL_MAIEV
1022 case EVENT_ENRAGE:
1024 Timer[EVENT_ENRAGE] = 0;
1025 break;
1026
1027 default:
1028 break;
1029 }
1031 }
1032
1033 if (Phase == PHASE_FLIGHT)
1034 {
1035 switch (Event)
1036 {
1037 case EVENT_FIREBALL:
1039 Timer[EVENT_FIREBALL] = 3000;
1040 break;
1041
1042 case EVENT_DARK_BARRAGE:
1045 break;
1046
1047 case EVENT_EYE_BLAST:
1048 CastEyeBlast();
1050 break;
1051
1052 case EVENT_MOVE_POINT:
1054 Timer[EVENT_FLIGHT_SEQUENCE] = 0; // do not start Event when changing hover point
1055 HoverPoint += (rand()%3 + 1);
1056 if (HoverPoint > 3)
1057 HoverPoint -= 4;
1058 me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
1059 break;
1060
1061 default:
1062 break;
1063 }
1064 }
1065
1066 if (Phase == PHASE_DEMON)
1067 {
1068 switch (Event)
1069 {
1070 case EVENT_SHADOW_BLAST:
1071 me->GetMotionMaster()->Clear(false);
1072 if (me->GetVictim() && (!me->IsWithinDistInMap(me->GetVictim(), 50) || !me->IsWithinLOSInMap(me->GetVictim())))
1073 me->GetMotionMaster()->MoveChase(me->GetVictim(), 30);
1074 else
1075 me->GetMotionMaster()->MoveIdle();
1077 Timer[EVENT_SHADOW_BLAST] = 4000;
1078 break;
1079 case EVENT_SHADOWDEMON:
1082 Timer[EVENT_FLAME_BURST] += 10000;
1083 break;
1084 case EVENT_FLAME_BURST:
1086 Timer[EVENT_FLAME_BURST] = 15000;
1087 break;
1090 break;
1091 default:
1092 break;
1093 }
1094 }
1095 }
1096
1097 public:
1101 private:
1112 };
1113
1115 {
1116 return new boss_illidan_stormrageAI(creature);
1117 }
1118};
1119
1120/********************************** End of Illidan AI* *****************************************/
1121
1122/******* Functions and vars for Akama's AI* *****/
1124{
1125public:
1126 boss_maiev_shadowsong() : CreatureScript("boss_maiev_shadowsong") { }
1127
1128 struct boss_maievAI : public ScriptedAI
1129 {
1130 boss_maievAI(Creature* creature) : ScriptedAI(creature) { };
1131
1133 {
1134 MaxTimer = 0;
1136 IllidanGUID = 0;
1138 Timer[EVENT_MAIEV_TAUNT] = std::rand() % (43 * IN_MILLISECONDS) + (22 * IN_MILLISECONDS);
1141 me->SetUInt32Value(UNIT_FIELD_VIRTUAL_ITEM_ID + 2, 45738);
1142 }
1143
1144 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1146
1148
1150 {
1151 IllidanGUID = guid;
1152 }
1153
1154 void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
1155 {
1156 if (done_by->GetGUID() != IllidanGUID)
1157 damage = 0;
1158 else
1159 {
1161 if (illidan->GetVictim() == me)
1162 damage = me->CountPctFromMaxHealth(10);
1163
1164 if (damage >= me->GetHealth())
1165 damage = 0;
1166 }
1167 }
1168
1170 {
1171 if (!who || Timer[EVENT_MAIEV_STEALTH])
1172 return;
1173
1175 AttackStartNoMove(who);
1177 {
1179 if (me->IsWithinDistInMap(illidan, 25))
1180 BlinkToPlayer(); // Do not let dread aura hurt her.
1181 AttackStartNoMove(who);
1182 }
1183 else
1185 }
1186
1188 {
1189 if (param > PHASE_ILLIDAN_NULL && param < PHASE_ILLIDAN_MAX)
1190 EnterPhase(PhaseIllidan(param));
1191 }
1192
1193 void EnterPhase(PhaseIllidan NextPhase) // This is in fact Illidan's phase.
1194 {
1195 switch (NextPhase)
1196 {
1199 {
1200 me->SetFullHealth();
1201 me->SetVisible(true);
1203 }
1204 me->InterruptNonMeleeSpells(false);
1205 me->GetMotionMaster()->Clear(false);
1206 me->AttackStop();
1207 me->SetTarget(IllidanGUID);
1208 MaxTimer = 0;
1209 break;
1211 MaxTimer = 4;
1212 Timer[EVENT_MAIEV_TAUNT] += 10000;
1214 break;
1215 case PHASE_DEMON:
1216 break;
1217 case PHASE_NORMAL_MAIEV:
1218 MaxTimer = 4;
1219 Timer[EVENT_MAIEV_TAUNT] += 10000;
1220 Timer[EVENT_MAIEV_TRAP] = 22000;
1221 break;
1222 default:
1223 break;
1224 }
1226 MaxTimer = 1;
1227 Phase = NextPhase;
1228 }
1229
1230 void BlinkTo(float x, float y, float z)
1231 {
1232 me->AttackStop();
1233 me->InterruptNonMeleeSpells(false);
1234 me->GetMotionMaster()->Clear(false);
1235 DoTeleportTo(x, y, z);
1237 }
1238
1240 {
1242 {
1243 Unit* target = illidan->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0);
1244
1245 if (!target || !me->IsWithinDistInMap(target, 80) || illidan->IsWithinDistInMap(target, 20))
1246 {
1247 uint8 pos = rand()%4;
1248 BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z);
1249 }
1250 else
1251 {
1252 float x, y, z;
1253 target->GetPosition(x, y, z);
1254 BlinkTo(x, y, z);
1255 }
1256 }
1257 }
1258
1260 {
1261 if ((!UpdateVictim())
1263 return;
1264
1266 for (uint8 i = 1; i <= MaxTimer; ++i)
1267 if (Timer[i])
1268 {
1269 if (Timer[i] <= diff)
1270 Event = (EventMaiev)i;
1271 else Timer[i] -= diff;
1272 }
1273
1274 switch (Event)
1275 {
1277 {
1278 me->SetFullHealth();
1279 me->SetVisible(true);
1282 BlinkToPlayer();
1284 }
1285 break;
1286 case EVENT_MAIEV_TAUNT:
1288 Timer[EVENT_MAIEV_TAUNT] = std::rand() % (43 * IN_MILLISECONDS) + (22 * IN_MILLISECONDS);
1289 break;
1293 break;
1294 case EVENT_MAIEV_TRAP:
1296 {
1297 BlinkToPlayer();
1299 Timer[EVENT_MAIEV_TRAP] = 22000;
1300 }
1301 else
1302 {
1303 if (!me->IsWithinDistInMap(me->GetVictim(), 40))
1304 me->GetMotionMaster()->MoveChase(me->GetVictim(), 30);
1307 }
1308 break;
1309 default:
1310 break;
1311 }
1312
1313 if (HealthBelowPct(50))
1314 {
1315 me->SetVisible(false);
1318 CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID());
1319 me->AttackStop();
1320 Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute
1321 MaxTimer = 1;
1322 }
1323
1326 }
1327
1328 private:
1334 };
1335
1337 {
1338 return new boss_maievAI(creature);
1339 }
1340};
1341
1343{
1344public:
1345 npc_akama_illidan() : CreatureScript("npc_akama_illidan") { }
1346
1348 {
1350 {
1351 instance = creature->GetInstanceScript();
1352 JustCreated = true;
1353 }
1354
1356 {
1357 WalkCount = 0;
1358 if (instance)
1359 {
1361
1364 DoorGUID[0] = instance->GetData64(DATA_GO_ILLIDAN_DOOR_R);
1365 DoorGUID[1] = instance->GetData64(DATA_GO_ILLIDAN_DOOR_L);
1366
1367 if (JustCreated) // close all doors at create
1368 {
1369 instance->HandleGameObject(GateGUID, false);
1370
1371 for (uint8 i = 0; i < 2; ++i)
1372 instance->HandleGameObject(DoorGUID[i], false);
1373 }
1374 else // open all doors, raid wiped
1375 {
1376 instance->HandleGameObject(GateGUID, true);
1377 WalkCount = 1; // skip first wp
1378
1379 for (uint8 i = 0; i < 2; ++i)
1380 instance->HandleGameObject(DoorGUID[i], true);
1381 }
1382 }
1383 else
1384 {
1385 IllidanGUID = 0;
1386 GateGUID = 0;
1387 DoorGUID[0] = 0;
1388 DoorGUID[1] = 0;
1389 }
1390
1391 ChannelGUID = 0;
1392 SpiritGUID[0] = 0;
1393 SpiritGUID[1] = 0;
1394
1396 Timer = 0;
1397
1398 ChannelCount = 0;
1399 TalkCount = 0;
1400 Check_Timer = 5000;
1401
1402 KillAllElites();
1403
1404 me->SetUInt32Value(UNIT_FIELD_NPC_FLAGS, 0); // Database sometimes has strange values..
1406 me->setActive(false);
1407 me->SetVisible(false);
1408 }
1409
1410 // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit
1412 {
1413 me->RemoveAllAuras();
1414 me->DeleteThreatList();
1415 me->CombatStop(true);
1416 }
1417
1418 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1420
1421
1422 void MovementInform(uint32 MovementType, uint32 /*Data*/) OVERRIDE
1423 {
1424 if (MovementType == POINT_MOTION_TYPE)
1425 Timer = 1;
1426 }
1427
1428 void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
1429 {
1430 if (damage > me->GetHealth() || done_by->GetGUID() != IllidanGUID)
1431 damage = 0;
1432 }
1433
1435 {
1436 ThreatContainer::StorageType const &threatList = me->getThreatManager().getThreatList();
1437 std::vector<Unit*> eliteList;
1438 for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
1439 {
1440 Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid());
1441 if (unit && unit->GetEntry() == ILLIDARI_ELITE)
1442 eliteList.push_back(unit);
1443 }
1444 for (std::vector<Unit*>::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr)
1445 (*itr)->setDeathState(DeathState::JUST_DIED);
1447 }
1448
1450 {
1451 if (!instance)
1452 return;
1453
1455 for (uint8 i = 0; i < 2; ++i)
1456 instance->HandleGameObject(DoorGUID[i], false);
1458 {
1459 illidan->RemoveAurasDueToSpell(SPELL_KNEEL);
1460 me->SetInFront(illidan);
1461 illidan->SetInFront(me);
1462 me->GetMotionMaster()->MoveIdle();
1463 illidan->GetMotionMaster()->MoveIdle();
1464 CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->AkamaGUID = me->GetGUID();
1466 }
1467 }
1468
1470 {
1471 me->setActive(true);
1473 if (!JustCreated)
1474 return;
1475 float x, y, z;
1477 gate->GetPosition(x, y, z);
1478 else
1479 return; // if door not spawned, don't crash server
1480
1481 if (Creature* Channel = me->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TempSummonType::TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000))
1482 {
1483 ChannelGUID = Channel->GetGUID();
1484 Channel->SetDisplayId(MODEL_INVISIBLE); // Invisible but spell visuals can still be seen.
1486 }
1487
1488 for (uint8 i = 0; i < 2; ++i)
1489 if (Creature* Spirit = me->SummonCreature(i ? SPIRIT_OF_OLUM : SPIRIT_OF_UDALO, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 20000))
1490 {
1491 Spirit->SetVisible(false);
1492 SpiritGUID[i] = Spirit->GetGUID();
1493 }
1494 }
1495
1497 {
1498 me->SetWalk(false);
1499 me->SetSpeed(MOVE_RUN, 1.0f);
1500 me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z);
1501 }
1502
1503 void EnterPhase(PhaseAkama NextPhase)
1504 {
1505 if (!instance)
1506 return;
1507 switch (NextPhase)
1508 {
1509 case PHASE_CHANNEL:
1510 BeginChannel();
1511 Timer = 5000;
1512 ChannelCount = 0;
1513 break;
1514 case PHASE_WALK:
1515 if (Phase == PHASE_CHANNEL)
1516 WalkCount = 0;
1517 else if (Phase == PHASE_TALK)
1518 {
1520 CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID());
1523 ++WalkCount;
1524 }
1525 JustCreated = false;
1526 BeginWalk();
1527 Timer = 0;
1528 break;
1529 case PHASE_TALK:
1530 if (Phase == PHASE_WALK)
1531 {
1532 BeginTalk();
1533 Timer = 0;
1534 }
1535 else if (Phase == PHASE_FIGHT_ILLIDAN)
1536 {
1537 Timer = 1;
1538 TalkCount = 0;
1539 }
1540 break;
1543 {
1544 me->AddThreat(illidan, 10000000.0f);
1545 me->GetMotionMaster()->MoveChase(illidan);
1546 }
1547 Timer = 30000; // chain lightning
1548 break;
1551 Timer = std::rand() % 16000 + 10000; // summon minion
1552 break;
1553 case PHASE_RETURN:
1555 KillAllElites();
1556 WalkCount = 0;
1557 BeginWalk();
1558 Timer = 1;
1559 break;
1560 default:
1561 break;
1562 }
1563 Phase = NextPhase;
1564 Event = false;
1565 }
1566
1568 {
1569 switch (TalkCount)
1570 {
1571 case 0:
1573 {
1575 illidan->AI()->Talk(SAY_ILLIDAN_MINION);
1576 }
1577 Timer = 8000;
1578 break;
1579 case 1:
1581 Timer = 3000;
1582 break;
1583 case 2:
1585 break;
1586 }
1587 ++TalkCount;
1588 }
1589
1591 {
1592 Unit* Channel = NULL;
1593 Unit* Spirit[2] = { NULL, NULL };
1594 if (ChannelCount <= 5)
1595 {
1597 Spirit[0] = Unit::GetUnit(*me, SpiritGUID[0]);
1598 Spirit[1] = Unit::GetUnit(*me, SpiritGUID[1]);
1599 if (!Channel || !Spirit[0] || !Spirit[1])
1600 return;
1601 }
1602
1603 switch (ChannelCount)
1604 {
1605 case 0: // channel failed
1606 me->InterruptNonMeleeSpells(true);
1607 Timer = 2000;
1608 break;
1609 case 1: // spirit appear
1610 Spirit[0]->SetVisible(true);
1611 Spirit[1]->SetVisible(true);
1612 Timer = 2000;
1613 break;
1614 case 2: // spirit help
1618 Timer = 5000;
1619 break;
1620 case 3: // open the gate
1621 me->InterruptNonMeleeSpells(true);
1622 Spirit[0]->InterruptNonMeleeSpells(true);
1623 Spirit[1]->InterruptNonMeleeSpells(true);
1624 if (instance)
1625 instance->HandleGameObject(GateGUID, true);
1626 Timer = 2000;
1627 break;
1628 case 4:
1629 me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
1630 Timer = 2000;
1631 break;
1632 case 5:
1634 Channel->setDeathState(DeathState::JUST_DIED);
1635 Spirit[0]->SetVisible(false);
1636 Spirit[1]->SetVisible(false);
1637 Timer = 3000;
1638 break;
1639 case 6:
1641 break;
1642 default:
1643 break;
1644 }
1645 ++ChannelCount;
1646 }
1647
1649 {
1650 switch (WalkCount)
1651 {
1652 case 6:
1653 for (uint8 i = 0; i < 2; ++i)
1654 if (instance)
1655 instance->HandleGameObject(DoorGUID[i], true);
1656 break;
1657 case 8:
1658 if (Phase == PHASE_WALK)
1660 else
1662 break;
1663 case 12:
1665 break;
1666 }
1667
1668 if (Phase == PHASE_WALK)
1669 {
1670 Timer = 0;
1671 ++WalkCount;
1672 me->GetMotionMaster()->MovePoint(WalkCount, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z);
1673 }
1674 }
1675
1677 {
1678 if (!me->IsVisible())
1679 {
1680 if (Check_Timer <= diff)
1681 {
1682 if (instance && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE)
1683 me->SetVisible(true);
1684
1685 Check_Timer = 5000;
1686 } else Check_Timer -= diff;
1687 }
1688 Event = false;
1689 if (Timer)
1690 {
1691 if (Timer <= diff)
1692 Event = true;
1693 else Timer -= diff;
1694 }
1695
1696 if (Event)
1697 {
1698 switch (Phase)
1699 {
1700 case PHASE_CHANNEL:
1701 if (JustCreated)
1703 else{
1705 }
1706 break;
1707 case PHASE_TALK:
1709 break;
1710 case PHASE_WALK:
1711 case PHASE_RETURN:
1713 break;
1715 {
1717 if (illidan && illidan->HealthBelowPct(90))
1719 else
1720 {
1722 Timer = 30000;
1723 }
1724 }
1725 break;
1727 {
1728 float x, y, z;
1729 me->GetPosition(x, y, z);
1730 Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TempSummonType::TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000);
1731 // Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000);
1732 if (Elite)
1733 {
1734 Elite->AI()->AttackStart(me);
1735 Elite->AddThreat(me, 1000000.0f);
1736 AttackStart(Elite);
1737 me->AddThreat(Elite, 1000000.0f);
1738 }
1739 Timer = std::rand() % 16000 + 10000;
1741 if (illidan->HealthBelowPct(10))
1743 }
1744 break;
1745 default:
1746 break;
1747 }
1748 }
1749
1750 if (!UpdateVictim())
1751 return;
1752
1753 if (HealthBelowPct(20))
1755
1757 }
1758
1759 void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
1760 {
1761 player->CLOSE_GOSSIP_MENU();
1763 }
1764
1765 private:
1769 bool Event;
1780 };
1781
1783 {
1784 return new npc_akama_illidanAI(creature);
1785 }
1786};
1787
1789{
1790 if (instance)
1792
1794 {
1795 if (!akama->IsAlive())
1796 akama->Respawn();
1797 else
1798 akama->AI()->EnterEvadeMode();
1799 }
1800
1801 MaievGUID = 0;
1802 for (uint8 i = 0; i < 2; ++i)
1803 {
1804 FlameGUID[i] = 0;
1805 GlaiveGUID[i] = 0;
1806 }
1807
1809 Event = EVENT_NULL;
1810 Timer[EVENT_BERSERK] = 1500000;
1811
1812 HoverPoint = 0;
1813 TalkCount = 0;
1814 FlightCount = 0;
1815 TransformCount = 0;
1816
1817 me->SetDisplayId(MODEL_ILLIDAN);
1822 me->SetDisableGravity(false);
1823 me->setActive(false);
1824 Summons.DespawnAll();
1825}
1826
1828{
1829 Summons.Summon(summon);
1830 switch (summon->GetEntry())
1831 {
1833 {
1835 {
1836 summon->SetVisible(false);
1838 return;
1839 }
1840 Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true);
1841 if (!target || target->HasAura(SPELL_PARASITIC_SHADOWFIEND)
1843 target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true);
1844 if (target)
1845 summon->AI()->AttackStart(target);
1846 }
1847 break;
1848 case SHADOW_DEMON:
1849 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players.
1850 {
1851 summon->AddThreat(target, 5000000.0f);
1852 summon->AI()->AttackStart(target);
1853 }
1854 break;
1855 case MAIEV_SHADOWSONG:
1856 {
1857 summon->SetVisible(false); // Leave her invisible until she has to talk
1859 MaievGUID = summon->GetGUID();
1860 CAST_AI(boss_maiev_shadowsong::boss_maievAI, summon->AI())->GetIllidanGUID(me->GetGUID());
1861 summon->AI()->DoAction(PHASE_TALK_SEQUENCE);
1862 }
1863 break;
1864 case FLAME_OF_AZZINOTH:
1865 {
1866 summon->AI()->AttackStart(summon->SelectNearestTarget(999));
1867 }
1868 break;
1869 default:
1870 break;
1871 }
1872}
1873
1875{
1876 switch (TalkCount)
1877 {
1878 case 0:
1880 break;
1881 case 8:
1882 // Equip our warglaives!
1885 me->SetWalk(false);
1886 break;
1887 case 9:
1889 {
1891 me->AddThreat(akama, 100.0f);
1894 }
1895 break;
1896 case 10:
1897 SummonMaiev();
1898 break;
1899 case 11:
1901 {
1902 maiev->SetVisible(true); // Maiev is now visible
1903 maiev->CastSpell(maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported!
1904 maiev->SetInFront(me); // Have her face us
1905 me->SetInFront(maiev); // Face her, so it's not rude =P
1906 maiev->GetMotionMaster()->MoveIdle();
1907 me->GetMotionMaster()->MoveIdle();
1908 }
1909 break;
1910 case 14:
1912 {
1915 maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE
1916 maiev->AI()->AttackStart(me); // Force Maiev to attack us.
1918 }
1919 break;
1920 case 15:
1921 DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him
1922 Summons.DespawnAll();
1923 break;
1924 case 17:
1926 {
1927 if (!me->IsWithinDistInMap(akama, 15))
1928 {
1929 float x, y, z;
1930 me->GetPosition(x, y, z);
1931 x += 10; y += 10;
1932 akama->GetMotionMaster()->Clear(false);
1933 // Akama->GetMotionMaster()->MoveIdle();
1934 akama->SetPosition(x, y, z, 0.0f);
1935 akama->MonsterMoveWithSpeed(x, y, z, 0); // Illidan must not die until Akama arrives.
1936 akama->GetMotionMaster()->MoveChase(me);
1937 }
1938 }
1939 break;
1940 case 19: // Make Maiev leave
1942 {
1943 maiev->CastSpell(maiev, SPELL_TELEPORT_VISUAL, true);
1944 maiev->setDeathState(DeathState::JUST_DIED);
1946 }
1947 break;
1948 case 21: // Kill ourself.
1949 me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
1950 break;
1951 default:
1952 break;
1953 }
1955 Talk(TalkCount); // This function does most of the talking
1956 ++TalkCount;
1957}
1958
1960{
1961public:
1962 npc_cage_trap_trigger() : CreatureScript("npc_cage_trap_trigger") { }
1963
1965 {
1966 cage_trap_triggerAI(Creature* creature) : ScriptedAI(creature) { }
1967
1969 {
1970 IllidanGUID = 0;
1971
1972 Active = false;
1973 SummonedBeams = false;
1974
1975 DespawnTimer = 0;
1976
1978 }
1979
1980 void EnterCombat(Unit* /*who*/)OVERRIDE { }
1981
1983
1984 {
1985 if (!Active)
1986 return;
1987
1988 if (who && (who->GetTypeId() != TypeID::TYPEID_PLAYER))
1989 {
1990 if (who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan
1991 {
1992 if (!IllidanGUID && me->IsWithinDistInMap(who, 3) && (!who->HasAura(SPELL_CAGED)))
1993 {
1994 IllidanGUID = who->GetGUID();
1995 who->CastSpell(who, SPELL_CAGED, true);
1996 DespawnTimer = 5000;
1997 if (who->HasAura(SPELL_ENRAGE))
1998 who->RemoveAurasDueToSpell(SPELL_ENRAGE); // Dispel his enrage
1999 // if (GameObject* CageTrap = instance->instance->GetGameObject(instance->GetData64(CageTrapGUID)))
2000
2001 // CageTrap->SetLootState(GO_JUST_DEACTIVATED);
2002 }
2003 }
2004 }
2005 }
2006
2008 {
2009 if (DespawnTimer)
2010 {
2011 if (DespawnTimer <= diff)
2012 me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2013 else DespawnTimer -= diff;
2014 }
2015
2016 // if (IllidanGUID && !SummonedBeams)
2017 // {
2018 // if (Unit* Illidan = Unit::GetUnit(*me, IllidanGUID)
2019 // {
2020 // /// @todo Find proper spells and properly apply 'caged' Illidan effect
2021 // }
2022 // }
2023 }
2024
2025 public:
2027 private:
2031 };
2032
2034 {
2035 return new cage_trap_triggerAI(creature);
2036 }
2037};
2038
2040{
2041public:
2042 gameobject_cage_trap() : GameObjectScript("gameobject_cage_trap") { }
2043
2045 {
2046 float x, y, z;
2047 player->GetPosition(x, y, z);
2048
2049 // Grid search for nearest live Creature of entry 23304 within 10 yards
2050 if (Creature* pTrigger = go->FindNearestCreature(23304, 10.0f))
2051 CAST_AI(npc_cage_trap_trigger::cage_trap_triggerAI, pTrigger->AI())->Active = true;
2052 go->SetGoState(GOState::GO_STATE_ACTIVE);
2053 return true;
2054 }
2055};
2056
2058{
2059public:
2060 npc_shadow_demon() : CreatureScript("npc_shadow_demon") { }
2061
2063 {
2064 shadow_demonAI(Creature* creature) : ScriptedAI(creature) { }
2065
2067 {
2069 }
2070
2072 {
2073 TargetGUID = 0;
2075 }
2076
2077 void JustDied(Unit* /*killer*/) OVERRIDE
2078 {
2079 if (Unit* target = Unit::GetUnit(*me, TargetGUID))
2080 target->RemoveAurasDueToSpell(SPELL_PARALYZE);
2081 }
2082
2083 void UpdateAI(uint32 /*diff*/) OVERRIDE
2084 {
2085 if (!UpdateVictim())
2086 return;
2087
2088 if (me->GetVictim()->GetTypeId() != TypeID::TYPEID_PLAYER)
2089 return; // Only cast the below on players.
2090
2091 if (!me->GetVictim()->HasAura(SPELL_PARALYZE))
2092 {
2093 TargetGUID = me->GetVictim()->GetGUID();
2094 me->AddThreat(me->GetVictim(), 10000000.0f);
2097 }
2098 // Kill our target if we're very close.
2099 if (me->IsWithinDistInMap(me->GetVictim(), 3))
2101 }
2102
2103 private:
2105 };
2106
2108 {
2109 return new shadow_demonAI(creature);
2110 }
2111};
2112
2114{
2115public:
2116 npc_blade_of_azzinoth() : CreatureScript("npc_blade_of_azzinoth") { }
2117
2119 {
2121
2122 void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
2123 {
2124 if (spell->Id == SPELL_THROW_GLAIVE2 || spell->Id == SPELL_THROW_GLAIVE)
2125 me->SetDisplayId(MODEL_BLADE);// appear when hit by Illidan's glaive
2126 }
2127 };
2128
2130 {
2131 return new blade_of_azzinothAI(creature);
2132 }
2133};
2134
2136{
2137public:
2138 npc_parasitic_shadowfiend() : CreatureScript("npc_parasitic_shadowfiend") { }
2139
2140 // Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap
2142 {
2144 {
2145 instance = creature->GetInstanceScript();
2146 }
2147
2149 {
2150 if (instance)
2152 else
2153 IllidanGUID = 0;
2154
2155 CheckTimer = 5000;
2157 }
2158
2160 {
2162 }
2163
2165 {
2166 if (me->isAttackReady() && me->IsWithinMeleeRange(me->GetVictim()))
2167 {
2168 if (!me->GetVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND)
2169 && !me->GetVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2))
2170 {
2171 if (Creature* illidan = Unit::GetCreature((*me), IllidanGUID))// summon only in 1. phase
2173 me->CastSpell(me->GetVictim(), SPELL_PARASITIC_SHADOWFIEND2, true, 0, 0, IllidanGUID); // do not stack
2174 }
2175 me->AttackerStateUpdate(me->GetVictim());
2176 me->resetAttackTimer();
2177 }
2178 }
2179
2181 {
2182 if (!me->GetVictim())
2183 {
2184 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true))
2185 AttackStart(target);
2186 else
2187 {
2188 me->DespawnOrUnsummon();
2189 return;
2190 }
2191 }
2192
2193 if (CheckTimer <= diff)
2194 {
2196 if (!illidan || illidan->IsInEvadeMode())
2197 {
2198 me->DespawnOrUnsummon();
2199 return;
2200 }
2201 else
2202 CheckTimer = 5000;
2203 }
2204 else
2205 CheckTimer -= diff;
2206
2208 }
2209
2210 private:
2214 };
2215
2217 {
2218 return new npc_parasitic_shadowfiendAI(creature);
2219 }
2220};
2221
@ IN_MILLISECONDS
Definition Common.h:125
@ EQUIP_UNEQUIP
Definition CreatureAI.h:50
@ EQUIP_NO_CHANGE
Definition CreatureAI.h:49
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ GO_STATE_ACTIVE
Definition GameObject.h:576
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ POINT_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_CORPSE_DESPAWN
Definition Object.h:72
@ TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN
Definition Object.h:69
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
Definition Object.h:68
@ TEMPSUMMON_CORPSE_TIMED_DESPAWN
Definition Object.h:73
#define CAST_AI(a, b)
@ EMOTE_ONESHOT_LAND
@ EMOTE_ONESHOT_SALUTE
@ EMOTE_ONESHOT_LIFTOFF
@ SPELL_SCHOOL_FIRE
@ SPELL_SCHOOL_MASK_NORMAL
@ UNIT_NPC_FLAG_GOSSIP
Definition Unit.h:687
@ JUST_DIED
Definition Unit.h:504
@ UNIT_STAND_STATE_DEAD
Definition Unit.h:169
@ SHEATH_STATE_MELEE
Definition Unit.h:246
@ MOVE_RUN
Definition Unit.h:556
@ MOVE_WALK
Definition Unit.h:555
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ DIRECT_DAMAGE
Definition Unit.h:614
@ SELECT_TARGET_FARTHEST
Definition UnitAI.h:27
@ SELECT_TARGET_TOPAGGRO
Definition UnitAI.h:24
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_VIRTUAL_ITEM_ID
@ UNIT_FIELD_SHAPESHIFT_FORM
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_ANIM_TIER
@ UNIT_FIELD_FLAGS
@ SPELL_ENRAGE
@ SPELL_CHARGE
@ EVENT_ENRAGE
@ DATA_ILLIDARI_COUNCIL
@ DATA_ILLIDAN_STORMRAGE
@ DATA_GO_ILLIDAN_DOOR_R
@ DATA_GO_ILLIDAN_DOOR_L
@ DATA_GO_ILLIDAN_GATE
@ SPELL_SHADOW_STRIKE
@ SPELL_PARALYZE
@ SPELL_FIREBALL
@ SPELL_CONSUME_SOUL
@ SPELL_DUAL_WIELD
@ SPELL_BLAZE_SUMMON
@ PHASE_FLIGHT
@ EVENT_FLIGHT_SEQUENCE
#define SPELL_BERSERK
#define EMOTE_UNABLE_TO_SUMMON
EventMaiev
@ EVENT_MAIEV_SHADOW_STRIKE
@ EVENT_MAIEV_NULL
@ EVENT_MAIEV_TRAP
@ EVENT_MAIEV_THROW_DAGGER
@ EVENT_MAIEV_STEALTH
@ EVENT_MAIEV_TAUNT
static const Locations AkamaWP[13]
CreatureEntryIllidan
@ MAIEV_SHADOWSONG
@ EMPTY
@ FLAME_CRASH
@ ILLIDAN_STORMRAGE
@ BLADE_OF_AZZINOTH
@ AKAMA
@ ILLIDAN_DOOR_TRIGGER
@ SHADOW_DEMON
@ FLAME_OF_AZZINOTH
@ DEMON_FIRE
@ CAGE_TRAP_TRIGGER
@ SPIRIT_OF_UDALO
@ SPIRIT_OF_OLUM
@ ILLIDARI_ELITE
@ PARASITIC_SHADOWFIEND
static const Locations EyeBlast[2]
@ MODEL_BLADE
@ MODEL_INVISIBLE
@ MODEL_ILLIDAN
@ FLAME_CHARGE_DISTANCE
@ EQUIP_ID_OFF_HAND
@ FLAME_ENRAGE_DISTANCE
@ EQUIP_ID_MAIN_HAND_MAIEV
@ EQUIP_ID_MAIN_HAND
static const Locations SpiritSpawns[2]
static const Yells Conversation[22]
@ SPELL_BLAZE_EFFECT
@ SPELL_FLAME_CRASH_EFFECT
@ SPELL_SHADOW_PRISON
@ SPELL_DRAW_SOUL
@ SPELL_SHEAR
@ SPELL_HEALING_POTION
@ SPELL_SHADOW_BLAST
@ SPELL_SHADOWFIEND_PASSIVE
@ SPELL_SUMMON_PARASITICS
@ SPELL_AGONIZING_FLAMES
@ SPELL_GLAIVE_RETURNS
@ SPELL_ENRAGE
@ SPELL_CONSUME_SOUL
@ SPELL_FLAME_CRASH
@ SPELL_CHARGE
@ SPELL_THROW_DAGGER
@ SPELL_KNEEL
@ SPELL_FAN_BLADES
@ SPELL_AZZINOTH_CHANNEL
@ SPELL_PURPLE_BEAM
@ SPELL_FLAME_BURST_EFFECT
@ SPELL_FLAME_BURST
@ SPELL_DUAL_WIELD
@ SPELL_DEATHSWORN_DOOR_CHANNEL
@ SPELL_AKAMA_DOOR_CHANNEL
@ SPELL_TELEPORT_VISUAL
@ SPELL_THROW_GLAIVE
@ SPELL_DARK_BARRAGE
@ SPELL_THROW_GLAIVE2
@ SPELL_SHADOW_STRIKE
@ SPELL_FIREBALL
@ SPELL_DEMON_FORM
@ SPELL_SHADOW_DEMON_PASSIVE
@ SPELL_DEMON_TRANSFORM_1
@ SPELL_BLAZE_SUMMON
@ SPELL_SUMMON_MAIEV
@ SPELL_FLAME_BLAST
@ SPELL_DEMON_TRANSFORM_2
@ SPELL_CAGE_TRAP_BEAM
@ SPELL_FLAME_ENRAGE
@ SPELL_EYE_BLAST_TRIGGER
@ SPELL_PARASITIC_SHADOWFIEND
@ SPELL_PARASITIC_SHADOWFIEND2
@ SPELL_PARALYZE
@ SPELL_CHAIN_LIGHTNING
@ SPELL_BERSERK
@ SPELL_CAGE_TRAP_DUMMY
@ SPELL_DEATH
@ SPELL_CAGE_TRAP_SUMMON
@ SPELL_AKAMA_DOOR_FAIL
@ SPELL_EYE_BLAST
@ SPELL_DEMON_FIRE
@ SPELL_CAGED
@ SPELL_SUMMON_SHADOWDEMON
@ SPELL_DEMON_TRANSFORM_3
#define CENTER_Y
PhaseIllidan
@ PHASE_TALK_SEQUENCE
@ PHASE_DEMON
@ PHASE_NORMAL_MAIEV
@ PHASE_ILLIDAN_NULL
@ PHASE_FLIGHT_SEQUENCE
@ PHASE_ILLIDAN_MAX
@ PHASE_FLIGHT
@ PHASE_NORMAL
@ PHASE_TRANSFORM_SEQUENCE
@ PHASE_NORMAL_2
static const Animation DemonTransformation[10]
@ EMOTE_AZZINOTH_GAZE
@ SAY_ILLIDAN_TAKEOFF
@ SAY_ILLIDAN_KILL
@ SAY_AKAMA_LEAVE
@ SAY_ILLIDAN_MINION
@ SAY_ILLIDAN_EYE_BLAST
@ SAY_ILLIDAN_SUMMONFLAMES
@ SAY_ILLIDAN_TAUNT
@ SAY_AKAMA_BEWARE
@ SAY_MAIEV_SHADOWSONG_TAUNT
@ SAY_ILLIDAN_MORPH
@ SAY_ILLIDAN_ENRAGE
static const Locations GlaivePosition[4]
PhaseAkama
@ PHASE_FIGHT_MINIONS
@ PHASE_TALK
@ PHASE_RETURN
@ PHASE_AKAMA_NULL
@ PHASE_WALK
@ PHASE_FIGHT_ILLIDAN
@ PHASE_CHANNEL
void AddSC_boss_illidan()
EventIllidan
@ EVENT_TRANSFORM_DEMON
@ EVENT_TRANSFORM_SEQUENCE
@ EVENT_SHADOW_BLAST
@ EVENT_FIREBALL
@ EVENT_SHADOWDEMON
@ EVENT_PARASITIC_SHADOWFIEND
@ EVENT_TALK_SEQUENCE
@ EVENT_TRANSFORM_NORMAL
@ EVENT_ENRAGE
@ EVENT_FLIGHT_SEQUENCE
@ EVENT_TAUNT
@ EVENT_SHEAR
@ EVENT_BERSERK
@ EVENT_AGONIZING_FLAMES
@ EVENT_EYE_BLAST
@ EVENT_DARK_BARRAGE
@ EVENT_DRAW_SOUL
@ EVENT_FLAME_BURST
@ EVENT_FLAME_CRASH
@ EVENT_PARASITE_CHECK
@ EVENT_MOVE_POINT
@ EVENT_NULL
#define CENTER_Z
static const EventIllidan MaxTimer[9]
static const Locations HoverPosition[4]
#define CENTER_X
@ PHASE_NORMAL
@ EVENT_BERSERK
@ EVENT_FIREBALL
@ SPELL_CHAIN_LIGHTNING
@ SPELL_TELEPORT_VISUAL
Definition chapter5.cpp:145
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:56
virtual void EnterEvadeMode()
void SetDisplayId(uint32 modelId) OVERRIDE
Unit * SelectNearestTarget(float dist=0, bool playerOnly=false) const
void setDeathState(DeathState s) OVERRIDE
bool IsInEvadeMode() const
Definition Creature.h:478
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
GameObjectScript(const char *name)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true)
NullCreatureAI(Creature *c)
Definition PassiveAI.cpp:12
static Creature * GetCreature(WorldObject const &u, uint64 guid)
static GameObject * GetGameObject(WorldObject const &u, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
uint32 GetEntry() const
Definition Object.h:125
std::list< HostileReference * > StorageType
virtual void DoAction(int32)
Definition UnitAI.h:126
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
Definition Unit.h:1367
void SetVisible(bool x)
Definition Unit.cpp:4163
void setFaction(uint32 faction)
Definition Unit.h:1699
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void AddThreat(Unit *victim, float fThreat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *threatSpell=NULL)
Definition Unit.cpp:4463
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:1433
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
bool HealthBelowPct(int32 pct) const
Definition Unit.h:1613
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
bool SetWalk(bool enable)
Definition Unit.cpp:9137
virtual void SetDisplayId(uint32 modelId)
Definition Unit.cpp:5941
void SetSpeed(UnitMoveType mtype, float rate, bool forced=false)
Definition Unit.cpp:4318
void HandleEmoteCommand(uint32 anim_id)
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2801
void MonsterYell(const char *text, Language language, WorldObject const *target)
Definition Object.cpp:2411
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipHello(Player *player, GameObject *go) 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
uint32 displayid
void GetPosition(float &x, float &y) const
Definition Object.h:333
void SetEquipmentSlots(bool loadDefault, int32 mainHand=EQUIP_NO_CHANGE, int32 offHand=EQUIP_NO_CHANGE, int32 ranged=EQUIP_NO_CHANGE)
Creature * me
void DoTeleportTo(float x, float y, float z, uint32 time=0)
bool HealthBelowPct(uint32 pct) const
void AttackStartNoMove(Unit *target)
ScriptedAI(Creature *creature)
void DoPlaySoundToSet(WorldObject *source, uint32 soundId)
void AttackStart(Unit *) OVERRIDE
uint32 emote
uint32 timer
uint32 sound
uint32 creature
std::string text
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *, const SpellInfo *spell) OVERRIDE
void SummonedCreatureDespawn(Creature *summon) OVERRIDE
void DamageTaken(Unit *done_by, uint32 &damage) OVERRIDE
void AttackStart(Unit *who) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void EnterPhase(PhaseIllidan NextPhase)
void DamageTaken(Unit *done_by, uint32 &damage) OVERRIDE
void DoAction(int32 param) OVERRIDE
void MoveInLineOfSight(Unit *) OVERRIDE
void BlinkTo(float x, float y, float z)
void EnterPhase(PhaseAkama NextPhase)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *done_by, uint32 &damage) OVERRIDE
void sGossipSelect(Player *player, uint32, uint32) OVERRIDE
void MovementInform(uint32 MovementType, uint32) OVERRIDE
void SpellHit(Unit *, const SpellInfo *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 EnterCombat(Unit *) OVERRIDE
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
@ SPELL_KNEEL