aboutsummaryrefslogtreecommitdiff
path: root/src/scripts/northrend/ulduar
diff options
context:
space:
mode:
authorRat <none@none>2010-01-19 11:36:05 +0100
committerRat <none@none>2010-01-19 11:36:05 +0100
commit0cc053ea4d42ce405a915857f75ee00f0f65666b (patch)
tree7c25955ee5db618deee963f515ba061fbb1e1e8c /src/scripts/northrend/ulduar
parentf5dea61b66a616110cfc82ff640ec448b1efa702 (diff)
*Integrate Script system to Core
-added ScriptMgr for loading scripts -removed bindings -moved script system to src/game -moved scripts to src/scripts -VC project files updated -cmakes updated (not 100% done yet) NOTE to Devs: -file locations changed -precompiled renamed to ScriptedPch -ecsort_ai renamed to ScriptedEscortAI -follower_ai renamed to ScriptedFollowerAI -guard_ai renamed to ScriptedGuardAI -simple_ai renamed to ScriptedSimpleAI -sc_creature renamed to ScriptedCreature -sc_gossip renamed to ScriptedGossip -sc_instance renamed to ScriptedInstance *use the new headers in scripts, thank you NOTE to ALL: cmake not fully tested, please report any errors with it could make creashes, incompability USE AT YOUR OWN RISK before further tests!! --HG-- branch : trunk
Diffstat (limited to 'src/scripts/northrend/ulduar')
-rw-r--r--src/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp432
-rw-r--r--src/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp380
-rw-r--r--src/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp239
-rw-r--r--src/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp478
-rw-r--r--src/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h34
-rw-r--r--src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp237
-rw-r--r--src/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp148
-rw-r--r--src/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp177
-rw-r--r--src/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp300
-rw-r--r--src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp690
-rw-r--r--src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h48
-rw-r--r--src/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp254
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_algalon.cpp20
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp560
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp103
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp395
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_freya.cpp85
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp20
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_hodir.cpp89
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_ignis.cpp111
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp140
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp20
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp331
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_thorim.cpp88
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_xt002.cpp107
-rw-r--r--src/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp20
-rw-r--r--src/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp344
-rw-r--r--src/scripts/northrend/ulduar/ulduar/ulduar.h65
-rw-r--r--src/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp92
29 files changed, 6007 insertions, 0 deletions
diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp b/src/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp
new file mode 100644
index 00000000000..d1dc90cd6bf
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp
@@ -0,0 +1,432 @@
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ * 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
+ */
+
+/* ScriptData
+SDName: Boss General Bjarngrim
+SD%Complete: 70%
+SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following
+SDCategory: Halls of Lightning
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "halls_of_lightning.h"
+
+enum eEnums
+{
+ //Yell
+ SAY_AGGRO = -1602000,
+ SAY_SLAY_1 = -1602001,
+ SAY_SLAY_2 = -1602002,
+ SAY_SLAY_3 = -1602003,
+ SAY_DEATH = -1602004,
+ SAY_BATTLE_STANCE = -1602005,
+ EMOTE_BATTLE_STANCE = -1602006,
+ SAY_BERSEKER_STANCE = -1602007,
+ EMOTE_BERSEKER_STANCE = -1602008,
+ SAY_DEFENSIVE_STANCE = -1602009,
+ EMOTE_DEFENSIVE_STANCE = -1602010,
+
+ SPELL_DEFENSIVE_STANCE = 53790,
+ //SPELL_DEFENSIVE_AURA = 41105,
+ SPELL_SPELL_REFLECTION = 36096,
+ SPELL_PUMMEL = 12555,
+ SPELL_KNOCK_AWAY = 52029,
+ SPELL_IRONFORM = 52022,
+
+ SPELL_BERSEKER_STANCE = 53791,
+ //SPELL_BERSEKER_AURA = 41107,
+ SPELL_INTERCEPT = 58769,
+ SPELL_WHIRLWIND = 52027,
+ SPELL_CLEAVE = 15284,
+
+ SPELL_BATTLE_STANCE = 53792,
+ //SPELL_BATTLE_AURA = 41106,
+ SPELL_MORTAL_STRIKE = 16856,
+ SPELL_SLAM = 52026,
+
+ //OTHER SPELLS
+ //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other
+ //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above
+
+ NPC_STORMFORGED_LIEUTENANT = 29240,
+ SPELL_ARC_WELD = 59085,
+ SPELL_RENEW_STEEL_N = 52774,
+ SPELL_RENEW_STEEL_H = 59160,
+
+ EQUIP_SWORD = 37871,
+ EQUIP_SHIELD = 35642,
+ EQUIP_MACE = 43623,
+
+ STANCE_DEFENSIVE = 0,
+ STANCE_BERSERKER = 1,
+ STANCE_BATTLE = 2
+};
+
+/*######
+## boss_bjarngrim
+######*/
+
+struct TRINITY_DLL_DECL boss_bjarngrimAI : public ScriptedAI
+{
+ boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ m_uiStance = STANCE_DEFENSIVE;
+ memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID));
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ bool m_bIsChangingStance;
+
+ uint8 m_uiChargingStatus;
+ uint8 m_uiStance;
+
+ uint32 m_uiCharge_Timer;
+ uint32 m_uiChangeStance_Timer;
+
+ uint32 m_uiReflection_Timer;
+ uint32 m_uiKnockAway_Timer;
+ uint32 m_uiPummel_Timer;
+ uint32 m_uiIronform_Timer;
+
+ uint32 m_uiIntercept_Timer;
+ uint32 m_uiWhirlwind_Timer;
+ uint32 m_uiCleave_Timer;
+
+ uint32 m_uiMortalStrike_Timer;
+ uint32 m_uiSlam_Timer;
+
+ uint64 m_auiStormforgedLieutenantGUID[2];
+
+ void Reset()
+ {
+ m_bIsChangingStance = false;
+
+ m_uiChargingStatus = 0;
+ m_uiCharge_Timer = 1000;
+
+ m_uiChangeStance_Timer = 20000 + rand()%5000;
+
+ m_uiReflection_Timer = 8000;
+ m_uiKnockAway_Timer = 20000;
+ m_uiPummel_Timer = 10000;
+ m_uiIronform_Timer = 25000;
+
+ m_uiIntercept_Timer = 5000;
+ m_uiWhirlwind_Timer = 10000;
+ m_uiCleave_Timer = 8000;
+
+ m_uiMortalStrike_Timer = 8000;
+ m_uiSlam_Timer = 10000;
+
+ for (uint8 i = 0; i < 2; ++i)
+ {
+ if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*m_creature), m_auiStormforgedLieutenantGUID[i])))
+ {
+ if (!pStormforgedLieutenant->isAlive())
+ pStormforgedLieutenant->Respawn();
+ }
+ }
+
+ if (m_uiStance != STANCE_DEFENSIVE)
+ {
+ DoRemoveStanceAura(m_uiStance);
+ DoCast(m_creature, SPELL_DEFENSIVE_STANCE);
+ m_uiStance = STANCE_DEFENSIVE;
+ }
+
+ SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ //must get both lieutenants here and make sure they are with him
+ m_creature->CallForHelp(30.0f);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BJARNGRIM, DONE);
+ }
+
+ //TODO: remove when removal is done by mangos
+ void DoRemoveStanceAura(uint8 uiStance)
+ {
+ switch(uiStance)
+ {
+ case STANCE_DEFENSIVE:
+ m_creature->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE);
+ break;
+ case STANCE_BERSERKER:
+ m_creature->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE);
+ break;
+ case STANCE_BATTLE:
+ m_creature->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE);
+ break;
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ // Change stance
+ if (m_uiChangeStance_Timer <= uiDiff)
+ {
+ //wait for current spell to finish before change stance
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ return;
+
+ DoRemoveStanceAura(m_uiStance);
+
+ int uiTempStance = rand()%(3-1);
+
+ if (uiTempStance >= m_uiStance)
+ ++uiTempStance;
+
+ m_uiStance = uiTempStance;
+
+ switch(m_uiStance)
+ {
+ case STANCE_DEFENSIVE:
+ DoScriptText(SAY_DEFENSIVE_STANCE, m_creature);
+ DoScriptText(EMOTE_DEFENSIVE_STANCE, m_creature);
+ DoCast(m_creature, SPELL_DEFENSIVE_STANCE);
+ SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE);
+ break;
+ case STANCE_BERSERKER:
+ DoScriptText(SAY_BERSEKER_STANCE, m_creature);
+ DoScriptText(EMOTE_BERSEKER_STANCE, m_creature);
+ DoCast(m_creature, SPELL_BERSEKER_STANCE);
+ SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE);
+ break;
+ case STANCE_BATTLE:
+ DoScriptText(SAY_BATTLE_STANCE, m_creature);
+ DoScriptText(EMOTE_BATTLE_STANCE, m_creature);
+ DoCast(m_creature, SPELL_BATTLE_STANCE);
+ SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
+ break;
+ }
+
+ m_uiChangeStance_Timer = 20000 + rand()%5000;
+ return;
+ }
+ else
+ m_uiChangeStance_Timer -= uiDiff;
+
+ switch(m_uiStance)
+ {
+ case STANCE_DEFENSIVE:
+ {
+ if (m_uiReflection_Timer <= uiDiff)
+ {
+ DoCast(m_creature, SPELL_SPELL_REFLECTION);
+ m_uiReflection_Timer = 8000 + rand()%1000;
+ }
+ else
+ m_uiReflection_Timer -= uiDiff;
+
+ if (m_uiKnockAway_Timer <= uiDiff)
+ {
+ DoCast(m_creature, SPELL_KNOCK_AWAY);
+ m_uiKnockAway_Timer = 20000 + rand()%1000;
+ }
+ else
+ m_uiKnockAway_Timer -= uiDiff;
+
+ if (m_uiPummel_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_PUMMEL);
+ m_uiPummel_Timer = 10000 + rand()%1000;
+ }
+ else
+ m_uiPummel_Timer -= uiDiff;
+
+ if (m_uiIronform_Timer <= uiDiff)
+ {
+ DoCast(m_creature, SPELL_IRONFORM);
+ m_uiIronform_Timer = 25000 + rand()%1000;
+ }
+ else
+ m_uiIronform_Timer -= uiDiff;
+
+ break;
+ }
+ case STANCE_BERSERKER:
+ {
+ if (m_uiIntercept_Timer <= uiDiff)
+ {
+ //not much point is this, better random target and more often?
+ DoCast(m_creature->getVictim(), SPELL_INTERCEPT);
+ m_uiIntercept_Timer = 45000 + rand()%1000;
+ }
+ else
+ m_uiIntercept_Timer -= uiDiff;
+
+ if (m_uiWhirlwind_Timer <= uiDiff)
+ {
+ DoCast(m_creature, SPELL_WHIRLWIND);
+ m_uiWhirlwind_Timer = 10000 + rand()%1000;
+ }
+ else
+ m_uiWhirlwind_Timer -= uiDiff;
+
+ if (m_uiCleave_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleave_Timer = 8000 + rand()%1000;
+ }
+ else
+ m_uiCleave_Timer -= uiDiff;
+
+ break;
+ }
+ case STANCE_BATTLE:
+ {
+ if (m_uiMortalStrike_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_MORTAL_STRIKE);
+ m_uiMortalStrike_Timer = 20000 + rand()%1000;
+ }
+ else
+ m_uiMortalStrike_Timer -= uiDiff;
+
+ if (m_uiSlam_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_SLAM);
+ m_uiSlam_Timer = 15000 + rand()%1000;
+ }
+ else
+ m_uiSlam_Timer -= uiDiff;
+
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+/*######
+## mob_stormforged_lieutenant
+######*/
+
+struct TRINITY_DLL_DECL mob_stormforged_lieutenantAI : public ScriptedAI
+{
+ mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiArcWeld_Timer;
+ uint32 m_uiRenewSteel_Timer;
+
+ void Reset()
+ {
+ m_uiArcWeld_Timer = 20000 + rand()%1000;
+ m_uiRenewSteel_Timer = 10000 + rand()%1000;
+ }
+
+ void EnterCombat(Unit* pWho)
+ {
+ if (m_pInstance)
+ {
+ if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM)))
+ {
+ if (pBjarngrim->isAlive() && !pBjarngrim->getVictim())
+ pBjarngrim->AI()->AttackStart(pWho);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ if (m_uiArcWeld_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_ARC_WELD);
+ m_uiArcWeld_Timer = 20000 + rand()%1000;
+ }
+ else
+ m_uiArcWeld_Timer -= uiDiff;
+
+ if (m_uiRenewSteel_Timer <= uiDiff)
+ {
+ if (m_pInstance)
+ {
+ if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM)))
+ {
+ if (pBjarngrim->isAlive())
+ DoCast(pBjarngrim, DUNGEON_MODE(SPELL_RENEW_STEEL_N, SPELL_RENEW_STEEL_H));
+ }
+ }
+ m_uiRenewSteel_Timer = 10000 + rand()%4000;
+ }
+ else
+ m_uiRenewSteel_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature)
+{
+ return new boss_bjarngrimAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature)
+{
+ return new mob_stormforged_lieutenantAI(pCreature);
+}
+
+void AddSC_boss_bjarngrim()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_bjarngrim";
+ newscript->GetAI = &GetAI_boss_bjarngrim;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_stormforged_lieutenant";
+ newscript->GetAI = &GetAI_mob_stormforged_lieutenant;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/src/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp
new file mode 100644
index 00000000000..7cb2b4ef634
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp
@@ -0,0 +1,380 @@
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ * 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
+ */
+
+/* ScriptData
+SDName: Boss Ionar
+SD%Complete: 80%
+SDComment: Timer check
+SDCategory: Halls of Lightning
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "halls_of_lightning.h"
+
+enum eEnums
+{
+ SAY_AGGRO = -1602011,
+ SAY_SLAY_1 = -1602012,
+ SAY_SLAY_2 = -1602013,
+ SAY_SLAY_3 = -1602014,
+ SAY_DEATH = -1602015,
+ SAY_SPLIT_1 = -1602016,
+ SAY_SPLIT_2 = -1602017,
+
+ SPELL_BALL_LIGHTNING_N = 52780,
+ SPELL_BALL_LIGHTNING_H = 59800,
+ SPELL_STATIC_OVERLOAD_N = 52658,
+ SPELL_STATIC_OVERLOAD_H = 59795,
+
+ SPELL_DISPERSE = 52770,
+ SPELL_SUMMON_SPARK = 52746,
+ SPELL_SPARK_DESPAWN = 52776,
+
+ //Spark of Ionar
+ SPELL_SPARK_VISUAL_TRIGGER_N = 52667,
+ SPELL_SPARK_VISUAL_TRIGGER_H = 59833,
+
+ NPC_SPARK_OF_IONAR = 28926,
+
+ MAX_SPARKS = 5,
+ POINT_CALLBACK = 0
+};
+
+/*######
+## Boss Ionar
+######*/
+
+struct TRINITY_DLL_DECL boss_ionarAI : public ScriptedAI
+{
+ boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ std::list<uint64> m_lSparkGUIDList;
+
+ bool m_bIsSplitPhase;
+ uint32 m_uiSplit_Timer;
+ uint32 m_uiSparkAtHomeCount;
+
+ uint32 m_uiStaticOverload_Timer;
+ uint32 m_uiBallLightning_Timer;
+
+ uint32 m_uiHealthAmountModifier;
+
+ void Reset()
+ {
+ m_lSparkGUIDList.clear();
+
+ m_bIsSplitPhase = true;
+ m_uiSplit_Timer = 25000;
+ m_uiSparkAtHomeCount = 0;
+
+ m_uiStaticOverload_Timer = 5000 + rand()%1000;
+ m_uiBallLightning_Timer = 10000 + rand()%1000;
+
+ m_uiHealthAmountModifier = 1;
+
+ if (m_creature->GetVisibility() == VISIBILITY_OFF)
+ m_creature->SetVisibility(VISIBILITY_ON);
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->GetVisibility() == VISIBILITY_OFF)
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_IONAR, IN_PROGRESS);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_IONAR, NOT_STARTED);
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (m_creature->Attack(pWho, true))
+ {
+ m_creature->AddThreat(pWho, 0.0f);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ if (m_creature->GetVisibility() != VISIBILITY_OFF)
+ m_creature->GetMotionMaster()->MoveChase(pWho);
+ }
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ DespawnSpark();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_IONAR, DONE);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), m_creature);
+ }
+
+ void DespawnSpark()
+ {
+ if (m_lSparkGUIDList.empty())
+ return;
+
+ for (std::list<uint64>::iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr)
+ {
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, *itr))
+ {
+ if (pTemp->isAlive())
+ pTemp->ForcedDespawn();
+ }
+ }
+
+ m_lSparkGUIDList.clear();
+ }
+
+ //make sparks come back
+ void CallBackSparks()
+ {
+ //should never be empty here, but check
+ if (m_lSparkGUIDList.empty())
+ return;
+
+ for (std::list<uint64>::iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr)
+ {
+ if (Creature* pSpark = Unit::GetCreature(*m_creature, *itr))
+ {
+ if (pSpark->isAlive())
+ {
+ if (pSpark->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ pSpark->GetMotionMaster()->MovementExpired();
+
+ pSpark->SetSpeed(MOVE_RUN, pSpark->GetCreatureInfo()->speed * 2);
+ pSpark->GetMotionMaster()->MovePoint(POINT_CALLBACK, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
+ }
+ }
+ }
+ }
+
+ void RegisterSparkAtHome()
+ {
+ ++m_uiSparkAtHomeCount;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR)
+ {
+ pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER_N,SPELL_SPARK_VISUAL_TRIGGER_H), true);
+
+ Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
+
+ if (m_creature->getVictim())
+ pSummoned->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim());
+
+ m_lSparkGUIDList.push_back(pSummoned->GetGUID());
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Splitted
+ if (m_creature->GetVisibility() == VISIBILITY_OFF)
+ {
+ /*if (!m_creature->getVictim())
+ {
+ Reset();
+ return;
+ }*/
+
+ if (m_uiSplit_Timer <= uiDiff)
+ {
+ m_uiSplit_Timer = 2500;
+
+ // Return sparks to where Ionar splitted
+ if (m_bIsSplitPhase)
+ {
+ CallBackSparks();
+ m_bIsSplitPhase = false;
+ }
+ // Lightning effect and restore Ionar
+ else if (m_uiSparkAtHomeCount == MAX_SPARKS)
+ {
+ m_creature->SetVisibility(VISIBILITY_ON);
+ DoCast(m_creature, SPELL_SPARK_DESPAWN, false);
+
+ DespawnSpark();
+
+ m_uiSparkAtHomeCount = 0;
+ m_uiSplit_Timer = 25000;
+ m_bIsSplitPhase = true;
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ {
+ if (m_creature->getVictim())
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ }
+ }
+ }
+ else
+ m_uiSplit_Timer -= uiDiff;
+
+ return;
+ }
+
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ if (m_uiStaticOverload_Timer <= uiDiff)
+ {
+ if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_STATIC_OVERLOAD_N, SPELL_STATIC_OVERLOAD_H));
+
+ m_uiStaticOverload_Timer = 5000 + rand()%1000;
+ }
+ else
+ m_uiStaticOverload_Timer -= uiDiff;
+
+ if (m_uiBallLightning_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_BALL_LIGHTNING_N, SPELL_BALL_LIGHTNING_H));
+ m_uiBallLightning_Timer = 10000 + rand()%1000;
+ }
+ else
+ m_uiBallLightning_Timer -= uiDiff;
+
+ // Health check
+ if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier)))
+ {
+ ++m_uiHealthAmountModifier;
+
+ DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), m_creature);
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoCast(m_creature, SPELL_DISPERSE);
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_ionar(Creature* pCreature)
+{
+ return new boss_ionarAI(pCreature);
+}
+
+bool EffectDummyCreature_boss_ionar(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget)
+{
+ //always check spellid and effectindex
+ if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0)
+ {
+ if (pCreatureTarget->GetEntry() != NPC_IONAR)
+ return true;
+
+ for (uint8 i = 0; i < MAX_SPARKS; ++i)
+ pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true);
+
+ pCreatureTarget->AttackStop();
+ pCreatureTarget->SetVisibility(VISIBILITY_OFF);
+
+ if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ pCreatureTarget->GetMotionMaster()->MovementExpired();
+
+ //always return true when we are handling this spell and effect
+ return true;
+ }
+ return false;
+}
+
+/*######
+## mob_spark_of_ionar
+######*/
+
+struct TRINITY_DLL_DECL mob_spark_of_ionarAI : public ScriptedAI
+{
+ mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset() { }
+
+ void MovementInform(uint32 uiType, uint32 uiPointId)
+ {
+ if (uiType != POINT_MOTION_TYPE || !m_pInstance)
+ return;
+
+ if (uiPointId == POINT_CALLBACK)
+ {
+ if (Creature* pIonar = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_IONAR)))
+ {
+ if (!pIonar->isAlive())
+ {
+ m_creature->ForcedDespawn();
+ return;
+ }
+
+ if (boss_ionarAI* pIonarAI = dynamic_cast<boss_ionarAI*>(pIonar->AI()))
+ pIonarAI->RegisterSparkAtHome();
+ }
+ else
+ m_creature->ForcedDespawn();
+ }
+ }
+};
+
+CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature)
+{
+ return new mob_spark_of_ionarAI(pCreature);
+}
+
+void AddSC_boss_ionar()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_ionar";
+ newscript->GetAI = &GetAI_boss_ionar;
+ newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_spark_of_ionar";
+ newscript->GetAI = &GetAI_mob_spark_of_ionar;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp b/src/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp
new file mode 100644
index 00000000000..b7cc283e2b9
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp
@@ -0,0 +1,239 @@
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ * 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
+ */
+
+/* ScriptData
+SDName: Boss Loken
+SD%Complete: 60%
+SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414)
+SDCategory: Halls of Lightning
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "halls_of_lightning.h"
+
+#define MAX_ENCOUNTER_TIME 2 * 60 * 1000
+
+enum eEnums
+{
+ ACHIEVEMENT_TIMELY_DEATH = 1867,
+
+ SAY_AGGRO = -1602018,
+ SAY_INTRO_1 = -1602019,
+ SAY_INTRO_2 = -1602020,
+ SAY_SLAY_1 = -1602021,
+ SAY_SLAY_2 = -1602022,
+ SAY_SLAY_3 = -1602023,
+ SAY_DEATH = -1602024,
+ SAY_NOVA_1 = -1602025,
+ SAY_NOVA_2 = -1602026,
+ SAY_NOVA_3 = -1602027,
+ SAY_75HEALTH = -1602028,
+ SAY_50HEALTH = -1602029,
+ SAY_25HEALTH = -1602030,
+ EMOTE_NOVA = -1602031,
+
+ SPELL_ARC_LIGHTNING = 52921,
+ SPELL_LIGHTNING_NOVA_N = 52960,
+ SPELL_LIGHTNING_NOVA_H = 59835,
+
+ SPELL_PULSING_SHOCKWAVE_N = 52961,
+ SPELL_PULSING_SHOCKWAVE_H = 59836,
+ SPELL_PULSING_SHOCKWAVE_AURA = 59414
+};
+
+/*######
+## Boss Loken
+######*/
+
+struct TRINITY_DLL_DECL boss_lokenAI : public ScriptedAI
+{
+ boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ bool m_bIsAura;
+
+ uint32 m_uiArcLightning_Timer;
+ uint32 m_uiLightningNova_Timer;
+ uint32 m_uiPulsingShockwave_Timer;
+ uint32 m_uiResumePulsingShockwave_Timer;
+
+ uint32 m_uiHealthAmountModifier;
+
+ uint32 EncounterTime;
+
+ void Reset()
+ {
+ m_bIsAura = false;
+
+ m_uiArcLightning_Timer = 15000;
+ m_uiLightningNova_Timer = 20000;
+ m_uiPulsingShockwave_Timer = 2000;
+ m_uiResumePulsingShockwave_Timer = 15000;
+
+ m_uiHealthAmountModifier = 1;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ EncounterTime = 0;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (IsHeroic() && EncounterTime <= MAX_ENCOUNTER_TIME)
+ {
+ AchievementEntry const *AchievTimelyDeath = GetAchievementStore()->LookupEntry(ACHIEVEMENT_TIMELY_DEATH);
+ if (AchievTimelyDeath)
+ {
+ Map* pMap = m_creature->GetMap();
+ if (pMap && pMap->IsDungeon())
+ {
+ Map::PlayerList const &players = pMap->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ itr->getSource()->CompletedAchievement(AchievTimelyDeath);
+ }
+ }
+ }
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_LOKEN, DONE);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ EncounterTime += uiDiff;
+
+ if (m_bIsAura)
+ {
+ // workaround for PULSING_SHOCKWAVE
+ if (m_uiPulsingShockwave_Timer <= uiDiff)
+ {
+ Map* pMap = m_creature->GetMap();
+ if (pMap->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+
+ if (PlayerList.isEmpty())
+ return;
+
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack())
+ {
+ int32 dmg;
+ float m_fDist = m_creature->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ());
+
+ dmg = DUNGEON_MODE(100, 150); // need to correct damage
+ if (m_fDist > 1.0f) // Further from 1 yard
+ dmg *= m_fDist;
+
+ m_creature->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false);
+ }
+ }
+ m_uiPulsingShockwave_Timer = 2000;
+ } else m_uiPulsingShockwave_Timer -= uiDiff;
+ }
+ else
+ {
+ if (m_uiResumePulsingShockwave_Timer <= uiDiff)
+ {
+ //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement?
+ DoCast(m_creature, SPELL_PULSING_SHOCKWAVE_AURA, true);
+
+ DoCast(m_creature, DUNGEON_MODE(SPELL_PULSING_SHOCKWAVE_N, SPELL_PULSING_SHOCKWAVE_H)); // need core support
+ m_bIsAura = true;
+ m_uiResumePulsingShockwave_Timer = 0;
+ }
+ else
+ m_uiResumePulsingShockwave_Timer -= uiDiff;
+ }
+
+ if (m_uiArcLightning_Timer <= uiDiff)
+ {
+ if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, SPELL_ARC_LIGHTNING);
+
+ m_uiArcLightning_Timer = 15000 + rand()%1000;
+ }
+ else
+ m_uiArcLightning_Timer -= uiDiff;
+
+ if (m_uiLightningNova_Timer <= uiDiff)
+ {
+ DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), m_creature);
+ DoScriptText(EMOTE_NOVA, m_creature);
+ DoCast(m_creature, DUNGEON_MODE(SPELL_LIGHTNING_NOVA_N, SPELL_LIGHTNING_NOVA_H));
+
+ m_bIsAura = false;
+ m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura
+ m_uiLightningNova_Timer = 20000 + rand()%1000;
+ }
+ else
+ m_uiLightningNova_Timer -= uiDiff;
+
+ // Health check
+ if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier)))
+ {
+ switch(m_uiHealthAmountModifier)
+ {
+ case 1: DoScriptText(SAY_75HEALTH, m_creature); break;
+ case 2: DoScriptText(SAY_50HEALTH, m_creature); break;
+ case 3: DoScriptText(SAY_25HEALTH, m_creature); break;
+ }
+
+ ++m_uiHealthAmountModifier;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_loken(Creature* pCreature)
+{
+ return new boss_lokenAI(pCreature);
+}
+
+void AddSC_boss_loken()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_loken";
+ newscript->GetAI = &GetAI_boss_loken;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/src/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp
new file mode 100644
index 00000000000..4dddf375bac
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp
@@ -0,0 +1,478 @@
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ * 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
+ */
+
+/* ScriptData
+SDName: Boss Volkhan
+SD%Complete: 60%
+SDComment: Not considered complete. Some events may fail and need further development
+SDCategory: Halls of Lightning
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "halls_of_lightning.h"
+
+enum eEnums
+{
+ SAY_AGGRO = -1602032,
+ SAY_SLAY_1 = -1602033,
+ SAY_SLAY_2 = -1602034,
+ SAY_SLAY_3 = -1602035,
+ SAY_DEATH = -1602036,
+ SAY_STOMP_1 = -1602037,
+ SAY_STOMP_2 = -1602038,
+ SAY_FORGE_1 = -1602039,
+ SAY_FORGE_2 = -1602040,
+ EMOTE_TO_ANVIL = -1602041,
+ EMOTE_SHATTER = -1602042,
+
+ SPELL_HEAT_N = 52387,
+ SPELL_HEAT_H = 59528,
+ SPELL_SHATTERING_STOMP_N = 52237,
+ SPELL_SHATTERING_STOMP_H = 59529,
+
+ //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on:
+ SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil
+ SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss
+
+ //SPELL_TEMPER_VISUAL = 52661, //summons GO
+
+ SPELL_SUMMON_MOLTEN_GOLEM = 52405,
+
+ //Molten Golem
+ SPELL_BLAST_WAVE = 23113,
+ SPELL_IMMOLATION_STRIKE_N = 52433,
+ SPELL_IMMOLATION_STRIKE_H = 59530,
+ SPELL_SHATTER_N = 52429,
+ SPELL_SHATTER_H = 59527,
+
+ NPC_VOLKHAN_ANVIL = 28823,
+ NPC_MOLTEN_GOLEM = 28695,
+ NPC_BRITTLE_GOLEM = 28681,
+
+ POINT_ID_ANVIL = 0,
+ MAX_GOLEM = 2,
+
+ ACHIEVEMENT_SHATTER_RESISTANT = 2042
+};
+
+/*######
+## Boss Volkhan
+######*/
+
+struct TRINITY_DLL_DECL boss_volkhanAI : public ScriptedAI
+{
+ boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ std::list<uint64> m_lGolemGUIDList;
+
+ bool m_bHasTemper;
+ bool m_bIsStriking;
+ bool m_bCanShatterGolem;
+
+ uint8 GolemsShattered;
+ uint32 m_uiPause_Timer;
+ uint32 m_uiShatteringStomp_Timer;
+ uint32 m_uiShatter_Timer;
+
+ uint32 m_uiHealthAmountModifier;
+
+ void Reset()
+ {
+ m_bIsStriking = false;
+ m_bHasTemper = false;
+ m_bCanShatterGolem = false;
+
+ m_uiPause_Timer = 3500;
+ m_uiShatteringStomp_Timer = 0;
+ m_uiShatter_Timer = 5000;
+ GolemsShattered = 0;
+
+ m_uiHealthAmountModifier = 1;
+
+ DespawnGolem();
+ m_lGolemGUIDList.clear();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS);
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (m_creature->Attack(pWho, true))
+ {
+ m_creature->AddThreat(pWho, 0.0f);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ if (!m_bHasTemper)
+ m_creature->GetMotionMaster()->MoveChase(pWho);
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ DespawnGolem();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_VOLKHAN, DONE);
+
+ if (IsHeroic() && GolemsShattered < 5)
+ {
+ AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT);
+ if (AchievShatterResistant)
+ {
+ Map* pMap = m_creature->GetMap();
+ if (pMap && pMap->IsDungeon())
+ {
+ Map::PlayerList const &players = pMap->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ itr->getSource()->CompletedAchievement(AchievShatterResistant);
+ }
+ }
+ }
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), m_creature);
+ }
+
+ void DespawnGolem()
+ {
+ if (m_lGolemGUIDList.empty())
+ return;
+
+ for (std::list<uint64>::iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr)
+ {
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, *itr))
+ {
+ if (pTemp->isAlive())
+ pTemp->ForcedDespawn();
+ }
+ }
+
+ m_lGolemGUIDList.clear();
+ }
+
+ void ShatterGolem()
+ {
+ if (m_lGolemGUIDList.empty())
+ return;
+
+ for (std::list<uint64>::iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr)
+ {
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, *itr))
+ {
+ // only shatter brittle golems
+ if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM)
+ {
+ pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false);
+ GolemsShattered += 1;
+ }
+ }
+ }
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_TEMPER_DUMMY)
+ m_bIsStriking = true;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM)
+ {
+ m_lGolemGUIDList.push_back(pSummoned->GetGUID());
+
+ if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ pSummoned->AI()->AttackStart(pTarget);
+
+ //why healing when just summoned?
+ pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, m_creature->GetGUID());
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ if (m_bIsStriking)
+ {
+ if (m_uiPause_Timer <= uiDiff)
+ {
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
+ {
+ if (m_creature->getVictim())
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ }
+
+ m_bHasTemper = false;
+ m_bIsStriking = false;
+ m_uiPause_Timer = 3500;
+ }
+ else
+ m_uiPause_Timer -= uiDiff;
+
+ return;
+ }
+
+ // When to start shatter? After 60, 40 or 20% hp?
+ if (!m_bHasTemper && m_uiHealthAmountModifier >= 3)
+ {
+ if (m_uiShatteringStomp_Timer <= uiDiff)
+ {
+ //should he stomp even if he has no brittle golem to shatter?
+
+ DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), m_creature);
+
+ DoCast(m_creature, DUNGEON_MODE(SPELL_SHATTERING_STOMP_N, SPELL_SHATTERING_STOMP_H));
+
+ DoScriptText(EMOTE_SHATTER, m_creature);
+
+ m_uiShatteringStomp_Timer = 30000;
+ m_bCanShatterGolem = true;
+ }
+ else
+ m_uiShatteringStomp_Timer -= uiDiff;
+ }
+
+ // Shatter Golems 3 seconds after Shattering Stomp
+ if (m_bCanShatterGolem)
+ {
+ if (m_uiShatter_Timer <= uiDiff)
+ {
+ ShatterGolem();
+ m_uiShatter_Timer = 3000;
+ m_bCanShatterGolem = false;
+ }
+ else
+ m_uiShatter_Timer -= uiDiff;
+ }
+
+ // Health check
+ if (!m_bCanShatterGolem && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier)))
+ {
+ ++m_uiHealthAmountModifier;
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), m_creature);
+
+ m_bHasTemper = true;
+
+ DoCast(m_creature, SPELL_TEMPER, false);
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_volkhan(Creature* pCreature)
+{
+ return new boss_volkhanAI(pCreature);
+}
+
+bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget)
+{
+ //always check spellid and effectindex
+ if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0)
+ {
+ if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN)
+ return true;
+
+ for (uint8 i = 0; i < MAX_GOLEM; ++i)
+ {
+ pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true);
+ }
+
+ //always return true when we are handling this spell and effect
+ return true;
+ }
+
+ return false;
+}
+
+/*######
+## npc_volkhan_anvil
+######*/
+
+bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget)
+{
+ //always check spellid and effectindex
+ if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0)
+ {
+ if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL)
+ return true;
+
+ Creature *cre = CAST_CRE(pCaster);
+
+ DoScriptText(EMOTE_TO_ANVIL, pCaster);
+
+ float fX, fY, fZ;
+ pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE);
+
+ pCaster->AttackStop();
+
+ if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ pCaster->GetMotionMaster()->MovementExpired();
+
+ cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation());
+ cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1);
+
+ pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false);
+
+ //always return true when we are handling this spell and effect
+ return true;
+ }
+
+ return false;
+}
+
+/*######
+## mob_molten_golem
+######*/
+
+struct TRINITY_DLL_DECL mob_molten_golemAI : public ScriptedAI
+{
+ mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ }
+
+ bool m_bIsFrozen;
+
+ uint32 m_uiBlast_Timer;
+ uint32 m_uiDeathDelay_Timer;
+ uint32 m_uiImmolation_Timer;
+
+ void Reset()
+ {
+ m_bIsFrozen = false;
+
+ m_uiBlast_Timer = 20000;
+ m_uiDeathDelay_Timer = 0;
+ m_uiImmolation_Timer = 5000;
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (m_creature->Attack(pWho, true))
+ {
+ m_creature->AddThreat(pWho, 0.0f);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ if (!m_bIsFrozen)
+ m_creature->GetMotionMaster()->MoveChase(pWho);
+ }
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage > m_creature->GetHealth())
+ {
+ m_creature->UpdateEntry(NPC_BRITTLE_GOLEM);
+ m_creature->SetHealth(1);
+ uiDamage = 0;
+ m_creature->RemoveAllAuras();
+ m_creature->AttackStop();
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ m_creature->GetMotionMaster()->MovementExpired();
+ m_bIsFrozen = true;
+ }
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ //this is the dummy effect of the spells
+ if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H)
+ {
+ if (m_creature->GetEntry() == NPC_BRITTLE_GOLEM)
+ m_creature->ForcedDespawn();
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target or if we are frozen
+ if (!UpdateVictim() || m_bIsFrozen)
+ return;
+
+ if (m_uiBlast_Timer <= uiDiff)
+ {
+ DoCast(m_creature, SPELL_BLAST_WAVE);
+ m_uiBlast_Timer = 20000;
+ }
+ else
+ m_uiBlast_Timer -= uiDiff;
+
+ if (m_uiImmolation_Timer <= uiDiff)
+ {
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_IMMOLATION_STRIKE_N, SPELL_IMMOLATION_STRIKE_H));
+ m_uiImmolation_Timer = 5000;
+ }
+ else
+ m_uiImmolation_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_molten_golem(Creature* pCreature)
+{
+ return new mob_molten_golemAI(pCreature);
+}
+
+void AddSC_boss_volkhan()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_volkhan";
+ newscript->GetAI = &GetAI_boss_volkhan;
+ newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_volkhan_anvil";
+ newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_molten_golem";
+ newscript->GetAI = &GetAI_mob_molten_golem;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h b/src/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h
new file mode 100644
index 00000000000..d9739fdf888
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ * This program is free software licensed under GPL version 2
+ * Please see the included DOCS/LICENSE.TXT for more information */
+
+#ifndef DEF_HALLS_OF_LIGHTNING_H
+#define DEF_HALLS_OF_LIGHTNING_H
+
+enum eTypes
+{
+ MAX_ENCOUNTER = 4,
+
+ DATA_BJARNGRIM = 1,
+ DATA_IONAR = 2,
+ DATA_LOKEN = 3,
+ DATA_VOLKHAN = 4,
+
+ TYPE_BJARNGRIM = 10,
+ TYPE_IONAR = 11,
+ TYPE_LOKEN = 12,
+ TYPE_VOLKHAN = 13,
+
+ NPC_BJARNGRIM = 28586,
+ NPC_VOLKHAN = 28587,
+ NPC_IONAR = 28546,
+ NPC_LOKEN = 28923,
+
+ GO_BJARNGRIM_DOOR = 191416, //_doors10
+ GO_VOLKHAN_DOOR = 191325, //_doors07
+ GO_IONAR_DOOR = 191326, //_doors05
+ GO_LOKEN_DOOR = 191324, //_doors02
+ GO_LOKEN_THRONE = 192654
+};
+
+#endif
diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp
new file mode 100644
index 00000000000..fc556d3ddb7
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp
@@ -0,0 +1,237 @@
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ * 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
+ */
+
+/* ScriptData
+SDName: Instance_Halls_of_Lightning
+SD%Complete: 90%
+SDComment: All ready.
+SDCategory: Halls of Lightning
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "halls_of_lightning.h"
+
+/* Halls of Lightning encounters:
+0 - General Bjarngrim
+1 - Volkhan
+2 - Ionar
+3 - Loken
+*/
+
+struct TRINITY_DLL_DECL instance_halls_of_lightning : public ScriptedInstance
+{
+ instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint64 m_uiGeneralBjarngrimGUID;
+ uint64 m_uiIonarGUID;
+ uint64 m_uiLokenGUID;
+ uint64 m_uiVolkhanGUID;
+
+ uint64 m_uiBjarngrimDoorGUID;
+ uint64 m_uiVolkhanDoorGUID;
+ uint64 m_uiIonarDoorGUID;
+ uint64 m_uiLokenDoorGUID;
+ uint64 m_uiLokenGlobeGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiGeneralBjarngrimGUID = 0;
+ m_uiVolkhanGUID = 0;
+ m_uiIonarGUID = 0;
+ m_uiLokenGUID = 0;
+
+ m_uiBjarngrimDoorGUID = 0;
+ m_uiVolkhanDoorGUID = 0;
+ m_uiIonarDoorGUID = 0;
+ m_uiLokenDoorGUID = 0;
+ m_uiLokenGlobeGUID = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature, bool add)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_BJARNGRIM:
+ m_uiGeneralBjarngrimGUID = pCreature->GetGUID();
+ break;
+ case NPC_VOLKHAN:
+ m_uiVolkhanGUID = pCreature->GetGUID();
+ break;
+ case NPC_IONAR:
+ m_uiIonarGUID = pCreature->GetGUID();
+ break;
+ case NPC_LOKEN:
+ m_uiLokenGUID = pCreature->GetGUID();
+ break;
+ }
+ }
+
+ void OnGameObjectCreate(GameObject* pGo, bool add)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_BJARNGRIM_DOOR:
+ m_uiBjarngrimDoorGUID = pGo->GetGUID();
+ if (m_auiEncounter[0] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_VOLKHAN_DOOR:
+ m_uiVolkhanDoorGUID = pGo->GetGUID();
+ if (m_auiEncounter[1] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_IONAR_DOOR:
+ m_uiIonarDoorGUID = pGo->GetGUID();
+ if (m_auiEncounter[2] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_LOKEN_DOOR:
+ m_uiLokenDoorGUID = pGo->GetGUID();
+ if (m_auiEncounter[3] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_LOKEN_THRONE:
+ m_uiLokenGlobeGUID = pGo->GetGUID();
+ break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_BJARNGRIM:
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiBjarngrimDoorGUID);
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_VOLKHAN:
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiVolkhanDoorGUID);
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_IONAR:
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiIonarDoorGUID);
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_LOKEN:
+ if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiLokenDoorGUID);
+
+ //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder
+ if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID))
+ pGlobe->SetGoState(GO_STATE_ACTIVE);
+ }
+ m_auiEncounter[3] = uiData;
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_BJARNGRIM:
+ return m_auiEncounter[0];
+ case TYPE_VOLKHAN:
+ return m_auiEncounter[1];
+ case TYPE_IONAR:
+ return m_auiEncounter[2];
+ case TYPE_LOKEN:
+ return m_auiEncounter[3];
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_BJARNGRIM:
+ return m_uiGeneralBjarngrimGUID;
+ case DATA_VOLKHAN:
+ return m_uiVolkhanGUID;
+ case DATA_IONAR:
+ return m_uiIonarGUID;
+ case DATA_LOKEN:
+ return m_uiLokenGUID;
+ }
+ return 0;
+ }
+
+ std::string GetSaveData()
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " "
+ << m_auiEncounter[2] << " " << m_auiEncounter[3];
+
+ 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;
+ uint16 data0, data1, data2, data3;
+
+ std::istringstream loadStream(in);
+ loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3;
+
+ if (dataHead1 == 'H' && dataHead2 == 'L')
+ {
+ m_auiEncounter[0] = data0;
+ m_auiEncounter[1] = data1;
+ m_auiEncounter[2] = data2;
+ m_auiEncounter[3] = data3;
+
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ } else OUT_LOAD_INST_DATA_FAIL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap)
+{
+ return new instance_halls_of_lightning(pMap);
+}
+
+void AddSC_instance_halls_of_lightning()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_halls_of_lightning";
+ newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp b/src/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp
new file mode 100644
index 00000000000..f8a88e9fcc7
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp
@@ -0,0 +1,148 @@
+/* Script Data Start
+SDName: Boss krystallus
+SDAuthor: LordVanMartin
+SD%Complete:
+SDComment:
+SDCategory:
+Script Data End */
+
+/*** SQL START ***
+update creature_template set scriptname = 'boss_krystallus' where entry = '';
+*** SQL END ***/
+#include "ScriptedPch.h"
+#include "halls_of_stone.h"
+
+enum Spells
+{
+ SPELL_BOULDER_TOSS = 50843,
+ H_SPELL_BOULDER_TOSS = 59742,
+ SPELL_GROUND_SPIKE = 59750,
+ SPELL_GROUND_SLAM = 50827,
+ SPELL_SHATTER = 50810,
+ H_SPELL_SHATTER = 61546,
+ SPELL_STOMP = 48131,
+ H_SPELL_STOMP = 59744
+};
+
+enum Yells
+{
+ SAY_AGGRO = -1603007,
+ SAY_KILL = -1603008,
+ SAY_DEATH = -1603009,
+ SAY_SHATTER = -1603010
+};
+
+struct TRINITY_DLL_DECL boss_krystallusAI : public ScriptedAI
+{
+ boss_krystallusAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiBoulderTossTimer;
+ uint32 uiGroundSpikeTimer;
+ uint32 uiGroundSlamTimer;
+ uint32 uiShatterTimer;
+ uint32 uiStompTimer;
+
+ bool bIsSlam;
+
+ ScriptedInstance* pInstance;
+
+ void Reset()
+ {
+ bIsSlam = false;
+
+ uiBoulderTossTimer = 3000 + rand()%6000;
+ uiGroundSpikeTimer = 9000 + rand()%5000;
+ uiGroundSlamTimer = 15000 + rand()%3000;
+ uiStompTimer = 20000 + rand()%9000;
+ uiShatterTimer = 0;
+
+ if (pInstance)
+ pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED);
+ }
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (pInstance)
+ pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ if (uiBoulderTossTimer <= diff)
+ {
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_BOULDER_TOSS, H_SPELL_BOULDER_TOSS));
+ uiBoulderTossTimer = 9000 + rand()%6000;
+ } else uiBoulderTossTimer -= diff;
+
+ if (uiGroundSpikeTimer <= diff)
+ {
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(pTarget, SPELL_GROUND_SPIKE);
+ uiGroundSpikeTimer = 12000 + rand()%5000;
+ } else uiGroundSpikeTimer -= diff;
+
+ if (uiStompTimer <= diff)
+ {
+ DoCast(m_creature, DUNGEON_MODE(SPELL_STOMP, H_SPELL_STOMP));
+ uiStompTimer = 20000 + rand()%9000;
+ } else uiStompTimer -= diff;
+
+ if (uiGroundSlamTimer <= diff)
+ {
+ DoCast(m_creature, SPELL_GROUND_SLAM);
+ bIsSlam = true;
+ uiShatterTimer = 10000;
+ uiGroundSlamTimer = 15000 + rand()%3000;
+ } else uiGroundSlamTimer -= diff;
+
+ if (bIsSlam)
+ {
+ if (uiShatterTimer <= diff)
+ {
+ DoCast(m_creature, DUNGEON_MODE(SPELL_SHATTER, H_SPELL_SHATTER));
+ bIsSlam = false;
+ } else uiShatterTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (pInstance)
+ pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ if (victim == m_creature)
+ return;
+ DoScriptText(SAY_KILL, m_creature);
+ }
+};
+
+CreatureAI* GetAI_boss_krystallus(Creature* pCreature)
+{
+ return new boss_krystallusAI (pCreature);
+}
+
+void AddSC_boss_krystallus()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_krystallus";
+ newscript->GetAI = &GetAI_boss_krystallus;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/src/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp
new file mode 100644
index 00000000000..615e4c5cc44
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp
@@ -0,0 +1,177 @@
+/* Script Data Start
+SDName: Boss maiden_of_grief
+SDAuthor: LordVanMartin
+SD%Complete:
+SDComment:
+SDCategory:
+Script Data End */
+
+/*** SQL START ***
+update creature_template set scriptname = 'boss_maiden_of_grief' where entry = '';
+*** SQL END ***/
+#include "ScriptedPch.h"
+#include "halls_of_stone.h"
+
+enum Spells
+{
+ SPELL_PARTING_SORROW = 59723,
+ SPELL_STORM_OF_GRIEF_N = 50752,
+ SPELL_STORM_OF_GRIEF_H = 59772,
+ SPELL_SHOCK_OF_SORROW_N = 50760,
+ SPELL_SHOCK_OF_SORROW_H = 59726,
+ SPELL_PILLAR_OF_WOE_N = 50761,
+ SPELL_PILLAR_OF_WOE_H = 59727
+};
+
+enum Yells
+{
+ SAY_AGGRO = -1603000,
+ SAY_SLAY_1 = -1603001,
+ SAY_SLAY_2 = -1603002,
+ SAY_SLAY_3 = -1603003,
+ SAY_SLAY_4 = -1603004,
+ SAY_DEATH = -1603005,
+ SAY_STUN = -1603006
+};
+
+enum Achievements
+{
+ ACHIEVEMENT_GOOD_GRIEF = 1866
+};
+
+struct TRINITY_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI
+{
+ boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = m_creature->GetInstanceData();
+ }
+
+ ScriptedInstance* pInstance;
+
+ uint32 PartingSorrowTimer;
+ uint32 StormOfGriefTimer;
+ uint32 ShockOfSorrowTimer;
+ uint32 PillarOfWoeTimer;
+ uint32 AchievTimer;
+
+ void Reset()
+ {
+ PartingSorrowTimer = 25000 + rand()%5000;
+ StormOfGriefTimer = 10000;
+ ShockOfSorrowTimer = 20000+rand()%5000;
+ PillarOfWoeTimer = 5000 + rand()%10000;
+ AchievTimer = 0;
+
+ if (pInstance)
+ pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (pInstance)
+ {
+ if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR)))
+ if (pDoor->GetGoState() == GO_STATE_READY)
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ //Achievement counter
+ if (pInstance)
+ if (pInstance->GetData(DATA_MAIDEN_OF_GRIEF_EVENT) == IN_PROGRESS)
+ AchievTimer += diff;
+
+ if (IsHeroic())
+ {
+ if (PartingSorrowTimer <= diff)
+ {
+ Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
+
+ if(pTarget)
+ DoCast(pTarget, SPELL_PARTING_SORROW);
+
+ PartingSorrowTimer = 30000 + rand()%10000;
+ } else PartingSorrowTimer -= diff;
+ }
+
+ if (StormOfGriefTimer <= diff)
+ {
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_STORM_OF_GRIEF_N, SPELL_STORM_OF_GRIEF_H), true);
+ StormOfGriefTimer = 15000 + rand()%5000;
+ } else StormOfGriefTimer -= diff;
+
+ if (ShockOfSorrowTimer <= diff)
+ {
+ DoResetThreat();
+ DoScriptText(SAY_STUN, m_creature);
+ DoCast(m_creature, DUNGEON_MODE(SPELL_SHOCK_OF_SORROW_N, SPELL_SHOCK_OF_SORROW_H));
+ ShockOfSorrowTimer = 20000 + rand()%10000;
+ } else ShockOfSorrowTimer -= diff;
+
+ if (PillarOfWoeTimer <= diff)
+ {
+ Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
+
+ if (pTarget)
+ DoCast(pTarget, DUNGEON_MODE(SPELL_PILLAR_OF_WOE_N, SPELL_PILLAR_OF_WOE_H));
+ else
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_PILLAR_OF_WOE_N, SPELL_PILLAR_OF_WOE_H));
+
+ PillarOfWoeTimer = 5000 + rand()%20000;
+ } else PillarOfWoeTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (pInstance)
+ pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE);
+
+ AchievementEntry const *AchievGoodGrief = GetAchievementStore()->LookupEntry(ACHIEVEMENT_GOOD_GRIEF);
+ Map* pMap = m_creature->GetMap();
+
+ if (IsHeroic() && AchievTimer < 60000 && pMap && pMap->IsDungeon() && AchievGoodGrief)
+ {
+ Map::PlayerList const &players = pMap->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ itr->getSource()->CompletedAchievement(AchievGoodGrief);
+ }
+ }
+ void KilledUnit(Unit *victim)
+ {
+ if (victim == m_creature)
+ return;
+
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), m_creature);
+ }
+};
+
+CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature)
+{
+ return new boss_maiden_of_griefAI (pCreature);
+}
+
+void AddSC_boss_maiden_of_grief()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_maiden_of_grief";
+ newscript->GetAI = &GetAI_boss_maiden_of_grief;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp b/src/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp
new file mode 100644
index 00000000000..5986748f0c5
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp
@@ -0,0 +1,300 @@
+/* Script Data Start
+SDName: Boss sjonnir
+SDAuthor: LordVanMartin
+SD%Complete:
+SDComment:
+SDCategory:
+Script Data End */
+
+/*** SQL START ***
+update creature_template set scriptname = 'boss_sjonnir' where entry = '';
+*** SQL END ***/
+#include "ScriptedPch.h"
+#include "halls_of_stone.h"
+
+enum Spells
+{
+ SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841
+ H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849
+ SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841
+ H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849
+ SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835
+ H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847
+ SPELL_CHAIN_LIGHTING = 50830,
+ H_SPELL_CHAIN_LIGHTING = 59844,
+ SPELL_LIGHTING_SHIELD = 50831,
+ H_SPELL_LIGHTING_SHIELD = 59845,
+ SPELL_FRENZY = 28747
+};
+
+enum Yells
+{
+ SAY_AGGRO = -1603011,
+ SAY_SLAY_1 = -1603012,
+ SAY_SLAY_2 = -1603013,
+ SAY_SLAY_3 = -1603014,
+ SAY_DEATH = -1603015
+};
+
+#define EMOTE_GENERIC_FRENZY -1000002
+
+enum SjonnirCreatures
+{
+ CREATURE_FORGED_IRON_TROGG = 27979,
+ CREATURE_MALFORMED_OOZE = 27981,
+ CREATURE_FORGED_IRON_DWARF = 27982,
+ CREATURE_IRON_SLUDGE = 28165
+};
+
+enum Misc
+{
+ DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs
+ ACHIEV_ABUSE_THE_OOZE = 2155
+};
+
+struct Locations
+{
+ float x, y, z;
+};
+
+static Locations PipeLocations[] =
+{
+ {1295.44, 734.07, 200.3}, //left
+ {1297.7, 595.6, 199.9} //right
+};
+
+static Locations CenterPoint = {1295.21, 667.157, 189.691};
+
+struct TRINITY_DLL_DECL boss_sjonnirAI : public ScriptedAI
+{
+ boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ bool bIsFrenzy;
+
+ uint32 uiChainLightningTimer;
+ uint32 uiLightningShieldTimer;
+ uint32 uiStaticChargeTimer;
+ uint32 uiLightningRingTimer;
+ uint32 uiSummonTimer;
+ uint32 uiFrenzyTimer;
+ uint32 uiEncounterTimer;
+ uint32 uiKilledIronSludges;
+
+ SummonList lSummons;
+
+ ScriptedInstance* pInstance;
+
+ void Reset()
+ {
+ bIsFrenzy = false;
+
+ uiEncounterTimer = 0;
+ uiChainLightningTimer = 3000 + rand()%5000;
+ uiLightningShieldTimer = 20000 + rand()%5000;
+ uiStaticChargeTimer = 20000 + rand()%5000;
+ uiLightningRingTimer = 30000 + rand()%5000;
+ uiSummonTimer = 5000;
+ uiFrenzyTimer = 300000; //5 minutes
+ uiKilledIronSludges = 0;
+
+ lSummons.DespawnAll();
+
+ if (pInstance)
+ pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ uiEncounterTimer = 0;
+
+ if (pInstance)
+ {
+ if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR)))
+ if (pDoor->GetGoState() == GO_STATE_READY)
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ if (uiChainLightningTimer <= diff)
+ {
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_CHAIN_LIGHTING, H_SPELL_CHAIN_LIGHTING));
+ uiChainLightningTimer = 10000 + rand()%5000;
+ } else uiChainLightningTimer -= diff;
+
+ if (uiLightningShieldTimer <= diff)
+ {
+ DoCast(m_creature, DUNGEON_MODE(SPELL_LIGHTING_SHIELD, H_SPELL_LIGHTING_SHIELD));
+ uiLightningShieldTimer -= diff;
+ }
+
+ if (uiStaticChargeTimer <= diff)
+ {
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_STATIC_CHARGE, H_SPELL_STATIC_CHARGE));
+ uiStaticChargeTimer = 20000 + rand()%5000;
+ } uiStaticChargeTimer -= diff;
+
+ if (uiLightningRingTimer <= diff)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCast(m_creature, DUNGEON_MODE(SPELL_LIGHTING_RING, H_SPELL_LIGHTING_RING));
+ uiLightningRingTimer = 30000 + rand()%5000;
+ } else uiLightningRingTimer -= diff;
+
+ if (uiSummonTimer <= diff)
+ {
+ uint32 uiSummonPipe = rand()%2;
+ m_creature->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE :
+ RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG),
+ PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f,
+ TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ uiSummonTimer = 20000;
+ } else uiSummonTimer -= diff;
+
+ if (!bIsFrenzy)
+ {
+ if (uiFrenzyTimer <= diff)
+ {
+ DoCast(m_creature, SPELL_FRENZY);
+ bIsFrenzy = true;
+ }
+ else uiFrenzyTimer -= diff;
+ }
+
+ uiEncounterTimer +=diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z);
+ /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ summon->AI()->AttackStart(pTarget);*/
+ lSummons.Summon(summon);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ lSummons.DespawnAll();
+
+ if (pInstance)
+ {
+ pInstance->SetData(DATA_SJONNIR_EVENT, DONE);
+ if (IsHeroic() && uiKilledIronSludges > 4)
+ pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE);
+ }
+ }
+ void KilledUnit(Unit *victim)
+ {
+ if (victim == m_creature)
+ return;
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), m_creature);
+ }
+
+ void KilledIronSludge()
+ {
+ ++uiKilledIronSludges;
+ }
+};
+
+CreatureAI* GetAI_boss_sjonnir(Creature* pCreature)
+{
+ return new boss_sjonnirAI (pCreature);
+}
+
+struct TRINITY_DLL_DECL mob_malformed_oozeAI : public ScriptedAI
+{
+ mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {}
+
+ uint32 uiMergeTimer;
+
+ void Reset()
+ {
+ uiMergeTimer = 10000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (uiMergeTimer <= diff)
+ {
+ if (Creature* pTemp = m_creature->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true))
+ {
+ DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000);
+ pTemp->DisappearAndDie();
+ m_creature->DisappearAndDie();
+ }
+ uiMergeTimer = 3000;
+ } else uiMergeTimer -= diff;
+
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature)
+{
+ return new mob_malformed_oozeAI(pCreature);
+}
+
+struct TRINITY_DLL_DECL mob_iron_sludgeAI : public ScriptedAI
+{
+ mob_iron_sludgeAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ ScriptedInstance* pInstance;
+
+ void JustDied(Unit* pKiller)
+ {
+ if (pInstance)
+ if(Creature* pSjonnir = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_SJONNIR)))
+ CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge();
+ }
+};
+
+CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature)
+{
+ return new mob_iron_sludgeAI(pCreature);
+}
+
+void AddSC_boss_sjonnir()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_sjonnir";
+ newscript->GetAI = &GetAI_boss_sjonnir;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_malformed_ooze";
+ newscript->GetAI = &GetAI_mob_malformed_ooze;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_iron_sludge";
+ newscript->GetAI = &GetAI_mob_iron_sludge;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp b/src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp
new file mode 100644
index 00000000000..1c21f531c96
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp
@@ -0,0 +1,690 @@
+#include "ScriptedPch.h"
+#include "ScriptedEscortAI.h"
+#include "halls_of_stone.h"
+
+enum Texts
+{
+ SAY_KILL_1 = -1603016,
+ SAY_KILL_2 = -1603017,
+ SAY_KILL_3 = -1603018,
+ SAY_LOW_HEALTH = -1603019,
+ SAY_DEATH = -1603020,
+ SAY_PLAYER_DEATH_1 = -1603021,
+ SAY_PLAYER_DEATH_2 = -1603022,
+ SAY_PLAYER_DEATH_3 = -1603023,
+ SAY_ESCORT_START = -1603024,
+
+ SAY_SPAWN_DWARF = -1603025,
+ SAY_SPAWN_TROGG = -1603026,
+ SAY_SPAWN_OOZE = -1603027,
+ SAY_SPAWN_EARTHEN = -1603028,
+
+ SAY_EVENT_INTRO_1 = -1603029,
+ SAY_EVENT_INTRO_2 = -1603030,
+ SAY_EVENT_INTRO_3_ABED = -1603031,
+
+ SAY_EVENT_A_1 = -1603032,
+ SAY_EVENT_A_2_KADD = -1603033,
+ SAY_EVENT_A_3 = -1603034,
+
+ SAY_EVENT_B_1 = -1603035,
+ SAY_EVENT_B_2_MARN = -1603036,
+ SAY_EVENT_B_3 = -1603037,
+
+ SAY_EVENT_C_1 = -1603038,
+ SAY_EVENT_C_2_ABED = -1603039,
+ SAY_EVENT_C_3 = -1603040,
+
+ SAY_EVENT_D_1 = -1603041,
+ SAY_EVENT_D_2_ABED = -1603042,
+ SAY_EVENT_D_3 = -1603043,
+ SAY_EVENT_D_4_ABED = -1603044,
+
+ SAY_EVENT_END_01 = -1603045,
+ SAY_EVENT_END_02 = -1603046,
+ SAY_EVENT_END_03_ABED = -1603047,
+ SAY_EVENT_END_04 = -1603048,
+ SAY_EVENT_END_05_ABED = -1603049,
+ SAY_EVENT_END_06 = -1603050,
+ SAY_EVENT_END_07_ABED = -1603051,
+ SAY_EVENT_END_08 = -1603052,
+ SAY_EVENT_END_09_KADD = -1603053,
+ SAY_EVENT_END_10 = -1603054,
+ SAY_EVENT_END_11_KADD = -1603055,
+ SAY_EVENT_END_12 = -1603056,
+ SAY_EVENT_END_13_KADD = -1603057,
+ SAY_EVENT_END_14 = -1603058,
+ SAY_EVENT_END_15_MARN = -1603059,
+ SAY_EVENT_END_16 = -1603060,
+ SAY_EVENT_END_17_MARN = -1603061,
+ SAY_EVENT_END_18 = -1603062,
+ SAY_EVENT_END_19_MARN = -1603063,
+ SAY_EVENT_END_20 = -1603064,
+ SAY_EVENT_END_21_ABED = -1603065,
+
+ SAY_VICTORY_SJONNIR_1 = -1603066,
+ SAY_VICTORY_SJONNIR_2 = -1603067,
+
+ SAY_ENTRANCE_MEET = -1603068,
+
+ TEXT_ID_START = 13100,
+ TEXT_ID_PROGRESS = 13101
+};
+
+enum BrannCreatures
+{
+ CREATURE_TRIBUNAL_OF_THE_AGES = 28234,
+ CREATURE_BRANN_BRONZEBEARD = 28070,
+ CREATURE_DARK_MATTER_TARGET = 28237,
+ CREATURE_SEARING_GAZE_TARGET = 28265,
+ CREATURE_DARK_RUNE_PROTECTOR = 27983,
+ CREATURE_DARK_RUNE_STORMCALLER = 27984,
+ CREATURE_IRON_GOLEM_CUSTODIAN = 27985,
+};
+
+enum Spells
+{
+ SPELL_STEALTH = 58506,
+ //Kadrak
+ SPELL_GLARE_OF_THE_TRIBUNAL = 50988,
+ H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868,
+ //Marnak
+ SPELL_DARK_MATTER = 51012,
+ H_SPELL_DARK_MATTER = 59868,
+ //Abedneum
+ SPELL_SEARING_GAZE = 51136,
+ H_SPELL_SEARING_GAZE = 59867
+};
+
+enum Quests
+{
+ QUEST_HALLS_OF_STONE = 13207
+};
+
+#define GOSSIP_ITEM_START "Brann, it would be our honor!"
+#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!"
+
+struct Locations
+{
+ float x, y, z;
+};
+
+static Locations SpawnLocations[]=
+{
+ {946.992, 397.016, 208.374},
+ {960.748, 382.944, 208.374},
+};
+
+struct TRINITY_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI
+{
+ mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ SetCombatMovement(false);
+ }
+
+ ScriptedInstance* pInstance;
+
+ uint32 uiKaddrakEncounterTimer;
+ uint32 uiMarnakEncounterTimer;
+ uint32 uiAbedneumEncounterTimer;
+
+ bool bKaddrakActivated;
+ bool bMarnakActivated;
+ bool bAbedneumActivated;
+
+ std::list<Creature*> lKaddrakGUIDList;
+
+ void Reset()
+ {
+ uiKaddrakEncounterTimer = 1500;
+ uiMarnakEncounterTimer = 10000;
+ uiAbedneumEncounterTimer = 10000;
+
+ bKaddrakActivated = false;
+ bMarnakActivated = false;
+ bAbedneumActivated = false;
+
+ lKaddrakGUIDList.clear();
+ }
+
+ void UpdateFacesList()
+ {
+ /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, m_creature, CREATURE_KADDRAK, 50.0f);
+ if (!lKaddrakGUIDList.empty())
+ {
+ uint32 uiPositionCounter = 0;
+ for (std::list<Creature*>::iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr)
+ {
+ if ((*itr)->isAlive())
+ {
+ if (uiPositionCounter == 0)
+ {
+ (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation());
+ (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1);
+ }
+ else
+ {
+ (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation());
+ (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1);
+ }
+ }
+ ++uiPositionCounter;
+ }
+ }*/
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(bKaddrakActivated)
+ {
+ if (uiKaddrakEncounterTimer <= diff)
+ {
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ if (!lKaddrakGUIDList.empty())
+ for (std::list<Creature*>::iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr)
+ if ((*itr)->isAlive())
+ (*itr)->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true);
+ uiKaddrakEncounterTimer = 1500;
+ } else uiKaddrakEncounterTimer -= diff;
+ }
+ if (bMarnakActivated)
+ {
+ if (uiMarnakEncounterTimer <= diff)
+ {
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ {
+ if (Creature* pSummon = m_creature->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000))
+ {
+ pSummon->SetDisplayId(11686);
+ pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true);
+ }
+ }
+ uiMarnakEncounterTimer = 30000 + rand()%1000;
+ } else uiMarnakEncounterTimer -= diff;
+ }
+ if (bAbedneumActivated)
+ {
+ if (uiAbedneumEncounterTimer <= diff)
+ {
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ {
+ if (Creature* pSummon = m_creature->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000))
+ {
+ pSummon->SetDisplayId(11686);
+ pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true);
+ }
+ }
+ uiAbedneumEncounterTimer = 30000 + rand()%1000;
+ } else uiAbedneumEncounterTimer -= diff;
+ }
+ }
+};
+
+struct TRINITY_DLL_DECL npc_brann_hosAI : public npc_escortAI
+{
+ npc_brann_hosAI(Creature *c) : npc_escortAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ uint32 uiStep;
+ uint32 uiPhaseTimer;
+
+ uint64 uiControllerGUID;
+ std::list<uint64> lDwarfGUIDList;
+
+ ScriptedInstance* pInstance;
+
+ bool bIsBattle;
+ bool bIsLowHP;
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ bIsLowHP = false;
+ bIsBattle = false;
+ uiStep = 0;
+ uiPhaseTimer = 0;
+ uiControllerGUID = 0;
+
+ DespawnDwarf();
+
+ if (pInstance)
+ pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED);
+ }
+ }
+
+ void DespawnDwarf()
+ {
+ if (lDwarfGUIDList.empty())
+ return;
+ for (std::list<uint64>::iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr)
+ {
+ Creature* pTemp = Unit::GetCreature(*m_creature, pInstance ? (*itr) : 0);
+ if (pTemp && pTemp->isAlive())
+ pTemp->ForcedDespawn();
+ }
+ lDwarfGUIDList.clear();
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 7:
+ if (Creature* pCreature = GetClosestCreatureWithEntry(m_creature, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f))
+ {
+ if (!pCreature->isAlive())
+ pCreature->Respawn();
+ CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList();
+ uiControllerGUID = pCreature->GetGUID();
+ }
+ break;
+ case 13:
+ DoScriptText(SAY_EVENT_INTRO_1, m_creature);
+ SetEscortPaused(true);
+ SetRun(true);
+ JumpToNextStep(20000);
+ break;
+ case 17:
+ DoScriptText(SAY_EVENT_INTRO_2, m_creature);
+ if (pInstance)
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ SetEscortPaused(true);
+ JumpToNextStep(8500);
+ break;
+ case 18:
+ SetEscortPaused(true);
+ break;
+ }
+ }
+
+ void SpawnDwarf(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case 1:
+ {
+ uint32 uiSpawnNumber = DUNGEON_MODE(2,3);
+ for (uint8 i = 0; i < uiSpawnNumber; ++i)
+ m_creature->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0].x, SpawnLocations[0].y, SpawnLocations[0].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ m_creature->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0].x, SpawnLocations[0].y, SpawnLocations[0].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ break;
+ }
+ case 2:
+ for (uint8 i = 0; i < 2; ++i)
+ m_creature->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[1].x, SpawnLocations[1].y, SpawnLocations[1].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ break;
+ case 3:
+ m_creature->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[1].x, SpawnLocations[1].y, SpawnLocations[1].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ lDwarfGUIDList.push_back(pSummoned->GetGUID());
+ pSummoned->AddThreat(m_creature, 0.0f);
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+
+ void JumpToNextStep(uint32 uiTimer)
+ {
+ uiPhaseTimer = uiTimer;
+ ++uiStep;
+ }
+
+ void StartWP()
+ {
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ SetEscortPaused(false);
+ uiStep = 1;
+ Start();
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (uiPhaseTimer <= uiDiff)
+ {
+ switch(uiStep)
+ {
+ case 1:
+ if (pInstance)
+ {
+ if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED)
+ return;
+ pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS);
+ }
+ bIsBattle = false;
+ DoScriptText(SAY_ESCORT_START, m_creature);
+ JumpToNextStep(0);
+ break;
+ case 3:
+ SetEscortPaused(false);
+ JumpToNextStep(0);
+ break;
+ case 5:
+ if (pInstance)
+ if (Creature* pTemp = (Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM))))
+ DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp);
+ JumpToNextStep(8500);
+ break;
+ case 6:
+ DoScriptText(SAY_EVENT_A_1, m_creature);
+ JumpToNextStep(6500);
+ break;
+ case 7:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_KADDRAK)))
+ DoScriptText(SAY_EVENT_A_2_KADD, pTemp);
+ JumpToNextStep(12500);
+ break;
+ case 8:
+ DoScriptText(SAY_EVENT_A_3, m_creature);
+ if (pInstance)
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true);
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, uiControllerGUID))
+ CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true;
+ JumpToNextStep(5000);
+ break;
+ case 9:
+ SpawnDwarf(1);
+ JumpToNextStep(20000);
+ break;
+ case 10:
+ DoScriptText(SAY_EVENT_B_1, m_creature);
+ JumpToNextStep(6000);
+ break;
+ case 11:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_MARNAK)))
+ DoScriptText(SAY_EVENT_B_2_MARN, pTemp);
+ SpawnDwarf(1);
+ JumpToNextStep(20000);
+ break;
+ case 12:
+ DoScriptText(SAY_EVENT_B_3, m_creature);
+ if (pInstance)
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true);
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, uiControllerGUID))
+ CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true;
+ JumpToNextStep(10000);
+ break;
+ case 13:
+ SpawnDwarf(1);
+ JumpToNextStep(10000);
+ break;
+ case 14:
+ SpawnDwarf(2);
+ JumpToNextStep(20000);
+ break;
+ case 15:
+ DoScriptText(SAY_EVENT_C_1, m_creature);
+ SpawnDwarf(1);
+ JumpToNextStep(10000);
+ break;
+ case 16:
+ SpawnDwarf(2);
+ JumpToNextStep(20000);
+ break;
+ case 17:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_C_2_ABED, pTemp);
+ SpawnDwarf(1);
+ JumpToNextStep(20000);
+ break;
+ case 18:
+ DoScriptText(SAY_EVENT_C_3, m_creature);
+ if (pInstance)
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true);
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, uiControllerGUID))
+ CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true;
+ JumpToNextStep(5000);
+ break;
+ case 19:
+ SpawnDwarf(2);
+ JumpToNextStep(10000);
+ break;
+ case 20:
+ SpawnDwarf(1);
+ JumpToNextStep(15000);
+ break;
+ case 21:
+ DoScriptText(SAY_EVENT_D_1, m_creature);
+ SpawnDwarf(3);
+ JumpToNextStep(20000);
+ break;
+ case 22:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_D_2_ABED, pTemp);
+ SpawnDwarf(1);
+ JumpToNextStep(5000);
+ break;
+ case 23:
+ SpawnDwarf(2);
+ JumpToNextStep(15000);
+ break;
+ case 24:
+ DoScriptText(SAY_EVENT_D_3, m_creature);
+ SpawnDwarf(3);
+ JumpToNextStep(5000);
+ break;
+ case 25:
+ SpawnDwarf(1);
+ JumpToNextStep(5000);
+ break;
+ case 26:
+ SpawnDwarf(2);
+ JumpToNextStep(10000);
+ break;
+ case 27:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_D_4_ABED, pTemp);
+ SpawnDwarf(1);
+ JumpToNextStep(10000);
+ break;
+ case 28:
+ DoScriptText(SAY_EVENT_END_01, m_creature);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ if (pInstance)
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true);
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, uiControllerGUID))
+ pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ bIsBattle = true;
+ SetEscortPaused(false);
+ JumpToNextStep(6500);
+ break;
+ case 29:
+ DoScriptText(SAY_EVENT_END_02, m_creature);
+ JumpToNextStep(5500);
+ break;
+ case 30:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_END_03_ABED, pTemp);
+ JumpToNextStep(8500);
+ break;
+ case 31:
+ DoScriptText(SAY_EVENT_END_04, m_creature);
+ JumpToNextStep(11500);
+ break;
+ case 32:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_END_05_ABED, pTemp);
+ JumpToNextStep(11500);
+ break;
+ case 33:
+ DoScriptText(SAY_EVENT_END_06, m_creature);
+ JumpToNextStep(4500);
+ break;
+ case 34:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_END_07_ABED, pTemp);
+ JumpToNextStep(22500);
+ break;
+ case 35:
+ DoScriptText(SAY_EVENT_END_08, m_creature);
+ JumpToNextStep(7500);
+ break;
+ case 36:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_KADDRAK)))
+ DoScriptText(SAY_EVENT_END_09_KADD, pTemp);
+ JumpToNextStep(18500);
+ break;
+ case 37:
+ DoScriptText(SAY_EVENT_END_10, m_creature);
+ JumpToNextStep(5500);
+ break;
+ case 38:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_KADDRAK)))
+ DoScriptText(SAY_EVENT_END_11_KADD, pTemp);
+ JumpToNextStep(20500);
+ break;
+ case 39:
+ DoScriptText(SAY_EVENT_END_12, m_creature);
+ JumpToNextStep(2500);
+ break;
+ case 40:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_KADDRAK)))
+ DoScriptText(SAY_EVENT_END_13_KADD, pTemp);
+ JumpToNextStep(19500);
+ break;
+ case 41:
+ DoScriptText(SAY_EVENT_END_14, m_creature);
+ JumpToNextStep(10500);
+ break;
+ case 42:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_MARNAK)))
+ DoScriptText(SAY_EVENT_END_15_MARN, pTemp);
+ JumpToNextStep(6500);
+ break;
+ case 43:
+ DoScriptText(SAY_EVENT_END_16, m_creature);
+ JumpToNextStep(6500);
+ break;
+ case 44:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_MARNAK)))
+ DoScriptText(SAY_EVENT_END_17_MARN, pTemp);
+ JumpToNextStep(25500);
+ break;
+ case 45:
+ DoScriptText(SAY_EVENT_END_18, m_creature);
+ JumpToNextStep(23500);
+ break;
+ case 46:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_MARNAK)))
+ DoScriptText(SAY_EVENT_END_19_MARN, pTemp);
+ JumpToNextStep(3500);
+ break;
+ case 47:
+ DoScriptText(SAY_EVENT_END_20, m_creature);
+ JumpToNextStep(8500);
+ break;
+ case 48:
+ if (pInstance)
+ if (Creature* pTemp = Unit::GetCreature(*m_creature, pInstance->GetData64(DATA_ABEDNEUM)))
+ DoScriptText(SAY_EVENT_END_21_ABED, pTemp);
+ JumpToNextStep(5500);
+ break;
+ case 49:
+ {
+ if (pInstance)
+ {
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true);
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true);
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true);
+ pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true);
+ pInstance->SetData(DATA_BRANN_EVENT, DONE);
+ }
+ Player* pPlayer = GetPlayerForEscort();
+ if (pPlayer)
+ pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, m_creature);
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ JumpToNextStep(180000);
+ break;
+ }
+ case 50:
+ SetEscortPaused(false);
+ break;
+ }
+ } else uiPhaseTimer -= uiDiff;
+
+ if (!bIsLowHP && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 30)
+ {
+ DoScriptText(SAY_LOW_HEALTH, m_creature);
+ bIsLowHP = true;
+ } else if (bIsLowHP && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) > 30)
+ bIsLowHP = false;
+
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP();
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature)
+{
+ return new mob_tribuna_controllerAI(pCreature);
+}
+
+CreatureAI* GetAI_npc_brann_hos(Creature* pCreature)
+{
+ return new npc_brann_hosAI(pCreature);
+}
+
+void AddSC_halls_of_stone()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_brann_hos";
+ newscript->GetAI = &GetAI_npc_brann_hos;
+ newscript->pGossipHello = &GossipHello_npc_brann_hos;
+ newscript->pGossipSelect = &GossipSelect_npc_brann_hos;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_tribuna_controller";
+ newscript->GetAI = &GetAI_mob_tribuna_controller;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h b/src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h
new file mode 100644
index 00000000000..b61e7057ddc
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h
@@ -0,0 +1,48 @@
+#ifndef DEF_HALLS_OF_STONE_H
+#define DEF_HALLS_OF_STONE_H
+enum Data
+{
+ DATA_KRYSTALLUS_EVENT,
+ DATA_MAIDEN_OF_GRIEF_EVENT,
+ DATA_SJONNIR_EVENT,
+ DATA_BRANN_EVENT
+};
+enum Data64
+{
+ DATA_KRYSTALLUS,
+ DATA_MAIDEN_OF_GRIEF,
+ DATA_SJONNIR,
+ DATA_KADDRAK,
+ DATA_MARNAK,
+ DATA_ABEDNEUM,
+ DATA_GO_TRIBUNAL_CONSOLE,
+ DATA_GO_KADDRAK,
+ DATA_GO_MARNAK,
+ DATA_GO_ABEDNEUM,
+ DATA_GO_SKY_FLOOR,
+ DATA_SJONNIR_DOOR,
+ DATA_MAIDEN_DOOR
+};
+enum Creatures
+{
+ CREATURE_MAIDEN = 27975,
+ CREATURE_KRYSTALLUS = 27977,
+ CREATURE_SJONNIR = 27978,
+ CREATURE_MARNAK = 30897,
+ CREATURE_KADDRAK = 30898,
+ CREATURE_ABEDNEUM = 30899,
+ CREATURE_BRANN = 28070
+};
+enum GameObjects
+{
+ GO_ABEDNEUM = 191669,
+ GO_MARNAK = 192170,
+ GO_KADDRAK = 192171,
+ GO_MAIDEN_DOOR = 191292,
+ GO_BRANN_DOOR = 191295,
+ GO_SJONNIR_DOOR = 191296,
+ GO_TRIBUNAL_CONSOLE = 193907,
+ GO_TRIBUNAL_CHEST = 190586,
+ GO_TRIBUNAL_CHEST_HERO = 193996
+};
+#endif
diff --git a/src/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp b/src/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp
new file mode 100644
index 00000000000..07fece777f5
--- /dev/null
+++ b/src/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp
@@ -0,0 +1,254 @@
+#include "ScriptedPch.h"
+#include "halls_of_stone.h"
+
+#define MAX_ENCOUNTER 4
+
+/* Halls of Stone encounters:
+0- Krystallus
+1- Maiden of Grief
+2- Escort Event
+3- Sjonnir The Ironshaper
+*/
+
+struct TRINITY_DLL_DECL instance_halls_of_stone : public ScriptedInstance
+{
+ instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint64 uiMaidenOfGrief;
+ uint64 uiKrystallus;
+ uint64 uiSjonnir;
+
+ uint64 uiKaddrak;
+ uint64 uiAbedneum;
+ uint64 uiMarnak;
+ uint64 uiBrann;
+
+ uint64 uiMaidenOfGriefDoor;
+ uint64 uiSjonnirDoor;
+ uint64 uiBrannDoor;
+ uint64 uiTribunalConsole;
+ uint64 uiTribunalChest;
+ uint64 uiTribunalSkyFloor;
+ uint64 uiKaddrakGo;
+ uint64 uiAbedneumGo;
+ uint64 uiMarnakGo;
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ std::string str_data;
+
+ void Initialize()
+ {
+ uiMaidenOfGrief = 0;
+ uiKrystallus = 0;
+ uiSjonnir = 0;
+
+ uiKaddrak = 0;
+ uiMarnak = 0;
+ uiAbedneum = 0;
+ uiBrann = 0;
+
+ uiMaidenOfGriefDoor = 0;
+ uiSjonnirDoor = 0;
+ uiBrannDoor = 0;
+ uiKaddrakGo = 0;
+ uiMarnakGo = 0;
+ uiAbedneumGo = 0;
+ uiTribunalConsole = 0;
+ uiTribunalChest = 0;
+ uiTribunalSkyFloor = 0;
+
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ void OnCreatureCreate(Creature* pCreature, bool add)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break;
+ case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break;
+ case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break;
+ case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break;
+ case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break;
+ case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break;
+ case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnGameObjectCreate(GameObject* pGo, bool add)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_ABEDNEUM:
+ uiAbedneumGo = pGo->GetGUID();
+ break;
+ case GO_MARNAK:
+ uiMarnakGo = pGo->GetGUID();
+ break;
+ case GO_KADDRAK:
+ uiKaddrakGo = pGo->GetGUID();
+ break;
+ case GO_MAIDEN_DOOR:
+ uiMaidenOfGriefDoor = pGo->GetGUID();
+ if (m_auiEncounter[0] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ else
+ pGo->SetGoState(GO_STATE_READY);
+ break;
+ case GO_BRANN_DOOR:
+ uiBrannDoor = pGo->GetGUID();
+ if (m_auiEncounter[1] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ else
+ pGo->SetGoState(GO_STATE_READY);
+ break;
+ case GO_SJONNIR_DOOR:
+ uiSjonnirDoor = pGo->GetGUID();
+ if (m_auiEncounter[2] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ else
+ pGo->SetGoState(GO_STATE_READY);
+ break;
+ case GO_TRIBUNAL_CONSOLE:
+ uiTribunalConsole = pGo->GetGUID();
+ break;
+ case GO_TRIBUNAL_CHEST:
+ case GO_TRIBUNAL_CHEST_HERO:
+ uiTribunalChest = pGo->GetGUID();
+ if (m_auiEncounter[2] == DONE)
+ pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
+ break;
+ case 191527:
+ uiTribunalSkyFloor = pGo->GetGUID();
+ break;
+ }
+ }
+
+ void SetData(uint32 type, uint32 data)
+ {
+ switch(type)
+ {
+ case DATA_MAIDEN_OF_GRIEF_EVENT:
+ m_auiEncounter[1] = data;
+ if (m_auiEncounter[1] == DONE)
+ HandleGameObject(uiBrannDoor,true);
+ break;
+ case DATA_KRYSTALLUS_EVENT:
+ m_auiEncounter[0] = data;
+ if (m_auiEncounter[0] == DONE)
+ HandleGameObject(uiMaidenOfGriefDoor,true);
+ break;
+ case DATA_SJONNIR_EVENT:
+ m_auiEncounter[3] = data;
+ break;
+ case DATA_BRANN_EVENT:
+ m_auiEncounter[2] = data;
+ if (m_auiEncounter[2] == DONE)
+ {
+ HandleGameObject(uiSjonnirDoor,true);
+ GameObject *pGo = instance->GetGameObject(uiTribunalChest);
+ if (pGo)
+ pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
+ }
+ break;
+ }
+
+ if (data == DONE)
+ SaveToDB();
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ switch(type)
+ {
+ case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0];
+ case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1];
+ case DATA_SJONNIR_EVENT: return m_auiEncounter[2];
+ case DATA_BRANN_EVENT: return m_auiEncounter[3];
+ }
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 identifier)
+ {
+ switch(identifier)
+ {
+ case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief;
+ case DATA_KRYSTALLUS: return uiKrystallus;
+ case DATA_SJONNIR: return uiSjonnir;
+ case DATA_KADDRAK: return uiKaddrak;
+ case DATA_MARNAK: return uiMarnak;
+ case DATA_ABEDNEUM: return uiAbedneum;
+ case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole;
+ case DATA_GO_KADDRAK: return uiKaddrakGo;
+ case DATA_GO_ABEDNEUM: return uiAbedneumGo;
+ case DATA_GO_MARNAK: return uiMarnakGo;
+ case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor;
+ case DATA_SJONNIR_DOOR: return uiSjonnirDoor;
+ case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor;
+ }
+
+ return 0;
+ }
+
+ std::string GetSaveData()
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3];
+
+ str_data = saveStream.str();
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return str_data;
+ }
+
+ void Load(const char* in)
+ {
+ if (!in)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(in);
+
+ char dataHead1, dataHead2;
+ uint16 data0, data1, data2, data3;
+
+ std::istringstream loadStream(in);
+ loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3;
+
+ if (dataHead1 == 'H' && dataHead2 == 'S')
+ {
+ m_auiEncounter[0] = data0;
+ m_auiEncounter[1] = data1;
+ m_auiEncounter[2] = data2;
+ m_auiEncounter[3] = data3;
+
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+
+ } else OUT_LOAD_INST_DATA_FAIL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap)
+{
+ return new instance_halls_of_stone(pMap);
+}
+
+void AddSC_instance_halls_of_stone()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_halls_of_stone";
+ newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_algalon.cpp b/src/scripts/northrend/ulduar/ulduar/boss_algalon.cpp
new file mode 100644
index 00000000000..a9f1be65f2d
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_algalon.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp b/src/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp
new file mode 100644
index 00000000000..229f912e226
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2008 - 2009 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
+ */
+
+/* ScriptData
+SDName: Assembly of Iron encounter
+SD%Complete: 60%
+SDComment: Runes need DB support, chain lightning won't cast, supercharge won't cast (pTarget error?) - it worked before during debugging.
+SDCategory: Ulduar - Ulduar
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "ulduar.h"
+
+// Any boss
+#define SPELL_SUPERCHARGE 61920
+#define SPELL_BERSERK 47008 // Hard enrage, don't know the correct ID.
+
+// Steelbreaker
+#define SPELL_HIGH_VOLTAGE 61890
+#define SPELL_HIGH_VOLTAGE_H 63498
+#define SPELL_FUSION_PUNCH 61903
+#define SPELL_FUSION_PUNCH_H 63493
+#define SPELL_STATIC_DISRUPTION 44008
+#define SPELL_STATIC_DISRUPTION_H 63494
+#define SPELL_OVERWHELMING_POWER_H 61888
+#define SPELL_OVERWHELMING_POWER 64637
+#define SPELL_ELECTRICAL_CHARGE 61902
+
+// Runemaster Molgeim
+#define SPELL_SHIELD_OF_RUNES 62274
+#define SPELL_SHIELD_OF_RUNES_H 63489
+#define SPELL_RUNE_OF_POWER 64320
+#define SPELL_RUNE_OF_DEATH 62269
+#define SPELL_RUNE_OF_SUMMONING 62273
+#define SPELL_LIGHTNING_BLAST 62054
+#define SPELL_LIGHTNING_BLAST_H 63491
+#define CREATURE_RUNE_OF_SUMMONING 33051
+
+// Stormcaller Brundir
+#define SPELL_CHAIN_LIGHTNING_N 61879
+#define SPELL_CHAIN_LIGHTNING_H 63479
+#define SPELL_OVERLOAD 61869
+#define SPELL_OVERLOAD_H 63481
+#define SPELL_LIGHTNING_WHIRL 61915
+#define SPELL_LIGHTNING_WHIRL_H 63483
+#define SPELL_LIGHTNING_TENDRILS 61887
+#define SPELL_LIGHTNING_TENDRILS_H 63486
+#define SPELL_STORMSHIELD 64187
+
+enum eEnums
+{
+ EVENT_ENRAGE,
+ // Steelbreaker
+ EVENT_FUSION_PUNCH,
+ EVENT_STATIC_DISRUPTION,
+ EVENT_OVERWHELMING_POWER,
+ // Molgeim
+ EVENT_RUNE_OF_POWER,
+ EVENT_SHIELD_OF_RUNES,
+ EVENT_RUNE_OF_DEATH,
+ EVENT_RUNE_OF_SUMMONING,
+ EVENT_LIGHTNING_BLAST,
+ // Brundir
+ EVENT_CHAIN_LIGHTNING,
+ EVENT_OVERLOAD,
+ EVENT_LIGHTNING_WHIRL,
+ EVENT_LIGHTNING_TENDRILS,
+ EVENT_STORMSHIELD,
+ MAX_EVENT
+
+};
+
+bool IsEncounterComplete(ScriptedInstance* pInstance, Creature* m_creature)
+{
+ if (!pInstance || !m_creature)
+ return false;
+
+ for (uint8 i = 0; i < 3; ++i)
+ {
+ uint64 guid = pInstance->GetData64(DATA_STEELBREAKER+i);
+ if(!guid)
+ return false;
+
+ if(Creature *boss = (Unit::GetCreature((*m_creature), guid)))
+ {
+ if(boss->isAlive())
+ return false;
+
+ continue;
+ }
+ else
+ return false;
+ }
+ return true;
+}
+
+struct TRINITY_DLL_DECL boss_steelbreakerAI : public ScriptedAI
+{
+ boss_steelbreakerAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ phase = 0;
+ m_creature->RemoveAllAuras();
+ if(pInstance)
+ pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
+ }
+
+ EventMap events;
+ ScriptedInstance* pInstance;
+ uint32 phase;
+
+ void EnterCombat(Unit *who)
+ {
+ DoZoneInCombat();
+ DoCast(m_creature, RAID_MODE(SPELL_HIGH_VOLTAGE, SPELL_HIGH_VOLTAGE_H));
+ events.ScheduleEvent(EVENT_ENRAGE, 900000);
+ UpdatePhase();
+ }
+
+ void UpdatePhase()
+ {
+ ++phase;
+ events.SetPhase(phase);
+ events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000);
+ if(phase >= 2)
+ events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000);
+ if(phase >= 3)
+ events.RescheduleEvent(EVENT_OVERWHELMING_POWER, rand()%5000);
+ }
+
+ void DamageTaken(Unit* pKiller, uint32 &damage)
+ {
+ if(damage >= m_creature->GetHealth())
+ {
+ if(Creature* Brundir = Unit::GetCreature(*m_creature, pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0))
+ if(Brundir->isAlive())
+ {
+ Brundir->SetHealth(Brundir->GetMaxHealth());
+ }
+
+ if(Creature* Molgeim = Unit::GetCreature(*m_creature, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0))
+ if(Molgeim->isAlive())
+ {
+ Molgeim->SetHealth(Molgeim->GetMaxHealth());
+ }
+ DoCast(SPELL_SUPERCHARGE);
+ }
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if(IsEncounterComplete(pInstance, m_creature) && pInstance)
+ pInstance->SetData(TYPE_ASSEMBLY, DONE);
+ }
+
+ void KilledUnit(Unit *who)
+ {
+ if(phase == 3)
+ DoCast(m_creature, SPELL_ELECTRICAL_CHARGE);
+ }
+
+ void SpellHit(Unit *from, const SpellEntry *spell)
+ {
+ if(spell->Id == SPELL_SUPERCHARGE)
+ UpdatePhase();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_ENRAGE:
+ DoCast(SPELL_BERSERK);
+ break;
+ case EVENT_FUSION_PUNCH:
+ DoCast(me->getVictim(), RAID_MODE(SPELL_FUSION_PUNCH_H, SPELL_FUSION_PUNCH));
+ events.ScheduleEvent(EVENT_FUSION_PUNCH, 13000 + (rand()%9)*1000);
+ break;
+ case EVENT_STATIC_DISRUPTION:
+ {
+ Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM);
+ DoCast(pTarget, RAID_MODE(SPELL_STATIC_DISRUPTION_H, SPELL_STATIC_DISRUPTION));
+ events.ScheduleEvent(EVENT_STATIC_DISRUPTION, 20000 + (rand()%20)*1000);
+ }
+ break;
+ case EVENT_OVERWHELMING_POWER:
+ DoCast(me->getVictim(), RAID_MODE(SPELL_OVERWHELMING_POWER, SPELL_OVERWHELMING_POWER_H));
+ events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000));
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct TRINITY_DLL_DECL boss_runemaster_molgeimAI : public ScriptedAI
+{
+ boss_runemaster_molgeimAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ void Reset()
+ {
+ if(pInstance)
+ pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
+ events.Reset();
+ m_creature->RemoveAllAuras();
+ phase = 0;
+ }
+
+ ScriptedInstance* pInstance;
+ EventMap events;
+ uint32 phase;
+
+ void EnterCombat(Unit* who)
+ {
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_ENRAGE, 900000);
+ UpdatePhase();
+ }
+
+ void UpdatePhase()
+ {
+ ++phase;
+ events.SetPhase(phase);
+ events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000);
+ events.RescheduleEvent(EVENT_RUNE_OF_POWER, 60000);
+ if(phase >= 2)
+ events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000);
+ if(phase >= 3)
+ events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, 20000+(rand()%10)*1000);
+ }
+
+ void DamageTaken(Unit* pKiller, uint32 &damage)
+ {
+ if(damage >= m_creature->GetHealth())
+ {
+ if(Creature* Steelbreaker = Unit::GetCreature(*m_creature, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0))
+ if(Steelbreaker->isAlive())
+ {
+ Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth());
+ }
+
+ if(Creature* Brundir = Unit::GetCreature((*m_creature), pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0))
+ if(Brundir->isAlive())
+ {
+ Brundir->SetHealth(Brundir->GetMaxHealth());
+ }
+ DoCast(m_creature, SPELL_SUPERCHARGE);
+ }
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if(IsEncounterComplete(pInstance, m_creature) && pInstance)
+ pInstance->SetData(TYPE_ASSEMBLY, DONE);
+ }
+
+ void SpellHit(Unit *from, const SpellEntry *spell)
+ {
+ if(spell->Id == SPELL_SUPERCHARGE)
+ UpdatePhase();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_ENRAGE:
+ DoCast(SPELL_BERSERK);
+ break;
+ case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly
+ {
+ Unit *Target = DoSelectLowestHpFriendly(60);
+ if(!Target || (Target && !Target->isAlive()))
+ Target = m_creature;
+ DoCast(Target, SPELL_RUNE_OF_POWER);
+ events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000);
+ }
+ break;
+ case EVENT_SHIELD_OF_RUNES:
+ DoCast(m_creature, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H));
+ events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, 27000+ (rand()%7)*1000);
+ break;
+ case EVENT_RUNE_OF_DEATH:
+ {
+ Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM);
+ DoCast(pTarget, SPELL_RUNE_OF_DEATH);
+ events.ScheduleEvent(EVENT_RUNE_OF_DEATH, 30000+ (rand()%10)*1000);
+ }
+ break;
+ case EVENT_RUNE_OF_SUMMONING:
+ {
+ Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM);
+ DoCast(pTarget, SPELL_RUNE_OF_SUMMONING);
+ events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, 20000+(rand()%10)*1000);
+ }
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct TRINITY_DLL_DECL mob_lightning_elementalAI : public ScriptedAI
+{
+ mob_lightning_elementalAI(Creature *c) : ScriptedAI(c)
+ {
+ Charge();
+ }
+
+ Unit* Target;
+
+ void Charge()
+ {
+ Target = m_creature->SelectNearestTarget();
+ m_creature->AddThreat(Target, 5000000.0f);
+ AttackStart(Target);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(!m_creature->isInCombat())
+ return;
+
+ if(m_creature->IsWithinMeleeRange(Target))
+ {
+ DoCast(Target, RAID_MODE(SPELL_LIGHTNING_BLAST, SPELL_LIGHTNING_BLAST_H));
+ m_creature->Kill(m_creature); // hack until spell works
+ }
+
+ m_creature->GetMotionMaster()->MoveChase(Target); // needed at every update?
+ }
+
+};
+
+struct TRINITY_DLL_DECL mob_rune_of_summoningAI : public ScriptedAI
+{
+ mob_rune_of_summoningAI(Creature *c) : ScriptedAI(c)
+ {
+ SummonLightningElemental();
+ }
+
+ void SummonLightningElemental()
+ {
+ m_creature->SummonCreature(CREATURE_RUNE_OF_SUMMONING, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN );
+ m_creature->DealDamage(m_creature, m_creature->GetHealth());
+ }
+};
+
+struct TRINITY_DLL_DECL boss_stormcaller_brundirAI : public ScriptedAI
+{
+ boss_stormcaller_brundirAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ void Reset()
+ {
+ if(pInstance)
+ pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
+ m_creature->RemoveAllAuras();
+ events.Reset();
+ phase = 0;
+ }
+
+ EventMap events;
+ ScriptedInstance* pInstance;
+ uint32 phase;
+
+ void EnterCombat(Unit* who)
+ {
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_ENRAGE, 900000);
+ UpdatePhase();
+ }
+
+ void UpdatePhase()
+ {
+ ++phase;
+ events.SetPhase(phase);
+ events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, 9000+ (rand()%8)*1000);
+ events.RescheduleEvent(EVENT_OVERLOAD, 60000+ (rand()%65)*1000);
+ if(phase >= 2)
+ events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, 20000+ (rand()%20)*1000);
+ if(phase >= 3)
+ {
+ DoCast(m_creature, SPELL_STORMSHIELD);
+ events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, 40000+ (rand()%40)*1000);
+ }
+
+ }
+
+ void DamageTaken(Unit* pKiller, uint32 &damage)
+ {
+ if(damage >= m_creature->GetHealth())
+ {
+ if(Creature* Steelbreaker = Unit::GetCreature(*m_creature, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0))
+ if(Steelbreaker->isAlive())
+ {
+ Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth());
+ }
+
+ if(Creature* Molgeim = Unit::GetCreature(*m_creature, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0))
+ if(Molgeim->isAlive())
+ {
+ Molgeim->SetHealth(Molgeim->GetMaxHealth());
+ }
+
+ DoCast(SPELL_SUPERCHARGE);
+ }
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if(IsEncounterComplete(pInstance, m_creature) && pInstance)
+ pInstance->SetData(TYPE_ASSEMBLY, DONE);
+ }
+
+ void SpellHit(Unit *from, const SpellEntry *spell)
+ {
+ if(spell->Id == SPELL_SUPERCHARGE)
+ {
+ UpdatePhase();
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_ENRAGE:
+ DoCast(SPELL_BERSERK);
+ break;
+ case EVENT_CHAIN_LIGHTNING:
+ {
+ Unit* Target = SelectUnit(SELECT_TARGET_RANDOM,0);
+ DoCast(Target, RAID_MODE(SPELL_CHAIN_LIGHTNING_N , SPELL_CHAIN_LIGHTNING_H));
+ events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 9000+ (rand()%8)*1000);
+ }
+ break;
+ case EVENT_OVERLOAD:
+ DoCast(RAID_MODE(SPELL_OVERLOAD , SPELL_OVERLOAD_H));
+ events.ScheduleEvent(EVENT_OVERLOAD, 60000+ (rand()%65)*1000);
+ break;
+ case EVENT_LIGHTNING_WHIRL:
+ DoCast(RAID_MODE(SPELL_LIGHTNING_WHIRL , SPELL_LIGHTNING_WHIRL_H));
+ events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, 20000+ (rand()%20)*1000);
+ break;
+ case EVENT_LIGHTNING_TENDRILS:
+ DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS, SPELL_LIGHTNING_TENDRILS_H));
+ events.DelayEvents(15000, 5000);
+ DoResetThreat();
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_steelbreaker(Creature* pCreature)
+{
+ return new boss_steelbreakerAI (pCreature);
+}
+
+CreatureAI* GetAI_boss_runemaster_molgeim(Creature* pCreature)
+{
+ return new boss_runemaster_molgeimAI (pCreature);
+}
+
+CreatureAI* GetAI_boss_stormcaller_brundir(Creature* pCreature)
+{
+ return new boss_stormcaller_brundirAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_lightning_elemental(Creature* pCreature)
+{
+ return new mob_lightning_elementalAI (pCreature);
+}
+
+CreatureAI* GetAI_mob_rune_of_summoning(Creature* pCreature)
+{
+ return new mob_rune_of_summoningAI (pCreature);
+}
+
+void AddSC_boss_assembly_of_iron()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_steelbreaker";
+ newscript->GetAI = &GetAI_boss_steelbreaker;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_runemaster_molgeim";
+ newscript->GetAI = &GetAI_boss_runemaster_molgeim;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_stormcaller_brundir";
+ newscript->GetAI = &GetAI_boss_stormcaller_brundir;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_lightning_elemental";
+ newscript->GetAI = &GetAI_mob_lightning_elemental;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_rune_of_summoning";
+ newscript->GetAI = &GetAI_mob_rune_of_summoning;
+ newscript->RegisterSelf();
+
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp b/src/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp
new file mode 100644
index 00000000000..c3ae8c01f59
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+//boss_auriaya
+#define SPELL_TERRIFYING_SCREECH 64386
+#define SPELL_SETINEL_BLAST 64679
+#define SPELL_SONIC_SCREECH 64422
+#define SPELL_SUMMON_SWARMING_GUARDIAN 64397
+//wrong text ids. correct are beetwen -1000000 AND -1999999
+//beetwen -2000000 and -2999999 are custom texts so wtf?
+#define SAY_AGGRO -2615016
+#define SAY_SLAY_1 -2615017
+
+struct TRINITY_DLL_DECL boss_auriaya_AI : public BossAI
+{
+ boss_auriaya_AI(Creature *pCreature) : BossAI(pCreature, TYPE_AURIAYA)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 TERRIFYING_SCREECH_Timer;
+ uint32 SONIC_SCREECH_Timer;
+
+ void Reset()
+ {
+ TERRIFYING_SCREECH_Timer = 180000;
+ SONIC_SCREECH_Timer = 30000;
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO,m_creature);
+ }
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_SLAY_1, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_SLAY_1, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_AURIAYA, DONE);
+ }
+
+ void MoveInLineOfSight(Unit* who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (TERRIFYING_SCREECH_Timer <= diff)
+ {
+ DoCast(SPELL_TERRIFYING_SCREECH);
+ DoScriptText(SAY_SLAY_1, m_creature);
+ TERRIFYING_SCREECH_Timer = 180000;
+ } else TERRIFYING_SCREECH_Timer -= diff;
+
+ if (SONIC_SCREECH_Timer <= diff)
+ {
+ DoCastVictim(SPELL_SONIC_SCREECH);
+ SONIC_SCREECH_Timer = 30000;
+ } else SONIC_SCREECH_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_auriaya(Creature* pCreature)
+{
+ return new boss_auriaya_AI (pCreature);
+}
+void AddSC_boss_auriaya()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_auriaya";
+ newscript->GetAI = &GetAI_boss_auriaya;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp b/src/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp
new file mode 100644
index 00000000000..b05e59cad20
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+#include "Vehicle.h"
+
+#define SPELL_PURSUED 62374
+#define SPELL_GATHERING_SPEED 62375
+#define SPELL_BATTERING_RAM 62376
+#define SPELL_FLAME_VENTS 62396
+#define SPELL_MISSILE_BARRAGE 62400
+#define SPELL_SYSTEMS_SHUTDOWN 62475
+
+#define SPELL_FLAME_CANNON 62395
+//#define SPELL_FLAME_CANNON 64692 trigger the same spell
+
+#define SPELL_OVERLOAD_CIRCUIT 62399
+
+#define SPELL_SEARING_FLAME 62402
+
+#define SPELL_BLAZE 62292
+
+#define SPELL_SMOKE_TRAIL 63575
+
+#define SPELL_MIMIRON_INFERNO 62910
+
+#define SPELL_HODIR_FURY 62297
+
+#define SPELL_ELECTROSHOCK 62522
+
+enum Mobs
+{
+ MOB_MECHANOLIFT = 33214,
+ MOB_LIQUID = 33189,
+ MOB_CONTAINER = 33218,
+};
+
+enum Events
+{
+ EVENT_PURSUE = 1,
+ EVENT_MISSILE,
+ EVENT_VENT,
+ EVENT_SPEED,
+ EVENT_SUMMON,
+ EVENT_MIMIRON_INFERNO, // Not Blizzlike
+ EVENT_HODIR_FURY, // Not Blizzlike
+};
+
+enum Seats
+{
+ SEAT_PLAYER = 0,
+ SEAT_TURRET = 1,
+ SEAT_DEVICE = 2,
+};
+
+struct TRINITY_DLL_DECL boss_flame_leviathanAI : public BossAI
+{
+ boss_flame_leviathanAI(Creature *pCreature) : BossAI(pCreature, TYPE_LEVIATHAN), vehicle(me->GetVehicleKit())
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ assert(vehicle);
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ Vehicle *vehicle;
+
+ void Reset()
+ {
+ _Reset();
+ me->SetReactState(REACT_AGGRESSIVE);
+ }
+
+ void EnterCombat(Unit *who)
+ {
+ _EnterCombat();
+ me->SetReactState(REACT_DEFENSIVE);
+ events.ScheduleEvent(EVENT_PURSUE, 0);
+ events.ScheduleEvent(EVENT_MISSILE, 1500);
+ events.ScheduleEvent(EVENT_VENT, 20000);
+ events.ScheduleEvent(EVENT_SPEED, 15000);
+ events.ScheduleEvent(EVENT_SUMMON, 0);
+ //events.ScheduleEvent(EVENT_MIMIRON_INFERNO, 60000 + (rand()%60000)); // Not Blizzlike
+ //events.ScheduleEvent(EVENT_HODIR_FURY, 60000 + (rand()%60000)); // Not Blizzlike
+ if (Creature *turret = CAST_CRE(vehicle->GetPassenger(7)))
+ turret->AI()->DoZoneInCombat();
+ }
+
+ // TODO: effect 0 and effect 1 may be on different target
+ void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
+ {
+ if (spell->Id == SPELL_PURSUED)
+ AttackStart(pTarget);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_LEVIATHAN, DONE);
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if(spell->Id == 62472)
+ vehicle->InstallAllAccessories();
+ else if(spell->Id == SPELL_ELECTROSHOCK)
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!me->isInCombat())
+ return;
+
+ if (me->getThreatManager().isThreatListEmpty())
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ events.Update(diff);
+
+ if (me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ uint32 eventId = events.GetEvent();
+ if (!me->getVictim())
+ eventId = EVENT_PURSUE;
+
+ switch(eventId)
+ {
+ case 0: break; // this is a must
+ case EVENT_PURSUE:
+ DoCastAOE(SPELL_PURSUED, true);
+ //events.RepeatEvent(35000); // this should not be used because eventId may be overriden
+ events.RescheduleEvent(EVENT_PURSUE, 35000);
+ if(!me->getVictim()) // all siege engines and demolishers are dead
+ UpdateVictim(); // begin to kill other things
+ return;
+ case EVENT_MISSILE:
+ //TODO: without target no visual effect
+ //DoCastAOE(SPELL_MISSILE_BARRAGE);
+ DoCast(me->getVictim(), SPELL_MISSILE_BARRAGE);
+ events.RepeatEvent(1500);
+ return;
+ case EVENT_VENT:
+ DoCastAOE(SPELL_FLAME_VENTS);
+ events.RepeatEvent(20000);
+ return;
+ case EVENT_SPEED:
+ DoCastAOE(SPELL_GATHERING_SPEED);
+ events.RepeatEvent(15000);
+ return;
+ case EVENT_SUMMON:
+ if(summons.size() < 15) // 4seat+1turret+10lift
+ if(Creature *lift = DoSummonFlyer(MOB_MECHANOLIFT, me, rand()%20 + 20, 50, 0))
+ lift->GetMotionMaster()->MoveRandom(100);
+ events.RepeatEvent(2000);
+ return;
+ case EVENT_MIMIRON_INFERNO: // Not Blizzlike
+ DoCast(me->getVictim(), SPELL_MIMIRON_INFERNO);
+ events.RepeatEvent(60000 + (rand()%60000));
+ return;
+ case EVENT_HODIR_FURY: // Not Blizzlike
+ DoCast(me->getVictim(), SPELL_HODIR_FURY);
+ events.RepeatEvent(60000 + (rand()%60000));
+ default:
+ events.PopEvent();
+ break;
+ }
+
+ DoSpellAttackIfReady(SPELL_BATTERING_RAM);
+ }
+};
+
+//#define BOSS_DEBUG
+
+struct TRINITY_DLL_DECL boss_flame_leviathan_seatAI : public PassiveAI
+{
+ boss_flame_leviathan_seatAI(Creature *c) : PassiveAI(c), vehicle(c->GetVehicleKit())
+ {
+ assert(vehicle);
+#ifdef BOSS_DEBUG
+ me->SetReactState(REACT_AGGRESSIVE);
+#endif
+ }
+
+ Vehicle *vehicle;
+
+#ifdef BOSS_DEBUG
+ void MoveInLineOfSight(Unit *who)
+ {
+ if(who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->isGameMaster()
+ && !who->GetVehicle() && vehicle->GetPassenger(SEAT_TURRET))
+ who->EnterVehicle(vehicle, SEAT_PLAYER);
+ }
+#endif
+
+ void PassengerBoarded(Unit *who, int8 seatId, bool apply)
+ {
+ if(!me->GetVehicle())
+ return;
+
+ if(seatId == SEAT_PLAYER)
+ {
+ if(!apply)
+ return;
+
+ if(Creature *turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET)))
+ {
+ turret->setFaction(me->GetVehicleBase()->getFaction());
+ turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable
+ turret->AI()->AttackStart(who);
+ }
+ if(Unit *device = vehicle->GetPassenger(SEAT_DEVICE))
+ {
+ device->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ device->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+ }
+ else if(seatId == SEAT_TURRET)
+ {
+ if(apply)
+ return;
+
+ if(Unit *device = vehicle->GetPassenger(SEAT_DEVICE))
+ {
+ device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable
+ }
+ }
+ }
+};
+
+struct TRINITY_DLL_DECL boss_flame_leviathan_defense_turretAI : public TurretAI
+{
+ boss_flame_leviathan_defense_turretAI(Creature *c) : TurretAI(c) {}
+
+ void DamageTaken(Unit *who, uint32 &damage)
+ {
+ if(!CanAIAttack(who))
+ damage = 0;
+ }
+
+ bool CanAIAttack(const Unit *who) const
+ {
+ if (who->GetTypeId() != TYPEID_PLAYER || !who->GetVehicle() || who->GetVehicleBase()->GetEntry() != 33114)
+ return false;
+ return true;
+ }
+};
+
+struct TRINITY_DLL_DECL boss_flame_leviathan_overload_deviceAI : public PassiveAI
+{
+ boss_flame_leviathan_overload_deviceAI(Creature *c) : PassiveAI(c) {}
+
+ void DoAction(const int32 param)
+ {
+ if(param == EVENT_SPELLCLICK)
+ {
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ if(me->GetVehicle())
+ {
+ if(Unit *player = me->GetVehicle()->GetPassenger(SEAT_PLAYER))
+ {
+ player->ExitVehicle();
+ me->GetVehicleBase()->CastSpell(player, SPELL_SMOKE_TRAIL, true);
+ if(Unit *leviathan = me->GetVehicleBase()->GetVehicleBase())
+ player->GetMotionMaster()->MoveKnockbackFrom(leviathan->GetPositionX(), leviathan->GetPositionY(), 30, 30);
+ }
+ }
+ }
+ }
+};
+
+struct TRINITY_DLL_DECL boss_flame_leviathan_safety_containerAI : public PassiveAI
+{
+ boss_flame_leviathan_safety_containerAI(Creature *c) : PassiveAI(c) {}
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if(id == me->GetEntry())
+ {
+ if(Creature *liquid = DoSummon(MOB_LIQUID, me, 0))
+ liquid->CastSpell(liquid, 62494, true);
+ me->DisappearAndDie(); // this will relocate creature to sky
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(!me->GetVehicle() && me->isSummon() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE)
+ me->GetMotionMaster()->MoveFall(409.8f, me->GetEntry());
+ }
+};
+
+struct TRINITY_DLL_DECL spell_pool_of_tarAI : public TriggerAI
+{
+ spell_pool_of_tarAI(Creature *c) : TriggerAI(c)
+ {
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void DamageTaken(Unit *who, uint32 &damage)
+ {
+ damage = 0;
+ }
+
+ void SpellHit(Unit* caster, const SpellEntry *spell)
+ {
+ if(spell->SchoolMask & SPELL_SCHOOL_MASK_FIRE && !me->HasAura(SPELL_BLAZE))
+ me->CastSpell(me, SPELL_BLAZE, true);
+ }
+};
+
+CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature)
+{
+ return new boss_flame_leviathanAI (pCreature);
+}
+
+CreatureAI* GetAI_boss_flame_leviathan_seat(Creature* pCreature)
+{
+ return new boss_flame_leviathan_seatAI (pCreature);
+}
+
+CreatureAI* GetAI_boss_flame_leviathan_defense_turret(Creature* pCreature)
+{
+ return new boss_flame_leviathan_defense_turretAI (pCreature);
+}
+
+CreatureAI* GetAI_boss_flame_leviathan_overload_device(Creature* pCreature)
+{
+ return new boss_flame_leviathan_overload_deviceAI (pCreature);
+}
+
+CreatureAI* GetAI_boss_flame_leviathan_safety_containerAI(Creature* pCreature)
+{
+ return new boss_flame_leviathan_safety_containerAI(pCreature);
+}
+
+CreatureAI* GetAI_spell_pool_of_tar(Creature* pCreature)
+{
+ return new spell_pool_of_tarAI (pCreature);
+}
+
+void AddSC_boss_flame_leviathan()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_flame_leviathan";
+ newscript->GetAI = &GetAI_boss_flame_leviathan;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_flame_leviathan_seat";
+ newscript->GetAI = &GetAI_boss_flame_leviathan_seat;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_flame_leviathan_defense_turret";
+ newscript->GetAI = &GetAI_boss_flame_leviathan_defense_turret;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_flame_leviathan_overload_device";
+ newscript->GetAI = &GetAI_boss_flame_leviathan_overload_device;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_flame_leviathan_safety_container";
+ newscript->GetAI = &GetAI_boss_flame_leviathan_safety_containerAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "spell_pool_of_tar";
+ newscript->GetAI = &GetAI_spell_pool_of_tar;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_freya.cpp b/src/scripts/northrend/ulduar/ulduar/boss_freya.cpp
new file mode 100644
index 00000000000..22f53c3a2e8
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_freya.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+/*
+#define SAY_AGGRO -1
+#define SAY_SLAY -1
+*/
+
+struct TRINITY_DLL_DECL boss_freyaAI : public BossAI
+{
+ boss_freyaAI(Creature* pCreature) : BossAI(pCreature, TYPE_FREYA)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_FREYA, DONE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+// DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_FREYA, IN_PROGRESS);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+//SPELLS TODO:
+
+//
+ DoMeleeAttackIfReady();
+
+ EnterEvadeIfOutOfCombatArea(diff);
+ }
+};
+
+CreatureAI* GetAI_boss_freya(Creature* pCreature)
+{
+ return new boss_freyaAI(pCreature);
+}
+
+void AddSC_boss_freya()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_freya";
+ newscript->GetAI = &GetAI_boss_freya;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp b/src/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp
new file mode 100644
index 00000000000..a9f1be65f2d
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_hodir.cpp b/src/scripts/northrend/ulduar/ulduar/boss_hodir.cpp
new file mode 100644
index 00000000000..8603d287b99
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_hodir.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+/*
+#define SAY_AGGRO -1
+#define SAY_SLAY -1
+*/
+
+struct TRINITY_DLL_DECL boss_hodirAI : public BossAI
+{
+ boss_hodirAI(Creature *pCreature) : BossAI(pCreature, TYPE_HODIR)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_HODIR, DONE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+// DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_HODIR, IN_PROGRESS);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+//SPELLS TODO:
+
+//
+ DoMeleeAttackIfReady();
+
+ EnterEvadeIfOutOfCombatArea(diff);
+
+ }
+
+};
+
+CreatureAI* GetAI_boss_hodir(Creature* pCreature)
+{
+ return new boss_hodirAI(pCreature);
+}
+
+void AddSC_boss_hodir()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_hodir";
+ newscript->GetAI = &GetAI_boss_hodir;
+ newscript->RegisterSelf();
+
+}
+
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_ignis.cpp b/src/scripts/northrend/ulduar/ulduar/boss_ignis.cpp
new file mode 100644
index 00000000000..3c924b07289
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_ignis.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+#define SPELL_FLAME_JETS 62680
+#define SPELL_SCORCH 62546
+#define SPELL_SLAG_POT 62717
+
+//wrong ids. not in db
+#define SAY_AGGRO -10000002
+#define SAY_SLAY -1000003
+
+struct TRINITY_DLL_DECL boss_ignis_AI : public BossAI
+{
+ boss_ignis_AI(Creature *pCreature) : BossAI(pCreature, TYPE_IGNIS) {}
+
+ uint32 FLAME_JETS_Timer;
+ uint32 SCORCH_Timer;
+ uint32 SLAG_POT_Timer;
+
+ void Reset()
+ {
+ FLAME_JETS_Timer = 32000;
+ SCORCH_Timer = 100;
+ SLAG_POT_Timer = 100;
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO,m_creature);
+ }
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void MoveInLineOfSight(Unit* who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if(m_creature->GetPositionY() < 150 || m_creature->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles.
+ {
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(false);
+ m_creature->GetMotionMaster()->MoveTargetedHome();
+ }
+
+ if (FLAME_JETS_Timer <= diff)
+ {
+ DoCast(SPELL_FLAME_JETS);
+ DoScriptText(SAY_SLAY, m_creature);
+ FLAME_JETS_Timer = 25000;
+ } else FLAME_JETS_Timer -= diff;
+
+ if (SCORCH_Timer <= diff)
+ {
+ DoCast(SPELL_SCORCH);
+ SCORCH_Timer = 20000;
+ } else SCORCH_Timer -= diff;
+
+ if (SLAG_POT_Timer <= diff)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(pTarget, SPELL_SLAG_POT);
+ DoScriptText(SAY_SLAY, m_creature);
+ SLAG_POT_Timer = 30000;
+ } else SLAG_POT_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_ignis(Creature* pCreature)
+{
+ return new boss_ignis_AI (pCreature);
+}
+void AddSC_boss_ignis()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_ignis";
+ newscript->GetAI = &GetAI_boss_ignis;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp b/src/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp
new file mode 100644
index 00000000000..4701a63fca1
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+#include "Vehicle.h"
+
+#define SPELL_ARM_DEAD_DAMAGE RAID_MODE(63629,63979)
+#define SPELL_TWO_ARM_SMASH RAID_MODE(63356,64003)
+#define SPELL_ONE_ARM_SMASH RAID_MODE(63573,64006)
+#define SPELL_STONE_SHOUT RAID_MODE(63716,64005)
+#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980)
+
+#define SPELL_STONE_GRIP RAID_MODE(62166,63981)
+#define SPELL_ARM_SWEEP RAID_MODE(63766,63983)
+
+enum Events
+{
+ EVENT_NONE = 0,
+ EVENT_SMASH,
+ EVENT_GRIP,
+ EVENT_SWEEP,
+};
+
+struct TRINITY_DLL_DECL boss_kologarnAI : public BossAI
+{
+ boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(me->GetVehicleKit()),
+ left(false), right(false)
+ {
+ m_pInstance = me->GetInstanceData();
+ assert(vehicle);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // i think this is a hack, but there is no other way to disable his rotation
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ Vehicle *vehicle;
+ bool left, right;
+
+ void AttackStart(Unit *who)
+ {
+ me->Attack(who, true);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_KOLOGARN, DONE);
+ }
+
+ void PassengerBoarded(Unit *who, int8 seatId, bool apply)
+ {
+ if(who->GetTypeId() == TYPEID_UNIT)
+ {
+ if(who->GetEntry() == 32933)
+ left = apply;
+ else if(who->GetEntry() == 32934)
+ right = apply;
+ who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
+ CAST_CRE(who)->SetReactState(REACT_PASSIVE);
+ }
+ }
+
+ void EnterCombat(Unit *who)
+ {
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_SMASH, 5000);
+ events.ScheduleEvent(EVENT_SWEEP, 10000);
+ events.ScheduleEvent(EVENT_GRIP, 15000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if(me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ // TODO: because we are using hack, he is stunned and cannot cast, so we use triggered for every spell
+ switch(events.GetEvent())
+ {
+ case EVENT_NONE: break;
+ case EVENT_SMASH:
+ if(left && right)
+ DoCastVictim(SPELL_TWO_ARM_SMASH, true);
+ else if(left || right)
+ DoCastVictim(SPELL_ONE_ARM_SMASH, true);
+ events.RepeatEvent(15000);
+ break;
+ case EVENT_SWEEP:
+ if(left)
+ DoCastAOE(SPELL_ARM_SWEEP, true);
+ events.RepeatEvent(15000);
+ break;
+ case EVENT_GRIP:
+ if(right)
+ DoCastAOE(SPELL_STONE_GRIP, true);
+ events.RepeatEvent(15000);
+ break;
+ default:
+ events.PopEvent();
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_kologarn(Creature* pCreature)
+{
+ return new boss_kologarnAI (pCreature);
+}
+
+void AddSC_boss_kologarn()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_kologarn";
+ newscript->GetAI = &GetAI_boss_kologarn;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp b/src/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp
new file mode 100644
index 00000000000..a9f1be65f2d
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp b/src/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp
new file mode 100644
index 00000000000..cf114e00897
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2008 - 2009 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
+ */
+
+/* ScriptData
+SDName: razorscale
+SDAuthor: MaXiMiUS
+SD%Complete: 65
+EndScriptData */
+
+#include "ScriptedPch.h"
+#include "ulduar.h"
+
+//not in db
+#define SAY_AGGRO -2000000
+#define SAY_KILL -2000001
+#define SAY_PHASE_2_TRANS -2000002
+#define SAY_PHASE_3_TRANS -2000003
+#define EMOTE_BREATH -2000004
+
+enum Spells
+{
+ SPELL_FLAMEBUFFET = 64016,
+ SPELL_FIREBALL = 62796,
+
+ SPELL_WINGBUFFET = 62666,
+ SPELL_FLAMEBREATH = 63317,
+ SPELL_FUSEARMOR = 64771,
+ SPELL_DEVOURINGFLAME = 63014
+};
+
+enum Mobs
+{
+ NPC_DARK_RUNE_SENTINEL = 33846
+};
+
+struct TRINITY_DLL_DECL boss_razorscaleAI : public BossAI
+{
+ boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE) {}
+
+ uint8 Phase;
+
+ uint32 FlameBreathTimer;
+ uint32 FuseArmorTimer;
+ uint32 DevouringFlameTimer;
+ uint32 FlameBuffetTimer;
+ uint32 SummonAddsTimer;
+ uint32 WingBuffetTimer;
+ uint32 FireballTimer;
+ //uint32 StunTimer;
+ //uint32 CastSpellsTimer;
+
+ bool InitialSpawn;
+ bool IsFlying;
+
+ void Reset()
+ {
+ Phase = 1;
+
+ FlyPhase(Phase, 0);
+
+ FlameBreathTimer = 20000;
+ DevouringFlameTimer = 2000;
+ FuseArmorTimer = 15000;
+ FlameBuffetTimer = 3000;
+ SummonAddsTimer = 45000;
+ WingBuffetTimer = 17000;
+ FireballTimer = 18000;
+ //StunTimer = 30000;
+ //CastSpellsTimer = 0;
+
+ InitialSpawn = true;
+ IsFlying = true;
+
+ m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
+ m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ DoZoneInCombat();
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if(m_creature->GetPositionY() > -60 || m_creature->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles.
+ {
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(false);
+ m_creature->GetMotionMaster()->MoveTargetedHome();
+ }
+
+ // Victim is not controlled by a player (should never happen)
+ if (m_creature->getVictim() && !m_creature->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
+ m_creature->Kill(m_creature->getVictim());
+
+ if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 99 && Phase == 1) // TODO: Only land (exit Phase 1) if brought down with harpoon guns! This is important!
+ {
+ Phase = 2;
+ DoScriptText(SAY_PHASE_2_TRANS, m_creature); // Audio: "Move quickly! She won't remain grounded for long!"
+ }
+
+ if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 33 && Phase == 2) // Health under 33%, Razorscale can't fly anymore.
+ {
+ Phase = 3;
+ DoScriptText(SAY_PHASE_3_TRANS, m_creature); // "Razorscale lands permanently!"
+ // TODO: Cast Devouring Flame on all harpoon guns simultaneously, briefly after Phase 3 starts (lasts until the harpoon guns are destroyed)
+ }
+
+ /*
+ if (Phase == 2 && CastSpellsTimer > 0) // 5 seconds of spell casting, after stun breaks, during Phase 2
+ {
+ if (CastSpellsTimer <= diff) // 5 seconds are up
+ Phase = 1; // Return to phase 1
+ else
+ CastSpellsTimer -= diff;
+ }*/
+
+ FlyPhase(Phase, diff);
+
+ if (Phase >= 2) // Ground Phase (Phase 3 = permanent ground phase)
+ {
+ if (FuseArmorTimer <= diff)
+ {
+ DoCastVictim(SPELL_FUSEARMOR);
+ FuseArmorTimer = 10000;
+ } else FuseArmorTimer -= diff;
+
+ if (WingBuffetTimer <= diff)
+ {
+ DoCast(SPELL_WINGBUFFET);
+ WingBuffetTimer = urand(7000,14000);
+ } else WingBuffetTimer -= diff;
+
+ if (FireballTimer <= diff)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
+ {
+ m_creature->SetInFront(pTarget);
+ DoCast(pTarget, SPELL_FIREBALL);
+ }
+
+ FireballTimer = 18000;
+ } else FireballTimer -= diff;
+
+ if (FlameBreathTimer <= diff)
+ {
+ DoScriptText(EMOTE_BREATH, m_creature); // TODO: "Razorscale takes a deep breath..."
+ DoCastVictim(SPELL_FLAMEBREATH);
+ FlameBreathTimer = 15000;
+ WingBuffetTimer = 0;
+ } else FlameBreathTimer -= diff;
+
+ if (Phase == 3)
+ {
+ if (FlameBuffetTimer <= diff)
+ {
+ DoScriptText(EMOTE_BREATH, m_creature);
+ std::list<Unit*> pTargets;
+ SelectTargetList(pTargets, RAID_MODE(3,9), SELECT_TARGET_RANDOM, 100, true);
+ uint8 i = 0;
+ for (std::list<Unit*>::iterator itr = pTargets.begin(); itr != pTargets.end();)
+ {
+ if (m_creature->HasInArc(M_PI, *itr))
+ {
+ DoCast(*itr, SPELL_FLAMEBUFFET, true);
+ ++i;
+ }
+ if (++itr == pTargets.end() || i == RAID_MODE(3,9))
+ {
+ AttackStart(*--itr); // seems to attack targets randomly during perma-ground phase..
+ break;
+ }
+ }
+ FlameBuffetTimer = 25000;
+ } else FlameBuffetTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ else if (Phase == 1) //Flying Phase
+ {
+ if (InitialSpawn)
+ SummonAdds();
+
+ InitialSpawn = false;
+
+ if (FireballTimer <= diff)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
+ {
+ m_creature->SetInFront(pTarget);
+ DoCast(pTarget, SPELL_FIREBALL);
+ }
+
+ FireballTimer = 18000;
+ } else FireballTimer -= diff;
+
+ if (DevouringFlameTimer <= diff)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
+ {
+ m_creature->SetInFront(pTarget);
+ DoCast(pTarget, SPELL_DEVOURINGFLAME);
+ }
+
+ DevouringFlameTimer = 10000;
+ } else DevouringFlameTimer -= diff;
+
+ if (SummonAddsTimer <= diff)
+ SummonAdds();
+ else SummonAddsTimer -= diff;
+ }
+ }
+
+ void SummonAdds()
+ {
+ // TODO: Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher
+ // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time.
+ uint8 random = urand(1,4);
+ for (uint8 i = 0; i < random; ++i)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
+ {
+ float x = std::max(500.0f, std::min(650.0f, pTarget->GetPositionX() + irand(-20,20))); // Safe range is between 500 and 650
+ float y = std::max(-235.0f, std::min(-145.0f, pTarget->GetPositionY() + irand(-20,20))); // Safe range is between -235 and -145
+ float z = m_creature->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); // Ground level
+ // TODO: Spawn drillers, then spawn adds 5 seconds later
+ if (Creature *pAdd = m_creature->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
+ pAdd->AI()->AttackStart(pTarget);
+ }
+ }
+ SummonAddsTimer = 45000;
+ }
+
+ void FlyPhase(uint8 Phase, const uint32 diff)
+ {
+ const float x = 587.54;
+ const float y = -174.92;
+ const float GroundLevel = m_creature->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT);
+ const float FlightHeight = GroundLevel + 4.0f; // TODO: Fly out of range of attacks (442 is sufficient height for this), minus ~(10*number of harpoon gun chains attached to Razorscale)
+
+ if (Phase == 1) // Always flying during Phase 1
+ IsFlying = true;
+
+ m_creature->SetFlying(IsFlying);
+ m_creature->SendMovementFlagUpdate();
+ m_creature->SetSpeed(MOVE_WALK, IsFlying ? 7.0f : 2.5f, IsFlying);
+
+ if (Phase == 1) // Flying Phase
+ {
+ if (m_creature->GetPositionZ() > FlightHeight) // Correct height, stop moving
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ else // Incorrect height
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ m_creature->GetMotionMaster()->MovePoint(0, x, y, FlightHeight + 0.5f); // Fly to slightly above (x, y, FlightHeight)
+ }
+ }
+ else // Ground Phases
+ {
+ const float CurrentGroundLevel = m_creature->GetBaseMap()->GetHeight(m_creature->GetPositionX(), m_creature->GetPositionY(), MAX_HEIGHT);
+ //if (StunTimer == 30000) // Only fly around if not stunned.
+ //{
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ if (IsFlying && m_creature->GetPositionZ() > CurrentGroundLevel) // Fly towards the ground
+ m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), CurrentGroundLevel);
+ // TODO: Swoop up just before landing
+ else
+ IsFlying = false; // Landed, no longer flying
+ //}
+
+ //if (!IsFlying &&Phase == 2 && CastSpellsTimer == 0 && StunTimer >= diff) // No longer flying, non-permanent ground phase, and not casting spells
+ //{
+ // TODO: Add stun here. 30 second stun after Razorscale is grounded by harpoon guns
+ //StunTimer -= diff;
+ //}
+ //else if (StunTimer != 30000 && (StunTimer < 0 || Phase == 3)) // Stun is active, and needs to end. Note: Stun breaks instantly if Phase 3 starts
+ //{
+ // TODO: Remove stun here.
+ //DoCast(SPELL_WINGBUFFET); // "Used in the beginning of the phase."
+ //WingBuffetTimer = urand(7000,14000);
+ //StunTimer = 30000; // Reinitialize the stun timer
+ //if (Phase == 2) // Non-permanent ground phase
+ // CastSpellsTimer = 5000; // Five seconds of casting before returning to Phase 1
+ //}
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_razorscale(Creature* pCreature)
+{
+ return new boss_razorscaleAI (pCreature);
+}
+
+void AddSC_boss_razorscale()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_razorscale";
+ newscript->GetAI = &GetAI_boss_razorscale;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_thorim.cpp b/src/scripts/northrend/ulduar/ulduar/boss_thorim.cpp
new file mode 100644
index 00000000000..2eececb76a8
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_thorim.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+/*
+#define SAY_AGGRO -1
+#define SAY_SLAY -1
+*/
+
+struct TRINITY_DLL_DECL boss_thorimAI : public BossAI
+{
+ boss_thorimAI(Creature* pCreature) : BossAI(pCreature, TYPE_THORIM)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THORIM, DONE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+// DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THORIM, IN_PROGRESS);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+//SPELLS TODO:
+
+//
+ DoMeleeAttackIfReady();
+
+ EnterEvadeIfOutOfCombatArea(diff);
+
+ }
+
+};
+
+CreatureAI* GetAI_boss_thorim(Creature* pCreature)
+{
+ return new boss_thorimAI(pCreature);
+}
+
+void AddSC_boss_thorim()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_thorim";
+ newscript->GetAI = &GetAI_boss_thorim;
+ newscript->RegisterSelf();
+
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_xt002.cpp b/src/scripts/northrend/ulduar/ulduar/boss_xt002.cpp
new file mode 100644
index 00000000000..66be50292cb
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_xt002.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+#define SPELL_SEARING_LIGHT 63018
+#define SPELL_SONIC_BOOM 38897
+
+#define SAY_AGGRO -1000000
+#define SAY_SLAY -1000001
+
+struct TRINITY_DLL_DECL boss_xt002_AI : public BossAI
+{
+ boss_xt002_AI(Creature *pCreature) : BossAI(pCreature, TYPE_XT002)
+ {
+ m_pInstance = pCreature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 SEARING_LIGHT_Timer;
+ uint32 SONIC_BOOM_Timer;
+
+ void Reset()
+ {
+ SEARING_LIGHT_Timer = 100;
+ SONIC_BOOM_Timer = 20;
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO,m_creature);
+ }
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_XT002, DONE);
+ }
+
+ void MoveInLineOfSight(Unit* who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if(m_creature->GetPositionX() < 700) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles.
+ {
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(false);
+ m_creature->GetMotionMaster()->MoveTargetedHome();
+ }
+
+ if (SEARING_LIGHT_Timer <= diff)
+ {
+ DoCast(m_creature, SPELL_SEARING_LIGHT);
+ DoScriptText(SAY_SLAY, m_creature);
+ SEARING_LIGHT_Timer = 50000;
+ } else SEARING_LIGHT_Timer -= diff;
+
+ if (SONIC_BOOM_Timer <= diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_SONIC_BOOM);
+ SONIC_BOOM_Timer = 20000;
+ } else SONIC_BOOM_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_xt002(Creature* pCreature)
+{
+ return new boss_xt002_AI (pCreature);
+}
+void AddSC_boss_xt002()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_xt002";
+ newscript->GetAI = &GetAI_boss_xt002;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp b/src/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp
new file mode 100644
index 00000000000..a9f1be65f2d
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
diff --git a/src/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp b/src/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp
new file mode 100644
index 00000000000..2c961073d89
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2008 - 2009 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 "ScriptedPch.h"
+#include "ulduar.h"
+
+enum eGameObjects
+{
+ GO_Kologarn_CHEST_HERO = 195047,
+ GO_Kologarn_CHEST = 195046,
+ GO_Thorim_CHEST_HERO = 194315,
+ GO_Thorim_CHEST = 194314,
+ GO_Hodir_CHEST_HERO = 194308,
+ GO_Hodir_CHEST = 194307,
+ GO_Freya_CHEST_HERO = 194325,
+ GO_Freya_CHEST = 194324,
+};
+
+struct TRINITY_DLL_DECL instance_ulduar : public ScriptedInstance
+{
+ instance_ulduar(Map* pMap) : ScriptedInstance(pMap), KologarnChest(NULL), ThorimChest(NULL), HodirChest(NULL), FreyaChest(NULL) { Initialize(); };
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string m_strInstData;
+
+ uint64 m_uiLeviathanGUID;
+ uint64 m_uiIgnisGUID;
+ uint64 m_uiRazorscaleGUID;
+ uint64 m_uiXT002GUID;
+ uint64 m_auiAssemblyGUIDs[3];
+ uint64 m_uiKologarnGUID;
+ uint64 m_uiAuriayaGUID;
+ uint64 m_uiMimironGUID;
+ uint64 m_uiHodirGUID;
+ uint64 m_uiThorimGUID;
+ uint64 m_uiFreyaGUID;
+ uint64 m_uiVezaxGUID;
+ uint64 m_uiYoggSaronGUID;
+ uint64 m_uiAlgalonGUID;
+
+ GameObject* KologarnChest, *ThorimChest, *HodirChest, *FreyaChest;
+
+ void Initialize()
+ {
+ m_uiLeviathanGUID = 0;
+ m_uiIgnisGUID = 0;
+ m_uiRazorscaleGUID = 0;
+ m_uiXT002GUID = 0;
+ m_uiKologarnGUID = 0;
+ m_uiAuriayaGUID = 0;
+ m_uiMimironGUID = 0;
+ m_uiHodirGUID = 0;
+ m_uiThorimGUID = 0;
+ m_uiFreyaGUID = 0;
+ m_uiVezaxGUID = 0;
+ m_uiYoggSaronGUID = 0;
+ m_uiAlgalonGUID = 0;
+ KologarnChest = 0;
+ ThorimChest = 0;
+ HodirChest = 0;
+ FreyaChest = 0;
+
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ memset(&m_auiAssemblyGUIDs, 0, sizeof(m_auiAssemblyGUIDs));
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ return true;
+ }
+
+ return false;
+ }
+
+ void OnCreatureCreate(Creature* pCreature, bool add)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_LEVIATHAN:
+ m_uiLeviathanGUID = pCreature->GetGUID();
+ break;
+ case NPC_IGNIS:
+ m_uiIgnisGUID = pCreature->GetGUID();
+ break;
+ case NPC_RAZORSCALE:
+ m_uiRazorscaleGUID = pCreature->GetGUID();
+ break;
+ case NPC_XT002:
+ m_uiXT002GUID = pCreature->GetGUID();
+ break;
+
+ // Assembly of Iron
+ case NPC_STEELBREAKER:
+ m_auiAssemblyGUIDs[0] = pCreature->GetGUID();
+ break;
+ case NPC_MOLGEIM:
+ m_auiAssemblyGUIDs[1] = pCreature->GetGUID();
+ break;
+ case NPC_BRUNDIR:
+ m_auiAssemblyGUIDs[2] = pCreature->GetGUID();
+ break;
+
+ case NPC_KOLOGARN:
+ m_uiKologarnGUID = pCreature->GetGUID();
+ break;
+ case NPC_AURIAYA:
+ m_uiAuriayaGUID = pCreature->GetGUID();
+ break;
+ case NPC_MIMIRON:
+ m_uiMimironGUID = pCreature->GetGUID();
+ break;
+ case NPC_HODIR:
+ m_uiHodirGUID = pCreature->GetGUID();
+ break;
+ case NPC_THORIM:
+ m_uiThorimGUID = pCreature->GetGUID();
+ break;
+ case NPC_FREYA:
+ m_uiFreyaGUID = pCreature->GetGUID();
+ break;
+ case NPC_VEZAX:
+ m_uiVezaxGUID = pCreature->GetGUID();
+ break;
+ case NPC_YOGGSARON:
+ m_uiYoggSaronGUID = pCreature->GetGUID();
+ break;
+ case NPC_ALGALON:
+ m_uiAlgalonGUID = pCreature->GetGUID();
+ break;
+ }
+
+ }
+
+ void OnGameObjectCreate(GameObject* pGo, bool add)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_Kologarn_CHEST_HERO: KologarnChest = add ? pGo : NULL; break;
+ case GO_Kologarn_CHEST: KologarnChest = add ? pGo : NULL; break;
+ case GO_Thorim_CHEST_HERO: ThorimChest = add ? pGo : NULL; break;
+ case GO_Thorim_CHEST: ThorimChest = add ? pGo : NULL; break;
+ case GO_Hodir_CHEST_HERO: HodirChest = add ? pGo : NULL; break;
+ case GO_Hodir_CHEST: HodirChest = add ? pGo : NULL; break;
+ case GO_Freya_CHEST_HERO: FreyaChest = add ? pGo : NULL; break;
+ case GO_Freya_CHEST: FreyaChest = add ? pGo : NULL; break;
+ }
+ }
+
+ void SetData(uint32 type, uint32 data)
+ {
+ switch(type)
+ {
+ case TYPE_LEVIATHAN:
+ case TYPE_IGNIS:
+ case TYPE_RAZORSCALE:
+ case TYPE_XT002:
+ case TYPE_ASSEMBLY:
+ case TYPE_KOLOGARN:
+ m_auiEncounter[TYPE_KOLOGARN] = data;
+ if (data == DONE && KologarnChest)
+ KologarnChest->SetRespawnTime(KologarnChest->GetRespawnDelay());
+ case TYPE_AURIAYA:
+ case TYPE_MIMIRON:
+ case TYPE_HODIR:
+ m_auiEncounter[TYPE_HODIR] = data;
+ if (data == DONE && HodirChest)
+ HodirChest->SetRespawnTime(HodirChest->GetRespawnDelay());
+ case TYPE_THORIM:
+ m_auiEncounter[TYPE_THORIM] = data;
+ if (data == DONE && ThorimChest)
+ ThorimChest->SetRespawnTime(ThorimChest->GetRespawnDelay());
+ case TYPE_FREYA:
+ m_auiEncounter[TYPE_FREYA] = data;
+ if (data == DONE && FreyaChest)
+ FreyaChest->SetRespawnTime(FreyaChest->GetRespawnDelay());
+ case TYPE_VEZAX:
+ case TYPE_YOGGSARON:
+ case TYPE_ALGALON:
+ m_auiEncounter[type] = data;
+ break;
+ }
+
+ if (data == DONE)
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ saveStream << m_auiEncounter[i] << " ";
+
+ m_strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ uint64 GetData64(uint32 data)
+ {
+ switch(data)
+ {
+ case TYPE_LEVIATHAN:
+ return m_uiLeviathanGUID;
+ case TYPE_IGNIS:
+ return m_uiIgnisGUID;
+ case TYPE_RAZORSCALE:
+ return m_uiRazorscaleGUID;
+ case TYPE_XT002:
+ return m_uiXT002GUID;
+ case TYPE_KOLOGARN:
+ return m_uiKologarnGUID;
+ case TYPE_AURIAYA:
+ return m_uiAuriayaGUID;
+ case TYPE_MIMIRON:
+ return m_uiMimironGUID;
+ case TYPE_HODIR:
+ return m_uiMimironGUID;
+ case TYPE_THORIM:
+ return m_uiThorimGUID;
+ case TYPE_FREYA:
+ return m_uiFreyaGUID;
+ case TYPE_VEZAX:
+ return m_uiVezaxGUID;
+ case TYPE_YOGGSARON:
+ return m_uiYoggSaronGUID;
+ case TYPE_ALGALON:
+ return m_uiAlgalonGUID;
+
+ // Assembly of Iron
+ case DATA_STEELBREAKER:
+ return m_auiAssemblyGUIDs[0];
+ case DATA_MOLGEIM:
+ return m_auiAssemblyGUIDs[1];
+ case DATA_BRUNDIR:
+ return m_auiAssemblyGUIDs[2];
+ }
+
+ return 0;
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ switch(type)
+ {
+ case TYPE_LEVIATHAN:
+ case TYPE_IGNIS:
+ case TYPE_RAZORSCALE:
+ case TYPE_XT002:
+ case TYPE_ASSEMBLY:
+ case TYPE_KOLOGARN:
+ case TYPE_AURIAYA:
+ case TYPE_MIMIRON:
+ case TYPE_HODIR:
+ case TYPE_THORIM:
+ case TYPE_FREYA:
+ case TYPE_VEZAX:
+ case TYPE_YOGGSARON:
+ case TYPE_ALGALON:
+ return m_auiEncounter[type];
+ }
+
+ return 0;
+ }
+
+ std::string GetSaveData()
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "U U " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]
+ << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7]
+ << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11]
+ << m_auiEncounter[12] << " " << m_auiEncounter[13];
+
+ m_strInstData = saveStream.str();
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return m_strInstData;
+ }
+
+ void Load(const char* strIn)
+ {
+ if (!strIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(strIn);
+
+ char dataHead1, dataHead2;
+ uint32 data0, data1, data2, data3, data4, data5, data6,
+ data7, data8, data9, data10, data11, data12, data13;
+
+ std::istringstream loadStream(strIn);
+ loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6
+ >> data7 >> data8 >> data9 >> data10 >> data11 >> data12 >> data13;
+
+ if (dataHead1 == 'U' && dataHead2 == 'U')
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ loadStream >> m_auiEncounter[i];
+
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+ }
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_ulduar(Map* pMap)
+{
+ return new instance_ulduar(pMap);
+}
+
+void AddSC_instance_ulduar()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_ulduar";
+ newscript->GetInstanceData = &GetInstanceData_instance_ulduar;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/ulduar/ulduar/ulduar.h b/src/scripts/northrend/ulduar/ulduar/ulduar.h
new file mode 100644
index 00000000000..ed7686343fb
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/ulduar.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 - 2009 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_ULDUAR_H
+#define DEF_ULDUAR_H
+
+enum eTypes
+{
+ MAX_ENCOUNTER = 14,
+
+ TYPE_LEVIATHAN = 0,
+ TYPE_IGNIS = 1,
+ TYPE_RAZORSCALE = 2,
+ TYPE_XT002 = 3,
+ TYPE_ASSEMBLY = 4,
+ TYPE_KOLOGARN = 5,
+ TYPE_AURIAYA = 6,
+ TYPE_MIMIRON = 7,
+ TYPE_HODIR = 8,
+ TYPE_THORIM = 9,
+ TYPE_FREYA = 10,
+ TYPE_VEZAX = 11,
+ TYPE_YOGGSARON = 12,
+ TYPE_ALGALON = 13,
+
+ DATA_STEELBREAKER = 20,
+ DATA_MOLGEIM = 21,
+ DATA_BRUNDIR = 22,
+ DATA_RUNEMASTER_MOLGEIM = 23,
+ DATA_STORMCALLER_BRUNDIR = 24,
+
+ NPC_LEVIATHAN = 33113,
+ NPC_IGNIS = 33118,
+ NPC_RAZORSCALE = 33186,
+ NPC_XT002 = 33293,
+ NPC_STEELBREAKER = 32867,
+ NPC_MOLGEIM = 32927,
+ NPC_BRUNDIR = 32857,
+ NPC_KOLOGARN = 32930,
+ NPC_AURIAYA = 33515,
+ NPC_MIMIRON = 33350,
+ NPC_HODIR = 32845,
+ NPC_THORIM = 32865,
+ NPC_FREYA = 32906,
+ NPC_VEZAX = 33271,
+ NPC_YOGGSARON = 33288,
+ NPC_ALGALON = 32871
+};
+
+#endif
diff --git a/src/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp b/src/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp
new file mode 100644
index 00000000000..8489bf4272b
--- /dev/null
+++ b/src/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp
@@ -0,0 +1,92 @@
+#include "ScriptedPch.h"
+#include "ulduar.h"
+
+/*
+The teleporter appears to be active and stable.
+
+- Expedition Base Camp
+- Formation Grounds
+- Colossal Forge
+- Scrapyard
+- Antechamber of Ulduar
+- Shattered Walkway
+- Conservatory of Life
+*/
+
+#define BASE_CAMP 200
+#define GROUNDS 201
+#define FORGE 202
+#define SCRAPYARD 203
+#define ANTECHAMBER 204
+#define WALKWAY 205
+#define CONSERVATORY 206
+
+bool GoHello_ulduar_teleporter( Player *pPlayer, GameObject *pGO )
+{
+ ScriptedInstance *pInstance = (ScriptedInstance *) pGO->GetInstanceData();
+ if(!pInstance) return true;
+
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP);
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS);
+ if(pInstance->GetData(TYPE_LEVIATHAN) == DONE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE);
+ if(pInstance->GetData(TYPE_XT002) == DONE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD);
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER);
+ if(pInstance->GetData(TYPE_KOLOGARN) == DONE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY);
+ if(pInstance->GetData(TYPE_AURIAYA) == DONE)
+ pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY);
+ }
+ }
+ }
+ pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pGO->GetGUID());
+
+ return true;
+}
+
+bool GOSelect_ulduar_teleporter( Player *pPlayer, GameObject *pGO, uint32 sender, uint32 action )
+{
+ if(sender != GOSSIP_SENDER_MAIN) return true;
+ if(!pPlayer->getAttackers().empty()) return true;
+
+ switch(action)
+ {
+ case BASE_CAMP:
+ pPlayer->TeleportTo(603, -706.122, -92.6024, 429.876, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ case GROUNDS:
+ pPlayer->TeleportTo(603, 131.248, -35.3802, 409.804, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ case FORGE:
+ pPlayer->TeleportTo(603, 553.233, -12.3247, 409.679, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ case SCRAPYARD:
+ pPlayer->TeleportTo(603, 926.292, -11.4635, 418.595, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ case ANTECHAMBER:
+ pPlayer->TeleportTo(603, 1498.09, -24.246, 420.967, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ case WALKWAY:
+ pPlayer->TeleportTo(603, 1859.45, -24.1, 448.9, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ case CONSERVATORY:
+ pPlayer->TeleportTo(603, 2086.27, -24.3134, 421.239, 0);
+ pPlayer->CLOSE_GOSSIP_MENU(); break;
+ }
+
+ return true;
+}
+
+void AddSC_ulduar_teleporter()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "ulduar_teleporter";
+ newscript->pGOHello = &GoHello_ulduar_teleporter;
+ newscript->pGOSelect = &GOSelect_ulduar_teleporter;
+ newscript->RegisterSelf();
+}