* Rename InstanceData to InstanceScript

* Rename *mgr to their new names in scripts project
* Mass convert all the scripts (NEEDS THOROUGH TESTING, because it was done automatically) Please, report bugs on issue tracker.

--HG--
branch : trunk
rename : src/server/game/Instances/InstanceData.cpp => src/server/game/Instances/InstanceScript.cpp
rename : src/server/game/Instances/InstanceData.h => src/server/game/Instances/InstanceScript.h
This commit is contained in:
azazel
2010-08-08 22:54:58 +06:00
parent 8a69e50d6a
commit 590199d8e1
482 changed files with 84476 additions and 82697 deletions
@@ -42,157 +42,160 @@ EndScriptData */
#define SPELL_EVOCATION 30254
#define SPELL_ENRAGE 30403 //Arcane Infusion: Transforms Curator and adds damage.
#define SPELL_BERSERK 26662
struct boss_curatorAI : public ScriptedAI
␍class boss_curator : public CreatureScript
{
boss_curatorAI(Creature *c) : ScriptedAI(c) {}
public:
boss_curator() : CreatureScript("boss_curator") { }
uint32 AddTimer;
uint32 HatefulBoltTimer;
uint32 BerserkTimer;
bool Enraged;
bool Evocating;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
AddTimer = 10000;
HatefulBoltTimer = 15000; //This time may be wrong
BerserkTimer = 720000; //12 minutes
Enraged = false;
Evocating = false;
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true);
return new boss_curatorAI (pCreature);
}
void KilledUnit(Unit * /*victim*/)
struct boss_curatorAI : public ScriptedAI
{
DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me);
}
boss_curatorAI(Creature *c) : ScriptedAI(c) {}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
}
uint32 AddTimer;
uint32 HatefulBoltTimer;
uint32 BerserkTimer;
void EnterCombat(Unit * /*who*/)
{
DoScriptText(SAY_AGGRO, me);
}
bool Enraged;
bool Evocating;
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
//always decrease BerserkTimer
if (BerserkTimer <= diff)
void Reset()
{
//if evocate, then break evocate
AddTimer = 10000;
HatefulBoltTimer = 15000; //This time may be wrong
BerserkTimer = 720000; //12 minutes
Enraged = false;
Evocating = false;
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true);
}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me);
}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
}
void EnterCombat(Unit * /*who*/)
{
DoScriptText(SAY_AGGRO, me);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
//always decrease BerserkTimer
if (BerserkTimer <= diff)
{
//if evocate, then break evocate
if (Evocating)
{
if (me->HasAura(SPELL_EVOCATION))
me->RemoveAurasDueToSpell(SPELL_EVOCATION);
Evocating = false;
}
//may not be correct SAY (generic hard enrage)
DoScriptText(SAY_ENRAGE, me);
me->InterruptNonMeleeSpells(true);
DoCast(me, SPELL_BERSERK);
//don't know if he's supposed to do summon/evocate after hard enrage (probably not)
Enraged = true;
} else BerserkTimer -= diff;
if (Evocating)
{
//not supposed to do anything while evocate
if (me->HasAura(SPELL_EVOCATION))
me->RemoveAurasDueToSpell(SPELL_EVOCATION);
Evocating = false;
return;
else
Evocating = false;
}
//may not be correct SAY (generic hard enrage)
DoScriptText(SAY_ENRAGE, me);
me->InterruptNonMeleeSpells(true);
DoCast(me, SPELL_BERSERK);
//don't know if he's supposed to do summon/evocate after hard enrage (probably not)
Enraged = true;
} else BerserkTimer -= diff;
if (Evocating)
{
//not supposed to do anything while evocate
if (me->HasAura(SPELL_EVOCATION))
return;
else
Evocating = false;
}
if (!Enraged)
{
if (AddTimer <= diff)
if (!Enraged)
{
//Summon Astral Flare
Creature* AstralFlare = DoSpawnCreature(17096, rand()%37, rand()%37, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
Unit *pTarget = NULL;
pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
if (AstralFlare && pTarget)
if (AddTimer <= diff)
{
AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false);
AstralFlare->AI()->AttackStart(pTarget);
}
//Summon Astral Flare
Creature* AstralFlare = DoSpawnCreature(17096, rand()%37, rand()%37, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
Unit *pTarget = NULL;
pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
//Reduce Mana by 10% of max health
if (int32 mana = me->GetMaxPower(POWER_MANA))
{
mana /= 10;
me->ModifyPower(POWER_MANA, -mana);
//if this get's us below 10%, then we evocate (the 10th should be summoned now)
if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10)
if (AstralFlare && pTarget)
{
DoScriptText(SAY_EVOCATE, me);
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_EVOCATION);
Evocating = true;
//no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected
return;
AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false);
AstralFlare->AI()->AttackStart(pTarget);
}
else
//Reduce Mana by 10% of max health
if (int32 mana = me->GetMaxPower(POWER_MANA))
{
if (urand(0,1) == 0)
mana /= 10;
me->ModifyPower(POWER_MANA, -mana);
//if this get's us below 10%, then we evocate (the 10th should be summoned now)
if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10)
{
DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me);
DoScriptText(SAY_EVOCATE, me);
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_EVOCATION);
Evocating = true;
//no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected
return;
}
else
{
if (urand(0,1) == 0)
{
DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me);
}
}
}
AddTimer = 10000;
} else AddTimer -= diff;
if (me->GetHealth()*100 / me->GetMaxHealth() <= 15)
{
Enraged = true;
DoCast(me, SPELL_ENRAGE);
DoScriptText(SAY_ENRAGE, me);
}
AddTimer = 10000;
} else AddTimer -= diff;
if (me->GetHealth()*100 / me->GetMaxHealth() <= 15)
{
Enraged = true;
DoCast(me, SPELL_ENRAGE);
DoScriptText(SAY_ENRAGE, me);
}
if (HatefulBoltTimer <= diff)
{
if (Enraged)
HatefulBoltTimer = 7000;
else
HatefulBoltTimer = 15000;
if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1))
DoCast(pTarget, SPELL_HATEFUL_BOLT);
} else HatefulBoltTimer -= diff;
DoMeleeAttackIfReady();
}
};
if (HatefulBoltTimer <= diff)
{
if (Enraged)
HatefulBoltTimer = 7000;
else
HatefulBoltTimer = 15000;
if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1))
DoCast(pTarget, SPELL_HATEFUL_BOLT);
} else HatefulBoltTimer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_boss_curator(Creature* pCreature)
{
return new boss_curatorAI (pCreature);
}
void AddSC_boss_curator()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_curator";
newscript->GetAI = &GetAI_boss_curator;
newscript->RegisterSelf();
new boss_curator();
}
@@ -38,103 +38,105 @@ EndScriptData */
#define SPELL_HOLYWRATH 32445
#define SPELL_HOLYGROUND 29512
#define SPELL_BERSERK 26662
struct boss_maiden_of_virtueAI : public ScriptedAI
␍class boss_maiden_of_virtue : public CreatureScript
{
boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {}
public:
boss_maiden_of_virtue() : CreatureScript("boss_maiden_of_virtue") { }
uint32 Repentance_Timer;
uint32 Holyfire_Timer;
uint32 Holywrath_Timer;
uint32 Holyground_Timer;
uint32 Enrage_Timer;
bool Enraged;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
Repentance_Timer = 25000+(rand()%15000);
Holyfire_Timer = 8000+(rand()%17000);
Holywrath_Timer = 15000+(rand()%10000);
Holyground_Timer = 3000;
Enrage_Timer = 600000;
Enraged = false;
return new boss_maiden_of_virtueAI (pCreature);
}
void KilledUnit(Unit* /*Victim*/)
struct boss_maiden_of_virtueAI : public ScriptedAI
{
if (urand(0,1) == 0)
DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me);
}
boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {}
void JustDied(Unit* /*Killer*/)
{
DoScriptText(SAY_DEATH, me);
}
uint32 Repentance_Timer;
uint32 Holyfire_Timer;
uint32 Holywrath_Timer;
uint32 Holyground_Timer;
uint32 Enrage_Timer;
void EnterCombat(Unit * /*who*/)
{
DoScriptText(SAY_AGGRO, me);
}
bool Enraged;
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (Enrage_Timer < diff && !Enraged)
void Reset()
{
DoCast(me, SPELL_BERSERK, true);
Enraged = true;
} else Enrage_Timer -= diff;
Repentance_Timer = 25000+(rand()%15000);
Holyfire_Timer = 8000+(rand()%17000);
Holywrath_Timer = 15000+(rand()%10000);
Holyground_Timer = 3000;
Enrage_Timer = 600000;
if (Holyground_Timer <= diff)
Enraged = false;
}
void KilledUnit(Unit* /*Victim*/)
{
DoCast(me, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all
Holyground_Timer = 3000;
} else Holyground_Timer -= diff;
if (urand(0,1) == 0)
DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me);
}
if (Repentance_Timer <= diff)
void JustDied(Unit* /*Killer*/)
{
DoCast(me->getVictim(), SPELL_REPENTANCE);
DoScriptText(RAND(SAY_REPENTANCE1,SAY_REPENTANCE2), me);
DoScriptText(SAY_DEATH, me);
}
Repentance_Timer = urand(25000,35000); //A little randomness on that spell
} else Repentance_Timer -= diff;
if (Holyfire_Timer <= diff)
void EnterCombat(Unit * /*who*/)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_HOLYFIRE);
DoScriptText(SAY_AGGRO, me);
}
Holyfire_Timer = urand(8000,23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row!
} else Holyfire_Timer -= diff;
if (Holywrath_Timer <= diff)
void UpdateAI(const uint32 diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_HOLYWRATH);
if (!UpdateVictim())
return;
Holywrath_Timer = urand(20000,25000); //20-30 secs sounds nice
} else Holywrath_Timer -= diff;
if (Enrage_Timer < diff && !Enraged)
{
DoCast(me, SPELL_BERSERK, true);
Enraged = true;
} else Enrage_Timer -= diff;
DoMeleeAttackIfReady();
}
if (Holyground_Timer <= diff)
{
DoCast(me, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all
Holyground_Timer = 3000;
} else Holyground_Timer -= diff;
if (Repentance_Timer <= diff)
{
DoCast(me->getVictim(), SPELL_REPENTANCE);
DoScriptText(RAND(SAY_REPENTANCE1,SAY_REPENTANCE2), me);
Repentance_Timer = urand(25000,35000); //A little randomness on that spell
} else Repentance_Timer -= diff;
if (Holyfire_Timer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_HOLYFIRE);
Holyfire_Timer = urand(8000,23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row!
} else Holyfire_Timer -= diff;
if (Holywrath_Timer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_HOLYWRATH);
Holywrath_Timer = urand(20000,25000); //20-30 secs sounds nice
} else Holywrath_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_maiden_of_virtue(Creature* pCreature)
{
return new boss_maiden_of_virtueAI (pCreature);
}
void AddSC_boss_maiden_of_virtue()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_maiden_of_virtue";
newscript->GetAI = &GetAI_boss_maiden_of_virtue;
newscript->RegisterSelf();
new boss_maiden_of_virtue();
}
@@ -45,268 +45,271 @@ EndScriptData */
//Attumen (TODO: Use the summoning spell instead of Creature id. It works , but is not convenient for us)
#define SUMMON_ATTUMEN 15550
struct boss_midnightAI : public ScriptedAI
␍class boss_attumen : public CreatureScript
{
boss_midnightAI(Creature *c) : ScriptedAI(c) {}
public:
boss_attumen() : CreatureScript("boss_attumen") { }
uint64 Attumen;
uint8 Phase;
uint32 Mount_Timer;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
Phase = 1;
Attumen = 0;
Mount_Timer = 0;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetVisibility(VISIBILITY_ON);
return new boss_attumenAI (pCreature);
}
void EnterCombat(Unit* /*who*/) {}
void KilledUnit(Unit * /*victim*/)
struct boss_attumenAI : public ScriptedAI
{
if (Phase == 2)
boss_attumenAI(Creature *c) : ScriptedAI(c)
{
if (Unit *pUnit = Unit::GetUnit(*me, Attumen))
DoScriptText(SAY_MIDNIGHT_KILL, pUnit);
}
}
Phase = 1;
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (Phase == 1 && (me->GetHealth()*100)/me->GetMaxHealth() < 95)
{
Phase = 2;
if (Creature* pAttumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000))
{
Attumen = pAttumen->GetGUID();
pAttumen->AI()->AttackStart(me->getVictim());
SetMidnight(pAttumen, me->GetGUID());
DoScriptText(RAND(SAY_APPEAR1,SAY_APPEAR2,SAY_APPEAR3), pAttumen);
}
}
else if (Phase == 2 && (me->GetHealth()*100)/me->GetMaxHealth() < 25)
{
if (Unit *pAttumen = Unit::GetUnit(*me, Attumen))
Mount(pAttumen);
}
else if (Phase == 3)
{
if (Mount_Timer)
{
if (Mount_Timer <= diff)
{
Mount_Timer = 0;
me->SetVisibility(VISIBILITY_OFF);
me->GetMotionMaster()->MoveIdle();
if (Unit *pAttumen = Unit::GetUnit(*me, Attumen))
{
pAttumen->SetDisplayId(MOUNTED_DISPLAYID);
pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
if (pAttumen->getVictim())
{
pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim());
pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID());
}
pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1);
}
} else Mount_Timer -= diff;
}
}
if (Phase != 3)
DoMeleeAttackIfReady();
}
void Mount(Unit *pAttumen)
{
DoScriptText(SAY_MOUNT, pAttumen);
Phase = 3;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
float angle = me->GetAngle(pAttumen);
float distance = me->GetDistance2d(pAttumen);
float newX = me->GetPositionX() + cos(angle)*(distance/2) ;
float newY = me->GetPositionY() + sin(angle)*(distance/2) ;
float newZ = 50;
//me->Relocate(newX,newY,newZ,angle);
//me->SendMonsterMove(newX, newY, newZ, 0, true, 1000);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(0, newX, newY, newZ);
distance += 10;
newX = me->GetPositionX() + cos(angle)*(distance/2) ;
newY = me->GetPositionY() + sin(angle)*(distance/2) ;
pAttumen->GetMotionMaster()->Clear();
pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ);
//pAttumen->Relocate(newX,newY,newZ,-angle);
//pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000);
Mount_Timer = 1000;
}
void SetMidnight(Creature *, uint64); //Below ..
};
CreatureAI* GetAI_boss_midnight(Creature* pCreature)
{
return new boss_midnightAI(pCreature);
}
struct boss_attumenAI : public ScriptedAI
{
boss_attumenAI(Creature *c) : ScriptedAI(c)
{
Phase = 1;
CleaveTimer = urand(10000,15000);
CurseTimer = 30000;
RandomYellTimer = urand(30000,60000); //Occasionally yell
ChargeTimer = 20000;
ResetTimer = 0;
}
uint64 Midnight;
uint8 Phase;
uint32 CleaveTimer;
uint32 CurseTimer;
uint32 RandomYellTimer;
uint32 ChargeTimer; //only when mounted
uint32 ResetTimer;
void Reset()
{
ResetTimer = 2000;
}
void EnterCombat(Unit* /*who*/) {}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me);
}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
if (Unit *pMidnight = Unit::GetUnit(*me, Midnight))
pMidnight->Kill(pMidnight);
}
void UpdateAI(const uint32 diff)
{
if (ResetTimer)
{
if (ResetTimer <= diff)
{
ResetTimer = 0;
Unit *pMidnight = Unit::GetUnit(*me, Midnight);
if (pMidnight)
{
pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pMidnight->SetVisibility(VISIBILITY_ON);
}
Midnight = 0;
me->SetVisibility(VISIBILITY_OFF);
me->Kill(me);
}
} else ResetTimer -= diff;
//Return since we have no target
if (!UpdateVictim())
return;
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
return;
if (CleaveTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SHADOWCLEAVE);
CleaveTimer = urand(10000,15000);
} else CleaveTimer -= diff;
if (CurseTimer <= diff)
{
DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE);
CurseTimer = 30000;
} else CurseTimer -= diff;
if (RandomYellTimer <= diff)
{
DoScriptText(RAND(SAY_RANDOM1,SAY_RANDOM2), me);
RandomYellTimer = urand(30000,60000);
} else RandomYellTimer -= diff;
if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID)
{
if (ChargeTimer <= diff)
{
Unit *pTarget = NULL;
std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
std::vector<Unit *> target_list;
for (std::list<HostileReference *>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
{
pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid());
if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false))
target_list.push_back(pTarget);
pTarget = NULL;
}
if (target_list.size())
pTarget = *(target_list.begin()+rand()%target_list.size());
DoCast(pTarget, SPELL_BERSERKER_CHARGE);
ChargeTimer = 20000;
} else ChargeTimer -= diff;
RandomYellTimer = urand(30000,60000); //Occasionally yell
ChargeTimer = 20000;
ResetTimer = 0;
}
else
uint64 Midnight;
uint8 Phase;
uint32 CleaveTimer;
uint32 CurseTimer;
uint32 RandomYellTimer;
uint32 ChargeTimer; //only when mounted
uint32 ResetTimer;
void Reset()
{
if ((me->GetHealth()*100)/me->GetMaxHealth() < 25)
ResetTimer = 2000;
}
void EnterCombat(Unit* /*who*/) {}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me);
}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
if (Unit *pMidnight = Unit::GetUnit(*me, Midnight))
pMidnight->Kill(pMidnight);
}
void UpdateAI(const uint32 diff);
void SpellHit(Unit * /*source*/, const SpellEntry *spell)
{
if (spell->Mechanic == MECHANIC_DISARM)
DoScriptText(SAY_DISARMED, me);
}
};
};
␍class boss_midnight : public CreatureScript
{
public:
boss_midnight() : CreatureScript("boss_midnight") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new boss_midnightAI(pCreature);
}
struct boss_midnightAI : public ScriptedAI
{
boss_midnightAI(Creature *c) : ScriptedAI(c) {}
uint64 Attumen;
uint8 Phase;
uint32 Mount_Timer;
void Reset()
{
Phase = 1;
Attumen = 0;
Mount_Timer = 0;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetVisibility(VISIBILITY_ON);
}
void EnterCombat(Unit* /*who*/) {}
void KilledUnit(Unit * /*victim*/)
{
if (Phase == 2)
{
Creature *pMidnight = Unit::GetCreature(*me, Midnight);
if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT)
{
CAST_AI(boss_midnightAI, (pMidnight->AI()))->Mount(me);
me->SetHealth(pMidnight->GetHealth());
DoResetThreat();
}
if (Unit *pUnit = Unit::GetUnit(*me, Attumen))
DoScriptText(SAY_MIDNIGHT_KILL, pUnit);
}
}
DoMeleeAttackIfReady();
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (Phase == 1 && (me->GetHealth()*100)/me->GetMaxHealth() < 95)
{
Phase = 2;
if (Creature* pAttumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000))
{
Attumen = pAttumen->GetGUID();
pAttumen->AI()->AttackStart(me->getVictim());
SetMidnight(pAttumen, me->GetGUID());
DoScriptText(RAND(SAY_APPEAR1,SAY_APPEAR2,SAY_APPEAR3), pAttumen);
}
}
else if (Phase == 2 && (me->GetHealth()*100)/me->GetMaxHealth() < 25)
{
if (Unit *pAttumen = Unit::GetUnit(*me, Attumen))
Mount(pAttumen);
}
else if (Phase == 3)
{
if (Mount_Timer)
{
if (Mount_Timer <= diff)
{
Mount_Timer = 0;
me->SetVisibility(VISIBILITY_OFF);
me->GetMotionMaster()->MoveIdle();
if (Unit *pAttumen = Unit::GetUnit(*me, Attumen))
{
pAttumen->SetDisplayId(MOUNTED_DISPLAYID);
pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
if (pAttumen->getVictim())
{
pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim());
pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID());
}
pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1);
}
} else Mount_Timer -= diff;
}
}
if (Phase != 3)
DoMeleeAttackIfReady();
}
void Mount(Unit *pAttumen)
{
DoScriptText(SAY_MOUNT, pAttumen);
Phase = 3;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
float angle = me->GetAngle(pAttumen);
float distance = me->GetDistance2d(pAttumen);
float newX = me->GetPositionX() + cos(angle)*(distance/2) ;
float newY = me->GetPositionY() + sin(angle)*(distance/2) ;
float newZ = 50;
//me->Relocate(newX,newY,newZ,angle);
//me->SendMonsterMove(newX, newY, newZ, 0, true, 1000);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(0, newX, newY, newZ);
distance += 10;
newX = me->GetPositionX() + cos(angle)*(distance/2) ;
newY = me->GetPositionY() + sin(angle)*(distance/2) ;
pAttumen->GetMotionMaster()->Clear();
pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ);
//pAttumen->Relocate(newX,newY,newZ,-angle);
//pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000);
Mount_Timer = 1000;
}
void SetMidnight(Creature *pAttumen, uint64 value)
{
CAST_AI(boss_attumen::boss_attumenAI, pAttumen->AI())->Midnight = value;
}␍ };
void SpellHit(Unit * /*source*/, const SpellEntry *spell)
{
if (spell->Mechanic == MECHANIC_DISARM)
DoScriptText(SAY_DISARMED, me);
}
};
void boss_midnightAI::SetMidnight(Creature *pAttumen, uint64 value)
void boss_attumen::boss_attumenAI::UpdateAI(const uint32 diff)
{
CAST_AI(boss_attumenAI, pAttumen->AI())->Midnight = value;
if (ResetTimer)
{
if (ResetTimer <= diff)
{
ResetTimer = 0;
Unit *pMidnight = Unit::GetUnit(*me, Midnight);
if (pMidnight)
{
pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pMidnight->SetVisibility(VISIBILITY_ON);
}
Midnight = 0;
me->SetVisibility(VISIBILITY_OFF);
me->Kill(me);
}
} else ResetTimer -= diff;
//Return since we have no target
if (!UpdateVictim())
return;
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
return;
if (CleaveTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SHADOWCLEAVE);
CleaveTimer = urand(10000,15000);
} else CleaveTimer -= diff;
if (CurseTimer <= diff)
{
DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE);
CurseTimer = 30000;
} else CurseTimer -= diff;
if (RandomYellTimer <= diff)
{
DoScriptText(RAND(SAY_RANDOM1,SAY_RANDOM2), me);
RandomYellTimer = urand(30000,60000);
} else RandomYellTimer -= diff;
if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID)
{
if (ChargeTimer <= diff)
{
Unit *pTarget = NULL;
std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
std::vector<Unit *> target_list;
for (std::list<HostileReference *>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
{
pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid());
if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false))
target_list.push_back(pTarget);
pTarget = NULL;
}
if (target_list.size())
pTarget = *(target_list.begin()+rand()%target_list.size());
DoCast(pTarget, SPELL_BERSERKER_CHARGE);
ChargeTimer = 20000;
} else ChargeTimer -= diff;
}
else
{
if ((me->GetHealth()*100)/me->GetMaxHealth() < 25)
{
Creature *pMidnight = Unit::GetCreature(*me, Midnight);
if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT)
{
CAST_AI(boss_midnight::boss_midnightAI, (pMidnight->AI()))->Mount(me);
me->SetHealth(pMidnight->GetHealth());
DoResetThreat();
}
}
}
DoMeleeAttackIfReady();
}
CreatureAI* GetAI_boss_attumen(Creature* pCreature)
{
return new boss_attumenAI (pCreature);
}
void AddSC_boss_attumen()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_attumen";
newscript->GetAI = &GetAI_boss_attumen;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "boss_midnight";
newscript->GetAI = &GetAI_boss_midnight;
newscript->RegisterSelf();
new boss_attumen();
new boss_midnight();
}
File diff suppressed because it is too large Load Diff
@@ -57,283 +57,285 @@ const uint32 PortalBeam[3] = {30465,30464,30463};
const uint32 PlayerBuff[3] = {30421,30422,30423};
const uint32 NetherBuff[3] = {30466,30467,30468};
const uint32 PlayerDebuff[3] = {38637,38638,38639};
struct boss_netherspiteAI : public ScriptedAI
␍class boss_netherspite : public CreatureScript
{
boss_netherspiteAI(Creature* c) : ScriptedAI(c)
{
pInstance = c->GetInstanceData();
public:
boss_netherspite() : CreatureScript("boss_netherspite") { }
for (int i=0; i<3; ++i)
CreatureAI* GetAI(Creature *pCreature)
{
return new boss_netherspiteAI(pCreature);
}
struct boss_netherspiteAI : public ScriptedAI
{
boss_netherspiteAI(Creature* c) : ScriptedAI(c)
{
PortalGUID[i] = 0;
BeamTarget[i] = 0;
BeamerGUID[i] = 0;
}
}
pInstance = c->GetInstanceScript();
ScriptedInstance* pInstance;
bool PortalPhase;
bool Berserk;
uint32 PhaseTimer; // timer for phase switching
uint32 VoidZoneTimer;
uint32 NetherInfusionTimer; // berserking timer
uint32 NetherbreathTimer;
uint32 EmpowermentTimer;
uint32 PortalTimer; // timer for beam checking
uint64 PortalGUID[3]; // guid's of portals
uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals
uint64 BeamTarget[3]; // guid's of portals' current targets
bool IsBetween(WorldObject* u1, WorldObject *pTarget, WorldObject* u2) // the in-line checker
{
if (!u1 || !u2 || !pTarget)
return false;
float xn, yn, xp, yp, xh, yh;
xn = u1->GetPositionX();
yn = u1->GetPositionY();
xp = u2->GetPositionX();
yp = u2->GetPositionY();
xh = pTarget->GetPositionX();
yh = pTarget->GetPositionY();
// check if target is between (not checking distance from the beam yet)
if (dist(xn,yn,xh,yh) >= dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh) >= dist(xn,yn,xp,yp))
return false;
// check distance from the beam
return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f);
}
float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance
{
return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb));
}
void Reset()
{
Berserk = false;
NetherInfusionTimer = 540000;
VoidZoneTimer = 15000;
NetherbreathTimer = 3000;
HandleDoors(true);
DestroyPortals();
}
void SummonPortals()
{
uint8 r = rand()%4;
uint8 pos[3];
pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0);
pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1));
pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0)
for (int i=0; i<3; ++i)
if (Creature *portal = me->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000))
for (int i=0; i<3; ++i)
{
PortalGUID[i] = portal->GetGUID();
portal->AddAura(PortalVisual[i], portal);
PortalGUID[i] = 0;
BeamTarget[i] = 0;
BeamerGUID[i] = 0;
}
}
void DestroyPortals()
{
for (int i=0; i<3; ++i)
{
if (Creature *portal = Unit::GetCreature(*me, PortalGUID[i]))
portal->DisappearAndDie();
if (Creature *portal = Unit::GetCreature(*me, BeamerGUID[i]))
portal->DisappearAndDie();
PortalGUID[i] = 0;
BeamTarget[i] = 0;
}
}
void UpdatePortals() // Here we handle the beams' behavior
{
for (int j=0; j<3; ++j) // j = color
if (Creature *portal = Unit::GetCreature(*me, PortalGUID[j]))
{
// the one who's been casted upon before
Unit *current = Unit::GetUnit(*portal, BeamTarget[j]);
// temporary store for the best suitable beam reciever
Unit *pTarget = me;
InstanceScript* pInstance;
if (Map* map = me->GetMap())
{
Map::PlayerList const& players = map->GetPlayers();
bool PortalPhase;
bool Berserk;
uint32 PhaseTimer; // timer for phase switching
uint32 VoidZoneTimer;
uint32 NetherInfusionTimer; // berserking timer
uint32 NetherbreathTimer;
uint32 EmpowermentTimer;
uint32 PortalTimer; // timer for beam checking
uint64 PortalGUID[3]; // guid's of portals
uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals
uint64 BeamTarget[3]; // guid's of portals' current targets
// get the best suitable target
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
{
Player* p = i->getSource();
if (p && p->isAlive() // alive
&& (!pTarget || pTarget->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best
&& !p->HasAura(PlayerDebuff[j],0) // not exhausted
&& !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam
&& !p->HasAura(PlayerBuff[(j+2)%3],0)
&& IsBetween(me, p, portal)) // on the beam
pTarget = p;
}
}
// buff the target
if (pTarget->GetTypeId() == TYPEID_PLAYER)
pTarget->AddAura(PlayerBuff[j], pTarget);
else
pTarget->AddAura(NetherBuff[j], pTarget);
// cast visual beam on the chosen target if switched
// simple target switching isn't working -> using BeamerGUID to cast (workaround)
if (!current || pTarget != current)
{
BeamTarget[j] = pTarget->GetGUID();
// remove currently beaming portal
if (Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j]))
{
beamer->CastSpell(pTarget, PortalBeam[j], false);
beamer->DisappearAndDie();
BeamerGUID[j] = 0;
}
// create new one and start beaming on the target
if (Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000))
{
beamer->CastSpell(pTarget, PortalBeam[j], false);
BeamerGUID[j] = beamer->GetGUID();
}
}
// aggro target if Red Beam
if (j == RED_PORTAL && me->getVictim() != pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
me->getThreatManager().addThreat(pTarget, 100000.0f+DoGetThreat(me->getVictim()));
}
}
void SwitchToPortalPhase()
{
me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT);
me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL);
SummonPortals();
PhaseTimer = 60000;
PortalPhase = true;
PortalTimer = 10000;
EmpowermentTimer = 10000;
DoScriptText(EMOTE_PHASE_PORTAL,me);
}
void SwitchToBanishPhase()
{
me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT);
me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA);
DoCast(me, SPELL_BANISH_VISUAL, true);
DoCast(me, SPELL_BANISH_ROOT, true);
DestroyPortals();
PhaseTimer = 30000;
PortalPhase = false;
DoScriptText(EMOTE_PHASE_BANISH,me);
for (int i=0; i<3; ++i)
me->RemoveAurasDueToSpell(NetherBuff[i]);
}
void HandleDoors(bool open) // Massive Door switcher
{
if (GameObject *Door = GameObject::GetGameObject(*me, pInstance ? pInstance->GetData64(DATA_GO_MASSIVE_DOOR) : 0))
Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
}
void EnterCombat(Unit * /*who*/)
{
HandleDoors(false);
SwitchToPortalPhase();
}
void JustDied(Unit* /*killer*/)
{
HandleDoors(true);
DestroyPortals();
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
// Void Zone
if (VoidZoneTimer <= diff)
bool IsBetween(WorldObject* u1, WorldObject *pTarget, WorldObject* u2) // the in-line checker
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true);
if (!u1 || !u2 || !pTarget)
return false;
float xn, yn, xp, yp, xh, yh;
xn = u1->GetPositionX();
yn = u1->GetPositionY();
xp = u2->GetPositionX();
yp = u2->GetPositionY();
xh = pTarget->GetPositionX();
yh = pTarget->GetPositionY();
// check if target is between (not checking distance from the beam yet)
if (dist(xn,yn,xh,yh) >= dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh) >= dist(xn,yn,xp,yp))
return false;
// check distance from the beam
return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f);
}
float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance
{
return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb));
}
void Reset()
{
Berserk = false;
NetherInfusionTimer = 540000;
VoidZoneTimer = 15000;
} else VoidZoneTimer -= diff;
NetherbreathTimer = 3000;
// NetherInfusion Berserk
if (!Berserk && NetherInfusionTimer <= diff)
{
me->AddAura(SPELL_NETHER_INFUSION, me);
DoCast(me, SPELL_NETHERSPITE_ROAR);
Berserk = true;
} else NetherInfusionTimer -= diff;
if (PortalPhase) // PORTAL PHASE
{
// Distribute beams and buffs
if (PortalTimer <= diff)
{
UpdatePortals();
PortalTimer = 1000;
} else PortalTimer -= diff;
// Empowerment & Nether Burn
if (EmpowermentTimer <= diff)
{
DoCast(me, SPELL_EMPOWERMENT);
me->AddAura(SPELL_NETHERBURN_AURA, me);
EmpowermentTimer = 90000;
} else EmpowermentTimer -= diff;
if (PhaseTimer <= diff)
{
if (!me->IsNonMeleeSpellCasted(false))
{
SwitchToBanishPhase();
return;
}
} else PhaseTimer -= diff;
}
else // BANISH PHASE
{
// Netherbreath
if (NetherbreathTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,40,true))
DoCast(pTarget, SPELL_NETHERBREATH);
NetherbreathTimer = urand(5000,7000);
} else NetherbreathTimer -= diff;
if (PhaseTimer <= diff)
{
if (!me->IsNonMeleeSpellCasted(false))
{
SwitchToPortalPhase();
return;
}
} else PhaseTimer -= diff;
HandleDoors(true);
DestroyPortals();
}
DoMeleeAttackIfReady();
}
void SummonPortals()
{
uint8 r = rand()%4;
uint8 pos[3];
pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0);
pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1));
pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0)
for (int i=0; i<3; ++i)
if (Creature *portal = me->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000))
{
PortalGUID[i] = portal->GetGUID();
portal->AddAura(PortalVisual[i], portal);
}
}
void DestroyPortals()
{
for (int i=0; i<3; ++i)
{
if (Creature *portal = Unit::GetCreature(*me, PortalGUID[i]))
portal->DisappearAndDie();
if (Creature *portal = Unit::GetCreature(*me, BeamerGUID[i]))
portal->DisappearAndDie();
PortalGUID[i] = 0;
BeamTarget[i] = 0;
}
}
void UpdatePortals() // Here we handle the beams' behavior
{
for (int j=0; j<3; ++j) // j = color
if (Creature *portal = Unit::GetCreature(*me, PortalGUID[j]))
{
// the one who's been casted upon before
Unit *current = Unit::GetUnit(*portal, BeamTarget[j]);
// temporary store for the best suitable beam reciever
Unit *pTarget = me;
if (Map* map = me->GetMap())
{
Map::PlayerList const& players = map->GetPlayers();
// get the best suitable target
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
{
Player* p = i->getSource();
if (p && p->isAlive() // alive
&& (!pTarget || pTarget->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best
&& !p->HasAura(PlayerDebuff[j],0) // not exhausted
&& !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam
&& !p->HasAura(PlayerBuff[(j+2)%3],0)
&& IsBetween(me, p, portal)) // on the beam
pTarget = p;
}
}
// buff the target
if (pTarget->GetTypeId() == TYPEID_PLAYER)
pTarget->AddAura(PlayerBuff[j], pTarget);
else
pTarget->AddAura(NetherBuff[j], pTarget);
// cast visual beam on the chosen target if switched
// simple target switching isn't working -> using BeamerGUID to cast (workaround)
if (!current || pTarget != current)
{
BeamTarget[j] = pTarget->GetGUID();
// remove currently beaming portal
if (Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j]))
{
beamer->CastSpell(pTarget, PortalBeam[j], false);
beamer->DisappearAndDie();
BeamerGUID[j] = 0;
}
// create new one and start beaming on the target
if (Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000))
{
beamer->CastSpell(pTarget, PortalBeam[j], false);
BeamerGUID[j] = beamer->GetGUID();
}
}
// aggro target if Red Beam
if (j == RED_PORTAL && me->getVictim() != pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
me->getThreatManager().addThreat(pTarget, 100000.0f+DoGetThreat(me->getVictim()));
}
}
void SwitchToPortalPhase()
{
me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT);
me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL);
SummonPortals();
PhaseTimer = 60000;
PortalPhase = true;
PortalTimer = 10000;
EmpowermentTimer = 10000;
DoScriptText(EMOTE_PHASE_PORTAL,me);
}
void SwitchToBanishPhase()
{
me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT);
me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA);
DoCast(me, SPELL_BANISH_VISUAL, true);
DoCast(me, SPELL_BANISH_ROOT, true);
DestroyPortals();
PhaseTimer = 30000;
PortalPhase = false;
DoScriptText(EMOTE_PHASE_BANISH,me);
for (int i=0; i<3; ++i)
me->RemoveAurasDueToSpell(NetherBuff[i]);
}
void HandleDoors(bool open) // Massive Door switcher
{
if (GameObject *Door = GameObject::GetGameObject(*me, pInstance ? pInstance->GetData64(DATA_GO_MASSIVE_DOOR) : 0))
Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
}
void EnterCombat(Unit * /*who*/)
{
HandleDoors(false);
SwitchToPortalPhase();
}
void JustDied(Unit* /*killer*/)
{
HandleDoors(true);
DestroyPortals();
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
// Void Zone
if (VoidZoneTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true);
VoidZoneTimer = 15000;
} else VoidZoneTimer -= diff;
// NetherInfusion Berserk
if (!Berserk && NetherInfusionTimer <= diff)
{
me->AddAura(SPELL_NETHER_INFUSION, me);
DoCast(me, SPELL_NETHERSPITE_ROAR);
Berserk = true;
} else NetherInfusionTimer -= diff;
if (PortalPhase) // PORTAL PHASE
{
// Distribute beams and buffs
if (PortalTimer <= diff)
{
UpdatePortals();
PortalTimer = 1000;
} else PortalTimer -= diff;
// Empowerment & Nether Burn
if (EmpowermentTimer <= diff)
{
DoCast(me, SPELL_EMPOWERMENT);
me->AddAura(SPELL_NETHERBURN_AURA, me);
EmpowermentTimer = 90000;
} else EmpowermentTimer -= diff;
if (PhaseTimer <= diff)
{
if (!me->IsNonMeleeSpellCasted(false))
{
SwitchToBanishPhase();
return;
}
} else PhaseTimer -= diff;
}
else // BANISH PHASE
{
// Netherbreath
if (NetherbreathTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,40,true))
DoCast(pTarget, SPELL_NETHERBREATH);
NetherbreathTimer = urand(5000,7000);
} else NetherbreathTimer -= diff;
if (PhaseTimer <= diff)
{
if (!me->IsNonMeleeSpellCasted(false))
{
SwitchToPortalPhase();
return;
}
} else PhaseTimer -= diff;
}
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_netherspite(Creature *pCreature)
{
return new boss_netherspiteAI(pCreature);
}
void AddSC_boss_netherspite()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_netherspite";
newscript->GetAI = GetAI_boss_netherspite;
newscript->RegisterSelf();
new boss_netherspite();
}
@@ -57,364 +57,366 @@ float IntroWay[8][3] =
{-11140 , -1915 ,122},
{-11163 , -1903 ,91.473}
};
struct boss_nightbaneAI : public ScriptedAI
␍class boss_nightbane : public CreatureScript
{
boss_nightbaneAI(Creature* c) : ScriptedAI(c)
public:
boss_nightbane() : CreatureScript("boss_nightbane") { }
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
Intro = true;
return new boss_nightbaneAI (pCreature);
}
ScriptedInstance* pInstance;
uint32 Phase;
bool RainBones;
bool Skeletons;
uint32 BellowingRoarTimer;
uint32 CharredEarthTimer;
uint32 DistractingAshTimer;
uint32 SmolderingBreathTimer;
uint32 TailSweepTimer;
uint32 RainofBonesTimer;
uint32 SmokingBlastTimer;
uint32 FireballBarrageTimer;
uint32 SearingCindersTimer;
uint32 FlyCount;
uint32 FlyTimer;
bool Intro;
bool Flying;
bool Movement;
uint32 WaitTimer;
uint32 MovePhase;
void Reset()
struct boss_nightbaneAI : public ScriptedAI
{
BellowingRoarTimer = 30000;
CharredEarthTimer = 15000;
DistractingAshTimer = 20000;
SmolderingBreathTimer = 10000;
TailSweepTimer = 12000;
RainofBonesTimer = 10000;
SmokingBlastTimer = 20000;
FireballBarrageTimer = 13000;
SearingCindersTimer = 14000;
WaitTimer = 1000;
Phase =1;
FlyCount = 0;
MovePhase = 0;
me->SetSpeed(MOVE_RUN, 2.0f);
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
me->setActive(true);
if (pInstance)
boss_nightbaneAI(Creature* c) : ScriptedAI(c)
{
if (pInstance->GetData(TYPE_NIGHTBANE) == DONE || pInstance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS)
me->DisappearAndDie();
else
pInstance->SetData(TYPE_NIGHTBANE, NOT_STARTED);
pInstance = c->GetInstanceScript();
Intro = true;
}
HandleTerraceDoors(true);
InstanceScript* pInstance;
Flying = false;
Movement = false;
uint32 Phase;
if (!Intro)
bool RainBones;
bool Skeletons;
uint32 BellowingRoarTimer;
uint32 CharredEarthTimer;
uint32 DistractingAshTimer;
uint32 SmolderingBreathTimer;
uint32 TailSweepTimer;
uint32 RainofBonesTimer;
uint32 SmokingBlastTimer;
uint32 FireballBarrageTimer;
uint32 SearingCindersTimer;
uint32 FlyCount;
uint32 FlyTimer;
bool Intro;
bool Flying;
bool Movement;
uint32 WaitTimer;
uint32 MovePhase;
void Reset()
{
me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0);
me->GetMotionMaster()->MoveTargetedHome();
}
}
BellowingRoarTimer = 30000;
CharredEarthTimer = 15000;
DistractingAshTimer = 20000;
SmolderingBreathTimer = 10000;
TailSweepTimer = 12000;
RainofBonesTimer = 10000;
SmokingBlastTimer = 20000;
FireballBarrageTimer = 13000;
SearingCindersTimer = 14000;
WaitTimer = 1000;
void HandleTerraceDoors(bool open)
{
if (pInstance)
{
pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open);
pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open);
}
}
Phase =1;
FlyCount = 0;
MovePhase = 0;
void EnterCombat(Unit * /*who*/)
{
if (pInstance)
pInstance->SetData(TYPE_NIGHTBANE, IN_PROGRESS);
me->SetSpeed(MOVE_RUN, 2.0f);
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
me->setActive(true);
HandleTerraceDoors(false);
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
}
void AttackStart(Unit* who)
{
if (!Intro && !Flying)
ScriptedAI::AttackStart(who);
}
void JustDied(Unit* /*killer*/)
{
if (pInstance)
pInstance->SetData(TYPE_NIGHTBANE, DONE);
HandleTerraceDoors(true);
}
void MoveInLineOfSight(Unit *who)
{
if (!Intro && !Flying)
ScriptedAI::MoveInLineOfSight(who);
}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (Intro)
{
if (id >= 8)
if (pInstance)
{
if (pInstance->GetData(TYPE_NIGHTBANE) == DONE || pInstance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS)
me->DisappearAndDie();
else
pInstance->SetData(TYPE_NIGHTBANE, NOT_STARTED);
}
HandleTerraceDoors(true);
Flying = false;
Movement = false;
if (!Intro)
{
Intro = false;
me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0);
return;
me->GetMotionMaster()->MoveTargetedHome();
}
WaitTimer = 1;
}
if (Flying)
void HandleTerraceDoors(bool open)
{
if (id == 0)
if (pInstance)
{
me->MonsterTextEmote(EMOTE_BREATH, 0, true);
Flying = false;
Phase = 2;
return;
pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open);
pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open);
}
if (id == 3)
{
MovePhase = 4;
WaitTimer = 1;
return;
}
if (id == 8)
{
Flying = false;
Phase = 1;
Movement = true;
return;
}
WaitTimer = 1;
}
}
void JustSummoned(Creature *summoned)
{
summoned->AI()->AttackStart(me->getVictim());
}
void TakeOff()
{
me->MonsterYell(YELL_FLY_PHASE, LANG_UNIVERSAL, NULL);
me->InterruptSpell(CURRENT_GENERIC_SPELL);
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
(*me).GetMotionMaster()->Clear(false);
(*me).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]);
Flying = true;
FlyTimer = urand(45000,60000); //timer wrong between 45 and 60 seconds
++FlyCount;
RainofBonesTimer = 5000; //timer wrong (maybe)
RainBones = false;
Skeletons = false;
}
void UpdateAI(const uint32 diff)
{
/* The timer for this was never setup apparently, not sure if the code works properly:
if (WaitTimer <= diff)
void EnterCombat(Unit * /*who*/)
{
if (pInstance)
pInstance->SetData(TYPE_NIGHTBANE, IN_PROGRESS);
HandleTerraceDoors(false);
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
}
void AttackStart(Unit* who)
{
if (!Intro && !Flying)
ScriptedAI::AttackStart(who);
}
void JustDied(Unit* /*killer*/)
{
if (pInstance)
pInstance->SetData(TYPE_NIGHTBANE, DONE);
HandleTerraceDoors(true);
}
void MoveInLineOfSight(Unit *who)
{
if (!Intro && !Flying)
ScriptedAI::MoveInLineOfSight(who);
}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (Intro)
{
if (MovePhase >= 7)
if (id >= 8)
{
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]);
}
else
{
me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]);
++MovePhase;
Intro = false;
me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0);
return;
}
WaitTimer = 1;
}
if (Flying)
{
if (MovePhase >= 7)
if (id == 0)
{
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]);
me->MonsterTextEmote(EMOTE_BREATH, 0, true);
Flying = false;
Phase = 2;
return;
}
else
if (id == 3)
{
me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]);
++MovePhase;
MovePhase = 4;
WaitTimer = 1;
return;
}
if (id == 8)
{
Flying = false;
Phase = 1;
Movement = true;
return;
}
WaitTimer = 1;
}
WaitTimer = 0;
} else WaitTimer -= diff;
*/
if (!UpdateVictim())
return;
if (Flying)
return;
// Phase 1 "GROUND FIGHT"
if (Phase == 1)
{
if (Movement)
{
DoStartMovement(me->getVictim());
Movement = false;
}
if (BellowingRoarTimer <= diff)
{
DoCast(me->getVictim(), SPELL_BELLOWING_ROAR);
BellowingRoarTimer = urand(30000,40000);
} else BellowingRoarTimer -= diff;
if (SmolderingBreathTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SMOLDERING_BREATH);
SmolderingBreathTimer = 20000;
} else SmolderingBreathTimer -= diff;
if (CharredEarthTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_CHARRED_EARTH);
CharredEarthTimer = 20000;
} else CharredEarthTimer -= diff;
if (TailSweepTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
if (!me->HasInArc(M_PI, pTarget))
DoCast(pTarget, SPELL_TAIL_SWEEP);
TailSweepTimer = 15000;
} else TailSweepTimer -= diff;
if (SearingCindersTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_SEARING_CINDERS);
SearingCindersTimer = 10000;
} else SearingCindersTimer -= diff;
uint32 Prozent;
Prozent = (me->GetHealth()*100) / me->GetMaxHealth();
if (Prozent < 75 && FlyCount == 0) // first take off 75%
TakeOff();
if (Prozent < 50 && FlyCount == 1) // secound take off 50%
TakeOff();
if (Prozent < 25 && FlyCount == 2) // third take off 25%
TakeOff();
DoMeleeAttackIfReady();
}
//Phase 2 "FLYING FIGHT"
if (Phase == 2)
void JustSummoned(Creature *summoned)
{
if (!RainBones)
summoned->AI()->AttackStart(me->getVictim());
}
void TakeOff()
{
me->MonsterYell(YELL_FLY_PHASE, LANG_UNIVERSAL, NULL);
me->InterruptSpell(CURRENT_GENERIC_SPELL);
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
(*me).GetMotionMaster()->Clear(false);
(*me).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]);
Flying = true;
FlyTimer = urand(45000,60000); //timer wrong between 45 and 60 seconds
++FlyCount;
RainofBonesTimer = 5000; //timer wrong (maybe)
RainBones = false;
Skeletons = false;
}
void UpdateAI(const uint32 diff)
{
/* The timer for this was never setup apparently, not sure if the code works properly:
if (WaitTimer <= diff)
{
if (!Skeletons)
if (Intro)
{
for (uint8 i = 0; i <= 3; ++i)
if (MovePhase >= 7)
{
DoCast(me->getVictim(), SPELL_SUMMON_SKELETON);
Skeletons = true;
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]);
}
else
{
me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]);
++MovePhase;
}
}
if (Flying)
{
if (MovePhase >= 7)
{
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]);
}
else
{
me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]);
++MovePhase;
}
}
if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2
{
DoCast(me->getVictim(), SPELL_RAIN_OF_BONES);
RainBones = true;
SmokingBlastTimer = 20000;
} else RainofBonesTimer -= diff;
WaitTimer = 0;
} else WaitTimer -= diff;
*/
if (DistractingAshTimer <= diff)
if (!UpdateVictim())
return;
if (Flying)
return;
// Phase 1 "GROUND FIGHT"
if (Phase == 1)
{
if (Movement)
{
DoStartMovement(me->getVictim());
Movement = false;
}
if (BellowingRoarTimer <= diff)
{
DoCast(me->getVictim(), SPELL_BELLOWING_ROAR);
BellowingRoarTimer = urand(30000,40000);
} else BellowingRoarTimer -= diff;
if (SmolderingBreathTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SMOLDERING_BREATH);
SmolderingBreathTimer = 20000;
} else SmolderingBreathTimer -= diff;
if (CharredEarthTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_DISTRACTING_ASH);
DistractingAshTimer = 2000; //timer wrong
} else DistractingAshTimer -= diff;
DoCast(pTarget, SPELL_CHARRED_EARTH);
CharredEarthTimer = 20000;
} else CharredEarthTimer -= diff;
if (TailSweepTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
if (!me->HasInArc(M_PI, pTarget))
DoCast(pTarget, SPELL_TAIL_SWEEP);
TailSweepTimer = 15000;
} else TailSweepTimer -= diff;
if (SearingCindersTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_SEARING_CINDERS);
SearingCindersTimer = 10000;
} else SearingCindersTimer -= diff;
uint32 Prozent;
Prozent = (me->GetHealth()*100) / me->GetMaxHealth();
if (Prozent < 75 && FlyCount == 0) // first take off 75%
TakeOff();
if (Prozent < 50 && FlyCount == 1) // secound take off 50%
TakeOff();
if (Prozent < 25 && FlyCount == 2) // third take off 25%
TakeOff();
DoMeleeAttackIfReady();
}
if (RainBones)
//Phase 2 "FLYING FIGHT"
if (Phase == 2)
{
if (SmokingBlastTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SMOKING_BLAST);
SmokingBlastTimer = 1500; //timer wrong
} else SmokingBlastTimer -= diff;
if (!RainBones)
{
if (!Skeletons)
{
for (uint8 i = 0; i <= 3; ++i)
{
DoCast(me->getVictim(), SPELL_SUMMON_SKELETON);
Skeletons = true;
}
}
if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2
{
DoCast(me->getVictim(), SPELL_RAIN_OF_BONES);
RainBones = true;
SmokingBlastTimer = 20000;
} else RainofBonesTimer -= diff;
if (DistractingAshTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_DISTRACTING_ASH);
DistractingAshTimer = 2000; //timer wrong
} else DistractingAshTimer -= diff;
}
if (RainBones)
{
if (SmokingBlastTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SMOKING_BLAST);
SmokingBlastTimer = 1500; //timer wrong
} else SmokingBlastTimer -= diff;
}
if (FireballBarrageTimer <= diff)
{
if (Unit *pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0))
DoCast(pTarget, SPELL_FIREBALL_BARRAGE);
FireballBarrageTimer = 20000;
} else FireballBarrageTimer -= diff;
if (FlyTimer <= diff) //landing
{
me->MonsterYell(RAND(*YELL_LAND_PHASE_1,*YELL_LAND_PHASE_2), LANG_UNIVERSAL, NULL);
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]);
Flying = true;
} else FlyTimer -= diff;
}
if (FireballBarrageTimer <= diff)
{
if (Unit *pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0))
DoCast(pTarget, SPELL_FIREBALL_BARRAGE);
FireballBarrageTimer = 20000;
} else FireballBarrageTimer -= diff;
if (FlyTimer <= diff) //landing
{
me->MonsterYell(RAND(*YELL_LAND_PHASE_1,*YELL_LAND_PHASE_2), LANG_UNIVERSAL, NULL);
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]);
Flying = true;
} else FlyTimer -= diff;
}
}
};
};
CreatureAI* GetAI_boss_nightbane(Creature* pCreature)
{
return new boss_nightbaneAI (pCreature);
}
void AddSC_boss_nightbane()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_nightbane";
newscript->GetAI = &GetAI_boss_nightbane;
newscript->RegisterSelf();
new boss_nightbane();
}
@@ -95,512 +95,513 @@ static InfernalPoint InfernalPoints[] =
#define EQUIP_ID_AXE 33542 //Axes info
//---------Infernal code first
struct netherspite_infernalAI : public ScriptedAI
//---------Infernal code first␍class netherspite_infernal : public CreatureScript
{
netherspite_infernalAI(Creature *c) : ScriptedAI(c) ,
malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {}
public:
netherspite_infernal() : CreatureScript("netherspite_infernal") { }
uint32 HellfireTimer;
uint32 CleanupTimer;
uint32 malchezaar;
InfernalPoint *point;
void Reset() {}
void EnterCombat(Unit * /*who*/) {}
void MoveInLineOfSight(Unit * /*who*/) {}
void UpdateAI(const uint32 diff)
CreatureAI* GetAI(Creature* pCreature) const
{
if (HellfireTimer)
if (HellfireTimer <= diff)
return new netherspite_infernalAI (pCreature);
}
struct netherspite_infernalAI : public ScriptedAI
{
netherspite_infernalAI(Creature *c) : ScriptedAI(c) ,
malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {}
uint32 HellfireTimer;
uint32 CleanupTimer;
uint32 malchezaar;
InfernalPoint *point;
void Reset() {}
void EnterCombat(Unit * /*who*/) {}
void MoveInLineOfSight(Unit * /*who*/) {}
void UpdateAI(const uint32 diff)
{
DoCast(me, SPELL_HELLFIRE);
HellfireTimer = 0;
if (HellfireTimer)
if (HellfireTimer <= diff)
{
DoCast(me, SPELL_HELLFIRE);
HellfireTimer = 0;
}
else HellfireTimer -= diff;
if (CleanupTimer)
if (CleanupTimer <= diff)
{
Cleanup();
CleanupTimer = 0;
} else CleanupTimer -= diff;
}
else HellfireTimer -= diff;
if (CleanupTimer)
if (CleanupTimer <= diff)
void KilledUnit(Unit *who)
{
Cleanup();
CleanupTimer = 0;
} else CleanupTimer -= diff;
}
void KilledUnit(Unit *who)
{
Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar);
if (pMalchezaar)
CAST_CRE(pMalchezaar)->AI()->KilledUnit(who);
}
void SpellHit(Unit * /*who*/, const SpellEntry *spell)
{
if (spell->Id == SPELL_INFERNAL_RELAY)
{
me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID));
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
HellfireTimer = 4000;
CleanupTimer = 170000;
Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar);
if (pMalchezaar)
CAST_CRE(pMalchezaar)->AI()->KilledUnit(who);
}
}
void DamageTaken(Unit *done_by, uint32 &damage)
{
if (done_by->GetGUID() != malchezaar)
damage = 0;
}
void SpellHit(Unit * /*who*/, const SpellEntry *spell)
{
if (spell->Id == SPELL_INFERNAL_RELAY)
{
me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID));
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
HellfireTimer = 4000;
CleanupTimer = 170000;
}
}
void DamageTaken(Unit *done_by, uint32 &damage)
{
if (done_by->GetGUID() != malchezaar)
damage = 0;
}
void Cleanup()
{
Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar);
if (pMalchezaar && pMalchezaar->isAlive())
CAST_AI(boss_malchezaar::boss_malchezaarAI, CAST_CRE(pMalchezaar)->AI())->Cleanup(me, point);
}␍ //below ...
};
void Cleanup(); //below ...
};
struct boss_malchezaarAI : public ScriptedAI
␍class boss_malchezaar : public CreatureScript
{
boss_malchezaarAI(Creature *c) : ScriptedAI(c)
public:
boss_malchezaar() : CreatureScript("boss_malchezaar") { }
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
return new boss_malchezaarAI (pCreature);
}
ScriptedInstance *pInstance;
uint32 EnfeebleTimer;
uint32 EnfeebleResetTimer;
uint32 ShadowNovaTimer;
uint32 SWPainTimer;
uint32 SunderArmorTimer;
uint32 AmplifyDamageTimer;
uint32 Cleave_Timer;
uint32 InfernalTimer;
uint32 AxesTargetSwitchTimer;
uint32 InfernalCleanupTimer;
std::vector<uint64> infernals;
std::vector<InfernalPoint*> positions;
uint64 axes[2];
uint64 enfeeble_targets[5];
uint64 enfeeble_health[5];
uint32 phase;
void Reset()
struct boss_malchezaarAI : public ScriptedAI
{
AxesCleanup();
ClearWeapons();
InfernalCleanup();
positions.clear();
for (uint8 i = 0; i < 5; ++i)
enfeeble_targets[i] = 0;
for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
positions.push_back(&InfernalPoints[i]);
EnfeebleTimer = 30000;
EnfeebleResetTimer = 38000;
ShadowNovaTimer = 35500;
SWPainTimer = 20000;
AmplifyDamageTimer = 5000;
Cleave_Timer = 8000;
InfernalTimer = 45000;
InfernalCleanupTimer = 47000;
AxesTargetSwitchTimer = urand(7500,20000);
SunderArmorTimer = urand(5000,10000);
phase = 1;
if (pInstance)
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true);
}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me);
}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
AxesCleanup();
ClearWeapons();
InfernalCleanup();
positions.clear();
for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
positions.push_back(&InfernalPoints[i]);
if (pInstance)
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true);
}
void EnterCombat(Unit * /*who*/)
{
DoScriptText(SAY_AGGRO, me);
if (pInstance)
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in
}
void InfernalCleanup()
{
//Infernal Cleanup
for (std::vector<uint64>::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr)
if (Unit *pInfernal = Unit::GetUnit(*me, *itr))
if (pInfernal->isAlive())
{
pInfernal->SetVisibility(VISIBILITY_OFF);
pInfernal->setDeathState(JUST_DIED);
}
infernals.clear();
}
void AxesCleanup()
{
for (uint8 i = 0; i < 2; ++i)
boss_malchezaarAI(Creature *c) : ScriptedAI(c)
{
Unit *axe = Unit::GetUnit(*me, axes[i]);
if (axe && axe->isAlive())
axe->Kill(axe);
axes[i] = 0;
}
}
void ClearWeapons()
{
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
//damage
const CreatureInfo *cinfo = me->GetCreatureInfo();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg);
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg);
me->UpdateDamagePhysical(BASE_ATTACK);
}
void EnfeebleHealthEffect()
{
const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT);
if (!info)
return;
std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
std::vector<Unit *> targets;
if (!t_list.size())
return;
//begin + 1, so we don't target the one with the highest threat
std::list<HostileReference *>::const_iterator itr = t_list.begin();
std::advance(itr, 1);
for (; itr != t_list.end(); ++itr) //store the threat list in a different container
if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()))
if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
targets.push_back(pTarget);
//cut down to size if we have more than 5 targets
while (targets.size() > 5)
targets.erase(targets.begin()+rand()%targets.size());
uint32 i = 0;
for (std::vector<Unit *>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i)
if (Unit *pTarget = *iter)
{
enfeeble_targets[i] = pTarget->GetGUID();
enfeeble_health[i] = pTarget->GetHealth();
pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID());
pTarget->SetHealth(1);
}
}
void EnfeebleResetHealth()
{
for (uint8 i = 0; i < 5; ++i)
{
Unit *pTarget = Unit::GetUnit(*me, enfeeble_targets[i]);
if (pTarget && pTarget->isAlive())
pTarget->SetHealth(enfeeble_health[i]);
enfeeble_targets[i] = 0;
enfeeble_health[i] = 0;
}
}
void SummonInfernal(const uint32 /*diff*/)
{
InfernalPoint *point = NULL;
Position pos;
if ((me->GetMapId() != 532) || positions.empty())
me->GetRandomNearPosition(pos, 60);
else
{
std::vector<InfernalPoint*>::iterator itr = positions.begin()+rand()%positions.size();
point = *itr;
positions.erase(itr);
pos.Relocate(point->x, point->y, INFERNAL_Z);
pInstance = c->GetInstanceScript();
}
Creature *Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000);
InstanceScript *pInstance;
uint32 EnfeebleTimer;
uint32 EnfeebleResetTimer;
uint32 ShadowNovaTimer;
uint32 SWPainTimer;
uint32 SunderArmorTimer;
uint32 AmplifyDamageTimer;
uint32 Cleave_Timer;
uint32 InfernalTimer;
uint32 AxesTargetSwitchTimer;
uint32 InfernalCleanupTimer;
if (Infernal)
std::vector<uint64> infernals;
std::vector<InfernalPoint*> positions;
uint64 axes[2];
uint64 enfeeble_targets[5];
uint64 enfeeble_health[5];
uint32 phase;
void Reset()
{
Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE);
Infernal->setFaction(me->getFaction());
if (point)
CAST_AI(netherspite_infernalAI, Infernal->AI())->point=point;
CAST_AI(netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID();
AxesCleanup();
ClearWeapons();
InfernalCleanup();
positions.clear();
infernals.push_back(Infernal->GetGUID());
DoCast(Infernal, SPELL_INFERNAL_RELAY);
for (uint8 i = 0; i < 5; ++i)
enfeeble_targets[i] = 0;
for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
positions.push_back(&InfernalPoints[i]);
EnfeebleTimer = 30000;
EnfeebleResetTimer = 38000;
ShadowNovaTimer = 35500;
SWPainTimer = 20000;
AmplifyDamageTimer = 5000;
Cleave_Timer = 8000;
InfernalTimer = 45000;
InfernalCleanupTimer = 47000;
AxesTargetSwitchTimer = urand(7500,20000);
SunderArmorTimer = urand(5000,10000);
phase = 1;
if (pInstance)
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true);
}
DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that
void KilledUnit(Unit * /*victim*/)
{
EnfeebleResetHealth();
EnfeebleResetTimer = 0;
} else EnfeebleResetTimer -= diff;
if (me->hasUnitState(UNIT_STAT_STUNNED)) // While shifting to phase 2 malchezaar stuns himself
return;
if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->getVictim()->GetGUID())
me->SetUInt64Value(UNIT_FIELD_TARGET, me->getVictim()->GetGUID());
if (phase == 1)
{
if ((me->GetHealth()*100) / me->GetMaxHealth() < 60)
{
me->InterruptNonMeleeSpells(false);
phase = 2;
//animation
DoCast(me, SPELL_EQUIP_AXES);
//text
DoScriptText(SAY_AXE_TOSS1, me);
//passive thrash aura
DoCast(me, SPELL_THRASH_AURA, true);
//models
SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
//damage
const CreatureInfo *cinfo = me->GetCreatureInfo();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg);
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg);
me->UpdateDamagePhysical(BASE_ATTACK);
me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg);
me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg);
//Sigh, updating only works on main attack, do it manually ....
me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg);
me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg);
me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100);
}
DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me);
}
else if (phase == 2)
void JustDied(Unit * /*victim*/)
{
if ((me->GetHealth()*100) / me->GetMaxHealth() < 30)
{
InfernalTimer = 15000;
DoScriptText(SAY_DEATH, me);
phase = 3;
AxesCleanup();
ClearWeapons();
InfernalCleanup();
positions.clear();
ClearWeapons();
for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
positions.push_back(&InfernalPoints[i]);
//remove thrash
me->RemoveAurasDueToSpell(SPELL_THRASH_AURA);
if (pInstance)
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true);
}
DoScriptText(SAY_AXE_TOSS2, me);
void EnterCombat(Unit * /*who*/)
{
DoScriptText(SAY_AGGRO, me);
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
for (uint8 i = 0; i < 2; ++i)
{
Creature *axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
if (axe)
if (pInstance)
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in
}
void InfernalCleanup()
{
//Infernal Cleanup
for (std::vector<uint64>::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr)
if (Unit *pInfernal = Unit::GetUnit(*me, *itr))
if (pInfernal->isAlive())
{
axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
axe->setFaction(me->getFaction());
axes[i] = axe->GetGUID();
if (pTarget)
{
axe->AI()->AttackStart(pTarget);
//axe->getThreatManager().tauntApply(pTarget); //Taunt Apply and fade out does not work properly
// So we'll use a hack to add a lot of threat to our target
axe->AddThreat(pTarget, 10000000.0f);
}
pInfernal->SetVisibility(VISIBILITY_OFF);
pInfernal->setDeathState(JUST_DIED);
}
}
if (ShadowNovaTimer > 35000)
ShadowNovaTimer = EnfeebleTimer + 5000;
infernals.clear();
}
void AxesCleanup()
{
for (uint8 i = 0; i < 2; ++i)
{
Unit *axe = Unit::GetUnit(*me, axes[i]);
if (axe && axe->isAlive())
axe->Kill(axe);
axes[i] = 0;
}
}
void ClearWeapons()
{
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
//damage
const CreatureInfo *cinfo = me->GetCreatureInfo();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg);
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg);
me->UpdateDamagePhysical(BASE_ATTACK);
}
void EnfeebleHealthEffect()
{
const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT);
if (!info)
return;
std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
std::vector<Unit *> targets;
if (!t_list.size())
return;
//begin + 1, so we don't target the one with the highest threat
std::list<HostileReference *>::const_iterator itr = t_list.begin();
std::advance(itr, 1);
for (; itr != t_list.end(); ++itr) //store the threat list in a different container
if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()))
if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
targets.push_back(pTarget);
//cut down to size if we have more than 5 targets
while (targets.size() > 5)
targets.erase(targets.begin()+rand()%targets.size());
uint32 i = 0;
for (std::vector<Unit *>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i)
if (Unit *pTarget = *iter)
{
enfeeble_targets[i] = pTarget->GetGUID();
enfeeble_health[i] = pTarget->GetHealth();
pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID());
pTarget->SetHealth(1);
}
}
void EnfeebleResetHealth()
{
for (uint8 i = 0; i < 5; ++i)
{
Unit *pTarget = Unit::GetUnit(*me, enfeeble_targets[i]);
if (pTarget && pTarget->isAlive())
pTarget->SetHealth(enfeeble_health[i]);
enfeeble_targets[i] = 0;
enfeeble_health[i] = 0;
}
}
void SummonInfernal(const uint32 /*diff*/)
{
InfernalPoint *point = NULL;
Position pos;
if ((me->GetMapId() != 532) || positions.empty())
me->GetRandomNearPosition(pos, 60);
else
{
std::vector<InfernalPoint*>::iterator itr = positions.begin()+rand()%positions.size();
point = *itr;
positions.erase(itr);
pos.Relocate(point->x, point->y, INFERNAL_Z);
}
if (SunderArmorTimer <= diff)
Creature *Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000);
if (Infernal)
{
DoCast(me->getVictim(), SPELL_SUNDER_ARMOR);
SunderArmorTimer = urand(10000,18000);
Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE);
Infernal->setFaction(me->getFaction());
if (point)
CAST_AI(netherspite_infernal::netherspite_infernalAI, Infernal->AI())->point=point;
CAST_AI(netherspite_infernal::netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID();
} else SunderArmorTimer -= diff;
infernals.push_back(Infernal->GetGUID());
DoCast(Infernal, SPELL_INFERNAL_RELAY);
}
if (Cleave_Timer <= diff)
{
DoCast(me->getVictim(), SPELL_CLEAVE);
Cleave_Timer = urand(6000,12000);
} else Cleave_Timer -= diff;
DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me);
}
else
{
if (AxesTargetSwitchTimer <= diff)
{
AxesTargetSwitchTimer = urand(7500,20000);
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that
{
EnfeebleResetHealth();
EnfeebleResetTimer = 0;
} else EnfeebleResetTimer -= diff;
if (me->hasUnitState(UNIT_STAT_STUNNED)) // While shifting to phase 2 malchezaar stuns himself
return;
if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->getVictim()->GetGUID())
me->SetUInt64Value(UNIT_FIELD_TARGET, me->getVictim()->GetGUID());
if (phase == 1)
{
if ((me->GetHealth()*100) / me->GetMaxHealth() < 60)
{
me->InterruptNonMeleeSpells(false);
phase = 2;
//animation
DoCast(me, SPELL_EQUIP_AXES);
//text
DoScriptText(SAY_AXE_TOSS1, me);
//passive thrash aura
DoCast(me, SPELL_THRASH_AURA, true);
//models
SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
//damage
const CreatureInfo *cinfo = me->GetCreatureInfo();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg);
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg);
me->UpdateDamagePhysical(BASE_ATTACK);
me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg);
me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg);
//Sigh, updating only works on main attack, do it manually ....
me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg);
me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg);
me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100);
}
}
else if (phase == 2)
{
if ((me->GetHealth()*100) / me->GetMaxHealth() < 30)
{
InfernalTimer = 15000;
phase = 3;
ClearWeapons();
//remove thrash
me->RemoveAurasDueToSpell(SPELL_THRASH_AURA);
DoScriptText(SAY_AXE_TOSS2, me);
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
for (uint8 i = 0; i < 2; ++i)
{
if (Unit *axe = Unit::GetUnit(*me, axes[i]))
Creature *axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
if (axe)
{
if (axe->getVictim())
DoModifyThreatPercent(axe->getVictim(), -100);
axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
axe->setFaction(me->getFaction());
axes[i] = axe->GetGUID();
if (pTarget)
axe->AddThreat(pTarget, 1000000.0f);
//axe->getThreatManager().tauntFadeOut(axe->getVictim());
//axe->getThreatManager().tauntApply(pTarget);
{
axe->AI()->AttackStart(pTarget);
//axe->getThreatManager().tauntApply(pTarget); //Taunt Apply and fade out does not work properly
// So we'll use a hack to add a lot of threat to our target
axe->AddThreat(pTarget, 10000000.0f);
}
}
}
if (ShadowNovaTimer > 35000)
ShadowNovaTimer = EnfeebleTimer + 5000;
return;
}
} else AxesTargetSwitchTimer -= diff;
if (AmplifyDamageTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_AMPLIFY_DAMAGE);
AmplifyDamageTimer = urand(20000,30000);
} else AmplifyDamageTimer -= diff;
}
if (SunderArmorTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SUNDER_ARMOR);
SunderArmorTimer = urand(10000,18000);
//Time for global and double timers
if (InfernalTimer <= diff)
{
SummonInfernal(diff);
InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise
} else InfernalTimer -= diff;
} else SunderArmorTimer -= diff;
if (ShadowNovaTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SHADOWNOVA);
ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1);
} else ShadowNovaTimer -= diff;
if (Cleave_Timer <= diff)
{
DoCast(me->getVictim(), SPELL_CLEAVE);
Cleave_Timer = urand(6000,12000);
if (phase != 2)
{
if (SWPainTimer <= diff)
{
Unit *pTarget = NULL;
if (phase == 1)
pTarget = me->getVictim(); // the tank
else // anyone but the tank
pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
if (pTarget)
DoCast(pTarget, SPELL_SW_PAIN);
SWPainTimer = 20000;
} else SWPainTimer -= diff;
}
if (phase != 3)
{
if (EnfeebleTimer <= diff)
{
EnfeebleHealthEffect();
EnfeebleTimer = 30000;
ShadowNovaTimer = 5000;
EnfeebleResetTimer = 9000;
} else EnfeebleTimer -= diff;
}
if (phase == 2)
DoMeleeAttacksIfReady();
else
DoMeleeAttackIfReady();
}
void DoMeleeAttacksIfReady()
{
if (me->IsWithinMeleeRange(me->getVictim()) && !me->IsNonMeleeSpellCasted(false))
{
//Check for base attack
if (me->isAttackReady() && me->getVictim())
{
me->AttackerStateUpdate(me->getVictim());
me->resetAttackTimer();
} else Cleave_Timer -= diff;
}
//Check for offhand attack
if (me->isAttackReady(OFF_ATTACK) && me->getVictim())
else
{
me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK);
me->resetAttackTimer(OFF_ATTACK);
if (AxesTargetSwitchTimer <= diff)
{
AxesTargetSwitchTimer = urand(7500,20000);
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
for (uint8 i = 0; i < 2; ++i)
{
if (Unit *axe = Unit::GetUnit(*me, axes[i]))
{
if (axe->getVictim())
DoModifyThreatPercent(axe->getVictim(), -100);
if (pTarget)
axe->AddThreat(pTarget, 1000000.0f);
//axe->getThreatManager().tauntFadeOut(axe->getVictim());
//axe->getThreatManager().tauntApply(pTarget);
}
}
}
} else AxesTargetSwitchTimer -= diff;
if (AmplifyDamageTimer <= diff)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_AMPLIFY_DAMAGE);
AmplifyDamageTimer = urand(20000,30000);
} else AmplifyDamageTimer -= diff;
}
//Time for global and double timers
if (InfernalTimer <= diff)
{
SummonInfernal(diff);
InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise
} else InfernalTimer -= diff;
if (ShadowNovaTimer <= diff)
{
DoCast(me->getVictim(), SPELL_SHADOWNOVA);
ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1);
} else ShadowNovaTimer -= diff;
if (phase != 2)
{
if (SWPainTimer <= diff)
{
Unit *pTarget = NULL;
if (phase == 1)
pTarget = me->getVictim(); // the tank
else // anyone but the tank
pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
if (pTarget)
DoCast(pTarget, SPELL_SW_PAIN);
SWPainTimer = 20000;
} else SWPainTimer -= diff;
}
if (phase != 3)
{
if (EnfeebleTimer <= diff)
{
EnfeebleHealthEffect();
EnfeebleTimer = 30000;
ShadowNovaTimer = 5000;
EnfeebleResetTimer = 9000;
} else EnfeebleTimer -= diff;
}
if (phase == 2)
DoMeleeAttacksIfReady();
else
DoMeleeAttackIfReady();
}
void DoMeleeAttacksIfReady()
{
if (me->IsWithinMeleeRange(me->getVictim()) && !me->IsNonMeleeSpellCasted(false))
{
//Check for base attack
if (me->isAttackReady() && me->getVictim())
{
me->AttackerStateUpdate(me->getVictim());
me->resetAttackTimer();
}
//Check for offhand attack
if (me->isAttackReady(OFF_ATTACK) && me->getVictim())
{
me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK);
me->resetAttackTimer(OFF_ATTACK);
}
}
}
}
void Cleanup(Creature *infernal, InfernalPoint *point)
{
for (std::vector<uint64>::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr)
if (*itr == infernal->GetGUID())
void Cleanup(Creature *infernal, InfernalPoint *point)
{
infernals.erase(itr);
break;
}
for (std::vector<uint64>::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr)
if (*itr == infernal->GetGUID())
{
infernals.erase(itr);
break;
}
positions.push_back(point);
}
};
positions.push_back(point);
}
};
void netherspite_infernalAI::Cleanup()
{
Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar);
if (pMalchezaar && pMalchezaar->isAlive())
CAST_AI(boss_malchezaarAI, CAST_CRE(pMalchezaar)->AI())->Cleanup(me, point);
}
CreatureAI* GetAI_netherspite_infernal(Creature* pCreature)
{
return new netherspite_infernalAI (pCreature);
}
CreatureAI* GetAI_boss_malchezaar(Creature* pCreature)
{
return new boss_malchezaarAI (pCreature);
}
void AddSC_boss_malchezaar()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_malchezaar";
newscript->GetAI = &GetAI_boss_malchezaar;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "netherspite_infernal";
newscript->GetAI = &GetAI_netherspite_infernal;
newscript->RegisterSelf();
new boss_malchezaar();
new netherspite_infernal();
}
@@ -80,492 +80,497 @@ enum SuperSpell
SUPER_BLIZZARD,
SUPER_AE,
};
struct boss_aranAI : public ScriptedAI
␍class boss_shade_of_aran : public CreatureScript
{
boss_aranAI(Creature *c) : ScriptedAI(c)
public:
boss_shade_of_aran() : CreatureScript("boss_shade_of_aran") { }
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
return new boss_aranAI (pCreature);
}
ScriptedInstance* pInstance;
uint32 SecondarySpellTimer;
uint32 NormalCastTimer;
uint32 SuperCastTimer;
uint32 BerserkTimer;
uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering.
uint8 LastSuperSpell;
uint32 FlameWreathTimer;
uint32 FlameWreathCheckTime;
uint64 FlameWreathTarget[3];
float FWTargPosX[3];
float FWTargPosY[3];
uint32 CurrentNormalSpell;
uint32 ArcaneCooldown;
uint32 FireCooldown;
uint32 FrostCooldown;
uint32 DrinkInterruptTimer;
bool ElementalsSpawned;
bool Drinking;
bool DrinkInturrupted;
void Reset()
struct boss_aranAI : public ScriptedAI
{
SecondarySpellTimer = 5000;
NormalCastTimer = 0;
SuperCastTimer = 35000;
BerserkTimer = 720000;
CloseDoorTimer = 15000;
LastSuperSpell = rand()%3;
FlameWreathTimer = 0;
FlameWreathCheckTime = 0;
CurrentNormalSpell = 0;
ArcaneCooldown = 0;
FireCooldown = 0;
FrostCooldown = 0;
DrinkInterruptTimer = 10000;
ElementalsSpawned = false;
Drinking = false;
DrinkInturrupted = false;
if (pInstance)
boss_aranAI(Creature *c) : ScriptedAI(c)
{
// Not in progress
pInstance->SetData(TYPE_ARAN, NOT_STARTED);
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true);
}
}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me);
}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
if (pInstance)
{
pInstance->SetData(TYPE_ARAN, DONE);
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true);
}
}
void EnterCombat(Unit * /*who*/)
{
DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me);
if (pInstance)
{
pInstance->SetData(TYPE_ARAN, IN_PROGRESS);
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false);
}
}
void FlameWreathEffect()
{
std::vector<Unit*> targets;
std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
if (!t_list.size())
return;
//store the threat list in a different container
for (std::list<HostileReference *>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
{
Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid());
//only on alive players
if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
targets.push_back(pTarget);
pInstance = c->GetInstanceScript();
}
//cut down to size if we have more than 3 targets
while (targets.size() > 3)
targets.erase(targets.begin()+rand()%targets.size());
InstanceScript* pInstance;
uint32 i = 0;
for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr)
uint32 SecondarySpellTimer;
uint32 NormalCastTimer;
uint32 SuperCastTimer;
uint32 BerserkTimer;
uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering.
uint8 LastSuperSpell;
uint32 FlameWreathTimer;
uint32 FlameWreathCheckTime;
uint64 FlameWreathTarget[3];
float FWTargPosX[3];
float FWTargPosY[3];
uint32 CurrentNormalSpell;
uint32 ArcaneCooldown;
uint32 FireCooldown;
uint32 FrostCooldown;
uint32 DrinkInterruptTimer;
bool ElementalsSpawned;
bool Drinking;
bool DrinkInturrupted;
void Reset()
{
if (*itr)
SecondarySpellTimer = 5000;
NormalCastTimer = 0;
SuperCastTimer = 35000;
BerserkTimer = 720000;
CloseDoorTimer = 15000;
LastSuperSpell = rand()%3;
FlameWreathTimer = 0;
FlameWreathCheckTime = 0;
CurrentNormalSpell = 0;
ArcaneCooldown = 0;
FireCooldown = 0;
FrostCooldown = 0;
DrinkInterruptTimer = 10000;
ElementalsSpawned = false;
Drinking = false;
DrinkInturrupted = false;
if (pInstance)
{
FlameWreathTarget[i] = (*itr)->GetGUID();
FWTargPosX[i] = (*itr)->GetPositionX();
FWTargPosY[i] = (*itr)->GetPositionY();
DoCast((*itr), SPELL_FLAME_WREATH, true);
++i;
// Not in progress
pInstance->SetData(TYPE_ARAN, NOT_STARTED);
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true);
}
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (CloseDoorTimer)
void KilledUnit(Unit * /*victim*/)
{
if (CloseDoorTimer <= diff)
DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me);
}
void JustDied(Unit * /*victim*/)
{
DoScriptText(SAY_DEATH, me);
if (pInstance)
{
if (pInstance)
pInstance->SetData(TYPE_ARAN, DONE);
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true);
}
}
void EnterCombat(Unit * /*who*/)
{
DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me);
if (pInstance)
{
pInstance->SetData(TYPE_ARAN, IN_PROGRESS);
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false);
}
}
void FlameWreathEffect()
{
std::vector<Unit*> targets;
std::list<HostileReference *> t_list = me->getThreatManager().getThreatList();
if (!t_list.size())
return;
//store the threat list in a different container
for (std::list<HostileReference *>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
{
Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid());
//only on alive players
if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
targets.push_back(pTarget);
}
//cut down to size if we have more than 3 targets
while (targets.size() > 3)
targets.erase(targets.begin()+rand()%targets.size());
uint32 i = 0;
for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr)
{
if (*itr)
{
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false);
CloseDoorTimer = 0;
FlameWreathTarget[i] = (*itr)->GetGUID();
FWTargPosX[i] = (*itr)->GetPositionX();
FWTargPosY[i] = (*itr)->GetPositionY();
DoCast((*itr), SPELL_FLAME_WREATH, true);
++i;
}
} else CloseDoorTimer -= diff;
}
}
//Cooldowns for casts
if (ArcaneCooldown)
void UpdateAI(const uint32 diff)
{
if (ArcaneCooldown >= diff)
ArcaneCooldown -= diff;
else ArcaneCooldown = 0;
if (!UpdateVictim())
return;
if (CloseDoorTimer)
{
if (CloseDoorTimer <= diff)
{
if (pInstance)
{
pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false);
CloseDoorTimer = 0;
}
} else CloseDoorTimer -= diff;
}
//Cooldowns for casts
if (ArcaneCooldown)
{
if (ArcaneCooldown >= diff)
ArcaneCooldown -= diff;
else ArcaneCooldown = 0;
}
if (FireCooldown)
{
if (FireCooldown >= diff)
FireCooldown -= diff;
else FireCooldown = 0;
}
if (FrostCooldown)
{
if (FrostCooldown >= diff)
FrostCooldown -= diff;
else FrostCooldown = 0;
}
if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20)
{
Drinking = true;
me->InterruptNonMeleeSpells(false);
DoScriptText(SAY_DRINK, me);
if (!DrinkInturrupted)
{
DoCast(me, SPELL_MASS_POLY, true);
DoCast(me, SPELL_CONJURE, false);
DoCast(me, SPELL_DRINK, false);
me->SetStandState(UNIT_STAND_STATE_SIT);
DrinkInterruptTimer = 10000;
}
}
//Drink Interrupt
if (Drinking && DrinkInturrupted)
{
Drinking = false;
me->RemoveAurasDueToSpell(SPELL_DRINK);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000);
DoCast(me, SPELL_POTION, false);
}
//Drink Interrupt Timer
if (Drinking && !DrinkInturrupted)
if (DrinkInterruptTimer >= diff)
DrinkInterruptTimer -= diff;
else
{
me->SetStandState(UNIT_STAND_STATE_STAND);
DoCast(me, SPELL_POTION, true);
DoCast(me, SPELL_AOE_PYROBLAST, false);
DrinkInturrupted = true;
Drinking = false;
}
//Don't execute any more code if we are drinking
if (Drinking)
return;
//Normal casts
if (NormalCastTimer <= diff)
{
if (!me->IsNonMeleeSpellCasted(false))
{
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (!pTarget)
return;
uint32 Spells[3];
uint8 AvailableSpells = 0;
//Check for what spells are not on cooldown
if (!ArcaneCooldown)
{
Spells[AvailableSpells] = SPELL_ARCMISSLE;
++AvailableSpells;
}
if (!FireCooldown)
{
Spells[AvailableSpells] = SPELL_FIREBALL;
++AvailableSpells;
}
if (!FrostCooldown)
{
Spells[AvailableSpells] = SPELL_FROSTBOLT;
++AvailableSpells;
}
//If no available spells wait 1 second and try again
if (AvailableSpells)
{
CurrentNormalSpell = Spells[rand() % AvailableSpells];
DoCast(pTarget, CurrentNormalSpell);
}
}
NormalCastTimer = 1000;
} else NormalCastTimer -= diff;
if (SecondarySpellTimer <= diff)
{
switch (urand(0,1))
{
case 0:
DoCast(me, SPELL_AOE_CS);
break;
case 1:
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_CHAINSOFICE);
break;
}
SecondarySpellTimer = urand(5000,20000);
} else SecondarySpellTimer -= diff;
if (SuperCastTimer <= diff)
{
uint8 Available[2];
switch (LastSuperSpell)
{
case SUPER_AE:
Available[0] = SUPER_FLAME;
Available[1] = SUPER_BLIZZARD;
break;
case SUPER_FLAME:
Available[0] = SUPER_AE;
Available[1] = SUPER_BLIZZARD;
break;
case SUPER_BLIZZARD:
Available[0] = SUPER_FLAME;
Available[1] = SUPER_AE;
break;
}
LastSuperSpell = Available[urand(0,1)];
switch (LastSuperSpell)
{
case SUPER_AE:
DoScriptText(RAND(SAY_EXPLOSION1,SAY_EXPLOSION2), me);
DoCast(me, SPELL_BLINK_CENTER, true);
DoCast(me, SPELL_PLAYERPULL, true);
DoCast(me, SPELL_MASSSLOW, true);
DoCast(me, SPELL_AEXPLOSION, false);
break;
case SUPER_FLAME:
DoScriptText(RAND(SAY_FLAMEWREATH1,SAY_FLAMEWREATH2), me);
FlameWreathTimer = 20000;
FlameWreathCheckTime = 500;
FlameWreathTarget[0] = 0;
FlameWreathTarget[1] = 0;
FlameWreathTarget[2] = 0;
FlameWreathEffect();
break;
case SUPER_BLIZZARD:
DoScriptText(RAND(SAY_BLIZZARD1,SAY_BLIZZARD2), me);
if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000))
{
pSpawn->setFaction(me->getFaction());
pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false);
}
break;
}
SuperCastTimer = urand(35000,40000);
} else SuperCastTimer -= diff;
if (!ElementalsSpawned && me->GetHealth()*100 / me->GetMaxHealth() < 40)
{
ElementalsSpawned = true;
for (uint32 i = 0; i < 4; ++i)
{
if (Creature* pUnit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000))
{
pUnit->Attack(me->getVictim(), true);
pUnit->setFaction(me->getFaction());
}
}
DoScriptText(SAY_ELEMENTALS, me);
}
if (BerserkTimer <= diff)
{
for (uint32 i = 0; i < 5; ++i)
{
if (Creature* pUnit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
{
pUnit->Attack(me->getVictim(), true);
pUnit->setFaction(me->getFaction());
}
}
DoScriptText(SAY_TIMEOVER, me);
BerserkTimer = 60000;
} else BerserkTimer -= diff;
//Flame Wreath check
if (FlameWreathTimer)
{
if (FlameWreathTimer >= diff)
FlameWreathTimer -= diff;
else FlameWreathTimer = 0;
if (FlameWreathCheckTime <= diff)
{
for (uint8 i = 0; i < 3; ++i)
{
if (!FlameWreathTarget[i])
continue;
Unit* pUnit = Unit::GetUnit(*me, FlameWreathTarget[i]);
if (pUnit && !pUnit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
{
pUnit->CastSpell(pUnit, 20476, true, 0, 0, me->GetGUID());
pUnit->CastSpell(pUnit, 11027, true);
FlameWreathTarget[i] = 0;
}
}
FlameWreathCheckTime = 500;
} else FlameWreathCheckTime -= diff;
}
if (ArcaneCooldown && FireCooldown && FrostCooldown)
DoMeleeAttackIfReady();
}
if (FireCooldown)
void DamageTaken(Unit* /*pAttacker*/, uint32 &damage)
{
if (FireCooldown >= diff)
FireCooldown -= diff;
else FireCooldown = 0;
if (!DrinkInturrupted && Drinking && damage)
DrinkInturrupted = true;
}
if (FrostCooldown)
void SpellHit(Unit* /*pAttacker*/, const SpellEntry* Spell)
{
if (FrostCooldown >= diff)
FrostCooldown -= diff;
else FrostCooldown = 0;
}
//We only care about interrupt effects and only if they are durring a spell currently being casted
if ((Spell->Effect[0] != SPELL_EFFECT_INTERRUPT_CAST &&
Spell->Effect[1] != SPELL_EFFECT_INTERRUPT_CAST &&
Spell->Effect[2] != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCasted(false))
return;
if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20)
{
Drinking = true;
//Interrupt effect
me->InterruptNonMeleeSpells(false);
DoScriptText(SAY_DRINK, me);
//Normally we would set the cooldown equal to the spell duration
//but we do not have access to the DurationStore
if (!DrinkInturrupted)
switch (CurrentNormalSpell)
{
DoCast(me, SPELL_MASS_POLY, true);
DoCast(me, SPELL_CONJURE, false);
DoCast(me, SPELL_DRINK, false);
me->SetStandState(UNIT_STAND_STATE_SIT);
DrinkInterruptTimer = 10000;
case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break;
case SPELL_FIREBALL: FireCooldown = 5000; break;
case SPELL_FROSTBOLT: FrostCooldown = 5000; break;
}
}
};
//Drink Interrupt
if (Drinking && DrinkInturrupted)
{
Drinking = false;
me->RemoveAurasDueToSpell(SPELL_DRINK);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000);
DoCast(me, SPELL_POTION, false);
}
};
␍class mob_aran_elemental : public CreatureScript
{
public:
mob_aran_elemental() : CreatureScript("mob_aran_elemental") { }
//Drink Interrupt Timer
if (Drinking && !DrinkInturrupted)
if (DrinkInterruptTimer >= diff)
DrinkInterruptTimer -= diff;
else
{
me->SetStandState(UNIT_STAND_STATE_STAND);
DoCast(me, SPELL_POTION, true);
DoCast(me, SPELL_AOE_PYROBLAST, false);
DrinkInturrupted = true;
Drinking = false;
}
//Don't execute any more code if we are drinking
if (Drinking)
return;
//Normal casts
if (NormalCastTimer <= diff)
{
if (!me->IsNonMeleeSpellCasted(false))
{
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (!pTarget)
return;
uint32 Spells[3];
uint8 AvailableSpells = 0;
//Check for what spells are not on cooldown
if (!ArcaneCooldown)
{
Spells[AvailableSpells] = SPELL_ARCMISSLE;
++AvailableSpells;
}
if (!FireCooldown)
{
Spells[AvailableSpells] = SPELL_FIREBALL;
++AvailableSpells;
}
if (!FrostCooldown)
{
Spells[AvailableSpells] = SPELL_FROSTBOLT;
++AvailableSpells;
}
//If no available spells wait 1 second and try again
if (AvailableSpells)
{
CurrentNormalSpell = Spells[rand() % AvailableSpells];
DoCast(pTarget, CurrentNormalSpell);
}
}
NormalCastTimer = 1000;
} else NormalCastTimer -= diff;
if (SecondarySpellTimer <= diff)
{
switch (urand(0,1))
{
case 0:
DoCast(me, SPELL_AOE_CS);
break;
case 1:
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(pTarget, SPELL_CHAINSOFICE);
break;
}
SecondarySpellTimer = urand(5000,20000);
} else SecondarySpellTimer -= diff;
if (SuperCastTimer <= diff)
{
uint8 Available[2];
switch (LastSuperSpell)
{
case SUPER_AE:
Available[0] = SUPER_FLAME;
Available[1] = SUPER_BLIZZARD;
break;
case SUPER_FLAME:
Available[0] = SUPER_AE;
Available[1] = SUPER_BLIZZARD;
break;
case SUPER_BLIZZARD:
Available[0] = SUPER_FLAME;
Available[1] = SUPER_AE;
break;
}
LastSuperSpell = Available[urand(0,1)];
switch (LastSuperSpell)
{
case SUPER_AE:
DoScriptText(RAND(SAY_EXPLOSION1,SAY_EXPLOSION2), me);
DoCast(me, SPELL_BLINK_CENTER, true);
DoCast(me, SPELL_PLAYERPULL, true);
DoCast(me, SPELL_MASSSLOW, true);
DoCast(me, SPELL_AEXPLOSION, false);
break;
case SUPER_FLAME:
DoScriptText(RAND(SAY_FLAMEWREATH1,SAY_FLAMEWREATH2), me);
FlameWreathTimer = 20000;
FlameWreathCheckTime = 500;
FlameWreathTarget[0] = 0;
FlameWreathTarget[1] = 0;
FlameWreathTarget[2] = 0;
FlameWreathEffect();
break;
case SUPER_BLIZZARD:
DoScriptText(RAND(SAY_BLIZZARD1,SAY_BLIZZARD2), me);
if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000))
{
pSpawn->setFaction(me->getFaction());
pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false);
}
break;
}
SuperCastTimer = urand(35000,40000);
} else SuperCastTimer -= diff;
if (!ElementalsSpawned && me->GetHealth()*100 / me->GetMaxHealth() < 40)
{
ElementalsSpawned = true;
for (uint32 i = 0; i < 4; ++i)
{
if (Creature* pUnit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000))
{
pUnit->Attack(me->getVictim(), true);
pUnit->setFaction(me->getFaction());
}
}
DoScriptText(SAY_ELEMENTALS, me);
}
if (BerserkTimer <= diff)
{
for (uint32 i = 0; i < 5; ++i)
{
if (Creature* pUnit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
{
pUnit->Attack(me->getVictim(), true);
pUnit->setFaction(me->getFaction());
}
}
DoScriptText(SAY_TIMEOVER, me);
BerserkTimer = 60000;
} else BerserkTimer -= diff;
//Flame Wreath check
if (FlameWreathTimer)
{
if (FlameWreathTimer >= diff)
FlameWreathTimer -= diff;
else FlameWreathTimer = 0;
if (FlameWreathCheckTime <= diff)
{
for (uint8 i = 0; i < 3; ++i)
{
if (!FlameWreathTarget[i])
continue;
Unit* pUnit = Unit::GetUnit(*me, FlameWreathTarget[i]);
if (pUnit && !pUnit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
{
pUnit->CastSpell(pUnit, 20476, true, 0, 0, me->GetGUID());
pUnit->CastSpell(pUnit, 11027, true);
FlameWreathTarget[i] = 0;
}
}
FlameWreathCheckTime = 500;
} else FlameWreathCheckTime -= diff;
}
if (ArcaneCooldown && FireCooldown && FrostCooldown)
DoMeleeAttackIfReady();
}
void DamageTaken(Unit* /*pAttacker*/, uint32 &damage)
CreatureAI* GetAI(Creature* pCreature) const
{
if (!DrinkInturrupted && Drinking && damage)
DrinkInturrupted = true;
return new water_elementalAI (pCreature);
}
void SpellHit(Unit* /*pAttacker*/, const SpellEntry* Spell)
struct water_elementalAI : public ScriptedAI
{
//We only care about interrupt effects and only if they are durring a spell currently being casted
if ((Spell->Effect[0] != SPELL_EFFECT_INTERRUPT_CAST &&
Spell->Effect[1] != SPELL_EFFECT_INTERRUPT_CAST &&
Spell->Effect[2] != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCasted(false))
return;
water_elementalAI(Creature *c) : ScriptedAI(c) {}
//Interrupt effect
me->InterruptNonMeleeSpells(false);
uint32 CastTimer;
//Normally we would set the cooldown equal to the spell duration
//but we do not have access to the DurationStore
switch (CurrentNormalSpell)
void Reset()
{
case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break;
case SPELL_FIREBALL: FireCooldown = 5000; break;
case SPELL_FROSTBOLT: FrostCooldown = 5000; break;
CastTimer = 2000 + (rand()%3000);
}
}
void EnterCombat(Unit* /*who*/) {}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (CastTimer <= diff)
{
DoCast(me->getVictim(), SPELL_WATERBOLT);
CastTimer = urand(2000,5000);
} else CastTimer -= diff;
}
};
};
struct water_elementalAI : public ScriptedAI
// CONVERT TO ACID␍class mob_shadow_of_aran : public CreatureScript
{
water_elementalAI(Creature *c) : ScriptedAI(c) {}
public:
mob_shadow_of_aran() : CreatureScript("mob_shadow_of_aran") { }
uint32 CastTimer;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
CastTimer = 2000 + (rand()%3000);
sLog.outString("TSCR: Convert simpleAI script for Creature Entry %u to ACID", pCreature->GetEntry());
SimpleAI* ai = new SimpleAI (pCreature);
ai->Spell[0].Enabled = true;
ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO;
ai->Spell[0].Cooldown = 5000;
ai->Spell[0].First_Cast = 1000;
ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET;
ai->EnterEvadeMode();
return ai;
}
void EnterCombat(Unit* /*who*/) {}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (CastTimer <= diff)
{
DoCast(me->getVictim(), SPELL_WATERBOLT);
CastTimer = urand(2000,5000);
} else CastTimer -= diff;
}
};
CreatureAI* GetAI_boss_aran(Creature* pCreature)
{
return new boss_aranAI (pCreature);
}
CreatureAI* GetAI_water_elemental(Creature* pCreature)
{
return new water_elementalAI (pCreature);
}
// CONVERT TO ACID
CreatureAI* GetAI_shadow_of_aran(Creature* pCreature)
{
sLog.outString("TSCR: Convert simpleAI script for Creature Entry %u to ACID", pCreature->GetEntry());
SimpleAI* ai = new SimpleAI (pCreature);
ai->Spell[0].Enabled = true;
ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO;
ai->Spell[0].Cooldown = 5000;
ai->Spell[0].First_Cast = 1000;
ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET;
ai->EnterEvadeMode();
return ai;
}
void AddSC_boss_shade_of_aran()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_shade_of_aran";
newscript->GetAI = &GetAI_boss_aran;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_shadow_of_aran";
newscript->GetAI = &GetAI_shadow_of_aran;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_aran_elemental";
newscript->GetAI = &GetAI_water_elemental;
newscript->RegisterSelf();
new boss_shade_of_aran();
new mob_shadow_of_aran();
new mob_aran_elemental();
}
@@ -55,365 +55,374 @@ EndScriptData */
#define CREATURE_FIENDISHIMP 17267
#define CREATURE_PORTAL 17265
#define CREATURE_KILREK 17229
struct mob_kilrekAI : public ScriptedAI
␍class mob_kilrek : public CreatureScript
{
mob_kilrekAI(Creature *c) : ScriptedAI(c)
public:
mob_kilrek() : CreatureScript("mob_kilrek") { }
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
return new mob_kilrekAI (pCreature);
}
ScriptedInstance* pInstance;
uint64 TerestianGUID;
uint32 AmplifyTimer;
void Reset()
struct mob_kilrekAI : public ScriptedAI
{
TerestianGUID = 0;
AmplifyTimer = 2000;
}
void EnterCombat(Unit * /*who*/)
{
if (!pInstance)
mob_kilrekAI(Creature *c) : ScriptedAI(c)
{
ERROR_INST_DATA(me);
return;
pInstance = c->GetInstanceScript();
}
}
void JustDied(Unit* /*Killer*/)
{
if (pInstance)
InstanceScript* pInstance;
uint64 TerestianGUID;
uint32 AmplifyTimer;
void Reset()
{
uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN);
if (TerestianGUID)
TerestianGUID = 0;
AmplifyTimer = 2000;
}
void EnterCombat(Unit * /*who*/)
{
if (!pInstance)
{
Unit* Terestian = Unit::GetUnit((*me), TerestianGUID);
if (Terestian && Terestian->isAlive())
DoCast(Terestian, SPELL_BROKEN_PACT, true);
ERROR_INST_DATA(me);
return;
}
} else ERROR_INST_DATA(me);
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
if (AmplifyTimer <= diff)
{
me->InterruptNonMeleeSpells(false);
DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES);
AmplifyTimer = urand(10000,20000);
} else AmplifyTimer -= diff;
DoMeleeAttackIfReady();
}
};
struct mob_demon_chainAI : public ScriptedAI
{
mob_demon_chainAI(Creature *c) : ScriptedAI(c) {}
uint64 SacrificeGUID;
void Reset()
{
SacrificeGUID = 0;
}
void EnterCombat(Unit* /*who*/) {}
void AttackStart(Unit* /*who*/) {}
void MoveInLineOfSight(Unit* /*who*/) {}
void JustDied(Unit * /*killer*/)
{
if (SacrificeGUID)
{
Unit* Sacrifice = Unit::GetUnit((*me),SacrificeGUID);
if (Sacrifice)
Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE);
}
}
};
struct mob_fiendish_portalAI : public PassiveAI
{
mob_fiendish_portalAI(Creature *c) : PassiveAI(c),summons(me){}
SummonList summons;
void Reset()
{
summons.DespawnAll();
}
void JustSummoned(Creature* summon)
{
summons.Summon(summon);
DoZoneInCombat(summon);
}
void DespawnAllImp()
{
summons.DespawnAll();
}
};
struct boss_terestianAI : public ScriptedAI
{
boss_terestianAI(Creature *c) : ScriptedAI(c)
{
for (uint8 i = 0; i < 2; ++i)
PortalGUID[i] = 0;
pInstance = c->GetInstanceData();
}
ScriptedInstance *pInstance;
uint64 PortalGUID[2];
uint8 PortalsCount;
uint32 SacrificeTimer;
uint32 ShadowboltTimer;
uint32 SummonTimer;
uint32 BerserkTimer;
bool SummonedPortals;
bool Berserk;
void Reset()
{
for (uint8 i = 0; i < 2; ++i)
void JustDied(Unit* /*Killer*/)
{
if (PortalGUID[i])
if (pInstance)
{
if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i]))
uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN);
if (TerestianGUID)
{
CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp();
pPortal->ForcedDespawn();
Unit* Terestian = Unit::GetUnit((*me), TerestianGUID);
if (Terestian && Terestian->isAlive())
DoCast(Terestian, SPELL_BROKEN_PACT, true);
}
PortalGUID[i] = 0;
}
} else ERROR_INST_DATA(me);
}
PortalsCount = 0;
SacrificeTimer = 30000;
ShadowboltTimer = 5000;
SummonTimer = 10000;
BerserkTimer = 600000;
SummonedPortals = false;
Berserk = false;
if (pInstance)
pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED);
me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);
if (Minion* Kilrek = me->GetFirstMinion())
void UpdateAI(const uint32 diff)
{
if (!Kilrek->isAlive())
//Return since we have no target
if (!UpdateVictim())
return;
if (AmplifyTimer <= diff)
{
Kilrek->UnSummon();
DoCast(me, SPELL_SUMMON_IMP, true);
}
me->InterruptNonMeleeSpells(false);
DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES);
AmplifyTimer = urand(10000,20000);
} else AmplifyTimer -= diff;
DoMeleeAttackIfReady();
}
else DoCast(me, SPELL_SUMMON_IMP, true);
};
};
␍class mob_demon_chain : public CreatureScript
{
public:
mob_demon_chain() : CreatureScript("mob_demon_chain") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new mob_demon_chainAI(pCreature);
}
void EnterCombat(Unit* /*who*/)
struct mob_demon_chainAI : public ScriptedAI
{
DoScriptText(SAY_AGGRO, me);
}
mob_demon_chainAI(Creature *c) : ScriptedAI(c) {}
void JustSummoned(Creature* pSummoned)
{
if (pSummoned->GetEntry() == CREATURE_PORTAL)
uint64 SacrificeGUID;
void Reset()
{
PortalGUID[PortalsCount] = pSummoned->GetGUID();
++PortalsCount;
if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1)
{
DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me);
SummonedPortals = true;
}
}
}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me);
}
void JustDied(Unit * /*killer*/)
{
for (uint8 i = 0; i < 2; ++i)
{
if (PortalGUID[i])
{
if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i]))
pPortal->ForcedDespawn();
PortalGUID[i] = 0;
}
SacrificeGUID = 0;
}
DoScriptText(SAY_DEATH, me);
void EnterCombat(Unit* /*who*/) {}
void AttackStart(Unit* /*who*/) {}
void MoveInLineOfSight(Unit* /*who*/) {}
if (pInstance)
pInstance->SetData(TYPE_TERESTIAN, DONE);
void JustDied(Unit * /*killer*/)
{
if (SacrificeGUID)
{
Unit* Sacrifice = Unit::GetUnit((*me),SacrificeGUID);
if (Sacrifice)
Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE);
}
}
};
};
␍class mob_fiendish_portal : public CreatureScript
{
public:
mob_fiendish_portal() : CreatureScript("mob_fiendish_portal") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new mob_fiendish_portalAI (pCreature);
}
void UpdateAI(const uint32 diff)
struct mob_fiendish_portalAI : public PassiveAI
{
if (!UpdateVictim())
return;
mob_fiendish_portalAI(Creature *c) : PassiveAI(c),summons(me){}
if (SacrificeTimer <= diff)
SummonList summons;
void Reset()
{
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
if (pTarget && pTarget->isAlive())
{
DoCast(pTarget, SPELL_SACRIFICE, true);
DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true);
if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000))
{
CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID();
Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true);
DoScriptText(RAND(SAY_SACRIFICE1,SAY_SACRIFICE2), me);
SacrificeTimer = 30000;
}
}
} else SacrificeTimer -= diff;
if (ShadowboltTimer <= diff)
{
DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT);
ShadowboltTimer = 10000;
} else ShadowboltTimer -= diff;
if (SummonTimer <= diff)
{
if (!PortalGUID[0])
DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false);
if (!PortalGUID[1])
DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false);
if (PortalGUID[0] && PortalGUID[1])
{
if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0,1)]))
pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false);
SummonTimer = 5000;
}
} else SummonTimer -= diff;
if (!Berserk)
{
if (BerserkTimer <= diff)
{
DoCast(me, SPELL_BERSERK);
Berserk = true;
} else BerserkTimer -= diff;
summons.DespawnAll();
}
DoMeleeAttackIfReady();
}
void JustSummoned(Creature* summon)
{
summons.Summon(summon);
DoZoneInCombat(summon);
}
void DespawnAllImp()
{
summons.DespawnAll();
}
};
};
#define SPELL_FIREBOLT 30050 // Blasts a target for 181-209 Fire damage.
struct mob_fiendish_impAI : public ScriptedAI
␍class mob_fiendish_imp : public CreatureScript
{
mob_fiendish_impAI(Creature *c) : ScriptedAI(c) {}
public:
mob_fiendish_imp() : CreatureScript("mob_fiendish_imp") { }
uint32 FireboltTimer;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
FireboltTimer = 2000;
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
return new mob_fiendish_impAI (pCreature);
}
void EnterCombat(Unit * /*who*/) {}
void UpdateAI(const uint32 diff)
struct mob_fiendish_impAI : public ScriptedAI
{
//Return since we have no target
if (!UpdateVictim())
return;
mob_fiendish_impAI(Creature *c) : ScriptedAI(c) {}
if (FireboltTimer <= diff)
uint32 FireboltTimer;
void Reset()
{
DoCast(me->getVictim(), SPELL_FIREBOLT);
FireboltTimer = 2200;
} else FireboltTimer -= diff;
FireboltTimer = 2000;
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
}
void EnterCombat(Unit * /*who*/) {}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
if (FireboltTimer <= diff)
{
DoCast(me->getVictim(), SPELL_FIREBOLT);
FireboltTimer = 2200;
} else FireboltTimer -= diff;
DoMeleeAttackIfReady();
}
};
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_kilrek(Creature* pCreature)
␍class boss_terestian_illhoof : public CreatureScript
{
return new mob_kilrekAI (pCreature);
}
public:
boss_terestian_illhoof() : CreatureScript("boss_terestian_illhoof") { }
CreatureAI* GetAI_mob_fiendish_imp(Creature* pCreature)
{
return new mob_fiendish_impAI (pCreature);
}
CreatureAI* GetAI(Creature* pCreature) const
{
return new boss_terestianAI (pCreature);
}
CreatureAI* GetAI_mob_fiendish_portal(Creature* pCreature)
{
return new mob_fiendish_portalAI (pCreature);
}
struct boss_terestianAI : public ScriptedAI
{
boss_terestianAI(Creature *c) : ScriptedAI(c)
{
for (uint8 i = 0; i < 2; ++i)
PortalGUID[i] = 0;
pInstance = c->GetInstanceScript();
}
CreatureAI* GetAI_boss_terestian_illhoof(Creature* pCreature)
{
return new boss_terestianAI (pCreature);
}
InstanceScript *pInstance;
CreatureAI* GetAI_mob_demon_chain(Creature* pCreature)
{
return new mob_demon_chainAI(pCreature);
}
uint64 PortalGUID[2];
uint8 PortalsCount;
uint32 SacrificeTimer;
uint32 ShadowboltTimer;
uint32 SummonTimer;
uint32 BerserkTimer;
bool SummonedPortals;
bool Berserk;
void Reset()
{
for (uint8 i = 0; i < 2; ++i)
{
if (PortalGUID[i])
{
if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i]))
{
CAST_AI(mob_fiendish_portal::mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp();
pPortal->ForcedDespawn();
}
PortalGUID[i] = 0;
}
}
PortalsCount = 0;
SacrificeTimer = 30000;
ShadowboltTimer = 5000;
SummonTimer = 10000;
BerserkTimer = 600000;
SummonedPortals = false;
Berserk = false;
if (pInstance)
pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED);
me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);
if (Minion* Kilrek = me->GetFirstMinion())
{
if (!Kilrek->isAlive())
{
Kilrek->UnSummon();
DoCast(me, SPELL_SUMMON_IMP, true);
}
}
else DoCast(me, SPELL_SUMMON_IMP, true);
}
void EnterCombat(Unit* /*who*/)
{
DoScriptText(SAY_AGGRO, me);
}
void JustSummoned(Creature* pSummoned)
{
if (pSummoned->GetEntry() == CREATURE_PORTAL)
{
PortalGUID[PortalsCount] = pSummoned->GetGUID();
++PortalsCount;
if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1)
{
DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me);
SummonedPortals = true;
}
}
}
void KilledUnit(Unit * /*victim*/)
{
DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me);
}
void JustDied(Unit * /*killer*/)
{
for (uint8 i = 0; i < 2; ++i)
{
if (PortalGUID[i])
{
if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i]))
pPortal->ForcedDespawn();
PortalGUID[i] = 0;
}
}
DoScriptText(SAY_DEATH, me);
if (pInstance)
pInstance->SetData(TYPE_TERESTIAN, DONE);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (SacrificeTimer <= diff)
{
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
if (pTarget && pTarget->isAlive())
{
DoCast(pTarget, SPELL_SACRIFICE, true);
DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true);
if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000))
{
CAST_AI(mob_demon_chain::mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID();
Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true);
DoScriptText(RAND(SAY_SACRIFICE1,SAY_SACRIFICE2), me);
SacrificeTimer = 30000;
}
}
} else SacrificeTimer -= diff;
if (ShadowboltTimer <= diff)
{
DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT);
ShadowboltTimer = 10000;
} else ShadowboltTimer -= diff;
if (SummonTimer <= diff)
{
if (!PortalGUID[0])
DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false);
if (!PortalGUID[1])
DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false);
if (PortalGUID[0] && PortalGUID[1])
{
if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0,1)]))
pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false);
SummonTimer = 5000;
}
} else SummonTimer -= diff;
if (!Berserk)
{
if (BerserkTimer <= diff)
{
DoCast(me, SPELL_BERSERK);
Berserk = true;
} else BerserkTimer -= diff;
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_terestian_illhoof()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_terestian_illhoof";
newscript->GetAI = &GetAI_boss_terestian_illhoof;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_fiendish_imp";
newscript->GetAI = &GetAI_mob_fiendish_imp;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name= "mob_fiendish_portal";
newscript->GetAI = &GetAI_mob_fiendish_portal;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_kilrek";
newscript->GetAI = &GetAI_mob_kilrek;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_demon_chain";
newscript->GetAI = &GetAI_mob_demon_chain;
newscript->RegisterSelf();
new boss_terestian_illhoof();
new mob_fiendish_imp();
new mob_fiendish_portal();
new mob_kilrek();
new mob_demon_chain();
}
File diff suppressed because it is too large Load Diff
@@ -42,269 +42,271 @@ EndScriptData */
10 - Prince Malchezzar
11 - Nightbane
*/
struct instance_karazhan : public ScriptedInstance
␍class instance_karazhan : public InstanceMapScript
{
instance_karazhan(Map* pMap) : ScriptedInstance(pMap) {Initialize();}
public:
instance_karazhan() : InstanceMapScript("instance_karazhan") { }
uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string strSaveData;
uint32 m_uiOperaEvent;
uint32 m_uiOzDeathCount;
uint64 m_uiCurtainGUID;
uint64 m_uiStageDoorLeftGUID;
uint64 m_uiStageDoorRightGUID;
uint64 m_uiKilrekGUID;
uint64 m_uiTerestianGUID;
uint64 m_uiMoroesGUID;
uint64 m_uiLibraryDoor; // Door at Shade of Aran
uint64 m_uiMassiveDoor; // Door at Netherspite
uint64 m_uiSideEntranceDoor; // Side Entrance
uint64 m_uiGamesmansDoor; // Door before Chess
uint64 m_uiGamesmansExitDoor; // Door after Chess
uint64 m_uiNetherspaceDoor; // Door at Malchezaar
uint64 MastersTerraceDoor[2];
uint64 ImageGUID;
uint64 DustCoveredChest;
void Initialize()
InstanceScript* GetInstanceData_InstanceMapScript(Map* pMap)
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
// 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered.
m_uiOperaEvent = urand(1,3);
m_uiOzDeathCount = 0;
m_uiCurtainGUID = 0;
m_uiStageDoorLeftGUID = 0;
m_uiStageDoorRightGUID = 0;
m_uiKilrekGUID = 0;
m_uiTerestianGUID = 0;
m_uiMoroesGUID = 0;
m_uiLibraryDoor = 0;
m_uiMassiveDoor = 0;
m_uiSideEntranceDoor = 0;
m_uiGamesmansDoor = 0;
m_uiGamesmansExitDoor = 0;
m_uiNetherspaceDoor = 0;
MastersTerraceDoor[0]= 0;
MastersTerraceDoor[1]= 0;
ImageGUID = 0;
DustCoveredChest = 0;
return new instance_karazhan_InstanceMapScript(pMap);
}
bool IsEncounterInProgress() const
struct instance_karazhan_InstanceMapScript : public InstanceScript
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
return true;
instance_karazhan_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();}
return false;
}
uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string strSaveData;
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
{
switch (pCreature->GetEntry())
uint32 m_uiOperaEvent;
uint32 m_uiOzDeathCount;
uint64 m_uiCurtainGUID;
uint64 m_uiStageDoorLeftGUID;
uint64 m_uiStageDoorRightGUID;
uint64 m_uiKilrekGUID;
uint64 m_uiTerestianGUID;
uint64 m_uiMoroesGUID;
uint64 m_uiLibraryDoor; // Door at Shade of Aran
uint64 m_uiMassiveDoor; // Door at Netherspite
uint64 m_uiSideEntranceDoor; // Side Entrance
uint64 m_uiGamesmansDoor; // Door before Chess
uint64 m_uiGamesmansExitDoor; // Door after Chess
uint64 m_uiNetherspaceDoor; // Door at Malchezaar
uint64 MastersTerraceDoor[2];
uint64 ImageGUID;
uint64 DustCoveredChest;
void Initialize()
{
case 17229: m_uiKilrekGUID = pCreature->GetGUID(); break;
case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break;
case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break;
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
// 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered.
m_uiOperaEvent = urand(1,3);
m_uiOzDeathCount = 0;
m_uiCurtainGUID = 0;
m_uiStageDoorLeftGUID = 0;
m_uiStageDoorRightGUID = 0;
m_uiKilrekGUID = 0;
m_uiTerestianGUID = 0;
m_uiMoroesGUID = 0;
m_uiLibraryDoor = 0;
m_uiMassiveDoor = 0;
m_uiSideEntranceDoor = 0;
m_uiGamesmansDoor = 0;
m_uiGamesmansExitDoor = 0;
m_uiNetherspaceDoor = 0;
MastersTerraceDoor[0]= 0;
MastersTerraceDoor[1]= 0;
ImageGUID = 0;
DustCoveredChest = 0;
}
}
void SetData(uint32 type, uint32 uiData)
{
switch (type)
bool IsEncounterInProgress() const
{
case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break;
case TYPE_MOROES:
if (m_auiEncounter[1] == DONE)
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
return true;
return false;
}
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
{
switch (pCreature->GetEntry())
{
case 17229: m_uiKilrekGUID = pCreature->GetGUID(); break;
case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break;
case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break;
}
}
void SetData(uint32 type, uint32 uiData)
{
switch (type)
{
case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break;
case TYPE_MOROES:
if (m_auiEncounter[1] == DONE)
break;
m_auiEncounter[1] = uiData;
break;
m_auiEncounter[1] = uiData;
break;
case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break;
case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break;
case TYPE_OPERA: m_auiEncounter[4] = uiData; break;
case TYPE_CURATOR: m_auiEncounter[5] = uiData; break;
case TYPE_ARAN: m_auiEncounter[6] = uiData; break;
case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break;
case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break;
case TYPE_CHESS:
if (uiData == DONE)
DoRespawnGameObject(DustCoveredChest,DAY);
m_auiEncounter[9] = uiData;
break;
case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break;
case TYPE_NIGHTBANE:
if (m_auiEncounter[11] != DONE)
m_auiEncounter[11] = uiData;
break;
case DATA_OPERA_OZ_DEATHCOUNT:
if (uiData == SPECIAL)
++m_uiOzDeathCount;
else if (uiData == IN_PROGRESS)
m_uiOzDeathCount = 0;
break;
case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break;
case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break;
case TYPE_OPERA: m_auiEncounter[4] = uiData; break;
case TYPE_CURATOR: m_auiEncounter[5] = uiData; break;
case TYPE_ARAN: m_auiEncounter[6] = uiData; break;
case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break;
case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break;
case TYPE_CHESS:
if (uiData == DONE)
DoRespawnGameObject(DustCoveredChest,DAY);
m_auiEncounter[9] = uiData;
break;
case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break;
case TYPE_NIGHTBANE:
if (m_auiEncounter[11] != DONE)
m_auiEncounter[11] = uiData;
break;
case DATA_OPERA_OZ_DEATHCOUNT:
if (uiData == SPECIAL)
++m_uiOzDeathCount;
else if (uiData == IN_PROGRESS)
m_uiOzDeathCount = 0;
break;
}
if (uiData == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
<< m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " "
<< m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11];
strSaveData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
if (uiData == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
<< m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " "
<< m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11];
strSaveData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
void SetData64(uint32 identifier, uint64 data)
{
switch(identifier)
void SetData64(uint32 identifier, uint64 data)
{
case DATA_IMAGE_OF_MEDIVH: ImageGUID = data;
switch(identifier)
{
case DATA_IMAGE_OF_MEDIVH: ImageGUID = data;
}
}
}
void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
{
switch(pGo->GetEntry())
void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
{
case 183932: m_uiCurtainGUID = pGo->GetGUID(); break;
case 184278:
m_uiStageDoorLeftGUID = pGo->GetGUID();
if (m_auiEncounter[4] == DONE)
pGo->SetGoState(GO_STATE_ACTIVE);
break;
case 184279:
m_uiStageDoorRightGUID = pGo->GetGUID();
if (m_auiEncounter[4] == DONE)
pGo->SetGoState(GO_STATE_ACTIVE);
break;
case 184517: m_uiLibraryDoor = pGo->GetGUID(); break;
case 185521: m_uiMassiveDoor = pGo->GetGUID(); break;
case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break;
case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break;
case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break;
case 184274: MastersTerraceDoor[0] = pGo->GetGUID(); break;
case 184280: MastersTerraceDoor[1] = pGo->GetGUID(); break;
case 184275:
m_uiSideEntranceDoor = pGo->GetGUID();
if (m_auiEncounter[4] == DONE)
pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
else
pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
break;
case 185119: DustCoveredChest = pGo->GetGUID(); break;
switch(pGo->GetEntry())
{
case 183932: m_uiCurtainGUID = pGo->GetGUID(); break;
case 184278:
m_uiStageDoorLeftGUID = pGo->GetGUID();
if (m_auiEncounter[4] == DONE)
pGo->SetGoState(GO_STATE_ACTIVE);
break;
case 184279:
m_uiStageDoorRightGUID = pGo->GetGUID();
if (m_auiEncounter[4] == DONE)
pGo->SetGoState(GO_STATE_ACTIVE);
break;
case 184517: m_uiLibraryDoor = pGo->GetGUID(); break;
case 185521: m_uiMassiveDoor = pGo->GetGUID(); break;
case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break;
case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break;
case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break;
case 184274: MastersTerraceDoor[0] = pGo->GetGUID(); break;
case 184280: MastersTerraceDoor[1] = pGo->GetGUID(); break;
case 184275:
m_uiSideEntranceDoor = pGo->GetGUID();
if (m_auiEncounter[4] == DONE)
pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
else
pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
break;
case 185119: DustCoveredChest = pGo->GetGUID(); break;
}
switch(m_uiOperaEvent)
{
//TODO: Set Object visibilities for Opera based on performance
case EVENT_OZ:
break;
case EVENT_HOOD:
break;
case EVENT_RAJ:
break;
}
}
switch(m_uiOperaEvent)
std::string GetSaveData()
{
//TODO: Set Object visibilities for Opera based on performance
case EVENT_OZ:
break;
case EVENT_HOOD:
break;
case EVENT_RAJ:
break;
}
}
std::string GetSaveData()
{
return strSaveData;
}
uint32 GetData(uint32 uiData)
{
switch (uiData)
{
case TYPE_ATTUMEN: return m_auiEncounter[0];
case TYPE_MOROES: return m_auiEncounter[1];
case TYPE_MAIDEN: return m_auiEncounter[2];
case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3];
case TYPE_OPERA: return m_auiEncounter[4];
case TYPE_CURATOR: return m_auiEncounter[5];
case TYPE_ARAN: return m_auiEncounter[6];
case TYPE_TERESTIAN: return m_auiEncounter[7];
case TYPE_NETHERSPITE: return m_auiEncounter[8];
case TYPE_CHESS: return m_auiEncounter[9];
case TYPE_MALCHEZZAR: return m_auiEncounter[10];
case TYPE_NIGHTBANE: return m_auiEncounter[11];
case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent;
case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount;
case DATA_IMAGE_OF_MEDIVH: return ImageGUID;
return strSaveData;
}
return 0;
}
uint64 GetData64(uint32 uiData)
{
switch (uiData)
uint32 GetData(uint32 uiData)
{
case DATA_KILREK: return m_uiKilrekGUID;
case DATA_TERESTIAN: return m_uiTerestianGUID;
case DATA_MOROES: return m_uiMoroesGUID;
case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID;
case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID;
case DATA_GO_CURTAINS: return m_uiCurtainGUID;
case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor;
case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor;
case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor;
case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor;
case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor;
case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor;
case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0];
case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1];
switch (uiData)
{
case TYPE_ATTUMEN: return m_auiEncounter[0];
case TYPE_MOROES: return m_auiEncounter[1];
case TYPE_MAIDEN: return m_auiEncounter[2];
case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3];
case TYPE_OPERA: return m_auiEncounter[4];
case TYPE_CURATOR: return m_auiEncounter[5];
case TYPE_ARAN: return m_auiEncounter[6];
case TYPE_TERESTIAN: return m_auiEncounter[7];
case TYPE_NETHERSPITE: return m_auiEncounter[8];
case TYPE_CHESS: return m_auiEncounter[9];
case TYPE_MALCHEZZAR: return m_auiEncounter[10];
case TYPE_NIGHTBANE: return m_auiEncounter[11];
case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent;
case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount;
case DATA_IMAGE_OF_MEDIVH: return ImageGUID;
}
return 0;
}
return 0;
}
void Load(const char* chrIn)
{
if (!chrIn)
uint64 GetData64(uint32 uiData)
{
OUT_LOAD_INST_DATA_FAIL;
return;
switch (uiData)
{
case DATA_KILREK: return m_uiKilrekGUID;
case DATA_TERESTIAN: return m_uiTerestianGUID;
case DATA_MOROES: return m_uiMoroesGUID;
case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID;
case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID;
case DATA_GO_CURTAINS: return m_uiCurtainGUID;
case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor;
case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor;
case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor;
case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor;
case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor;
case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor;
case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0];
case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1];
}
return 0;
}
OUT_LOAD_INST_DATA(chrIn);
std::istringstream loadStream(chrIn);
void Load(const char* chrIn)
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(chrIn);
std::istringstream loadStream(chrIn);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
>> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7]
>> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
m_auiEncounter[i] = NOT_STARTED;
OUT_LOAD_INST_DATA_COMPLETE;
}
};
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
>> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7]
>> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
m_auiEncounter[i] = NOT_STARTED;
OUT_LOAD_INST_DATA_COMPLETE;
}
};
InstanceData* GetInstanceData_instance_karazhan(Map* pMap)
{
return new instance_karazhan(pMap);
}
void AddSC_instance_karazhan()
{
Script *newscript;
newscript = new Script;
newscript->Name = "instance_karazhan";
newscript->GetInstanceData = &GetInstanceData_instance_karazhan;
newscript->RegisterSelf();
new instance_karazhan();
}
@@ -101,294 +101,302 @@ float Spawns[6][2]=
#define SPAWN_Z 90.5
#define SPAWN_Y -1758
#define SPAWN_O 4.738
struct npc_barnesAI : public npc_escortAI
␍class npc_barnes : public CreatureScript
{
npc_barnesAI(Creature* c) : npc_escortAI(c)
public:
npc_barnes() : CreatureScript("npc_barnes") { }
struct npc_barnesAI : public npc_escortAI
{
RaidWiped = false;
m_uiEventId = 0;
pInstance = c->GetInstanceData();
}
ScriptedInstance* pInstance;
uint64 m_uiSpotlightGUID;
uint32 TalkCount;
uint32 TalkTimer;
uint32 WipeTimer;
uint32 m_uiEventId;
bool PerformanceReady;
bool RaidWiped;
void Reset()
{
m_uiSpotlightGUID = 0;
TalkCount = 0;
TalkTimer = 2000;
WipeTimer = 5000;
PerformanceReady = false;
if (pInstance)
m_uiEventId = pInstance->GetData(DATA_OPERA_PERFORMANCE);
}
void StartEvent()
{
if (!pInstance)
return;
pInstance->SetData(TYPE_OPERA, IN_PROGRESS);
//resets count for this event, in case earlier failed
if (m_uiEventId == EVENT_OZ)
pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS);
Start(false, false);
}
void EnterCombat(Unit* /*who*/) {}
void WaypointReached(uint32 i)
{
if (!pInstance)
return;
switch(i)
npc_barnesAI(Creature* c) : npc_escortAI(c)
{
case 0:
DoCast(me, SPELL_TUXEDO, false);
pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT));
break;
case 4:
TalkCount = 0;
SetEscortPaused(true);
if (Creature* pSpotlight = me->SummonCreature(CREATURE_SPOTLIGHT,
me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f,
TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
{
pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false);
m_uiSpotlightGUID = pSpotlight->GetGUID();
}
break;
case 8:
pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT));
PerformanceReady = true;
break;
case 9:
PrepareEncounter();
pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_CURTAINS));
break;
}
}
void Talk(uint32 count)
{
int32 text = 0;
switch(m_uiEventId)
{
case EVENT_OZ:
if (OzDialogue[count].textid)
text = OzDialogue[count].textid;
if (OzDialogue[count].timer)
TalkTimer = OzDialogue[count].timer;
break;
case EVENT_HOOD:
if (HoodDialogue[count].textid)
text = HoodDialogue[count].textid;
if (HoodDialogue[count].timer)
TalkTimer = HoodDialogue[count].timer;
break;
case EVENT_RAJ:
if (RAJDialogue[count].textid)
text = RAJDialogue[count].textid;
if (RAJDialogue[count].timer)
TalkTimer = RAJDialogue[count].timer;
break;
RaidWiped = false;
m_uiEventId = 0;
pInstance = c->GetInstanceScript();
}
if (text)
DoScriptText(text, me);
}
InstanceScript* pInstance;
void PrepareEncounter()
{
sLog.outDebug("TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId);
uint8 index = 0;
uint8 count = 0;
uint64 m_uiSpotlightGUID;
switch(m_uiEventId)
uint32 TalkCount;
uint32 TalkTimer;
uint32 WipeTimer;
uint32 m_uiEventId;
bool PerformanceReady;
bool RaidWiped;
void Reset()
{
case EVENT_OZ:
index = 0;
count = 4;
break;
case EVENT_HOOD:
index = 4;
count = index+1;
break;
case EVENT_RAJ:
index = 5;
count = index+1;
break;
m_uiSpotlightGUID = 0;
TalkCount = 0;
TalkTimer = 2000;
WipeTimer = 5000;
PerformanceReady = false;
if (pInstance)
m_uiEventId = pInstance->GetData(DATA_OPERA_PERFORMANCE);
}
for (; index < count; ++index)
void StartEvent()
{
uint32 entry = ((uint32)Spawns[index][0]);
float PosX = Spawns[index][1];
if (!pInstance)
return;
if (Creature* pCreature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS))
pInstance->SetData(TYPE_OPERA, IN_PROGRESS);
//resets count for this event, in case earlier failed
if (m_uiEventId == EVENT_OZ)
pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS);
Start(false, false);
}
void EnterCombat(Unit* /*who*/) {}
void WaypointReached(uint32 i)
{
if (!pInstance)
return;
switch(i)
{
// In case database has bad flags
pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
case 0:
DoCast(me, SPELL_TUXEDO, false);
pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT));
break;
case 4:
TalkCount = 0;
SetEscortPaused(true);
if (Creature* pSpotlight = me->SummonCreature(CREATURE_SPOTLIGHT,
me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f,
TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
{
pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false);
m_uiSpotlightGUID = pSpotlight->GetGUID();
}
break;
case 8:
pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT));
PerformanceReady = true;
break;
case 9:
PrepareEncounter();
pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_CURTAINS));
break;
}
}
RaidWiped = false;
}
void UpdateAI(const uint32 diff)
{
npc_escortAI::UpdateAI(diff);
if (HasEscortState(STATE_ESCORT_PAUSED))
void Talk(uint32 count)
{
if (TalkTimer <= diff)
int32 text = 0;
switch(m_uiEventId)
{
if (TalkCount > 3)
{
if (Creature* pSpotlight = Unit::GetCreature(*me, m_uiSpotlightGUID))
pSpotlight->ForcedDespawn();
case EVENT_OZ:
if (OzDialogue[count].textid)
text = OzDialogue[count].textid;
if (OzDialogue[count].timer)
TalkTimer = OzDialogue[count].timer;
break;
SetEscortPaused(false);
return;
}
case EVENT_HOOD:
if (HoodDialogue[count].textid)
text = HoodDialogue[count].textid;
if (HoodDialogue[count].timer)
TalkTimer = HoodDialogue[count].timer;
break;
Talk(TalkCount);
++TalkCount;
} else TalkTimer -= diff;
case EVENT_RAJ:
if (RAJDialogue[count].textid)
text = RAJDialogue[count].textid;
if (RAJDialogue[count].timer)
TalkTimer = RAJDialogue[count].timer;
break;
}
if (text)
DoScriptText(text, me);
}
if (PerformanceReady)
void PrepareEncounter()
{
if (!RaidWiped)
sLog.outDebug("TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId);
uint8 index = 0;
uint8 count = 0;
switch(m_uiEventId)
{
if (WipeTimer <= diff)
case EVENT_OZ:
index = 0;
count = 4;
break;
case EVENT_HOOD:
index = 4;
count = index+1;
break;
case EVENT_RAJ:
index = 5;
count = index+1;
break;
}
for (; index < count; ++index)
{
uint32 entry = ((uint32)Spawns[index][0]);
float PosX = Spawns[index][1];
if (Creature* pCreature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS))
{
Map* pMap = me->GetMap();
if (!pMap->IsDungeon())
return;
// In case database has bad flags
pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
}
Map::PlayerList const &PlayerList = pMap->GetPlayers();
if (PlayerList.isEmpty())
return;
RaidWiped = false;
}
RaidWiped = true;
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
void UpdateAI(const uint32 diff)
{
npc_escortAI::UpdateAI(diff);
if (HasEscortState(STATE_ESCORT_PAUSED))
{
if (TalkTimer <= diff)
{
if (TalkCount > 3)
{
if (i->getSource()->isAlive() && !i->getSource()->isGameMaster())
{
RaidWiped = false;
break;
}
if (Creature* pSpotlight = Unit::GetCreature(*me, m_uiSpotlightGUID))
pSpotlight->ForcedDespawn();
SetEscortPaused(false);
return;
}
if (RaidWiped)
Talk(TalkCount);
++TalkCount;
} else TalkTimer -= diff;
}
if (PerformanceReady)
{
if (!RaidWiped)
{
if (WipeTimer <= diff)
{
Map* pMap = me->GetMap();
if (!pMap->IsDungeon())
return;
Map::PlayerList const &PlayerList = pMap->GetPlayers();
if (PlayerList.isEmpty())
return;
RaidWiped = true;
EnterEvadeMode();
return;
}
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->getSource()->isAlive() && !i->getSource()->isGameMaster())
{
RaidWiped = false;
break;
}
}
if (RaidWiped)
{
RaidWiped = true;
EnterEvadeMode();
return;
}
WipeTimer = 15000;
} else WipeTimer -= diff;
}
WipeTimer = 15000;
} else WipeTimer -= diff;
}
}
};
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
{
npc_barnesAI* pBarnesAI = CAST_AI(npc_barnes::npc_barnesAI, pCreature->AI());
switch(uiAction)
{
case GOSSIP_ACTION_INFO_DEF+1:
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+2:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->StartEvent();
break;
case GOSSIP_ACTION_INFO_DEF+3:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_OZ;
sLog.outString("TSCR: player (GUID %i) manually set Opera event to EVENT_OZ",pPlayer->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+4:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_HOOD;
sLog.outString("TSCR: player (GUID %i) manually set Opera event to EVENT_HOOD",pPlayer->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+5:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_RAJ;
sLog.outString("TSCR: player (GUID %i) manually set Opera event to EVENT_RAJ",pPlayer->GetGUID());
break;
}
return true;
}
bool OnGossipHello(Player* pPlayer, Creature* pCreature)
{
if (InstanceScript* pInstance = pCreature->GetInstanceScript())
{
// Check for death of Moroes and if opera event is not done already
if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE)
{
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (pPlayer->isGameMaster())
{
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
}
if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnes::npc_barnesAI,pCreature->AI()))
{
if (!pBarnesAI->RaidWiped)
pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID());
else
pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID());
return true;
}
}
}
pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID());
return true;
}
CreatureAI* GetAI(Creature* pCreature) const
{
return new npc_barnesAI(pCreature);
}
};
CreatureAI* GetAI_npc_barnesAI(Creature* pCreature)
{
return new npc_barnesAI(pCreature);
}
bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature)
{
if (ScriptedInstance* pInstance = pCreature->GetInstanceData())
{
// Check for death of Moroes and if opera event is not done already
if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE)
{
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (pPlayer->isGameMaster())
{
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
}
if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI,pCreature->AI()))
{
if (!pBarnesAI->RaidWiped)
pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID());
else
pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID());
return true;
}
}
}
pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID());
return true;
}
bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
{
npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI, pCreature->AI());
switch(uiAction)
{
case GOSSIP_ACTION_INFO_DEF+1:
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+2:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->StartEvent();
break;
case GOSSIP_ACTION_INFO_DEF+3:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_OZ;
sLog.outString("TSCR: player (GUID %i) manually set Opera event to EVENT_OZ",pPlayer->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+4:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_HOOD;
sLog.outString("TSCR: player (GUID %i) manually set Opera event to EVENT_HOOD",pPlayer->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+5:
pPlayer->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_RAJ;
sLog.outString("TSCR: player (GUID %i) manually set Opera event to EVENT_RAJ",pPlayer->GetGUID());
break;
}
return true;
}
/*###
# npc_berthold
@@ -400,28 +408,35 @@ enum eBerthold
};
#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library"
bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature)
␍class npc_berthold : public CreatureScript
{
if (ScriptedInstance* pInstance = pCreature->GetInstanceData())
public:
npc_berthold() : CreatureScript("npc_berthold") { }
bool OnGossipSelect(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction)
{
// Check if Shade of Aran event is done
if (pInstance->GetData(TYPE_ARAN) == DONE)
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true);
pPlayer->CLOSE_GOSSIP_MENU();
return true;
}
pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
return true;
}
bool OnGossipHello(Player* pPlayer, Creature* pCreature)
{
if (InstanceScript* pInstance = pCreature->GetInstanceScript())
{
// Check if Shade of Aran event is done
if (pInstance->GetData(TYPE_ARAN) == DONE)
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
}
bool GossipSelect_npc_berthold(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction)
{
if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true);
pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
return true;
}
};
pPlayer->CLOSE_GOSSIP_MENU();
return true;
}
/*###
# npc_image_of_medivh
@@ -445,204 +460,194 @@ bool GossipSelect_npc_berthold(Player* pPlayer, Creature* /*pCreature*/, uint32
static float MedivPos[4] = {-11161.49,-1902.24,91.48,1.94};
static float ArcanagosPos[4] = {-11169.75,-1881.48,95.39,4.83};
struct npc_image_of_medivhAI : public ScriptedAI
␍class npc_image_of_medivh : public CreatureScript
{
npc_image_of_medivhAI(Creature* c) : ScriptedAI(c)
public:
npc_image_of_medivh() : CreatureScript("npc_image_of_medivh") { }
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
return new npc_image_of_medivhAI(pCreature);
}
ScriptedInstance *pInstance;
uint64 ArcanagosGUID;
uint32 YellTimer;
uint32 Step;
uint32 FireMedivhTimer;
uint32 FireArcanagosTimer;
bool EventStarted;
void Reset()
struct npc_image_of_medivhAI : public ScriptedAI
{
ArcanagosGUID = 0;
if (pInstance && pInstance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0)
npc_image_of_medivhAI(Creature* c) : ScriptedAI(c)
{
pInstance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID());
(*me).GetMotionMaster()->MovePoint(1,MedivPos[0],MedivPos[1],MedivPos[2]);
Step = 0;
}else
{
me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
me->RemoveCorpse();
pInstance = c->GetInstanceScript();
}
}
void EnterCombat(Unit* /*who*/) {}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (id == 1)
InstanceScript *pInstance;
uint64 ArcanagosGUID;
uint32 YellTimer;
uint32 Step;
uint32 FireMedivhTimer;
uint32 FireArcanagosTimer;
bool EventStarted;
void Reset()
{
StartEvent();
me->SetOrientation(MedivPos[3]);
me->SetOrientation(MedivPos[3]);
}
}
ArcanagosGUID = 0;
void StartEvent()
{
Step = 1;
EventStarted = true;
Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000);
if (!Arcanagos)
return;
ArcanagosGUID = Arcanagos->GetGUID();
Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
(*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]);
Arcanagos->SetOrientation(ArcanagosPos[3]);
me->SetOrientation(MedivPos[3]);
YellTimer = 10000;
}
uint32 NextStep(uint32 Step)
{
Unit* arca = Unit::GetUnit((*me),ArcanagosGUID);
Map* pMap = me->GetMap();
switch(Step)
{
case 0: return 9999999;
case 1:
me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL);
return 10000;
case 2:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL);
return 20000;
case 3:
me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL);
return 10000;
case 4:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL);
return 20000;
case 5:
me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL);
return 20000;
case 6:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL);
return 10000;
case 7:
FireArcanagosTimer = 500;
return 5000;
case 8:
FireMedivhTimer = 500;
DoCast(me, SPELL_MANA_SHIELD);
return 10000;
case 9:
me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false);
return 10000;
case 10:
if (arca)
DoCast(arca, SPELL_CONFLAGRATION_BLAST, false);
return 1000;
case 11:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL);
return 5000;
case 12:
arca->GetMotionMaster()->MovePoint(0, -11010.82,-1761.18, 156.47);
arca->setActive(true);
arca->InterruptNonMeleeSpells(true);
arca->SetSpeed(MOVE_FLIGHT, 2.0f);
return 10000;
case 13:
me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL);
return 10000;
case 14:
me->SetVisibility(VISIBILITY_OFF);
me->ClearInCombat();
if (pMap->IsDungeon())
if (pInstance && pInstance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0)
{
InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers();
for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->getSource()->isAlive())
{
if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE)
i->getSource()->CompleteQuest(9645);
}
}
pInstance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID());
(*me).GetMotionMaster()->MovePoint(1,MedivPos[0],MedivPos[1],MedivPos[2]);
Step = 0;
}else
{
me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
me->RemoveCorpse();
}
}
void EnterCombat(Unit* /*who*/) {}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (id == 1)
{
StartEvent();
me->SetOrientation(MedivPos[3]);
me->SetOrientation(MedivPos[3]);
}
return 50000;
case 15:
arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return 5000;
default : return 9999999;
}
}
void UpdateAI(const uint32 diff)
{
if (YellTimer <= diff)
void StartEvent()
{
if (EventStarted)
YellTimer = NextStep(Step++);
} else YellTimer -= diff;
Step = 1;
EventStarted = true;
Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000);
if (!Arcanagos)
return;
ArcanagosGUID = Arcanagos->GetGUID();
Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
(*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]);
Arcanagos->SetOrientation(ArcanagosPos[3]);
me->SetOrientation(MedivPos[3]);
YellTimer = 10000;
}
if (Step >= 7 && Step <= 12)
uint32 NextStep(uint32 Step)
{
Unit* arca = Unit::GetUnit((*me),ArcanagosGUID);
if (FireArcanagosTimer <= diff)
Map* pMap = me->GetMap();
switch(Step)
{
case 0: return 9999999;
case 1:
me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL);
return 10000;
case 2:
if (arca)
arca->CastSpell(me, SPELL_FIRE_BALL, false);
FireArcanagosTimer = 6000;
} else FireArcanagosTimer -= diff;
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL);
return 20000;
case 3:
me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL);
return 10000;
case 4:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL);
return 20000;
case 5:
me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL);
return 20000;
case 6:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL);
return 10000;
case 7:
FireArcanagosTimer = 500;
return 5000;
case 8:
FireMedivhTimer = 500;
DoCast(me, SPELL_MANA_SHIELD);
return 10000;
case 9:
me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false);
return 10000;
case 10:
if (arca)
DoCast(arca, SPELL_CONFLAGRATION_BLAST, false);
return 1000;
case 11:
if (arca)
CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL);
return 5000;
case 12:
arca->GetMotionMaster()->MovePoint(0, -11010.82,-1761.18, 156.47);
arca->setActive(true);
arca->InterruptNonMeleeSpells(true);
arca->SetSpeed(MOVE_FLIGHT, 2.0f);
return 10000;
case 13:
me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL);
return 10000;
case 14:
me->SetVisibility(VISIBILITY_OFF);
me->ClearInCombat();
if (pMap->IsDungeon())
{
InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers();
for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->getSource()->isAlive())
{
if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE)
i->getSource()->CompleteQuest(9645);
}
}
}
return 50000;
case 15:
arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return 5000;
default : return 9999999;
}
if (FireMedivhTimer <= diff)
{
if (arca)
DoCast(arca, SPELL_FIRE_BALL);
FireMedivhTimer = 5000;
} else FireMedivhTimer -= diff;
}
}
void UpdateAI(const uint32 diff)
{
if (YellTimer <= diff)
{
if (EventStarted)
YellTimer = NextStep(Step++);
} else YellTimer -= diff;
if (Step >= 7 && Step <= 12)
{
Unit* arca = Unit::GetUnit((*me),ArcanagosGUID);
if (FireArcanagosTimer <= diff)
{
if (arca)
arca->CastSpell(me, SPELL_FIRE_BALL, false);
FireArcanagosTimer = 6000;
} else FireArcanagosTimer -= diff;
if (FireMedivhTimer <= diff)
{
if (arca)
DoCast(arca, SPELL_FIRE_BALL);
FireMedivhTimer = 5000;
} else FireMedivhTimer -= diff;
}
}
};
};
CreatureAI* GetAI_npc_image_of_medivh(Creature* pCreature)
{
return new npc_image_of_medivhAI(pCreature);
}
void AddSC_karazhan()
{
Script* newscript;
newscript = new Script;
newscript->GetAI = &GetAI_npc_barnesAI;
newscript->Name = "npc_barnes";
newscript->pGossipHello = &GossipHello_npc_barnes;
newscript->pGossipSelect = &GossipSelect_npc_barnes;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "npc_berthold";
newscript->pGossipHello = &GossipHello_npc_berthold;
newscript->pGossipSelect = &GossipSelect_npc_berthold;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "npc_image_of_medivh";
newscript->GetAI = &GetAI_npc_image_of_medivh;
newscript->RegisterSelf();
new npc_barnes();
new npc_berthold();
new npc_image_of_medivh();
}