[svn] Add Alar script.

Update Magtheridon script.
Update Vorpil script. Patch provided by BroodWyrm.
Add sunwell boss scripts into scriptmgr.cpp (forgot to do so in previous revs).

--HG--
branch : trunk
This commit is contained in:
megamage
2008-10-20 14:02:13 -05:00
parent 4f06be912b
commit 717cfa01f0
15 changed files with 1531 additions and 512 deletions

View File

@@ -337,6 +337,7 @@ scripts/zone/tempest_keep/arcatraz/instance_arcatraz.cpp \
scripts/zone/tempest_keep/botanica/boss_high_botanist_freywinn.cpp \
scripts/zone/tempest_keep/botanica/boss_laj.cpp \
scripts/zone/tempest_keep/botanica/boss_warp_splinter.cpp \
scripts/zone/tempest_keep/the_eye/boss_alar.cpp \
scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp \
scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp \
scripts/zone/tempest_keep/the_eye/boss_void_reaver.cpp \

View File

@@ -495,6 +495,13 @@ extern void AddSC_instance_stratholme();
extern void AddSC_stratholme();
//Sunken Temple
//Sunwell Plateau
extern void AddSC_instance_sunwell_plateau();
extern void AddSC_boss_kalecgos();
extern void AddSC_boss_brutallus();
extern void AddSC_boss_felmyst();
extern void AddSC_boss_eredar_twins();
//Tanaris
extern void AddSC_tanaris();
@@ -511,6 +518,7 @@ extern void AddSC_boss_laj();
extern void AddSC_boss_warp_splinter();
//--The Eye
extern void AddSC_boss_alar();
extern void AddSC_boss_kaelthas();
extern void AddSC_boss_void_reaver();
extern void AddSC_boss_high_astromancer_solarian();
@@ -1677,6 +1685,13 @@ void ScriptsInit()
AddSC_stratholme();
//Sunken Temple
//Sunwell Plateau
AddSC_instance_sunwell_plateau();
AddSC_boss_kalecgos();
AddSC_boss_brutallus();
AddSC_boss_felmyst();
AddSC_boss_eredar_twins();
//Tanaris
AddSC_tanaris();
@@ -1693,6 +1708,7 @@ void ScriptsInit()
AddSC_boss_warp_splinter();
//--The Eye
AddSC_boss_alar();
AddSC_boss_kaelthas();
AddSC_boss_void_reaver();
AddSC_boss_high_astromancer_solarian();

View File

@@ -1520,6 +1520,10 @@
<Filter
Name="The Eye"
>
<File
RelativePath="..\scripts\zone\tempest_keep\the_eye\boss_alar.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\tempest_keep\the_eye\boss_astromancer.cpp"
>

View File

@@ -1753,6 +1753,10 @@
<Filter
Name="The Eye"
>
<File
RelativePath="..\scripts\zone\tempest_keep\the_eye\boss_alar.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\tempest_keep\the_eye\boss_astromancer.cpp"
>

View File

@@ -1751,6 +1751,10 @@
<Filter
Name="The Eye"
>
<File
RelativePath="..\scripts\zone\tempest_keep\the_eye\boss_alar.cpp"
>
</File>
<File
RelativePath="..\scripts\zone\tempest_keep\the_eye\boss_astromancer.cpp"
>

View File

@@ -16,265 +16,268 @@
/* ScriptData
SDName: Boss_Grandmaster_Vorpil
SD%Complete: 75
SDComment: Despawn all summoned on death not implemented. Void Traveler effects not implemented.
SD%Complete: 100
SDComment:
SDCategory: Auchindoun, Shadow Labyrinth
EndScriptData */
#include "precompiled.h"
#include "def_shadow_labyrinth.h"
#define SPELL_DRAW_SHADOWS 33563
#define SPELL_VOID_PORTAL_A 33566 //spell only summon one unit, but we use it for the visual effect and summon the 4 other portals manual way(only one spell exist)
#define SPELL_VOID_PORTAL_VISUAL 33569
#define SPELL_SHADOW_BOLT_VOLLEY 32963
#define SPELL_SUMMON_VOIDWALKER_A 33582
#define SPELL_SUMMON_VOIDWALKER_B 33583
#define SPELL_SUMMON_VOIDWALKER_C 33584
#define SPELL_SUMMON_VOIDWALKER_D 33585
#define SPELL_SUMMON_VOIDWALKER_E 33586
#define SPELL_RAIN_OF_FIRE 33617
#define H_SPELL_RAIN_OF_FIRE 39363
#define H_SPELL_BANISH 38791
#define SAY_INTRO "Keep your minds focused for the days of reckoning are close at hand. Soon, the destroyer of worlds will return to make good on his promise. Soon the destruction of all that is will begin!"
#define SAY_AGGRO1 "I'll make an offering of your blood!"
#define SAY_AGGRO2 "You'll be a fine example, for the others."
#define SAY_AGGRO3 "Good, a worthy sacrifice."
#define SAY_HELP "Come to my aid, heed your master now!"
#define SAY_SLAY1 "I serve with pride."
#define SAY_SLAY2 "Your death is for the greater cause!"
#define SAY_DEATH "I give my life... Gladly."
#define SAY_INTRO "Keep your minds focused for the days of reckoning are close at hand. Soon, the destroyer of worlds will return to make good on his promise. Soon the destruction of all that is will begin!"
#define SAY_AGGRO1 "I'll make an offering of your blood!"
#define SAY_AGGRO2 "You'll be a fine example, for the others."
#define SAY_AGGRO3 "Good, a worthy sacrifice."
#define SAY_HELP "Come to my aid, heed your master now!"
#define SAY_SLAY1 "I serve with pride."
#define SAY_SLAY2 "Your death is for the greater cause!"
#define SAY_DEATH "I give my life... Gladly."
#define SOUND_INTRO 10522
#define SOUND_AGGRO1 10524
#define SOUND_AGGRO2 10525
#define SOUND_AGGRO3 10526
#define SOUND_HELP 10523
#define SOUND_SLAY1 10527
#define SOUND_SLAY2 10528
#define SOUND_DEATH 10529
#define SOUND_INTRO 10522
#define SOUND_AGGRO1 10524
#define SOUND_AGGRO2 10525
#define SOUND_AGGRO3 10526
#define SOUND_HELP 10523
#define SOUND_SLAY1 10527
#define SOUND_SLAY2 10528
#define SOUND_DEATH 10529
#define SPELL_RAIN_OF_FIRE 33617
#define H_SPELL_RAIN_OF_FIRE 39363
#define ENTRY_VOID_PORTAL 19224
#define ENTRY_VOID_TRAVELER 19226
#define SPELL_DRAWN_SHADOWS 33563
#define SPELL_SHADOWBOLT_VOLLEY 33841
#define LOCX -253.06f
#define LOCY -264.02f
#define LOCZ 17.08
#define MOB_VOID_TRAVELER 19226
#define SPELL_SACRIFICE 33587
#define SPELL_SHADOW_NOVA 33846
#define SPELL_HEALVORPIL 33783
#define H_SPELL_HEALVORPIL 39364
#define MOB_VOID_PORTAL 19224
#define SPELL_VOID_PORTAL_VISUAL 33569
float VorpilPosition[1][3] =
{
{-252.8820,-264.3030,17.1}
};
float VoidPortalCoords[5][3] =
{
{-283.5894, -239.5718, 12.7},
{-306.5853, -258.4539, 12.7},
{-295.8789, -269.0899, 12.7},
{-209.3401, -262.7564, 17.1},
{-261.4533, -297.3298, 17.1}
};
struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
{
boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Intro = false;
Reset();
}
ScriptedInstance* pInstance;
bool HeroicMode;
uint32 ShadowBoltVolley_Timer;
uint32 DrawShadows_Timer;
uint32 Teleport_Timer;
uint32 VoidTraveler_Timer;
uint32 Banish_Timer;
ScriptedInstance *pInstance;
bool Intro;
bool Teleport;
bool sumportals;
bool HeroicMode;
uint32 ShadowBoltVolley_Timer;
uint32 DrawnShadows_Timer;
uint32 sumportals_Timer;
uint32 summonTraveler_Timer;
uint64 PortalsGuid[5];
void summonPortals()
{
for (int i = 0;i<5;i++)
{
Creature *Portal = NULL;
Portal = m_creature->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000);
PortalsGuid[i] = Portal->GetGUID();
Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false);
}
sumportals = true;
summonTraveler_Timer = 5000;
}
void destroyPortals()
{
for (int i = 0;i < 5; i ++)
{
Unit *Portal = Unit::GetUnit((*m_creature), PortalsGuid[i]);
if (Portal)
if (Portal->isAlive())
Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
PortalsGuid[i] = 0;
}
}
void spawnVoidTraveler()
{
srand( (unsigned) time(NULL) ) ;
int pos = rand()%5;
Creature *traveler;
traveler = m_creature->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000);
}
void Reset()
{
HeroicMode = m_creature->GetMap()->IsHeroic();
if( HeroicMode )
debug_log("SD2: creature %u is in heroic mode",m_creature->GetEntry());
ShadowBoltVolley_Timer = 15000;
DrawShadows_Timer = 40000;
Teleport_Timer = 1000;
VoidTraveler_Timer = 20000;
Banish_Timer = 25000;
Intro = false;
Teleport = false;
DrawnShadows_Timer = 45000;
sumportals_Timer = 10000;
summonTraveler_Timer = 90000;
if( pInstance )
InCombat = false;
sumportals = false;
destroyPortals();
if(pInstance)
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED);
}
void MoveInLineOfSight(Unit *who)
{
if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) )
{
//not sure about right radius
if(!Intro && m_creature->IsWithinDistInMap(who, 50))
{
DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_INTRO);
DoCast(m_creature, SPELL_VOID_PORTAL_A,true);
m_creature->SummonCreature(ENTRY_VOID_PORTAL,-262.40,-229.57,17.08,0,TEMPSUMMON_CORPSE_DESPAWN,0);
m_creature->SummonCreature(ENTRY_VOID_PORTAL,-260.35,-297.56,17.08,0,TEMPSUMMON_CORPSE_DESPAWN,0);
m_creature->SummonCreature(ENTRY_VOID_PORTAL,-292.05,-270.37,12.68,0,TEMPSUMMON_CORPSE_DESPAWN,0);
m_creature->SummonCreature(ENTRY_VOID_PORTAL,-301.64,-255.97,12.68,0,TEMPSUMMON_CORPSE_DESPAWN,0);
Intro = true;
}
if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
float attackRadius = m_creature->GetAttackDistance(who);
if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) )
{
DoStartAttackAndMovement(who);
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
if (!InCombat)
{
InCombat = true;
Aggro(who);
}
}
}
}
void Aggro(Unit *who)
{
switch(rand()%3)
{
case 0:
DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO1);
break;
case 1:
DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO2);
break;
case 2:
DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO3);
break;
}
if( pInstance )
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS);
}
void KilledUnit(Unit *victim)
{
switch(rand()%2)
{
case 0:
DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_SLAY1);
break;
DoYell(SAY_SLAY1, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_SLAY1);
break;
case 1:
DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_SLAY2);
break;
DoYell(SAY_SLAY2, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_SLAY2);
break;
}
}
void JustSummoned(Creature *summoned)
{
if( summoned->GetEntry() == ENTRY_VOID_TRAVELER )
{
summoned->GetMotionMaster()->MoveChase(m_creature);
summoned->SetSpeed(MOVE_WALK,0.8,true);
}
if( summoned->GetEntry() == ENTRY_VOID_PORTAL )
summoned->CastSpell(summoned,SPELL_VOID_PORTAL_VISUAL,true);
}
void JustDied(Unit *victim)
{
DoYell(SAY_DEATH, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_DEATH);
if( pInstance )
destroyPortals();
if(pInstance)
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE);
}
void UpdateAI(const uint32 diff)
void StartEvent()
{
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
if( Teleport )
switch(rand()%3)
{
if( Teleport_Timer <= diff )
{
m_creature->Relocate(LOCX,LOCY,LOCZ);
m_creature->SendMonsterMove(LOCX,LOCY,LOCZ,0,true,0);
case 0:
DoYell(SAY_AGGRO1, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO1);
break;
float ranX = LOCX;
float ranY = LOCY;
float ranZ = LOCZ;
case 1:
DoYell(SAY_AGGRO2, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO2);
break;
std::list<HostilReference *> t_list = m_creature->getThreatManager().getThreatList();
for( std::list<HostilReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr )
{
Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
if( target && target->GetTypeId() == TYPEID_PLAYER )
{
target->GetRandomPoint(LOCX,LOCY,LOCZ,3.0,ranX,ranY,ranZ);
DoTeleportPlayer(target,ranX,ranY,ranZ,m_creature->GetAngle(m_creature->GetPositionX(),m_creature->GetPositionY()));
}
}
Teleport = false;
if( HeroicMode ) DoCast(m_creature->getVictim(), H_SPELL_RAIN_OF_FIRE);
else DoCast(m_creature->getVictim(), SPELL_RAIN_OF_FIRE);
Teleport_Timer = 1000;
}else Teleport_Timer -= diff;
case 2:
DoYell(SAY_AGGRO3, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_AGGRO3);
break;
}
if( ShadowBoltVolley_Timer < diff )
{
DoCast(m_creature->getVictim(), SPELL_SHADOW_BOLT_VOLLEY);
ShadowBoltVolley_Timer = 30000;
}else ShadowBoltVolley_Timer -= diff;
if(pInstance)
pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS);
}
if( DrawShadows_Timer < diff )
{
DoCast(m_creature,SPELL_DRAW_SHADOWS);
DrawShadows_Timer = 35000;
Teleport = true;
}else DrawShadows_Timer -= diff;
void Aggro(Unit *who)
{
if(!InCombat)
{
InCombat = true;
StartEvent();
}
}
if( VoidTraveler_Timer < diff )
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);
DoStartAttackAndMovement(who);
Aggro(who);
}
}
else if (!Intro && m_creature->IsWithinLOSInMap(who)&& m_creature->IsWithinDistInMap(who, 100) ) //not sure about right radius
{
DoYell(SAY_INTRO, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_INTRO);
Intro = true;
}
}
void UpdateAI(const uint32 diff)
{
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
if (!sumportals)
if (sumportals_Timer < diff)
{
DoYell(SAY_HELP, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_HELP);
summonPortals();
sumportals_Timer = 1000000;
}else sumportals_Timer -= diff;
switch(rand()%5)
{
case 0:
DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_A,true);
break;
case 1:
DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_B,true);
break;
case 2:
DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_C,true);
break;
case 3:
DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_D,true);
break;
case 4:
DoCast(m_creature,SPELL_SUMMON_VOIDWALKER_E,true);
break;
}
//faster rate when below (X) health?
VoidTraveler_Timer = 35000;
}else VoidTraveler_Timer -= diff;
if( HeroicMode )
if (ShadowBoltVolley_Timer < diff)
{
if( Banish_Timer < diff )
DoCast(m_creature,SPELL_SHADOWBOLT_VOLLEY);
ShadowBoltVolley_Timer = 15000;
}else ShadowBoltVolley_Timer -= diff;
if ( DrawnShadows_Timer < diff)
{
Map *map = m_creature->GetMap();
if(map->IsDungeon())
{
if( Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1) )
DoCast(target,H_SPELL_BANISH);
Banish_Timer = 35000;
}else Banish_Timer -= diff;
}
InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers();
for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if((*i)->isAlive())
{
(*i)->TeleportTo(555,VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0);
}
}
}
m_creature->Relocate(VorpilPosition[0][0],VorpilPosition[0][1],VorpilPosition[0][2],0);
DoCast(m_creature,SPELL_DRAWN_SHADOWS,true);
if(!HeroicMode) DoCast(m_creature,SPELL_RAIN_OF_FIRE);
else DoCast(m_creature,H_SPELL_RAIN_OF_FIRE);
ShadowBoltVolley_Timer = 6000;
DrawnShadows_Timer = 45000;
}else DrawnShadows_Timer -= diff;
if ( summonTraveler_Timer < diff)
{
spawnVoidTraveler();
summonTraveler_Timer = 10000;
}else summonTraveler_Timer -=diff;
DoMeleeAttackIfReady();
}
@@ -284,6 +287,118 @@ CreatureAI* GetAI_boss_grandmaster_vorpil(Creature *_Creature)
return new boss_grandmaster_vorpilAI (_Creature);
}
struct TRINITY_DLL_DECL mob_voidtravelerAI : public ScriptedAI
{
mob_voidtravelerAI(Creature *c) : ScriptedAI(c)
{
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset();
}
ScriptedInstance *pInstance;
uint32 VorpilCheck_Timer;
uint32 eventCheck_Timer;
bool sacrifice;
bool sacrificed;
bool oneTarget;
bool HeroicMode;
uint32 target_timer;
void Reset()
{
HeroicMode = m_creature->GetMap()->IsHeroic();
if( HeroicMode )
debug_log("SD2: creature %u is in heroic mode",m_creature->GetEntry());
VorpilCheck_Timer = 5000;
eventCheck_Timer = 1000;
target_timer = 2000;
oneTarget = false;
sacrificed = false;
sacrifice = false;
}
void EnterEvadeMode(){}
void Aggro(Unit *who) {}
void AttackStart(Unit *who){}
void MoveInLineOfSight(Unit *who){}
void UpdateAI(const uint32 diff)
{
if (eventCheck_Timer < diff)
{
if(pInstance)
{
Unit *Vorpil = Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_GRANDMASTERVORPIL));
if (Vorpil)
{
if (Vorpil->isDead())
{
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
if (Vorpil->getVictim())
{
if((*m_creature).GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
(*m_creature).GetMotionMaster()->MoveFollow(Vorpil,1,0);
}
}
if(pInstance->GetData(DATA_GRANDMASTERVORPILEVENT) != IN_PROGRESS)
{
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
}
eventCheck_Timer = 5000;
}else eventCheck_Timer -=diff;
if (VorpilCheck_Timer < diff)
{
if (pInstance)
{
if (!sacrificed)
{
if (!sacrifice)
{
Unit *Vorpil = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_GRANDMASTERVORPIL));
if (Vorpil)
if (Vorpil->isAlive())
{
if (m_creature->IsWithinDistInMap(Vorpil, 2))
{
sacrifice = true;
DoCast(m_creature,SPELL_SACRIFICE);
VorpilCheck_Timer = 2000;
}
}
if (!sacrifice)
VorpilCheck_Timer = 3000;
}
else
{
Unit *Vorpil = Unit::GetUnit((*m_creature),pInstance->GetData64(DATA_GRANDMASTERVORPIL));
if (Vorpil)
if (Vorpil->isAlive())
{
if(!HeroicMode) Vorpil->CastSpell(Vorpil,SPELL_HEALVORPIL,true);
else Vorpil->CastSpell(Vorpil,H_SPELL_HEALVORPIL,true);
};
DoCast(m_creature,SPELL_SHADOW_NOVA);
sacrificed = true;
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
VorpilCheck_Timer = 100000;
}
}
}
}else VorpilCheck_Timer -= diff;
}
};
CreatureAI* GetAI_mob_voidtraveler(Creature *_Creature)
{
return new mob_voidtravelerAI (_Creature);
}
void AddSC_boss_grandmaster_vorpil()
{
Script *newscript;
@@ -291,4 +406,9 @@ void AddSC_boss_grandmaster_vorpil()
newscript->Name="boss_grandmaster_vorpil";
newscript->GetAI = GetAI_boss_grandmaster_vorpil;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="mob_voidtraveler";
newscript->GetAI = GetAI_mob_voidtraveler;
m_scripts[nrscripts++] = newscript;
}

View File

@@ -10,4 +10,5 @@
#define DATA_BLACKHEARTTHEINCITEREVENT 3
#define DATA_GRANDMASTERVORPILEVENT 4
#define DATA_MURMUREVENT 5
#define DATA_GRANDMASTERVORPIL 6
#endif

View File

@@ -156,7 +156,7 @@ struct TRINITY_DLL_DECL instance_shadow_labyrinth : public ScriptedInstance
uint64 GetData64(uint32 identifier)
{
if(identifier == DATA_GRANDMASTERVORPILEVENT)
if(identifier == DATA_GRANDMASTERVORPIL)
return GrandmasterVorpil;
return 0;

View File

@@ -1,18 +1,18 @@
/* 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
*/
/* 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
@@ -23,116 +23,237 @@ EndScriptData */
#include "precompiled.h"
#include "def_magtheridons_lair.h"
#include "WorldPacket.h"
//Phase 2 Spells
#define SPELL_QUAKE_PROC 30571
#define SPELL_QUAKE 30576 //must be cast with 30561 as the proc spell
#define SPELL_BLASTNOVA 30616
#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_BERSERK 27680
#define SPELL_DEBRIS 30631
#define SPELL_QUAKE_TRIGGER 30576 // 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
//Banish
#define SPELL_SHADOW_CAGE 30205
//Player version of the banish
#define SPELL_SHADOW_CAGE_2 30168
//Spell that is cast on players from the cube
#define SPELL_SHADOW_CAGE 30168
#define SPELL_SHADOW_GRASP 30410
#define SPELL_SHADOW_GRASP_UKN 30166
#define SPELL_SHADOW_GRASP_VIS 30207
#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
//Dialog
#define SAY_AGGRO "Thank you for releasing me. Now...die!"
#define SOUND_AGGRO 10254
#define SAY_BANISH "Not again...NOT AGAIN!"
#define SOUND_BANISH 10256
#define SAY_FREED "I...am...UNLEASHED!!!"
#define SOUND_FREED 10253
#define SAY_CHAMBER_DESTROY "I will not be taken so easily. Let the walls of this prison tremble...and FALL!!!"
#define SOUND_CHAMBER_DESTROY 10257
#define SAY_PLAYER_KILLED "Did you think me weak? Soft? Who is the weak one now?!"
#define SOUND_PLAYER_KILLED 10255
#define SAY_DEATH "The Legion...will consume you...all...."
#define SOUND_DEATH 10258
#define SOUND_DEATH 10258
#define EMOTE_BERSERK "becomes enraged!"
#define EMOTE_BLASTNOVA "begins to cast Blast Nova!"
#define EMOTE_BEGIN "%s's bonds begin to weaken!"
//Spawned objects
#define SPELL_COLLAPSE 34233 //This spell casted by the "cave in" type object
#define SPELL_CONFLAGERATION 35840 //Actually casted by a creature or object spawned on the ground
//Cubes
#define SPELL_MIND_EXHAUSTIOIN 30509 //Casted by the cubes when channeling ends
//Channeler spells
//#define MOB_HELLFIRE_CHANNELLER 17256
#define SPELL_SOUL_TRANSFER 30531
#define SPELL_SHADOW_BOLT_VOLLEY 30510
#define SPELL_DARK_MENDING 30528
#define SPELL_HELLFIRE_CHANNELING 31059
#define SPELL_HELLFIRE_CAST_VISUAL 24207
#define SPELL_FEAR 39176
#define SPELL_BURNING_ABYSSAL 30511
// count of clickers needed to interrupt blast nova
#define CLICKERS_COUNT 5
// Unkown sounds
uint32 RandomSound[] = {10247, 10248, 10249, 10250, 10251, 10252};
struct TRINITY_DLL_DECL boss_magtheridonAI : public ScriptedAI
typedef std::map<uint64, uint64> CubeMap;
struct TRINITY_DLL_DECL mob_abyssalAI : public ScriptedAI
{
boss_magtheridonAI(Creature *c) : ScriptedAI(c)
mob_abyssalAI(Creature *c) : ScriptedAI(c)
{
pInst = (ScriptedInstance*)m_creature->GetInstanceData();
trigger = 0;
Despawn_Timer = 60000;
Reset();
}
ScriptedInstance* pInst;
uint32 Phase1_Timer;
uint32 Cleave_Timer;
uint32 BlastNova_Timer;
uint32 Quake_Timer;
uint32 QuakePhase;
uint32 Collapse_Timer;
uint32 Berserk_Timer;
bool Banished;
bool Phase3;
uint32 RandChat_Timer;
uint32 FireBlast_Timer;
uint32 Despawn_Timer;
uint32 trigger;
void Reset()
{
RandChat_Timer = 90000;
FireBlast_Timer = 6000;
}
Phase1_Timer = 0;
Cleave_Timer = 15000;
Berserk_Timer = 1200000; //20 minutes
BlastNova_Timer = 60000;
void SpellHit(Unit*, const SpellEntry *spell)
{
if(trigger == 2 && spell->Id == SPELL_BLAZE_TARGET)
{
m_creature->CastSpell(m_creature, SPELL_BLAZE_TRAP, true);
m_creature->SetVisibility(VISIBILITY_OFF);
Despawn_Timer = 130000;
}
}
void SetTrigger(uint32 _trigger)
{
trigger = _trigger;
m_creature->SetDisplayId(11686);
if(trigger == 1) //debris
{
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->CastSpell(m_creature, SPELL_DEBRIS_VISUAL, true);
FireBlast_Timer = 5000;
Despawn_Timer = 10000;
}
}
void Aggro(Unit*) {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)
{
m_creature->CastSpell(m_creature, SPELL_DEBRIS_DAMAGE, true);
trigger = 3;
}else FireBlast_Timer -= diff;
}
return;
}
if(Despawn_Timer < diff)
{
m_creature->SetVisibility(VISIBILITY_OFF);
m_creature->setDeathState(JUST_DIED);
}else Despawn_Timer -= diff;
if(!m_creature->SelectHostilTarget() && !m_creature->getVictim())
return;
if(FireBlast_Timer < diff)
{
DoCast(m_creature->getVictim(), SPELL_FIRE_BLAST);
FireBlast_Timer = 5000+rand()%10000;
}else FireBlast_Timer -= diff;
DoMeleeAttackIfReady();
}
};
struct TRINITY_DLL_DECL boss_magtheridonAI : public ScriptedAI
{
boss_magtheridonAI(Creature *c) : ScriptedAI(c)
{
pInstance =(ScriptedInstance*)m_creature->GetInstanceData();
m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10);
m_creature->SetFloatValue(UNIT_FIELD_COMBATREACH, 10);
Reset();
}
CubeMap Cube;
ScriptedInstance* pInstance;
uint32 Berserk_Timer;
uint32 Quake_Timer;
uint32 Cleave_Timer;
uint32 BlastNova_Timer;
uint32 Blaze_Timer;
uint32 Debris_Timer;
bool Phase3;
bool NeedCheckCube;
void Reset()
{
if(pInstance)
{
pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED);
pInstance->SetData(DATA_COLLAPSE, false);
}
Berserk_Timer = 1320000;
Quake_Timer = 40000;
QuakePhase = 0;
Collapse_Timer = 0;
Banished = false;
Debris_Timer = 10000;
Blaze_Timer = 10000+rand()%20000;
BlastNova_Timer = 60000;
Cleave_Timer = 15000;
m_creature->setFaction(35);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Phase3 = false;
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->CastSpell(m_creature, SPELL_SHADOW_CAGE, false);
m_creature->addUnitState(UNIT_STAT_STUNNED);
m_creature->CastSpell(m_creature, SPELL_SHADOW_CAGE_C, true);
}
if(pInst)
pInst->SetData(DATA_MAGTHERIDON_EVENT_ENDED, false);
void SetClicker(uint64 cubeGUID, uint64 clickerGUID)
{
// to avoid multiclicks from 1 cube
if(uint64 guid = Cube[cubeGUID])
DebuffClicker(Unit::GetUnit(*m_creature, 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(*m_creature, (*i).second);
if(!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP, 1))
{
DebuffClicker(clicker);
(*i).second = 0;
}else ClickerNum++;
}
// if 5 clickers from other cubes apply shadow cage
if(ClickerNum >= CLICKERS_COUNT && !m_creature->HasAura(SPELL_SHADOW_CAGE, 0))
{
DoYell(SAY_BANISH, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_BANISH);
m_creature->CastSpell(m_creature, SPELL_SHADOW_CAGE, true);
}
else if(ClickerNum < CLICKERS_COUNT && m_creature->HasAura(SPELL_SHADOW_CAGE, 0))
m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE);
if(!ClickerNum) NeedCheckCube = false;
}
void KilledUnit(Unit* victim)
@@ -143,126 +264,122 @@ struct TRINITY_DLL_DECL boss_magtheridonAI : public ScriptedAI
void JustDied(Unit* Killer)
{
if(pInstance)
pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE);
DoYell(SAY_DEATH,LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_DEATH);
}
void Aggro(Unit *who) {}
void MoveInLineOfSight(Unit*) {}
void MoveInLineOfSight(Unit* who) {}
void AttackStart(Unit *who)
{
if(!m_creature->hasUnitState(UNIT_STAT_STUNNED))
ScriptedAI::AttackStart(who);
}
void Aggro(Unit *who)
{
if(pInstance)
pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS);
DoZoneInCombat();
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C);
DoYell(SAY_FREED, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_FREED);
}
void UpdateAI(const uint32 diff)
{
if (!InCombat && !Phase1_Timer)
if (RandChat_Timer < diff)
{
DoPlaySoundToSet(m_creature, RandomSound[rand()%5]);
RandChat_Timer = 90000;
}else RandChat_Timer -= diff;
if (!InCombat && !Phase1_Timer && pInst && pInst->GetData64(DATA_EVENT_STARTER))
{
//Unbanish self after 2 minutes
Phase1_Timer = 120000;
DoTextEmote(EMOTE_BEGIN, NULL);
return;
}
//Phase timer
if (Phase1_Timer)
if (Phase1_Timer <= diff)
{
m_creature->setFaction(14);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
DoYell(SAY_FREED, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_FREED);
m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE);
AttackStart(Unit::GetUnit(*m_creature, pInst->GetData64(DATA_EVENT_STARTER)));
Phase1_Timer = 0;
}else
{
if (!Unit::GetUnit(*m_creature, pInst->GetData64(DATA_EVENT_STARTER)))
{
Phase1_Timer = 0;
return;
}
Phase1_Timer -= diff;
return;
}
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
if(!m_creature->SelectHostilTarget() && !m_creature->getVictim())
return;
//Interrupt Blast Nova
if (m_creature->HasAura(SPELL_SHADOW_GRASP_VIS, 0) && m_creature->HasAura(SPELL_BLASTNOVA, 0) && !Banished)
{
DoYell(SAY_BANISH, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_BANISH);
m_creature->RemoveAurasDueToSpell(SPELL_BLASTNOVA);
m_creature->InterruptNonMeleeSpells(false);
DoCast(m_creature, SPELL_SHADOW_CAGE_2);
Banished = true;
}
if(NeedCheckCube) NeedCheckCubeStatus();
if (Banished && !m_creature->HasAura(SPELL_SHADOW_GRASP_VIS, 0))
if(Berserk_Timer < diff)
{
Banished = false;
m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_2);
}
//Berserk_Timer
if (Berserk_Timer < diff)
{
DoCast(m_creature, SPELL_BERSERK);
m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
DoTextEmote(EMOTE_BERSERK, NULL);
Berserk_Timer = 300000;
Berserk_Timer = 60000;
}else Berserk_Timer -= diff;
//Cleave_Timer
if (Cleave_Timer < diff)
if(Cleave_Timer < diff)
{
DoCast(m_creature->getVictim(),SPELL_CLEAVE);
Cleave_Timer = 10000;
}else Cleave_Timer -= diff;
//Quake_Timer
if (Quake_Timer < diff)
if(BlastNova_Timer < diff)
{
int32 i = SPELL_QUAKE_PROC;
m_creature->CastCustomSpell(m_creature, SPELL_QUAKE, &i, 0, 0, false);
Quake_Timer = 40000;
}else Quake_Timer -= diff;
//BlastNova_Timer
if (BlastNova_Timer < diff)
{
//Inturrupt Quake if it is casting
m_creature->InterruptNonMeleeSpells(false);
DoTextEmote(EMOTE_BLASTNOVA, NULL);
DoCast(m_creature, SPELL_BLASTNOVA);
BlastNova_Timer = 40000;
// to avoid earthquake interruption
if(!m_creature->hasUnitState(UNIT_STAT_STUNNED))
{
DoTextEmote(EMOTE_BLASTNOVA, NULL);
DoCast(m_creature, SPELL_BLASTNOVA);
BlastNova_Timer = 60000;
}
}else BlastNova_Timer -= diff;
//Phase3 if not already enraged and below 30%
if (!Phase3 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30)
if(Quake_Timer < diff)
{
Phase3 = true;
// to avoid blastnova interruption
if(!m_creature->IsNonMeleeSpellCasted(false))
{
int32 i = SPELL_QUAKE_KNOCKBACK;
m_creature->CastCustomSpell(m_creature, SPELL_QUAKE_TRIGGER, &i, 0, 0, false);
Quake_Timer = 50000;
}
}else Quake_Timer -= diff;
if(Blaze_Timer < diff)
{
if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{
float x, y, z;
target->GetPosition(x, y, z);
Creature *summon = m_creature->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
if(summon)
{
((mob_abyssalAI*)summon->AI())->SetTrigger(2);
m_creature->CastSpell(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 && m_creature->GetHealth()*10 < m_creature->GetMaxHealth()*3
&& !m_creature->IsNonMeleeSpellCasted(false) // blast nova
&& !m_creature->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake
{
Phase3 = true;
DoYell(SAY_CHAMBER_DESTROY, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_CHAMBER_DESTROY);
m_creature->CastSpell(m_creature, SPELL_CAMERA_SHAKE, true);
m_creature->CastSpell(m_creature, SPELL_DEBRIS_KNOCKDOWN, true);
if(pInstance)
pInstance->SetData(DATA_COLLAPSE, true);
}
if(Phase3)
{
if(Debris_Timer < diff)
{
if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{
float x, y, z;
target->GetPosition(x, y, z);
Creature *summon = m_creature->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
if(summon) ((mob_abyssalAI*)summon->AI())->SetTrigger(1);
}
Debris_Timer = 10000;
}else Debris_Timer -= diff;
}
//Melee
DoMeleeAttackIfReady();
}
};
@@ -271,150 +388,129 @@ struct TRINITY_DLL_DECL mob_hellfire_channelerAI : public ScriptedAI
{
mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c)
{
pInst = (ScriptedInstance*)m_creature->GetInstanceData();
pInstance =(ScriptedInstance*)m_creature->GetInstanceData();
Reset();
}
ScriptedInstance* pInst;
ScriptedInstance* pInstance;
uint32 ShadowBoltVolley_Timer;
uint32 DarkMending_Timer;
uint32 Fear_Timer;
uint32 Infernal_Timer;
bool InfernalSpawned;
uint32 Check_Timer;
void Reset()
{
ShadowBoltVolley_Timer = 8000 + rand()%2000;
DarkMending_Timer = 30000;
DarkMending_Timer = 10000;
Fear_Timer = 15000 + rand()%5000;
Infernal_Timer = 20000 + rand()%5000;
Infernal_Timer = 10000 + rand()%40000;
InfernalSpawned = false;
Check_Timer = 5000;
//Suprisingly this works very well, but only if the channelers are spawned after magtheridon
DoCast(m_creature, SPELL_SHADOW_GRASP_VIS);
if(pInst)
pInst->SetData(DATA_MAGTHERIDON_EVENT_ENDED, false);
if(pInstance)
pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED);
m_creature->CastSpell(m_creature, SPELL_SHADOW_GRASP_C, false);
}
void Aggro(Unit *who)
{
if(pInstance)
pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS);
m_creature->InterruptNonMeleeSpells(false);
if(!pInst || pInst->GetData64(DATA_EVENT_STARTER))
return;
pInst->SetData64(DATA_EVENT_STARTER, who->GetGUID());
pInst->SetData(DATA_MAGTHERIDON_EVENT_STARTED, true);
DoZoneInCombat();
}
void MoveInLineOfSight(Unit*)
void JustSummoned(Creature *summon) {summon->AI()->AttackStart(m_creature->getVictim());}
void MoveInLineOfSight(Unit*) {}
// bugged
/*void DamageTaken(Unit*, uint32 &damage)
{
if(damage >= m_creature->GetHealth())
m_creature->CastSpell(m_creature, SPELL_SOUL_TRANSFER, true);
}*/
void JustDied(Unit*)
{
if(pInstance)
pInstance->SetData(DATA_CHANNELER_EVENT, DONE);
}
void UpdateAI(const uint32 diff)
{
if (!InCombat && pInst && pInst->GetData64(DATA_EVENT_STARTER))
if(!m_creature->SelectHostilTarget() && !m_creature->getVictim())
return;
if(ShadowBoltVolley_Timer < diff)
{
m_creature->InterruptNonMeleeSpells(false);
AttackStart(Unit::GetUnit(*m_creature, pInst->GetData64(DATA_EVENT_STARTER)));
return;
}
//Return since we have no target
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() )
return;
//Shadow bolt volley
if (ShadowBoltVolley_Timer < diff)
{
DoCast(m_creature->getVictim(),SPELL_SHADOW_BOLT_VOLLEY);
ShadowBoltVolley_Timer = 10000 + (rand()%10000);
DoCast(m_creature, SPELL_SHADOW_BOLT_VOLLEY);
ShadowBoltVolley_Timer = 10000 + rand()%10000;
}else ShadowBoltVolley_Timer -= diff;
//Dark Mending
if (DarkMending_Timer < diff)
if(DarkMending_Timer < diff)
{
if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50)
{
//Cast on ourselves if we are lower then lowest hp friendly unit
/*if (pLowestHPTarget && LowestHP < m_creature->GetHealth())
DoCast(pLowestHPTarget, SPELL_DARK_MENDING);
else*/
if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50)
DoCast(m_creature, SPELL_DARK_MENDING);
}
DarkMending_Timer = 10000 + (rand() % 10000);
DarkMending_Timer = 10000 +(rand() % 10000);
}else DarkMending_Timer -= diff;
//Fear
if (Fear_Timer < diff)
if(Fear_Timer < diff)
{
Unit* target = NULL;
target = SelectUnit(SELECT_TARGET_RANDOM, 1);
if (target)
DoCast(target,SPELL_FEAR);
Fear_Timer = 25000 + (rand()%15000);
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1))
DoCast(target, SPELL_FEAR);
Fear_Timer = 25000 + rand()%15000;
}else Fear_Timer -= diff;
//Infernal spawning
if (!InfernalSpawned && Infernal_Timer < diff)
if(Infernal_Timer < diff)
{
Unit* target = NULL;
target = SelectUnit(SELECT_TARGET_RANDOM, 0);
if (target)
DoCast(target, SPELL_BURNING_ABYSSAL);
InfernalSpawned = true;
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
m_creature->CastSpell(target, SPELL_BURNING_ABYSSAL, true);
Infernal_Timer = 30000 + rand()%10000;
}else Infernal_Timer -= diff;
DoMeleeAttackIfReady();
}
};
//Manticron Cube
bool GOHello_go_Manticron_Cube(Player *player, GameObject* _GO)
{
ScriptedInstance* pInst = (ScriptedInstance*)_GO->GetInstanceData();
ScriptedInstance* pInstance =(ScriptedInstance*)_GO->GetInstanceData();
if(!pInstance) return true;
if(pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true;
Creature *Magtheridon =(Creature*)Unit::GetUnit(*_GO, pInstance->GetData64(DATA_MAGTHERIDON));
if(!Magtheridon || !Magtheridon->isAlive()) return true;
Unit* pUnit = NULL;
if(pInst)
pUnit = Unit::GetUnit(*_GO, pInst->GetData64(DATA_MAGTHERIDON));
else
{
_GO->TextEmote("Manticron Cube: NO INSTANCE", 0);
// if exhausted or already channeling return
if(player->HasAura(SPELL_MIND_EXHAUSTION, 0) || player->HasAura(SPELL_SHADOW_GRASP, 1))
return true;
}
if (!pUnit || !pUnit->isAlive() || !player)
{
_GO->TextEmote("Mantricon Cube: NO TARGET", 0);
return true;
}
player->InterruptNonMeleeSpells(false);
player->CastSpell(pUnit, SPELL_SHADOW_GRASP, true);
player->CastSpell(pUnit, SPELL_SHADOW_GRASP_VIS, false);
_GO->Say("Mantricon Cube Clicked", LANG_UNIVERSAL, 0);
player->CastSpell(player, SPELL_SHADOW_GRASP, true);
player->CastSpell(player, SPELL_SHADOW_GRASP_VISUAL, false);
((boss_magtheridonAI*)Magtheridon->AI())->SetClicker(_GO->GetGUID(), player->GetGUID());
return true;
}
CreatureAI* GetAI_boss_magtheridon(Creature *_Creature)
{
return new boss_magtheridonAI (_Creature);
return new boss_magtheridonAI(_Creature);
}
CreatureAI* GetAI_mob_hellfire_channeler(Creature *_Creature)
{
return new mob_hellfire_channelerAI (_Creature);
return new mob_hellfire_channelerAI(_Creature);
}
CreatureAI* GetAI_mob_abyssalAI(Creature *_Creature)
{
return new mob_abyssalAI(_Creature);
}
void AddSC_boss_magtheridon()
@@ -434,4 +530,10 @@ void AddSC_boss_magtheridon()
newscript->Name="go_manticron_cube";
newscript->pGOHello = &GOHello_go_Manticron_Cube;
m_scripts[nrscripts++] = newscript;
}
newscript = new Script;
newscript->Name="mob_abyssal";
newscript->GetAI = GetAI_mob_abyssalAI;
m_scripts[nrscripts++] = newscript;
}

View File

@@ -5,9 +5,9 @@
#ifndef DEF_MAGTHERIDONS_LAIR_H
#define DEF_MAGTHERIDONS_LAIR_H
#define DATA_EVENT_STARTER 1
#define DATA_MAGTHERIDON 2
#define DATA_MAGTHERIDON_EVENT_ENDED 3
#define DATA_MAGTHERIDON_EVENT_STARTED 4
#define DATA_MAGTHERIDON_EVENT_STATUS 5
#define DATA_MAGTHERIDON_EVENT 1
#define DATA_MAGTHERIDON 3
#define DATA_CHANNELER_EVENT 2
#define DATA_COLLAPSE 6
#define DATA_CHANNELER 9
#endif

View File

@@ -6,12 +6,12 @@
*
* 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
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
@@ -24,81 +24,297 @@ EndScriptData */
#include "precompiled.h"
#include "def_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 SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8
#define SPELL_DEBRIS_KNOCKDOWN 36449 // core bug, does not support target 8
#define CHAMBER_CENTER_X -15.14
#define CHAMBER_CENTER_Y 1.8
#define CHAMBER_CENTER_Z -0.4
#define ENCOUNTERS 2
struct TRINITY_DLL_DECL instance_magtheridons_lair : public ScriptedInstance
{
instance_magtheridons_lair(Map *Map) : ScriptedInstance(Map) {Initialize();};
instance_magtheridons_lair(Map *Map) : ScriptedInstance(Map)
{
Initialize();
// target 7, random target with certain entry spell, need core fix
SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_BLAZE_TARGET);
if(TempSpell && TempSpell->EffectImplicitTargetA[0] != 6)
{
TempSpell->EffectImplicitTargetA[0] = 6;
TempSpell->EffectImplicitTargetB[0] = 0;
}
TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_SOUL_TRANSFER);
if(TempSpell && TempSpell->EffectImplicitTargetB[0] != 30)
{
TempSpell->EffectImplicitTargetA[0] = 1;
TempSpell->EffectImplicitTargetA[1] = 1;
TempSpell->EffectImplicitTargetA[2] = 1;
TempSpell->EffectImplicitTargetB[0] = 0;
TempSpell->EffectImplicitTargetB[1] = 0;
TempSpell->EffectImplicitTargetB[2] = 0;
}
// target 8, but core only push back the caster
TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_DEBRIS_DAMAGE);
if(TempSpell && TempSpell->EffectImplicitTargetA[0] != 53)
{
TempSpell->EffectImplicitTargetA[0] = 53;
TempSpell->EffectImplicitTargetB[0] = 16;
}
TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_DEBRIS_KNOCKDOWN);
if(TempSpell && TempSpell->EffectImplicitTargetA[0] != 53)
{
TempSpell->EffectImplicitTargetA[0] = 53;
TempSpell->EffectImplicitTargetB[0] = 16;
TempSpell->EffectImplicitTargetA[1] = 53;
TempSpell->EffectImplicitTargetB[1] = 16;
}
}
bool EncounterInProgress;
uint64 Magtheridon;
uint64 EventStarter;
uint32 Encounters[ENCOUNTERS];
uint64 MagtheridonGUID;
std::set<uint64> ChannelerGUID;
uint64 DoorGUID;
std::set<uint64> ColumnGUID;
uint32 CageTimer;
uint32 RespawnTimer;
void Initialize()
{
Magtheridon = 0;
EventStarter = 0;
EncounterInProgress = false;
for(uint8 i = 0; i < ENCOUNTERS; i++)
Encounters[i] = NOT_STARTED;
MagtheridonGUID = 0;
ChannelerGUID.clear();
DoorGUID = 0;
ColumnGUID.clear();
CageTimer = 0;
RespawnTimer = 0;
}
bool IsEncounterInProgress() const
{
return EncounterInProgress;
for(uint8 i = 0; i < ENCOUNTERS; i++)
if(Encounters[i] == IN_PROGRESS) return true;
return false;
}
void OnCreatureCreate(Creature *creature, uint32 creature_entry)
{
if (creature_entry == 17257)
Magtheridon = creature->GetGUID();
switch(creature->GetEntry())
{
case 17257:
MagtheridonGUID = creature->GetGUID();
break;
case 17256:
ChannelerGUID.insert(creature->GetGUID());
break;
}
}
uint64 GetData64(uint32 identifier)
void OnObjectCreate(GameObject *go)
{
switch(identifier)
switch(go->GetEntry())
{
case DATA_MAGTHERIDON:
return Magtheridon;
case 181713:
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
break;
case 183847:
DoorGUID = go->GetGUID();
break;
case 184653: // hall
case 184634: // six columns
case 184635:
case 184636:
case 184637:
case 184638:
case 184639:
ColumnGUID.insert(go->GetGUID());
break;
}
}
case DATA_EVENT_STARTER:
return EventStarter;
uint64 GetData64(uint32 type)
{
switch(type)
{
case DATA_MAGTHERIDON:
return MagtheridonGUID;
}
return 0;
}
void SetData64(uint32 identifier, uint64 guid)
{
switch(identifier)
{
case DATA_MAGTHERIDON:
Magtheridon = guid;
break;
case DATA_EVENT_STARTER:
EventStarter = guid;
break;
}
}
void SetData(uint32 type, uint32 data)
{
Player *player = GetPlayer();
if(!player) return;
switch(type)
{
case DATA_MAGTHERIDON_EVENT_STARTED:
EncounterInProgress = true;
break;
case DATA_MAGTHERIDON_EVENT_ENDED:
EncounterInProgress = false;
EventStarter = 0;
break;
case DATA_MAGTHERIDON_EVENT:
Encounters[0] = data;
if(data == NOT_STARTED)
RespawnTimer = 10000;
if(data != IN_PROGRESS)
{
if(GameObject *Door = GameObject::GetGameObject(*player, DoorGUID))
Door->SetGoState(0);
}
break;
case DATA_CHANNELER_EVENT:
switch(data)
{
case NOT_STARTED: // Reset all channelers once one is reset.
if(Encounters[1] != NOT_STARTED)
{
Encounters[1] = NOT_STARTED;
for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i)
{
if(Creature *Channeler = (Creature*)Unit::GetUnit(*player, *i))
{
if(Channeler->isAlive())
Channeler->AI()->EnterEvadeMode();
else
Channeler->Respawn();
}
}
CageTimer = 0;
if(GameObject *Door = GameObject::GetGameObject(*player, DoorGUID))
Door->SetGoState(0);
}break;
case IN_PROGRESS: // Event start.
if(Encounters[1] != IN_PROGRESS)
{
Encounters[1] = IN_PROGRESS;
// Let all five channelers aggro.
for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i)
{
Creature *Channeler = (Creature*)Unit::GetUnit(*player, *i);
if(Channeler && Channeler->isAlive())
{
//if(Unit *target = Channeler->SelectNearbyTarget())
//always return true, do not know why
AttackNearestTarget(Channeler);
}
}
// Release Magtheridon after two minutes.
Creature *Magtheridon = (Creature*)Unit::GetUnit(*player, MagtheridonGUID);
if(Magtheridon && Magtheridon->isAlive())
{
Magtheridon->TextEmote("'s bonds begin to weaken!", 0);
CageTimer = 120000;
}
if(GameObject *Door = GameObject::GetGameObject(*player, DoorGUID))
Door->SetGoState(1);
}break;
case DONE: // Add buff and check if all channelers are dead.
for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i)
{
Unit *Channeler = Unit::GetUnit(*player, *i);
if(Channeler && Channeler->isAlive())
{
Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true);
data = IN_PROGRESS;
}
}break;
}
Encounters[1] = data;
break;
case DATA_COLLAPSE:
// true - collapse / false - reset
for(std::set<uint64>::iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i)
{
if(GameObject *Column = GameObject::GetGameObject(*player, *i))
Column->SetGoState(!data);
}
break;
default:
break;
}
}
uint32 GetData(uint32 type)
{
if(type == DATA_MAGTHERIDON_EVENT_STATUS)
return EncounterInProgress;
if(type == DATA_MAGTHERIDON_EVENT)
return Encounters[0];
return 0;
}
Player* GetPlayer()
{
if(((InstanceMap*)instance)->GetPlayers().size())
return ((InstanceMap*)instance)->GetPlayers().front();
return NULL;
}
void AttackNearestTarget(Creature *creature)
{
float minRange = 999.0f;
float range;
Player* target = NULL;
InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)instance)->GetPlayers();
InstanceMap::PlayerList::const_iterator i;
for(i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if((*i)->isTargetableForAttack())
{
range = (*i)->GetDistance(creature);
if(range < minRange)
{
minRange = range;
target = *i;
}
}
}
creature->AI()->AttackStart(target);
}
void Update(uint32 diff)
{
if(CageTimer)
{
if(CageTimer <= diff)
{
if(Player *player = GetPlayer())
{
Creature *Magtheridon = (Creature*)Unit::GetUnit(*player, MagtheridonGUID);
if(Magtheridon && Magtheridon->isAlive())
{
Magtheridon->clearUnitState(UNIT_STAT_STUNNED);
AttackNearestTarget(Magtheridon);
}
}
CageTimer = 0;
}else CageTimer -= diff;
}
if(RespawnTimer)
{
if(RespawnTimer <= diff)
{
if(Player *player = GetPlayer())
{
for(std::set<uint64>::iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i)
{
if(Creature *Channeler = (Creature*)Unit::GetUnit(*player, *i))
{
if(Channeler->isAlive())
Channeler->AI()->EnterEvadeMode();
else
Channeler->Respawn();
}
}
}
RespawnTimer = 0;
}else RespawnTimer -= diff;
}
}
};
InstanceData* GetInstanceData_instance_magtheridons_lair(Map* map)

View File

@@ -0,0 +1,532 @@
/* 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_alar
SD%Complete: 95
SDComment:
SDCategory: Tempest Keep, The Eye
EndScriptData */
#include "precompiled.h"
#include "def_the_eye.h"
#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions
#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20%
#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1)
#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2
#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2
#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown
#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec
#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5.
#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown)
#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health.
#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast
#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2
#define SPELL_FLAME_PATCH 35380 //
static float waypoint[6][3] =
{
{340.15, 58.65, 17.71},
{388.09, 31.54, 20.18},
{388.18, -32.85, 20.18},
{340.29, -60.19, 17.72},
{332, 0.01, 39}, // better not use the same xy coord
{331, 0.01, -2.39}
};
enum WaitEventType
{
WE_NONE = 0,
WE_DUMMY = 1,
WE_PLATFORM = 2,
WE_QUILL = 3,
WE_DIE = 4,
WE_REVIVE = 5,
WE_CHARGE = 6,
WE_METEOR = 7,
WE_DIVE = 8,
WE_LAND = 9,
WE_SUMMON = 10
};
struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI
{
boss_alarAI(Creature *c) : ScriptedAI(c)
{
pInstance =((ScriptedInstance*)c->GetInstanceData());
DefaultMoveSpeedRate = m_creature->GetSpeedRate(MOVE_RUN);
Reset();
}
ScriptedInstance *pInstance;
WaitEventType WaitEvent;
uint32 WaitTimer;
bool AfterMoving;
uint32 Platforms_Move_Timer;
uint32 DiveBomb_Timer;
uint32 MeltArmor_Timer;
uint32 Charge_Timer;
uint32 FlamePatch_Timer;
uint32 Berserk_Timer;
float DefaultMoveSpeedRate;
bool Phase1;
int8 cur_wp;
void Reset()
{
if(pInstance)
pInstance->SetData(DATA_ALAREVENT, NOT_STARTED);
Berserk_Timer = 1200000;
Platforms_Move_Timer = 0;
Phase1 = true;
WaitEvent = WE_NONE;
WaitTimer = 0;
AfterMoving = false;
cur_wp = 4;
m_creature->SetDisplayId(m_creature->GetNativeDisplayId());
m_creature->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10);
m_creature->SetFloatValue(UNIT_FIELD_COMBATREACH, 10);
m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void Aggro(Unit *who)
{
if(pInstance)
pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS);
m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement
DoZoneInCombat();
}
void JustDied(Unit *victim)
{
if(pInstance)
pInstance->SetData(DATA_ALAREVENT, DONE);
}
void JustSummoned(Creature *summon)
{
if(summon->GetEntry() == CREATURE_EMBER_OF_ALAR)
{
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{
summon->AI()->AttackStart(target);
summon->SetInCombatWith(target);
}
}
}
void MoveInLineOfSight(Unit *who) {}
void AttackStart(Unit* who)
{
if(!who)
return;
if(who->isTargetableForAttack())
{
//Begin attack
if(Phase1)
DoStartAttackNoMovement(who);
else
DoStartAttackAndMovement(who);
if(!InCombat)
{
Aggro(who);
InCombat = true;
}
}
}
void DamageTaken(Unit* pKiller, uint32 &damage)
{
if(damage >= m_creature->GetHealth() && Phase1)
{
damage = 0;
if(!WaitEvent)
{
WaitEvent = WE_DIE;
WaitTimer = 0;
m_creature->SetHealth(0);
m_creature->InterruptNonMeleeSpells(true);
m_creature->RemoveAllAuras();
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->AttackStop();
m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
m_creature->SetSpeed(MOVE_RUN, 5.0f);
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]);
}
}
}
void SpellHit(Unit*, const SpellEntry *spell)
{
if(spell->Id == SPELL_DIVE_BOMB_VISUAL)
{
m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
m_creature->SetDisplayId(11686);
//m_creature->SendUpdateObjectToAllExcept(NULL);
}
}
void MovementInform(uint32 type, uint32 id)
{
if(type == POINT_MOTION_TYPE)
{
WaitTimer = 1;
AfterMoving = true;
}
}
void UpdateAI(const uint32 diff)
{
if(!m_creature->isInCombat()) // sometimes isincombat but !incombat, faction bug?
return;
if(Berserk_Timer < diff)
{
m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
Berserk_Timer = 60000;
}else Berserk_Timer -= diff;
if(WaitEvent)
{
if(WaitTimer)
{
if(WaitTimer <= diff)
{
if(AfterMoving)
{
m_creature->GetMotionMaster()->MoveIdle();
AfterMoving = false;
}
switch(WaitEvent)
{
case WE_PLATFORM:
Platforms_Move_Timer = 30000+rand()%5000;
break;
case WE_QUILL:
m_creature->CastSpell(m_creature, SPELL_FLAME_QUILLS, true);
Platforms_Move_Timer = 1;
WaitTimer = 10000;
WaitEvent = WE_DUMMY;
return;
case WE_DIE:
m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD);
WaitTimer = 5000;
WaitEvent = WE_REVIVE;
return;
case WE_REVIVE:
m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE);
m_creature->SetHealth(m_creature->GetMaxHealth());
m_creature->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
DoResetThreat();
DoZoneInCombat();
m_creature->CastSpell(m_creature, SPELL_REBIRTH, true);
MeltArmor_Timer = 60000;
Charge_Timer = 7000;
DiveBomb_Timer = 40000+rand()%5000;
FlamePatch_Timer = 30000;
Phase1 = false;
break;
case WE_CHARGE:
m_creature->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
break;
case WE_METEOR:
m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false);
m_creature->CastSpell(m_creature, SPELL_DIVE_BOMB_VISUAL, false);
WaitEvent = WE_DIVE;
WaitTimer = 4000;
return;
case WE_DIVE:
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{
m_creature->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL);
m_creature->CastSpell(target, SPELL_DIVE_BOMB, true);
float dist = m_creature->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
if (dist < 5.0f) dist = 5.0f;
WaitTimer = 1000 + floor(dist / 80 * 1000.0f);
m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
m_creature->StopMoving();
WaitEvent = WE_LAND;
}else EnterEvadeMode();
return;
case WE_LAND:
WaitEvent = WE_SUMMON;
WaitTimer = 2000;
return;
case WE_SUMMON:
for(uint8 i = 0; i < 2; ++i)
DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->SetDisplayId(m_creature->GetNativeDisplayId());
m_creature->CastSpell(m_creature, SPELL_REBIRTH_2, true);
break;
case WE_DUMMY:
default:
break;
}
WaitEvent = WE_NONE;
WaitTimer = 0;
}else WaitTimer -= diff;
}
return;
}
if(Phase1)
{
if(m_creature->getThreatManager().getThreatList().empty())
{
EnterEvadeMode();
return;
}
if(Platforms_Move_Timer < diff)
{
if(cur_wp == 4)
{
cur_wp = 0;
WaitEvent = WE_PLATFORM;
}
else
{
if(rand()%5) // next platform
{
DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
if(cur_wp == 3)
cur_wp = 0;
else
cur_wp++;
WaitEvent = WE_PLATFORM;
}
else // flame quill
{
cur_wp = 4;
WaitEvent = WE_QUILL;
}
}
m_creature->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]);
WaitTimer = 0;
return;
}else Platforms_Move_Timer -= diff;
}
else
{
if(!m_creature->SelectHostilTarget() && !m_creature->getVictim())
return;
if(Charge_Timer < diff)
{
if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1))
{
m_creature->SetInFront(target);
m_creature->GetMotionMaster()->Clear();
m_creature->AttackStop();
m_creature->SetSpeed(MOVE_RUN, 5.0f);
DoCast(target, SPELL_CHARGE);
WaitEvent = WE_CHARGE;
WaitTimer = 1000;
return;
}
Charge_Timer = 30000;
}else Charge_Timer -= diff;
if(MeltArmor_Timer < diff)
{
DoCast(m_creature->getVictim(), SPELL_MELT_ARMOR);
MeltArmor_Timer = 60000;
}else MeltArmor_Timer -= diff;
if(DiveBomb_Timer < diff)
{
m_creature->AttackStop();
m_creature->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50);
WaitEvent = WE_METEOR;
WaitTimer = 0;
DiveBomb_Timer = 40000+rand()%5000;
return;
}else DiveBomb_Timer -= diff;
if(FlamePatch_Timer < diff)
{
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{
Creature* Summoned = m_creature->SummonCreature(CREATURE_FLAME_PATCH_ALAR, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000);
if(Summoned)
{
Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f);
Summoned->SetDisplayId(11686);
Summoned->setFaction(m_creature->getFaction());
Summoned->SetLevel(m_creature->getLevel());
Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false);
}
}
FlamePatch_Timer = 30000;
}else FlamePatch_Timer -= diff;
}
DoMeleeAttackIfReady();
}
void DoMeleeAttackIfReady()
{
if(m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
{
if(m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
else
{
Unit *target = NULL;
if(Phase1 && (target = m_creature->SelectNearbyTarget()) && m_creature->IsHostileTo(target)) // core bug, 1620 faction bugged
m_creature->AI()->AttackStart(target);
else
{
m_creature->CastSpell(m_creature, SPELL_FLAME_BUFFET, true);
m_creature->setAttackTimer(BASE_ATTACK, 1500);
}
}
}
}
};
CreatureAI* GetAI_boss_alar(Creature *_Creature)
{
return new boss_alarAI(_Creature);
}
struct TRINITY_DLL_DECL mob_ember_of_alarAI : public ScriptedAI
{
mob_ember_of_alarAI(Creature *c) : ScriptedAI(c)
{
pInstance = (ScriptedInstance*)c->GetInstanceData();
m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
m_creature->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
Reset();
}
ScriptedInstance *pInstance;
bool toDie;
void Reset() {toDie = false;}
void Aggro(Unit *who) {DoZoneInCombat();}
void EnterEvadeMode() {m_creature->setDeathState(JUST_DIED);}
void DamageTaken(Unit* pKiller, uint32 &damage)
{
if(damage >= m_creature->GetHealth() && pKiller != m_creature && !toDie)
{
damage = 0;
m_creature->CastSpell(m_creature, SPELL_EMBER_BLAST, true);
m_creature->SetDisplayId(11686);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
if(pInstance && pInstance->GetData(DATA_ALAREVENT) == 2)
{
if(Unit* Alar = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_ALAR)))
{
int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03;
if(AlarHealth > 0)
Alar->SetHealth(AlarHealth);
else
Alar->SetHealth(1);
}
}
toDie = true;
}
}
void UpdateAI(const uint32 diff)
{
if(!m_creature->SelectHostilTarget() && !m_creature->getVictim())
return;
if(toDie)
{
m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
//m_creature->SetVisibility(VISIBILITY_OFF);
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_ember_of_alar(Creature *_Creature)
{
return new mob_ember_of_alarAI(_Creature);
}
struct TRINITY_DLL_DECL mob_flame_patch_alarAI : public ScriptedAI
{
mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {}
void Reset() {}
void Aggro(Unit *who) {}
void AttackStart(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff) {}
};
CreatureAI* GetAI_mob_flame_patch_alar(Creature *_Creature)
{
return new mob_flame_patch_alarAI(_Creature);
}
void AddSC_boss_alar()
{
Script *newscript;
newscript = new Script;
newscript->Name="boss_alar";
newscript->GetAI = GetAI_boss_alar;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="mob_ember_of_alar";
newscript->GetAI = GetAI_mob_ember_of_alar;
m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="mob_flame_patch_alar";
newscript->GetAI = GetAI_mob_flame_patch_alar;
m_scripts[nrscripts++] = newscript;
}

View File

@@ -17,4 +17,5 @@
#define DATA_SOLARIANEVENT 10
#define DATA_THALADREDTHEDARKENER 11
#define DATA_VOIDREAVEREVENT 12
#define DATA_ALAR 13
#endif

View File

@@ -6,12 +6,12 @@
*
* 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
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
@@ -43,8 +43,10 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
uint64 MasterEngineerTelonicus;
uint64 Kaelthas;
uint64 Astromancer;
uint64 Alar;
uint8 KaelthasEventPhase;
uint8 AlarEventPhase;
bool Encounters[ENCOUNTERS];
@@ -56,8 +58,10 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
MasterEngineerTelonicus = 0;
Kaelthas = 0;
Astromancer = 0;
Alar = 0;
KaelthasEventPhase = 0;
AlarEventPhase = 0;
for(uint8 i = 0; i < ENCOUNTERS; i++)
Encounters[i] = false;
@@ -81,6 +85,10 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
case 20060: LordSanguinar = creature->GetGUID(); break;
case 19622: Kaelthas = creature->GetGUID(); break;
case 18805: Astromancer = creature->GetGUID(); break;
case 19514:
Alar = creature->GetGUID();
break;
}
}
@@ -105,6 +113,9 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
case DATA_ASTROMANCER:
return Astromancer;
case DATA_ALAR:
return Alar;
}
return 0;
@@ -115,6 +126,7 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
switch(type)
{
case DATA_ALAREVENT:
AlarEventPhase = data;
Encounters[0] = (data) ? true : false;
break;
@@ -143,7 +155,7 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
switch(type)
{
case DATA_ALAREVENT:
return Encounters[0];
return AlarEventPhase;
case DATA_SOLARIANEVENT:
return Encounters[1];

View File

@@ -0,0 +1,6 @@
update `creature_template` set `ScriptName`='boss_alar' where `entry`='19514';
update `creature_template` set `ScriptName`='mob_ember_of_alar' where `entry`='19551';
update `creature_template` set `ScriptName`='mob_flame_patch_alar' where `entry`='20602';
update gameobject_template set scriptname = "go_manticron_cube" where entry = 181713;
update creature_template set scriptname = "mob_abyssal" where entry = 17454;