* 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:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user