/* Copyright (C) 2006 - 2008 ScriptDev2 * 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_moroes SD%Complete: 100 SDComment: EndScriptData */ #include "def_karazhan.h" #include "../../../../../game/TargetedMovementGenerator.h" #include "../../../../../game/IdleMovementGenerator.h" #define SAY_AGGRO "Hmm, unannounced visitors? Preparations must be made." #define SOUND_AGGRO 9211 #define SAY_SPECIAL_1 "Now, where was I? Oh yes..." #define SOUND_SPECIAL_1 9215 #define SAY_SPECIAL_2 "You rang?" #define SOUND_SPECIAL_2 9316 #define SAY_KILL_1 "One more for dinner this evening" #define SOUND_KILL_1 9214 #define SAY_KILL_2 "Time... Never enough time." #define SOUND_KILL_2 9314 #define SAY_KILL_3 "I've gone and made a mess." #define SOUND_KILL_3 9315 #define SAY_DEATH "How terribly clumsy of me..." #define SOUND_DEATH 9213 #define SPELL_VANISH 41476 #define SPELL_GARROTE 37066 #define SPELL_BLIND 34654 #define SPELL_GOUGE 28456 #define SPELL_ENRAGE 19953 #define ORIENT 4.5784 #define SPAWN1_X -10976.27929 #define SPAWN1_Y -1878.17358 #define SPAWN1_Z 81.73 #define SPAWN2_X -10979.7587 #define SPAWN2_Y -1877.8706 #define SPAWN2_Z 81.73 #define SPAWN3_X -10985.665 #define SPAWN3_Y -1877.2458 #define SPAWN3_Z 81.73 #define SPAWN4_X -10989.136719 #define SPAWN4_Y -1876.8309 #define SPAWN4_Z 81.73 uint32 Adds[6] = {19875, 19874, 19872, 17007, 19876, 19873}; uint64 AddGuid[4] = {0,0,0,0}; uint32 AddType[4] = {0,0,0,0}; struct MANGOS_DLL_DECL boss_moroesAI : public ScriptedAI { boss_moroesAI(Creature *c) : ScriptedAI(c) { pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; EnterEvadeMode(); } ScriptedInstance *pInstance; uint32 Vanish_Timer; uint32 Blind_Timer; uint32 Gouge_Timer; uint32 Wait_Timer; uint32 CheckAdds_Timer; bool InCombat; bool InVanish; bool Enrage; void Reset() { Vanish_Timer = 52000; Blind_Timer = 35000; Gouge_Timer = 23000; Wait_Timer = 999999999; CheckAdds_Timer = 5000; InCombat = false; Enrage = false; InVanish = false; DeSpawnAdds(); SpawnAdds(); if (pInstance) pInstance->SetData(DATA_MOROES_EVENT, 0); } void StartEvent() { if (!pInstance) return; DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_AGGRO); if (pInstance) pInstance->SetData(DATA_MOROES_EVENT, 1); } void Aggro(Unit *who) { StartEvent(); } void MoveInLineOfSight(Unit *who) { if (!who || m_creature->getVictim()) return; if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) { float attackRadius = m_creature->GetAttackDistance(who); if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) { if (who->HasStealthAura()) who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); DoStartMeleeAttack(who); if (!InCombat) { DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_AGGRO); InCombat = true; AddsAttack(); } } } } void KilledUnit(Unit *victim) { switch (rand()%3) { case 0: DoYell(SAY_KILL_1, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(victim, SOUND_KILL_1); break; case 1: DoYell(SAY_KILL_2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(victim, SOUND_KILL_2); break; case 2: DoYell(SAY_KILL_3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(victim, SOUND_KILL_3); break; } } void JustDied(Unit *victim) { DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(NULL, SOUND_DEATH); if (pInstance) pInstance->SetData(DATA_MOROES_EVENT, 0); DeSpawnAdds(); } void SpawnAdds() { uint32 i1; uint32 i2; uint32 i3; uint32 i = rand()%6; Unit *pCreature; if (AddType[0]) { pCreature = m_creature->SummonCreature(AddType[0], SPAWN1_X, SPAWN1_Y, SPAWN1_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); i1 = i; } else { pCreature = m_creature->SummonCreature(Adds[i], SPAWN1_X, SPAWN1_Y, SPAWN1_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); AddType[0] = Adds[i]; } AddGuid[0] = pCreature->GetGUID(); while (i == i1) { i = rand()%6; } if (AddType[1]) pCreature = m_creature->SummonCreature(AddType[1], SPAWN2_X, SPAWN2_Y, SPAWN2_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); else { pCreature = m_creature->SummonCreature(Adds[i], SPAWN2_X, SPAWN2_Y, SPAWN2_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); AddType[1] = Adds[i]; } AddGuid[1] = pCreature->GetGUID(); i2 = i; while (i == i1 || i == i2) { i = rand()%6; } if (AddType[2]) pCreature = m_creature->SummonCreature(AddType[2], SPAWN3_X, SPAWN3_Y, SPAWN3_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); else { pCreature = m_creature->SummonCreature(Adds[i], SPAWN3_X, SPAWN3_Y, SPAWN3_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); AddType[2] = Adds[i]; } AddGuid[2] = pCreature->GetGUID(); i3 = i; while (i == i1 || i == i2 || i == i3) { i = rand()%6; } if (AddType[3]) pCreature = m_creature->SummonCreature(AddType[3], SPAWN4_X, SPAWN4_Y, SPAWN4_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); else { pCreature = m_creature->SummonCreature(Adds[i], SPAWN4_X, SPAWN4_Y, SPAWN4_Z, ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 60000); AddType[3] = Adds[i]; } AddGuid[3] = pCreature->GetGUID(); } void DeSpawnAdds() { for (uint32 i =0;i<4;i++) { Unit *Temp; if (AddGuid[i]) { Temp = Unit::GetUnit((*m_creature),AddGuid[i]); if (Temp) Temp->DealDamage(Temp, Temp->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, false); } } } void AddsAttack() { if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 99) for (uint32 i =0;i<4;i++) { Unit *Temp; if (AddGuid[i]) { Temp = Unit::GetUnit((*m_creature),AddGuid[i]); if (Temp && Temp->isAlive()) ((Creature*)Temp)->AI()->AttackStart(m_creature->getVictim()); else EnterEvadeMode(); } } } void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) return; if (pInstance && !pInstance->GetData(DATA_MOROES_EVENT)) EnterEvadeMode(); if (!Enrage && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) { DoCast(m_creature, SPELL_ENRAGE); Enrage = true; } if (CheckAdds_Timer < diff) { for (uint32 i =0;i<4;i++) { Unit *Temp; if (AddGuid[i]) { Temp = Unit::GetUnit((*m_creature),AddGuid[i]); if (Temp && Temp->isAlive()) if (!Temp->SelectHostilTarget() || !Temp->getVictim() ) ((Creature*)Temp)->AI()->AttackStart(m_creature->getVictim()); } } CheckAdds_Timer = 5000; }else CheckAdds_Timer -= diff; if (!Enrage) { //Cast Vanish, then Garrote random victim if (Vanish_Timer < diff) { m_creature->setFaction(35); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoCast(m_creature, SPELL_VANISH); InVanish = true; Vanish_Timer = 60000; Wait_Timer = 5000; }else Vanish_Timer -= diff; if (Wait_Timer < diff) { Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); if (target) target->CastSpell(target, SPELL_GARROTE, true); m_creature->setFaction(14); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); InVanish = false; Wait_Timer = 999999999; }else Wait_Timer -= diff; //Blind highest aggro, and attack second highest if (Gouge_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_GOUGE); Unit *target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); if (target) m_creature->getThreatManager().modifyThreatPercent(target,-100); Gouge_Timer = 40000; }else Gouge_Timer -= diff; if (Blind_Timer < diff) { Unit *target; std::list t_list = m_creature->getThreatManager().getThreatList(); std::vector target_list; for (std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); if (target && target->GetDistance2dSq(m_creature) < 25) target_list.push_back(target); target = NULL; } if (target_list.size()) target = *(target_list.begin()+rand()%target_list.size()); DoCast(target, SPELL_BLIND); Blind_Timer = 40000; }else Blind_Timer -= diff; } if (!InVanish) DoMeleeAttackIfReady(); } }; #define SPELL_MANABURN 29405 #define SPELL_MINDFLY 29570 #define SPELL_SWPAIN 34441 #define SPELL_SHADOWFORM 29406 struct MANGOS_DLL_DECL boss_baroness_dorothea_millstipeAI : public ScriptedAI { //Shadow Priest boss_baroness_dorothea_millstipeAI(Creature *c) : ScriptedAI(c) { pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; EnterEvadeMode(); } ScriptedInstance *pInstance; uint32 ManaBurn_Timer; uint32 MindFlay_Timer; uint32 ShadowWordPain_Timer; bool InCombat; void Reset() { ManaBurn_Timer = 7000; MindFlay_Timer = 1000; ShadowWordPain_Timer = 6000; InCombat = false; if (pInstance) pInstance->SetData(DATA_MOROES_EVENT, 0); } void Aggro(Unit *who) { return; } void MoveInLineOfSight(Unit *who) { if (!who || m_creature->getVictim()) return; if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) { float attackRadius = m_creature->GetAttackDistance(who); if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) { if (who->HasStealthAura()) who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); DoStartMeleeAttack(who); if (!InCombat) { InCombat=true; DoCast(m_creature,SPELL_SHADOWFORM); if (pInstance) pInstance->SetData(DATA_MOROES_EVENT, 1); } } } } void KilledUnit(Unit *victim) { } void JustDied(Unit *victim) { } void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) return; if (pInstance && !pInstance->GetData(DATA_MOROES_EVENT)) EnterEvadeMode(); if (MindFlay_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_MINDFLY); MindFlay_Timer = 12000; //3sec channeled }else MindFlay_Timer -= diff; if (ManaBurn_Timer < diff) { Unit *target; std::list t_list = m_creature->getThreatManager().getThreatList(); std::vector target_list; for (std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()); if (target && target->GetPower(POWER_MANA)) { DoCast(target,SPELL_MANABURN); itr= t_list.end(); } } ManaBurn_Timer = 5000; //3 sec cast }else ManaBurn_Timer -= diff; if (ShadowWordPain_Timer < diff) { Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); if (target) DoCast(m_creature->getVictim(),SPELL_SWPAIN); ShadowWordPain_Timer = 7000; }else ShadowWordPain_Timer -= diff; DoMeleeAttackIfReady(); } }; CreatureAI* GetAI_boss_moroes(Creature *_Creature) { return new boss_moroesAI (_Creature); } CreatureAI* GetAI_baroness_dorothea_millstipe(Creature *_Creature) { return new boss_baroness_dorothea_millstipeAI (_Creature); } void AddSC_boss_moroes() { Script *newscript; newscript = new Script; newscript->Name="boss_moroes"; newscript->GetAI = GetAI_boss_moroes; m_scripts[nrscripts++] = newscript; newscript = new Script; newscript->Name="baroness_dorothea_millstipe"; newscript->GetAI = GetAI_baroness_dorothea_millstipe; m_scripts[nrscripts++] = newscript; }