/* 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_Leotheras_The_Blind SD%Complete: 90% SDComment: Missing proper spawn of inner demons EndScriptData */ #include "../../../sc_defines.h" #include "def_serpent_shrine.h" #define SPELL_WHIRLWIND 40653 #define SPELL_CHAOS_BLAST 37675 // #define SPELL_INSIDIOUS_WHISPER 37676 // useless - dummy effect that can't be implemented #define SPELL_BERSERK 27680 #define SPELL_BERSERKWHIRLWIND 37641 #define INNER_DEMON_ID 21857 // Temporary summon 5 demons in random players with aura #define INNER_DEMON_AURA 37713 // Demonic Alignment aura #define SAY_AGGRO "Finally my banishment ends!" #define SAY_SWITCH_TO_DEMON "Be gone trifling elf. I'm in control now." #define SAY_INNER_DEMONS "We all have our demons..." #define SAY_DEMON_SLAY1 "I have no equal." #define SAY_DEMON_SLAY2 "Perish, mortal." #define SAY_DEMON_SLAY3 "Yes, YES! Ahahah!" #define SAY_NIGHTELF_SLAY1 "Kill! KILL!" #define SAY_NIGHTELF_SLAY2 "That's right! Yes!" #define SAY_NIGHTELF_SLAY3 "Who's the master now?" #define SAY_FINAL_FORM "No! NO! What have you done?! I am the master, do you hear me? I... aaghh... Can't... contain him..." #define SAY_FREE "At last I am liberated. It has been too long since I have tasted true freedom!" #define SAY_DEATH "You cannot kill me! Fools, I'll be back! I'll... aarghh..." #define SOUND_AGGRO 11312 #define SOUND_SWITCH_TO_DEMON 11304 #define SOUND_INNER_DEMONS 11305 #define SOUND_DEMON_SLAY1 11306 #define SOUND_DEMON_SLAY2 11307 #define SOUND_DEMON_SLAY3 11308 #define SOUND_NIGHTELF_SLAY1 11314 #define SOUND_NIGHTELF_SLAY2 11315 #define SOUND_NIGHTELF_SLAY3 11316 #define SOUND_FINAL_FORM 11313 #define SOUND_FREE 11309 #define SOUND_DEATH 11317 #define MODEL_DEMON 14555 #define MODEL_NIGHTELF 20514 #define DEMON_FORM 21845 // BANISH PHASE #define GREEN_BEAM 38909 #define BANISH_EFFECT 37833 float add1SPlace[4] = { 364.219208, -448.394073, 29.515247, 0.170111 }; float add2SPlace[4] = { 375.948334, -426.4744335, 29.524292, 4.982298 }; float add3SPlace[4] = { 396.755188, -433.087402, 30.189342, 3.782232 }; //Original Leotheras the Blind AI struct MANGOS_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI { boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) { pInstance = (c->GetInstanceData()) ? ((ScriptedInstance*)c->GetInstanceData()) : NULL; Demon = 0; initialize(); EnterEvadeMode(); } Creature *add1; Creature *add2; Creature *add3; ScriptedInstance *pInstance; uint32 Whirlwind_Timer; uint32 ChaosBlast_Timer; uint32 Switch_Timer; uint32 Berserk_Timer; uint32 Berserk_Whirlwind_Timer; bool DemonForm; bool IsFinalForm; bool InCombat; bool Berserk; bool spawned; bool relased; bool channeling[3]; bool add1Dead; bool add2Dead; bool add3Dead; uint64 Demon; void initialize() { relased = false; spawned = false; relased = false; for(uint8 i = 0; i < 3; ++i) channeling[i] = false; add1Dead = false; add2Dead = false; add3Dead = false; add1 = NULL; add2 = NULL; add3 = NULL; } void Reset() { Whirlwind_Timer = 20000; ChaosBlast_Timer = 1000; Switch_Timer = 45000; Berserk_Timer = 600000; Berserk_Whirlwind_Timer = 15000; DemonForm = false; IsFinalForm = false; InCombat = false; Berserk = false; m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); //m_creature->RemoveAllAuras(); //m_creature->DeleteThreatList(); //m_creature->CombatStop(); //DoGoHome(); if(pInstance) pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 0); } void StartEvent() { if(!relased) { m_creature->CombatStop(); return; } DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_AGGRO); if(pInstance) pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 1); InCombat = true; } void KilledUnit(Unit *victim) { if(victim->GetTypeId() != TYPEID_PLAYER) return; if(DemonForm) switch(rand()%3) { case 0: DoYell(SAY_DEMON_SLAY1, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY1); break; case 1: DoYell(SAY_DEMON_SLAY2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY2); break; case 2: DoYell(SAY_DEMON_SLAY3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY3); break; } else switch(rand()%3) { case 0: DoYell(SAY_NIGHTELF_SLAY1, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_NIGHTELF_SLAY1); break; case 1: DoYell(SAY_NIGHTELF_SLAY2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_NIGHTELF_SLAY2); break; case 2: DoYell(SAY_NIGHTELF_SLAY3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_NIGHTELF_SLAY3); break; } } void JustDied(Unit *victim) { DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEATH); //despawn copy if(Demon) { Unit *pUnit = NULL; pUnit = Unit::GetUnit((*m_creature), Demon); if(pUnit) pUnit->DealDamage(pUnit, pUnit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, false); } if(pInstance) pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, 0); // ustawia wskazniki add1,add2,add3 na NULl, spawned = false itd. (bez tego po respawnie nie było by addów) initialize(); } void AttackStart(Unit *who) { if(!who && who != m_creature) return; if (who->isTargetableForAttack() && who!= m_creature) { //Begin melee attack if we are within range DoStartMeleeAttack(who); if(!InCombat) 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) StartEvent(); } } } // VICTIMSTATE_DODGE void UpdateAI(const uint32 diff) { banishPhase(); //Return since we have no target if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) return; if(!DemonForm) { //Whirlwind_Timer if(Whirlwind_Timer < diff) { DoCast(m_creature, SPELL_WHIRLWIND); Whirlwind_Timer = 25000; ResetThreat(); }else Whirlwind_Timer -= diff; if(Berserk == true && Berserk_Whirlwind_Timer < diff) { DoCast(m_creature, SPELL_BERSERKWHIRLWIND); Berserk_Whirlwind_Timer = 20000; ResetThreat(); }else Berserk_Whirlwind_Timer -=diff; //Switch_Timer if(!IsFinalForm) if(Switch_Timer < diff) { //switch to demon form m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON); DoYell(SAY_SWITCH_TO_DEMON, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_SWITCH_TO_DEMON); ResetThreat(); DemonForm = true; Unit* Spawn = NULL; Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); Spawn = m_creature->SummonCreature(INNER_DEMON_ID, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 600000); Switch_Timer = 60000; }else Switch_Timer -= diff; DoMeleeAttackIfReady(); } else { //ChaosBlast_Timer if(ChaosBlast_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_CHAOS_BLAST); ChaosBlast_Timer = 1500; }else ChaosBlast_Timer -= diff; //Switch_Timer if(Switch_Timer < diff) { //switch to nightelf form m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); DemonForm = false; Switch_Timer = 45000; }else Switch_Timer -= diff; //WIPE after 10 minutes if(Berserk_Timer < diff) { DoCast(m_creature, SPELL_BERSERK); Berserk_Timer = 600000; Berserk = true; }else Berserk_Timer -=diff; } if(!IsFinalForm && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 15) { //at this point he divides himself in two parts Creature *Copy = NULL; Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); if(Copy) { Demon = Copy->GetGUID(); Copy->AI()->AttackStart(m_creature->getVictim()); } //set nightelf final form IsFinalForm = true; DemonForm = false; DoYell(SAY_FINAL_FORM, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_FINAL_FORM); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); } } void ResetThreat() { std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); std::list::iterator i = m_threatlist.begin(); for(i = m_threatlist.begin(); i != m_threatlist.end(); ++i) { Unit* pUnit = NULL; pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); if(pUnit) { m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); } } } void banishPhase() { // Banish Phase by Krz (just educational code ^_^) // ---------- BANISH PHASE START ---------- if(!spawned) { m_creature->ApplySpellImmune(BANISH_EFFECT,IMMUNITY_MECHANIC,MECHANIC_BANISH,false); // żeby mógł rzucić banisha - Ustawione na true podczas relase add1 = m_creature->SummonCreature(21806, add1SPlace[0], add1SPlace[1],add1SPlace[2],add1SPlace[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,1000); add2 = m_creature->SummonCreature(21806, add2SPlace[0], add2SPlace[1],add2SPlace[2],add2SPlace[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,1000); add3 = m_creature->SummonCreature(21806, add3SPlace[0], add3SPlace[1],add3SPlace[2],add3SPlace[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,1000); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON); // DemonModel - Blizzlike banishment DoCast(m_creature, BANISH_EFFECT); // selfCast banisha spawned = true; } // Zacznš castować tylko gdy nie sš w combacie (jak wejdš w combat to channeling[] = false, żeby w razie gdy zabijš cel to powrócš i znów wycastujš ten channeling spell if(!add1 == NULL) { // odwróci je w stronę blinda - Visual bug... trzeba się odsunšc i wrócić, to wtedy będš odwrócone -_- if(add1->GetPositionX() == add1SPlace[0] && add1->GetPositionY() == add1SPlace[1] && add1->GetPositionZ() == add1SPlace[2] && add1->GetOrientation() != add1SPlace[3] ) add1->SetOrientation(add1SPlace[3]); /* Unit *target = add1->getVictim(); if(target) <- test, żeby addy castowały shocka tylko jak cel castuje ( pozniej przerobie na random.target@threatlist ale chcialem sprawdzic czy zadziala wykrywanie casta if(target->m_currentSpells[3] || target->m_currentSpells[2] || target->m_currentSpells[1])//->getState() == 2 && target)//->getState() == 2 && target) add1->CastSpell(add1->getVictim(), 39076, false); */ if(!channeling[0] && !add1->isInCombat()) { add1->CastSpell(m_creature,GREEN_BEAM,false); channeling[0] = true; } if(add1->isInCombat() && channeling[0] == true) { channeling[0] = false; add1->InterruptSpell(CURRENT_CHANNELED_SPELL, true); if(!add2 == NULL) if(!add2->isInCombat()) add2->getThreatManager().addThreat(add1->getVictim(),1); if(!add3 == NULL) if(!add3->isInCombat()) add3->getThreatManager().addThreat(add1->getVictim(),1); } if(add1->GetHealth() == 0) { add1Dead = true; add1 = NULL; } } if(!add2 == NULL) { if(add2->GetPositionX() == add2SPlace[0] && add2->GetPositionY() == add2SPlace[1] && add2->GetPositionZ() == add2SPlace[2] && add2->GetOrientation() != add2SPlace[3] ) add2->SetOrientation(add2SPlace[3]); if(!channeling[1] && !add2->isInCombat()) { add2->CastSpell(m_creature,GREEN_BEAM,false); channeling[1] = true; } if(add2->isInCombat() && channeling[1] == true) { channeling[1] = false; add2->InterruptSpell(CURRENT_CHANNELED_SPELL, true); if(!add1 == NULL) if(!add1->isInCombat()) add1->getThreatManager().addThreat(add2->getVictim(),1); if(!add3 == NULL) if(!add3->isInCombat()) add3->getThreatManager().addThreat(add2->getVictim(),1); } if(add2->GetHealth() == 0) { add2Dead = true; add2 = NULL; } } if(!add3 == NULL) { if(add3->GetPositionX() == add3SPlace[0] && add3->GetPositionY() == add3SPlace[1] && add3->GetPositionZ() == add3SPlace[2] && add3->GetOrientation() != add3SPlace[3] ) add3->SetOrientation(add3SPlace[3]); if(!channeling[2] && !add3->isInCombat()) { add3->CastSpell(m_creature,GREEN_BEAM,false); channeling[2] = true; } if(add3->isInCombat() && channeling[2] == true) { channeling[2] = false; add3->InterruptSpell(CURRENT_CHANNELED_SPELL, true); //zaatakuja wszystkie gdy 1 wejdzie w combat if(!add1 == NULL) if(!add1->isInCombat()) add1->getThreatManager().addThreat(add3->getVictim(),1); if(!add2 == NULL) if(!add2->isInCombat()) add2->getThreatManager().addThreat(add3->getVictim(),1); } if(add3->GetHealth() == 0) { add3Dead = true; add3 = NULL; } } if(add1Dead && add2Dead && add3Dead) { m_creature->RemoveAllAuras(); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); m_creature->ApplySpellImmune(37546,IMMUNITY_MECHANIC,MECHANIC_BANISH,true); relased = true; add1Dead = false; add2Dead = false; add3Dead = false; } // ---------- BANISH PHASE END ---------- } }; //Leotheras the Blind Demon Form AI struct MANGOS_DLL_DECL boss_leotheras_the_blind_demonformAI : public ScriptedAI { boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) { InCombat = false; EnterEvadeMode(); } uint32 ChaosBlast_Timer; bool InCombat; void Reset() { ChaosBlast_Timer = 1000; InCombat = false; //m_creature->RemoveAllAuras(); //m_creature->DeleteThreatList(); //m_creature->CombatStop(); //DoGoHome(); } void StartEvent() { DoYell(SAY_FREE, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_FREE); InCombat = true; } void KilledUnit(Unit *victim) { if(victim->GetTypeId() != TYPEID_PLAYER) return; switch(rand()%3) { case 0: DoYell(SAY_DEMON_SLAY1, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY1); break; case 1: DoYell(SAY_DEMON_SLAY2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY2); break; case 2: DoYell(SAY_DEMON_SLAY3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_DEMON_SLAY3); break; } } void JustDied(Unit *victim) { //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) m_creature->CastSpell(m_creature, 8149, true); } void AttackStart(Unit *who) { if(!who && who != m_creature) return; if (who->isTargetableForAttack() && who!= m_creature) { //Begin melee attack if we are within range DoStartMeleeAttack(who); if(!InCombat) 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) StartEvent(); } } } void UpdateAI(const uint32 diff) { //Return since we have no target if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) return; //ChaosBlast_Timer if(ChaosBlast_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_CHAOS_BLAST); ChaosBlast_Timer = 1500; }else ChaosBlast_Timer -= diff; //Do NOT deal any melee damage to the target. } }; CreatureAI* GetAI_boss_leotheras_the_blind(Creature *_Creature) { return new boss_leotheras_the_blindAI (_Creature); } CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature *_Creature) { return new boss_leotheras_the_blind_demonformAI (_Creature); } void AddSC_boss_leotheras_the_blind() { Script *newscript; newscript = new Script; newscript->Name="boss_leotheras_the_blind"; newscript->GetAI = GetAI_boss_leotheras_the_blind; m_scripts[nrscripts++] = newscript; newscript = new Script; newscript->Name="boss_leotheras_the_blind_demonform"; newscript->GetAI = GetAI_boss_leotheras_the_blind_demonform; m_scripts[nrscripts++] = newscript; }