/* 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 Inner Demons proper spawn's
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;
}