aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2011-02-07 17:21:44 +0100
committerShauren <shauren.trinity@gmail.com>2011-02-07 17:21:44 +0100
commitdc1b02d35d682e1fee28ddc9ebe790fe8c3e711f (patch)
tree5a932cc83a3c45091cdc142851910da4a38e751a /src
parent00b93c508f811577f7bd93b352badd715912acd1 (diff)
Scripts/Icecrown Citadel: Added Sindragosa script
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp17
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp1481
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h24
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp91
6 files changed, 1611 insertions, 5 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index adbfbe64810..e4bb4318fb8 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -473,6 +473,7 @@ void AddSC_boss_rotface();
void AddSC_boss_professor_putricide();
void AddSC_boss_blood_prince_council();
void AddSC_boss_blood_queen_lana_thel();
+void AddSC_boss_sindragosa();
void AddSC_icecrown_citadel_teleport();
void AddSC_instance_icecrown_citadel();
@@ -1162,6 +1163,7 @@ void AddNorthrendScripts()
AddSC_boss_professor_putricide();
AddSC_boss_blood_prince_council();
AddSC_boss_blood_queen_lana_thel();
+ AddSC_boss_sindragosa();
AddSC_icecrown_citadel_teleport();
AddSC_instance_icecrown_citadel();
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 5bd5cd8ed71..e1c85ce1460 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -4040,11 +4040,26 @@ void SpellMgr::LoadSpellCustomAttr()
spellInfo->AreaGroupId = 0;
count++;
break;
+ case 71357: // Order Whelp
+ spellInfo->EffectRadiusIndex[0] = 22;
+ count++;
+ break;
+ case 70598: // Sindragosa's Fury
+ spellInfo->EffectImplicitTargetA[0] = TARGET_DST_CASTER;
+ count++;
+ break;
+ case 69846: // Frost Bomb
+ spellInfo->speed = 10;
+ spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_TARGET_ANY;
+ spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ANY;
+ spellInfo->Effect[1] = 0;
+ count++;
+ break;
default:
break;
}
- switch(spellInfo->SpellFamilyName)
+ switch (spellInfo->SpellFamilyName)
{
case SPELLFAMILY_WARRIOR:
// Shout
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index f1c80b14bd1..2ff4974c7a4 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -154,6 +154,7 @@ set(scripts_STAT_SRCS
Northrend/IcecrownCitadel/boss_professor_putricide.cpp
Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
+ Northrend/IcecrownCitadel/boss_sindragosa.cpp
Northrend/zuldrak.cpp
Northrend/icecrown.cpp
Northrend/Gundrak/boss_slad_ran.cpp
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
new file mode 100644
index 00000000000..9d0be34cd23
--- /dev/null
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -0,0 +1,1481 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "icecrown_citadel.h"
+
+enum Texts
+{
+ SAY_AGGRO = 0, // You are fools to have come to this place! The icy winds of Northrend will consume your souls!
+ SAY_UNCHAINED_MAGIC = 1, // Suffer, mortals, as your pathetic magic betrays you!
+ EMOTE_WARN_BLISTERING_COLD = 2, // %s prepares to unleash a wave of blistering cold!
+ SAY_BLISTERING_COLD = 3, // Can you feel the cold hand of death upon your heart?
+ SAY_RESPITE_FOR_A_TORMENTED_SOUL = 4, // Aaah! It burns! What sorcery is this?!
+ SAY_AIR_PHASE = 5, // Your incursion ends here! None shall survive!
+ SAY_PHASE_2 = 6, // Now feel my master's limitless power and despair!
+ EMOTE_WARN_FROZEN_ORB = 7, // %s fires a frozen orb towards $N!
+ SAY_KILL = 8, // Perish!
+ // A flaw of mortality...
+ SAY_BERSERK = 9, // Enough! I tire of these games!
+ SAY_DEATH = 10,// Free...at last...
+};
+
+enum Spells
+{
+ // Sindragosa
+ SPELL_SINDRAGOSA_S_FURY = 70608,
+ SPELL_TANK_MARKER = 71039,
+ SPELL_FROST_AURA = 70084,
+ SPELL_PERMAEATING_CHILL = 70109,
+ SPELL_CLEAVE = 19983,
+ SPELL_TAIL_SMASH = 71077,
+ SPELL_FROST_BREATH_P1 = 69649,
+ SPELL_FROST_BREATH_P2 = 73061,
+ SPELL_UNCHAINED_MAGIC = 69762,
+ SPELL_BACKLASH = 69770,
+ SPELL_ICY_GRIP = 70117,
+ SPELL_BLISTERING_COLD = 70123,
+ SPELL_FROST_BEACON = 70126,
+ SPELL_ICE_TOMB_TARGET = 69712,
+ SPELL_ICE_TOMB_DUMMY = 69675,
+ SPELL_ICE_TOMB_UNTARGETABLE = 69700,
+ SPELL_ICE_TOMB_DAMAGE = 70157,
+ SPELL_ASPHYXIATION = 71665,
+ SPELL_FROST_BOMB_TRIGGER = 69846,
+ SPELL_FROST_BOMB_VISUAL = 70022,
+ SPELL_FROST_BOMB = 69845,
+ SPELL_MYSTIC_BUFFET = 70128,
+
+ // Spinestalker
+ SPELL_BELLOWING_ROAR = 36922,
+ SPELL_CLEAVE_SPINESTALKER = 40505,
+ SPELL_TAIL_SWEEP = 71370,
+
+ // Rimefang
+ SPELL_FROST_BREATH = 71386,
+ SPELL_FROST_AURA_RIMEFANG = 71387,
+ SPELL_ICY_BLAST = 71376,
+ SPELL_ICY_BLAST_AREA = 71380,
+
+ // Frostwarden Handler
+ SPELL_FOCUS_FIRE = 71350,
+ SPELL_ORDER_WHELP = 71357,
+ SPELL_CONCUSSIVE_SHOCK = 71337,
+};
+
+enum Events
+{
+ // Sindragosa
+ EVENT_BERSERK = 1,
+ EVENT_CLEAVE = 2,
+ EVENT_TAIL_SMASH = 3,
+ EVENT_FROST_BREATH = 4,
+ EVENT_UNCHAINED_MAGIC = 5,
+ EVENT_ICY_GRIP = 6,
+ EVENT_BLISTERING_COLD = 7,
+ EVENT_BLISTERING_COLD_YELL = 8,
+ EVENT_AIR_PHASE = 9,
+ EVENT_ICE_TOMB = 10,
+ EVENT_FROST_BOMB = 11,
+ EVENT_LAND = 12,
+
+ // Spinestalker
+ EVENT_BELLOWING_ROAR = 13,
+ EVENT_CLEAVE_SPINESTALKER = 14,
+ EVENT_TAIL_SWEEP = 15,
+
+ // Rimefang
+ EVENT_FROST_BREATH_RIMEFANG = 16,
+ EVENT_ICY_BLAST = 17,
+ EVENT_ICY_BLAST_CAST = 18,
+
+ // Trash
+ EVENT_FROSTWARDEN_ORDER_WHELP = 19,
+ EVENT_CONCUSSIVE_SHOCK = 20,
+
+ // event groups
+ EVENT_GROUP_LAND_PHASE = 1,
+};
+
+enum FrostwingData
+{
+ DATA_MYSTIC_BUFFET_STACK = 0,
+ DATA_FROSTWYRM_OWNER = 1,
+ DATA_WHELP_MARKER = 2,
+ DATA_LINKED_GAMEOBJECT = 3,
+ DATA_TRAPPED_PLAYER = 4,
+};
+
+enum MovementPoints
+{
+ POINT_FROSTWYRM_FLY_IN = 1,
+ POINT_FROSTWYRM_LAND = 2,
+ POINT_AIR_PHASE = 3,
+ POINT_LAND = 4,
+};
+
+enum Shadowmourne
+{
+ QUEST_FROST_INFUSION = 24757,
+ ITEM_SHADOW_S_EDGE = 49888,
+
+ SPELL_FROST_INFUSION = 72292,
+ SPELL_FROST_IMBUED_BLADE = 72290,
+};
+
+static Position const RimefangFlyPos = {4413.309f, 2456.421f, 223.3795f, 2.890186f};
+static Position const RimefangLandPos = {4413.309f, 2456.421f, 203.3848f, 2.890186f};
+static Position const SpinestalkerFlyPos = {4418.895f, 2514.233f, 220.4864f, 3.396045f};
+static Position const SpinestalkerLandPos = {4418.895f, 2514.233f, 203.3848f, 3.396045f};
+static Position const SindragosaSpawnPos = {4818.700f, 2483.710f, 287.0650f, 3.089233f};
+static Position const SindragosaFlyPos = {4475.190f, 2484.570f, 234.8510f, 3.141593f};
+static Position const SindragosaLandPos = {4419.190f, 2484.570f, 203.3848f, 3.141593f};
+static Position const SindragosaAirPos = {4475.990f, 2484.430f, 247.9340f, 3.141593f};
+
+class FrostwyrmLandEvent : public BasicEvent
+{
+ public:
+ FrostwyrmLandEvent(Creature& _owner, Position const& _dest) : owner(_owner), dest(_dest) { }
+
+ bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
+ {
+ owner.GetMotionMaster()->MovePoint(POINT_FROSTWYRM_LAND, dest);
+ return true;
+ }
+
+ Creature& owner;
+ Position const& dest;
+};
+
+class boss_sindragosa : public CreatureScript
+{
+ public:
+ boss_sindragosa() : CreatureScript("boss_sindragosa") { }
+
+ struct boss_sindragosaAI : public BossAI
+ {
+ boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA)
+ {
+ }
+
+ void InitializeAI()
+ {
+ if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
+ me->IsAIEnabled = false;
+ else if (!me->isDead())
+ Reset();
+ }
+
+ void Reset()
+ {
+ BossAI::Reset();
+ me->SetReactState(REACT_DEFENSIVE);
+ DoCast(me, SPELL_TANK_MARKER, true);
+ events.ScheduleEvent(EVENT_BERSERK, 600000);
+ events.ScheduleEvent(EVENT_CLEAVE, 10000, EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_TAIL_SMASH, 20000, EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_FROST_BREATH, urand(8000, 12000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(9000, 14000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_ICY_GRIP, 33500, EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_AIR_PHASE, 50000);
+ mysticBuffetStack = 0;
+ isThirdPhase = false;
+
+ if (instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) != 255)
+ {
+ me->SetFlying(true);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ }
+ }
+
+ void JustDied(Unit* killer)
+ {
+ BossAI::JustDied(killer);
+ Talk(SAY_DEATH);
+ }
+
+ void EnterCombat(Unit* victim)
+ {
+ if (!instance->CheckRequiredBosses(DATA_SINDRAGOSA, victim->ToPlayer()))
+ {
+ EnterEvadeMode();
+ instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
+ return;
+ }
+
+ BossAI::EnterCombat(victim);
+ DoCast(me, SPELL_FROST_AURA);
+ DoCast(me, SPELL_PERMAEATING_CHILL);
+ Talk(SAY_AGGRO);
+ }
+
+ void JustReachedHome()
+ {
+ BossAI::JustReachedHome();
+ instance->SetBossState(DATA_SINDRAGOSA, FAIL);
+ me->SetFlying(false);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ void DoAction(const int32 action)
+ {
+ if (action == ACTION_START_FROSTWYRM)
+ {
+ instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 255);
+ if (me->isDead())
+ return;
+ me->SetSpeed(MOVE_FLIGHT, 4.0f);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ float moveTime = me->GetExactDist(&SindragosaFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
+ me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), uint64(moveTime) + 250);
+ me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SindragosaFlyPos);
+ DoCast(me, SPELL_SINDRAGOSA_S_FURY);
+ }
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ if (type == DATA_MYSTIC_BUFFET_STACK)
+ return mysticBuffetStack;
+ return 0xFFFFFFFF;
+ }
+
+ void MovementInform(uint32 type, uint32 point)
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (point)
+ {
+ case POINT_FROSTWYRM_LAND:
+ me->setActive(false);
+ me->SetFlying(false);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetHomePosition(SindragosaLandPos);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetSpeed(MOVE_FLIGHT, 2.0f);
+
+ // Sindragosa enters combat as soon as she lands
+ DoZoneInCombat();
+ break;
+ case POINT_AIR_PHASE:
+ me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 3, 6), false);
+ events.ScheduleEvent(EVENT_FROST_BOMB, 8000);
+ break;
+ case POINT_LAND:
+ me->SetFlying(false);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetReactState(REACT_DEFENSIVE);
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
+ me->GetMotionMaster()->MovementExpired();
+ DoStartMovement(me->getVictim());
+ // trigger Asphyxiation
+ summons.DoAction(NPC_ICE_TOMB, ACTION_TRIGGER_ASPHYXIATION);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/)
+ {
+ if (!isThirdPhase && !HealthAbovePct(35))
+ {
+ Talk(SAY_PHASE_2);
+ events.CancelEvent(EVENT_AIR_PHASE);
+ events.ScheduleEvent(EVENT_ICE_TOMB, urand(7000, 10000));
+ events.RescheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000));
+ DoCast(me, SPELL_MYSTIC_BUFFET, true);
+ isThirdPhase = true;
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ summons.Summon(summon);
+ }
+
+ void SummonedCreatureDespawn(Creature* summon)
+ {
+ BossAI::SummonedCreatureDespawn(summon);
+ if (summon->GetEntry() == NPC_ICE_TOMB)
+ summon->AI()->JustDied(summon);
+ }
+
+ void SpellHitTarget(Unit* target, SpellEntry const* spell)
+ {
+ if (SpellEntry const* buffet = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(70127), me))
+ if (buffet->Id == spell->Id)
+ if (Aura const* mysticBuffet = target->GetAura(spell->Id))
+ mysticBuffetStack = std::max<uint8>(mysticBuffetStack, mysticBuffet->GetStackAmount());
+
+ // Frost Infusion
+ if (Player* player = target->ToPlayer())
+ {
+ if (SpellEntry const* breath = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1), me))
+ {
+ if (player->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_REWARDED && breath->Id == spell->Id)
+ {
+ if (Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true))
+ {
+ if (!player->HasAura(SPELL_FROST_IMBUED_BLADE) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE)
+ {
+ if (Aura* infusion = player->GetAura(SPELL_FROST_INFUSION))
+ {
+ if (infusion->GetStackAmount() == 3)
+ {
+ player->CastSpell(player, SPELL_FROST_IMBUED_BLADE, true);
+ player->RemoveAura(infusion);
+ }
+ else
+ player->CastSpell(player, SPELL_FROST_INFUSION, true);
+ }
+ else
+ player->CastSpell(player, SPELL_FROST_INFUSION, true);
+ }
+ }
+ }
+ }
+ }
+
+ if (spell->Id == SPELL_FROST_BOMB_TRIGGER)
+ {
+ target->CastSpell(target, SPELL_FROST_BOMB, true);
+ target->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim() || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BERSERK:
+ DoScriptText(EMOTE_GENERIC_BERSERK_RAID, me);
+ Talk(SAY_BERSERK);
+ DoCast(me, SPELL_BERSERK);
+ break;
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ events.ScheduleEvent(EVENT_CLEAVE, urand(15000, 20000), EVENT_GROUP_LAND_PHASE);
+ break;
+ case EVENT_TAIL_SMASH:
+ DoCast(me, SPELL_TAIL_SMASH);
+ events.ScheduleEvent(EVENT_TAIL_SMASH, urand(27000, 32000), EVENT_GROUP_LAND_PHASE);
+ break;
+ case EVENT_FROST_BREATH:
+ DoCastVictim(isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1);
+ events.ScheduleEvent(EVENT_FROST_BREATH, urand(20000, 25000), EVENT_GROUP_LAND_PHASE);
+ break;
+ case EVENT_UNCHAINED_MAGIC:
+ Talk(SAY_UNCHAINED_MAGIC);
+ DoCast(me, SPELL_UNCHAINED_MAGIC);
+ events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(30000, 35000), EVENT_GROUP_LAND_PHASE);
+ break;
+ case EVENT_ICY_GRIP:
+ DoCast(me, SPELL_ICY_GRIP);
+ events.ScheduleEvent(EVENT_ICY_GRIP, urand(70000, 75000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_BLISTERING_COLD, 1000, EVENT_GROUP_LAND_PHASE);
+ break;
+ case EVENT_BLISTERING_COLD:
+ Talk(EMOTE_WARN_BLISTERING_COLD);
+ DoCast(me, SPELL_BLISTERING_COLD);
+ events.ScheduleEvent(EVENT_BLISTERING_COLD_YELL, 5000, EVENT_GROUP_LAND_PHASE);
+ break;
+ case EVENT_BLISTERING_COLD_YELL:
+ Talk(SAY_BLISTERING_COLD);
+ break;
+ case EVENT_AIR_PHASE:
+ Talk(SAY_AIR_PHASE);
+ me->SetFlying(true);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetReactState(REACT_PASSIVE);
+ me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE, SindragosaAirPos);
+ events.DelayEvents(45000, EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_AIR_PHASE, 110000);
+ events.RescheduleEvent(EVENT_UNCHAINED_MAGIC, urand(55000, 60000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_LAND, 45000);
+ break;
+ case EVENT_ICE_TOMB:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_ICE_TOMB_UNTARGETABLE))
+ {
+ Talk(EMOTE_WARN_FROZEN_ORB, target->GetGUID());
+ DoCast(target, SPELL_ICE_TOMB_DUMMY, true);
+ }
+ events.ScheduleEvent(EVENT_ICE_TOMB, urand(16000, 23000));
+ break;
+ case EVENT_FROST_BOMB:
+ {
+ float destX, destY, destZ;
+ destX = float(rand_norm()) * 117.25f + 4339.25f;
+ if (destX > 4371.5f && destX < 4432.0f)
+ destY = float(rand_norm()) * 111.0f + 2429.0f;
+ else
+ destY = float(rand_norm()) * 31.23f + 2454.64f;
+ destZ = 205.0f; // random number close to ground, get exact in next call
+ me->UpdateGroundPositionZ(destX, destY, destZ);
+ Position pos;
+ pos.Relocate(destX, destY, destZ);
+ if (TempSummon* summ = me->SummonCreature(NPC_FROST_BOMB, pos, TEMPSUMMON_TIMED_DESPAWN, 40000))
+ {
+ summ->CastSpell(summ, SPELL_FROST_BOMB_VISUAL, true);
+ DoCast(summ, SPELL_FROST_BOMB_TRIGGER);
+ //me->CastSpell(destX, destY, destZ, SPELL_FROST_BOMB_TRIGGER, false);
+ }
+ events.ScheduleEvent(EVENT_FROST_BOMB, urand(5000, 10000));
+ break;
+ }
+ case EVENT_LAND:
+ {
+ events.CancelEvent(EVENT_FROST_BOMB);
+ me->GetMotionMaster()->MovePoint(POINT_LAND, SindragosaLandPos);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ uint8 mysticBuffetStack;
+ bool isThirdPhase;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new boss_sindragosaAI(creature);
+ }
+};
+
+class npc_ice_tomb : public CreatureScript
+{
+ public:
+ npc_ice_tomb() : CreatureScript("npc_ice_tomb") { }
+
+ struct npc_ice_tombAI : public Scripted_NoMovementAI
+ {
+ npc_ice_tombAI(Creature* creature) : Scripted_NoMovementAI(creature)
+ {
+ trappedPlayer = 0;
+ }
+
+ void Reset()
+ {
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void SetGUID(const uint64& guid, int32 type/* = 0 */)
+ {
+ if (type == DATA_TRAPPED_PLAYER)
+ {
+ trappedPlayer = guid;
+ existenceCheckTimer = 1000;
+ }
+ }
+
+ void DoAction(const int32 action)
+ {
+ if (action == ACTION_TRIGGER_ASPHYXIATION)
+ if (Player* player = ObjectAccessor::GetPlayer(*me, trappedPlayer))
+ player->CastSpell(player, SPELL_ASPHYXIATION, true);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ me->RemoveAllGameObjects();
+
+ if (Player* player = ObjectAccessor::GetPlayer(*me, trappedPlayer))
+ {
+ trappedPlayer = 0;
+ player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE);
+ player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!trappedPlayer)
+ return;
+
+ if (existenceCheckTimer <= diff)
+ {
+ Player* player = ObjectAccessor::GetPlayer(*me, trappedPlayer);
+ if (!player || player->isDead() || !player->HasAura(SPELL_ICE_TOMB_DAMAGE))
+ {
+ // Remove object
+ JustDied(me);
+ me->DespawnOrUnsummon();
+ return;
+ }
+ existenceCheckTimer = 1000;
+ }
+ else
+ existenceCheckTimer -= diff;
+ }
+
+ private:
+ uint64 trappedPlayer;
+ uint32 existenceCheckTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_ice_tombAI(creature);
+ }
+};
+
+class npc_spinestalker : public CreatureScript
+{
+ public:
+ npc_spinestalker() : CreatureScript("npc_spinestalker") { }
+
+ struct npc_spinestalkerAI : public ScriptedAI
+ {
+ npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript())
+ {
+ }
+
+ void InitializeAI()
+ {
+ if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
+ me->IsAIEnabled = false;
+ else if (!me->isDead())
+ Reset();
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ events.ScheduleEvent(EVENT_BELLOWING_ROAR, urand(20000, 25000));
+ events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, urand(10000, 15000));
+ events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(8000, 12000));
+ me->SetReactState(REACT_DEFENSIVE);
+
+ if (instance->GetData(DATA_SPINESTALKER) != 255)
+ {
+ me->SetFlying(true);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ }
+ }
+
+ void JustRespawned()
+ {
+ ScriptedAI::JustRespawned();
+ instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ events.Reset();
+ instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0);
+ }
+
+ void DoAction(const int32 action)
+ {
+ if (action == ACTION_START_FROSTWYRM)
+ {
+ instance->SetData(DATA_SPINESTALKER, 255);
+ if (me->isDead())
+ return;
+ me->SetSpeed(MOVE_FLIGHT, 2.0f);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ float moveTime = me->GetExactDist(&SpinestalkerFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
+ me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), uint64(moveTime) + 250);
+ me->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE);
+ me->StopMoving();
+ me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos);
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 point)
+ {
+ if (type != POINT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND)
+ return;
+
+ me->SetFlying(false);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetHomePosition(SpinestalkerLandPos);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BELLOWING_ROAR:
+ DoCast(me, SPELL_BELLOWING_ROAR);
+ events.ScheduleEvent(EVENT_BELLOWING_ROAR, urand(25000, 30000));
+ break;
+ case EVENT_CLEAVE_SPINESTALKER:
+ DoCastVictim(SPELL_CLEAVE_SPINESTALKER);
+ events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, urand(10000, 15000));
+ break;
+ case EVENT_TAIL_SWEEP:
+ DoCast(me, SPELL_TAIL_SWEEP);
+ events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(22000, 25000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ InstanceScript* instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_spinestalkerAI(creature);
+ }
+};
+
+class npc_rimefang : public CreatureScript
+{
+ public:
+ npc_rimefang() : CreatureScript("npc_rimefang_icc") { }
+
+ struct npc_rimefangAI : public ScriptedAI
+ {
+ npc_rimefangAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript())
+ {
+ }
+
+ void InitializeAI()
+ {
+ if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
+ me->IsAIEnabled = false;
+ else if (!me->isDead())
+ Reset();
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, urand(12000, 15000));
+ events.ScheduleEvent(EVENT_ICY_BLAST, urand(30000, 35000));
+ me->SetReactState(REACT_DEFENSIVE);
+ icyBlastCounter = 0;
+
+ if (instance->GetData(DATA_RIMEFANG) != 255)
+ {
+ me->SetFlying(true);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ }
+ }
+
+ void JustRespawned()
+ {
+ ScriptedAI::JustRespawned();
+ instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ events.Reset();
+ instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0);
+ }
+
+ void DoAction(const int32 action)
+ {
+ if (action == ACTION_START_FROSTWYRM)
+ {
+ instance->SetData(DATA_RIMEFANG, 255);
+ if (me->isDead())
+ return;
+ me->SetSpeed(MOVE_FLIGHT, 2.0f);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ float moveTime = me->GetExactDist(&RimefangFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
+ me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), uint64(moveTime) + 250);
+ me->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE);
+ me->StopMoving();
+ me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos);
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 point)
+ {
+ if (type != POINT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND)
+ return;
+
+ me->SetFlying(false);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetHomePosition(RimefangLandPos);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ }
+
+ void EnterCombat(Unit* /*victim*/)
+ {
+ DoCast(me, SPELL_FROST_AURA_RIMEFANG, true);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FROST_BREATH_RIMEFANG:
+ DoCast(me, SPELL_FROST_BREATH);
+ events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, urand(35000, 40000));
+ break;
+ case EVENT_ICY_BLAST:
+ {
+ icyBlastCounter = RAID_MODE<uint32>(5, 7, 6, 8);
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->SetFlying(true);
+ me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos);
+ float moveTime = me->GetExactDist(&RimefangFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f);
+ events.ScheduleEvent(EVENT_ICY_BLAST, uint64(moveTime) + urand(60000, 70000));
+ events.ScheduleEvent(EVENT_ICY_BLAST_CAST, uint64(moveTime) + 250);
+ break;
+ }
+ case EVENT_ICY_BLAST_CAST:
+ if (--icyBlastCounter)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ {
+ me->SetFacingToObject(target);
+ DoCast(target, SPELL_ICY_BLAST);
+ }
+ events.ScheduleEvent(EVENT_ICY_BLAST_CAST, 3000);
+ }
+ else if (Unit *victim = me->SelectVictim())
+ {
+ me->SetReactState(REACT_DEFENSIVE);
+ AttackStart(victim);
+ me->SetFlying(false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ InstanceScript* instance;
+ uint8 icyBlastCounter;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_rimefangAI(creature);
+ }
+};
+
+class npc_sindragosa_trash : public CreatureScript
+{
+ public:
+ npc_sindragosa_trash() : CreatureScript("npc_sindragosa_trash") { }
+
+ struct npc_sindragosa_trashAI : public ScriptedAI
+ {
+ npc_sindragosa_trashAI(Creature* creature) : ScriptedAI(creature)
+ {
+ frostwyrmId = (creature->GetHomePosition().GetPositionY() < 2484.35f) ? DATA_RIMEFANG : DATA_SPINESTALKER;
+ instance = creature->GetInstanceScript();
+ }
+
+ void InitializeAI()
+ {
+ // Increase add count
+ if (!me->isDead() && instance)
+ instance->SetData(frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade
+ }
+
+ void Reset()
+ {
+ // This is shared AI for handler and whelps
+ if (me->GetEntry() == NPC_FROSTWARDEN_HANDLER)
+ {
+ events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3000);
+ events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, urand(8000, 10000));
+ }
+
+ isTaunted = false;
+ }
+
+ void JustRespawned()
+ {
+ ScriptedAI::JustRespawned();
+
+ // Increase add count
+ if (instance)
+ instance->SetData(frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ // Decrease add count
+ if (instance)
+ instance->SetData(frostwyrmId, 0);
+ }
+
+ void SetData(uint32 type, uint32 data)
+ {
+ if (type == DATA_WHELP_MARKER)
+ isTaunted = data != 0;
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ if (type == DATA_FROSTWYRM_OWNER)
+ return frostwyrmId;
+ else if (type == DATA_WHELP_MARKER)
+ return uint32(isTaunted);
+ return 0;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FROSTWARDEN_ORDER_WHELP:
+ DoCast(me, SPELL_ORDER_WHELP);
+ events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3000);
+ break;
+ case EVENT_CONCUSSIVE_SHOCK:
+ DoCast(me, SPELL_CONCUSSIVE_SHOCK);
+ events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, urand(10000, 13000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ uint32 frostwyrmId;
+ bool isTaunted; // Frostwing Whelp only
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_sindragosa_trashAI(creature);
+ }
+};
+
+class spell_sindragosa_s_fury : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_s_fury() : SpellScriptLoader("spell_sindragosa_s_fury") { }
+
+ class spell_sindragosa_s_fury_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sindragosa_s_fury_SpellScript);
+
+ bool Load()
+ {
+ targetCount = 0;
+ return true;
+ }
+
+ void CountTargets(std::list<Unit*>& unitList)
+ {
+ targetCount = unitList.size();
+ }
+
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+
+ if (!GetHitUnit()->isAlive())
+ return;
+
+ float resistance = float(GetHitUnit()->GetResistance(GetFirstSchoolInMask(SpellSchoolMask(GetSpellInfo()->SchoolMask))));
+ uint32 minResistFactor = uint32((resistance / (resistance + 510.0f))* 10.0f) * 2;
+ uint32 randomResist = urand(0, (9 - minResistFactor) * 100)/100 + minResistFactor;
+
+ uint32 damage = (uint32(GetEffectValue()/targetCount) * randomResist) / 10;
+
+ SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo()->Id, GetSpellInfo()->SchoolMask);
+ damageInfo.damage = damage;
+ GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo);
+ GetCaster()->DealSpellDamage(&damageInfo, false);
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_sindragosa_s_fury_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_s_fury_SpellScript::CountTargets, EFFECT_1, TARGET_UNIT_AREA_ENTRY_DST);
+ }
+
+ uint32 targetCount;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sindragosa_s_fury_SpellScript();
+ }
+};
+
+class UnchainedMagicTargetSelector
+{
+ public:
+ UnchainedMagicTargetSelector() { }
+
+ bool operator()(Unit* unit)
+ {
+ return unit->getPowerType() != POWER_MANA;
+ }
+};
+
+class spell_sindragosa_unchained_magic : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_unchained_magic() : SpellScriptLoader("spell_sindragosa_unchained_magic") { }
+
+ class spell_sindragosa_unchained_magic_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sindragosa_unchained_magic_SpellScript);
+
+ void FilterTargets(std::list<Unit*>& unitList)
+ {
+ unitList.remove_if(UnchainedMagicTargetSelector());
+ uint32 maxSize = GetCaster()->GetMap()->GetSpawnMode() & 1 ? 5 : 2;
+ if (unitList.size() > maxSize)
+ Trinity::RandomResizeList(unitList, maxSize);
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sindragosa_unchained_magic_SpellScript();
+ }
+};
+
+class spell_sindragosa_instability : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_instability() : SpellScriptLoader("spell_sindragosa_instability") { }
+
+ class spell_sindragosa_instability_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_sindragosa_instability_AuraScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_BACKLASH))
+ return false;
+ return true;
+ }
+
+ void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ PreventDefaultAction();
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ GetTarget()->CastCustomSpell(SPELL_BACKLASH, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff, GetCasterGUID());
+ }
+
+ void Register()
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_sindragosa_instability_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_sindragosa_instability_AuraScript();
+ }
+};
+
+class spell_sindragosa_frost_beacon : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_frost_beacon() : SpellScriptLoader("spell_sindragosa_frost_beacon") { }
+
+ class spell_sindragosa_frost_beacon_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_sindragosa_frost_beacon_AuraScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_ICE_TOMB_DAMAGE))
+ return false;
+ return true;
+ }
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), SPELL_ICE_TOMB_DAMAGE, true);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_frost_beacon_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_sindragosa_frost_beacon_AuraScript();
+ }
+};
+
+class spell_sindragosa_ice_tomb : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_ice_tomb() : SpellScriptLoader("spell_sindragosa_ice_tomb_trap") { }
+
+ class spell_sindragosa_ice_tomb_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sindragosa_ice_tomb_SpellScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!ObjectMgr::GetCreatureTemplate(NPC_ICE_TOMB))
+ return false;
+ if (!ObjectMgr::GetGameObjectInfo(GO_ICE_BLOCK))
+ return false;
+ return true;
+ }
+
+ void SummonTomb()
+ {
+ Position pos;
+ GetHitUnit()->GetPosition(&pos);
+ if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICE_TOMB, pos))
+ {
+ summon->AI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TRAPPED_PLAYER);
+ 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))
+ {
+ go->SetSpellId(SPELL_ICE_TOMB_DAMAGE);
+ summon->AddGameObject(go);
+ }
+ }
+ }
+
+ void Register()
+ {
+ AfterHit += SpellHitFn(spell_sindragosa_ice_tomb_SpellScript::SummonTomb);
+ }
+ };
+
+ class spell_sindragosa_ice_tomb_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript);
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb_AuraScript::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sindragosa_ice_tomb_SpellScript();
+ }
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_sindragosa_ice_tomb_AuraScript();
+ }
+};
+
+class FrostBombTargetSelector
+{
+ public:
+ FrostBombTargetSelector(Unit* _caster, std::list<Unit*> const& _collisionList) : caster(_caster), collisionList(_collisionList) { }
+
+ bool operator()(Unit* unit)
+ {
+ if (unit->HasAura(SPELL_ICE_TOMB_DAMAGE))
+ return true;
+
+ for (std::list<Unit*>::const_iterator itr = collisionList.begin(); itr != collisionList.end(); ++itr)
+ if ((*itr)->IsInBetween(caster, unit))
+ return true;
+
+ return false;
+ }
+
+ Unit* caster;
+ std::list<Unit*> const& collisionList;
+};
+
+class spell_sindragosa_collision_filter : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_collision_filter() : SpellScriptLoader("spell_sindragosa_collision_filter") { }
+
+ class spell_sindragosa_collision_filter_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sindragosa_collision_filter_SpellScript);
+
+ void FilterTargets(std::list<Unit*>& unitList)
+ {
+ std::list<Unit*> tombs;
+ for (std::list<Unit*>::const_iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
+ if ((*itr)->HasAura(SPELL_ICE_TOMB_DAMAGE))
+ tombs.push_back(*itr);
+
+ unitList.remove_if(FrostBombTargetSelector(GetCaster(), tombs));
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_collision_filter_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sindragosa_collision_filter_SpellScript();
+ }
+};
+
+class spell_rimefang_icy_blast : public SpellScriptLoader
+{
+ public:
+ spell_rimefang_icy_blast() : SpellScriptLoader("spell_rimefang_icy_blast") { }
+
+ class spell_rimefang_icy_blast_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_rimefang_icy_blast_SpellScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_ICY_BLAST_AREA))
+ return false;
+ return true;
+ }
+
+ void HandleTriggerMissile(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Position* pos = GetTargetDest())
+ if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICY_BLAST, *pos, TEMPSUMMON_TIMED_DESPAWN, 40000))
+ summon->CastSpell(summon, SPELL_ICY_BLAST_AREA, true);
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_rimefang_icy_blast_SpellScript::HandleTriggerMissile, EFFECT_1, SPELL_EFFECT_TRIGGER_MISSILE);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_rimefang_icy_blast_SpellScript();
+ }
+};
+
+class OrderWhelpTargetSelector
+{
+ public:
+ explicit OrderWhelpTargetSelector(Creature* _owner) : owner(_owner) { }
+
+ bool operator()(Creature* creature)
+ {
+ if (!creature->AI()->GetData(DATA_WHELP_MARKER) && creature->AI()->GetData(DATA_FROSTWYRM_OWNER) == owner->AI()->GetData(DATA_FROSTWYRM_OWNER))
+ return false;
+ return true;
+ }
+
+ private:
+ Creature* owner;
+};
+
+class spell_frostwarden_handler_order_whelp : public SpellScriptLoader
+{
+ public:
+ spell_frostwarden_handler_order_whelp() : SpellScriptLoader("spell_frostwarden_handler_order_whelp") { }
+
+ class spell_frostwarden_handler_order_whelp_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_frostwarden_handler_order_whelp_SpellScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_FOCUS_FIRE))
+ return false;
+ return true;
+ }
+
+ void FilterTargets(std::list<Unit*>& unitList)
+ {
+ for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end();)
+ {
+ if ((*itr)->GetTypeId() != TYPEID_PLAYER)
+ unitList.erase(itr++);
+ else
+ ++itr;
+ }
+
+ std::list<Unit*>::iterator itr = unitList.begin();
+ std::advance(itr, urand(0, unitList.size()-1));
+ Unit* target = *itr;
+ unitList.clear();
+ unitList.push_back(target);
+ }
+
+ void HandleForcedCast(SpellEffIndex effIndex)
+ {
+ // caster is Frostwarden Handler, target is player, caster of triggered is whelp
+ PreventHitDefaultEffect(effIndex);
+ std::list<Creature*> unitList;
+ GetCreatureListWithEntryInGrid(unitList, GetCaster(), NPC_FROSTWING_WHELP, 150.0f);
+ if (Creature* creature = GetCaster()->ToCreature())
+ unitList.remove_if(OrderWhelpTargetSelector(creature));
+
+ std::list<Creature*>::iterator itr = unitList.begin();
+ std::advance(itr, urand(0, unitList.size()-1));
+ (*itr)->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_frostwarden_handler_order_whelp_SpellScript::HandleForcedCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_DST);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_frostwarden_handler_order_whelp_SpellScript();
+ }
+};
+
+class spell_frostwarden_handler_focus_fire : public SpellScriptLoader
+{
+ public:
+ spell_frostwarden_handler_focus_fire() : SpellScriptLoader("spell_frostwarden_handler_focus_fire") { }
+
+ class spell_frostwarden_handler_focus_fire_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_frostwarden_handler_focus_fire_SpellScript);
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->AddThreat(GetHitUnit(), float(GetEffectValue()));
+ GetCaster()->GetAI()->SetData(DATA_WHELP_MARKER, 1);
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_frostwarden_handler_focus_fire_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ class spell_frostwarden_handler_focus_fire_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_frostwarden_handler_focus_fire_AuraScript);
+
+ void PeriodicTick(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+ if (Unit* caster = GetCaster())
+ {
+ caster->AddThreat(GetTarget(), -float(SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_1)));
+ caster->GetAI()->SetData(DATA_WHELP_MARKER, 0);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_frostwarden_handler_focus_fire_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_frostwarden_handler_focus_fire_SpellScript();
+ }
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_frostwarden_handler_focus_fire_AuraScript();
+ }
+};
+
+class spell_trigger_spell_from_caster : public SpellScriptLoader
+{
+ public:
+ spell_trigger_spell_from_caster(char const* scriptName, uint32 _triggerId) : SpellScriptLoader(scriptName), triggerId(_triggerId) { }
+
+ class spell_trigger_spell_from_caster_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_trigger_spell_from_caster_SpellScript);
+
+ public:
+ spell_trigger_spell_from_caster_SpellScript(uint32 _triggerId) : SpellScript(), triggerId(_triggerId) { }
+
+ void HandleTrigger()
+ {
+ GetCaster()->CastSpell(GetHitUnit(), triggerId, true);
+ }
+
+ void Register()
+ {
+ AfterHit += SpellHitFn(spell_trigger_spell_from_caster_SpellScript::HandleTrigger);
+ }
+
+ uint32 triggerId;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_trigger_spell_from_caster_SpellScript(triggerId);
+ }
+
+ private:
+ uint32 triggerId;
+};
+
+class at_sindragosa_lair : public AreaTriggerScript
+{
+ public:
+ at_sindragosa_lair() : AreaTriggerScript("at_sindragosa_lair") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/)
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ {
+ if (!instance->GetData(DATA_SPINESTALKER))
+ if (Creature* spinestalker = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_SPINESTALKER)))
+ spinestalker->AI()->DoAction(ACTION_START_FROSTWYRM);
+
+ if (!instance->GetData(DATA_RIMEFANG))
+ if (Creature* rimefang = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_RIMEFANG)))
+ rimefang->AI()->DoAction(ACTION_START_FROSTWYRM);
+
+ if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && instance->GetBossState(DATA_SINDRAGOSA) != DONE)
+ {
+ player->GetMap()->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY());
+ if (Creature* sindragosa = player->GetMap()->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos))
+ {
+ sindragosa->setActive(true);
+ sindragosa->AI()->DoAction(ACTION_START_FROSTWYRM);
+ }
+ }
+ }
+
+ return true;
+ }
+};
+
+class achievement_all_you_can_eat : public AchievementCriteriaScript
+{
+ public:
+ achievement_all_you_can_eat() : AchievementCriteriaScript("achievement_all_you_can_eat") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ if (!target)
+ return false;
+ return target->GetAI()->GetData(DATA_MYSTIC_BUFFET_STACK) <= 5;
+ }
+};
+
+void AddSC_boss_sindragosa()
+{
+ new boss_sindragosa();
+ new npc_ice_tomb();
+ new npc_spinestalker();
+ new npc_rimefang();
+ new npc_sindragosa_trash();
+ new spell_sindragosa_s_fury();
+ new spell_sindragosa_unchained_magic();
+ new spell_sindragosa_instability();
+ new spell_sindragosa_frost_beacon();
+ new spell_sindragosa_ice_tomb();
+ new spell_sindragosa_collision_filter();
+ new spell_rimefang_icy_blast();
+ new spell_frostwarden_handler_order_whelp();
+ new spell_frostwarden_handler_focus_fire();
+ new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY);
+ new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON);
+ new at_sindragosa_lair();
+ new achievement_all_you_can_eat();
+}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index 6eac43f391e..0c00b4e7a74 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -65,6 +65,9 @@ enum DataTypes
DATA_PRINCE_TALDARAM_GUID = 19,
DATA_PRINCE_VALANAR_GUID = 20,
DATA_BLOOD_PRINCES_CONTROL = 21,
+ DATA_SINDRAGOSA_FROSTWYRMS = 22,
+ DATA_SPINESTALKER = 23,
+ DATA_RIMEFANG = 24,
};
#define MAX_ENCOUNTER 12
@@ -150,6 +153,16 @@ enum CreaturesIds
// Blood-Queen Lana'thel
NPC_BLOOD_QUEEN_LANA_THEL = 37955,
+
+ // Sindragosa
+ NPC_SINDRAGOSA = 36853,
+ NPC_SPINESTALKER = 37534,
+ NPC_RIMEFANG = 37533,
+ NPC_FROSTWARDEN_HANDLER = 37531,
+ NPC_FROSTWING_WHELP = 37532,
+ NPC_ICY_BLAST = 38223,
+ NPC_FROST_BOMB = 37186,
+ NPC_ICE_TOMB = 36980,
};
enum GameObjectsIds
@@ -199,6 +212,8 @@ enum GameObjectsIds
GO_SINDRAGOSA_ENTRANCE_DOOR = 201373,
GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR = 201369,
GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR = 201379,
+ GO_ICE_WALL = 202396,
+ GO_ICE_BLOCK = 201722,
};
enum AchievementCriteriaIds
@@ -247,7 +262,14 @@ enum SharedActions
ACTION_ROTFACE_COMBAT = -366270,
ACTION_ROTFACE_OOZE = -366271,
ACTION_ROTFACE_DEATH = -366272,
- ACTION_CHANGE_PHASE = -366780
+ ACTION_CHANGE_PHASE = -366780,
+
+ // Sindragosa
+ ACTION_START_FROSTWYRM = -368530,
+ ACTION_TRIGGER_ASPHYXIATION = -368531,
};
+// Declaration
+extern Position const SindragosaSpawnPos;
+
#endif // DEF_ICECROWN_CITADEL_H
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index c739364d23d..f3fbef29ce8 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -39,8 +39,10 @@ static const DoorData doorData[] =
{GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM, BOUNDARY_N },
{GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_S },
- {GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_E },
+ {GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
+ {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SE },
+ {GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SW },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
};
@@ -72,6 +74,12 @@ class instance_icecrown_citadel : public InstanceMapScript
memset(bloodCouncil, 0, 3*sizeof(uint64));
bloodCouncilController = 0;
bloodQueenLanaThel = 0;
+ sindragosa = 0;
+ spinestalker = 0;
+ rimefang = 0;
+ frostwyrms = 0;
+ spinestalkerTrash = 0;
+ rimefangTrash = 0;
isBonedEligible = true;
isOozeDanceEligible = true;
isNauseaEligible = true;
@@ -170,6 +178,19 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_BLOOD_QUEEN_LANA_THEL:
bloodQueenLanaThel = creature->GetGUID();
break;
+ case NPC_SINDRAGOSA:
+ sindragosa = creature->GetGUID();
+ break;
+ case NPC_SPINESTALKER:
+ spinestalker = creature->GetGUID();
+ if (!creature->isDead())
+ ++frostwyrms;
+ break;
+ case NPC_RIMEFANG:
+ rimefang = creature->GetGUID();
+ if (!creature->isDead())
+ ++frostwyrms;
+ break;
default:
break;
}
@@ -196,6 +217,7 @@ class instance_icecrown_citadel : public InstanceMapScript
case GO_SINDRAGOSA_ENTRANCE_DOOR:
case GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR:
case GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR:
+ case GO_ICE_WALL:
AddDoor(go, true);
break;
case GO_LADY_DEATHWHISPER_ELEVATOR:
@@ -276,6 +298,7 @@ class instance_icecrown_citadel : public InstanceMapScript
case GO_SINDRAGOSA_ENTRANCE_DOOR:
case GO_SINDRAGOSA_SHORTCUT_ENTRANCE_DOOR:
case GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR:
+ case GO_ICE_WALL:
AddDoor(go, false);
break;
default:
@@ -283,6 +306,23 @@ class instance_icecrown_citadel : public InstanceMapScript
}
}
+ uint32 GetData(uint32 type)
+ {
+ switch (type)
+ {
+ case DATA_SINDRAGOSA_FROSTWYRMS:
+ return frostwyrms;
+ case DATA_SPINESTALKER:
+ return spinestalkerTrash;
+ case DATA_RIMEFANG:
+ return rimefangTrash;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
uint64 GetData64(uint32 type)
{
switch (type)
@@ -313,6 +353,12 @@ class instance_icecrown_citadel : public InstanceMapScript
return bloodCouncilController;
case DATA_BLOOD_QUEEN_LANA_THEL:
return bloodQueenLanaThel;
+ case DATA_SINDRAGOSA:
+ return sindragosa;
+ case DATA_SPINESTALKER:
+ return spinestalker;
+ case DATA_RIMEFANG:
+ return rimefang;
default:
break;
}
@@ -411,6 +457,39 @@ class instance_icecrown_citadel : public InstanceMapScript
case DATA_ORB_WHISPERER_ACHIEVEMENT:
isOrbWhispererEligible = data ? true : false;
break;
+ case DATA_SINDRAGOSA_FROSTWYRMS:
+ if (data > 1)
+ frostwyrms = data;
+ else if (data == 1)
+ ++frostwyrms;
+ else if (!data && !--frostwyrms && GetBossState(DATA_SINDRAGOSA) != DONE)
+ {
+ instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY());
+ if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos))
+ {
+ boss->setActive(true);
+ boss->AI()->DoAction(ACTION_START_FROSTWYRM);
+ }
+ }
+ break;
+ case DATA_SPINESTALKER:
+ if (data > 1)
+ spinestalkerTrash = data;
+ else if (data == 1)
+ ++spinestalkerTrash;
+ else if (!data && !--spinestalkerTrash)
+ if (Creature* spinestalk = instance->GetCreature(spinestalker))
+ spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM);
+ break;
+ case DATA_RIMEFANG:
+ if (data > 1)
+ rimefangTrash = data;
+ else if (data == 1)
+ ++rimefangTrash;
+ else if (!data && !--rimefangTrash)
+ if (Creature* rime = instance->GetCreature(rimefang))
+ rime->AI()->DoAction(ACTION_START_FROSTWYRM);
+ break;
default:
break;
}
@@ -544,8 +623,8 @@ class instance_icecrown_citadel : public InstanceMapScript
return false;
// no break
case DATA_SINDRAGOSA:
- if (GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
- return false;
+ //if (GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
+ // return false;
break;
default:
break;
@@ -647,7 +726,13 @@ class instance_icecrown_citadel : public InstanceMapScript
uint64 bloodCouncil[3];
uint64 bloodCouncilController;
uint64 bloodQueenLanaThel;
+ uint64 sindragosa;
+ uint64 spinestalker;
+ uint64 rimefang;
uint32 teamInInstance;
+ uint8 frostwyrms;
+ uint8 spinestalkerTrash;
+ uint8 rimefangTrash;
bool isBonedEligible;
bool isOozeDanceEligible;
bool isNauseaEligible;