diff options
| author | Xanadu <none@none> | 2010-07-17 22:58:24 +0200 |
|---|---|---|
| committer | Xanadu <none@none> | 2010-07-17 22:58:24 +0200 |
| commit | b5f8bfd66561e4a63fa8c28961b829a35ceb2fb0 (patch) | |
| tree | 6691fda7c0985077aeb6ff3a93e829447dddd736 /src/server/scripts/Outland/HellfireCitadel | |
| parent | ec244dbe366e84a93c8fa1ef294af4a2e4e3b0b1 (diff) | |
| parent | dc510c9a143de1977daedea0aefb9589c01adde2 (diff) | |
Merge
--HG--
branch : trunk
Diffstat (limited to 'src/server/scripts/Outland/HellfireCitadel')
18 files changed, 3883 insertions, 0 deletions
diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h new file mode 100644 index 00000000000..b845c66823f --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h @@ -0,0 +1,29 @@ +/* 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_BLOOD_FURNACE_H +#define DEF_BLOOD_FURNACE_H + +#define DATA_THE_MAKER 1 +#define DATA_BROGGOK 2 +#define DATA_KELIDAN_THE_MAKER 3 +#define TYPE_THE_MAKER_EVENT 4 +#define TYPE_BROGGOK_EVENT 5 +#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 +#define DATA_DOOR1 7 +#define DATA_DOOR2 8 +#define DATA_DOOR3 9 +#define DATA_DOOR4 10 +#define DATA_DOOR5 11 +#define DATA_DOOR6 12 +#define DATA_PRISON_CELL1 13 +#define DATA_PRISON_CELL2 14 +#define DATA_PRISON_CELL3 15 +#define DATA_PRISON_CELL4 16 +#define DATA_PRISON_CELL5 17 +#define DATA_PRISON_CELL6 18 +#define DATA_PRISON_CELL7 19 +#define DATA_PRISON_CELL8 20 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp new file mode 100644 index 00000000000..d5fb9bdba49 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp @@ -0,0 +1,131 @@ +/* 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_Broggok +SD%Complete: 70 +SDComment: pre-event not made +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO = -1542008, + + SPELL_SLIME_SPRAY = 30913, + SPELL_POISON_CLOUD = 30916, + SPELL_POISON_BOLT = 30917, + + SPELL_POISON = 30914 +}; + +struct boss_broggokAI : public ScriptedAI +{ + boss_broggokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 PoisonSpawn_Timer; + uint32 PoisonBolt_Timer; + + void Reset() + { + AcidSpray_Timer = 10000; + PoisonSpawn_Timer = 5000; + PoisonBolt_Timer = 7000; + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); + } + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLIME_SPRAY); + AcidSpray_Timer = 4000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (PoisonBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_BOLT); + PoisonBolt_Timer = 4000+rand()%8000; + } else PoisonBolt_Timer -=diff; + + if (PoisonSpawn_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLOUD); + PoisonSpawn_Timer = 20000; + } else PoisonSpawn_Timer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); + pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); + } + } + +}; + +CreatureAI* GetAI_boss_broggok(Creature* pCreature) +{ + return new boss_broggokAI (pCreature); +} + +void AddSC_boss_broggok() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_broggok"; + newscript->GetAI = &GetAI_boss_broggok; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp new file mode 100644 index 00000000000..a44ad9cc3c8 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp @@ -0,0 +1,356 @@ +/* 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_Kelidan_The_Breaker +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +/* ContentData +boss_kelidan_the_breaker +mob_shadowmoon_channeler +EndContentData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eKelidan +{ + SAY_WAKE = -1542000, + SAY_ADD_AGGRO_1 = -1542001, + SAY_ADD_AGGRO_2 = -1542002, + SAY_ADD_AGGRO_3 = -1542003, + SAY_KILL_1 = -1542004, + SAY_KILL_2 = -1542005, + SAY_NOVA = -1542006, + SAY_DIE = -1542007, + + SPELL_CORRUPTION = 30938, + SPELL_EVOCATION = 30935, + + SPELL_FIRE_NOVA = 33132, + H_SPELL_FIRE_NOVA = 37371, + + SPELL_SHADOW_BOLT_VOLLEY = 28599, + H_SPELL_SHADOW_BOLT_VOLLEY = 40070, + + SPELL_BURNING_NOVA = 30940, + SPELL_VORTEX = 37370, + + ENTRY_KELIDAN = 17377, + ENTRY_CHANNELER = 17653 +}; + +const float ShadowmoonChannelers[5][4]= +{ + {302,-87,-24.4,0.157}, + {321,-63.5,-24.6,4.887}, + {346,-74.5,-24.6,3.595}, + {344,-103.5,-24.5,2.356}, + {316,-109,-24.6,1.257} +}; + +struct boss_kelidan_the_breakerAI : public ScriptedAI +{ + boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i=0; i<5; ++i) + Channelers[i] = 0; + } + + ScriptedInstance* pInstance; + + uint32 ShadowVolley_Timer; + uint32 BurningNova_Timer; + uint32 Firenova_Timer; + uint32 Corruption_Timer; + uint32 check_Timer; + bool Firenova; + bool addYell; + uint64 Channelers[5]; + + void Reset() + { + ShadowVolley_Timer = 1000; + BurningNova_Timer = 15000; + Corruption_Timer = 5000; + check_Timer = 0; + Firenova = false; + addYell = false; + SummonChannelers(); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_WAKE, me); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void ChannelerEngaged(Unit* who) + { + if (who && !addYell) + { + addYell = true; + DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); + } + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (who && channeler && !channeler->isInCombat()) + channeler->AI()->AttackStart(who); + } + } + + void ChannelerDied(Unit* killer) + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->isAlive()) + return; + } + + if (killer) + me->AI()->AttackStart(killer); + } + + uint64 GetChanneled(Creature *channeler1) + { + SummonChannelers(); + if (!channeler1) return NULL; + uint8 i; + for (i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->GetGUID() == channeler1->GetGUID()) + break; + } + return Channelers[(i+2)%5]; + } + + void SummonChannelers() + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (!channeler || channeler->isDead()) + channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); + if (channeler) + Channelers[i] = channeler->GetGUID(); + else + Channelers[i] = 0; + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + DoCast(me, SPELL_EVOCATION); + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (Firenova) + { + if (Firenova_Timer <= diff) + { + DoCast(me, SPELL_FIRE_NOVA, true); + Firenova = false; + ShadowVolley_Timer = 2000; + } else Firenova_Timer -=diff; + + return; + } + + if (ShadowVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowVolley_Timer = 5000+rand()%8000; + } else ShadowVolley_Timer -=diff; + + if (Corruption_Timer <= diff) + { + DoCast(me, SPELL_CORRUPTION); + Corruption_Timer = 30000+rand()%20000; + } else Corruption_Timer -=diff; + + if (BurningNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_NOVA, me); + + if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) + { + if (Aura * aura = Aura::TryCreate(nova, me, me)) + aura->ApplyForTargets(); + } + + if (IsHeroic()) + DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + + BurningNova_Timer = 20000+rand()%8000; + Firenova_Timer= 5000; + Firenova = true; + } else BurningNova_Timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) +{ + return new boss_kelidan_the_breakerAI (pCreature); +} + +/*###### +## mob_shadowmoon_channeler +######*/ + +enum eShadowmoon +{ + SPELL_SHADOW_BOLT = 12739, + H_SPELL_SHADOW_BOLT = 15472, + + SPELL_MARK_OF_SHADOW = 30937, + SPELL_CHANNELING = 39123 +}; + +struct mob_shadowmoon_channelerAI : public ScriptedAI +{ + mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 ShadowBolt_Timer; + uint32 MarkOfShadow_Timer; + uint32 check_Timer; + + void Reset() + { + ShadowBolt_Timer = 1000+rand()%1000; + MarkOfShadow_Timer = 5000+rand()%2000; + check_Timer = 0; + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + } + + void EnterCombat(Unit* who) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + } + + void JustDied(Unit* Killer) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + { + uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); + if (Unit *channeled = Unit::GetUnit(*me, channeler)) + DoCast(channeled, SPELL_CHANNELING); + } + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (MarkOfShadow_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_SHADOW); + MarkOfShadow_Timer = 15000+rand()%5000; + } else MarkOfShadow_Timer -=diff; + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 5000+rand()%1000; + } else ShadowBolt_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) +{ + return new mob_shadowmoon_channelerAI (pCreature); +} + +void AddSC_boss_kelidan_the_breaker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_kelidan_the_breaker"; + newscript->GetAI = &GetAI_boss_kelidan_the_breaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadowmoon_channeler"; + newscript->GetAI = &GetAI_mob_shadowmoon_channeler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp new file mode 100644 index 00000000000..45219b6509b --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp @@ -0,0 +1,152 @@ +/* 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_The_Maker +SD%Complete: 80 +SDComment: Mind control no support +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO_1 = -1542009, + SAY_AGGRO_2 = -1542010, + SAY_AGGRO_3 = -1542011, + SAY_KILL_1 = -1542012, + SAY_KILL_2 = -1542013, + SAY_DIE = -1542014, + + SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 + SPELL_EXPLODING_BREAKER = 30925, + SPELL_KNOCKDOWN = 20276, + SPELL_DOMINATION = 25772 // ??? +}; + +struct boss_the_makerAI : public ScriptedAI +{ + boss_the_makerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 ExplodingBreaker_Timer; + uint32 Domination_Timer; + uint32 Knockdown_Timer; + + void Reset() + { + AcidSpray_Timer = 15000; + ExplodingBreaker_Timer = 6000; + Domination_Timer = 120000; + Knockdown_Timer = 10000; + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); + + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ACID_SPRAY); + AcidSpray_Timer = 15000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (ExplodingBreaker_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_EXPLODING_BREAKER); + ExplodingBreaker_Timer = 4000+rand()%8000; + } else ExplodingBreaker_Timer -=diff; + + /* // Disabled until Core Support for mind control + if (domination_timer_timer <= diff) + { + Unit *pTarget; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(pTarget, SPELL_DOMINATION); + + domination_timer = 120000; + } else domination_timer -=diff; + */ + + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 4000+rand()%8000; + } else Knockdown_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) +{ + return new boss_the_makerAI (pCreature); +} + +void AddSC_boss_the_maker() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_maker"; + newscript->GetAI = &GetAI_boss_the_makerAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp new file mode 100644 index 00000000000..3a2eb8ba5ee --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp @@ -0,0 +1,232 @@ +/* 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_Blood_Furnace +SD%Complete: 85 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +#define ENTRY_SEWER1 181823 +#define ENTRY_SEWER2 181766 +#define MAX_ENCOUNTER 3 + +struct instance_blood_furnace : public ScriptedInstance +{ + instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 The_MakerGUID; + uint64 BroggokGUID; + uint64 Kelidan_The_BreakerGUID; + + uint64 Door1GUID; + uint64 Door2GUID; + uint64 Door3GUID; + uint64 Door4GUID; + uint64 Door5GUID; + uint64 Door6GUID; + + uint64 PrisonCell1GUID; + uint64 PrisonCell2GUID; + uint64 PrisonCell3GUID; + uint64 PrisonCell4GUID; + uint64 PrisonCell5GUID; + uint64 PrisonCell6GUID; + uint64 PrisonCell7GUID; + uint64 PrisonCell8GUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + The_MakerGUID = 0; + BroggokGUID = 0; + Kelidan_The_BreakerGUID = 0; + + Door1GUID = 0; + Door2GUID = 0; + Door3GUID = 0; + Door4GUID = 0; + Door5GUID = 0; + Door6GUID = 0; + + PrisonCell1GUID = 0; + PrisonCell2GUID = 0; + PrisonCell3GUID = 0; + PrisonCell4GUID = 0; + PrisonCell5GUID = 0; + PrisonCell6GUID = 0; + PrisonCell7GUID = 0; + PrisonCell8GUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + switch(pCreature->GetEntry()) + { + case 17381: The_MakerGUID = pCreature->GetGUID(); break; + case 17380: BroggokGUID = pCreature->GetGUID(); break; + case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + if (pGo->GetEntry() == 181766) //Final exit door + Door1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181811) //The Maker Front door + Door2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181812) //The Maker Rear door + Door3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181822) //Broggok Front door + Door4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181819) //Broggok Rear door + Door5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181823) //Kelidan exit door + Door6GUID = pGo->GetGUID(); + + if (pGo->GetEntry() == 181813) //The Maker prison cell front right + PrisonCell1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181814) //The Maker prison cell back right + PrisonCell2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181816) //The Maker prison cell front left + PrisonCell3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181815) //The Maker prison cell back left + PrisonCell4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181821) //Broggok prison cell front right + PrisonCell5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181818) //Broggok prison cell back right + PrisonCell6GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181820) //Broggok prison cell front left + PrisonCell7GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181817) //Broggok prison cell back left + PrisonCell8GUID = pGo->GetGUID(); + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THE_MAKER: return The_MakerGUID; + case DATA_BROGGOK: return BroggokGUID; + case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; + case DATA_DOOR1: return Door1GUID; + case DATA_DOOR2: return Door2GUID; + case DATA_DOOR3: return Door3GUID; + case DATA_DOOR4: return Door4GUID; + case DATA_DOOR5: return Door5GUID; + case DATA_DOOR6: return Door6GUID; + case DATA_PRISON_CELL1: return PrisonCell1GUID; + case DATA_PRISON_CELL2: return PrisonCell2GUID; + case DATA_PRISON_CELL3: return PrisonCell3GUID; + case DATA_PRISON_CELL4: return PrisonCell4GUID; + case DATA_PRISON_CELL5: return PrisonCell5GUID; + case DATA_PRISON_CELL6: return PrisonCell6GUID; + case DATA_PRISON_CELL7: return PrisonCell7GUID; + case DATA_PRISON_CELL8: return PrisonCell8GUID; + } + + return 0; + } + + void SetData(uint32 /*type*/, uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; + case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; + case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; + case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; + case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + const char* Save() + { + return str_data.c_str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) +{ + return new instance_blood_furnace(pMap); +} + +void AddSC_instance_blood_furnace() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blood_furnace"; + newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp new file mode 100644 index 00000000000..d6c0b2fd401 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp @@ -0,0 +1,206 @@ +/* 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_Omar_The_Unscarred +SD%Complete: 90 +SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1543009 +#define SAY_AGGRO_2 -1543010 +#define SAY_AGGRO_3 -1543011 +#define SAY_SUMMON -1543012 +#define SAY_CURSE -1543013 +#define SAY_KILL_1 -1543014 +#define SAY_DIE -1543015 +#define SAY_WIPE -1543016 + +#define SPELL_ORBITAL_STRIKE 30637 +#define SPELL_SHADOW_WHIP 30638 +#define SPELL_TREACHEROUS_AURA 30695 +#define H_SPELL_BANE_OF_TREACHERY 37566 +#define SPELL_DEMONIC_SHIELD 31901 +#define SPELL_SHADOW_BOLT 30686 +#define H_SPELL_SHADOW_BOLT 39297 +#define SPELL_SUMMON_FIENDISH_HOUND 30707 + +struct boss_omor_the_unscarredAI : public ScriptedAI +{ + boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 OrbitalStrike_Timer; + uint32 ShadowWhip_Timer; + uint32 Aura_Timer; + uint32 DemonicShield_Timer; + uint32 Shadowbolt_Timer; + uint32 Summon_Timer; + uint32 SummonedCount; + uint64 PlayerGUID; + bool CanPullBack; + + void Reset() + { + DoScriptText(SAY_WIPE, me); + + OrbitalStrike_Timer = 25000; + ShadowWhip_Timer = 2000; + Aura_Timer = 10000; + DemonicShield_Timer = 1000; + Shadowbolt_Timer = 2000; + Summon_Timer = 10000; + SummonedCount = 0; + PlayerGUID = 0; + CanPullBack = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(SAY_KILL_1, me); + } + + void JustSummoned(Creature* summoned) + { + DoScriptText(SAY_SUMMON, me); + + if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(random); + + ++SummonedCount; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //only two may be wrong, perhaps increase timer and spawn periodically instead. + if (SummonedCount < 2) + { + if (Summon_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); + Summon_Timer = 15000+rand()%15000; + } else Summon_Timer -= diff; + } + + if (CanPullBack) + { + if (ShadowWhip_Timer <= diff) + { + if (Player* temp = Unit::GetPlayer(PlayerGUID)) + { + //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) + if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) + { + me->InterruptNonMeleeSpells(false); + DoCast(temp, SPELL_SHADOW_WHIP); + } + } + PlayerGUID = 0; + ShadowWhip_Timer = 2000; + CanPullBack = false; + } else ShadowWhip_Timer -= diff; + } + else if (OrbitalStrike_Timer <= diff) + { + Unit* temp = NULL; + if (me->IsWithinMeleeRange(me->getVictim())) + temp = me->getVictim(); + else temp = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (temp && temp->GetTypeId() == TYPEID_PLAYER) + { + DoCast(temp, SPELL_ORBITAL_STRIKE); + OrbitalStrike_Timer = 14000+rand()%2000; + PlayerGUID = temp->GetGUID(); + + if (PlayerGUID) + CanPullBack = true; + } + } else OrbitalStrike_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (DemonicShield_Timer <= diff) + { + DoCast(me, SPELL_DEMONIC_SHIELD); + DemonicShield_Timer = 15000; + } else DemonicShield_Timer -= diff; + } + + if (Aura_Timer <= diff) + { + DoScriptText(SAY_CURSE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_TREACHEROUS_AURA); + Aura_Timer = 8000+rand()%8000; + } + } else Aura_Timer -= diff; + + if (Shadowbolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_SHADOW_BOLT); + Shadowbolt_Timer = 4000+rand()%2500; + } + } else Shadowbolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) +{ + return new boss_omor_the_unscarredAI (pCreature); +} + +void AddSC_boss_omor_the_unscarred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_omor_the_unscarred"; + newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp new file mode 100644 index 00000000000..181911f77a4 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp @@ -0,0 +1,467 @@ +/* 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 +Name: Boss_Vazruden_the_Herald +%Complete: 90 +Comment: +Category: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) +#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) +#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) +#define SPELL_KIDNEY_SHOT 30621 +#define SPELL_FIRE_NOVA_VISUAL 19823 + +#define ENTRY_HELLFIRE_SENTRY 17517 +#define ENTRY_VAZRUDEN_HERALD 17307 +#define ENTRY_VAZRUDEN 17537 +#define ENTRY_NAZAN 17536 +#define ENTRY_LIQUID_FIRE 22515 +#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) + +#define SAY_INTRO -1543017 +#define SAY_WIPE -1543018 +#define SAY_AGGRO_1 -1543019 +#define SAY_AGGRO_2 -1543020 +#define SAY_AGGRO_3 -1543021 +#define SAY_KILL_1 -1543022 +#define SAY_KILL_2 -1543023 +#define SAY_DIE -1543024 +#define EMOTE -1543025 + +#define PATH_ENTRY 2081 + +const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; +const float VazrudenRing[2][3] = +{ + {-1430, 1705, 112}, + {-1377, 1760, 112} +}; + +struct boss_nazanAI : public ScriptedAI +{ + boss_nazanAI(Creature *c) : ScriptedAI(c) + { + VazrudenGUID = 0; + flight = true; + } + + uint32 Fireball_Timer; + uint32 ConeOfFire_Timer; + uint32 BellowingRoar_Timer; + uint32 Fly_Timer; + uint32 Turn_Timer; + uint32 UnsummonCheck; + bool flight; + uint64 VazrudenGUID; + SpellEntry *liquid_fire; + + void Reset() + { + Fireball_Timer = 4000; + Fly_Timer = 45000; + Turn_Timer = 0; + UnsummonCheck = 5000; + } + + void EnterCombat(Unit* /*who*/) {} + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) + { + summoned->SetLevel(me->getLevel()); + summoned->setFaction(me->getFaction()); + summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); + summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) + { + if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) + me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + me->DisappearAndDie(); + else + UnsummonCheck -= diff; + return; + } + + if (Fireball_Timer <= diff) + { + if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(victim, SPELL_FIREBALL, true); + Fireball_Timer = urand(4000,7000); + } else Fireball_Timer -= diff; + + if (flight) // phase 1 - the flight + { + Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); + if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) + { + flight = false; + BellowingRoar_Timer = 6000; + ConeOfFire_Timer = 12000; + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->Clear(); + if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) + me->AI()->AttackStart(victim); + DoStartMovement(me->getVictim()); + DoScriptText(EMOTE, me); + return; + } else Fly_Timer -= diff; + + if (Turn_Timer <= diff) + { + uint32 waypoint = (Fly_Timer/10000)%2; + if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) + me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); + Turn_Timer = 10000; + } else Turn_Timer -= diff; + } + else // phase 2 - land fight + { + if (ConeOfFire_Timer <= diff) + { + DoCast(me, SPELL_CONE_OF_FIRE); + ConeOfFire_Timer = 12000; + Fireball_Timer = 4000; + } else ConeOfFire_Timer -= diff; + + if (IsHeroic()) + if (BellowingRoar_Timer <= diff) + { + DoCast(me, SPELL_BELLOWING_ROAR); + BellowingRoar_Timer = 45000; + } else BellowingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +struct boss_vazrudenAI : public ScriptedAI +{ + boss_vazrudenAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Revenge_Timer; + bool WipeSaid; + uint32 UnsummonCheck; + + void Reset() + { + Revenge_Timer = 4000; + UnsummonCheck = 2000; + WipeSaid = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* who) + { + if (who && who->GetEntry() != ENTRY_VAZRUDEN) + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* who) + { + if (who && who != me) + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + { + if (!WipeSaid) + { + DoScriptText(SAY_WIPE, me); + WipeSaid = true; + } + me->DisappearAndDie(); + } else UnsummonCheck -= diff; + return; + } + + if (Revenge_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_REVENGE); + Revenge_Timer = 5000; + } else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_vazruden_the_heraldAI : public ScriptedAI +{ + boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) + { + summoned = false; + sentryDown = false; + NazanGUID = 0; + VazrudenGUID = 0; + } + + uint32 phase; + uint32 waypoint; + uint32 check; + bool sentryDown; + uint64 NazanGUID; + uint64 VazrudenGUID; + bool summoned; + + void Reset() + { + phase = 0; + waypoint = 0; + check = 0; + UnsummonAdds(); + me->GetMotionMaster()->MovePath(PATH_ENTRY, true); + } + + void UnsummonAdds() + { + if (summoned) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + if (!Nazan) + Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); + if (Nazan) + { + Nazan->DisappearAndDie(); + NazanGUID = 0; + } + + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (!Vazruden) + Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); + if (Vazruden) + { + Vazruden->DisappearAndDie(); + VazrudenGUID = 0; + } + summoned = false; + me->clearUnitState(UNIT_STAT_ROOT); + me->SetVisibility(VISIBILITY_ON); + } + } + + void SummonAdds() + { + if (!summoned) + { + if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + VazrudenGUID = Vazruden->GetGUID(); + if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + NazanGUID = Nazan->GetGUID(); + summoned = true; + me->SetVisibility(VISIBILITY_OFF); + me->addUnitState(UNIT_STAT_ROOT); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (phase == 0) + { + phase = 1; + check = 0; + DoScriptText(SAY_INTRO, me); + } + } + + void JustSummoned(Creature *summoned) + { + if (!summoned) return; + Unit *victim = me->getVictim(); + if (summoned->GetEntry() == ENTRY_NAZAN) + { + CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; + summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + summoned->SetSpeed(MOVE_FLIGHT, 2.5); + if (victim) + AttackStartNoMove(victim); + } + else if (victim) + summoned->AI()->AttackStart(victim); + } + + void SentryDownBy(Unit* killer) + { + if (sentryDown) + { + AttackStartNoMove(killer); + sentryDown = false; + } + else + sentryDown = true; + } + + void UpdateAI(const uint32 diff) + { + switch(phase) + { + case 0: // circle around the platform + return; + break; + case 1: // go to the middle and begin the fight + if (check <= diff) + { + if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); + check = 1000; + } + else + { + SummonAdds(); + phase = 2; + return; + } + } else check -= diff; + break; + default: // adds do the job now + if (check <= diff) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) + { + if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) + return; + else + { + UnsummonAdds(); + EnterEvadeMode(); + return; + } + } + else + { + me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); + me->SetLootRecipient(NULL); // don't think this is necessary.. + me->Kill(me); + } + check = 2000; + } else check -= diff; + break; + } + } +}; + +struct mob_hellfire_sentryAI : public ScriptedAI +{ + mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} + + uint32 KidneyShot_Timer; + + void Reset() + { + KidneyShot_Timer = urand(3000,7000); + } + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* who) + { + if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) + CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (KidneyShot_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_KIDNEY_SHOT); + KidneyShot_Timer = 20000; + } else KidneyShot_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) +{ + return new boss_vazruden_the_heraldAI (pCreature); +} + +CreatureAI* GetAI_boss_vazruden(Creature* pCreature) +{ + return new boss_vazrudenAI (pCreature); +} + +CreatureAI* GetAI_boss_nazan(Creature* pCreature) +{ + return new boss_nazanAI (pCreature); +} + +CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) +{ + return new mob_hellfire_sentryAI (pCreature); +} + +void AddSC_boss_vazruden_the_herald() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vazruden_the_herald"; + newscript->GetAI = &GetAI_boss_vazruden_the_herald; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vazruden"; + newscript->GetAI = &GetAI_boss_vazruden; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_nazan"; + newscript->GetAI = &GetAI_boss_nazan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_sentry"; + newscript->GetAI = &GetAI_mob_hellfire_sentry; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp new file mode 100644 index 00000000000..f0e813d3890 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp @@ -0,0 +1,156 @@ +/* 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_Watchkeeper_Gargolmar +SD%Complete: 80 +SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_TAUNT -1543000 +#define SAY_HEAL -1543001 +#define SAY_SURGE -1543002 +#define SAY_AGGRO_1 -1543003 +#define SAY_AGGRO_2 -1543004 +#define SAY_AGGRO_3 -1543005 +#define SAY_KILL_1 -1543006 +#define SAY_KILL_2 -1543007 +#define SAY_DIE -1543008 + +#define SPELL_MORTAL_WOUND 30641 +#define H_SPELL_MORTAL_WOUND 36814 +#define SPELL_SURGE 34645 +#define SPELL_RETALIATION 22857 + +struct boss_watchkeeper_gargolmarAI : public ScriptedAI +{ + boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Surge_Timer; + uint32 MortalWound_Timer; + uint32 Retaliation_Timer; + + bool HasTaunted; + bool YelledForHeal; + + void Reset() + { + Surge_Timer = 5000; + MortalWound_Timer = 4000; + Retaliation_Timer = 0; + + HasTaunted = false; + YelledForHeal = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void MoveInLineOfSight(Unit* who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) + { + DoScriptText(SAY_TAUNT, me); + HasTaunted = true; + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (MortalWound_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + MortalWound_Timer = 5000+rand()%8000; + } else MortalWound_Timer -= diff; + + if (Surge_Timer <= diff) + { + DoScriptText(SAY_SURGE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SURGE); + + Surge_Timer = 5000+rand()%8000; + } else Surge_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (Retaliation_Timer <= diff) + { + DoCast(me, SPELL_RETALIATION); + Retaliation_Timer = 30000; + } else Retaliation_Timer -= diff; + } + + if (!YelledForHeal) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) + { + DoScriptText(SAY_HEAL, me); + YelledForHeal = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) +{ + return new boss_watchkeeper_gargolmarAI (pCreature); +} + +void AddSC_boss_watchkeeper_gargolmar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_watchkeeper_gargolmar"; + newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h new file mode 100644 index 00000000000..599aa237774 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h @@ -0,0 +1,16 @@ +/* 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_RAMPARTS_H +#define DEF_RAMPARTS_H + +#define MAX_ENCOUNTER 2 + +enum eTypes +{ + TYPE_VAZRUDEN = 1, + TYPE_NAZAN = 2 +}; + +#endif diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp new file mode 100644 index 00000000000..29c58675e9c --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp @@ -0,0 +1,84 @@ +/* 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_Hellfire_Ramparts +SD%Complete: 50 +SDComment: +SDCategory: Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" +#include "hellfire_ramparts.h" + +struct instance_ramparts : public ScriptedInstance +{ + instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 m_uiChestNGUID; + uint64 m_uiChestHGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiChestNGUID = 0; + m_uiChestHGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 185168: m_uiChestNGUID = pGo->GetGUID(); break; + case 185169: m_uiChestHGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); + + switch(uiType) + { + case TYPE_VAZRUDEN: + if (uiData == DONE && m_auiEncounter[1] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[0] = uiData; + break; + case TYPE_NAZAN: + if (uiData == DONE && m_auiEncounter[0] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[1] = uiData; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_ramparts(Map* pMap) +{ + return new instance_ramparts(pMap); +} + +void AddSC_instance_ramparts() +{ + Script* pNewScript; + pNewScript = new Script; + pNewScript->Name = "instance_ramparts"; + pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; + pNewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp new file mode 100644 index 00000000000..5fb381f4065 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp @@ -0,0 +1,570 @@ +/* Copyright(C) 2006 - 2008 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_Magtheridon +SD%Complete: 60 +SDComment: In Development +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +struct Yell +{ + int32 id; +}; + +static Yell RandomTaunt[]= +{ + {-1544000}, + {-1544001}, + {-1544002}, + {-1544003}, + {-1544004}, + {-1544005}, +}; + +#define SAY_FREED -1544006 +#define SAY_AGGRO -1544007 +#define SAY_BANISH -1544008 +#define SAY_CHAMBER_DESTROY -1544009 +#define SAY_PLAYER_KILLED -1544010 +#define SAY_DEATH -1544011 + +#define EMOTE_BERSERK -1544012 +#define EMOTE_BLASTNOVA -1544013 +#define EMOTE_BEGIN -1544014 + +#define MOB_MAGTHERIDON 17257 +#define MOB_ROOM 17516 +#define MOB_CHANNELLER 17256 +#define MOB_ABYSSAL 17454 + +#define SPELL_BLASTNOVA 30616 +#define SPELL_CLEAVE 30619 +#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell +#define SPELL_QUAKE_KNOCKBACK 30571 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 +#define SPELL_BLAZE_TRAP 30542 +#define SPELL_DEBRIS_KNOCKDOWN 36449 +#define SPELL_DEBRIS_VISUAL 30632 +#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 +#define SPELL_CAMERA_SHAKE 36455 +#define SPELL_BERSERK 27680 + +#define SPELL_SHADOW_CAGE 30168 +#define SPELL_SHADOW_GRASP 30410 +#define SPELL_SHADOW_GRASP_VISUAL 30166 +#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends + +#define SPELL_SHADOW_CAGE_C 30205 +#define SPELL_SHADOW_GRASP_C 30207 + +#define SPELL_SHADOW_BOLT_VOLLEY 30510 +#define SPELL_DARK_MENDING 30528 +#define SPELL_FEAR 30530 //39176 +#define SPELL_BURNING_ABYSSAL 30511 +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 + +#define SPELL_FIRE_BLAST 37110 + +// count of clickers needed to interrupt blast nova +#define CLICKERS_COUNT 5 + +typedef std::map<uint64, uint64> CubeMap; + +struct mob_abyssalAI : public ScriptedAI +{ + mob_abyssalAI(Creature *c) : ScriptedAI(c) + { + trigger = 0; + Despawn_Timer = 60000; + } + + uint32 FireBlast_Timer; + uint32 Despawn_Timer; + uint32 trigger; + + void Reset() + { + FireBlast_Timer = 6000; + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) + { + DoCast(me, SPELL_BLAZE_TRAP, true); + me->SetVisibility(VISIBILITY_OFF); + Despawn_Timer = 130000; + } + } + + void SetTrigger(uint32 _trigger) + { + trigger = _trigger; + me->SetDisplayId(11686); + if (trigger == 1) //debris + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_DEBRIS_VISUAL, true); + FireBlast_Timer = 5000; + Despawn_Timer = 10000; + } + } + + void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} + void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} + void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} + + void UpdateAI(const uint32 diff) + { + if (trigger) + { + if (trigger == 1) + { + if (FireBlast_Timer <= diff) + { + DoCast(me, SPELL_DEBRIS_DAMAGE, true); + trigger = 3; + } else FireBlast_Timer -= diff; + } + return; + } + + if (Despawn_Timer <= diff) + { + me->ForcedDespawn(); + } else Despawn_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (FireBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRE_BLAST); + FireBlast_Timer = 5000+rand()%10000; + } else FireBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_magtheridonAI : public ScriptedAI +{ + boss_magtheridonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + + // target 7, random target with certain entry spell, need core fix + SpellEntry *TempSpell; + TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) + { + TempSpell->EffectImplicitTargetA[0] = 6; + TempSpell->EffectImplicitTargetB[0] = 0; + } + TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); + if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) + { + TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; + } + } + + CubeMap Cube; + + ScriptedInstance* pInstance; + + uint32 Berserk_Timer; + uint32 Quake_Timer; + uint32 Cleave_Timer; + uint32 BlastNova_Timer; + uint32 Blaze_Timer; + uint32 Debris_Timer; + uint32 RandChat_Timer; + + bool Phase3; + bool NeedCheckCube; + + void Reset() + { + Berserk_Timer = 1320000; + Quake_Timer = 40000; + Debris_Timer = 10000; + Blaze_Timer = 10000+rand()%20000; + BlastNova_Timer = 60000; + Cleave_Timer = 15000; + RandChat_Timer = 90000; + + Phase3 = false; + NeedCheckCube = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->addUnitState(UNIT_STAT_STUNNED); + DoCast(me, SPELL_SHADOW_CAGE_C, true); + } + + void JustReachedHome() + { + if (pInstance) + { + pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); + pInstance->SetData(DATA_COLLAPSE, false); + } + } + + void SetClicker(uint64 cubeGUID, uint64 clickerGUID) + { + // to avoid multiclicks from 1 cube + if (uint64 guid = Cube[cubeGUID]) + DebuffClicker(Unit::GetUnit(*me, guid)); + Cube[cubeGUID] = clickerGUID; + NeedCheckCube = true; + } + + //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) + void DebuffClicker(Unit *clicker) + { + if (!clicker || !clicker->isAlive()) + return; + + clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells + clicker->InterruptNonMeleeSpells(false); + clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); + } + + void NeedCheckCubeStatus() + { + uint32 ClickerNum = 0; + // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) + // if not - apply mind exhaustion and delete from clicker's list + for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) + { + Unit *clicker = Unit::GetUnit(*me, (*i).second); + if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) + { + DebuffClicker(clicker); + (*i).second = 0; + } else ++ClickerNum; + } + + // if 5 clickers from other cubes apply shadow cage + if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_SHADOW_CAGE, true); + } + else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + + if (!ClickerNum) NeedCheckCube = false; + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_PLAYER_KILLED, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); + DoZoneInCombat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); + + DoScriptText(SAY_FREED, me); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (RandChat_Timer <= diff) + { + DoScriptText(RandomTaunt[rand()%6].id, me); + RandChat_Timer = 90000; + } else RandChat_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (NeedCheckCube) NeedCheckCubeStatus(); + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + DoScriptText(EMOTE_BERSERK, me); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + if (BlastNova_Timer <= diff) + { + // to avoid earthquake interruption + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + { + DoScriptText(EMOTE_BLASTNOVA, me); + DoCast(me, SPELL_BLASTNOVA); + BlastNova_Timer = 60000; + } + } else BlastNova_Timer -= diff; + + if (Quake_Timer <= diff) + { + // to avoid blastnova interruption + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_QUAKE_TRIGGER, true); + Quake_Timer = 50000; + } + } else Quake_Timer -= diff; + + if (Blaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) + { + CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); + DoCast(summon, SPELL_BLAZE_TARGET, true); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + Blaze_Timer = 20000 + rand()%20000; + } else Blaze_Timer -= diff; + + if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 + && !me->IsNonMeleeSpellCasted(false) // blast nova + && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake + { + Phase3 = true; + DoScriptText(SAY_CHAMBER_DESTROY, me); + DoCast(me, SPELL_CAMERA_SHAKE, true); + DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); + + if (pInstance) + pInstance->SetData(DATA_COLLAPSE, true); + } + + if (Phase3) + { + if (Debris_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); + } + Debris_Timer = 10000; + } else Debris_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hellfire_channelerAI : public ScriptedAI +{ + mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) + { + pInstance =me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBoltVolley_Timer; + uint32 DarkMending_Timer; + uint32 Fear_Timer; + uint32 Infernal_Timer; + + uint32 Check_Timer; + + void Reset() + { + ShadowBoltVolley_Timer = 8000 + rand()%2000; + DarkMending_Timer = 10000; + Fear_Timer = 15000 + rand()%5000; + Infernal_Timer = 10000 + rand()%40000; + + Check_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); + + me->InterruptNonMeleeSpells(false); + DoZoneInCombat(); + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); + + DoCast(me, SPELL_SHADOW_GRASP_C, false); + } + + void JustSummoned(Creature *summon) + { + summon->AI()->AttackStart(me->getVictim()); + } + + void DamageTaken(Unit*, uint32 &damage) + { + if (damage >= me->GetHealth()) + DoCast(me, SPELL_SOUL_TRANSFER, true); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolley_Timer = 10000 + rand()%10000; + } else ShadowBoltVolley_Timer -= diff; + + if (DarkMending_Timer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + DoCast(me, SPELL_DARK_MENDING); + DarkMending_Timer = 10000 +(rand() % 10000); + } else DarkMending_Timer -= diff; + + if (Fear_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_FEAR); + Fear_Timer = 25000 + rand()%15000; + } else Fear_Timer -= diff; + + if (Infernal_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); + Infernal_Timer = 30000 + rand()%10000; + } else Infernal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Manticron Cube +bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + if (!pInstance) + return true; + if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; + Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); + if (!Magtheridon || !Magtheridon->isAlive()) return true; + + // if exhausted or already channeling return + if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) + return true; + + pPlayer->InterruptNonMeleeSpells(false); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); + CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); + return true; +} + +CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) +{ + return new boss_magtheridonAI(pCreature); +} + +CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) +{ + return new mob_hellfire_channelerAI(pCreature); +} + +CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) +{ + return new mob_abyssalAI(pCreature); +} + +void AddSC_boss_magtheridon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magtheridon"; + newscript->GetAI = &GetAI_boss_magtheridon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_channeler"; + newscript->GetAI = &GetAI_mob_hellfire_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_manticron_cube"; + newscript->pGOHello = &GOHello_go_Manticron_Cube; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abyssal"; + newscript->GetAI = &GetAI_mob_abyssalAI; + newscript->RegisterSelf(); + +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp new file mode 100644 index 00000000000..d5b459a1fa1 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp @@ -0,0 +1,254 @@ +/* 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_Magtheridons_Lair +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 + +#define CHAMBER_CENTER_X -15.14 +#define CHAMBER_CENTER_Y 1.8 +#define CHAMBER_CENTER_Z -0.4 + +#define MAX_ENCOUNTER 2 + +#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" + +struct instance_magtheridons_lair : public ScriptedInstance +{ + instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + } + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 MagtheridonGUID; + std::set<uint64> ChannelerGUID; + uint64 DoorGUID; + std::set<uint64> ColumnGUID; + + uint32 CageTimer; + uint32 RespawnTimer; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + MagtheridonGUID = 0; + ChannelerGUID.clear(); + DoorGUID = 0; + ColumnGUID.clear(); + + CageTimer = 0; + RespawnTimer = 0; + } + + 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 17257: + MagtheridonGUID = pCreature->GetGUID(); + break; + case 17256: + ChannelerGUID.insert(pCreature->GetGUID()); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 181713: + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); + break; + case 183847: + DoorGUID = pGo->GetGUID(); + break; + case 184653: // hall + case 184634: // six columns + case 184635: + case 184636: + case 184637: + case 184638: + case 184639: + ColumnGUID.insert(pGo->GetGUID()); + break; + } + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + case DATA_MAGTHERIDON: + return MagtheridonGUID; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAGTHERIDON_EVENT: + m_auiEncounter[0] = data; + if (data == NOT_STARTED) + RespawnTimer = 10000; + if (data != IN_PROGRESS) + HandleGameObject(DoorGUID, true); + break; + case DATA_CHANNELER_EVENT: + switch(data) + { + case NOT_STARTED: // Reset all channelers once one is reset. + if (m_auiEncounter[1] != NOT_STARTED) + { + m_auiEncounter[1] = NOT_STARTED; + for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + CageTimer = 0; + HandleGameObject(DoorGUID, true); + } + break; + case IN_PROGRESS: // Event start. + if (m_auiEncounter[1] != IN_PROGRESS) + { + m_auiEncounter[1] = IN_PROGRESS; + // Let all five channelers aggro. + for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); + } + // Release Magtheridon after two minutes. + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); + CageTimer = 120000; + } + HandleGameObject(DoorGUID, false); + } + break; + case DONE: // Add buff and check if all channelers are dead. + for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + { + //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); + data = IN_PROGRESS; + break; + } + } + break; + } + m_auiEncounter[1] = data; + break; + case DATA_COLLAPSE: + // true - collapse / false - reset + for (std::set<uint64>::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) + DoUseDoorOrButton(*i); + break; + default: + break; + } + } + + uint32 GetData(uint32 type) + { + if (type == DATA_MAGTHERIDON_EVENT) + return m_auiEncounter[0]; + return 0; + } + + void Update(uint32 diff) + { + if (CageTimer) + { + if (CageTimer <= diff) + { + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->clearUnitState(UNIT_STAT_STUNNED); + Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); + } + CageTimer = 0; + } else CageTimer -= diff; + } + + if (RespawnTimer) + { + if (RespawnTimer <= diff) + { + for (std::set<uint64>::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + RespawnTimer = 0; + } else RespawnTimer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) +{ + return new instance_magtheridons_lair(pMap); +} + +void AddSC_instance_magtheridons_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_magtheridons_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h new file mode 100644 index 00000000000..1b3e525fc54 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h @@ -0,0 +1,14 @@ +/* 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_MAGTHERIDONS_LAIR_H +#define DEF_MAGTHERIDONS_LAIR_H + +#define DATA_MAGTHERIDON_EVENT 1 +#define DATA_MAGTHERIDON 3 +#define DATA_CHANNELER_EVENT 2 +#define DATA_COLLAPSE 6 +#define DATA_CHANNELER 9 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp new file mode 100644 index 00000000000..e3ded52edc9 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp @@ -0,0 +1,396 @@ +/* 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_Grand_Warlock_Nethekurse +SD%Complete: 75 +SDComment: encounter not fully completed. missing part where boss kill minions. +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_grand_warlock_nethekurse +mob_fel_orc_convert +mob_lesser_shadow_fissure +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +struct Say +{ + int32 id; +}; + +static Say PeonAttacked[]= +{ + {-1540001}, + {-1540002}, + {-1540003}, + {-1540004}, +}; +static Say PeonDies[]= +{ + {-1540005}, + {-1540006}, + {-1540007}, + {-1540008}, +}; + +#define SAY_INTRO -1540000 +#define SAY_TAUNT_1 -1540009 +#define SAY_TAUNT_2 -1540010 +#define SAY_TAUNT_3 -1540011 +#define SAY_AGGRO_1 -1540012 +#define SAY_AGGRO_2 -1540013 +#define SAY_AGGRO_3 -1540014 +#define SAY_SLAY_1 -1540015 +#define SAY_SLAY_2 -1540016 +#define SAY_DIE -1540017 + +#define SPELL_DEATH_COIL 30500 +#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D +#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC + +#define SPELL_SHADOW_CLEAVE 30495 +#define H_SPELL_SHADOW_SLAM 35953 + +#define SPELL_HEMORRHAGE 30478 + +#define SPELL_CONSUMPTION 30497 +#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should + +struct boss_grand_warlock_nethekurseAI : public ScriptedAI +{ + boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool IntroOnce; + bool IsIntroEvent; + bool IsMainEvent; + bool SpinOnce; + //bool HasTaunted; + bool Phase; + + uint32 PeonEngagedCount; + uint32 PeonKilledCount; + + uint32 IntroEvent_Timer; + uint32 DeathCoil_Timer; + uint32 ShadowFissure_Timer; + uint32 Cleave_Timer; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + IsIntroEvent = false; + IntroOnce = false; + IsMainEvent = false; + //HasTaunted = false; + SpinOnce = false; + Phase = false; + + PeonEngagedCount = 0; + PeonKilledCount = 0; + + IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? + DeathCoil_Timer = 20000; + ShadowFissure_Timer = 8000; + Cleave_Timer = 5000; + } + + void DoYellForPeonAggro() + { + if (PeonEngagedCount >= 4) + return; + + DoScriptText(PeonAttacked[PeonEngagedCount].id, me); + ++PeonEngagedCount; + } + + void DoYellForPeonDeath() + { + if (PeonKilledCount >= 4) + return; + + DoScriptText(PeonDies[PeonKilledCount].id, me); + ++PeonKilledCount; + + if (PeonKilledCount == 4) + { + IsIntroEvent = false; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void DoTauntPeons() + { + DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); + + //TODO: kill the peons first + IsIntroEvent = false; + PeonEngagedCount = 4; + PeonKilledCount = 4; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* who) + { + if (IsIntroEvent || !IsMainEvent) + return; + + if (me->Attack(who, true)) + { + if (Phase) + DoStartNoMovement(who); + else + DoStartMovement(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) + { + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(SAY_INTRO, me); + IntroOnce = true; + IsIntroEvent = true; + + if (pInstance) + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + + if (IsIntroEvent || !IsMainEvent) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? + summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); + summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_NETHEKURSE,DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); + } + + void UpdateAI(const uint32 diff) + { + if (IsIntroEvent) + { + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + { + if (IntroEvent_Timer <= diff) + DoTauntPeons(); + else + IntroEvent_Timer -= diff; + } + } + + if (!UpdateVictim()) + return; + + if (!IsMainEvent) + return; + + if (Phase) + { + if (!SpinOnce) + { + DoCast(me->getVictim(), SPELL_DARK_SPIN); + SpinOnce = true; + } + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); + Cleave_Timer = 6000+rand()%2500; + } else Cleave_Timer -= diff; + } + else + { + if (ShadowFissure_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_FISSURE); + ShadowFissure_Timer = urand(7500,15000); + } else ShadowFissure_Timer -= diff; + + if (DeathCoil_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_DEATH_COIL); + DeathCoil_Timer = urand(15000,20000); + } else DeathCoil_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) + Phase = true; + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_fel_orc_convertAI : public ScriptedAI +{ + mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 Hemorrhage_Timer; + + void Reset() + { + me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) + Hemorrhage_Timer = 3000; + } + + void MoveInLineOfSight(Unit * /*who*/) + { + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (pInstance->GetData64(DATA_NETHEKURSE)) + { + Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); + if (pKurse && me->IsWithinDist(pKurse, 45.0f)) + { + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + return; + else + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + } + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) + return; + if (pInstance->GetData64(DATA_NETHEKURSE)) + if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Hemorrhage_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Hemorrhage_Timer = 15000; + } else Hemorrhage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//NOTE: this Creature are also summoned by other spells, for different creatures +struct mob_lesser_shadow_fissureAI : public ScriptedAI +{ + mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void MoveInLineOfSight(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) +{ + return new boss_grand_warlock_nethekurseAI (pCreature); +} + +CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) +{ + return new mob_fel_orc_convertAI (pCreature); +} + +CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) +{ + return new mob_lesser_shadow_fissureAI (pCreature); +} + +void AddSC_boss_grand_warlock_nethekurse() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_grand_warlock_nethekurse"; + newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_orc_convert"; + newscript->GetAI = &GetAI_mob_fel_orc_convert; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_shadow_fissure"; + newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp new file mode 100644 index 00000000000..6fa1c9efe33 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp @@ -0,0 +1,404 @@ +/* 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_Warbringer_Omrogg +SD%Complete: 85 +SDComment: Heroic enabled. Spell timing may need additional tweaks +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +mob_omrogg_heads +boss_warbringer_omrogg +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +enum eEnums +{ + YELL_DIE_L = -1540039, + YELL_DIE_R = -1540040, + EMOTE_ENRAGE = -1540041, + + SPELL_BLAST_WAVE = 30600, + SPELL_FEAR = 30584, + SPELL_THUNDERCLAP = 30633, + + SPELL_BURNING_MAUL = 30598, + H_SPELL_BURNING_MAUL = 36056, + + NPC_LEFT_HEAD = 19523, + NPC_RIGHT_HEAD = 19524 +}; + +struct Yell +{ + int32 id; + uint32 creature; +}; + +static Yell GoCombat[]= +{ + {-1540018, NPC_LEFT_HEAD}, + {-1540019, NPC_LEFT_HEAD}, + {-1540020, NPC_LEFT_HEAD}, +}; +static Yell GoCombatDelay[]= +{ + {-1540021, NPC_RIGHT_HEAD}, + {-1540022, NPC_RIGHT_HEAD}, + {-1540023, NPC_RIGHT_HEAD}, +}; + +static Yell Threat[]= +{ + {-1540024, NPC_LEFT_HEAD}, + {-1540025, NPC_RIGHT_HEAD}, + {-1540026, NPC_LEFT_HEAD}, + {-1540027, NPC_LEFT_HEAD}, +}; +static Yell ThreatDelay1[]= +{ + {-1540028, NPC_RIGHT_HEAD}, + {-1540029, NPC_LEFT_HEAD}, + {-1540030, NPC_RIGHT_HEAD}, + {-1540031, NPC_RIGHT_HEAD}, +}; +static Yell ThreatDelay2[]= +{ + {-1540032, NPC_LEFT_HEAD}, + {-1540033, NPC_RIGHT_HEAD}, + {-1540034, NPC_LEFT_HEAD}, + {-1540035, NPC_LEFT_HEAD}, +}; + +static Yell Killing[]= +{ + {-1540036, NPC_LEFT_HEAD}, + {-1540037, NPC_RIGHT_HEAD}, +}; +static Yell KillingDelay[]= +{ + {-1540038, NPC_RIGHT_HEAD}, + {-1000000, NPC_LEFT_HEAD}, +}; + +struct mob_omrogg_headsAI : public ScriptedAI +{ + mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} + + bool DeathYell; + uint32 Death_Timer; + + void Reset() + { + Death_Timer = 4000; + DeathYell = false; + } + void EnterCombat(Unit* /*who*/) {} + + void DoDeathYell() + { + DeathYell = true; + } + + void UpdateAI(const uint32 diff) + { + if (!DeathYell) + return; + + if (Death_Timer <= diff) + { + DoScriptText(YELL_DIE_R, me); + Death_Timer = false; + me->setDeathState(JUST_DIED); + } else Death_Timer -= diff; + } +}; + +struct boss_warbringer_omroggAI : public ScriptedAI +{ + boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) + { + LeftHeadGUID = 0; + RightHeadGUID = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 LeftHeadGUID; + uint64 RightHeadGUID; + int iaggro; + int ithreat; + int ikilling; + + bool AggroYell; + bool ThreatYell; + bool ThreatYell2; + bool KillingYell; + + uint32 Delay_Timer; + uint32 BlastWave_Timer; + uint32 BlastCount; + uint32 Fear_Timer; + uint32 BurningMaul_Timer; + uint32 ThunderClap_Timer; + uint32 ResetThreat_Timer; + + void Reset() + { + if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + pLeftHead->setDeathState(JUST_DIED); + LeftHeadGUID = 0; + } + + if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) + { + pRightHead->setDeathState(JUST_DIED); + RightHeadGUID = 0; + } + + AggroYell = false; + ThreatYell = false; + ThreatYell2 = false; + KillingYell = false; + + Delay_Timer = 4000; + BlastWave_Timer = 0; + BlastCount = 0; + Fear_Timer = 8000; + BurningMaul_Timer = 25000; + ThunderClap_Timer = 15000; + ResetThreat_Timer = 30000; + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. + } + + void DoYellForThreat() + { + Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ithreat = rand()%4; + + Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(Threat[ithreat].id, source); + + Delay_Timer = 3500; + ThreatYell = true; + } + + void EnterCombat(Unit * /*who*/) + { + me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + + if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + iaggro = rand()%3; + + DoScriptText(GoCombat[iaggro].id, pLeftHead); + + Delay_Timer = 3500; + AggroYell = true; + } + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_LEFT_HEAD) + LeftHeadGUID = summoned->GetGUID(); + + if (summoned->GetEntry() == NPC_RIGHT_HEAD) + RightHeadGUID = summoned->GetGUID(); + + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetVisibility(VISIBILITY_OFF); + } + + void KilledUnit(Unit* /*victim*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ikilling = rand()%2; + + Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); + + switch(ikilling) + { + case 0: + DoScriptText(Killing[ikilling].id, source); + Delay_Timer = 3500; + KillingYell = true; + break; + case 1: + DoScriptText(Killing[ikilling].id, source); + KillingYell = false; + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + DoScriptText(YELL_DIE_L, pLeftHead); + + CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (Delay_Timer <= diff) + { + Delay_Timer = 3500; + + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + if (AggroYell) + { + DoScriptText(GoCombatDelay[iaggro].id, pRightHead); + AggroYell = false; + } + + if (ThreatYell2) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay2[ithreat].id, source); + ThreatYell2 = false; + } + + if (ThreatYell) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay1[ithreat].id, source); + ThreatYell = false; + ThreatYell2 = true; + } + + if (KillingYell) + { + Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); + + DoScriptText(KillingDelay[ikilling].id, source); + KillingYell = false; + } + } else Delay_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (BlastCount && BlastWave_Timer <= diff) + { + DoCast(me, SPELL_BLAST_WAVE); + BlastWave_Timer = 5000; + ++BlastCount; + + if (BlastCount == 3) + BlastCount = 0; + } else BlastWave_Timer -= diff; + + if (BurningMaul_Timer <= diff) + { + DoScriptText(EMOTE_ENRAGE, me); + DoCast(me, SPELL_BURNING_MAUL); + BurningMaul_Timer = 40000; + BlastWave_Timer = 16000; + BlastCount = 1; + } else BurningMaul_Timer -= diff; + + if (ResetThreat_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoYellForThreat(); + DoResetThreat(); + me->AddThreat(pTarget, 0.0f); + } + ResetThreat_Timer = 25000+rand()%15000; + } else ResetThreat_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 15000+rand()%20000; + } else Fear_Timer -= diff; + + if (ThunderClap_Timer <= diff) + { + DoCast(me, SPELL_THUNDERCLAP); + ThunderClap_Timer = 15000+rand()%15000; + } else ThunderClap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) +{ + return new boss_warbringer_omroggAI (pCreature); +} + +CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) +{ + return new mob_omrogg_headsAI (pCreature); +} + +void AddSC_boss_warbringer_omrogg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_warbringer_omrogg"; + newscript->GetAI = &GetAI_boss_warbringer_omrogg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_omrogg_heads"; + newscript->GetAI = &GetAI_mob_omrogg_heads; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp new file mode 100644 index 00000000000..b108077518a --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp @@ -0,0 +1,288 @@ +/* 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_Warchief_Kargath_Bladefist +SD%Complete: 90 +SDComment: +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_warchief_kargath_bladefist +EndContentData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO1 -1540042 +#define SAY_AGGRO2 -1540043 +#define SAY_AGGRO3 -1540044 +#define SAY_SLAY1 -1540045 +#define SAY_SLAY2 -1540046 +#define SAY_DEATH -1540047 + +#define SPELL_BLADE_DANCE 30739 +#define H_SPELL_CHARGE 25821 + +#define TARGET_NUM 5 + +#define MOB_SHATTERED_ASSASSIN 17695 +#define MOB_HEARTHEN_GUARD 17621 +#define MOB_SHARPSHOOTER_GUARD 17622 +#define MOB_REAVER_GUARD 17623 + +float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 +float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 +float AddsEntrance[3] = {306.036,-84.29,1.93}; + +struct boss_warchief_kargath_bladefistAI : public ScriptedAI +{ + boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) + { + } + + std::vector<uint64> adds; + std::vector<uint64> assassins; + + uint32 Charge_timer; + uint32 Blade_Dance_Timer; + uint32 Summon_Assistant_Timer; + uint32 resetcheck_timer; + uint32 Wait_Timer; + + uint32 Assassins_Timer; + + uint32 summoned; + bool InBlade; + + uint32 target_num; + + void Reset() + { + removeAdds(); + + me->SetSpeed(MOVE_RUN,2); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + summoned = 2; + InBlade = false; + Wait_Timer = 0; + + Charge_timer = 0; + Blade_Dance_Timer = 45000; + Summon_Assistant_Timer = 30000; + Assassins_Timer = 5000; + resetcheck_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void JustSummoned(Creature *summoned) + { + switch(summoned->GetEntry()) + { + case MOB_HEARTHEN_GUARD: + case MOB_SHARPSHOOTER_GUARD: + case MOB_REAVER_GUARD: + summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); + adds.push_back(summoned->GetGUID()); + break; + case MOB_SHATTERED_ASSASSIN: + assassins.push_back(summoned->GetGUID()); + break; + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + removeAdds(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (InBlade) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id != 1) + return; + + if (target_num > 0) // to prevent loops + { + Wait_Timer = 1; + DoCast(me, SPELL_BLADE_DANCE, true); + target_num--; + } + } + } + + void removeAdds() + { + for (std::vector<uint64>::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + adds.clear(); + + for (std::vector<uint64>::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + assassins.clear(); + } + void SpawnAssassin() + { + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Assassins_Timer) + if (Assassins_Timer <= diff) + { + SpawnAssassin(); + Assassins_Timer = 0; + } else Assassins_Timer -= diff; + + if (InBlade) + { + if (Wait_Timer) + if (Wait_Timer <= diff) + { + if (target_num <= 0) + { + // stop bladedance + InBlade = false; + me->SetSpeed(MOVE_RUN,2); + me->GetMotionMaster()->MoveChase(me->getVictim()); + Blade_Dance_Timer = 30000; + Wait_Timer = 0; + if (IsHeroic()) + Charge_timer = 5000; + } + else + { + //move in bladedance + float x,y,randx,randy; + randx = (rand()%40); + randy = (rand()%40); + x = 210+ randx ; + y = -60- randy ; + me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); + Wait_Timer = 0; + } + } else Wait_Timer -= diff; + } + else + { + if (Blade_Dance_Timer) + if (Blade_Dance_Timer <= diff) + { + target_num = TARGET_NUM; + Wait_Timer = 1; + InBlade = true; + Blade_Dance_Timer = 0; + me->SetSpeed(MOVE_RUN,4); + return; + } else Blade_Dance_Timer -= diff; + + if (Charge_timer) + if (Charge_timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); + Charge_timer = 0; + } else Charge_timer -= diff; + + if (Summon_Assistant_Timer <= diff) + { + for (uint8 i = 0; i < summoned; ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + } + } + if (urand(0,9) < 2) + ++summoned; + Summon_Assistant_Timer = urand(25000,35000); + } else Summon_Assistant_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + if (resetcheck_timer <= diff) + { + uint32 tempx,tempy; + tempx = uint32(me->GetPositionX()); + tempy = uint32(me->GetPositionY()); + if (tempx > 255 || tempx < 205) + { + EnterEvadeMode(); + return; + } + resetcheck_timer = 5000; + } else resetcheck_timer -= diff; + } +}; + +CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) +{ + return new boss_warchief_kargath_bladefistAI (pCreature); +} + +void AddSC_boss_warchief_kargath_bladefist() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_warchief_kargath_bladefist"; + newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp new file mode 100644 index 00000000000..c29df4d6411 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp @@ -0,0 +1,114 @@ +/* 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_Shattered_Halls +SD%Complete: 50 +SDComment: currently missing info about door. instance not complete +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +#define MAX_ENCOUNTER 2 + +#define DOOR_NETHEKURSE 1 + +struct instance_shattered_halls : public ScriptedInstance +{ + instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 nethekurseGUID; + uint64 nethekurseDoorGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + nethekurseGUID = 0; + nethekurseDoorGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 16807: nethekurseGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_NETHEKURSE: + m_auiEncounter[0] = data; + break; + case TYPE_OMROGG: + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_NETHEKURSE: + return m_auiEncounter[0]; + case TYPE_OMROGG: + return m_auiEncounter[1]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_NETHEKURSE: + return nethekurseGUID; + case DATA_NETHEKURSE_DOOR: + return nethekurseDoorGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) +{ + return new instance_shattered_halls(pMap); +} + +void AddSC_instance_shattered_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shattered_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h new file mode 100644 index 00000000000..cbfa23ec4e0 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h @@ -0,0 +1,14 @@ +/* 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_SHATTERED_H +#define DEF_SHATTERED_H + +#define TYPE_NETHEKURSE 1 +#define DATA_NETHEKURSE 2 +#define DATA_NETHEKURSE_DOOR 3 + +#define TYPE_OMROGG 4 +#endif + |
