aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/world_database.sql9
-rw-r--r--sql/scripts/world_script_texts.sql15
-rw-r--r--sql/scripts/world_scripts_full.sql6
-rw-r--r--sql/updates/9453_world_script_texts.sql12
-rw-r--r--sql/updates/9453_world_scriptname.sql7
-rw-r--r--sql/updates/9453_world_spell_script_names.sql13
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp4
-rw-r--r--src/server/game/Spells/SpellEffects.cpp21
-rw-r--r--src/server/game/Spells/SpellMgr.cpp12
-rw-r--r--src/server/scripts/Northrend/Icecrown Citadel/boss_lord_marrowgar.cpp523
-rw-r--r--src/server/scripts/Northrend/Icecrown Citadel/icecrown_citadel.h69
-rw-r--r--src/server/scripts/Northrend/Icecrown Citadel/instance_icecrown_citadel.cpp209
12 files changed, 899 insertions, 1 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql
index eb34af2f546..8e3aab2680c 100644
--- a/sql/base/world_database.sql
+++ b/sql/base/world_database.sql
@@ -14740,6 +14740,15 @@ LOCK TABLES `spell_script_names` WRITE;
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
-- generic
( 58601, 'spell_gen_remove_flight_auras'),
+-- instances
+( 69057, 'spell_marrowgar_bone_spike_graveyard'),
+( 69140, 'spell_marrowgar_coldflame'),
+( 72705, 'spell_marrowgar_coldflame'),
+( 69147, 'spell_marrowgar_coldflame_trigger'),
+( 69075, 'spell_marrowgar_bone_storm'),
+( 70834, 'spell_marrowgar_bone_storm'),
+( 70835, 'spell_marrowgar_bone_storm'),
+( 70836, 'spell_marrowgar_bone_storm'),
-- quest
( 45449, 'spell_q11587_arcane_prisoner_rescue'),
( 46023, 'spell_q11730_ultrasonic_screwdriver'),
diff --git a/sql/scripts/world_script_texts.sql b/sql/scripts/world_script_texts.sql
index 5273d18ca90..9e35b9a7b49 100644
--- a/sql/scripts/world_script_texts.sql
+++ b/sql/scripts/world_script_texts.sql
@@ -2637,7 +2637,20 @@ INSERT INTO `script_texts` (`npc_entry`,`entry`,`content_default`,`content_loc1`
(29308,-1619026,'Fresh, warm blood. It has been too long.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0,0,'prince taldaram SAY_FEED2'),
(29308,-1619027,'Your heartbeat is music to my ears.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0,0,'prince taldaram SAY_VANISH1'),
(29308,-1619028,'I am nowhere. I am everywhere. I am the watcher, unseen.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0,0,'prince taldaram SAY_VANISH2'),
-
+
+-- -1 631 000 ICECROWN CITADEL: RAID
+-- Lord Marrowgar
+ (36612,-1631000,'This is the beginning AND the end, mortals. None may enter the master''s sanctum!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16950,1,0,0,'SAY_ENTER_ZONE'),
+ (36612,-1631001,'The Scourge will wash over this world as a swarm of death and destruction!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16941,1,0,0,'SAY_AGGRO'),
+ (36612,-1631002,'BONE STORM!',NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,16946,1,0,0,'SAY_BONE_STORM'),
+ (36612,-1631003,'Bound by bone!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16947,1,0,0, 'SAY_BONESPIKE_1'),
+ (36612,-1631004,'Stick Around!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16948,1,0,0,'SAY_BONESPIKE_2'),
+ (36612,-1631005,'The only escape is death!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16949,1,0,0,'SAY_BONESPIKE_3'),
+ (36612,-1631006,'More bones for the offering!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16942,1,0,0,'SAY_KILL_1'),
+ (36612,-1631007,'Languish in damnation!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16943,1,0,0,'SAY_KILL_2'),
+ (36612,-1631008,'I see... only darkness...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16944,1,0,0,'SAY_DEATH'),
+ (36612,-1631009,'THE MASTER''S RAGE COURSES THROUGH ME!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16945,1,0,0,'SAY_BERSERK');
+
-- -1 632 000 ICECROWN CITADEL: FROZEN HALLS: FORGE OF SOULS
-- Bronjham
(36497,-1632001,'Finally...a captive audience!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16595,1,0,0,'Bronjham SAY_AGGRO'),
diff --git a/sql/scripts/world_scripts_full.sql b/sql/scripts/world_scripts_full.sql
index ca91bfdd43b..fbdf1d5c863 100644
--- a/sql/scripts/world_scripts_full.sql
+++ b/sql/scripts/world_scripts_full.sql
@@ -826,6 +826,12 @@ UPDATE `creature_template` SET `ScriptName`='npc_argent_tournament_post' WHERE `
UPDATE `creature_template` SET `ScriptName`='npc_alorah_and_grimmin' WHERE `entry` IN (36101,36102);
UPDATE `creature_template` SET `ScriptName`='npc_guardian_pavilion' WHERE `entry` IN (33543,33643);
+/* ICECROWN CITADEL */
+UPDATE `instance_template` SET `script`='instance_icecrown_citadel' WHERE `map`=631;
+UPDATE `creature_template` SET `ScriptName`='boss_lord_marrowgar' WHERE `entry`=36612;
+UPDATE `creature_template` SET `ScriptName`='npc_coldflame' WHERE `entry`=36672;
+UPDATE `creature_template` SET `ScriptName`='npc_bone_spike' WHERE `entry`=38711;
+
/* IRONFORGE */
UPDATE `creature_template` SET `ScriptName`='npc_royal_historian_archesonus' WHERE `entry`=8879;
diff --git a/sql/updates/9453_world_script_texts.sql b/sql/updates/9453_world_script_texts.sql
new file mode 100644
index 00000000000..956ca43ccb2
--- /dev/null
+++ b/sql/updates/9453_world_script_texts.sql
@@ -0,0 +1,12 @@
+DELETE FROM `script_texts` WHERE `entry` BETWEEN -1631999 AND -1631000;
+INSERT INTO `script_texts` (`npc_entry`,`entry`,`content_default`,`content_loc1`,`content_loc2`,`content_loc3`,`content_loc4`,`content_loc5`,`content_loc6`,`content_loc7`,`content_loc8`,`sound`,`type`,`language`,`emote`,`comment`) VALUES
+(36612,-1631000,'This is the beginning AND the end, mortals. None may enter the master''s sanctum!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16950,1,0,0,'SAY_ENTER_ZONE'),
+(36612,-1631001,'The Scourge will wash over this world as a swarm of death and destruction!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16941,1,0,0,'SAY_AGGRO'),
+(36612,-1631002,'BONE STORM!',NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,16946,1,0,0,'SAY_BONE_STORM'),
+(36612,-1631003,'Bound by bone!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16947,1,0,0, 'SAY_BONESPIKE_1'),
+(36612,-1631004,'Stick Around!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16948,1,0,0,'SAY_BONESPIKE_2'),
+(36612,-1631005,'The only escape is death!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16949,1,0,0,'SAY_BONESPIKE_3'),
+(36612,-1631006,'More bones for the offering!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16942,1,0,0,'SAY_KILL_1'),
+(36612,-1631007,'Languish in damnation!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16943,1,0,0,'SAY_KILL_2'),
+(36612,-1631008,'I see... only darkness...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16944,1,0,0,'SAY_DEATH'),
+(36612,-1631009,'THE MASTER''S RAGE COURSES THROUGH ME!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16945,1,0,0,'SAY_BERSERK');
diff --git a/sql/updates/9453_world_scriptname.sql b/sql/updates/9453_world_scriptname.sql
new file mode 100644
index 00000000000..9b1c3617496
--- /dev/null
+++ b/sql/updates/9453_world_scriptname.sql
@@ -0,0 +1,7 @@
+-- Lord Marrowgar
+UPDATE `creature_template` SET `ScriptName`='boss_lord_marrowgar' WHERE `entry`=36612;
+UPDATE `creature_template` SET `ScriptName`='npc_coldflame' WHERE `entry`=36672;
+UPDATE `creature_template` SET `ScriptName`='npc_bone_spike' WHERE `entry`=38711;
+
+-- Instance
+UPDATE `instance_template` SET `script`='instance_icecrown_citadel' WHERE `map`=631;
diff --git a/sql/updates/9453_world_spell_script_names.sql b/sql/updates/9453_world_spell_script_names.sql
new file mode 100644
index 00000000000..cae78c9a8b9
--- /dev/null
+++ b/sql/updates/9453_world_spell_script_names.sql
@@ -0,0 +1,13 @@
+DELETE FROM `spell_script_names` WHERE `spell_id`=69057 AND `ScriptName`='spell_marrowgar_bone_spike_graveyard';
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (69140,72705) AND `ScriptName`='spell_marrowgar_coldflame';
+DELETE FROM `spell_script_names` WHERE `spell_id`=69147 AND `ScriptName`='spell_marrowgar_coldflame_trigger';
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (69075,70834,70835,70836) AND `ScriptName`='spell_marrowgar_bone_storm';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(69057,'spell_marrowgar_bone_spike_graveyard'),
+(69140,'spell_marrowgar_coldflame'),
+(72705,'spell_marrowgar_coldflame'),
+(69147,'spell_marrowgar_coldflame_trigger'),
+(69075,'spell_marrowgar_bone_storm'),
+(70834,'spell_marrowgar_bone_storm'),
+(70835,'spell_marrowgar_bone_storm'),
+(70836,'spell_marrowgar_bone_storm');
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index e40b9736712..6cc04d14f3a 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -417,6 +417,8 @@ void AddSC_instance_halls_of_reflection(); // Halls of Reflection
void AddSC_halls_of_reflection();
void AddSC_boss_falric();
void AddSC_boss_marwyn();
+void AddSC_boss_lord_marrowgar(); // Icecrown Citadel
+void AddSC_instance_icecrown_citadel();
void AddSC_dalaran();
void AddSC_borean_tundra();
@@ -1079,6 +1081,8 @@ void AddNorthrendScripts()
AddSC_halls_of_reflection();
AddSC_boss_falric();
AddSC_boss_marwyn();
+ AddSC_boss_lord_marrowgar(); // Icecrown Citadel
+ AddSC_instance_icecrown_citadel();
AddSC_dalaran();
AddSC_borean_tundra();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 09ef6e4b7b2..46e01b38958 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2041,6 +2041,9 @@ void Spell::EffectTriggerSpell(uint32 effIndex)
case 57879:
originalCaster = m_originalCaster;
break;
+ // Coldflame
+ case 33801:
+ return; // just make the core stfu
}
// normal case
@@ -4193,6 +4196,24 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
switch (m_spellInfo->SpellFamilyName)
{
+ case SPELLFAMILY_GENERIC:
+ {
+ switch (m_spellInfo->Id)
+ {
+ case 69055: // Saber Lash
+ case 70814: // Saber Lash
+ {
+ uint32 count = 0;
+ for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ if (ihit->effectMask & (1 << i))
+ ++count;
+
+ totalDamagePercentMod /= count;
+ break;
+ }
+ }
+ break;
+ }
case SPELLFAMILY_WARRIOR:
{
// Devastate (player ones)
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index fd936a130d6..31926eb5ced 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3841,6 +3841,18 @@ void SpellMgr::LoadSpellCustomAttr()
spellInfo->AttributesEx |= SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY;
count++;
break;
+ case 69055: // Saber Lash
+ case 70814: // Saber Lash
+ spellInfo->EffectRadiusIndex[0] = 8;
+ count++;
+ break;
+ case 69075: // Bone Storm
+ case 70834: // Bone Storm
+ case 70835: // Bone Storm
+ case 70836: // Bone Storm
+ spellInfo->EffectRadiusIndex[0] = 12;
+ count++;
+ break;
default:
break;
}
diff --git a/src/server/scripts/Northrend/Icecrown Citadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/Icecrown Citadel/boss_lord_marrowgar.cpp
new file mode 100644
index 00000000000..9545781b5ad
--- /dev/null
+++ b/src/server/scripts/Northrend/Icecrown Citadel/boss_lord_marrowgar.cpp
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ScriptPCH.h"
+#include "icecrown_citadel.h"
+#include "MapManager.h"
+
+enum eScriptTexts
+{
+ SAY_ENTER_ZONE = -1631000,
+ SAY_AGGRO = -1631001,
+ SAY_BONE_STORM = -1631002,
+ SAY_BONESPIKE_1 = -1631003,
+ SAY_BONESPIKE_2 = -1631004,
+ SAY_BONESPIKE_3 = -1631005,
+ SAY_KILL_1 = -1631006,
+ SAY_KILL_2 = -1631007,
+ SAY_DEATH = -1631008,
+ SAY_BERSERK = -1631009,
+};
+
+enum eSpells
+{
+ // Lord Marrowgar
+ SPELL_BONE_SLICE = 69055,
+ SPELL_BONE_STORM = 69076,
+ SPELL_BONE_SPIKE_GRAVEYARD = 69057,
+ SPELL_COLDFLAME_NORMAL = 69140,
+ SPELL_COLDFLAME_BONE_STORM = 72705,
+
+ // Bone Spike
+ SPELL_IMPALED = 69065,
+
+ // Coldflame
+ SPELL_COLDFLAME_PASSIVE = 69145,
+};
+
+enum eEvents
+{
+ EVENT_BONE_SPIKE_GRAVEYARD = 1,
+ EVENT_COLDFLAME = 2,
+ EVENT_BONE_STORM_BEGIN = 3,
+ EVENT_BONE_STORM_MOVE = 4,
+ EVENT_BONE_STORM_END = 5,
+ EVENT_ENABLE_BONE_SLICE = 6,
+ EVENT_ENRAGE = 7,
+
+ EVENT_COLDFLAME_TRIGGER = 8,
+ EVENT_FAIL_BONED = 9
+};
+
+enum eMovementPoints
+{
+ POINT_TARGET_BONESTORM_PLAYER = 36612631, // entry+mapid
+ POINT_TARGET_COLDFLAME = 36672631
+};
+
+class boss_lord_marrowgar : public CreatureScript
+{
+ public:
+ boss_lord_marrowgar() : CreatureScript("boss_lord_marrowgar") { }
+
+ struct boss_lord_marrowgarAI : public ScriptedAI
+ {
+ boss_lord_marrowgarAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ uiBoneStormDuration = RAID_MODE(20000,30000,20000,30000);
+ fBaseSpeed = pCreature->GetSpeedRate(MOVE_RUN);
+ bIntroDone = false;
+ pInstance = pCreature->GetInstanceScript();
+ }
+
+ void Reset()
+ {
+ me->SetSpeed(MOVE_RUN, fBaseSpeed, true);
+ me->RemoveAurasDueToSpell(SPELL_BONE_STORM);
+ events.Reset();
+ events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000);
+ events.ScheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, urand(20000, 35000));
+ events.ScheduleEvent(EVENT_COLDFLAME, urand(15000, 25000));
+ events.ScheduleEvent(EVENT_BONE_STORM_BEGIN, urand(35000, 50000));
+ events.ScheduleEvent(EVENT_ENRAGE, 600000);
+ if (pInstance)
+ pInstance->SetData(DATA_LORD_MARROWGAR, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, me);
+
+ if (pInstance)
+ pInstance->SetData(DATA_LORD_MARROWGAR, IN_PROGRESS);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, me);
+
+ if (pInstance)
+ pInstance->SetData(DATA_LORD_MARROWGAR, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ if(pInstance)
+ pInstance->SetData(DATA_LORD_MARROWGAR, FAIL);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ DoScriptText(RAND(SAY_KILL_1, SAY_KILL_2), me);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (!bIntroDone && me->IsWithinDistInMap(who, 70.0f))
+ {
+ DoScriptText(SAY_ENTER_ZONE, me);
+ bIntroDone = true;
+ }
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ 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_BONE_SPIKE_GRAVEYARD:
+ if (IsHeroic() || !me->HasAura(SPELL_BONE_STORM))
+ DoCast(me, SPELL_BONE_SPIKE_GRAVEYARD);
+ events.ScheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, urand(25000, 35000));
+ break;
+ case EVENT_COLDFLAME:
+ if (!me->HasAura(SPELL_BONE_STORM))
+ DoCast(me, SPELL_COLDFLAME_NORMAL);
+ else
+ DoCast(me, SPELL_COLDFLAME_BONE_STORM);
+ events.ScheduleEvent(EVENT_COLDFLAME, urand(20000, 30000));
+ break;
+ case EVENT_BONE_STORM_BEGIN:
+ {
+ bBoneSlice = false;
+ DoScriptText(SAY_BONE_STORM, me);
+ events.ScheduleEvent(EVENT_BONE_STORM_END, uiBoneStormDuration+1);
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_BONE_STORM);
+ if (Aura* pStorm = me->AddAura(spellInfo, 3, me))
+ pStorm->SetDuration(int32(uiBoneStormDuration));
+ me->FinishSpell(CURRENT_MELEE_SPELL, false);
+ me->SetSpeed(MOVE_RUN, fBaseSpeed*3.0f, true);
+ // no break here
+ }
+ case EVENT_BONE_STORM_MOVE:
+ {
+ events.ScheduleEvent(EVENT_BONE_STORM_MOVE, uiBoneStormDuration/3);
+ Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 1);
+ if (!pUnit)
+ pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0);
+ if (pUnit)
+ me->GetMotionMaster()->MovePoint(POINT_TARGET_BONESTORM_PLAYER, pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ());
+ break;
+ }
+ case EVENT_BONE_STORM_END:
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
+ me->GetMotionMaster()->MovementExpired();
+ DoStartMovement(me->getVictim());
+ me->SetSpeed(MOVE_RUN, fBaseSpeed, true);
+ events.CancelEvent(EVENT_BONE_STORM_MOVE);
+ events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000);
+ events.ScheduleEvent(EVENT_BONE_STORM_BEGIN, urand(35000, 50000));
+ break;
+ case EVENT_ENABLE_BONE_SLICE:
+ bBoneSlice = true;
+ break;
+ case EVENT_ENRAGE:
+ DoCast(me, SPELL_BERSERK, true);
+ break;
+ }
+ }
+
+ // We should not melee attack when storming
+ if (me->HasAura(SPELL_BONE_STORM))
+ return;
+
+ // After 10 seconds since encounter start Bone Slice replaces melee attacks
+ if (bBoneSlice && !me->GetCurrentSpell(CURRENT_MELEE_SPELL))
+ DoCastVictim(SPELL_BONE_SLICE);
+
+ DoMeleeAttackIfReady();
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type != POINT_MOTION_TYPE || id != POINT_TARGET_BONESTORM_PLAYER)
+ return;
+
+ // lock movement
+ DoStartNoMovement(me->getVictim());
+ }
+
+ private:
+
+ EventMap events;
+ InstanceScript* pInstance;
+ bool bIntroDone;
+ uint32 uiBoneStormDuration;
+ float fBaseSpeed;
+ bool bBoneSlice;
+ };
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new boss_lord_marrowgarAI(pCreature);
+ }
+};
+
+class npc_coldflame : public CreatureScript
+{
+ public:
+ npc_coldflame() : CreatureScript("npc_coldflame") { }
+
+ struct npc_coldflameAI : public ScriptedAI
+ {
+ npc_coldflameAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ }
+
+ void IsSummonedBy(Unit* owner)
+ {
+ DoCast(me, SPELL_COLDFLAME_PASSIVE, true);
+ float x, y, z;
+ // random target case
+ if (!owner->HasAura(SPELL_BONE_STORM) && owner->GetTypeId() == TYPEID_UNIT)
+ {
+ Creature* creOwner = owner->ToCreature();
+ // select any unit but not the tank (by owners threatlist)
+ Unit* target = creOwner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, 40.0f, true);
+ if (!target)
+ target = creOwner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true); // or the tank if its solo
+ if (!target)
+ {
+ me->ForcedDespawn();
+ return;
+ }
+
+ target->GetPosition(x, y, z);
+ float scale = 50.0f / me->GetExactDist2d(x, y);
+ x = me->GetPositionX() + (x - me->GetPositionX()) * scale;
+ y = me->GetPositionY() + (y - me->GetPositionY()) * scale;
+ }
+ else
+ {
+ me->GetPosition(x, y, z);
+ float ang = me->GetAngle(owner) - static_cast<float>(M_PI);
+ MapManager::NormalizeOrientation(ang);
+ x += 35.0f * cosf(ang);
+ y += 35.0f * sinf(ang);
+ }
+ me->GetMotionMaster()->MovePoint(POINT_TARGET_COLDFLAME, x, y, z);
+ events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 400);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ if (eventId == EVENT_COLDFLAME_TRIGGER)
+ {
+ if (me->HasAura(SPELL_COLDFLAME_PASSIVE))
+ DoCast(SPELL_COLDFLAME_PASSIVE);
+ events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 400);
+ }
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type != POINT_MOTION_TYPE || id != POINT_TARGET_COLDFLAME)
+ return;
+
+ // stop triggering but dont despawn
+ me->RemoveAura(SPELL_COLDFLAME_PASSIVE);
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new npc_coldflameAI(pCreature);
+ }
+};
+
+class npc_bone_spike : public CreatureScript
+{
+ public:
+ npc_bone_spike() : CreatureScript("npc_bone_spike") { }
+
+ struct npc_bone_spikeAI : public Scripted_NoMovementAI
+ {
+ npc_bone_spikeAI(Creature *pCreature) : Scripted_NoMovementAI(pCreature)
+ {
+ uiTrappedGUID = 0;
+ }
+
+ void Reset()
+ {
+ uiTrappedGUID = 0;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ events.Reset();
+ if (Unit* trapped = Unit::GetUnit((*me), uiTrappedGUID))
+ {
+ trapped->RemoveAurasDueToSpell(SPELL_IMPALED);
+ trapped->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ }
+ }
+
+ void KilledUnit(Unit *pVictim)
+ {
+ me->Kill(me);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!uiTrappedGUID)
+ return;
+
+ events.Update(diff);
+ Unit* trapped = Unit::GetUnit(*me, uiTrappedGUID);
+ if ((trapped && trapped->isAlive() && !trapped->HasAura(SPELL_IMPALED)) || !trapped)
+ me->Kill(me);
+
+ if (events.ExecuteEvent() == EVENT_FAIL_BONED)
+ if (InstanceScript* instance = me->GetInstanceScript())
+ instance->SetData(COMMAND_FAIL_BONED, 0);
+ }
+
+ void SetTrappedUnit(Unit* unit)
+ {
+ uiTrappedGUID = unit->GetGUID();
+ float x, y, z;
+ me->GetPosition(x, y, z);
+ unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DROWNED);
+ DoCast(unit, SPELL_IMPALED, true);
+ unit->NearTeleportTo(x, y, z+3.0f, unit->GetOrientation(), false);
+ events.ScheduleEvent(EVENT_FAIL_BONED, 8000);
+ }
+
+ private:
+ uint64 uiTrappedGUID;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new npc_bone_spikeAI(pCreature);
+ }
+};
+
+class spell_marrowgar_coldflame : public SpellHandlerScript
+{
+ public:
+ spell_marrowgar_coldflame() : SpellHandlerScript("spell_marrowgar_coldflame") { }
+
+ class spell_marrowgar_coldflame_SpellScript : public SpellScript
+ {
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ uint8 count = 1;
+ if (GetSpellInfo()->Id == 72705)
+ count = 4;
+
+ for (uint8 i = 0; i < count; ++i)
+ GetCaster()->CastSpell(GetCaster(), SpellMgr::CalculateSpellEffectAmount(GetSpellInfo(), EFFECT_0)+i, true);
+ }
+
+ void Register()
+ {
+ EffectHandlers += EffectHandlerFn(spell_marrowgar_coldflame_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+
+ bool Load()
+ {
+ if (GetCaster()->GetEntry() != NPC_LORD_MARROWGAR)
+ return false;
+ return true;
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_marrowgar_coldflame_SpellScript();
+ }
+};
+
+class spell_marrowgar_bone_spike_graveyard : public SpellHandlerScript
+{
+ public:
+ spell_marrowgar_bone_spike_graveyard() : SpellHandlerScript("spell_marrowgar_bone_spike_graveyard") { }
+
+ class spell_marrowgar_bone_spike_graveyard_SpellScript : public SpellScript
+ {
+ void HandleApplyAura(SpellEffIndex effIndex)
+ {
+ CreatureAI* marrowgarAI = GetCaster()->ToCreature()->AI();
+ bool yell = false;
+ uint8 boneSpikeCount = GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1;
+ for (uint8 i = 0; i < boneSpikeCount; ++i)
+ {
+ // select any unit but not the tank
+ Unit* target = marrowgarAI->SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -SPELL_IMPALED);
+ if (!target)
+ target = marrowgarAI->SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_IMPALED); // or the tank if its solo
+ if (!target)
+ break;
+ yell = true;
+ //marrowgarAI->DoCast(*itr, SPELL_IMPALE); // this is the proper spell but if we use it we dont have any way to assign a victim to it
+ Creature* pBone = GetCaster()->SummonCreature(NPC_BONE_SPIKE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN);
+ CAST_AI(npc_bone_spike::npc_bone_spikeAI, pBone->AI())->SetTrappedUnit(target);
+ }
+
+ if (yell)
+ DoScriptText(RAND(SAY_BONESPIKE_1, SAY_BONESPIKE_2, SAY_BONESPIKE_3), GetCaster());
+ }
+
+ void Register()
+ {
+ EffectHandlers += EffectHandlerFn(spell_marrowgar_bone_spike_graveyard_SpellScript::HandleApplyAura, EFFECT_1, SPELL_EFFECT_APPLY_AURA);
+ }
+
+ bool Load()
+ {
+ if (GetCaster()->GetEntry() != NPC_LORD_MARROWGAR)
+ return false;
+ return true;
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_marrowgar_bone_spike_graveyard_SpellScript();
+ }
+};
+
+class spell_marrowgar_bone_storm : public SpellHandlerScript
+{
+ public:
+ spell_marrowgar_bone_storm() : SpellHandlerScript("spell_marrowgar_bone_storm") { }
+
+ class spell_marrowgar_bone_storm_SpellScript : public SpellScript
+ {
+ void RecalculateDamage(SpellEffIndex effIndex)
+ {
+ int32 dmg = GetHitDamage();
+ float distance = GetHitUnit()->GetExactDist2d(GetCaster());
+ if (distance < 5.0f)
+ return;
+
+ float distVar = distance >= 20.0f ? 4 : (10.0f/3.0f);
+ dmg /= distance / distVar;
+ SetHitDamage(dmg);
+ }
+
+ void Register()
+ {
+ EffectHandlers += EffectHandlerFn(spell_marrowgar_bone_storm_SpellScript::RecalculateDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+
+ bool Load()
+ {
+ if (GetCaster()->GetEntry() != NPC_LORD_MARROWGAR)
+ return false;
+ return true;
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_marrowgar_bone_storm_SpellScript();
+ }
+};
+
+void AddSC_boss_lord_marrowgar()
+{
+ new boss_lord_marrowgar();
+ new npc_coldflame();
+ new npc_bone_spike();
+ new spell_marrowgar_coldflame();
+ new spell_marrowgar_bone_spike_graveyard();
+ new spell_marrowgar_bone_storm();
+}
diff --git a/src/server/scripts/Northrend/Icecrown Citadel/icecrown_citadel.h b/src/server/scripts/Northrend/Icecrown Citadel/icecrown_citadel.h
new file mode 100644
index 00000000000..083c1d27ba0
--- /dev/null
+++ b/src/server/scripts/Northrend/Icecrown Citadel/icecrown_citadel.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DEF_ICECROWN_CITADEL_H
+#define DEF_ICECROWN_CITADEL_H
+
+enum eSharedSpells
+{
+ SPELL_BERSERK = 26662
+};
+
+enum eData
+{
+ DATA_LORD_MARROWGAR = 0,
+ DATA_LADY_DEATHWHISPER = 1,
+ DATA_GUNSHIP_EVENT = 2,
+ DATA_DEATHBRINGER_SAURFANG = 3,
+ DATA_FESTERGUT = 4,
+ DATA_ROTFACE = 5,
+ DATA_PROFESSOR_PUTRICIDE = 6,
+ DATA_BLOOD_PRINCE_COUNCIL = 7,
+ DATA_BLOOD_QUEEN_LANA_THEL = 8,
+ DATA_VALITHRIA_DREAMWALKER = 9,
+ DATA_SINDRAGOSA = 10,
+ DATA_THE_LICH_KING = 11,
+
+ COMMAND_FAIL_BONED
+};
+
+#define MAX_ENCOUNTER 12
+
+enum eCreatures
+{
+ NPC_LORD_MARROWGAR = 36612,
+ NPC_COLDFLAME = 36672,
+ NPC_BONE_SPIKE = 38711
+};
+
+enum eGameobjects
+{
+ DOODAD_ICECROWN_ICEWALL02 = 201910,
+ ICEWALL = 201911,
+ LORD_MARROWGAR_S_ENTRANCE = 201857
+};
+
+enum eAchievementCriteria
+{
+ CRITERIA_BONED_10N = 12775,
+ CRITERIA_BONED_25N = 12962,
+ CRITERIA_BONED_10H = 13393,
+ CRITERIA_BONED_25H = 13394,
+};
+
+#endif // DEF_ICECROWN_CITADEL_H
diff --git a/src/server/scripts/Northrend/Icecrown Citadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/Icecrown Citadel/instance_icecrown_citadel.cpp
new file mode 100644
index 00000000000..78225570a5f
--- /dev/null
+++ b/src/server/scripts/Northrend/Icecrown Citadel/instance_icecrown_citadel.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ScriptPCH.h"
+#include "icecrown_citadel.h"
+
+class instance_icecrown_citadel : public InstanceMapScript
+{
+ public:
+ instance_icecrown_citadel() : InstanceMapScript("instance_icecrown_citadel", 631) { }
+
+ struct instance_icecrown_citadel_InstanceMapScript : public InstanceScript
+ {
+ instance_icecrown_citadel_InstanceMapScript(Map* pMap) : InstanceScript(pMap)
+ {
+ memset(uiEncounterState, 0, MAX_ENCOUNTER*sizeof(uint32));
+ memset(uiIcewall, 0, 2*sizeof(uint32));
+ uiMarrowgarEntrance = 0;
+ isBonedEgible = true;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (uiEncounterState[i] == IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+
+ void OnGameObjectCreate(GameObject* pGo, bool add)
+ {
+ switch (pGo->GetEntry())
+ {
+ case DOODAD_ICECROWN_ICEWALL02:
+ uiIcewall[0] = pGo->GetGUID();
+ if (GetData(DATA_LORD_MARROWGAR) == NOT_STARTED)
+ HandleGameObject(uiIcewall[0], false, pGo);
+ break;
+ case ICEWALL:
+ uiIcewall[1] = pGo->GetGUID();
+ if (GetData(DATA_LORD_MARROWGAR) == NOT_STARTED)
+ HandleGameObject(uiIcewall[1], false, pGo);
+ break;
+ case LORD_MARROWGAR_S_ENTRANCE:
+ uiMarrowgarEntrance = pGo->GetGUID();
+ if (GetData(DATA_LORD_MARROWGAR) == DONE)
+ HandleGameObject(uiMarrowgarEntrance, true, pGo);
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ switch (type)
+ {
+ case DATA_LORD_MARROWGAR:
+ case DATA_LADY_DEATHWHISPER:
+ case DATA_GUNSHIP_EVENT:
+ case DATA_DEATHBRINGER_SAURFANG:
+ case DATA_FESTERGUT:
+ case DATA_ROTFACE:
+ case DATA_PROFESSOR_PUTRICIDE:
+ case DATA_BLOOD_PRINCE_COUNCIL:
+ case DATA_BLOOD_QUEEN_LANA_THEL:
+ case DATA_VALITHRIA_DREAMWALKER:
+ case DATA_SINDRAGOSA:
+ case DATA_THE_LICH_KING:
+ return uiEncounterState[type];
+ }
+
+ return 0;
+ }
+
+ void SetData(uint32 type, uint32 data)
+ {
+ switch (type)
+ {
+ case DATA_LORD_MARROWGAR:
+ uiEncounterState[type] = data;
+ switch(data)
+ {
+ case DONE:
+ HandleGameObject(uiIcewall[0], true);
+ HandleGameObject(uiIcewall[1], true);
+ HandleGameObject(uiMarrowgarEntrance, true);
+ break;
+ case NOT_STARTED:
+ HandleGameObject(uiIcewall[0], false);
+ HandleGameObject(uiIcewall[1], false);
+ HandleGameObject(uiMarrowgarEntrance, true);
+ break;
+ case IN_PROGRESS:
+ HandleGameObject(uiMarrowgarEntrance, false);
+ break;
+ }
+ break;
+ case DATA_LADY_DEATHWHISPER:
+ case DATA_GUNSHIP_EVENT:
+ case DATA_DEATHBRINGER_SAURFANG:
+ case DATA_FESTERGUT:
+ case DATA_ROTFACE:
+ case DATA_PROFESSOR_PUTRICIDE:
+ case DATA_BLOOD_PRINCE_COUNCIL:
+ case DATA_BLOOD_QUEEN_LANA_THEL:
+ case DATA_VALITHRIA_DREAMWALKER:
+ case DATA_SINDRAGOSA:
+ case DATA_THE_LICH_KING:
+ uiEncounterState[type] = data;
+ break;
+
+ case COMMAND_FAIL_BONED:
+ isBonedEgible = data ? true : false;
+ }
+ }
+
+ bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/)
+ {
+ switch (criteria_id)
+ {
+ case CRITERIA_BONED_10N:
+ case CRITERIA_BONED_25N:
+ case CRITERIA_BONED_10H:
+ case CRITERIA_BONED_25H:
+ return isBonedEgible;
+ }
+
+ return false;
+ }
+
+ std::string GetSaveData()
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "I C ";
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ saveStream << uiEncounterState[i] << " ";
+
+ saveStream << isBonedEgible;
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
+ }
+
+ void Load(const char* in)
+ {
+ if (!in)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(in);
+
+ char dataHead1, dataHead2;
+
+ std::istringstream loadStream(in);
+ loadStream >> dataHead1 >> dataHead2;
+
+ if (dataHead1 == 'I' && dataHead2 == 'C')
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS)
+ tmpState = NOT_STARTED;
+ uiEncounterState[i] = tmpState;
+ }
+
+ loadStream >> isBonedEgible;
+ } else OUT_LOAD_INST_DATA_FAIL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ private:
+ uint32 uiEncounterState[MAX_ENCOUNTER];
+ uint64 uiIcewall[2];
+ uint64 uiMarrowgarEntrance;
+ bool isBonedEgible;
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* pMap) const
+ {
+ return new instance_icecrown_citadel_InstanceMapScript(pMap);
+ }
+};
+
+void AddSC_instance_icecrown_citadel()
+{
+ new instance_icecrown_citadel();
+}