Advertisement
Guest User

Leo

a guest
Feb 18th, 2011
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 57.95 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify it
  5.  * under the terms of the GNU General Public License as published by the
  6.  * Free Software Foundation; either version 2 of the License, or (at your
  7.  * option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful, but WITHOUT
  10.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11.  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12.  * more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License along
  15.  * with this program. If not, see <http://www.gnu.org/licenses/>.
  16.  */
  17.  
  18. #include "ObjectMgr.h"
  19. #include "ScriptMgr.h"
  20. #include "ScriptedCreature.h"
  21. #include "SpellScript.h"
  22. #include "SpellAuraEffects.h"
  23. #include "icecrown_citadel.h"
  24.  
  25. enum Texts
  26. {
  27.     SAY_AGGRO                           = 0, // You are fools to have come to this place! The icy winds of Northrend will consume your souls!
  28.     SAY_UNCHAINED_MAGIC                 = 1, // Suffer, mortals, as your pathetic magic betrays you!
  29.     EMOTE_WARN_BLISTERING_COLD          = 2, // %s prepares to unleash a wave of blistering cold!
  30.     SAY_BLISTERING_COLD                 = 3, // Can you feel the cold hand of death upon your heart?
  31.     SAY_RESPITE_FOR_A_TORMENTED_SOUL    = 4, // Aaah! It burns! What sorcery is this?!
  32.     SAY_AIR_PHASE                       = 5, // Your incursion ends here! None shall survive!
  33.     SAY_PHASE_2                         = 6, // Now feel my master's limitless power and despair!
  34.     EMOTE_WARN_FROZEN_ORB               = 7, // %s fires a frozen orb towards $N!
  35.     SAY_KILL                            = 8, // Perish!
  36.                                              // A flaw of mortality...
  37.     SAY_BERSERK                         = 9, // Enough! I tire of these games!
  38.     SAY_DEATH                           = 10,// Free...at last...
  39. };
  40.  
  41. enum Spells
  42. {
  43.     // Sindragosa
  44.     SPELL_SINDRAGOSA_S_FURY     = 70608,
  45.     SPELL_TANK_MARKER           = 71039,
  46.     SPELL_FROST_AURA            = 70084,
  47.     SPELL_PERMAEATING_CHILL     = 70109,
  48.     SPELL_CLEAVE                = 19983,
  49.     SPELL_TAIL_SMASH            = 71077,
  50.     SPELL_FROST_BREATH_P1       = 69649,
  51.     SPELL_FROST_BREATH_P2       = 73061,
  52.     SPELL_UNCHAINED_MAGIC       = 69762,
  53.     SPELL_BACKLASH              = 69770,
  54.     SPELL_ICY_GRIP              = 70117,
  55.     SPELL_ICY_GRIP_JUMP         = 70122,
  56.     SPELL_BLISTERING_COLD       = 70123,
  57.     SPELL_FROST_BEACON          = 70126,
  58.     SPELL_ICE_TOMB_TARGET       = 69712,
  59.     SPELL_ICE_TOMB_DUMMY        = 69675,
  60.     SPELL_ICE_TOMB_UNTARGETABLE = 69700,
  61.     SPELL_ICE_TOMB_DAMAGE       = 70157,
  62.     SPELL_ASPHYXIATION          = 71665,
  63.     SPELL_FROST_BOMB_TRIGGER    = 69846,
  64.     SPELL_FROST_BOMB_VISUAL     = 70022,
  65.     SPELL_FROST_BOMB            = 69845,
  66.     SPELL_MYSTIC_BUFFET         = 70128,
  67.  
  68.     // Spinestalker
  69.     SPELL_BELLOWING_ROAR        = 36922,
  70.     SPELL_CLEAVE_SPINESTALKER   = 40505,
  71.     SPELL_TAIL_SWEEP            = 71370,
  72.  
  73.     // Rimefang
  74.     SPELL_FROST_BREATH          = 71386,
  75.     SPELL_FROST_AURA_RIMEFANG   = 71387,
  76.     SPELL_ICY_BLAST             = 71376,
  77.     SPELL_ICY_BLAST_AREA        = 71380,
  78.  
  79.     // Frostwarden Handler
  80.     SPELL_FOCUS_FIRE            = 71350,
  81.     SPELL_ORDER_WHELP           = 71357,
  82.     SPELL_CONCUSSIVE_SHOCK      = 71337,
  83. };
  84.  
  85. enum Events
  86. {
  87.     // Sindragosa
  88.     EVENT_BERSERK                   = 1,
  89.     EVENT_CLEAVE                    = 2,
  90.     EVENT_TAIL_SMASH                = 3,
  91.     EVENT_FROST_BREATH              = 4,
  92.     EVENT_UNCHAINED_MAGIC           = 5,
  93.     EVENT_ICY_GRIP                  = 6,
  94.     EVENT_BLISTERING_COLD           = 7,
  95.     EVENT_BLISTERING_COLD_YELL      = 8,
  96.     EVENT_AIR_PHASE                 = 9,
  97.     EVENT_ICE_TOMB                  = 10,
  98.     EVENT_FROST_BOMB                = 11,
  99.     EVENT_LAND                      = 12,
  100.  
  101.     // Spinestalker
  102.     EVENT_BELLOWING_ROAR            = 13,
  103.     EVENT_CLEAVE_SPINESTALKER       = 14,
  104.     EVENT_TAIL_SWEEP                = 15,
  105.  
  106.     // Rimefang
  107.     EVENT_FROST_BREATH_RIMEFANG     = 16,
  108.     EVENT_ICY_BLAST                 = 17,
  109.     EVENT_ICY_BLAST_CAST            = 18,
  110.  
  111.     // Trash
  112.     EVENT_FROSTWARDEN_ORDER_WHELP   = 19,
  113.     EVENT_CONCUSSIVE_SHOCK          = 20,
  114.  
  115.     // event groups
  116.     EVENT_GROUP_LAND_PHASE          = 1,
  117. };
  118.  
  119. enum FrostwingData
  120. {
  121.     DATA_MYSTIC_BUFFET_STACK    = 0,
  122.     DATA_FROSTWYRM_OWNER        = 1,
  123.     DATA_WHELP_MARKER           = 2,
  124.     DATA_LINKED_GAMEOBJECT      = 3,
  125.     DATA_TRAPPED_PLAYER         = 4,
  126. };
  127.  
  128. enum MovementPoints
  129. {
  130.     POINT_FROSTWYRM_FLY_IN  = 1,
  131.     POINT_FROSTWYRM_LAND    = 2,
  132.     POINT_AIR_PHASE         = 3,
  133.     POINT_LAND              = 4,
  134. };
  135.  
  136. enum Shadowmourne
  137. {
  138.     QUEST_FROST_INFUSION        = 24757,
  139.     ITEM_SHADOW_S_EDGE          = 49888,
  140.  
  141.     SPELL_FROST_INFUSION        = 72292,
  142.     SPELL_FROST_IMBUED_BLADE    = 72290,
  143. };
  144.  
  145. static Position const RimefangFlyPos      = {4413.309f, 2456.421f, 223.3795f, 2.890186f};
  146. static Position const RimefangLandPos     = {4413.309f, 2456.421f, 203.3848f, 2.890186f};
  147. static Position const SpinestalkerFlyPos  = {4418.895f, 2514.233f, 220.4864f, 3.396045f};
  148. static Position const SpinestalkerLandPos = {4418.895f, 2514.233f, 203.3848f, 3.396045f};
  149.        Position const SindragosaSpawnPos  = {4818.700f, 2483.710f, 287.0650f, 3.089233f};
  150. static Position const SindragosaFlyPos    = {4475.190f, 2484.570f, 234.8510f, 3.141593f};
  151. static Position const SindragosaLandPos   = {4419.190f, 2484.570f, 203.3848f, 3.141593f};
  152. static Position const SindragosaAirPos    = {4475.990f, 2484.430f, 247.9340f, 3.141593f};
  153.  
  154. class FrostwyrmLandEvent : public BasicEvent
  155. {
  156.     public:
  157.         FrostwyrmLandEvent(Creature& _owner, Position const& _dest) : owner(_owner), dest(_dest) { }
  158.  
  159.         bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
  160.         {
  161.             owner.GetMotionMaster()->MovePoint(POINT_FROSTWYRM_LAND, dest);
  162.             return true;
  163.         }
  164.  
  165.         Creature& owner;
  166.         Position const& dest;
  167. };
  168.  
  169. class boss_sindragosa : public CreatureScript
  170. {
  171.     public:
  172.         boss_sindragosa() : CreatureScript("boss_sindragosa") { }
  173.  
  174.         struct boss_sindragosaAI : public BossAI
  175.         {
  176.             boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA)
  177.             {
  178.             }
  179.  
  180.             void InitializeAI()
  181.             {
  182.                 if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
  183.                     me->IsAIEnabled = false;
  184.                 else if (!me->isDead())
  185.                     Reset();
  186.             }
  187.  
  188.             void Reset()
  189.             {
  190.                 BossAI::Reset();
  191.                 me->SetReactState(REACT_DEFENSIVE);
  192.                 DoCast(me, SPELL_TANK_MARKER, true);
  193.                 events.ScheduleEvent(EVENT_BERSERK, 600000);
  194.                 events.ScheduleEvent(EVENT_CLEAVE, 10000, EVENT_GROUP_LAND_PHASE);
  195.                 events.ScheduleEvent(EVENT_TAIL_SMASH, 20000, EVENT_GROUP_LAND_PHASE);
  196.                 events.ScheduleEvent(EVENT_FROST_BREATH, urand(8000, 12000), EVENT_GROUP_LAND_PHASE);
  197.                 events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(9000, 14000), EVENT_GROUP_LAND_PHASE);
  198.                 events.ScheduleEvent(EVENT_ICY_GRIP, 33500, EVENT_GROUP_LAND_PHASE);
  199.                 events.ScheduleEvent(EVENT_AIR_PHASE, 50000);
  200.                 mysticBuffetStack = 0;
  201.                 isThirdPhase = false;
  202.  
  203.                 if (instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) != 255)
  204.                 {
  205.                     me->SetFlying(true);
  206.                     me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  207.                 }
  208.             }
  209.  
  210.             void JustDied(Unit* killer)
  211.             {
  212.                 BossAI::JustDied(killer);
  213.                 Talk(SAY_DEATH);
  214.             }
  215.  
  216.             void EnterCombat(Unit* victim)
  217.             {
  218.                 if (!instance->CheckRequiredBosses(DATA_SINDRAGOSA, victim->ToPlayer()))
  219.                 {
  220.                     EnterEvadeMode();
  221.                     instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
  222.                     return;
  223.                 }
  224.  
  225.                 BossAI::EnterCombat(victim);
  226.                 DoCast(me, SPELL_FROST_AURA);
  227.                 DoCast(me, SPELL_PERMAEATING_CHILL);
  228.                 Talk(SAY_AGGRO);
  229.             }
  230.  
  231.             void JustReachedHome()
  232.             {
  233.                 BossAI::JustReachedHome();
  234.                 instance->SetBossState(DATA_SINDRAGOSA, FAIL);
  235.                 me->SetFlying(false);
  236.                 me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  237.             }
  238.  
  239.             void KilledUnit(Unit* victim)
  240.             {
  241.                 if (victim->GetTypeId() == TYPEID_PLAYER)
  242.                     Talk(SAY_KILL);
  243.             }
  244.  
  245.             void DoAction(const int32 action)
  246.             {
  247.                 if (action == ACTION_START_FROSTWYRM)
  248.                 {
  249.                     instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 255);
  250.                     if (me->isDead())
  251.                         return;
  252.                     me->SetSpeed(MOVE_FLIGHT, 4.0f);
  253.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  254.                     float moveTime = me->GetExactDist(&SindragosaFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
  255.                     me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
  256.                     me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SindragosaFlyPos);
  257.                     DoCast(me, SPELL_SINDRAGOSA_S_FURY);
  258.                 }
  259.             }
  260.  
  261.             uint32 GetData(uint32 type)
  262.             {
  263.                 if (type == DATA_MYSTIC_BUFFET_STACK)
  264.                     return mysticBuffetStack;
  265.                 return 0xFFFFFFFF;
  266.             }
  267.  
  268.             void MovementInform(uint32 type, uint32 point)
  269.             {
  270.                 if (type != POINT_MOTION_TYPE)
  271.                     return;
  272.  
  273.                 switch (point)
  274.                 {
  275.                     case POINT_FROSTWYRM_LAND:
  276.                         me->setActive(false);
  277.                         me->SetFlying(false);
  278.                         me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  279.                         me->SetHomePosition(SindragosaLandPos);
  280.                         me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  281.                         me->SetSpeed(MOVE_FLIGHT, 2.0f);
  282.  
  283.                         // Sindragosa enters combat as soon as she lands
  284.                         DoZoneInCombat();
  285.                         break;
  286.                     case POINT_AIR_PHASE:
  287.                         me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 3, 6), false);
  288.                         events.ScheduleEvent(EVENT_FROST_BOMB, 8000);
  289.                         break;
  290.                     case POINT_LAND:
  291.                         me->SetFlying(false);
  292.                         me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  293.                         me->SetReactState(REACT_DEFENSIVE);
  294.                         if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
  295.                             me->GetMotionMaster()->MovementExpired();
  296.                         DoStartMovement(me->getVictim());
  297.                         // trigger Asphyxiation
  298.                         summons.DoAction(NPC_ICE_TOMB, ACTION_TRIGGER_ASPHYXIATION);
  299.                         break;
  300.                     default:
  301.                         break;
  302.                 }
  303.             }
  304.  
  305.             void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/)
  306.             {
  307.                 if (!isThirdPhase && !HealthAbovePct(35))
  308.                 {
  309.                     Talk(SAY_PHASE_2);
  310.                     events.CancelEvent(EVENT_AIR_PHASE);
  311.                     events.ScheduleEvent(EVENT_ICE_TOMB, urand(7000, 10000));
  312.                     events.RescheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000));
  313.                     DoCast(me, SPELL_MYSTIC_BUFFET, true);
  314.                     isThirdPhase = true;
  315.                 }
  316.             }
  317.  
  318.             void JustSummoned(Creature* summon)
  319.             {
  320.                 summons.Summon(summon);
  321.             }
  322.  
  323.             void SummonedCreatureDespawn(Creature* summon)
  324.             {
  325.                 BossAI::SummonedCreatureDespawn(summon);
  326.                 if (summon->GetEntry() == NPC_ICE_TOMB)
  327.                     summon->AI()->JustDied(summon);
  328.             }
  329.  
  330.             void SpellHitTarget(Unit* target, SpellEntry const* spell)
  331.             {
  332.                 if (SpellEntry const* buffet = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(70127), me))
  333.                     if (buffet->Id == spell->Id)
  334.                         if (Aura const* mysticBuffet = target->GetAura(spell->Id))
  335.                             mysticBuffetStack = std::max<uint8>(mysticBuffetStack, mysticBuffet->GetStackAmount());
  336.  
  337.                 // Frost Infusion
  338.                 if (Player* player = target->ToPlayer())
  339.                 {
  340.                     if (SpellEntry const* breath = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1), me))
  341.                     {
  342.                         if (player->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_REWARDED && breath->Id == spell->Id)
  343.                         {
  344.                             if (Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true))
  345.                             {
  346.                                 if (!player->HasAura(SPELL_FROST_IMBUED_BLADE) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE)
  347.                                 {
  348.                                     if (Aura* infusion = player->GetAura(SPELL_FROST_INFUSION))
  349.                                     {
  350.                                         if (infusion->GetStackAmount() == 3)
  351.                                         {
  352.                                             player->CastSpell(player, SPELL_FROST_IMBUED_BLADE, true);
  353.                                             player->RemoveAura(infusion);
  354.                                         }
  355.                                         else
  356.                                             player->CastSpell(player, SPELL_FROST_INFUSION, true);
  357.                                     }
  358.                                     else
  359.                                         player->CastSpell(player, SPELL_FROST_INFUSION, true);
  360.                                 }
  361.                             }
  362.                         }
  363.                     }
  364.                 }
  365.  
  366.                 if (spell->Id == SPELL_FROST_BOMB_TRIGGER)
  367.                 {
  368.                     target->CastSpell(target, SPELL_FROST_BOMB, true);
  369.                     target->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
  370.                 }
  371.             }
  372.  
  373.             void UpdateAI(const uint32 diff)
  374.             {
  375.                 if (!UpdateVictim() || !CheckInRoom())
  376.                     return;
  377.  
  378.                 events.Update(diff);
  379.  
  380.                 if (me->HasUnitState(UNIT_STAT_CASTING))
  381.                     return;
  382.  
  383.                 while (uint32 eventId = events.ExecuteEvent())
  384.                 {
  385.                     switch (eventId)
  386.                     {
  387.                         case EVENT_BERSERK:
  388.                             DoScriptText(EMOTE_GENERIC_BERSERK_RAID, me);
  389.                             Talk(SAY_BERSERK);
  390.                             DoCast(me, SPELL_BERSERK);
  391.                             break;
  392.                         case EVENT_CLEAVE:
  393.                             DoCastVictim(SPELL_CLEAVE);
  394.                             events.ScheduleEvent(EVENT_CLEAVE, urand(15000, 20000), EVENT_GROUP_LAND_PHASE);
  395.                             break;
  396.                         case EVENT_TAIL_SMASH:
  397.                             DoCast(me, SPELL_TAIL_SMASH);
  398.                             events.ScheduleEvent(EVENT_TAIL_SMASH, urand(27000, 32000), EVENT_GROUP_LAND_PHASE);
  399.                             break;
  400.                         case EVENT_FROST_BREATH:
  401.                             DoCastVictim(isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1);
  402.                             events.ScheduleEvent(EVENT_FROST_BREATH, urand(20000, 25000), EVENT_GROUP_LAND_PHASE);
  403.                             break;
  404.                         case EVENT_UNCHAINED_MAGIC:
  405.                             Talk(SAY_UNCHAINED_MAGIC);
  406.                             DoCast(me, SPELL_UNCHAINED_MAGIC);
  407.                             events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(30000, 35000), EVENT_GROUP_LAND_PHASE);
  408.                             break;
  409.                         case EVENT_ICY_GRIP:
  410.                             DoCast(me, SPELL_ICY_GRIP);
  411.                             events.ScheduleEvent(EVENT_ICY_GRIP, urand(70000, 75000), EVENT_GROUP_LAND_PHASE);
  412.                             events.ScheduleEvent(EVENT_BLISTERING_COLD, 1000, EVENT_GROUP_LAND_PHASE);
  413.                             break;
  414.                         case EVENT_BLISTERING_COLD:
  415.                             Talk(EMOTE_WARN_BLISTERING_COLD);
  416.                             DoCast(me, SPELL_BLISTERING_COLD);
  417.                             events.ScheduleEvent(EVENT_BLISTERING_COLD_YELL, 5000, EVENT_GROUP_LAND_PHASE);
  418.                             break;
  419.                         case EVENT_BLISTERING_COLD_YELL:
  420.                             Talk(SAY_BLISTERING_COLD);
  421.                             break;
  422.                         case EVENT_AIR_PHASE:
  423.                             Talk(SAY_AIR_PHASE);
  424.                             me->SetFlying(true);
  425.                             me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  426.                             me->SetReactState(REACT_PASSIVE);
  427.                             me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE, SindragosaAirPos);
  428.                             events.DelayEvents(45000, EVENT_GROUP_LAND_PHASE);
  429.                             events.ScheduleEvent(EVENT_AIR_PHASE, 110000);
  430.                             events.RescheduleEvent(EVENT_UNCHAINED_MAGIC, urand(55000, 60000), EVENT_GROUP_LAND_PHASE);
  431.                             events.ScheduleEvent(EVENT_LAND, 45000);
  432.                             break;
  433.                         case EVENT_ICE_TOMB:
  434.                             if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_ICE_TOMB_UNTARGETABLE))
  435.                             {
  436.                                 Talk(EMOTE_WARN_FROZEN_ORB, target->GetGUID());
  437.                                 DoCast(target, SPELL_ICE_TOMB_DUMMY, true);
  438.                             }
  439.                             events.ScheduleEvent(EVENT_ICE_TOMB, urand(16000, 23000));
  440.                             break;
  441.                         case EVENT_FROST_BOMB:
  442.                         {
  443.                             float destX, destY, destZ;
  444.                             destX = float(rand_norm()) * 117.25f + 4339.25f;
  445.                             if (destX > 4371.5f && destX < 4432.0f)
  446.                                 destY = float(rand_norm()) * 111.0f + 2429.0f;
  447.                             else
  448.                                 destY = float(rand_norm()) * 31.23f + 2454.64f;
  449.                             destZ = 205.0f; // random number close to ground, get exact in next call
  450.                             me->UpdateGroundPositionZ(destX, destY, destZ);
  451.                             Position pos;
  452.                             pos.Relocate(destX, destY, destZ);
  453.                             if (TempSummon* summ = me->SummonCreature(NPC_FROST_BOMB, pos, TEMPSUMMON_TIMED_DESPAWN, 40000))
  454.                             {
  455.                                 summ->CastSpell(summ, SPELL_FROST_BOMB_VISUAL, true);
  456.                                 DoCast(summ, SPELL_FROST_BOMB_TRIGGER);
  457.                                 //me->CastSpell(destX, destY, destZ, SPELL_FROST_BOMB_TRIGGER, false);
  458.                             }
  459.                             events.ScheduleEvent(EVENT_FROST_BOMB, urand(5000, 10000));
  460.                             break;
  461.                         }
  462.                         case EVENT_LAND:
  463.                         {
  464.                             events.CancelEvent(EVENT_FROST_BOMB);
  465.                             me->GetMotionMaster()->MovePoint(POINT_LAND, SindragosaLandPos);
  466.                             break;
  467.                         }
  468.                         default:
  469.                             break;
  470.                     }
  471.                 }
  472.  
  473.                 DoMeleeAttackIfReady();
  474.             }
  475.  
  476.         private:
  477.             uint8 mysticBuffetStack;
  478.             bool isThirdPhase;
  479.         };
  480.  
  481.         CreatureAI* GetAI(Creature* creature) const
  482.         {
  483.             return new boss_sindragosaAI(creature);
  484.         }
  485. };
  486.  
  487. class npc_ice_tomb : public CreatureScript
  488. {
  489.     public:
  490.         npc_ice_tomb() : CreatureScript("npc_ice_tomb") { }
  491.  
  492.         struct npc_ice_tombAI : public Scripted_NoMovementAI
  493.         {
  494.             npc_ice_tombAI(Creature* creature) : Scripted_NoMovementAI(creature)
  495.             {
  496.                 trappedPlayer = 0;
  497.             }
  498.  
  499.             void Reset()
  500.             {
  501.                 me->SetReactState(REACT_PASSIVE);
  502.             }
  503.  
  504.             void SetGUID(const uint64& guid, int32 type/* = 0 */)
  505.             {
  506.                 if (type == DATA_TRAPPED_PLAYER)
  507.                 {
  508.                     trappedPlayer = guid;
  509.                     existenceCheckTimer = 1000;
  510.                 }
  511.             }
  512.  
  513.             void DoAction(const int32 action)
  514.             {
  515.                 if (action == ACTION_TRIGGER_ASPHYXIATION)
  516.                     if (Player* player = ObjectAccessor::GetPlayer(*me, trappedPlayer))
  517.                         player->CastSpell(player, SPELL_ASPHYXIATION, true);
  518.             }
  519.  
  520.             void JustDied(Unit* /*killer*/)
  521.             {
  522.                 me->RemoveAllGameObjects();
  523.  
  524.                 if (Player* player = ObjectAccessor::GetPlayer(*me, trappedPlayer))
  525.                 {
  526.                     trappedPlayer = 0;
  527.                     player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE);
  528.                     player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION);
  529.                 }
  530.             }
  531.  
  532.             void UpdateAI(const uint32 diff)
  533.             {
  534.                 if (!trappedPlayer)
  535.                     return;
  536.  
  537.                 if (existenceCheckTimer <= diff)
  538.                 {
  539.                     Player* player = ObjectAccessor::GetPlayer(*me, trappedPlayer);
  540.                     if (!player || player->isDead() || !player->HasAura(SPELL_ICE_TOMB_DAMAGE))
  541.                     {
  542.                         // Remove object
  543.                         JustDied(me);
  544.                         me->DespawnOrUnsummon();
  545.                         return;
  546.                     }
  547.                     existenceCheckTimer = 1000;
  548.                 }
  549.                 else
  550.                     existenceCheckTimer -= diff;
  551.             }
  552.  
  553.         private:
  554.             uint64 trappedPlayer;
  555.             uint32 existenceCheckTimer;
  556.         };
  557.  
  558.         CreatureAI* GetAI(Creature* creature) const
  559.         {
  560.             return new npc_ice_tombAI(creature);
  561.         }
  562. };
  563.  
  564. class npc_spinestalker : public CreatureScript
  565. {
  566.     public:
  567.         npc_spinestalker() : CreatureScript("npc_spinestalker") { }
  568.  
  569.         struct npc_spinestalkerAI : public ScriptedAI
  570.         {
  571.             npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript())
  572.             {
  573.             }
  574.  
  575.             void InitializeAI()
  576.             {
  577.                 if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
  578.                     me->IsAIEnabled = false;
  579.                 else if (!me->isDead())
  580.                     Reset();
  581.             }
  582.  
  583.             void Reset()
  584.             {
  585.                 events.Reset();
  586.                 events.ScheduleEvent(EVENT_BELLOWING_ROAR, urand(20000, 25000));
  587.                 events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, urand(10000, 15000));
  588.                 events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(8000, 12000));
  589.                 me->SetReactState(REACT_DEFENSIVE);
  590.  
  591.                 if (instance->GetData(DATA_SPINESTALKER) != 255)
  592.                 {
  593.                     me->SetFlying(true);
  594.                     me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  595.                 }
  596.             }
  597.  
  598.             void JustRespawned()
  599.             {
  600.                 ScriptedAI::JustRespawned();
  601.                 instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1);  // this cannot be in Reset because reset also happens on evade
  602.             }
  603.  
  604.             void JustDied(Unit* /*killer*/)
  605.             {
  606.                 events.Reset();
  607.                 instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0);
  608.             }
  609.  
  610.             void DoAction(const int32 action)
  611.             {
  612.                 if (action == ACTION_START_FROSTWYRM)
  613.                 {
  614.                     instance->SetData(DATA_SPINESTALKER, 255);
  615.                     if (me->isDead())
  616.                         return;
  617.                     me->SetSpeed(MOVE_FLIGHT, 2.0f);
  618.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  619.                     float moveTime = me->GetExactDist(&SpinestalkerFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
  620.                     me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
  621.                     me->SetDefaultMovementType(IDLE_MOTION_TYPE);
  622.                     me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE);
  623.                     me->StopMoving();
  624.                     me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos);
  625.                 }
  626.             }
  627.  
  628.             void MovementInform(uint32 type, uint32 point)
  629.             {
  630.                 if (type != POINT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND)
  631.                     return;
  632.  
  633.                 me->SetFlying(false);
  634.                 me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  635.                 me->SetHomePosition(SpinestalkerLandPos);
  636.                 me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  637.             }
  638.  
  639.             void UpdateAI(const uint32 diff)
  640.             {
  641.                 if (!UpdateVictim())
  642.                     return;
  643.  
  644.                 events.Update(diff);
  645.  
  646.                 if (me->HasUnitState(UNIT_STAT_CASTING))
  647.                     return;
  648.  
  649.                 while (uint32 eventId = events.ExecuteEvent())
  650.                 {
  651.                     switch (eventId)
  652.                     {
  653.                         case EVENT_BELLOWING_ROAR:
  654.                             DoCast(me, SPELL_BELLOWING_ROAR);
  655.                             events.ScheduleEvent(EVENT_BELLOWING_ROAR, urand(25000, 30000));
  656.                             break;
  657.                         case EVENT_CLEAVE_SPINESTALKER:
  658.                             DoCastVictim(SPELL_CLEAVE_SPINESTALKER);
  659.                             events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, urand(10000, 15000));
  660.                             break;
  661.                         case EVENT_TAIL_SWEEP:
  662.                             DoCast(me, SPELL_TAIL_SWEEP);
  663.                             events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(22000, 25000));
  664.                             break;
  665.                         default:
  666.                             break;
  667.                     }
  668.                 }
  669.  
  670.                 DoMeleeAttackIfReady();
  671.             }
  672.  
  673.         private:
  674.             EventMap events;
  675.             InstanceScript* instance;
  676.         };
  677.  
  678.         CreatureAI* GetAI(Creature* creature) const
  679.         {
  680.             return new npc_spinestalkerAI(creature);
  681.         }
  682. };
  683.  
  684. class npc_rimefang : public CreatureScript
  685. {
  686.     public:
  687.         npc_rimefang() : CreatureScript("npc_rimefang_icc") { }
  688.  
  689.         struct npc_rimefangAI : public ScriptedAI
  690.         {
  691.             npc_rimefangAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript())
  692.             {
  693.             }
  694.  
  695.             void InitializeAI()
  696.             {
  697.                 if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
  698.                     me->IsAIEnabled = false;
  699.                 else if (!me->isDead())
  700.                     Reset();
  701.             }
  702.  
  703.             void Reset()
  704.             {
  705.                 events.Reset();
  706.                 events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, urand(12000, 15000));
  707.                 events.ScheduleEvent(EVENT_ICY_BLAST, urand(30000, 35000));
  708.                 me->SetReactState(REACT_DEFENSIVE);
  709.                 icyBlastCounter = 0;
  710.  
  711.                 if (instance->GetData(DATA_RIMEFANG) != 255)
  712.                 {
  713.                     me->SetFlying(true);
  714.                     me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  715.                 }
  716.             }
  717.  
  718.             void JustRespawned()
  719.             {
  720.                 ScriptedAI::JustRespawned();
  721.                 instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1);  // this cannot be in Reset because reset also happens on evade
  722.             }
  723.  
  724.             void JustDied(Unit* /*killer*/)
  725.             {
  726.                 events.Reset();
  727.                 instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0);
  728.             }
  729.  
  730.             void DoAction(const int32 action)
  731.             {
  732.                 if (action == ACTION_START_FROSTWYRM)
  733.                 {
  734.                     instance->SetData(DATA_RIMEFANG, 255);
  735.                     if (me->isDead())
  736.                         return;
  737.                     me->SetSpeed(MOVE_FLIGHT, 2.0f);
  738.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
  739.                     float moveTime = me->GetExactDist(&RimefangFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
  740.                     me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
  741.                     me->SetDefaultMovementType(IDLE_MOTION_TYPE);
  742.                     me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE);
  743.                     me->StopMoving();
  744.                     me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos);
  745.                 }
  746.             }
  747.  
  748.             void MovementInform(uint32 type, uint32 point)
  749.             {
  750.                 if (type != POINT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND)
  751.                     return;
  752.  
  753.                 me->SetFlying(false);
  754.                 me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
  755.                 me->SetHomePosition(RimefangLandPos);
  756.                 me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
  757.             }
  758.  
  759.             void EnterCombat(Unit* /*victim*/)
  760.             {
  761.                 DoCast(me, SPELL_FROST_AURA_RIMEFANG, true);
  762.             }
  763.  
  764.             void UpdateAI(const uint32 diff)
  765.             {
  766.                 if (!UpdateVictim())
  767.                     return;
  768.  
  769.                 events.Update(diff);
  770.  
  771.                 if (me->HasUnitState(UNIT_STAT_CASTING))
  772.                     return;
  773.  
  774.                 while (uint32 eventId = events.ExecuteEvent())
  775.                 {
  776.                     switch (eventId)
  777.                     {
  778.                         case EVENT_FROST_BREATH_RIMEFANG:
  779.                             DoCast(me, SPELL_FROST_BREATH);
  780.                             events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, urand(35000, 40000));
  781.                             break;
  782.                         case EVENT_ICY_BLAST:
  783.                         {
  784.                             icyBlastCounter = RAID_MODE<uint32>(5, 7, 6, 8);
  785.                             me->SetReactState(REACT_PASSIVE);
  786.                             me->AttackStop();
  787.                             me->SetFlying(true);
  788.                             me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos);
  789.                             float moveTime = me->GetExactDist(&RimefangFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
  790.                             events.ScheduleEvent(EVENT_ICY_BLAST, uint64(moveTime) + urand(60000, 70000));
  791.                             events.ScheduleEvent(EVENT_ICY_BLAST_CAST, uint64(moveTime) + 250);
  792.                             break;
  793.                         }
  794.                         case EVENT_ICY_BLAST_CAST:
  795.                             if (--icyBlastCounter)
  796.                             {
  797.                                 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
  798.                                 {
  799.                                     me->SetFacingToObject(target);
  800.                                     DoCast(target, SPELL_ICY_BLAST);
  801.                                 }
  802.                                 events.ScheduleEvent(EVENT_ICY_BLAST_CAST, 3000);
  803.                             }
  804.                             else if (Unit *victim = me->SelectVictim())
  805.                             {
  806.                                 me->SetReactState(REACT_DEFENSIVE);
  807.                                 AttackStart(victim);
  808.                                 me->SetFlying(false);
  809.                             }
  810.                             break;
  811.                         default:
  812.                             break;
  813.                     }
  814.                 }
  815.  
  816.                 DoMeleeAttackIfReady();
  817.             }
  818.  
  819.         private:
  820.             EventMap events;
  821.             InstanceScript* instance;
  822.             uint8 icyBlastCounter;
  823.         };
  824.  
  825.         CreatureAI* GetAI(Creature* creature) const
  826.         {
  827.             return new npc_rimefangAI(creature);
  828.         }
  829. };
  830.  
  831. class npc_sindragosa_trash : public CreatureScript
  832. {
  833.     public:
  834.         npc_sindragosa_trash() : CreatureScript("npc_sindragosa_trash") { }
  835.  
  836.         struct npc_sindragosa_trashAI : public ScriptedAI
  837.         {
  838.             npc_sindragosa_trashAI(Creature* creature) : ScriptedAI(creature)
  839.             {
  840.                 frostwyrmId = (creature->GetHomePosition().GetPositionY() < 2484.35f) ? DATA_RIMEFANG : DATA_SPINESTALKER;
  841.                 instance = creature->GetInstanceScript();
  842.             }
  843.  
  844.             void InitializeAI()
  845.             {
  846.                 // Increase add count
  847.                 if (!me->isDead() && instance)
  848.                     instance->SetData(frostwyrmId, 1);  // this cannot be in Reset because reset also happens on evade
  849.             }
  850.  
  851.             void Reset()
  852.             {
  853.                 // This is shared AI for handler and whelps
  854.                 if (me->GetEntry() == NPC_FROSTWARDEN_HANDLER)
  855.                 {
  856.                     events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3000);
  857.                     events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, urand(8000, 10000));
  858.                 }
  859.  
  860.                 isTaunted = false;
  861.             }
  862.  
  863.             void JustRespawned()
  864.             {
  865.                 ScriptedAI::JustRespawned();
  866.  
  867.                 // Increase add count
  868.                 if (instance)
  869.                     instance->SetData(frostwyrmId, 1);  // this cannot be in Reset because reset also happens on evade
  870.             }
  871.  
  872.             void JustDied(Unit* /*killer*/)
  873.             {
  874.                 // Decrease add count
  875.                 if (instance)
  876.                     instance->SetData(frostwyrmId, 0);
  877.             }
  878.  
  879.             void SetData(uint32 type, uint32 data)
  880.             {
  881.                 if (type == DATA_WHELP_MARKER)
  882.                     isTaunted = data != 0;
  883.             }
  884.  
  885.             uint32 GetData(uint32 type)
  886.             {
  887.                 if (type == DATA_FROSTWYRM_OWNER)
  888.                     return frostwyrmId;
  889.                 else if (type == DATA_WHELP_MARKER)
  890.                     return uint32(isTaunted);
  891.                 return 0;
  892.             }
  893.  
  894.             void UpdateAI(const uint32 diff)
  895.             {
  896.                 if (!UpdateVictim())
  897.                     return;
  898.  
  899.                 events.Update(diff);
  900.  
  901.                 if (me->HasUnitState(UNIT_STAT_CASTING))
  902.                     return;
  903.  
  904.                 while (uint32 eventId = events.ExecuteEvent())
  905.                 {
  906.                     switch (eventId)
  907.                     {
  908.                         case EVENT_FROSTWARDEN_ORDER_WHELP:
  909.                             DoCast(me, SPELL_ORDER_WHELP);
  910.                             events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3000);
  911.                             break;
  912.                         case EVENT_CONCUSSIVE_SHOCK:
  913.                             DoCast(me, SPELL_CONCUSSIVE_SHOCK);
  914.                             events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, urand(10000, 13000));
  915.                             break;
  916.                         default:
  917.                             break;
  918.                     }
  919.                 }
  920.  
  921.                 DoMeleeAttackIfReady();
  922.             }
  923.  
  924.         private:
  925.             InstanceScript* instance;
  926.             EventMap events;
  927.             uint32 frostwyrmId;
  928.             bool isTaunted; // Frostwing Whelp only
  929.         };
  930.  
  931.         CreatureAI* GetAI(Creature* creature) const
  932.         {
  933.             return new npc_sindragosa_trashAI(creature);
  934.         }
  935. };
  936.  
  937. class spell_sindragosa_s_fury : public SpellScriptLoader
  938. {
  939.     public:
  940.         spell_sindragosa_s_fury() : SpellScriptLoader("spell_sindragosa_s_fury") { }
  941.  
  942.         class spell_sindragosa_s_fury_SpellScript : public SpellScript
  943.         {
  944.             PrepareSpellScript(spell_sindragosa_s_fury_SpellScript);
  945.  
  946.             bool Load()
  947.             {
  948.                 targetCount = 0;
  949.                 return true;
  950.             }
  951.  
  952.             void CountTargets(std::list<Unit*>& unitList)
  953.             {
  954.                 targetCount = unitList.size();
  955.             }
  956.  
  957.             void HandleDummy(SpellEffIndex effIndex)
  958.             {
  959.                 PreventHitDefaultEffect(effIndex);
  960.  
  961.                 if (!GetHitUnit()->isAlive())
  962.                     return;
  963.  
  964.                 float resistance = float(GetHitUnit()->GetResistance(GetFirstSchoolInMask(SpellSchoolMask(GetSpellInfo()->SchoolMask))));
  965.                 uint32 minResistFactor = uint32((resistance / (resistance + 510.0f))* 10.0f) * 2;
  966.                 uint32 randomResist = urand(0, (9 - minResistFactor) * 100)/100 + minResistFactor;
  967.  
  968.                 uint32 damage = (uint32(GetEffectValue()/targetCount) * randomResist) / 10;
  969.  
  970.                 SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo()->Id, GetSpellInfo()->SchoolMask);
  971.                 damageInfo.damage = damage;
  972.                 GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo);
  973.                 GetCaster()->DealSpellDamage(&damageInfo, false);
  974.             }
  975.  
  976.             void Register()
  977.             {
  978.                 OnEffect += SpellEffectFn(spell_sindragosa_s_fury_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
  979.                 OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_s_fury_SpellScript::CountTargets, EFFECT_1, TARGET_UNIT_AREA_ENTRY_DST);
  980.             }
  981.  
  982.             uint32 targetCount;
  983.         };
  984.  
  985.         SpellScript* GetSpellScript() const
  986.         {
  987.             return new spell_sindragosa_s_fury_SpellScript();
  988.         }
  989. };
  990.  
  991. class UnchainedMagicTargetSelector
  992. {
  993.     public:
  994.         UnchainedMagicTargetSelector() { }
  995.  
  996.         bool operator()(Unit* unit)
  997.         {
  998.             return unit->getPowerType() != POWER_MANA;
  999.         }
  1000. };
  1001.  
  1002. class spell_sindragosa_unchained_magic : public SpellScriptLoader
  1003. {
  1004.     public:
  1005.         spell_sindragosa_unchained_magic() : SpellScriptLoader("spell_sindragosa_unchained_magic") { }
  1006.  
  1007.         class spell_sindragosa_unchained_magic_SpellScript : public SpellScript
  1008.         {
  1009.             PrepareSpellScript(spell_sindragosa_unchained_magic_SpellScript);
  1010.  
  1011.             void FilterTargets(std::list<Unit*>& unitList)
  1012.             {
  1013.                 unitList.remove_if(UnchainedMagicTargetSelector());
  1014.                 uint32 maxSize = GetCaster()->GetMap()->GetSpawnMode() & 1 ? 5 : 2;
  1015.                 if (unitList.size() > maxSize)
  1016.                     Trinity::RandomResizeList(unitList, maxSize);
  1017.             }
  1018.  
  1019.             void Register()
  1020.             {
  1021.                 OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC);
  1022.             }
  1023.         };
  1024.  
  1025.         SpellScript* GetSpellScript() const
  1026.         {
  1027.             return new spell_sindragosa_unchained_magic_SpellScript();
  1028.         }
  1029. };
  1030.  
  1031. class spell_sindragosa_instability : public SpellScriptLoader
  1032. {
  1033.     public:
  1034.         spell_sindragosa_instability() : SpellScriptLoader("spell_sindragosa_instability") { }
  1035.  
  1036.         class spell_sindragosa_instability_AuraScript : public AuraScript
  1037.         {
  1038.             PrepareAuraScript(spell_sindragosa_instability_AuraScript);
  1039.  
  1040.             bool Validate(SpellEntry const* /*spell*/)
  1041.             {
  1042.                 if (!sSpellStore.LookupEntry(SPELL_BACKLASH))
  1043.                     return false;
  1044.                 return true;
  1045.             }
  1046.  
  1047.             void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
  1048.             {
  1049.                 PreventDefaultAction();
  1050.                 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
  1051.                     GetTarget()->CastCustomSpell(SPELL_BACKLASH, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff, GetCasterGUID());
  1052.             }
  1053.  
  1054.             void Register()
  1055.             {
  1056.                 OnEffectRemove += AuraEffectRemoveFn(spell_sindragosa_instability_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
  1057.             }
  1058.         };
  1059.  
  1060.         AuraScript* GetAuraScript() const
  1061.         {
  1062.             return new spell_sindragosa_instability_AuraScript();
  1063.         }
  1064. };
  1065.  
  1066. class spell_sindragosa_frost_beacon : public SpellScriptLoader
  1067. {
  1068.     public:
  1069.         spell_sindragosa_frost_beacon() : SpellScriptLoader("spell_sindragosa_frost_beacon") { }
  1070.  
  1071.         class spell_sindragosa_frost_beacon_AuraScript : public AuraScript
  1072.         {
  1073.             PrepareAuraScript(spell_sindragosa_frost_beacon_AuraScript);
  1074.  
  1075.             bool Validate(SpellEntry const* /*spell*/)
  1076.             {
  1077.                 if (!sSpellStore.LookupEntry(SPELL_ICE_TOMB_DAMAGE))
  1078.                     return false;
  1079.                 return true;
  1080.             }
  1081.  
  1082.             void PeriodicTick(AuraEffect const* /*aurEff*/)
  1083.             {
  1084.                 PreventDefaultAction();
  1085.                 if (Unit* caster = GetCaster())
  1086.                     caster->CastSpell(GetTarget(), SPELL_ICE_TOMB_DAMAGE, true);
  1087.             }
  1088.  
  1089.             void Register()
  1090.             {
  1091.                 OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_frost_beacon_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
  1092.             }
  1093.         };
  1094.  
  1095.         AuraScript* GetAuraScript() const
  1096.         {
  1097.             return new spell_sindragosa_frost_beacon_AuraScript();
  1098.         }
  1099. };
  1100.  
  1101. class spell_sindragosa_ice_tomb : public SpellScriptLoader
  1102. {
  1103.     public:
  1104.         spell_sindragosa_ice_tomb() : SpellScriptLoader("spell_sindragosa_ice_tomb_trap") { }
  1105.  
  1106.         class spell_sindragosa_ice_tomb_SpellScript : public SpellScript
  1107.         {
  1108.             PrepareSpellScript(spell_sindragosa_ice_tomb_SpellScript);
  1109.  
  1110.             bool Validate(SpellEntry const* /*spell*/)
  1111.             {
  1112.                 if (!ObjectMgr::GetCreatureTemplate(NPC_ICE_TOMB))
  1113.                     return false;
  1114.                 if (!ObjectMgr::GetGameObjectInfo(GO_ICE_BLOCK))
  1115.                     return false;
  1116.                 return true;
  1117.             }
  1118.  
  1119.             void SummonTomb()
  1120.             {
  1121.                 Position pos;
  1122.                 GetHitUnit()->GetPosition(&pos);
  1123.                 if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICE_TOMB, pos))
  1124.                 {
  1125.                     summon->AI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TRAPPED_PLAYER);
  1126.                     if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0))
  1127.                     {
  1128.                         go->SetSpellId(SPELL_ICE_TOMB_DAMAGE);
  1129.                         summon->AddGameObject(go);
  1130.                     }
  1131.                 }
  1132.             }
  1133.  
  1134.             void Register()
  1135.             {
  1136.                 AfterHit += SpellHitFn(spell_sindragosa_ice_tomb_SpellScript::SummonTomb);
  1137.             }
  1138.         };
  1139.  
  1140.         class spell_sindragosa_ice_tomb_AuraScript : public AuraScript
  1141.         {
  1142.             PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript);
  1143.  
  1144.             void PeriodicTick(AuraEffect const* /*aurEff*/)
  1145.             {
  1146.                 PreventDefaultAction();
  1147.             }
  1148.  
  1149.             void Register()
  1150.             {
  1151.                 OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb_AuraScript::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
  1152.             }
  1153.         };
  1154.  
  1155.         SpellScript* GetSpellScript() const
  1156.         {
  1157.             return new spell_sindragosa_ice_tomb_SpellScript();
  1158.         }
  1159.  
  1160.         AuraScript* GetAuraScript() const
  1161.         {
  1162.             return new spell_sindragosa_ice_tomb_AuraScript();
  1163.         }
  1164. };
  1165.  
  1166. class FrostBombTargetSelector
  1167. {
  1168.     public:
  1169.         FrostBombTargetSelector(Unit* _caster, std::list<Unit*> const& _collisionList) : caster(_caster), collisionList(_collisionList) { }
  1170.  
  1171.         bool operator()(Unit* unit)
  1172.         {
  1173.             if (unit->HasAura(SPELL_ICE_TOMB_DAMAGE))
  1174.                 return true;
  1175.  
  1176.             for (std::list<Unit*>::const_iterator itr = collisionList.begin(); itr != collisionList.end(); ++itr)
  1177.                 if ((*itr)->IsInBetween(caster, unit))
  1178.                     return true;
  1179.  
  1180.             return false;
  1181.         }
  1182.  
  1183.         Unit* caster;
  1184.         std::list<Unit*> const& collisionList;
  1185. };
  1186.  
  1187. class spell_sindragosa_collision_filter : public SpellScriptLoader
  1188. {
  1189.     public:
  1190.         spell_sindragosa_collision_filter() : SpellScriptLoader("spell_sindragosa_collision_filter") { }
  1191.  
  1192.         class spell_sindragosa_collision_filter_SpellScript : public SpellScript
  1193.         {
  1194.             PrepareSpellScript(spell_sindragosa_collision_filter_SpellScript);
  1195.  
  1196.             void FilterTargets(std::list<Unit*>& unitList)
  1197.             {
  1198.                 std::list<Unit*> tombs;
  1199.                 for (std::list<Unit*>::const_iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
  1200.                     if ((*itr)->HasAura(SPELL_ICE_TOMB_DAMAGE))
  1201.                         tombs.push_back(*itr);
  1202.  
  1203.                 unitList.remove_if(FrostBombTargetSelector(GetCaster(), tombs));
  1204.             }
  1205.  
  1206.             void Register()
  1207.             {
  1208.                 OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_collision_filter_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC);
  1209.             }
  1210.         };
  1211.  
  1212.         SpellScript* GetSpellScript() const
  1213.         {
  1214.             return new spell_sindragosa_collision_filter_SpellScript();
  1215.         }
  1216. };
  1217.  
  1218. class spell_sindragosa_icy_grip : public SpellScriptLoader
  1219. {
  1220.     public:
  1221.         spell_sindragosa_icy_grip() : SpellScriptLoader("spell_sindragosa_icy_grip") { }
  1222.  
  1223.         class spell_sindragosa_icy_grip_SpellScript : public SpellScript
  1224.         {
  1225.             PrepareSpellScript(spell_sindragosa_icy_grip_SpellScript);
  1226.  
  1227.             bool Validate(SpellEntry const* /*spell*/)
  1228.             {
  1229.                 if (!sSpellStore.LookupEntry(SPELL_ICY_GRIP_JUMP))
  1230.                     return false;
  1231.                 return true;
  1232.             }
  1233.  
  1234.             void HandleScript(SpellEffIndex effIndex)
  1235.             {
  1236.                 PreventHitDefaultEffect(effIndex);
  1237.                 GetHitUnit()->CastSpell(GetCaster(), SPELL_ICY_GRIP_JUMP, true);
  1238.             }
  1239.  
  1240.             void Register()
  1241.             {
  1242.                 OnEffect += SpellEffectFn(spell_sindragosa_icy_grip_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
  1243.             }
  1244.         };
  1245.  
  1246.         SpellScript* GetSpellScript() const
  1247.         {
  1248.             return new spell_sindragosa_icy_grip_SpellScript();
  1249.         }
  1250. };
  1251.  
  1252. class spell_rimefang_icy_blast : public SpellScriptLoader
  1253. {
  1254.     public:
  1255.         spell_rimefang_icy_blast() : SpellScriptLoader("spell_rimefang_icy_blast") { }
  1256.  
  1257.         class spell_rimefang_icy_blast_SpellScript : public SpellScript
  1258.         {
  1259.             PrepareSpellScript(spell_rimefang_icy_blast_SpellScript);
  1260.  
  1261.             bool Validate(SpellEntry const* /*spell*/)
  1262.             {
  1263.                 if (!sSpellStore.LookupEntry(SPELL_ICY_BLAST_AREA))
  1264.                     return false;
  1265.                 return true;
  1266.             }
  1267.  
  1268.             void HandleTriggerMissile(SpellEffIndex effIndex)
  1269.             {
  1270.                 PreventHitDefaultEffect(effIndex);
  1271.                 if (Position* pos = GetTargetDest())
  1272.                     if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICY_BLAST, *pos, TEMPSUMMON_TIMED_DESPAWN, 40000))
  1273.                         summon->CastSpell(summon, SPELL_ICY_BLAST_AREA, true);
  1274.             }
  1275.  
  1276.             void Register()
  1277.             {
  1278.                 OnEffect += SpellEffectFn(spell_rimefang_icy_blast_SpellScript::HandleTriggerMissile, EFFECT_1, SPELL_EFFECT_TRIGGER_MISSILE);
  1279.             }
  1280.         };
  1281.  
  1282.         SpellScript* GetSpellScript() const
  1283.         {
  1284.             return new spell_rimefang_icy_blast_SpellScript();
  1285.         }
  1286. };
  1287.  
  1288. class OrderWhelpTargetSelector
  1289. {
  1290.     public:
  1291.         explicit OrderWhelpTargetSelector(Creature* _owner) : owner(_owner) { }
  1292.  
  1293.         bool operator()(Creature* creature)
  1294.         {
  1295.             if (!creature->AI()->GetData(DATA_WHELP_MARKER) && creature->AI()->GetData(DATA_FROSTWYRM_OWNER) == owner->AI()->GetData(DATA_FROSTWYRM_OWNER))
  1296.                 return false;
  1297.             return true;
  1298.         }
  1299.  
  1300.     private:
  1301.         Creature* owner;
  1302. };
  1303.  
  1304. class spell_frostwarden_handler_order_whelp : public SpellScriptLoader
  1305. {
  1306.     public:
  1307.         spell_frostwarden_handler_order_whelp() : SpellScriptLoader("spell_frostwarden_handler_order_whelp") { }
  1308.  
  1309.         class spell_frostwarden_handler_order_whelp_SpellScript : public SpellScript
  1310.         {
  1311.             PrepareSpellScript(spell_frostwarden_handler_order_whelp_SpellScript);
  1312.  
  1313.             bool Validate(SpellEntry const* /*spell*/)
  1314.             {
  1315.                 if (!sSpellStore.LookupEntry(SPELL_FOCUS_FIRE))
  1316.                     return false;
  1317.                 return true;
  1318.             }
  1319.  
  1320.             void FilterTargets(std::list<Unit*>& unitList)
  1321.             {
  1322.                 for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end();)
  1323.                 {
  1324.                     if ((*itr)->GetTypeId() != TYPEID_PLAYER)
  1325.                         unitList.erase(itr++);
  1326.                     else
  1327.                         ++itr;
  1328.                 }
  1329.  
  1330.                 std::list<Unit*>::iterator itr = unitList.begin();
  1331.                 std::advance(itr, urand(0, unitList.size()-1));
  1332.                 Unit* target = *itr;
  1333.                 unitList.clear();
  1334.                 unitList.push_back(target);
  1335.             }
  1336.  
  1337.             void HandleForcedCast(SpellEffIndex effIndex)
  1338.             {
  1339.                 // caster is Frostwarden Handler, target is player, caster of triggered is whelp
  1340.                 PreventHitDefaultEffect(effIndex);
  1341.                 std::list<Creature*> unitList;
  1342.                 GetCreatureListWithEntryInGrid(unitList, GetCaster(), NPC_FROSTWING_WHELP, 150.0f);
  1343.                 if (Creature* creature = GetCaster()->ToCreature())
  1344.                     unitList.remove_if(OrderWhelpTargetSelector(creature));
  1345.  
  1346.                 std::list<Creature*>::iterator itr = unitList.begin();
  1347.                 std::advance(itr, urand(0, unitList.size()-1));
  1348.                 (*itr)->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
  1349.             }
  1350.  
  1351.             void Register()
  1352.             {
  1353.                 OnEffect += SpellEffectFn(spell_frostwarden_handler_order_whelp_SpellScript::HandleForcedCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
  1354.                 OnUnitTargetSelect += SpellUnitTargetFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_DST);
  1355.             }
  1356.         };
  1357.  
  1358.         SpellScript* GetSpellScript() const
  1359.         {
  1360.             return new spell_frostwarden_handler_order_whelp_SpellScript();
  1361.         }
  1362. };
  1363.  
  1364. class spell_frostwarden_handler_focus_fire : public SpellScriptLoader
  1365. {
  1366.     public:
  1367.         spell_frostwarden_handler_focus_fire() : SpellScriptLoader("spell_frostwarden_handler_focus_fire") { }
  1368.  
  1369.         class spell_frostwarden_handler_focus_fire_SpellScript : public SpellScript
  1370.         {
  1371.             PrepareSpellScript(spell_frostwarden_handler_focus_fire_SpellScript);
  1372.  
  1373.             void HandleScript(SpellEffIndex effIndex)
  1374.             {
  1375.                 PreventHitDefaultEffect(effIndex);
  1376.                 GetCaster()->AddThreat(GetHitUnit(), float(GetEffectValue()));
  1377.                 GetCaster()->GetAI()->SetData(DATA_WHELP_MARKER, 1);
  1378.             }
  1379.  
  1380.             void Register()
  1381.             {
  1382.                 OnEffect += SpellEffectFn(spell_frostwarden_handler_focus_fire_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
  1383.             }
  1384.         };
  1385.  
  1386.         class spell_frostwarden_handler_focus_fire_AuraScript : public AuraScript
  1387.         {
  1388.             PrepareAuraScript(spell_frostwarden_handler_focus_fire_AuraScript);
  1389.  
  1390.             void PeriodicTick(AuraEffect const* aurEff)
  1391.             {
  1392.                 PreventDefaultAction();
  1393.                 if (Unit* caster = GetCaster())
  1394.                 {
  1395.                     caster->AddThreat(GetTarget(), -float(SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1)));
  1396.                     caster->GetAI()->SetData(DATA_WHELP_MARKER, 0);
  1397.                 }
  1398.             }
  1399.  
  1400.             void Register()
  1401.             {
  1402.                 OnEffectPeriodic += AuraEffectPeriodicFn(spell_frostwarden_handler_focus_fire_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
  1403.             }
  1404.         };
  1405.  
  1406.         SpellScript* GetSpellScript() const
  1407.         {
  1408.             return new spell_frostwarden_handler_focus_fire_SpellScript();
  1409.         }
  1410.  
  1411.         AuraScript* GetAuraScript() const
  1412.         {
  1413.             return new spell_frostwarden_handler_focus_fire_AuraScript();
  1414.         }
  1415. };
  1416.  
  1417. class spell_trigger_spell_from_caster : public SpellScriptLoader
  1418. {
  1419.     public:
  1420.         spell_trigger_spell_from_caster(char const* scriptName, uint32 _triggerId) : SpellScriptLoader(scriptName), triggerId(_triggerId) { }
  1421.  
  1422.         class spell_trigger_spell_from_caster_SpellScript : public SpellScript
  1423.         {
  1424.             PrepareSpellScript(spell_trigger_spell_from_caster_SpellScript);
  1425.  
  1426.         public:
  1427.             spell_trigger_spell_from_caster_SpellScript(uint32 _triggerId) : SpellScript(), triggerId(_triggerId) { }
  1428.  
  1429.             void HandleTrigger()
  1430.             {
  1431.                 GetCaster()->CastSpell(GetHitUnit(), triggerId, true);
  1432.             }
  1433.  
  1434.             void Register()
  1435.             {
  1436.                 AfterHit += SpellHitFn(spell_trigger_spell_from_caster_SpellScript::HandleTrigger);
  1437.             }
  1438.  
  1439.             uint32 triggerId;
  1440.         };
  1441.  
  1442.         SpellScript* GetSpellScript() const
  1443.         {
  1444.             return new spell_trigger_spell_from_caster_SpellScript(triggerId);
  1445.         }
  1446.  
  1447.     private:
  1448.         uint32 triggerId;
  1449. };
  1450.  
  1451. class at_sindragosa_lair : public AreaTriggerScript
  1452. {
  1453.     public:
  1454.         at_sindragosa_lair() : AreaTriggerScript("at_sindragosa_lair") { }
  1455.  
  1456.         bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/)
  1457.         {
  1458.             if (InstanceScript* instance = player->GetInstanceScript())
  1459.             {
  1460.                 if (!instance->GetData(DATA_SPINESTALKER))
  1461.                     if (Creature* spinestalker = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_SPINESTALKER)))
  1462.                         spinestalker->AI()->DoAction(ACTION_START_FROSTWYRM);
  1463.  
  1464.                 if (!instance->GetData(DATA_RIMEFANG))
  1465.                     if (Creature* rimefang = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_RIMEFANG)))
  1466.                         rimefang->AI()->DoAction(ACTION_START_FROSTWYRM);
  1467.  
  1468.                 if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && instance->GetBossState(DATA_SINDRAGOSA) != DONE)
  1469.                 {
  1470.                     player->GetMap()->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY());
  1471.                     if (Creature* sindragosa = player->GetMap()->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos))
  1472.                     {
  1473.                         sindragosa->setActive(true);
  1474.                         sindragosa->AI()->DoAction(ACTION_START_FROSTWYRM);
  1475.                     }
  1476.                 }
  1477.             }
  1478.  
  1479.             return true;
  1480.         }
  1481. };
  1482.  
  1483. class achievement_all_you_can_eat : public AchievementCriteriaScript
  1484. {
  1485.     public:
  1486.         achievement_all_you_can_eat() : AchievementCriteriaScript("achievement_all_you_can_eat") { }
  1487.  
  1488.         bool OnCheck(Player* /*source*/, Unit* target)
  1489.         {
  1490.             if (!target)
  1491.                 return false;
  1492.             return target->GetAI()->GetData(DATA_MYSTIC_BUFFET_STACK) <= 5;
  1493.         }
  1494. };
  1495.  
  1496. void AddSC_boss_sindragosa()
  1497. {
  1498.     new boss_sindragosa();
  1499.     new npc_ice_tomb();
  1500.     new npc_spinestalker();
  1501.     new npc_rimefang();
  1502.     new npc_sindragosa_trash();
  1503.     new spell_sindragosa_s_fury();
  1504.     new spell_sindragosa_unchained_magic();
  1505.     new spell_sindragosa_instability();
  1506.     new spell_sindragosa_frost_beacon();
  1507.     new spell_sindragosa_ice_tomb();
  1508.     new spell_sindragosa_collision_filter();
  1509.     new spell_sindragosa_icy_grip();
  1510.     new spell_rimefang_icy_blast();
  1511.     new spell_frostwarden_handler_order_whelp();
  1512.     new spell_frostwarden_handler_focus_fire();
  1513.     new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY);
  1514.     new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON);
  1515.     new at_sindragosa_lair();
  1516.     new achievement_all_you_can_eat();
  1517. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement