Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_faction_champions.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#include "ScriptMgr.h"
7#include "ScriptedCreature.h"
8#include "SpellScript.h"
9#include "SpellAuraEffects.h"
11#include "Player.h"
12#include "GridNotifiers.h"
13
15{
17};
18
19enum AIs
20{
25};
26
28{
29 // generic
32
33 // druid healer
40 SPELL_THORNS = 66068,
42
43 // shaman healer
46 SPELL_SPIRIT_CLEANSE = 66056, //friendly only
49 SPELL_HEX = 66054,
53 AURA_SATED = 57724,
54
55 // paladin healer
65
66 // priest healer
67 SPELL_RENEW = 66177,
68 SPELL_SHIELD = 66099,
70 SPELL_DISPEL = 65546,
74
75 // priest dps
81 SPELL_HORROR = 65545,
84
85 // warlock
90 SPELL_FEAR = 65809,
96
97 // mage
101 SPELL_BLINK = 65793,
107
108 // hunter
114 SPELL_SHOOT = 65868,
119
120 // druid dps
128 SPELL_WRATH = 65862,
129
130 // warrior
140
141 // death knight
149 SPELL_DEATH_GRIP_PULL = 64431, // used at spellscript
150
151 // rogue
153 SPELL_BLIND = 65960,
154 SPELL_CLOAK = 65961,
160
161 // shaman dps (some spells taken from shaman healer)
165
166 // paladin dps
174
175 // warlock pet
178
179 // hunter pet
181};
182
184{
185 // generic
188
189 // druid healer
198
199 // shaman healer
207
208 // paladin healer
217
218 // priest healer
226
227 // priest dps
236
237 // warlock
245
246 // mage
255
256 // hunter
265
266 // druid dps
275
276 // warrior
286
287 // death knight
295
296 // rogue
305
306 // shaman dps
313
314 // paladin dps
323
324 // warlock pet
327};
328
330{
331 public:
332 boss_toc_champion_controller() : CreatureScript("boss_toc_champion_controller") { }
333
335 {
337 {
338 _instance = creature->GetInstanceScript();
339 }
340
342 {
346 _inProgress = false;
347 }
348
349 std::vector<uint32> SelectChampions(Team playerTeam)
350 {
351 std::vector<uint32> vHealersEntries;
352 vHealersEntries.clear();
353 vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_DRUID_RESTORATION : NPC_ALLIANCE_DRUID_RESTORATION);
354 vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_PALADIN_HOLY : NPC_ALLIANCE_PALADIN_HOLY);
355 vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_PRIEST_DISCIPLINE : NPC_ALLIANCE_PRIEST_DISCIPLINE);
356 vHealersEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_SHAMAN_RESTORATION : NPC_ALLIANCE_SHAMAN_RESTORATION);
357
358 std::vector<uint32> vOtherEntries;
359 vOtherEntries.clear();
360 vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_DEATH_KNIGHT : NPC_ALLIANCE_DEATH_KNIGHT);
361 vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_HUNTER : NPC_ALLIANCE_HUNTER);
362 vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_MAGE : NPC_ALLIANCE_MAGE);
363 vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_ROGUE : NPC_ALLIANCE_ROGUE);
364 vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_WARLOCK : NPC_ALLIANCE_WARLOCK);
365 vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR);
366
367 uint8 healersSubtracted = 2;
368 if (_instance->instance->GetSpawnMode() == DIFFICULTY_25MAN_NORMAL || _instance->instance->GetSpawnMode() == DIFFICULTY_25MAN_HEROIC)
369 healersSubtracted = 1;
370 for (uint8 i = 0; i < healersSubtracted; ++i)
371 {
372 uint8 pos = std::rand() % (vHealersEntries.size() - 1);
373 switch (vHealersEntries[pos])
374 {
376 vOtherEntries.push_back(NPC_ALLIANCE_DRUID_BALANCE);
377 break;
379 vOtherEntries.push_back(NPC_HORDE_DRUID_BALANCE);
380 break;
382 vOtherEntries.push_back(NPC_ALLIANCE_PALADIN_RETRIBUTION);
383 break;
385 vOtherEntries.push_back(NPC_HORDE_PALADIN_RETRIBUTION);
386 break;
388 vOtherEntries.push_back(NPC_ALLIANCE_PRIEST_SHADOW);
389 break;
391 vOtherEntries.push_back(NPC_HORDE_PRIEST_SHADOW);
392 break;
394 vOtherEntries.push_back(NPC_ALLIANCE_SHAMAN_ENHANCEMENT);
395 break;
397 vOtherEntries.push_back(NPC_HORDE_SHAMAN_ENHANCEMENT);
398 break;
399 default:
400 break;
401 }
402 vHealersEntries.erase(vHealersEntries.begin() + pos);
403 }
404
405 if (_instance->instance->GetSpawnMode() == DIFFICULTY_10MAN_NORMAL || _instance->instance->GetSpawnMode() == DIFFICULTY_10MAN_HEROIC)
406 for (uint8 i = 0; i < 4; ++i)
407 vOtherEntries.erase(vOtherEntries.begin() + std::rand() % (vOtherEntries.size() - 1));
408
409 std::vector<uint32> vChampionEntries;
410 vChampionEntries.clear();
411 for (uint8 i = 0; i < vHealersEntries.size(); ++i)
412 vChampionEntries.push_back(vHealersEntries[i]);
413 for (uint8 i = 0; i < vOtherEntries.size(); ++i)
414 vChampionEntries.push_back(vOtherEntries[i]);
415
416 return vChampionEntries;
417 }
418
419 void SummonChampions(Team playerTeam)
420 {
421 std::vector<Position> vChampionJumpOrigin;
422 if (playerTeam == ALLIANCE)
423 for (uint8 i = 0; i < 5; i++)
424 vChampionJumpOrigin.push_back(FactionChampionLoc[i]);
425 else
426 for (uint8 i = 5; i < 10; i++)
427 vChampionJumpOrigin.push_back(FactionChampionLoc[i]);
428
429 std::vector<Position> vChampionJumpTarget;
430 for (uint8 i = 10; i < 20; i++)
431 vChampionJumpTarget.push_back(FactionChampionLoc[i]);
432 std::vector<uint32> vChampionEntries = SelectChampions(playerTeam);
433
434 for (uint8 i = 0; i < vChampionEntries.size(); ++i)
435 {
436 uint8 pos = std::rand() % (vChampionJumpTarget.size()-1);
437 if (Creature* temp = me->SummonCreature(vChampionEntries[i], vChampionJumpOrigin[std::rand() % (vChampionJumpOrigin.size()-1)], TempSummonType::TEMPSUMMON_MANUAL_DESPAWN))
438 {
439 _summons.Summon(temp);
440 temp->SetReactState(REACT_PASSIVE);
442 if (playerTeam == ALLIANCE)
443 {
444 temp->SetHomePosition(vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 0);
445 temp->GetMotionMaster()->MoveJump(vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 20.0f, 20.0f);
446 temp->SetOrientation(0);
447 }
448 else
449 {
450 temp->SetHomePosition((ToCCommonLoc[1].GetPositionX()*2)-vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 3);
451 temp->GetMotionMaster()->MoveJump((ToCCommonLoc[1].GetPositionX()*2)-vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 20.0f, 20.0f);
452 temp->SetOrientation(3);
453 }
454 }
455 vChampionJumpTarget.erase(vChampionJumpTarget.begin()+pos);
456 }
457 }
458
459 void SetData(uint32 uiType, uint32 uiData) OVERRIDE
460 {
461 switch (uiType)
462 {
463 case 0:
464 SummonChampions((Team)uiData);
465 break;
466 case 1:
467 for (std::list<uint64>::iterator i = _summons.begin(); i != _summons.end(); ++i)
468 {
469 if (Creature* temp = Unit::GetCreature(*me, *i))
470 {
471 temp->SetReactState(REACT_AGGRESSIVE);
473 }
474 }
475 break;
476 case 2:
477 switch (uiData)
478 {
479 case FAIL:
482 {
483 _instance->SetBossState(BOSS_CRUSADERS, FAIL);
484 _summons.DespawnAll();
485 me->DespawnOrUnsummon();
486 }
487 break;
488 case IN_PROGRESS:
489 if (!_inProgress)
490 {
494 _inProgress = true;
495 _summons.DoZoneInCombat();
496 _instance->SetBossState(BOSS_CRUSADERS, IN_PROGRESS);
497 }
498 break;
499 case DONE:
501 if (_championsKilled == 1)
502 _instance->SetBossState(BOSS_CRUSADERS, SPECIAL);
503 else if (_championsKilled >= _summons.size())
504 {
505 _instance->SetBossState(BOSS_CRUSADERS, DONE);
506 _summons.DespawnAll();
507 me->DespawnOrUnsummon();
508 }
509 break;
510 default:
511 break;
512 }
513 break;
514 default:
515 break;
516 }
517 }
518 private:
525 };
526
528 {
529 return new boss_toc_champion_controllerAI(creature);
530 }
531};
532
534{
536 {
537 _aiType = aitype;
538 }
539
541 {
542 _events.ScheduleEvent(EVENT_THREAT, 5*IN_MILLISECONDS);
543 if (IsHeroic() && (_aiType != AI_PET))
544 _events.ScheduleEvent(EVENT_REMOVE_CC, 5*IN_MILLISECONDS);
545 }
546
548 {
549 if (instance)
550 if (Creature* pChampionController = Unit::GetCreature((*me), instance->GetData64(NPC_CHAMPIONS_CONTROLLER)))
551 pChampionController->AI()->SetData(2, FAIL);
552 me->DespawnOrUnsummon();
553 }
554
555 float CalculateThreat(float distance, float armor, uint32 health)
556 {
557 float dist_mod = (_aiType == AI_MELEE || _aiType == AI_PET) ? 15.0f / (15.0f + distance) : 1.0f;
558 float armor_mod = (_aiType == AI_MELEE || _aiType == AI_PET) ? armor / 16635.0f : 0.0f;
559 float eh = (health + 1) * (1.0f + armor_mod);
560 return dist_mod * 30000.0f / eh;
561 }
562
564 {
565 std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList();
566 for (std::list<HostileReference*>::const_iterator itr = tList.begin(); itr != tList.end(); ++itr)
567 {
568 Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid());
569 if (unit && me->getThreatManager().getThreat(unit))
570 {
571 if (unit->GetTypeId() == TypeID::TYPEID_PLAYER)
572 {
573 float threat = CalculateThreat(me->GetDistance2d(unit), (float)unit->GetArmor(), unit->GetHealth());
574 me->getThreatManager().modifyThreatPercent(unit, -100);
575 me->AddThreat(unit, 1000000.0f * threat);
576 }
577 }
578 }
579 }
580
582 {
583 if (me->getPowerType() == POWER_MANA)
584 me->ModifyPower(POWER_MANA, me->GetMaxPower(POWER_MANA) / 3);
585 }
586
587 void RemoveCC()
588 {
589 me->RemoveAurasByType(SPELL_AURA_MOD_STUN);
590 me->RemoveAurasByType(SPELL_AURA_MOD_FEAR);
591 me->RemoveAurasByType(SPELL_AURA_MOD_ROOT);
592 me->RemoveAurasByType(SPELL_AURA_MOD_PACIFY);
593 me->RemoveAurasByType(SPELL_AURA_MOD_CONFUSE);
594 //DoCast(me, SPELL_PVP_TRINKET);
595 }
596
597 void JustDied(Unit* /*killer*/) OVERRIDE
598 {
599 if (_aiType != AI_PET)
600 if (instance)
601 if (Creature* pChampionController = Unit::GetCreature((*me), instance->GetData64(NPC_CHAMPIONS_CONTROLLER)))
602 pChampionController->AI()->SetData(2, DONE);
603 }
604
605 void EnterCombat(Unit* /*who*/) OVERRIDE
606 {
607 DoCast(me, SPELL_ANTI_AOE, true);
608 _EnterCombat();
609 if (instance)
610 if (Creature* pChampionController = Unit::GetCreature((*me), instance->GetData64(NPC_CHAMPIONS_CONTROLLER)))
611 pChampionController->AI()->SetData(2, IN_PROGRESS);
612 }
613
615 {
616 if (who->GetTypeId() == TypeID::TYPEID_PLAYER)
617 {
618 Map::PlayerList const &players = me->GetMap()->GetPlayers();
619 uint32 TeamInInstance = 0;
620
621 if (!players.isEmpty())
622 if (Player* player = players.begin()->GetSource())
623 TeamInInstance = player->GetTeam();
624
625 if (instance)
626 {
627 if (TeamInInstance == ALLIANCE)
628 {
629 if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_VARIAN)))
630 temp->AI()->Talk(SAY_KILL_PLAYER);
631 }
632 else
633 if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_GARROSH)))
634 temp->AI()->Talk(SAY_KILL_PLAYER);
635
636
638 }
639 }
640 }
641
643 {
644 std::list<Creature*> lst = DoFindFriendlyMissingBuff(40.0f, spell);
645 std::list<Creature*>::const_iterator itr = lst.begin();
646 if (lst.empty())
647 return NULL;
648 advance(itr, rand() % lst.size());
649 return (*itr);
650 }
651
652 Unit* SelectEnemyCaster(bool /*casting*/)
653 {
654 std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList();
655 std::list<HostileReference*>::const_iterator iter;
656 Unit* target;
657 for (iter = tList.begin(); iter!=tList.end(); ++iter)
658 {
659 target = Unit::GetUnit(*me, (*iter)->getUnitGuid());
660 if (target && target->getPowerType() == POWER_MANA)
661 return target;
662 }
663 return NULL;
664 }
665
666 uint32 EnemiesInRange(float distance)
667 {
668 std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList();
669 std::list<HostileReference*>::const_iterator iter;
670 uint32 count = 0;
671 Unit* target;
672 for (iter = tList.begin(); iter != tList.end(); ++iter)
673 {
674 target = Unit::GetUnit(*me, (*iter)->getUnitGuid());
675 if (target && me->GetDistance2d(target) < distance)
676 ++count;
677 }
678 return count;
679 }
680
682 {
683 if (!who)
684 return;
685
686 if (me->Attack(who, true))
687 {
688 me->AddThreat(who, 10.0f);
689 me->SetInCombatWith(who);
690 who->SetInCombatWith(me);
691
692 if (_aiType == AI_MELEE || _aiType == AI_PET)
693 DoStartMovement(who);
694 else
695 DoStartMovement(who, 20.0f);
696 SetCombatMovement(true);
697 }
698 }
699
701 {
702 _events.Update(diff);
703
704 while (uint32 eventId = _events.ExecuteEvent())
705 {
706 switch (eventId)
707 {
708 case EVENT_THREAT:
709 UpdatePower();
710 UpdateThreat();
711 _events.ScheduleEvent(EVENT_THREAT, 4*IN_MILLISECONDS);
712 return;
713 case EVENT_REMOVE_CC:
714 if (me->HasBreakableByDamageCrowdControlAura())
715 {
716 RemoveCC();
717 _events.RescheduleEvent(EVENT_REMOVE_CC, 2*MINUTE*IN_MILLISECONDS);
718 }
719 else
720 _events.RescheduleEvent(EVENT_REMOVE_CC, 3*IN_MILLISECONDS);
721 return;
722 default:
723 return;
724 }
725 }
726
727 if (_aiType == AI_MELEE || _aiType == AI_PET)
729 }
730
731 private:
733 // make sure that every bosses separate events dont mix with these _events
735};
736
737/********************************************************************
738 HEALERS
739********************************************************************/
741{
742 public:
743 npc_toc_druid() : CreatureScript("npc_toc_druid") { }
744
746 {
748
750 {
752 events.ScheduleEvent(EVENT_LIFEBLOOM, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
753 events.ScheduleEvent(EVENT_NOURISH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
754 events.ScheduleEvent(EVENT_REGROWTH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
755 events.ScheduleEvent(EVENT_REJUVENATION, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
756 events.ScheduleEvent(EVENT_TRANQUILITY, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
757 events.ScheduleEvent(EVENT_HEAL_BARKSKIN, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
758 events.ScheduleEvent(EVENT_THORNS, 2*IN_MILLISECONDS);
759 events.ScheduleEvent(EVENT_NATURE_GRASP, std::rand() % (20 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
761 }
762
764 {
765 if (!UpdateVictim())
766 return;
767
768 events.Update(diff);
770
771 if (me->HasUnitState(UNIT_STATE_CASTING))
772 return;
773
774 while (uint32 eventId = events.ExecuteEvent())
775 {
776 switch (eventId)
777 {
778 case EVENT_LIFEBLOOM:
779 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
780 DoCast(target, SPELL_LIFEBLOOM);
781 events.ScheduleEvent(EVENT_LIFEBLOOM, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
782 return;
783 case EVENT_NOURISH:
784 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
785 DoCast(target, SPELL_NOURISH);
786 events.ScheduleEvent(EVENT_NOURISH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
787 return;
788 case EVENT_REGROWTH:
789 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
790 DoCast(target, SPELL_REGROWTH);
791 events.ScheduleEvent(EVENT_REGROWTH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
792 return;
794 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
795 DoCast(target, SPELL_REJUVENATION);
796 events.ScheduleEvent(EVENT_REJUVENATION, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
797 return;
800 events.ScheduleEvent(EVENT_TRANQUILITY, std::rand() % (40 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
801 return;
803 if (HealthBelowPct(30))
804 {
806 events.RescheduleEvent(EVENT_HEAL_BARKSKIN, 60*IN_MILLISECONDS);
807 }
808 else
809 events.RescheduleEvent(EVENT_HEAL_BARKSKIN, 3*IN_MILLISECONDS);
810 return;
811 case EVENT_THORNS:
813 DoCast(target, SPELL_THORNS);
814 events.ScheduleEvent(EVENT_THORNS, std::rand() % (40 * IN_MILLISECONDS) + (25 * IN_MILLISECONDS));
815 return;
818 events.ScheduleEvent(EVENT_NATURE_GRASP, 60*IN_MILLISECONDS);
819 return;
820 default:
821 return;
822 }
823 }
824 }
825 };
826
828 {
829 return new npc_toc_druidAI(creature);
830 }
831};
832
834{
835 public:
836 npc_toc_shaman() : CreatureScript("npc_toc_shaman") { }
837
839 {
841
843 {
845 events.ScheduleEvent(EVENT_HEALING_WAVE, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
846 events.ScheduleEvent(EVENT_RIPTIDE, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
847 events.ScheduleEvent(EVENT_SPIRIT_CLEANSE, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
849 events.ScheduleEvent(EVENT_HEX, std::rand() % (30 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
850 events.ScheduleEvent(EVENT_EARTH_SHIELD, 1*IN_MILLISECONDS);
851 events.ScheduleEvent(EVENT_HEAL_EARTH_SHOCK, std::rand() % (30 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
853 }
854
856 {
857 if (!UpdateVictim())
858 return;
859
860 events.Update(diff);
862
863 if (me->HasUnitState(UNIT_STATE_CASTING))
864 return;
865
866 while (uint32 eventId = events.ExecuteEvent())
867 {
868 switch (eventId)
869 {
871 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
872 DoCast(target, SPELL_HEALING_WAVE);
873 events.ScheduleEvent(EVENT_HEALING_WAVE, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
874 return;
875 case EVENT_RIPTIDE:
876 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
877 DoCast(target, SPELL_RIPTIDE);
878 events.ScheduleEvent(EVENT_RIPTIDE, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
879 return;
881 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
883 events.ScheduleEvent(EVENT_SPIRIT_CLEANSE, std::rand() % (35 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
884 return;
886 if (me->getFaction()) // alliance = 1
887 {
888 if (!me->HasAura(AURA_EXHAUSTION))
890 }
891 else
892 {
893 if (!me->HasAura(AURA_SATED))
895 }
897 return;
898 case EVENT_HEX:
900 DoCast(target, SPELL_HEX);
901 events.ScheduleEvent(EVENT_HEX, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
902 return;
905 DoCast(target, SPELL_EARTH_SHIELD);
906 events.ScheduleEvent(EVENT_EARTH_SHIELD, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
907 return;
909 if (Unit* target = SelectEnemyCaster(true))
910 DoCast(target, SPELL_EARTH_SHOCK);
911 events.ScheduleEvent(EVENT_HEAL_EARTH_SHOCK, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
912 return;
913 default:
914 return;
915 }
916 }
917 }
918 };
919
921 {
922 return new npc_toc_shamanAI(creature);
923 }
924};
925
927{
928 public:
929 npc_toc_paladin() : CreatureScript("npc_toc_paladin") { }
930
932 {
934
936 {
938 events.ScheduleEvent(EVENT_HAND_OF_FREEDOM, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
940 events.ScheduleEvent(EVENT_CLEANSE, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
941 events.ScheduleEvent(EVENT_FLASH_OF_LIGHT, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
942 events.ScheduleEvent(EVENT_HOLY_LIGHT, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
943 events.ScheduleEvent(EVENT_HOLY_SHOCK, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
944 events.ScheduleEvent(EVENT_HEAL_HAND_OF_PROTECTION, std::rand() % (60 * IN_MILLISECONDS) + (30 * IN_MILLISECONDS));
945 events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
946 SetEquipmentSlots(false, 50771, 47079, EQUIP_NO_CHANGE);
947 }
948
950 {
951 if (!UpdateVictim())
952 return;
953
954 events.Update(diff);
956
957 if (me->HasUnitState(UNIT_STATE_CASTING))
958 return;
959
960 while (uint32 eventId = events.ExecuteEvent())
961 {
962 switch (eventId)
963 {
967 events.ScheduleEvent(EVENT_HAND_OF_FREEDOM, std::rand() % (35 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
968 return;
970 if (HealthBelowPct(30) && !me->HasAura(SPELL_FORBEARANCE))
971 {
974 }
975 else
977 return;
978 case EVENT_CLEANSE:
979 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
980 DoCast(target, SPELL_CLEANSE);
981 events.ScheduleEvent(EVENT_CLEANSE, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
982 return;
984 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
986 events.ScheduleEvent(EVENT_FLASH_OF_LIGHT, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
987 return;
988 case EVENT_HOLY_LIGHT:
989 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
990 DoCast(target, SPELL_HOLY_LIGHT);
991 events.ScheduleEvent(EVENT_HOLY_LIGHT, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
992 return;
993 case EVENT_HOLY_SHOCK:
994 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
995 DoCast(target, SPELL_HOLY_SHOCK);
996 events.ScheduleEvent(EVENT_HOLY_SHOCK, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
997 return;
999 if (Unit* target = DoSelectLowestHpFriendly(30.0f))
1000 {
1001 if (!target->HasAura(SPELL_FORBEARANCE))
1002 {
1005 }
1006 else
1008 }
1009 else
1011 return;
1013 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 15.0f, true))
1016 return;
1017 default:
1018 return;
1019 }
1020 }
1021 }
1022 };
1023
1025 {
1026 return new npc_toc_paladinAI(creature);
1027 }
1028};
1029
1031{
1032 public:
1033 npc_toc_priest() : CreatureScript("npc_toc_priest") { }
1034
1036 {
1038
1040 {
1042 events.ScheduleEvent(EVENT_RENEW, std::rand() % (10 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1043 events.ScheduleEvent(EVENT_SHIELD, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1044 events.ScheduleEvent(EVENT_FLASH_HEAL, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1045 events.ScheduleEvent(EVENT_HEAL_DISPEL, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1046 events.ScheduleEvent(EVENT_HEAL_PSYCHIC_SCREAM, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1047 events.ScheduleEvent(EVENT_MANA_BURN, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1048 events.ScheduleEvent(EVENT_PENANCE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1050 }
1051
1053 {
1054 if (!UpdateVictim())
1055 return;
1056
1057 events.Update(diff);
1059
1060 if (me->HasUnitState(UNIT_STATE_CASTING))
1061 return;
1062
1063 while (uint32 eventId = events.ExecuteEvent())
1064 {
1065 switch (eventId)
1066 {
1067 case EVENT_RENEW:
1068 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
1069 DoCast(target, SPELL_RENEW);
1070 events.ScheduleEvent(EVENT_RENEW, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1071 return;
1072 case EVENT_SHIELD:
1073 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
1074 DoCast(target, SPELL_SHIELD);
1075 events.ScheduleEvent(EVENT_SHIELD, std::rand() % (35 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1076 return;
1077 case EVENT_FLASH_HEAL:
1078 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
1079 DoCast(target, SPELL_FLASH_HEAL);
1080 events.ScheduleEvent(EVENT_FLASH_HEAL, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1081 return;
1082 case EVENT_HEAL_DISPEL:
1083 if (Unit* target = std::rand() % 1 ? SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) : DoSelectLowestHpFriendly(40.0f))
1084 DoCast(target, SPELL_DISPEL);
1085 events.ScheduleEvent(EVENT_HEAL_DISPEL, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1086 return;
1088 if (EnemiesInRange(10.0f) >= 2)
1090 events.ScheduleEvent(EVENT_HEAL_PSYCHIC_SCREAM, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1091 return;
1092 case EVENT_MANA_BURN:
1093 if (Unit* target = SelectEnemyCaster(false))
1094 DoCast(target, SPELL_MANA_BURN);
1095 events.ScheduleEvent(EVENT_MANA_BURN, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1096 return;
1097 case EVENT_PENANCE:
1098 if (Unit* target = DoSelectLowestHpFriendly(40.0f))
1099 DoCast(target, SPELL_PENANCE);
1100 events.ScheduleEvent(EVENT_PENANCE, std::rand() % (20 * IN_MILLISECONDS) + (10*IN_MILLISECONDS));
1101 return;
1102 default:
1103 return;
1104 }
1105 }
1106 }
1107 };
1108
1110 {
1111 return new npc_toc_priestAI(creature);
1112 }
1113};
1114
1115/********************************************************************
1116 RANGED
1117********************************************************************/
1119{
1120 public:
1121 npc_toc_shadow_priest() : CreatureScript("npc_toc_shadow_priest") { }
1122
1124 {
1126
1128 {
1130 events.ScheduleEvent(EVENT_SILENCE, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1131 events.ScheduleEvent(EVENT_VAMPIRIC_TOUCH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1132 events.ScheduleEvent(EVENT_SW_PAIN, std::rand() % (10 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1133 events.ScheduleEvent(EVENT_MIND_BLAST, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1134 events.ScheduleEvent(EVENT_HORROR, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1135 events.ScheduleEvent(EVENT_DISPERSION, std::rand() % (40 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1136 events.ScheduleEvent(EVENT_DPS_DISPEL, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1137 events.ScheduleEvent(EVENT_DPS_PSYCHIC_SCREAM, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1140 }
1141
1143 {
1144 if (!UpdateVictim())
1145 return;
1146
1147 events.Update(diff);
1149
1150 if (me->HasUnitState(UNIT_STATE_CASTING))
1151 return;
1152
1153 while (uint32 eventId = events.ExecuteEvent())
1154 {
1155 switch (eventId)
1156 {
1157 case EVENT_SILENCE:
1158 if (Unit* target = SelectEnemyCaster(true))
1159 DoCast(target, SPELL_SILENCE);
1160 events.ScheduleEvent(EVENT_SILENCE, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1161 return;
1163 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true))
1165 events.ScheduleEvent(EVENT_VAMPIRIC_TOUCH, std::rand() % (35 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1166 return;
1167 case EVENT_SW_PAIN:
1168 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
1169 DoCast(target, SPELL_SW_PAIN);
1170 events.ScheduleEvent(EVENT_SW_PAIN, std::rand() % (35 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1171 return;
1172 case EVENT_MIND_BLAST:
1174 events.ScheduleEvent(EVENT_MIND_BLAST, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1175 return;
1176 case EVENT_HORROR:
1178 events.ScheduleEvent(EVENT_HORROR, std::rand() % (35 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1179 return;
1180 case EVENT_DISPERSION:
1181 if (HealthBelowPct(40))
1182 {
1184 events.RescheduleEvent(EVENT_DISPERSION, 180*IN_MILLISECONDS);
1185 }
1186 else
1187 events.RescheduleEvent(EVENT_DISPERSION, 5*IN_MILLISECONDS);
1188 return;
1189 case EVENT_DPS_DISPEL:
1190 if (Unit* target = std::rand() % 1 ? SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) : DoSelectLowestHpFriendly(40.0f))
1191 DoCast(target, SPELL_DISPEL);
1192 events.ScheduleEvent(EVENT_DPS_DISPEL, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1193 return;
1195 if (EnemiesInRange(10.0f) >= 2)
1197 events.ScheduleEvent(EVENT_DPS_PSYCHIC_SCREAM, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1198 return;
1199 default:
1200 return;
1201 }
1202 }
1204 }
1205 };
1206
1208 {
1209 return new npc_toc_shadow_priestAI(creature);
1210 }
1211};
1212
1214{
1215 public:
1216 npc_toc_warlock() : CreatureScript("npc_toc_warlock") { }
1217
1219 {
1221
1223 {
1225 events.ScheduleEvent(EVENT_HELLFIRE, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1226 events.ScheduleEvent(EVENT_CORRUPTION, std::rand() % (5 * IN_MILLISECONDS) + (2 * IN_MILLISECONDS));
1227 events.ScheduleEvent(EVENT_CURSE_OF_AGONY, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1228 events.ScheduleEvent(EVENT_CURSE_OF_EXHAUSTION, std::rand() % (10 * IN_MILLISECONDS) + (5*IN_MILLISECONDS));
1229 events.ScheduleEvent(EVENT_FEAR, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1230 events.ScheduleEvent(EVENT_SEARING_PAIN, std::rand() % (12 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1231 events.ScheduleEvent(EVENT_UNSTABLE_AFFLICTION, std::rand() % (15 * IN_MILLISECONDS) + (7 * IN_MILLISECONDS));
1233 }
1234
1240
1242 {
1243 if (!UpdateVictim())
1244 return;
1245
1246 events.Update(diff);
1248
1249 if (me->HasUnitState(UNIT_STATE_CASTING))
1250 return;
1251
1252 while (uint32 eventId = events.ExecuteEvent())
1253 {
1254 switch (eventId)
1255 {
1256 case EVENT_HELLFIRE:
1257 if (EnemiesInRange(10.0f) >= 2)
1259 events.ScheduleEvent(EVENT_HELLFIRE, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1260 return;
1261 case EVENT_CORRUPTION:
1262 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f))
1263 DoCast(target, SPELL_CORRUPTION);
1264 events.ScheduleEvent(EVENT_CORRUPTION, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1265 return;
1267 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f))
1269 events.ScheduleEvent(EVENT_CURSE_OF_AGONY, std::rand() % (35 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1270 return;
1272 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f))
1274 events.ScheduleEvent(EVENT_CURSE_OF_EXHAUSTION, std::rand() % (35 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1275 return;
1276 case EVENT_FEAR:
1277 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true))
1278 DoCast(target, SPELL_FEAR);
1279 events.ScheduleEvent(EVENT_FEAR, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1280 return;
1281 case EVENT_SEARING_PAIN:
1283 events.ScheduleEvent(EVENT_SEARING_PAIN, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1284 return;
1286 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true))
1288 events.ScheduleEvent(EVENT_UNSTABLE_AFFLICTION, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1289 return;
1290 default:
1291 return;
1292 }
1293 }
1295 }
1296 };
1297
1299 {
1300 return new npc_toc_warlockAI(creature);
1301 }
1302};
1303
1305{
1306 public:
1307 npc_toc_mage() : CreatureScript("npc_toc_mage") { }
1308
1310 {
1312
1314 {
1316 events.ScheduleEvent(EVENT_ARCANE_BARRAGE, std::rand() % (5 * IN_MILLISECONDS) + (1 * IN_MILLISECONDS));
1317 events.ScheduleEvent(EVENT_ARCANE_BLAST, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1318 events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1319 events.ScheduleEvent(EVENT_BLINK, std::rand() % (20 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1320 events.ScheduleEvent(EVENT_COUNTERSPELL, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1321 events.ScheduleEvent(EVENT_FROST_NOVA, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1322 events.ScheduleEvent(EVENT_ICE_BLOCK, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1323 events.ScheduleEvent(EVENT_POLYMORPH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1325 }
1326
1328 {
1329 if (!UpdateVictim())
1330 return;
1331
1332 events.Update(diff);
1334
1335 if (me->HasUnitState(UNIT_STATE_CASTING))
1336 return;
1337
1338 while (uint32 eventId = events.ExecuteEvent())
1339 {
1340 switch (eventId)
1341 {
1344 events.ScheduleEvent(EVENT_ARCANE_BARRAGE, std::rand() % (7 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1345 return;
1346 case EVENT_ARCANE_BLAST:
1348 events.ScheduleEvent(EVENT_ARCANE_BLAST, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1349 return;
1351 if (EnemiesInRange(10.0f) >= 2)
1353 events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1354 return;
1355 case EVENT_BLINK:
1356 if (EnemiesInRange(10.0f) >= 2)
1358 events.ScheduleEvent(EVENT_BLINK, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1359 return;
1360 case EVENT_COUNTERSPELL:
1361 if (Unit* target = SelectEnemyCaster(true))
1362 DoCast(target, SPELL_COUNTERSPELL);
1363 events.ScheduleEvent(EVENT_COUNTERSPELL, 24*IN_MILLISECONDS);
1364 return;
1365 case EVENT_FROST_NOVA:
1366 if (EnemiesInRange(10.0f) >= 2)
1368 events.ScheduleEvent(EVENT_FROST_NOVA, 25*IN_MILLISECONDS);
1369 return;
1370 case EVENT_ICE_BLOCK:
1371 if (HealthBelowPct(30))
1372 {
1374 events.RescheduleEvent(EVENT_ICE_BLOCK, 5*MINUTE*IN_MILLISECONDS);
1375 }
1376 else
1377 events.RescheduleEvent(EVENT_ICE_BLOCK, 5*IN_MILLISECONDS);
1378 return;
1379 case EVENT_POLYMORPH:
1381 DoCast(target, SPELL_POLYMORPH);
1382 events.ScheduleEvent(EVENT_POLYMORPH, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1383 return;
1384 default:
1385 return;
1386 }
1387 }
1389 }
1390 };
1391
1393 {
1394 return new npc_toc_mageAI(creature);
1395 }
1396};
1397
1399{
1400 public:
1401 npc_toc_hunter() : CreatureScript("npc_toc_hunter") { }
1402
1404 {
1406
1408 {
1410 events.ScheduleEvent(EVENT_AIMED_SHOT, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1411 events.ScheduleEvent(EVENT_DETERRENCE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1412 events.ScheduleEvent(EVENT_DISENGAGE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1413 events.ScheduleEvent(EVENT_EXPLOSIVE_SHOT, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1414 events.ScheduleEvent(EVENT_FROST_TRAP, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1415 events.ScheduleEvent(EVENT_STEADY_SHOT, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1416 events.ScheduleEvent(EVENT_WING_CLIP, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1417 events.ScheduleEvent(EVENT_WYVERN_STING, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1418 SetEquipmentSlots(false, 47156, EQUIP_NO_CHANGE, 48711);
1419 }
1420
1426
1428 {
1429 if (!UpdateVictim())
1430 return;
1431
1432 events.Update(diff);
1434
1435 if (me->HasUnitState(UNIT_STATE_CASTING))
1436 return;
1437
1438 while (uint32 eventId = events.ExecuteEvent())
1439 {
1440 switch (eventId)
1441 {
1442 case EVENT_AIMED_SHOT:
1444 events.ScheduleEvent(EVENT_AIMED_SHOT, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1445 return;
1446 case EVENT_DETERRENCE:
1447 if (HealthBelowPct(30))
1448 {
1450 events.RescheduleEvent(EVENT_DETERRENCE, 150*IN_MILLISECONDS);
1451 }
1452 else
1453 events.RescheduleEvent(EVENT_DETERRENCE, 10*IN_MILLISECONDS);
1454 return;
1455 case EVENT_DISENGAGE:
1456 if (EnemiesInRange(10.0f) >= 2)
1458 events.ScheduleEvent(EVENT_DISENGAGE, 30*IN_MILLISECONDS);
1459 return;
1462 events.ScheduleEvent(EVENT_EXPLOSIVE_SHOT, std::rand() % (10 * IN_MILLISECONDS) + (6 * IN_MILLISECONDS));
1463 return;
1464 case EVENT_FROST_TRAP:
1465 if (EnemiesInRange(10.0f) >= 2)
1467 events.ScheduleEvent(EVENT_FROST_TRAP, 30*IN_MILLISECONDS);
1468 return;
1469 case EVENT_STEADY_SHOT:
1471 events.ScheduleEvent(EVENT_STEADY_SHOT, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1472 return;
1473 case EVENT_WING_CLIP:
1474 if (Unit* target = me->GetVictim())
1475 {
1476 if (me->GetDistance2d(target) < 6.0f)
1477 DoCast(target, SPELL_WING_CLIP);
1478 }
1479 events.ScheduleEvent(EVENT_WING_CLIP, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1480 return;
1481 case EVENT_WYVERN_STING:
1483 DoCast(target, SPELL_WYVERN_STING);
1484 events.ScheduleEvent(EVENT_WYVERN_STING, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1485 return;
1486 default:
1487 return;
1488 }
1489 }
1491 }
1492 };
1493
1495 {
1496 return new npc_toc_hunterAI(creature);
1497 }
1498};
1499
1501{
1502 public:
1503 npc_toc_boomkin() : CreatureScript("npc_toc_boomkin") { }
1504
1506 {
1508
1510 {
1512 events.ScheduleEvent(EVENT_CYCLONE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1513 events.ScheduleEvent(EVENT_ENTANGLING_ROOTS, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1514 events.ScheduleEvent(EVENT_FAERIE_FIRE, std::rand() % (5 * IN_MILLISECONDS) + (2 * IN_MILLISECONDS));
1515 events.ScheduleEvent(EVENT_FORCE_OF_NATURE, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1516 events.ScheduleEvent(EVENT_INSECT_SWARM, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1517 events.ScheduleEvent(EVENT_MOONFIRE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1518 events.ScheduleEvent(EVENT_STARFIRE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1519 events.ScheduleEvent(EVENT_DPS_BARKSKIN, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1520
1522 }
1523
1525 {
1526 if (!UpdateVictim())
1527 return;
1528
1529 events.Update(diff);
1531
1532 if (me->HasUnitState(UNIT_STATE_CASTING))
1533 return;
1534
1535 while (uint32 eventId = events.ExecuteEvent())
1536 {
1537 switch (eventId)
1538 {
1539 case EVENT_CYCLONE:
1541 DoCast(target, SPELL_CYCLONE);
1542 events.ScheduleEvent(EVENT_CYCLONE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1543 return;
1545 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true))
1547 events.ScheduleEvent(EVENT_ENTANGLING_ROOTS, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1548 return;
1549 case EVENT_FAERIE_FIRE:
1551 events.ScheduleEvent(EVENT_FAERIE_FIRE, std::rand() % (40 * IN_MILLISECONDS) + (30 * IN_MILLISECONDS));
1552 return;
1555 events.ScheduleEvent(EVENT_FORCE_OF_NATURE, 180*IN_MILLISECONDS);
1556 return;
1557 case EVENT_INSECT_SWARM:
1559 events.ScheduleEvent(EVENT_INSECT_SWARM, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1560 return;
1561 case EVENT_MOONFIRE:
1563 events.ScheduleEvent(EVENT_MOONFIRE, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1564 return;
1565 case EVENT_STARFIRE:
1567 events.ScheduleEvent(EVENT_STARFIRE, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1568 return;
1569 case EVENT_DPS_BARKSKIN:
1570 if (HealthBelowPct(30))
1571 {
1573 events.RescheduleEvent(EVENT_DPS_BARKSKIN, 60*IN_MILLISECONDS);
1574 }
1575 else
1576 events.RescheduleEvent(EVENT_DPS_BARKSKIN, 5*IN_MILLISECONDS);
1577 return;
1578 default:
1579 return;
1580 }
1581 }
1583 }
1584 };
1585
1587 {
1588 return new npc_toc_boomkinAI(creature);
1589 }
1590};
1591
1592/********************************************************************
1593 MELEE
1594********************************************************************/
1596{
1597 public:
1598 npc_toc_warrior() : CreatureScript("npc_toc_warrior") { }
1599
1601 {
1603
1605 {
1607 events.ScheduleEvent(EVENT_BLADESTORM, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1608 events.ScheduleEvent(EVENT_INTIMIDATING_SHOUT, std::rand() % (25 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1609 events.ScheduleEvent(EVENT_MORTAL_STRIKE, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1610 events.ScheduleEvent(EVENT_WARR_CHARGE, 1*IN_MILLISECONDS);
1611 events.ScheduleEvent(EVENT_DISARM, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1612 events.ScheduleEvent(EVENT_OVERPOWER, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1613 events.ScheduleEvent(EVENT_SUNDER_ARMOR, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1614 events.ScheduleEvent(EVENT_SHATTERING_THROW, std::rand() % (40 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1615 events.ScheduleEvent(EVENT_RETALIATION, std::rand() % (20 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1616 SetEquipmentSlots(false, 47427, 46964, EQUIP_NO_CHANGE);
1617 }
1618
1620 {
1621 if (!UpdateVictim())
1622 return;
1623
1624 events.Update(diff);
1626
1627 if (me->HasUnitState(UNIT_STATE_CASTING))
1628 return;
1629
1630 while (uint32 eventId = events.ExecuteEvent())
1631 {
1632 switch (eventId)
1633 {
1634 case EVENT_BLADESTORM:
1636 events.ScheduleEvent(EVENT_BLADESTORM, 150*IN_MILLISECONDS);
1637 return;
1641 return;
1644 events.ScheduleEvent(EVENT_MORTAL_STRIKE, std::rand() % (25 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1645 return;
1646 case EVENT_WARR_CHARGE:
1648 events.ScheduleEvent(EVENT_WARR_CHARGE, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1649 return;
1650 case EVENT_DISARM:
1652 events.ScheduleEvent(EVENT_DISARM, std::rand() % (35 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1653 return;
1654 case EVENT_OVERPOWER:
1656 events.ScheduleEvent(EVENT_OVERPOWER, std::rand() % (40 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1657 return;
1658 case EVENT_SUNDER_ARMOR:
1660 events.ScheduleEvent(EVENT_SUNDER_ARMOR, std::rand() % (5 * IN_MILLISECONDS) + (2 * IN_MILLISECONDS));
1661 return;
1663 if (Unit* target = me->GetVictim())
1664 {
1665 if (target->HasAuraWithMechanic(1 << MECHANIC_IMMUNE_SHIELD))
1666 {
1669 return;
1670 }
1671 }
1672 events.RescheduleEvent(EVENT_SHATTERING_THROW, 3*IN_MILLISECONDS);
1673 return;
1674 case EVENT_RETALIATION:
1675 if (HealthBelowPct(50))
1676 {
1678 events.RescheduleEvent(EVENT_RETALIATION, 5*MINUTE*IN_MILLISECONDS);
1679 }
1680 else
1681 events.RescheduleEvent(EVENT_RETALIATION, 5*IN_MILLISECONDS);
1682 return;
1683 default:
1684 return;
1685 }
1686 }
1687 }
1688 };
1689
1691 {
1692 return new npc_toc_warriorAI(creature);
1693 }
1694};
1695
1697{
1698 public:
1699 npc_toc_dk() : CreatureScript("npc_toc_dk") { }
1700
1702 {
1704
1706 {
1708 events.ScheduleEvent(EVENT_CHAINS_OF_ICE, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1709 events.ScheduleEvent(EVENT_DEATH_COIL, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1710 events.ScheduleEvent(EVENT_DEATH_GRIP, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1711 events.ScheduleEvent(EVENT_FROST_STRIKE, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1712 events.ScheduleEvent(EVENT_ICEBOUND_FORTITUDE, std::rand() % (35 * IN_MILLISECONDS) + (25 * IN_MILLISECONDS));
1713 events.ScheduleEvent(EVENT_ICY_TOUCH, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1714 events.ScheduleEvent(EVENT_STRANGULATE, std::rand() % (25 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1715 SetEquipmentSlots(false, 47518, 51021, EQUIP_NO_CHANGE);
1716 }
1717
1719 {
1720 if (!UpdateVictim())
1721 return;
1722
1723 events.Update(diff);
1725
1726 if (me->HasUnitState(UNIT_STATE_CASTING))
1727 return;
1728
1729 while (uint32 eventId = events.ExecuteEvent())
1730 {
1731 switch (eventId)
1732 {
1735 events.ScheduleEvent(EVENT_CHAINS_OF_ICE, std::rand() % (25 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
1736 return;
1737 case EVENT_DEATH_COIL:
1739 events.ScheduleEvent(EVENT_DEATH_COIL, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1740 return;
1741 case EVENT_DEATH_GRIP:
1742 if (Unit* target = me->GetVictim())
1743 {
1744 if (me->IsInRange(target, 5.0f, 30.0f, false))
1745 {
1746 DoCast(target, SPELL_DEATH_GRIP);
1747 events.RescheduleEvent(EVENT_DEATH_GRIP, 35*IN_MILLISECONDS);
1748 return;
1749 }
1750 }
1751 events.RescheduleEvent(EVENT_DEATH_GRIP, 3*IN_MILLISECONDS);
1752 return;
1753 case EVENT_FROST_STRIKE:
1755 events.ScheduleEvent(EVENT_FROST_STRIKE, std::rand() % (10 * IN_MILLISECONDS) + (6 * IN_MILLISECONDS));
1756 return;
1758 if (HealthBelowPct(50))
1759 {
1761 events.RescheduleEvent(EVENT_ICEBOUND_FORTITUDE, 60*IN_MILLISECONDS);
1762 }
1763 else
1765 return;
1766 case EVENT_ICY_TOUCH:
1768 events.ScheduleEvent(EVENT_ICY_TOUCH, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1769 return;
1770 case EVENT_STRANGULATE:
1771 if (Unit* target = SelectEnemyCaster(false))
1772 {
1773 DoCast(target, SPELL_STRANGULATE);
1774 events.RescheduleEvent(EVENT_STRANGULATE, 120*IN_MILLISECONDS);
1775 }
1776 else
1777 events.RescheduleEvent(EVENT_STRANGULATE, 5*IN_MILLISECONDS);
1778 return;
1779 default:
1780 return;
1781 }
1782 }
1783 }
1784 };
1785
1787 {
1788 return new npc_toc_dkAI(creature);
1789 }
1790};
1791
1793{
1794 public:
1795 npc_toc_rogue() : CreatureScript("npc_toc_rogue") { }
1796
1798 {
1800
1802 {
1804 events.ScheduleEvent(EVENT_FAN_OF_KNIVES, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1805 events.ScheduleEvent(EVENT_BLIND, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1806 events.ScheduleEvent(EVENT_CLOAK, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1807 events.ScheduleEvent(EVENT_BLADE_FLURRY, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1808 events.ScheduleEvent(EVENT_SHADOWSTEP, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1809 events.ScheduleEvent(EVENT_HEMORRHAGE, std::rand() % (10 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1810 events.ScheduleEvent(EVENT_EVISCERATE, std::rand() % (40 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1811 events.ScheduleEvent(EVENT_WOUND_POISON, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1812 SetEquipmentSlots(false, 47422, 49982, EQUIP_NO_CHANGE);
1813 me->setPowerType(POWER_ENERGY);
1814 me->SetMaxPower(POWER_ENERGY, 100);
1815 }
1816
1818 {
1819 if (!UpdateVictim())
1820 return;
1821
1822 events.Update(diff);
1824
1825 if (me->HasUnitState(UNIT_STATE_CASTING))
1826 return;
1827
1828 while (uint32 eventId = events.ExecuteEvent())
1829 {
1830 switch (eventId)
1831 {
1833 if (EnemiesInRange(10.0f) >= 2)
1835 events.ScheduleEvent(EVENT_FAN_OF_KNIVES, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1836 return;
1837 case EVENT_BLIND:
1839 DoCast(target, SPELL_BLIND);
1840 events.ScheduleEvent(EVENT_BLIND, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1841 return;
1842 case EVENT_CLOAK:
1843 if (HealthBelowPct(50))
1844 {
1846 events.RescheduleEvent(EVENT_CLOAK, 90*IN_MILLISECONDS);
1847 }
1848 else
1849 events.RescheduleEvent(EVENT_CLOAK, 5*IN_MILLISECONDS);
1850 return;
1851 case EVENT_BLADE_FLURRY:
1852 if (EnemiesInRange(10.0f) >= 2)
1853 {
1855 events.RescheduleEvent(EVENT_BLADE_FLURRY, 120*IN_MILLISECONDS);
1856 }
1857 else
1858 events.RescheduleEvent(EVENT_BLADE_FLURRY, 5*IN_MILLISECONDS);
1859 return;
1860 case EVENT_SHADOWSTEP:
1861 if (Unit* target = me->GetVictim())
1862 {
1863 if (me->IsInRange(target, 10.0f, 40.0f, false))
1864 {
1865 DoCast(target, SPELL_SHADOWSTEP);
1866 events.RescheduleEvent(EVENT_SHADOWSTEP, 30*IN_MILLISECONDS);
1867 return;
1868 }
1869 }
1870 events.RescheduleEvent(EVENT_SHADOWSTEP, 5*IN_MILLISECONDS);
1871 return;
1872 case EVENT_HEMORRHAGE:
1874 events.ScheduleEvent(EVENT_HEMORRHAGE, std::rand() % (10 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1875 return;
1876 case EVENT_EVISCERATE:
1878 events.ScheduleEvent(EVENT_EVISCERATE, std::rand() % (40 * IN_MILLISECONDS) + (30 * IN_MILLISECONDS));
1879 return;
1880 case EVENT_WOUND_POISON:
1882 events.ScheduleEvent(EVENT_WOUND_POISON, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1883 return;
1884 default:
1885 return;
1886 }
1887 }
1888 }
1889 };
1890
1892 {
1893 return new npc_toc_rogueAI(creature);
1894 }
1895};
1896
1898{
1899 public:
1900 npc_toc_enh_shaman() : CreatureScript("npc_toc_enh_shaman") { }
1901
1903 {
1905
1907 {
1909 events.ScheduleEvent(EVENT_DPS_EARTH_SHOCK, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1910 events.ScheduleEvent(EVENT_LAVA_LASH, std::rand() % (5 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1911 events.ScheduleEvent(EVENT_STORMSTRIKE, std::rand() % (5 * IN_MILLISECONDS) + (2 * IN_MILLISECONDS));
1913 events.ScheduleEvent(EVENT_DEPLOY_TOTEM, 1*IN_MILLISECONDS);
1914 events.ScheduleEvent(EVENT_WINDFURY, std::rand() % (50 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
1915
1916 _totemCount = 0;
1917 _totemOldCenterX = me->GetPositionX();
1918 _totemOldCenterY = me->GetPositionY();
1919 SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE);
1920 summons.DespawnAll();
1921 }
1922
1924 {
1925 summons.Summon(summoned);
1926 }
1927
1929 {
1930 --_totemCount;
1931 }
1932
1934 {
1935 _totemCount = 4;
1936 _totemOldCenterX = me->GetPositionX();
1937 _totemOldCenterY = me->GetPositionY();
1938 /*
1939 -Windfury (16% melee haste)
1940 -Grounding (redirects one harmful magic spell to the totem)
1941
1942 -Healing Stream (unable to find amount of healing in our logs)
1943
1944 -Tremor (prevents fear effects)
1945 -Strength of Earth (155 strength and agil for the opposing team)
1946
1947 -Searing (average ~3500 damage on a random target every ~3.5 seconds)
1948 */
1949 }
1950
1951 void JustDied(Unit* killer) OVERRIDE
1952 {
1954 summons.DespawnAll();
1955 }
1956
1958 {
1959 if (!UpdateVictim())
1960 return;
1961
1962 events.Update(diff);
1964
1965 if (me->HasUnitState(UNIT_STATE_CASTING))
1966 return;
1967
1968 while (uint32 eventId = events.ExecuteEvent())
1969 {
1970 switch (eventId)
1971 {
1973 if (Unit* target = SelectEnemyCaster(true))
1974 DoCast(target, SPELL_EARTH_SHOCK);
1975 events.ScheduleEvent(EVENT_DPS_EARTH_SHOCK, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
1976 return;
1977 case EVENT_LAVA_LASH:
1979 events.ScheduleEvent(EVENT_LAVA_LASH, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
1980 return;
1981 case EVENT_STORMSTRIKE:
1983 events.ScheduleEvent(EVENT_STORMSTRIKE, std::rand() % (10 * IN_MILLISECONDS) + (8 * IN_MILLISECONDS));
1984 return;
1986 if (me->getFaction()) //Am i alliance?
1987 {
1988 if (!me->HasAura(AURA_EXHAUSTION))
1990 }
1991 else
1992 {
1993 if (!me->HasAura(AURA_SATED))
1995 }
1997 return;
1998 case EVENT_DEPLOY_TOTEM:
2000 DeployTotem();
2001 events.ScheduleEvent(EVENT_DEPLOY_TOTEM, 1*IN_MILLISECONDS);
2002 return;
2003 case EVENT_WINDFURY:
2005 events.ScheduleEvent(EVENT_WINDFURY, std::rand() % (60 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
2006 return;
2007 default:
2008 return;
2009 }
2010 }
2011 }
2012 private:
2015 };
2016
2018 {
2019 return new npc_toc_enh_shamanAI(creature);
2020 }
2021};
2022
2024{
2025 public:
2026 npc_toc_retro_paladin() : CreatureScript("npc_toc_retro_paladin") { }
2027
2029 {
2031
2033 {
2035 events.ScheduleEvent(EVENT_AVENGING_WRATH, std::rand() % (35 * IN_MILLISECONDS) + (25 * IN_MILLISECONDS));
2036 events.ScheduleEvent(EVENT_CRUSADER_STRIKE, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
2037 events.ScheduleEvent(EVENT_DIVINE_STORM, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
2038 events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE_RET, std::rand() % (30 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
2039 events.ScheduleEvent(EVENT_JUDGEMENT_OF_COMMAND, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS));
2040 events.ScheduleEvent(EVENT_REPENTANCE, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
2041 events.ScheduleEvent(EVENT_DPS_HAND_OF_PROTECTION, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
2042 events.ScheduleEvent(EVENT_DPS_DIVINE_SHIELD, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS));
2044 }
2045
2051
2053 {
2054 if (!UpdateVictim())
2055 return;
2056
2057 events.Update(diff);
2059
2060 if (me->HasUnitState(UNIT_STATE_CASTING))
2061 return;
2062
2063 while (uint32 eventId = events.ExecuteEvent())
2064 {
2065 switch (eventId)
2066 {
2069 events.ScheduleEvent(EVENT_AVENGING_WRATH, 180*IN_MILLISECONDS);
2070 return;
2073 events.ScheduleEvent(EVENT_CRUSADER_STRIKE, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
2074 return;
2075 case EVENT_DIVINE_STORM:
2076 if (EnemiesInRange(10.0f) >= 2)
2078 events.ScheduleEvent(EVENT_DIVINE_STORM, std::rand() % (20 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
2079 return;
2083 return;
2086 events.ScheduleEvent(EVENT_JUDGEMENT_OF_COMMAND, std::rand() % (15 * IN_MILLISECONDS) + (10 * IN_MILLISECONDS));
2087 return;
2088 case EVENT_REPENTANCE:
2090 DoCast(target, SPELL_REPENTANCE);
2091 events.ScheduleEvent(EVENT_REPENTANCE, 60*IN_MILLISECONDS);
2092 return;
2094 if (Unit* target = DoSelectLowestHpFriendly(30.0f))
2095 {
2096 if (!target->HasAura(SPELL_FORBEARANCE))
2097 {
2100 }
2101 else
2103 }
2104 else
2106 return;
2108 if (HealthBelowPct(30) && !me->HasAura(SPELL_FORBEARANCE))
2109 {
2112 }
2113 else
2115 return;
2116 default:
2117 return;
2118 }
2119 }
2120 }
2121 };
2122
2124 {
2125 return new npc_toc_retro_paladinAI(creature);
2126 }
2127};
2128
2130{
2131 public:
2132 npc_toc_pet_warlock() : CreatureScript("npc_toc_pet_warlock") { }
2133
2135 {
2137
2139 {
2141 events.ScheduleEvent(EVENT_DEVOUR_MAGIC, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
2142 events.ScheduleEvent(EVENT_SPELL_LOCK, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
2143 }
2144
2146 {
2147 if (!UpdateVictim())
2148 return;
2149
2150 events.Update(diff);
2152
2153 if (me->HasUnitState(UNIT_STATE_CASTING))
2154 return;
2155
2156 while (uint32 eventId = events.ExecuteEvent())
2157 {
2158 switch (eventId)
2159 {
2160 case EVENT_DEVOUR_MAGIC:
2162 events.ScheduleEvent(EVENT_DEVOUR_MAGIC, std::rand() % (10 * IN_MILLISECONDS) + (8 * IN_MILLISECONDS));
2163 return;
2164 case EVENT_SPELL_LOCK:
2166 events.ScheduleEvent(EVENT_SPELL_LOCK, std::rand() % (30 * IN_MILLISECONDS) + (24 * IN_MILLISECONDS));
2167 return;
2168 default:
2169 return;
2170 }
2171 }
2172 }
2173 };
2174
2176 {
2177 return new npc_toc_pet_warlockAI(creature);
2178 }
2179};
2180
2182{
2183 public:
2184 npc_toc_pet_hunter() : CreatureScript("npc_toc_pet_hunter") { }
2185
2187 {
2189
2191 {
2193 _clawTimer = std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS);
2194 }
2195
2197 {
2198 if (!UpdateVictim())
2199 return;
2200
2202
2203 if (_clawTimer <= diff)
2204 {
2206 _clawTimer = std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS);
2207 }
2208 else
2209 _clawTimer -= diff;
2210 }
2211 private:
2213 };
2214
2216 {
2217 return new npc_toc_pet_hunterAI(creature);
2218 }
2219};
2220
2222{
2223 public:
2224 spell_faction_champion_warl_unstable_affliction() : SpellScriptLoader("spell_faction_champion_warl_unstable_affliction") { }
2225
2227 {
2229
2230 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
2231 {
2232 if (!sSpellMgr->GetSpellInfo(SPELL_UNSTABLE_AFFLICTION_DISPEL))
2233 return false;
2234 return true;
2235 }
2236
2237 void HandleDispel(DispelInfo* dispelInfo)
2238 {
2239 if (Unit* caster = GetCaster())
2240 caster->CastSpell(dispelInfo->GetDispeller(), SPELL_UNSTABLE_AFFLICTION_DISPEL, true, NULL, GetEffect(EFFECT_0));
2241 }
2242
2247 };
2248
2253};
2254
2256{
2257 public:
2258 spell_faction_champion_death_grip() : SpellScriptLoader("spell_faction_champion_death_grip") { }
2259
2261 {
2263
2264 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
2265 {
2266 if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_GRIP_PULL))
2267 return false;
2268 return true;
2269 }
2270
2271 void HandleDummy(SpellEffIndex /*effIndex*/)
2272 {
2273 if (Unit* target = GetHitUnit())
2274 {
2275 if (Unit* caster = GetCaster())
2276 target->CastSpell(caster, SPELL_DEATH_GRIP_PULL);
2277 }
2278 }
2279
2284 };
2285
2290};
2291
2293{
2294 public:
2295 spell_toc_bloodlust() : SpellScriptLoader("spell_toc_bloodlust") { }
2296
2298 {
2300
2301 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
2302 {
2303 if (!sSpellMgr->GetSpellInfo(AURA_SATED))
2304 return false;
2305 return true;
2306 }
2307
2308 void RemoveInvalidTargets(std::list<WorldObject*>& targets)
2309 {
2310 targets.remove_if(Skyfire::UnitAuraCheck(true, AURA_SATED));
2311 }
2312
2314 {
2315 if (Unit* target = GetHitUnit())
2316 target->CastSpell(target, AURA_SATED, true);
2317 }
2318
2325 };
2326
2328 {
2330 }
2331};
2332
2334{
2335 public:
2336 spell_toc_heroism() : SpellScriptLoader("spell_toc_heroism") { }
2337
2339 {
2341
2342 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
2343 {
2344 if (!sSpellMgr->GetSpellInfo(AURA_EXHAUSTION))
2345 return false;
2346 return true;
2347 }
2348
2349 void RemoveInvalidTargets(std::list<WorldObject*>& targets)
2350 {
2351 targets.remove_if(Skyfire::UnitAuraCheck(true, AURA_EXHAUSTION));
2352 }
2353
2355 {
2356 if (Unit* target = GetHitUnit())
2357 target->CastSpell(target, AURA_EXHAUSTION, true);
2358 }
2359
2366 };
2367
2369 {
2370 return new spell_toc_heroism_SpellScript();
2371 }
2372};
2373
2375{
2377 new npc_toc_druid();
2378 new npc_toc_shaman();
2379 new npc_toc_paladin();
2380 new npc_toc_priest();
2382 new npc_toc_mage();
2383 new npc_toc_warlock();
2384 new npc_toc_hunter();
2385 new npc_toc_boomkin();
2386 new npc_toc_warrior();
2387 new npc_toc_dk();
2388 new npc_toc_rogue();
2389 new npc_toc_enh_shaman();
2391 new npc_toc_pet_warlock();
2392 new npc_toc_pet_hunter();
2393
2396 new spell_toc_bloodlust();
2397 new spell_toc_heroism();
2398}
@ IN_MILLISECONDS
Definition Common.h:125
@ MINUTE
Definition Common.h:119
@ EQUIP_NO_CHANGE
Definition CreatureAI.h:49
@ DIFFICULTY_10MAN_HEROIC
Definition DBCEnums.h:336
@ DIFFICULTY_25MAN_NORMAL
Definition DBCEnums.h:335
@ DIFFICULTY_10MAN_NORMAL
Definition DBCEnums.h:334
@ DIFFICULTY_25MAN_HEROIC
Definition DBCEnums.h:337
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ IN_PROGRESS
@ FAIL
@ DONE
@ SPECIAL
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_MANUAL_DESPAWN
Definition Object.h:75
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ POWER_ENERGY
@ POWER_MANA
@ SPELL_EFFECT_DUMMY
@ TARGET_UNIT_SRC_AREA_ALLY
@ ALLIANCE
@ MECHANIC_IMMUNE_SHIELD
@ SPELL_AURA_MOD_FEAR
@ SPELL_AURA_MOD_PACIFY
@ SPELL_AURA_MOD_ROOT
@ SPELL_AURA_MOD_CONFUSE
@ SPELL_AURA_MOD_STUN
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define SpellHitFn(F)
#define AuraDispelFn(F)
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
@ SPELL_CHARGE
@ SPELL_FROST_NOVA
@ SPELL_FROSTBOLT
@ SPELL_ARCANE_EXPLOSION
@ SPELL_THORNS
Definition boss_buru.cpp:21
@ SPELL_HAMMER_OF_JUSTICE
@ SPELL_ARCANE_BLAST
@ EVENT_ARCANE_BLAST
@ SPELL_MIND_FLAY
@ SPELL_WINDFURY
void AddSC_boss_faction_champions()
@ SPELL_HAMMER_OF_JUSTICE
@ SPELL_ICEBOUND_FORTITUDE
@ SPELL_JUDGEMENT_OF_COMMAND
@ SPELL_VAMPIRIC_TOUCH
@ SPELL_ENTANGLING_ROOTS
@ SPELL_ARCANE_BARRAGE
@ SPELL_SHATTERING_THROW
@ SPELL_UNSTABLE_AFFLICTION
@ SPELL_SUMMON_FELHUNTER
@ SPELL_FLASH_OF_LIGHT
@ SPELL_ARCANE_EXPLOSION
@ SPELL_CRUSADER_STRIKE
@ SPELL_SPIRIT_CLEANSE
@ SPELL_HAMMER_OF_JUSTICE_RET
@ SPELL_DIVINE_SHIELD
@ SPELL_CURSE_OF_AGONY
@ SPELL_FORCE_OF_NATURE
@ SPELL_DEATH_GRIP_PULL
@ SPELL_CURSE_OF_EXHAUSTION
@ SPELL_HAND_OF_FREEDOM
@ SPELL_UNSTABLE_AFFLICTION_DISPEL
@ SPELL_INTIMIDATING_SHOUT
@ SPELL_HAND_OF_PROTECTION
@ SPELL_SEAL_OF_COMMAND
@ SPELL_PSYCHIC_SCREAM
@ EVENT_DPS_DIVINE_SHIELD
@ EVENT_CURSE_OF_EXHAUSTION
@ EVENT_HEAL_HAND_OF_PROTECTION
@ EVENT_HEAL_EARTH_SHOCK
@ EVENT_DPS_PSYCHIC_SCREAM
@ EVENT_HAMMER_OF_JUSTICE
@ EVENT_DPS_HAND_OF_PROTECTION
@ EVENT_HAND_OF_FREEDOM
@ EVENT_FORCE_OF_NATURE
@ EVENT_HAMMER_OF_JUSTICE_RET
@ EVENT_ARCANE_EXPLOSION
@ EVENT_INTIMIDATING_SHOUT
@ EVENT_HEAL_BLOODLUST_HEROISM
@ EVENT_CRUSADER_STRIKE
@ EVENT_HEAL_PSYCHIC_SCREAM
@ EVENT_ICEBOUND_FORTITUDE
@ EVENT_SHATTERING_THROW
@ EVENT_JUDGEMENT_OF_COMMAND
@ EVENT_HEAL_DIVINE_SHIELD
@ EVENT_DPS_EARTH_SHOCK
@ EVENT_UNSTABLE_AFFLICTION
@ EVENT_ENTANGLING_ROOTS
@ EVENT_DPS_BLOODLUST_HEROISM
@ SPELL_MORTAL_STRIKE
@ SPELL_SHADOW_BOLT
@ SPELL_FAN_OF_KNIVES
@ SPELL_EARTH_SHIELD
@ SPELL_DISENGAGE
@ SPELL_BLADESTORM
@ SPELL_MIND_BLAST
@ SPELL_VAMPIRIC_TOUCH
@ SPELL_SHADOWFORM
@ SPELL_CLEANSE
@ SPELL_BLIND
@ SPELL_DISARM
@ SPELL_FEAR
@ EVENT_FEAR
#define SPELL_BLINK
Definition boss_noth.cpp:28
@ SPELL_CYCLONE
@ EVENT_CYCLONE
@ EVENT_SILENCE
@ EVENT_DISARM
@ EVENT_MORTAL_STRIKE
@ SPELL_COUNTERSPELL
@ EVENT_BLINK
@ EVENT_COUNTERSPELL
@ EVENT_ARCANE_EXPLOSION
@ SPELL_EARTH_SHOCK
@ SPELL_HEALING_WAVE
@ EVENT_HEALING_WAVE
@ SPELL_DEATH_COIL
Definition chapter1.cpp:34
@ EVENT_ICY_TOUCH
Definition chapter1.cpp:39
@ SPELL_ICY_TOUCH
Definition chapter1.cpp:31
@ EVENT_DEATH_COIL
Definition chapter1.cpp:42
@ SPELL_REJUVENATION
Definition chapter5.cpp:192
@ SPELL_DEATH_GRIP
Definition chapter5.cpp:137
@ SPELL_WRATH
Definition chapter5.cpp:195
@ SPELL_TRANQUILITY
Definition chapter5.cpp:194
Unit * GetCaster() const
AuraEffect * GetEffect(uint8 effIndex) const
HookList< AuraDispelHandler > AfterDispel
InstanceScript *const instance
SummonList summons
EventMap events
BossAI(Creature *creature, uint32 bossId)
void _EnterCombat()
bool UpdateVictim()
CreatureScript(const char *name)
Unit * GetDispeller() const
Definition Unit.h:840
bool isEmpty() const
Definition LinkedList.h:86
MapRefManager PlayerList
Definition Map.h:406
iterator begin()
TypeID GetTypeId() const
Definition Object.h:131
FROM * GetSource() const
Definition Reference.h:83
HookList< HitHandler > AfterHit
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
Unit * GetCaster()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(const char *name)
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
bool DoSpellAttackIfReady(uint32 spell)
Definition UnitAI.cpp:48
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
Definition Unit.h:1367
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
uint32 GetHealth() const
Definition Unit.h:1600
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
uint32 GetArmor() const
Definition Unit.h:1581
Powers getPowerType() const
Definition Unit.h:1651
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
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
SpellScript * GetSpellScript() const OVERRIDE
void RemoveInvalidTargets(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_toc_bloodlust_SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
PrepareSpellScript(spell_toc_heroism_SpellScript)
void RemoveInvalidTargets(std::list< WorldObject * > &targets)
SpellScript * GetSpellScript() const OVERRIDE
@ SPELL_MANA_BURN
#define SPELL_FLASH_HEAL
bool IsHeroic() const
void SetEquipmentSlots(bool loadDefault, int32 mainHand=EQUIP_NO_CHANGE, int32 offHand=EQUIP_NO_CHANGE, int32 ranged=EQUIP_NO_CHANGE)
void SetCombatMovement(bool allowMovement)
Creature * me
Unit * DoSelectLowestHpFriendly(float range, uint32 minHPDiff=1)
bool HealthBelowPct(uint32 pct) const
std::list< Creature * > DoFindFriendlyMissingBuff(float range, uint32 spellId)
ScriptedAI(Creature *creature)
void DoStartMovement(Unit *target, float distance=0.0f, float angle=0.0f)
Creature * SelectRandomFriendlyMissingBuff(uint32 spell)
void AttackStart(Unit *who) OVERRIDE
float CalculateThreat(float distance, float armor, uint32 health)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
uint32 EnemiesInRange(float distance)
void KilledUnit(Unit *who) OVERRIDE
boss_faction_championsAI(Creature *creature, uint32 aitype)
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 JustSummoned(Creature *summoned) 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 ==================
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 ==================
@ NPC_ALLIANCE_SHAMAN_RESTORATION
@ NPC_ALLIANCE_MAGE
@ NPC_ALLIANCE_PALADIN_HOLY
@ NPC_CHAMPIONS_CONTROLLER
@ NPC_HORDE_SHAMAN_RESTORATION
@ NPC_ALLIANCE_DRUID_RESTORATION
@ NPC_ALLIANCE_DRUID_BALANCE
@ NPC_ALLIANCE_HUNTER
@ NPC_HORDE_ROGUE
@ NPC_HORDE_HUNTER
@ NPC_HORDE_PRIEST_SHADOW
@ NPC_HORDE_WARLOCK
@ NPC_ALLIANCE_ROGUE
@ NPC_HORDE_PALADIN_RETRIBUTION
@ NPC_ALLIANCE_WARRIOR
@ NPC_HORDE_DRUID_RESTORATION
@ NPC_HORDE_DEATH_KNIGHT
@ NPC_ALLIANCE_PALADIN_RETRIBUTION
@ NPC_HORDE_DRUID_BALANCE
@ NPC_HORDE_WARRIOR
@ NPC_HORDE_SHAMAN_ENHANCEMENT
@ NPC_ALLIANCE_PRIEST_DISCIPLINE
@ NPC_HORDE_PRIEST_DISCIPLINE
@ NPC_ALLIANCE_DEATH_KNIGHT
@ NPC_ALLIANCE_SHAMAN_ENHANCEMENT
@ NPC_ALLIANCE_WARLOCK
@ NPC_HORDE_PALADIN_HOLY
@ NPC_ALLIANCE_PRIEST_SHADOW
const Position ToCCommonLoc[]
const Position FactionChampionLoc[]
@ BOSS_CRUSADERS
@ DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE
@ SPELL_ENTANGLING_ROOTS
@ EVENT_ENTANGLING_ROOTS