*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
This commit is contained in:
Rat
2010-01-19 11:36:05 +01:00
parent f5dea61b66
commit 0cc053ea4d
601 changed files with 3908 additions and 7245 deletions
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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
@@ -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();
}
@@ -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"
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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"
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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"
@@ -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();
}
@@ -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();
}
@@ -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();
}
@@ -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"
@@ -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();
}
@@ -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
@@ -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();
}