* Rename InstanceData to InstanceScript

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

--HG--
branch : trunk
rename : src/server/game/Instances/InstanceData.cpp => src/server/game/Instances/InstanceScript.cpp
rename : src/server/game/Instances/InstanceData.h => src/server/game/Instances/InstanceScript.h
This commit is contained in:
azazel
2010-08-08 22:54:58 +06:00
parent 8a69e50d6a
commit 590199d8e1
482 changed files with 84476 additions and 82697 deletions
@@ -50,137 +50,140 @@ enum
{
ACHIEV_TIMED_START_EVENT = 9891,
};
struct boss_anubrekhanAI : public BossAI
␍class boss_anubrekhan : public CreatureScript
{
boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {}
public:
boss_anubrekhan() : CreatureScript("boss_anubrekhan") { }
bool hasTaunted;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
_Reset();
return new boss_anubrekhanAI (pCreature);
}
hasTaunted = false;
struct boss_anubrekhanAI : public BossAI
{
boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {}
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
bool hasTaunted;
void Reset()
{
Position pos;
_Reset();
// respawn guard using home position,
// otherwise, after a wipe, they respawn where boss was at wipe moment.
pos = me->GetHomePosition();
pos.m_positionY -= 10.0f;
me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN);
hasTaunted = false;
pos = me->GetHomePosition();
pos.m_positionY += 10.0f;
me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN);
}
}
void KilledUnit(Unit* victim)
{
//Force the player to spawn corpse scarabs via spell, TODO: Check percent chance for scarabs, 20% at the moment
if (!(rand()%5))
if (victim->GetTypeId() == TYPEID_PLAYER)
victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID());
DoScriptText(SAY_SLAY, me);
}
void JustDied(Unit *)
{
_JustDied();
// start achievement timer (kill Maexna within 20 min)
if (instance)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoScriptText(SAY_AGGRO, me);
events.ScheduleEvent(EVENT_IMPALE, 10000 + rand()%10000);
events.ScheduleEvent(EVENT_LOCUST, 90000);
events.ScheduleEvent(EVENT_BERSERK, 600000);
if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000,20000));
}
void MoveInLineOfSight(Unit *who)
{
if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER)
{
DoScriptText(SAY_GREET, me);
hasTaunted = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
void SummonedCreatureDespawn(Creature *summon)
{
BossAI::SummonedCreatureDespawn(summon);
// check if it is an actual killed guard
if (!me->isAlive() || summon->isAlive() || summon->GetEntry() != MOB_CRYPT_GUARD)
return;
summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID());
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
{
case EVENT_IMPALE:
//Cast Impale on a random target
//Do NOT cast it when we are afflicted by locust swarm
if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25)))
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(pTarget, RAID_MODE(SPELL_IMPALE_10,SPELL_IMPALE_25));
events.ScheduleEvent(EVENT_IMPALE, urand(10000,20000));
break;
case EVENT_LOCUST:
// TODO : Add Text
DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25));
DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
events.ScheduleEvent(EVENT_LOCUST, 90000);
break;
case EVENT_SPAWN_GUARDIAN_NORMAL:
// TODO : Add Text
DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK, true);
events.ScheduleEvent(EVENT_BERSERK, 600000);
break;
Position pos;
// respawn guard using home position,
// otherwise, after a wipe, they respawn where boss was at wipe moment.
pos = me->GetHomePosition();
pos.m_positionY -= 10.0f;
me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN);
pos = me->GetHomePosition();
pos.m_positionY += 10.0f;
me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN);
}
}
DoMeleeAttackIfReady();
}
void KilledUnit(Unit* victim)
{
//Force the player to spawn corpse scarabs via spell, TODO: Check percent chance for scarabs, 20% at the moment
if (!(rand()%5))
if (victim->GetTypeId() == TYPEID_PLAYER)
victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID());
DoScriptText(SAY_SLAY, me);
}
void JustDied(Unit *)
{
_JustDied();
// start achievement timer (kill Maexna within 20 min)
if (instance)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoScriptText(SAY_AGGRO, me);
events.ScheduleEvent(EVENT_IMPALE, 10000 + rand()%10000);
events.ScheduleEvent(EVENT_LOCUST, 90000);
events.ScheduleEvent(EVENT_BERSERK, 600000);
if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000,20000));
}
void MoveInLineOfSight(Unit *who)
{
if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER)
{
DoScriptText(SAY_GREET, me);
hasTaunted = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
void SummonedCreatureDespawn(Creature *summon)
{
BossAI::SummonedCreatureDespawn(summon);
// check if it is an actual killed guard
if (!me->isAlive() || summon->isAlive() || summon->GetEntry() != MOB_CRYPT_GUARD)
return;
summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID());
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_IMPALE:
//Cast Impale on a random target
//Do NOT cast it when we are afflicted by locust swarm
if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25)))
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(pTarget, RAID_MODE(SPELL_IMPALE_10,SPELL_IMPALE_25));
events.ScheduleEvent(EVENT_IMPALE, urand(10000,20000));
break;
case EVENT_LOCUST:
// TODO : Add Text
DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25));
DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
events.ScheduleEvent(EVENT_LOCUST, 90000);
break;
case EVENT_SPAWN_GUARDIAN_NORMAL:
// TODO : Add Text
DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK, true);
events.ScheduleEvent(EVENT_BERSERK, 600000);
break;
}
}
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_anubrekhan(Creature* pCreature)
{
return new boss_anubrekhanAI (pCreature);
}
void AddSC_boss_anubrekhan()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_anubrekhan";
newscript->GetAI = &GetAI_boss_anubrekhan;
newscript->RegisterSelf();
new boss_anubrekhan();
}
@@ -56,162 +56,166 @@ enum Achievements
ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10 = 1997,
ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25 = 2140
};
struct boss_faerlinaAI : public BossAI
␍class boss_faerlina : public CreatureScript
{
boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {}
public:
boss_faerlina() : CreatureScript("boss_faerlina") { }
bool greet;
bool doDelayFrenzy;
bool bAchievement;
void EnterCombat(Unit * /*who*/)
CreatureAI* GetAI(Creature* pCreature) const
{
_EnterCombat();
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4), me);
events.ScheduleEvent(EVENT_POISON, urand(10000,15000));
events.ScheduleEvent(EVENT_FIRE, urand(6000,18000));
events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000));
return new boss_faerlinaAI (pCreature);
}
void Reset()
struct boss_faerlinaAI : public BossAI
{
doDelayFrenzy = false;
bAchievement = true;
_Reset();
}
boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {}
void MoveInLineOfSight(Unit *who)
{
if (!greet && who->GetTypeId() == TYPEID_PLAYER)
bool greet;
bool doDelayFrenzy;
bool bAchievement;
void EnterCombat(Unit * /*who*/)
{
DoScriptText(SAY_GREET, me);
greet = true;
_EnterCombat();
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4), me);
events.ScheduleEvent(EVENT_POISON, urand(10000,15000));
events.ScheduleEvent(EVENT_FIRE, urand(6000,18000));
events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000));
}
BossAI::MoveInLineOfSight(who);
}
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%3))
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
if (instance && bAchievement)
instance->DoCompleteAchievement(RAID_MODE(ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10,ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25));
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (doDelayFrenzy && !me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE)))
void Reset()
{
doDelayFrenzy = false;
DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true);
bAchievement = true;
_Reset();
}
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
void MoveInLineOfSight(Unit *who)
{
switch(eventId)
if (!greet && who->GetTypeId() == TYPEID_PLAYER)
{
case EVENT_POISON:
if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE)))
DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY,H_SPELL_POISON_BOLT_VOLLEY));
events.ScheduleEvent(EVENT_POISON, urand(8000,15000));
break;
case EVENT_FIRE:
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(pTarget, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE));
events.ScheduleEvent(EVENT_FIRE, urand(6000,18000));
break;
case EVENT_FRENZY:
// TODO : Add Text
if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE)))
DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY));
else
doDelayFrenzy = true;
DoScriptText(SAY_GREET, me);
greet = true;
}
BossAI::MoveInLineOfSight(who);
}
events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000));
break;
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%3))
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
if (instance && bAchievement)
instance->DoCompleteAchievement(RAID_MODE(ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10,ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25));
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (doDelayFrenzy && !me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE)))
{
doDelayFrenzy = false;
DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true);
}
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_POISON:
if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE)))
DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY,H_SPELL_POISON_BOLT_VOLLEY));
events.ScheduleEvent(EVENT_POISON, urand(8000,15000));
break;
case EVENT_FIRE:
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(pTarget, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE));
events.ScheduleEvent(EVENT_FIRE, urand(6000,18000));
break;
case EVENT_FRENZY:
// TODO : Add Text
if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE)))
DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY));
else
doDelayFrenzy = true;
events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000));
break;
}
}
DoMeleeAttackIfReady();
}
void SpellHit(Unit* caster, const SpellEntry *spell)
{
if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE)
{
// TODO : Add Text
bAchievement = false;
doDelayFrenzy = true;
me->Kill(caster);
}
}
};
};
␍class mob_faerlina_add : public CreatureScript
{
public:
mob_faerlina_add() : CreatureScript("mob_faerlina_add") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new mob_faerlina_addAI (pCreature);
}
struct mob_faerlina_addAI : public ScriptedAI
{
mob_faerlina_addAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
}
InstanceScript *pInstance;
void Reset()
{
if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) {
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, SPELL_EFFECT_BIND, true);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true);
}
}
DoMeleeAttackIfReady();
}
void SpellHit(Unit* caster, const SpellEntry *spell)
{
if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE)
void JustDied(Unit * /*killer*/)
{
// TODO : Add Text
bAchievement = false;
doDelayFrenzy = true;
me->Kill(caster);
if (pInstance && getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
{
if (Creature *pFaerlina = pInstance->instance->GetCreature(pInstance->GetData64(DATA_FAERLINA)))
DoCast(pFaerlina, SPELL_WIDOWS_EMBRACE);
}
}
}
};
};
CreatureAI* GetAI_boss_faerlina(Creature* pCreature)
{
return new boss_faerlinaAI (pCreature);
}
struct mob_faerlina_addAI : public ScriptedAI
{
mob_faerlina_addAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = pCreature->GetInstanceData();
}
ScriptedInstance *pInstance;
void Reset()
{
if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) {
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, SPELL_EFFECT_BIND, true);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true);
}
}
void JustDied(Unit * /*killer*/)
{
if (pInstance && getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
{
if (Creature *pFaerlina = pInstance->instance->GetCreature(pInstance->GetData64(DATA_FAERLINA)))
DoCast(pFaerlina, SPELL_WIDOWS_EMBRACE);
}
}
};
CreatureAI* GetAI_mob_faerlina_add(Creature* pCreature)
{
return new mob_faerlina_addAI (pCreature);
}
void AddSC_boss_faerlina()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_faerlina";
newscript->GetAI = &GetAI_boss_faerlina;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_faerlina_add";
newscript->GetAI = &GetAI_mob_faerlina_add;
newscript->RegisterSelf();
new boss_faerlina();
new mob_faerlina_add();
}
@@ -76,323 +76,325 @@ const int32 SAY_DEATH[] = {-1533057, -1533050, -1533074, -1533064};
#define SAY_BARON_AGGRO RAND(-1533065,-1533066,-1533067)
#define SAY_BARON_SLAY RAND(-1533068,-1533069)
struct boss_four_horsemenAI : public BossAI
␍class boss_four_horsemen : public CreatureScript
{
boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMEN)
public:
boss_four_horsemen() : CreatureScript("boss_four_horsemen") { }
CreatureAI* GetAI(Creature* pCreature) const
{
id = Horsemen(0);
for (uint8 i = 0; i < 4; ++i)
if (me->GetEntry() == MOB_HORSEMEN[i])
id = Horsemen(i);
caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR);
return new boss_four_horsemenAI (pCreature);
}
Horsemen id;
uint64 uiEventStarterGUID;
uint8 nextWP;
uint32 punishTimer;
bool caster;
bool nextMovementStarted;
bool movementCompleted;
bool movementStarted;
bool encounterActionAttack;
bool encounterActionReset;
bool doDelayPunish;
void Reset()
struct boss_four_horsemenAI : public BossAI
{
if (!encounterActionReset)
DoEncounterAction(NULL, false, true, false);
if (instance)
instance->SetData(DATA_HORSEMEN0 + id, NOT_STARTED);
me->SetReactState(REACT_AGGRESSIVE);
uiEventStarterGUID = 0;
nextWP = 0;
punishTimer = 2000;
nextMovementStarted = false;
movementCompleted = false;
movementStarted = false;
encounterActionAttack = false;
encounterActionReset = false;
doDelayPunish = false;
_Reset();
}
bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead)
{
if (!instance)
return false;
Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE)));
Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY)));
Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON)));
Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR)));
if (Thane && Lady && Baron && Sir)
boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMEN)
{
if (attack && who)
{
CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemenAI, Thane->AI())->AttackStart(who);
CAST_AI(boss_four_horsemenAI, Lady->AI())->AttackStart(who);
CAST_AI(boss_four_horsemenAI, Baron->AI())->AttackStart(who);
CAST_AI(boss_four_horsemenAI, Sir->AI())->AttackStart(who);
}
if (reset)
{
if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED)
{
if (!Thane->isAlive())
Thane->Respawn();
if (!Lady->isAlive())
Lady->Respawn();
if (!Baron->isAlive())
Baron->Respawn();
if (!Sir->isAlive())
Sir->Respawn();
CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemenAI, Thane->AI())->EnterEvadeMode();
CAST_AI(boss_four_horsemenAI, Lady->AI())->EnterEvadeMode();
CAST_AI(boss_four_horsemenAI, Baron->AI())->EnterEvadeMode();
CAST_AI(boss_four_horsemenAI, Sir->AI())->EnterEvadeMode();
}
}
if (checkAllDead)
return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive();
id = Horsemen(0);
for (uint8 i = 0; i < 4; ++i)
if (me->GetEntry() == MOB_HORSEMEN[i])
id = Horsemen(i);
caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR);
}
return false;
}
void BeginFourHorsemenMovement()
{
movementStarted = true;
me->SetReactState(REACT_PASSIVE);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true);
Horsemen id;
uint64 uiEventStarterGUID;
uint8 nextWP;
uint32 punishTimer;
bool caster;
bool nextMovementStarted;
bool movementCompleted;
bool movementStarted;
bool encounterActionAttack;
bool encounterActionReset;
bool doDelayPunish;
switch(id)
void Reset()
{
case HORSEMEN_THANE:
me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]);
break;
case HORSEMEN_LADY:
me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]);
break;
case HORSEMEN_BARON:
me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]);
break;
case HORSEMEN_SIR:
me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]);
break;
}
}
if (!encounterActionReset)
DoEncounterAction(NULL, false, true, false);
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (instance)
instance->SetData(DATA_HORSEMEN0 + id, NOT_STARTED);
if (id == 2 || id == 5 || id == 8 || id == 11)
{
movementCompleted = true;
me->SetReactState(REACT_AGGRESSIVE);
uiEventStarterGUID = 0;
nextWP = 0;
punishTimer = 2000;
nextMovementStarted = false;
movementCompleted = false;
movementStarted = false;
encounterActionAttack = false;
encounterActionReset = false;
doDelayPunish = false;
_Reset();
}
Unit *eventStarter = Unit::GetUnit(*me, uiEventStarterGUID);
bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead)
{
if (!instance)
return false;
if (eventStarter && me->canAttack(eventStarter))
AttackStart(eventStarter);
else if (!UpdateVictim())
Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE)));
Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY)));
Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON)));
Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR)));
if (Thane && Lady && Baron && Sir)
{
EnterEvadeMode();
if (attack && who)
{
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Thane->AI())->AttackStart(who);
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Lady->AI())->AttackStart(who);
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Baron->AI())->AttackStart(who);
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Sir->AI())->AttackStart(who);
}
if (reset)
{
if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED)
{
if (!Thane->isAlive())
Thane->Respawn();
if (!Lady->isAlive())
Lady->Respawn();
if (!Baron->isAlive())
Baron->Respawn();
if (!Sir->isAlive())
Sir->Respawn();
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Thane->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Lady->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Baron->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Sir->AI())->encounterActionReset = true;
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Thane->AI())->EnterEvadeMode();
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Lady->AI())->EnterEvadeMode();
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Baron->AI())->EnterEvadeMode();
CAST_AI(boss_four_horsemen::boss_four_horsemenAI, Sir->AI())->EnterEvadeMode();
}
}
if (checkAllDead)
return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive();
}
return false;
}
void BeginFourHorsemenMovement()
{
movementStarted = true;
me->SetReactState(REACT_PASSIVE);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true);
switch(id)
{
case HORSEMEN_THANE:
me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]);
break;
case HORSEMEN_LADY:
me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]);
break;
case HORSEMEN_BARON:
me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]);
break;
case HORSEMEN_SIR:
me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]);
break;
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (id == 2 || id == 5 || id == 8 || id == 11)
{
movementCompleted = true;
me->SetReactState(REACT_AGGRESSIVE);
Unit *eventStarter = Unit::GetUnit(*me, uiEventStarterGUID);
if (eventStarter && me->canAttack(eventStarter))
AttackStart(eventStarter);
else if (!UpdateVictim())
{
EnterEvadeMode();
return;
}
if (caster)
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
}
return;
}
if (caster)
nextMovementStarted = false;
nextWP = id + 1;
}
// switch to "who" if nearer than current target.
void SelectNearestTarget(Unit *who)
{
if (me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who))
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->getThreatManager().modifyThreatPercent(me->getVictim(), -100);
me->AddThreat(who, 1000000.0f);
}
}
void MoveInLineOfSight(Unit *who)
{
BossAI::MoveInLineOfSight(who);
if (caster)
SelectNearestTarget(who);
}
void AttackStart(Unit *who)
{
if (!movementCompleted && !movementStarted)
{
uiEventStarterGUID = who->GetGUID();
BeginFourHorsemenMovement();
if (!encounterActionAttack)
DoEncounterAction(who, true, false, false);
}
else if (movementCompleted && movementStarted)
{
if (caster)
me->Attack(who, false);
else
BossAI::AttackStart(who);
}
}
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
{
if (id == HORSEMEN_BARON)
DoScriptText(SAY_BARON_SLAY, me);
else
DoScriptText(SAY_SLAY[id], me);
}
}
void JustDied(Unit* /*killer*/)
{
events.Reset();
summons.DespawnAll();
if (instance)
instance->SetData(DATA_HORSEMEN0 + id, DONE);
if (instance && DoEncounterAction(NULL, false, false, true))
{
instance->SetBossState(BOSS_HORSEMEN, DONE);
instance->SaveToDB();
// Achievements related to the 4-horsemen are given through spell 59450 which does not exist.
// There is thus no way it can be given by casting the spell on the players.
instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59450);
}
return;
DoScriptText(SAY_DEATH[id], me);
}
nextMovementStarted = false;
nextWP = id + 1;
}
// switch to "who" if nearer than current target.
void SelectNearestTarget(Unit *who)
{
if (me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who))
void EnterCombat(Unit * /*who*/)
{
me->getThreatManager().modifyThreatPercent(me->getVictim(), -100);
me->AddThreat(who, 1000000.0f);
}
}
_EnterCombat();
void MoveInLineOfSight(Unit *who)
{
BossAI::MoveInLineOfSight(who);
if (caster)
SelectNearestTarget(who);
}
void AttackStart(Unit *who)
{
if (!movementCompleted && !movementStarted)
{
uiEventStarterGUID = who->GetGUID();
BeginFourHorsemenMovement();
if (!encounterActionAttack)
DoEncounterAction(who, true, false, false);
}
else if (movementCompleted && movementStarted)
{
if (caster)
me->Attack(who, false);
else
BossAI::AttackStart(who);
}
}
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
{
if (id == HORSEMEN_BARON)
DoScriptText(SAY_BARON_SLAY, me);
DoScriptText(SAY_BARON_AGGRO, me);
else
DoScriptText(SAY_SLAY[id], me);
}
}
DoScriptText(SAY_AGGRO[id], me);
void JustDied(Unit* /*killer*/)
{
events.Reset();
summons.DespawnAll();
if (instance)
instance->SetData(DATA_HORSEMEN0 + id, DONE);
if (instance && DoEncounterAction(NULL, false, false, true))
{
instance->SetBossState(BOSS_HORSEMEN, DONE);
instance->SaveToDB();
// Achievements related to the 4-horsemen are given through spell 59450 which does not exist.
// There is thus no way it can be given by casting the spell on the players.
instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59450);
events.ScheduleEvent(EVENT_MARK, 15000);
events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000);
events.ScheduleEvent(EVENT_BERSERK, 15*100*1000);
}
DoScriptText(SAY_DEATH[id], me);
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
if (id == HORSEMEN_BARON)
DoScriptText(SAY_BARON_AGGRO, me);
else
DoScriptText(SAY_AGGRO[id], me);
events.ScheduleEvent(EVENT_MARK, 15000);
events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000);
events.ScheduleEvent(EVENT_BERSERK, 15*100*1000);
}
void UpdateAI(const uint32 diff)
{
if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted)
void UpdateAI(const uint32 diff)
{
nextMovementStarted = true;
me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]);
}
if (!UpdateVictim() || !CheckInRoom() || !movementCompleted)
return;
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted)
{
case EVENT_MARK:
if (!(rand()%5))
nextMovementStarted = true;
me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]);
}
if (!UpdateVictim() || !CheckInRoom() || !movementCompleted)
return;
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_MARK:
if (!(rand()%5))
DoScriptText(SAY_SPECIAL[id], me);
DoCastAOE(SPELL_MARK[id]);
events.ScheduleEvent(EVENT_MARK, 15000);
break;
case EVENT_CAST:
if (!(rand()%5))
DoScriptText(SAY_TAUNT[rand()%3][id], me);
if (caster)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(pTarget, SPELL_PRIMARY(id));
}
else
DoCast(me->getVictim(), SPELL_PRIMARY(id));
events.ScheduleEvent(EVENT_CAST, 15000);
break;
case EVENT_BERSERK:
DoScriptText(SAY_SPECIAL[id], me);
DoCastAOE(SPELL_MARK[id]);
events.ScheduleEvent(EVENT_MARK, 15000);
break;
case EVENT_CAST:
if (!(rand()%5))
DoScriptText(SAY_TAUNT[rand()%3][id], me);
if (caster)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(pTarget, SPELL_PRIMARY(id));
}
else
DoCast(me->getVictim(), SPELL_PRIMARY(id));
events.ScheduleEvent(EVENT_CAST, 15000);
break;
case EVENT_BERSERK:
DoScriptText(SAY_SPECIAL[id], me);
DoCast(me, EVENT_BERSERK);
break;
DoCast(me, EVENT_BERSERK);
break;
}
}
}
if (punishTimer <= diff)
{
if (doDelayPunish)
if (punishTimer <= diff)
{
DoCastAOE(SPELL_PUNISH[id], true);
doDelayPunish = false;
}
punishTimer = 2000;
} else punishTimer -= diff;
if (doDelayPunish)
{
DoCastAOE(SPELL_PUNISH[id], true);
doDelayPunish = false;
}
punishTimer = 2000;
} else punishTimer -= diff;
if (!caster)
DoMeleeAttackIfReady();
else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish)
doDelayPunish = true;
}
};
if (!caster)
DoMeleeAttackIfReady();
else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish)
doDelayPunish = true;
}
};
CreatureAI* GetAI_four_horsemen(Creature* pCreature)
{
return new boss_four_horsemenAI (pCreature);
}
void AddSC_boss_four_horsemen()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_four_horsemen";
newscript->GetAI = &GetAI_four_horsemen;
newscript->RegisterSelf();
new boss_four_horsemen();
}
@@ -44,105 +44,107 @@ enum Events
};
#define EMOTE_NEARBY " spots a nearby zombie to devour!"
struct boss_gluthAI : public BossAI
␍class boss_gluth : public CreatureScript
{
boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH)
public:
boss_gluth() : CreatureScript("boss_gluth") { }
CreatureAI* GetAI(Creature* pCreature) const
{
// Do not let Gluth be affected by zombies' debuff
me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true);
return new boss_gluthAI (pCreature);
}
void MoveInLineOfSight(Unit *who)
struct boss_gluthAI : public BossAI
{
if (who->GetEntry() == MOB_ZOMBIE && me->IsWithinDistInMap(who, 7))
boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH)
{
SetGazeOn(who);
// TODO: use a script text
me->MonsterTextEmote(EMOTE_NEARBY, 0, true);
// Do not let Gluth be affected by zombies' debuff
me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true);
}
else
BossAI::MoveInLineOfSight(who);
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
events.ScheduleEvent(EVENT_WOUND, 10000);
events.ScheduleEvent(EVENT_ENRAGE, 15000);
events.ScheduleEvent(EVENT_DECIMATE, 105000);
events.ScheduleEvent(EVENT_BERSERK, 8*60000);
events.ScheduleEvent(EVENT_SUMMON, 15000);
}
void JustSummoned(Creature *summon)
{
if (summon->GetEntry() == MOB_ZOMBIE)
summon->AI()->AttackStart(me);
summons.Summon(summon);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictimWithGaze() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void MoveInLineOfSight(Unit *who)
{
switch(eventId)
if (who->GetEntry() == MOB_ZOMBIE && me->IsWithinDistInMap(who, 7))
{
case EVENT_WOUND:
DoCast(me->getVictim(), SPELL_MORTAL_WOUND);
events.ScheduleEvent(EVENT_WOUND, 10000);
break;
case EVENT_ENRAGE:
// TODO : Add missing text
DoCast(me, SPELL_ENRAGE);
events.ScheduleEvent(EVENT_ENRAGE, 15000);
break;
case EVENT_DECIMATE:
// TODO : Add missing text
DoCastAOE(SPELL_DECIMATE);
events.ScheduleEvent(EVENT_DECIMATE, 105000);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK);
events.ScheduleEvent(EVENT_BERSERK, 5*60000);
break;
case EVENT_SUMMON:
for (uint32 i = 0; i < RAID_MODE(1,2); ++i)
DoSummon(MOB_ZOMBIE, PosSummon[rand()%3]);
events.ScheduleEvent(EVENT_SUMMON, 10000);
break;
SetGazeOn(who);
// TODO: use a script text
me->MonsterTextEmote(EMOTE_NEARBY, 0, true);
}
else
BossAI::MoveInLineOfSight(who);
}
if (me->getVictim() && me->getVictim()->GetEntry() == MOB_ZOMBIE)
void EnterCombat(Unit * /*who*/)
{
if (me->IsWithinMeleeRange(me->getVictim()))
{
me->Kill(me->getVictim());
me->ModifyHealth(me->GetMaxHealth() * 0.05f);
}
_EnterCombat();
events.ScheduleEvent(EVENT_WOUND, 10000);
events.ScheduleEvent(EVENT_ENRAGE, 15000);
events.ScheduleEvent(EVENT_DECIMATE, 105000);
events.ScheduleEvent(EVENT_BERSERK, 8*60000);
events.ScheduleEvent(EVENT_SUMMON, 15000);
}
else
DoMeleeAttackIfReady();
}
void JustSummoned(Creature *summon)
{
if (summon->GetEntry() == MOB_ZOMBIE)
summon->AI()->AttackStart(me);
summons.Summon(summon);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictimWithGaze() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_WOUND:
DoCast(me->getVictim(), SPELL_MORTAL_WOUND);
events.ScheduleEvent(EVENT_WOUND, 10000);
break;
case EVENT_ENRAGE:
// TODO : Add missing text
DoCast(me, SPELL_ENRAGE);
events.ScheduleEvent(EVENT_ENRAGE, 15000);
break;
case EVENT_DECIMATE:
// TODO : Add missing text
DoCastAOE(SPELL_DECIMATE);
events.ScheduleEvent(EVENT_DECIMATE, 105000);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK);
events.ScheduleEvent(EVENT_BERSERK, 5*60000);
break;
case EVENT_SUMMON:
for (uint32 i = 0; i < RAID_MODE(1,2); ++i)
DoSummon(MOB_ZOMBIE, PosSummon[rand()%3]);
events.ScheduleEvent(EVENT_SUMMON, 10000);
break;
}
}
if (me->getVictim() && me->getVictim()->GetEntry() == MOB_ZOMBIE)
{
if (me->IsWithinMeleeRange(me->getVictim()))
{
me->Kill(me->getVictim());
me->ModifyHealth(me->GetMaxHealth() * 0.05f);
}
}
else
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_gluth(Creature* pCreature)
{
return new boss_gluthAI (pCreature);
}
void AddSC_boss_gluth()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_gluth";
newscript->GetAI = &GetAI_boss_gluth;
newscript->RegisterSelf();
new boss_gluth();
}
@@ -142,442 +142,448 @@ struct NotOnSameSide : public std::unary_function<Unit *, bool> {
return (m_inLiveSide != IN_LIVE_SIDE(pTarget));
}
};
struct boss_gothikAI : public BossAI
␍class boss_gothik : public CreatureScript
{
boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {}
public:
boss_gothik() : CreatureScript("boss_gothik") { }
uint32 waveCount;
typedef std::vector<Creature*> TriggerVct;
TriggerVct liveTrigger, deadTrigger;
bool mergedSides;
bool phaseTwo;
bool thirtyPercentReached;
std::vector<uint64> LiveTriggerGUID;
std::vector<uint64> DeadTriggerGUID;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
LiveTriggerGUID.clear();
DeadTriggerGUID.clear();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE);
me->SetReactState(REACT_PASSIVE);
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
_Reset();
mergedSides = false;
phaseTwo = false;
thirtyPercentReached = false;
return new boss_gothikAI (pCreature);
}
void EnterCombat(Unit * /*who*/)
struct boss_gothikAI : public BossAI
{
for (uint32 i = 0; i < POS_LIVE; ++i)
if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i]))
LiveTriggerGUID.push_back(trigger->GetGUID());
for (uint32 i = 0; i < POS_DEAD; ++i)
if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i]))
DeadTriggerGUID.push_back(trigger->GetGUID());
boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {}
if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD)
uint32 waveCount;
typedef std::vector<Creature*> TriggerVct;
TriggerVct liveTrigger, deadTrigger;
bool mergedSides;
bool phaseTwo;
bool thirtyPercentReached;
std::vector<uint64> LiveTriggerGUID;
std::vector<uint64> DeadTriggerGUID;
void Reset()
{
sLog.outError("Script Gothik: cannot summon triggers!");
EnterEvadeMode();
return;
LiveTriggerGUID.clear();
DeadTriggerGUID.clear();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE);
me->SetReactState(REACT_PASSIVE);
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
_Reset();
mergedSides = false;
phaseTwo = false;
thirtyPercentReached = false;
}
_EnterCombat();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE);
waveCount = 0;
events.ScheduleEvent(EVENT_SUMMON, 30000);
DoTeleportTo(PosPlatform);
DoScriptText(SAY_SPEECH, me);
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY);
}
void JustSummoned(Creature *summon)
{
if (summon->GetEntry() == WORLD_TRIGGER)
summon->setActive(true);
else if (!mergedSides)
void EnterCombat(Unit * /*who*/)
{
summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0);
summon->AI()->EnterEvadeMode();
}
else
{
summon->AI()->DoAction(0);
summon->AI()->DoZoneInCombat();
}
summons.Summon(summon);
}
for (uint32 i = 0; i < POS_LIVE; ++i)
if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i]))
LiveTriggerGUID.push_back(trigger->GetGUID());
for (uint32 i = 0; i < POS_DEAD; ++i)
if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i]))
DeadTriggerGUID.push_back(trigger->GetGUID());
void SummonedCreatureDespawn(Creature *summon)
{
summons.Despawn(summon);
}
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
DoScriptText(SAY_KILL, me);
}
void JustDied(Unit* /*Killer*/)
{
LiveTriggerGUID.clear();
DeadTriggerGUID.clear();
_JustDied();
DoScriptText(SAY_DEATH, me);
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
}
void DoGothikSummon(uint32 entry)
{
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
{
switch(entry)
if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD)
{
case MOB_LIVE_TRAINEE:
{
if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[0]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1);
if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[1]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1);
if (Creature *LiveTrigger2 = Unit::GetCreature(*me, LiveTriggerGUID[2]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger2, 1);
break;
}
case MOB_LIVE_KNIGHT:
{
if (Creature *LiveTrigger3 = Unit::GetCreature(*me, LiveTriggerGUID[3]))
DoSummon(MOB_LIVE_KNIGHT, LiveTrigger3, 1);
if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[5]))
DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1);
break;
}
case MOB_LIVE_RIDER:
{
if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1);
break;
}
sLog.outError("Script Gothik: cannot summon triggers!");
EnterEvadeMode();
return;
}
_EnterCombat();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE);
waveCount = 0;
events.ScheduleEvent(EVENT_SUMMON, 30000);
DoTeleportTo(PosPlatform);
DoScriptText(SAY_SPEECH, me);
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY);
}
else
void JustSummoned(Creature *summon)
{
switch(entry)
if (summon->GetEntry() == WORLD_TRIGGER)
summon->setActive(true);
else if (!mergedSides)
{
case MOB_LIVE_TRAINEE:
{
if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1);
if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1);
break;
}
case MOB_LIVE_KNIGHT:
{
if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1);
break;
}
case MOB_LIVE_RIDER:
{
if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1);
break;
}
summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0);
summon->AI()->EnterEvadeMode();
}
}
}
bool CheckGroupSplitted()
{
bool checklife = false;
bool checkdead = false;
Map* pMap = me->GetMap();
if (pMap && pMap->IsDungeon())
{
Map::PlayerList const &PlayerList = pMap->GetPlayers();
if (!PlayerList.isEmpty())
else
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->getSource() && i->getSource()->isAlive() &&
i->getSource()->GetPositionX() <= POS_X_NORTH &&
i->getSource()->GetPositionX() >= POS_X_SOUTH &&
i->getSource()->GetPositionY() <= POS_Y_GATE &&
i->getSource()->GetPositionY() >= POS_Y_EAST)
{
checklife = true;
}
else if (i->getSource() && i->getSource()->isAlive() &&
i->getSource()->GetPositionX() <= POS_X_NORTH &&
i->getSource()->GetPositionX() >= POS_X_SOUTH &&
i->getSource()->GetPositionY() >= POS_Y_GATE &&
i->getSource()->GetPositionY() <= POS_Y_WEST)
{
checkdead = true;
}
if (checklife && checkdead)
return true;
}
summon->AI()->DoAction(0);
summon->AI()->DoZoneInCombat();
}
summons.Summon(summon);
}
return false;
}
void SpellHit(Unit * /*caster*/, const SpellEntry *spell)
{
uint32 spellId = 0;
switch(spell->Id)
void SummonedCreatureDespawn(Creature *summon)
{
case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break;
case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break;
case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break;
summons.Despawn(summon);
}
if (spellId && me->isInCombat())
void KilledUnit(Unit* /*victim*/)
{
me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST);
if (Creature *pRandomDeadTrigger = Unit::GetCreature(*me, DeadTriggerGUID[rand() % POS_DEAD]))
me->CastSpell(pRandomDeadTrigger, spellId, true);
if (!(rand()%5))
DoScriptText(SAY_KILL, me);
}
}
void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
{
if (!me->isInCombat())
return;
switch(spell->Id)
void JustDied(Unit* /*Killer*/)
{
case SPELL_INFORM_DEAD_TRAINEE:
DoSummon(MOB_DEAD_TRAINEE, pTarget, 0);
break;
case SPELL_INFORM_DEAD_KNIGHT:
DoSummon(MOB_DEAD_KNIGHT, pTarget, 0);
break;
case SPELL_INFORM_DEAD_RIDER:
DoSummon(MOB_DEAD_RIDER, pTarget, 1.0f);
DoSummon(MOB_DEAD_HORSE, pTarget, 1.0f);
break;
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateCombatState() || !CheckInRoom())
return;
events.Update(diff);
if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo)
{
thirtyPercentReached = true;
LiveTriggerGUID.clear();
DeadTriggerGUID.clear();
_JustDied();
DoScriptText(SAY_DEATH, me);
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
}
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
void DoGothikSummon(uint32 entry)
{
switch(eventId)
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
{
case EVENT_SUMMON:
if (waves[waveCount].entry)
{
if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL))
DoGothikSummon(waves[waveCount].entry);
else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL))
DoGothikSummon(waves[waveCount].entry);
else if (waves[waveCount].mode == 1)
DoGothikSummon(waves[waveCount].entry);
// if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11)
if (waveCount == 11)
{
if (!CheckGroupSplitted())
{
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
summons.DoAction(0, 0);
summons.DoZoneInCombat();
mergedSides = true;
}
}
if (waves[waveCount].mode == 1)
events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time);
else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL))
events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time);
else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL))
events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time);
else
events.ScheduleEvent(EVENT_SUMMON, 0);
++waveCount;
}
else
{
phaseTwo = true;
DoScriptText(SAY_TELEPORT, me);
DoTeleportTo(PosGroundLiveSide);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
summons.DoAction(0, 0);
summons.DoZoneInCombat();
events.ScheduleEvent(EVENT_BOLT, 1000);
events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000));
events.ScheduleEvent(EVENT_TELEPORT, 20000);
}
break;
case EVENT_BOLT:
DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT));
events.ScheduleEvent(EVENT_BOLT, 1000);
break;
case EVENT_HARVEST:
DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true);
events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000));
break;
case EVENT_TELEPORT:
if (!thirtyPercentReached)
{
me->AttackStop();
if (IN_LIVE_SIDE(me))
{
DoTeleportTo(PosGroundDeadSide);
}
else
{
DoTeleportTo(PosGroundLiveSide);
}
me->getThreatManager().resetAggro(NotOnSameSide(me));
if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0))
{
me->getThreatManager().addThreat(pTarget, 100.0f);
AttackStart(pTarget);
}
events.ScheduleEvent(EVENT_TELEPORT, 20000);
}
break;
}
}
DoMeleeAttackIfReady();
}
};
struct mob_gothik_minionAI : public CombatAI
{
mob_gothik_minionAI(Creature *c) : CombatAI(c)
{
liveSide = IN_LIVE_SIDE(me);
}
bool liveSide;
bool gateClose;
bool isOnSameSide(const Unit *pWho)
{
return (liveSide == IN_LIVE_SIDE(pWho));
}
void DoAction(const int32 param)
{
gateClose = param;
}
void DamageTaken(Unit *attacker, uint32 &damage)
{
if (gateClose && !isOnSameSide(attacker))
damage = 0;
}
void JustDied(Unit * /*killer*/)
{
if (me->isSummon())
{
if (Unit *owner = CAST_SUM(me)->GetSummoner())
CombatAI::JustDied(owner);
}
}
void EnterEvadeMode()
{
if (!gateClose)
{
CombatAI::EnterEvadeMode();
return;
}
if (!_EnterEvadeMode())
return;
Map* pMap = me->GetMap();
if (pMap->IsDungeon())
{
Map::PlayerList const &PlayerList = pMap->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
switch(entry)
{
if (i->getSource() && i->getSource()->isAlive() && isOnSameSide(i->getSource()))
case MOB_LIVE_TRAINEE:
{
AttackStart(i->getSource());
return;
if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[0]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1);
if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[1]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1);
if (Creature *LiveTrigger2 = Unit::GetCreature(*me, LiveTriggerGUID[2]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger2, 1);
break;
}
case MOB_LIVE_KNIGHT:
{
if (Creature *LiveTrigger3 = Unit::GetCreature(*me, LiveTriggerGUID[3]))
DoSummon(MOB_LIVE_KNIGHT, LiveTrigger3, 1);
if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[5]))
DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1);
break;
}
case MOB_LIVE_RIDER:
{
if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1);
break;
}
}
}
else
{
switch(entry)
{
case MOB_LIVE_TRAINEE:
{
if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1);
if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1);
break;
}
case MOB_LIVE_KNIGHT:
{
if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1);
break;
}
case MOB_LIVE_RIDER:
{
if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4]))
DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1);
break;
}
}
}
}
me->GetMotionMaster()->MoveIdle();
Reset();
}
void UpdateAI(const uint32 diff)
{
if (gateClose && (!isOnSameSide(me) || me->getVictim() && !isOnSameSide(me->getVictim())))
bool CheckGroupSplitted()
{
EnterEvadeMode();
return;
bool checklife = false;
bool checkdead = false;
Map* pMap = me->GetMap();
if (pMap && pMap->IsDungeon())
{
Map::PlayerList const &PlayerList = pMap->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->getSource() && i->getSource()->isAlive() &&
i->getSource()->GetPositionX() <= POS_X_NORTH &&
i->getSource()->GetPositionX() >= POS_X_SOUTH &&
i->getSource()->GetPositionY() <= POS_Y_GATE &&
i->getSource()->GetPositionY() >= POS_Y_EAST)
{
checklife = true;
}
else if (i->getSource() && i->getSource()->isAlive() &&
i->getSource()->GetPositionX() <= POS_X_NORTH &&
i->getSource()->GetPositionX() >= POS_X_SOUTH &&
i->getSource()->GetPositionY() >= POS_Y_GATE &&
i->getSource()->GetPositionY() <= POS_Y_WEST)
{
checkdead = true;
}
if (checklife && checkdead)
return true;
}
}
}
return false;
}
CombatAI::UpdateAI(diff);
void SpellHit(Unit * /*caster*/, const SpellEntry *spell)
{
uint32 spellId = 0;
switch(spell->Id)
{
case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break;
case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break;
case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break;
}
if (spellId && me->isInCombat())
{
me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST);
if (Creature *pRandomDeadTrigger = Unit::GetCreature(*me, DeadTriggerGUID[rand() % POS_DEAD]))
me->CastSpell(pRandomDeadTrigger, spellId, true);
}
}
void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
{
if (!me->isInCombat())
return;
switch(spell->Id)
{
case SPELL_INFORM_DEAD_TRAINEE:
DoSummon(MOB_DEAD_TRAINEE, pTarget, 0);
break;
case SPELL_INFORM_DEAD_KNIGHT:
DoSummon(MOB_DEAD_KNIGHT, pTarget, 0);
break;
case SPELL_INFORM_DEAD_RIDER:
DoSummon(MOB_DEAD_RIDER, pTarget, 1.0f);
DoSummon(MOB_DEAD_HORSE, pTarget, 1.0f);
break;
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateCombatState() || !CheckInRoom())
return;
events.Update(diff);
if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo)
{
thirtyPercentReached = true;
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
}
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_SUMMON:
if (waves[waveCount].entry)
{
if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL))
DoGothikSummon(waves[waveCount].entry);
else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL))
DoGothikSummon(waves[waveCount].entry);
else if (waves[waveCount].mode == 1)
DoGothikSummon(waves[waveCount].entry);
// if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11)
if (waveCount == 11)
{
if (!CheckGroupSplitted())
{
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
summons.DoAction(0, 0);
summons.DoZoneInCombat();
mergedSides = true;
}
}
if (waves[waveCount].mode == 1)
events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time);
else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL))
events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time);
else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL))
events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time);
else
events.ScheduleEvent(EVENT_SUMMON, 0);
++waveCount;
}
else
{
phaseTwo = true;
DoScriptText(SAY_TELEPORT, me);
DoTeleportTo(PosGroundLiveSide);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
summons.DoAction(0, 0);
summons.DoZoneInCombat();
events.ScheduleEvent(EVENT_BOLT, 1000);
events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000));
events.ScheduleEvent(EVENT_TELEPORT, 20000);
}
break;
case EVENT_BOLT:
DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT));
events.ScheduleEvent(EVENT_BOLT, 1000);
break;
case EVENT_HARVEST:
DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true);
events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000));
break;
case EVENT_TELEPORT:
if (!thirtyPercentReached)
{
me->AttackStop();
if (IN_LIVE_SIDE(me))
{
DoTeleportTo(PosGroundDeadSide);
}
else
{
DoTeleportTo(PosGroundLiveSide);
}
me->getThreatManager().resetAggro(NotOnSameSide(me));
if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0))
{
me->getThreatManager().addThreat(pTarget, 100.0f);
AttackStart(pTarget);
}
events.ScheduleEvent(EVENT_TELEPORT, 20000);
}
break;
}
}
DoMeleeAttackIfReady();
}
};
};
␍class mob_gothik_minion : public CreatureScript
{
public:
mob_gothik_minion() : CreatureScript("mob_gothik_minion") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new mob_gothik_minionAI (pCreature);
}
struct mob_gothik_minionAI : public CombatAI
{
mob_gothik_minionAI(Creature *c) : CombatAI(c)
{
liveSide = IN_LIVE_SIDE(me);
}
bool liveSide;
bool gateClose;
bool isOnSameSide(const Unit *pWho)
{
return (liveSide == IN_LIVE_SIDE(pWho));
}
void DoAction(const int32 param)
{
gateClose = param;
}
void DamageTaken(Unit *attacker, uint32 &damage)
{
if (gateClose && !isOnSameSide(attacker))
damage = 0;
}
void JustDied(Unit * /*killer*/)
{
if (me->isSummon())
{
if (Unit *owner = CAST_SUM(me)->GetSummoner())
CombatAI::JustDied(owner);
}
}
void EnterEvadeMode()
{
if (!gateClose)
{
CombatAI::EnterEvadeMode();
return;
}
if (!_EnterEvadeMode())
return;
Map* pMap = me->GetMap();
if (pMap->IsDungeon())
{
Map::PlayerList const &PlayerList = pMap->GetPlayers();
if (!PlayerList.isEmpty())
{
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->getSource() && i->getSource()->isAlive() && isOnSameSide(i->getSource()))
{
AttackStart(i->getSource());
return;
}
}
}
}
me->GetMotionMaster()->MoveIdle();
Reset();
}
void UpdateAI(const uint32 diff)
{
if (gateClose && (!isOnSameSide(me) || me->getVictim() && !isOnSameSide(me->getVictim())))
{
EnterEvadeMode();
return;
}
CombatAI::UpdateAI(diff);
}
};
};
CreatureAI* GetAI_boss_gothik(Creature* pCreature)
{
return new boss_gothikAI (pCreature);
}
CreatureAI* GetAI_mob_gothik_minion(Creature* pCreature)
{
return new mob_gothik_minionAI (pCreature);
}
void AddSC_boss_gothik()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_gothik";
newscript->GetAI = &GetAI_boss_gothik;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_gothik_minion";
newscript->GetAI = &GetAI_mob_gothik_minion;
newscript->RegisterSelf();
new boss_gothik();
new mob_gothik_minion();
}
@@ -32,112 +32,118 @@
#define EVENT_SPRAY 4
#define MOB_FALLOUT_SLIME 16290
struct boss_grobbulusAI : public BossAI
␍class boss_grobbulus : public CreatureScript
{
boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS)
public:
boss_grobbulus() : CreatureScript("boss_grobbulus") { }
CreatureAI* GetAI(Creature* pCreature) const
{
me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true);
return new boss_grobbulusAI (pCreature);
}
void EnterCombat(Unit * /*who*/)
struct boss_grobbulusAI : public BossAI
{
_EnterCombat();
events.ScheduleEvent(EVENT_CLOUD, 15000);
events.ScheduleEvent(EVENT_INJECT, 20000);
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure
events.ScheduleEvent(EVENT_BERSERK, 12*60000);
}
void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
{
if (spell->Id == uint32(SPELL_SLIME_SPRAY))
boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS)
{
if (TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0))
DoZoneInCombat(slime);
me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true);
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void EnterCombat(Unit * /*who*/)
{
switch(eventId)
_EnterCombat();
events.ScheduleEvent(EVENT_CLOUD, 15000);
events.ScheduleEvent(EVENT_INJECT, 20000);
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure
events.ScheduleEvent(EVENT_BERSERK, 12*60000);
}
void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
{
if (spell->Id == uint32(SPELL_SLIME_SPRAY))
{
case EVENT_CLOUD:
DoCastAOE(SPELL_POISON_CLOUD);
events.ScheduleEvent(EVENT_CLOUD, 15000);
return;
case EVENT_BERSERK:
DoCastAOE(SPELL_BERSERK);
return;
case EVENT_SPRAY:
DoCastAOE(SPELL_SLIME_SPRAY);
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000);
return;
case EVENT_INJECT:
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1))
if (!pTarget->HasAura(SPELL_MUTATING_INJECTION))
DoCast(pTarget, SPELL_MUTATING_INJECTION);
events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * ((float)me->GetHealth() / me->GetMaxHealth()));
return;
if (TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0))
DoZoneInCombat(slime);
}
}
DoMeleeAttackIfReady();
}
};
struct npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI
{
npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature)
{
Reset();
}
uint32 Cloud_Timer;
void Reset()
{
Cloud_Timer = 1000;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void UpdateAI(const uint32 diff)
{
if (Cloud_Timer <= diff)
void UpdateAI(const uint32 diff)
{
DoCast(me, SPELL_POISON_CLOUD_ADD);
Cloud_Timer = 10000;
} else Cloud_Timer -= diff;
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_CLOUD:
DoCastAOE(SPELL_POISON_CLOUD);
events.ScheduleEvent(EVENT_CLOUD, 15000);
return;
case EVENT_BERSERK:
DoCastAOE(SPELL_BERSERK);
return;
case EVENT_SPRAY:
DoCastAOE(SPELL_SLIME_SPRAY);
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000);
return;
case EVENT_INJECT:
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1))
if (!pTarget->HasAura(SPELL_MUTATING_INJECTION))
DoCast(pTarget, SPELL_MUTATING_INJECTION);
events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * ((float)me->GetHealth() / me->GetMaxHealth()));
return;
}
}
DoMeleeAttackIfReady();
}
};
};
␍class npc_grobbulus_poison_cloud : public CreatureScript
{
public:
npc_grobbulus_poison_cloud() : CreatureScript("npc_grobbulus_poison_cloud") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new npc_grobbulus_poison_cloudAI(pCreature);
}
struct npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI
{
npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature)
{
Reset();
}
uint32 Cloud_Timer;
void Reset()
{
Cloud_Timer = 1000;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void UpdateAI(const uint32 diff)
{
if (Cloud_Timer <= diff)
{
DoCast(me, SPELL_POISON_CLOUD_ADD);
Cloud_Timer = 10000;
} else Cloud_Timer -= diff;
}
};
};
CreatureAI* GetAI_boss_grobbulus(Creature* pCreature)
{
return new boss_grobbulusAI (pCreature);
}
CreatureAI* GetAI_npc_grobbulus_poison_cloud(Creature* pCreature)
{
return new npc_grobbulus_poison_cloudAI(pCreature);
}
void AddSC_boss_grobbulus()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_grobbulus";
newscript->GetAI = &GetAI_boss_grobbulus;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "npc_grobbulus_poison_cloud";
newscript->GetAI = &GetAI_npc_grobbulus_poison_cloud;
newscript->RegisterSelf();
new boss_grobbulus();
new npc_grobbulus_poison_cloud();
}
@@ -41,110 +41,113 @@ enum Phases
PHASE_FIGHT = 1,
PHASE_DANCE,
};
struct boss_heiganAI : public BossAI
␍class boss_heigan : public CreatureScript
{
boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {}
public:
boss_heigan() : CreatureScript("boss_heigan") { }
uint32 eruptSection;
bool eruptDirection;
Phases phase;
void KilledUnit(Unit* /*Victim*/)
CreatureAI* GetAI(Creature* pCreature) const
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
return new boss_heiganAI (pCreature);
}
void JustDied(Unit* /*Killer*/)
struct boss_heiganAI : public BossAI
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoScriptText(SAY_AGGRO, me);
EnterPhase(PHASE_FIGHT);
}
uint32 eruptSection;
bool eruptDirection;
Phases phase;
void EnterPhase(Phases newPhase)
{
phase = newPhase;
events.Reset();
eruptSection = 3;
if (phase == PHASE_FIGHT)
void KilledUnit(Unit* /*Victim*/)
{
events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000));
events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000));
events.ScheduleEvent(EVENT_PHASE, 90000);
events.ScheduleEvent(EVENT_ERUPT, 15000);
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
else
void JustDied(Unit* /*Killer*/)
{
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->NearTeleportTo(x, y, z, o);
DoCastAOE(SPELL_PLAGUE_CLOUD);
events.ScheduleEvent(EVENT_PHASE, 45000);
events.ScheduleEvent(EVENT_ERUPT, 8000);
_JustDied();
DoScriptText(SAY_DEATH, me);
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void EnterCombat(Unit * /*who*/)
{
switch(eventId)
_EnterCombat();
DoScriptText(SAY_AGGRO, me);
EnterPhase(PHASE_FIGHT);
}
void EnterPhase(Phases newPhase)
{
phase = newPhase;
events.Reset();
eruptSection = 3;
if (phase == PHASE_FIGHT)
{
case EVENT_DISRUPT:
DoCastAOE(SPELL_SPELL_DISRUPTION);
events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000));
break;
case EVENT_FEVER:
DoCastAOE(SPELL_DECREPIT_FEVER);
events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000));
break;
case EVENT_PHASE:
// TODO : Add missing texts for both phase switches
EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT);
break;
case EVENT_ERUPT:
instance->SetData(DATA_HEIGAN_ERUPT, eruptSection);
TeleportCheaters();
if (eruptSection == 0)
eruptDirection = true;
else if (eruptSection == 3)
eruptDirection = false;
eruptDirection ? ++eruptSection : --eruptSection;
events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000);
break;
events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000));
events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000));
events.ScheduleEvent(EVENT_PHASE, 90000);
events.ScheduleEvent(EVENT_ERUPT, 15000);
}
else
{
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->NearTeleportTo(x, y, z, o);
DoCastAOE(SPELL_PLAGUE_CLOUD);
events.ScheduleEvent(EVENT_PHASE, 45000);
events.ScheduleEvent(EVENT_ERUPT, 8000);
}
}
DoMeleeAttackIfReady();
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_DISRUPT:
DoCastAOE(SPELL_SPELL_DISRUPTION);
events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000));
break;
case EVENT_FEVER:
DoCastAOE(SPELL_DECREPIT_FEVER);
events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000));
break;
case EVENT_PHASE:
// TODO : Add missing texts for both phase switches
EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT);
break;
case EVENT_ERUPT:
instance->SetData(DATA_HEIGAN_ERUPT, eruptSection);
TeleportCheaters();
if (eruptSection == 0)
eruptDirection = true;
else if (eruptSection == 3)
eruptDirection = false;
eruptDirection ? ++eruptSection : --eruptSection;
events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000);
break;
}
}
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_heigan(Creature* pCreature)
{
return new boss_heiganAI (pCreature);
}
void AddSC_boss_heigan()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_heigan";
newscript->GetAI = &GetAI_boss_heigan;
newscript->RegisterSelf();
new boss_heigan();
}
@@ -251,458 +251,462 @@ struct NotCharmedTargetSelector : public std::unary_function<Unit *, bool> {
return (!pTarget->isCharmed());
}
};
struct boss_kelthuzadAI : public BossAI
␍class boss_kelthuzad : public CreatureScript
{
boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), spawns(c)
public:
boss_kelthuzad() : CreatureScript("boss_kelthuzad") { }
struct boss_kelthuzadAI : public BossAI
{
uiFaction = me->getFaction();
}
uint32 Phase;
uint32 uiGuardiansOfIcecrownTimer;
uint32 uiFaction;
uint8 nGuardiansOfIcecrownCount;
uint8 nAbomination;
uint8 nWeaver;
std::map<uint64, float> chained;
uint64 PortalsGUID[4];
uint64 KTTriggerGUID;
SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons)
void Reset()
{
_Reset();
PortalsGUID[0] = PortalsGUID[1] = PortalsGUID[2] = PortalsGUID[3] = 0;
KTTriggerGUID = 0;
me->setFaction(35);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
std::map<uint64, float>::const_iterator itr;
for (itr = chained.begin(); itr != chained.end(); ++itr)
boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), spawns(c)
{
if (Player* charmed = Unit::GetPlayer(*me, (*itr).first))
charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
uiFaction = me->getFaction();
}
chained.clear();
spawns.DespawnAll();
uint32 Phase;
uint32 uiGuardiansOfIcecrownTimer;
uint32 uiFaction;
FindGameObjects();
uint8 nGuardiansOfIcecrownCount;
uint8 nAbomination;
uint8 nWeaver;
if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID))
std::map<uint64, float> chained;
uint64 PortalsGUID[4];
uint64 KTTriggerGUID;
SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons)
void Reset()
{
pKTTrigger->ResetDoorOrButton();
pKTTrigger->SetPhaseMask(1, true);
}
_Reset();
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
PortalsGUID[0] = PortalsGUID[1] = PortalsGUID[2] = PortalsGUID[3] = 0;
KTTriggerGUID = 0;
me->setFaction(35);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
std::map<uint64, float>::const_iterator itr;
for (itr = chained.begin(); itr != chained.end(); ++itr)
{
if (!((pPortal->getLootState() == GO_READY) || (pPortal->getLootState() == GO_NOT_READY)))
if (Player* charmed = Unit::GetPlayer(*me, (*itr).first))
charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
}
chained.clear();
spawns.DespawnAll();
FindGameObjects();
if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID))
{
pKTTrigger->ResetDoorOrButton();
pKTTrigger->SetPhaseMask(1, true);
}
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
{
if (!((pPortal->getLootState() == GO_READY) || (pPortal->getLootState() == GO_NOT_READY)))
pPortal->ResetDoorOrButton();
}
}
nGuardiansOfIcecrownCount = 0;
uiGuardiansOfIcecrownTimer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3
Phase = 0;
nAbomination = 0;
nWeaver = 0;
}
void KilledUnit()
{
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
std::map<uint64, float>::const_iterator itr;
for (itr = chained.begin(); itr != chained.end(); ++itr)
{
if (Player* pPlayer = Unit::GetPlayer(*me, (*itr).first))
pPlayer->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
}
chained.clear();
}
void EnterCombat(Unit* /*who*/)
{
me->setFaction(uiFaction);
_EnterCombat();
FindGameObjects();
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
pPortal->ResetDoorOrButton();
}
DoCast(me, SPELL_KELTHUZAD_CHANNEL, false);
DoScriptText(SAY_SUMMON_MINIONS, me);
Phase = 1;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4);
me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4);
events.ScheduleEvent(EVENT_TRIGGER, 5000);
events.ScheduleEvent(EVENT_WASTE, 15000);
events.ScheduleEvent(EVENT_ABOMIN, 30000);
events.ScheduleEvent(EVENT_WEAVER, 50000);
events.ScheduleEvent(EVENT_PHASE, 228000);
}
nGuardiansOfIcecrownCount = 0;
uiGuardiansOfIcecrownTimer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3
Phase = 0;
nAbomination = 0;
nWeaver = 0;
}
void KilledUnit()
{
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
std::map<uint64, float>::const_iterator itr;
for (itr = chained.begin(); itr != chained.end(); ++itr)
void FindGameObjects()
{
if (Player* pPlayer = Unit::GetPlayer(*me, (*itr).first))
pPlayer->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0;
PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0;
PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0;
PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0;
KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0;
}
chained.clear();
}
void EnterCombat(Unit* /*who*/)
{
me->setFaction(uiFaction);
_EnterCombat();
FindGameObjects();
for (uint8 i = 0; i <= 3; ++i)
void UpdateAI(const uint32 diff)
{
if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
pPortal->ResetDoorOrButton();
}
DoCast(me, SPELL_KELTHUZAD_CHANNEL, false);
DoScriptText(SAY_SUMMON_MINIONS, me);
Phase = 1;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4);
me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4);
events.ScheduleEvent(EVENT_TRIGGER, 5000);
events.ScheduleEvent(EVENT_WASTE, 15000);
events.ScheduleEvent(EVENT_ABOMIN, 30000);
events.ScheduleEvent(EVENT_WEAVER, 50000);
events.ScheduleEvent(EVENT_PHASE, 228000);
}
void FindGameObjects()
{
PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0;
PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0;
PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0;
PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0;
KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0;
}
void UpdateAI(const uint32 diff)
{
if (!UpdateCombatState())
return;
events.Update(diff);
if (Phase == 1)
{
while (uint32 eventId = events.GetEvent())
{
switch(eventId)
{
case EVENT_WASTE:
DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]);
events.RepeatEvent(urand(2000,5000));
break;
case EVENT_ABOMIN:
if (nAbomination < 8)
{
DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]);
nAbomination++;
events.RepeatEvent(20000);
}
else
events.PopEvent();
break;
case EVENT_WEAVER:
if (nWeaver < 8)
{
DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]);
nWeaver++;
events.RepeatEvent(25000);
}
else
events.PopEvent();
break;
case EVENT_TRIGGER:
if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID))
pKTTrigger->SetPhaseMask(2, true);
events.PopEvent();
break;
case EVENT_PHASE:
events.Reset();
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me);
spawns.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->CastStop();
DoStartMovement(me->getVictim());
events.ScheduleEvent(EVENT_BOLT, urand(5000,10000));
events.ScheduleEvent(EVENT_NOVA, 15000);
events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000));
events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000));
events.ScheduleEvent(EVENT_BLAST, urand(60000,120000));
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000));
Phase = 2;
break;
default:
events.PopEvent();
break;
}
}
}
else
{
//start phase 3 when we are 45% health
if (Phase != 3)
{
if (HealthBelowPct(45))
{
Phase = 3 ;
DoScriptText(SAY_REQUEST_AID, me);
//here Lich King should respond to KelThuzad but I don't know which Creature to make talk
//so for now just make Kelthuzad says it.
DoScriptText(SAY_ANSWER_REQUEST, me);
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
{
if (pPortal->getLootState() == GO_READY)
pPortal->UseDoorOrButton();
}
}
}
}
else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4))
{
if (uiGuardiansOfIcecrownTimer <= diff)
{
// TODO : Add missing text
if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)]))
pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
++nGuardiansOfIcecrownCount;
uiGuardiansOfIcecrownTimer = 5000;
}
else uiGuardiansOfIcecrownTimer -= diff;
}
if (me->hasUnitState(UNIT_STAT_CASTING))
if (!UpdateCombatState())
return;
if (uint32 eventId = events.GetEvent())
events.Update(diff);
if (Phase == 1)
{
switch(eventId)
while (uint32 eventId = events.GetEvent())
{
case EVENT_BOLT:
DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT));
events.RepeatEvent(urand(5000,10000));
break;
case EVENT_NOVA:
DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE));
events.RepeatEvent(urand(15000,30000));
break;
case EVENT_CHAIN:
switch(eventId)
{
uint32 count = urand(1,3);
for (uint8 i = 1; i <= count; i++)
{
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true);
if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end()))
case EVENT_WASTE:
DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]);
events.RepeatEvent(urand(2000,5000));
break;
case EVENT_ABOMIN:
if (nAbomination < 8)
{
DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD);
float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X);
chained.insert(std::make_pair(pTarget->GetGUID(), scale));
pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2);
events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm
DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]);
nAbomination++;
events.RepeatEvent(20000);
}
}
if (!chained.empty())
DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me);
events.RepeatEvent(urand(100000,180000));
break;
}
case EVENT_CHAINED_SPELL:
{
std::map<uint64, float>::iterator itr;
for (itr = chained.begin(); itr != chained.end();)
{
if (Unit* player = Unit::GetPlayer(*me, (*itr).first))
else
events.PopEvent();
break;
case EVENT_WEAVER:
if (nWeaver < 8)
{
if (!player->isCharmed())
{
player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
std::map<uint64, float>::iterator next = itr;
++next;
chained.erase(itr);
itr = next;
continue;
}
if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector()))
{
switch(player->getClass())
{
case CLASS_DRUID:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_MOONFIRE, false);
else
player->CastSpell(me, SPELL_LIFEBLOOM, false);
break;
case CLASS_HUNTER:
player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false);
break;
case CLASS_MAGE:
player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false);
break;
case CLASS_WARLOCK:
player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true);
break;
case CLASS_WARRIOR:
player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false);
break;
case CLASS_PALADIN:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false);
else
player->CastSpell(me, SPELL_HOLY_SHOCK, false);
break;
case CLASS_PRIEST:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false);
else
player->CastSpell(me, SPELL_RENEW, false);
break;
case CLASS_SHAMAN:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false);
else
player->CastSpell(me, SPELL_HEALING_WAVE, false);
break;
case CLASS_ROGUE:
player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false);
break;
case CLASS_DEATH_KNIGHT:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true);
else
player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true);
break;
}
}
DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]);
nWeaver++;
events.RepeatEvent(25000);
}
++itr;
}
if (chained.empty())
else
events.PopEvent();
break;
case EVENT_TRIGGER:
if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID))
pKTTrigger->SetPhaseMask(2, true);
events.PopEvent();
else
events.RepeatEvent(5000);
break;
case EVENT_PHASE:
events.Reset();
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me);
spawns.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->CastStop();
break;
DoStartMovement(me->getVictim());
events.ScheduleEvent(EVENT_BOLT, urand(5000,10000));
events.ScheduleEvent(EVENT_NOVA, 15000);
events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000));
events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000));
events.ScheduleEvent(EVENT_BLAST, urand(60000,120000));
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000));
Phase = 2;
break;
default:
events.PopEvent();
break;
}
case EVENT_DETONATE:
{
std::vector<Unit*> unitList;
std::list<HostileReference*> *threatList = &me->getThreatManager().getThreatList();
for (std::list<HostileReference*>::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr)
{
if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER
&& (*itr)->getTarget()->getPowerType() == POWER_MANA
&& (*itr)->getTarget()->GetPower(POWER_MANA))
unitList.push_back((*itr)->getTarget());
}
if (!unitList.empty())
{
std::vector<Unit*>::const_iterator itr = unitList.begin();
advance(itr, rand()%unitList.size());
DoCast(*itr, SPELL_MANA_DETONATION);
DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me);
}
events.RepeatEvent(urand(20000,50000));
break;
}
case EVENT_FISSURE:
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0))
DoCast(pTarget, SPELL_SHADOW_FISURE);
events.RepeatEvent(urand(10000,45000));
break;
case EVENT_BLAST:
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true))
DoCast(pTarget, SPELL_FROST_BLAST);
if (rand()%2)
DoScriptText(SAY_FROST_BLAST, me);
events.RepeatEvent(urand(30000,90000));
break;
default:
events.PopEvent();
break;
}
}
else
{
//start phase 3 when we are 45% health
if (Phase != 3)
{
if (HealthBelowPct(45))
{
Phase = 3 ;
DoScriptText(SAY_REQUEST_AID, me);
//here Lich King should respond to KelThuzad but I don't know which Creature to make talk
//so for now just make Kelthuzad says it.
DoScriptText(SAY_ANSWER_REQUEST, me);
DoMeleeAttackIfReady();
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
{
if (pPortal->getLootState() == GO_READY)
pPortal->UseDoorOrButton();
}
}
}
}
else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4))
{
if (uiGuardiansOfIcecrownTimer <= diff)
{
// TODO : Add missing text
if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)]))
pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
++nGuardiansOfIcecrownCount;
uiGuardiansOfIcecrownTimer = 5000;
}
else uiGuardiansOfIcecrownTimer -= diff;
}
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
if (uint32 eventId = events.GetEvent())
{
switch(eventId)
{
case EVENT_BOLT:
DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT));
events.RepeatEvent(urand(5000,10000));
break;
case EVENT_NOVA:
DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE));
events.RepeatEvent(urand(15000,30000));
break;
case EVENT_CHAIN:
{
uint32 count = urand(1,3);
for (uint8 i = 1; i <= count; i++)
{
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true);
if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end()))
{
DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD);
float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X);
chained.insert(std::make_pair(pTarget->GetGUID(), scale));
pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2);
events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm
}
}
if (!chained.empty())
DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me);
events.RepeatEvent(urand(100000,180000));
break;
}
case EVENT_CHAINED_SPELL:
{
std::map<uint64, float>::iterator itr;
for (itr = chained.begin(); itr != chained.end();)
{
if (Unit* player = Unit::GetPlayer(*me, (*itr).first))
{
if (!player->isCharmed())
{
player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
std::map<uint64, float>::iterator next = itr;
++next;
chained.erase(itr);
itr = next;
continue;
}
if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector()))
{
switch(player->getClass())
{
case CLASS_DRUID:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_MOONFIRE, false);
else
player->CastSpell(me, SPELL_LIFEBLOOM, false);
break;
case CLASS_HUNTER:
player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false);
break;
case CLASS_MAGE:
player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false);
break;
case CLASS_WARLOCK:
player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true);
break;
case CLASS_WARRIOR:
player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false);
break;
case CLASS_PALADIN:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false);
else
player->CastSpell(me, SPELL_HOLY_SHOCK, false);
break;
case CLASS_PRIEST:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false);
else
player->CastSpell(me, SPELL_RENEW, false);
break;
case CLASS_SHAMAN:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false);
else
player->CastSpell(me, SPELL_HEALING_WAVE, false);
break;
case CLASS_ROGUE:
player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false);
break;
case CLASS_DEATH_KNIGHT:
if (urand(0,1))
player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true);
else
player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true);
break;
}
}
}
++itr;
}
if (chained.empty())
events.PopEvent();
else
events.RepeatEvent(5000);
break;
}
case EVENT_DETONATE:
{
std::vector<Unit*> unitList;
std::list<HostileReference*> *threatList = &me->getThreatManager().getThreatList();
for (std::list<HostileReference*>::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr)
{
if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER
&& (*itr)->getTarget()->getPowerType() == POWER_MANA
&& (*itr)->getTarget()->GetPower(POWER_MANA))
unitList.push_back((*itr)->getTarget());
}
if (!unitList.empty())
{
std::vector<Unit*>::const_iterator itr = unitList.begin();
advance(itr, rand()%unitList.size());
DoCast(*itr, SPELL_MANA_DETONATION);
DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me);
}
events.RepeatEvent(urand(20000,50000));
break;
}
case EVENT_FISSURE:
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0))
DoCast(pTarget, SPELL_SHADOW_FISURE);
events.RepeatEvent(urand(10000,45000));
break;
case EVENT_BLAST:
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true))
DoCast(pTarget, SPELL_FROST_BLAST);
if (rand()%2)
DoScriptText(SAY_FROST_BLAST, me);
events.RepeatEvent(urand(30000,90000));
break;
default:
events.PopEvent();
break;
}
}
DoMeleeAttackIfReady();
}
}
}
};
};
CreatureAI* GetAI_boss_kelthuzadAI(Creature* pCreature)
{
return new boss_kelthuzadAI (pCreature);
}
bool AreaTrigger_at_kelthuzad_center(Player* pPlayer, const AreaTriggerEntry * /*at*/)
{
if (pPlayer->isGameMaster())
return false;
ScriptedInstance* pInstance = pPlayer->GetInstanceData();
if (!pInstance || pInstance->IsEncounterInProgress() || pInstance->GetBossState(BOSS_KELTHUZAD) == DONE)
return false;
Creature* pKelthuzad = CAST_CRE(Unit::GetUnit(*pPlayer, pInstance->GetData64(DATA_KELTHUZAD)));
if (!pKelthuzad)
return false;
boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzadAI, pKelthuzad->AI());
if (!pKelthuzadAI)
return false;
pKelthuzadAI->AttackStart(pPlayer);
if (GameObject* trigger = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_TRIGGER)))
CreatureAI* GetAI(Creature* pCreature) const
{
if (trigger->getLootState() == GO_READY)
trigger->UseDoorOrButton();
// Note: summon must be done by trigger and not by KT.
// Otherwise, they attack immediately as KT is in combat.
for (uint8 i = 0; i <= MAX_ABOMINATIONS; ++i)
{
if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i]))
{
pKelthuzadAI->spawns.Summon(sum);
sum->GetMotionMaster()->MoveRandom(9.0f);
sum->SetReactState(REACT_DEFENSIVE);
}
}
for (uint8 i = 0; i <= MAX_WASTES; ++i)
{
if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i]))
{
pKelthuzadAI->spawns.Summon(sum);
sum->GetMotionMaster()->MoveRandom(5.0f);
sum->SetReactState(REACT_DEFENSIVE);
}
}
for (uint8 i = 0; i <= MAX_WEAVERS; ++i)
{
if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i]))
{
pKelthuzadAI->spawns.Summon(sum);
sum->GetMotionMaster()->MoveRandom(9.0f);
sum->SetReactState(REACT_DEFENSIVE);
}
}
return new boss_kelthuzadAI (pCreature);
}
return true;
}
};
␍class at_kelthuzad_center : public AreaTriggerScript
{
public:
at_kelthuzad_center() : AreaTriggerScript("at_kelthuzad_center") { }
bool OnTrigger(Player* pPlayer, const AreaTriggerEntry * /*at*/)
{
if (pPlayer->isGameMaster())
return false;
InstanceScript* pInstance = pPlayer->GetInstanceScript();
if (!pInstance || pInstance->IsEncounterInProgress() || pInstance->GetBossState(BOSS_KELTHUZAD) == DONE)
return false;
Creature* pKelthuzad = CAST_CRE(Unit::GetUnit(*pPlayer, pInstance->GetData64(DATA_KELTHUZAD)));
if (!pKelthuzad)
return false;
boss_kelthuzad::boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzad::boss_kelthuzadAI, pKelthuzad->AI());
if (!pKelthuzadAI)
return false;
pKelthuzadAI->AttackStart(pPlayer);
if (GameObject* trigger = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_TRIGGER)))
{
if (trigger->getLootState() == GO_READY)
trigger->UseDoorOrButton();
// Note: summon must be done by trigger and not by KT.
// Otherwise, they attack immediately as KT is in combat.
for (uint8 i = 0; i <= MAX_ABOMINATIONS; ++i)
{
if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i]))
{
pKelthuzadAI->spawns.Summon(sum);
sum->GetMotionMaster()->MoveRandom(9.0f);
sum->SetReactState(REACT_DEFENSIVE);
}
}
for (uint8 i = 0; i <= MAX_WASTES; ++i)
{
if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i]))
{
pKelthuzadAI->spawns.Summon(sum);
sum->GetMotionMaster()->MoveRandom(5.0f);
sum->SetReactState(REACT_DEFENSIVE);
}
}
for (uint8 i = 0; i <= MAX_WEAVERS; ++i)
{
if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i]))
{
pKelthuzadAI->spawns.Summon(sum);
sum->GetMotionMaster()->MoveRandom(9.0f);
sum->SetReactState(REACT_DEFENSIVE);
}
}
}
return true;
}
};
void AddSC_boss_kelthuzad()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_kelthuzad";
newscript->GetAI = &GetAI_boss_kelthuzadAI;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "at_kelthuzad_center";
newscript->pAreaTrigger = &AreaTrigger_at_kelthuzad_center;
newscript->RegisterSelf();
new boss_kelthuzad();
new at_kelthuzad_center();
}
@@ -35,90 +35,92 @@ enum Events
EVENT_BLOOM,
EVENT_DOOM,
};
struct boss_loathebAI : public BossAI
␍class boss_loatheb : public CreatureScript
{
boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) {}
public:
boss_loatheb() : CreatureScript("boss_loatheb") { }
void EnterCombat(Unit * /*who*/)
CreatureAI* GetAI(Creature* pCreature) const
{
_EnterCombat();
events.ScheduleEvent(EVENT_AURA, 10000);
events.ScheduleEvent(EVENT_BLOOM, 5000);
events.ScheduleEvent(EVENT_DOOM, 120000);
return new boss_loathebAI (pCreature);
}
void UpdateAI(const uint32 diff)
struct boss_loathebAI : public BossAI
{
if (!UpdateVictim())
return;
boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) {}
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void EnterCombat(Unit * /*who*/)
{
switch(eventId)
{
case EVENT_AURA:
DoCastAOE(SPELL_NECROTIC_AURA);
events.ScheduleEvent(EVENT_AURA, 20000);
break;
case EVENT_BLOOM:
// TODO : Add missing text
DoCastAOE(SPELL_SUMMON_SPORE, true);
DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM,H_SPELL_DEATHBLOOM));
events.ScheduleEvent(EVENT_BLOOM, 30000);
break;
case EVENT_DOOM:
DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM,H_SPELL_INEVITABLE_DOOM));
events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000);
break;
}
_EnterCombat();
events.ScheduleEvent(EVENT_AURA, 10000);
events.ScheduleEvent(EVENT_BLOOM, 5000);
events.ScheduleEvent(EVENT_DOOM, 120000);
}
DoMeleeAttackIfReady();
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_AURA:
DoCastAOE(SPELL_NECROTIC_AURA);
events.ScheduleEvent(EVENT_AURA, 20000);
break;
case EVENT_BLOOM:
// TODO : Add missing text
DoCastAOE(SPELL_SUMMON_SPORE, true);
DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM,H_SPELL_DEATHBLOOM));
events.ScheduleEvent(EVENT_BLOOM, 30000);
break;
case EVENT_DOOM:
DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM,H_SPELL_INEVITABLE_DOOM));
events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000);
break;
}
}
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_loatheb(Creature* pCreature)
{
return new boss_loathebAI (pCreature);
}
enum SporeSpells
{
SPELL_FUNGAL_CREEP = 29232
};
struct mob_loatheb_sporeAI : public ScriptedAI
␍class mob_loatheb_spore : public CreatureScript
{
mob_loatheb_sporeAI(Creature *c) : ScriptedAI(c) {}
public:
mob_loatheb_spore() : CreatureScript("mob_loatheb_spore") { }
void JustDied(Unit* killer)
CreatureAI* GetAI(Creature* pCreature) const
{
DoCast(killer, SPELL_FUNGAL_CREEP);
return new mob_loatheb_sporeAI (pCreature);
}
struct mob_loatheb_sporeAI : public ScriptedAI
{
mob_loatheb_sporeAI(Creature *c) : ScriptedAI(c) {}
void JustDied(Unit* killer)
{
DoCast(killer, SPELL_FUNGAL_CREEP);
}
};
};
CreatureAI* GetAI_mob_loatheb_spore(Creature* pCreature)
{
return new mob_loatheb_sporeAI (pCreature);
}
void AddSC_boss_loatheb()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_loatheb";
newscript->GetAI = &GetAI_boss_loatheb;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_loatheb_spore";
newscript->GetAI = &GetAI_mob_loatheb_spore;
newscript->RegisterSelf();
// Fungal Creep
//GetAISpellInfo(29232)->condition = AICOND_DIE;
new boss_loatheb();
new mob_loatheb_spore();
}
@@ -55,131 +55,134 @@ enum Events
EVENT_SUMMON,
EVENT_FRENZY,
};
struct boss_maexxnaAI : public BossAI
␍class boss_maexxna : public CreatureScript
{
boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA) {}
public:
boss_maexxna() : CreatureScript("boss_maexxna") { }
bool enraged;
void EnterCombat(Unit * /*who*/)
CreatureAI* GetAI(Creature* pCreature) const
{
_EnterCombat();
enraged = false;
events.ScheduleEvent(EVENT_WRAP, 20000);
events.ScheduleEvent(EVENT_SPRAY, 40000);
events.ScheduleEvent(EVENT_SHOCK, urand(5000,10000));
events.ScheduleEvent(EVENT_POISON, urand(10000,15000));
events.ScheduleEvent(EVENT_SUMMON, 30000);
return new boss_maexxnaAI (pCreature);
}
void UpdateAI(const uint32 diff)
struct boss_maexxnaAI : public BossAI
{
if (!UpdateVictim() || !CheckInRoom())
return;
boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA) {}
if (!enraged && HealthBelowPct(30))
bool enraged;
void EnterCombat(Unit * /*who*/)
{
enraged = true;
events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately
_EnterCombat();
enraged = false;
events.ScheduleEvent(EVENT_WRAP, 20000);
events.ScheduleEvent(EVENT_SPRAY, 40000);
events.ScheduleEvent(EVENT_SHOCK, urand(5000,10000));
events.ScheduleEvent(EVENT_POISON, urand(10000,15000));
events.ScheduleEvent(EVENT_SUMMON, 30000);
}
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void UpdateAI(const uint32 diff)
{
switch(eventId)
if (!UpdateVictim() || !CheckInRoom())
return;
if (!enraged && HealthBelowPct(30))
{
case EVENT_WRAP:
// TODO : Add missing text
for (uint8 i = 0; i < RAID_MODE(1,2); ++i)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP))
{
pTarget->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25));
uint8 pos = rand()%MAX_POS_WRAP;
pTarget->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20);
if (Creature *wrap = DoSummon(MOB_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN))
wrap->AI()->SetGUID(pTarget->GetGUID());
}
}
events.ScheduleEvent(EVENT_WRAP, 40000);
break;
case EVENT_SPRAY:
DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25));
events.ScheduleEvent(EVENT_SPRAY, 40000);
break;
case EVENT_SHOCK:
DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10,SPELL_POISON_SHOCK_25));
events.ScheduleEvent(EVENT_SHOCK, urand(10000,20000));
break;
case EVENT_POISON:
DoCast(me->getVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10,SPELL_NECROTIC_POISON_25));
events.ScheduleEvent(EVENT_POISON, urand(10000, 20000));
break;
case EVENT_FRENZY:
DoCast(me, RAID_MODE(SPELL_FRENZY_10,SPELL_FRENZY_25), true);
events.ScheduleEvent(EVENT_FRENZY, 600000);
break;
case EVENT_SUMMON:
// TODO : Add missing text
uint8 amount = urand(8,10);
for (uint8 i = 0; i < amount; ++i)
DoSummon(MOB_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN);
events.ScheduleEvent(EVENT_SUMMON, 40000);
break;
enraged = true;
events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately
}
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_WRAP:
// TODO : Add missing text
for (uint8 i = 0; i < RAID_MODE(1,2); ++i)
{
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP))
{
pTarget->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25));
uint8 pos = rand()%MAX_POS_WRAP;
pTarget->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20);
if (Creature *wrap = DoSummon(MOB_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN))
wrap->AI()->SetGUID(pTarget->GetGUID());
}
}
events.ScheduleEvent(EVENT_WRAP, 40000);
break;
case EVENT_SPRAY:
DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25));
events.ScheduleEvent(EVENT_SPRAY, 40000);
break;
case EVENT_SHOCK:
DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10,SPELL_POISON_SHOCK_25));
events.ScheduleEvent(EVENT_SHOCK, urand(10000,20000));
break;
case EVENT_POISON:
DoCast(me->getVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10,SPELL_NECROTIC_POISON_25));
events.ScheduleEvent(EVENT_POISON, urand(10000, 20000));
break;
case EVENT_FRENZY:
DoCast(me, RAID_MODE(SPELL_FRENZY_10,SPELL_FRENZY_25), true);
events.ScheduleEvent(EVENT_FRENZY, 600000);
break;
case EVENT_SUMMON:
// TODO : Add missing text
uint8 amount = urand(8,10);
for (uint8 i = 0; i < amount; ++i)
DoSummon(MOB_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN);
events.ScheduleEvent(EVENT_SUMMON, 40000);
break;
}
}
DoMeleeAttackIfReady();
}
};
};
␍class mob_webwrap : public CreatureScript
{
public:
mob_webwrap() : CreatureScript("mob_webwrap") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new mob_webwrapAI (pCreature);
}
struct mob_webwrapAI : public NullCreatureAI
{
mob_webwrapAI(Creature *c) : NullCreatureAI(c), victimGUID(0) {}
uint64 victimGUID;
void SetGUID(const uint64 &guid, int32 /*param*/)
{
victimGUID = guid;
if (me->m_spells[0] && victimGUID)
if (Unit *victim = Unit::GetUnit(*me, victimGUID))
victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID());
}
DoMeleeAttackIfReady();
}
void JustDied(Unit * /*killer*/)
{
if (me->m_spells[0] && victimGUID)
if (Unit *victim = Unit::GetUnit(*me, victimGUID))
victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID());
}
};
};
struct mob_webwrapAI : public NullCreatureAI
{
mob_webwrapAI(Creature *c) : NullCreatureAI(c), victimGUID(0) {}
uint64 victimGUID;
void SetGUID(const uint64 &guid, int32 /*param*/)
{
victimGUID = guid;
if (me->m_spells[0] && victimGUID)
if (Unit *victim = Unit::GetUnit(*me, victimGUID))
victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID());
}
void JustDied(Unit * /*killer*/)
{
if (me->m_spells[0] && victimGUID)
if (Unit *victim = Unit::GetUnit(*me, victimGUID))
victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID());
}
};
CreatureAI* GetAI_boss_maexxna(Creature* pCreature)
{
return new boss_maexxnaAI (pCreature);
}
CreatureAI* GetAI_mob_webwrap(Creature* pCreature)
{
return new mob_webwrapAI (pCreature);
}
void AddSC_boss_maexxna()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_maexxna";
newscript->GetAI = &GetAI_boss_maexxna;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_webwrap";
newscript->GetAI = &GetAI_mob_webwrap;
newscript->RegisterSelf();
new boss_maexxna();
new mob_webwrap();
}
@@ -62,152 +62,155 @@ enum Events
EVENT_WAVE,
EVENT_GROUND,
};
struct boss_nothAI : public BossAI
␍class boss_noth : public CreatureScript
{
boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {}
public:
boss_noth() : CreatureScript("boss_noth") { }
uint32 waveCount, balconyCount;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
_Reset();
return new boss_nothAI (pCreature);
}
void EnterCombat(Unit * /*who*/)
struct boss_nothAI : public BossAI
{
_EnterCombat();
DoScriptText(SAY_AGGRO, me);
balconyCount = 0;
EnterPhaseGround();
}
boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {}
void EnterPhaseGround()
{
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
DoZoneInCombat();
if (me->getThreatManager().isThreatListEmpty())
EnterEvadeMode();
else
uint32 waveCount, balconyCount;
void Reset()
{
events.ScheduleEvent(EVENT_BALCONY, 110000);
events.ScheduleEvent(EVENT_CURSE, 10000+rand()%15000);
events.ScheduleEvent(EVENT_WARRIOR, 30000);
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
events.ScheduleEvent(EVENT_BLINK, 20000 + rand()%20000);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
_Reset();
}
}
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
void JustSummoned(Creature *summon)
{
summons.Summon(summon);
summon->setActive(true);
summon->AI()->DoZoneInCombat();
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
void SummonUndead(uint32 entry, uint32 num)
{
for (uint32 i = 0; i < num; ++i)
void EnterCombat(Unit * /*who*/)
{
uint32 pos = rand()%MAX_SUMMON_POS;
me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2],
SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000);
_EnterCombat();
DoScriptText(SAY_AGGRO, me);
balconyCount = 0;
EnterPhaseGround();
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateCombatState() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void EnterPhaseGround()
{
switch(eventId)
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
DoZoneInCombat();
if (me->getThreatManager().isThreatListEmpty())
EnterEvadeMode();
else
{
case EVENT_CURSE:
DoCastAOE(SPELL_CURSE_PLAGUEBRINGER);
events.ScheduleEvent(EVENT_CURSE, 50000 + rand()%10000);
return;
case EVENT_WARRIOR:
DoScriptText(SAY_SUMMON, me);
SummonUndead(MOB_WARRIOR, RAID_MODE(2,3));
events.ScheduleEvent(EVENT_WARRIOR, 30000);
return;
case EVENT_BLINK:
DoCastAOE(SPELL_CRIPPLE, true);
DoCastAOE(SPELL_BLINK);
DoResetThreat();
events.ScheduleEvent(EVENT_BLINK, 40000);
return;
case EVENT_BALCONY:
me->SetReactState(REACT_PASSIVE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->AttackStop();
me->RemoveAllAuras();
me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O);
events.Reset();
events.ScheduleEvent(EVENT_WAVE, 2000 + rand()%3000);
waveCount = 0;
return;
case EVENT_WAVE:
DoScriptText(SAY_SUMMON, me);
switch(balconyCount)
{
case 0: SummonUndead(MOB_CHAMPION, RAID_MODE(2,4)); break;
case 1: SummonUndead(MOB_CHAMPION, RAID_MODE(1,2));
SummonUndead(MOB_GUARDIAN, RAID_MODE(1,2)); break;
case 2: SummonUndead(MOB_GUARDIAN, RAID_MODE(2,4)); break;
default:SummonUndead(MOB_CHAMPION, RAID_MODE(5,10));
SummonUndead(MOB_GUARDIAN, RAID_MODE(5,10));break;
}
++waveCount;
events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 30000 + rand()%15000);
return;
case EVENT_GROUND:
{
++balconyCount;
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->NearTeleportTo(x, y, z, o);
events.ScheduleEvent(EVENT_BALCONY, 110000);
EnterPhaseGround();
return;
}
events.ScheduleEvent(EVENT_BALCONY, 110000);
events.ScheduleEvent(EVENT_CURSE, 10000+rand()%15000);
events.ScheduleEvent(EVENT_WARRIOR, 30000);
if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
events.ScheduleEvent(EVENT_BLINK, 20000 + rand()%20000);
}
}
if (me->HasReactState(REACT_AGGRESSIVE))
DoMeleeAttackIfReady();
}
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
void JustSummoned(Creature *summon)
{
summons.Summon(summon);
summon->setActive(true);
summon->AI()->DoZoneInCombat();
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
void SummonUndead(uint32 entry, uint32 num)
{
for (uint32 i = 0; i < num; ++i)
{
uint32 pos = rand()%MAX_SUMMON_POS;
me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2],
SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000);
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateCombatState() || !CheckInRoom())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_CURSE:
DoCastAOE(SPELL_CURSE_PLAGUEBRINGER);
events.ScheduleEvent(EVENT_CURSE, 50000 + rand()%10000);
return;
case EVENT_WARRIOR:
DoScriptText(SAY_SUMMON, me);
SummonUndead(MOB_WARRIOR, RAID_MODE(2,3));
events.ScheduleEvent(EVENT_WARRIOR, 30000);
return;
case EVENT_BLINK:
DoCastAOE(SPELL_CRIPPLE, true);
DoCastAOE(SPELL_BLINK);
DoResetThreat();
events.ScheduleEvent(EVENT_BLINK, 40000);
return;
case EVENT_BALCONY:
me->SetReactState(REACT_PASSIVE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->AttackStop();
me->RemoveAllAuras();
me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O);
events.Reset();
events.ScheduleEvent(EVENT_WAVE, 2000 + rand()%3000);
waveCount = 0;
return;
case EVENT_WAVE:
DoScriptText(SAY_SUMMON, me);
switch(balconyCount)
{
case 0: SummonUndead(MOB_CHAMPION, RAID_MODE(2,4)); break;
case 1: SummonUndead(MOB_CHAMPION, RAID_MODE(1,2));
SummonUndead(MOB_GUARDIAN, RAID_MODE(1,2)); break;
case 2: SummonUndead(MOB_GUARDIAN, RAID_MODE(2,4)); break;
default:SummonUndead(MOB_CHAMPION, RAID_MODE(5,10));
SummonUndead(MOB_GUARDIAN, RAID_MODE(5,10));break;
}
++waveCount;
events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 30000 + rand()%15000);
return;
case EVENT_GROUND:
{
++balconyCount;
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->NearTeleportTo(x, y, z, o);
events.ScheduleEvent(EVENT_BALCONY, 110000);
EnterPhaseGround();
return;
}
}
}
if (me->HasReactState(REACT_AGGRESSIVE))
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_noth(Creature* pCreature)
{
return new boss_nothAI (pCreature);
}
void AddSC_boss_noth()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_noth";
newscript->GetAI = &GetAI_boss_noth;
newscript->RegisterSelf();
new boss_noth();
}
@@ -49,112 +49,115 @@ enum
{
ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT = 10286,
};
struct boss_patchwerkAI : public BossAI
␍class boss_patchwerk : public CreatureScript
{
boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {}
public:
boss_patchwerk() : CreatureScript("boss_patchwerk") { }
bool Enraged;
void Reset()
CreatureAI* GetAI(Creature* pCreature) const
{
_Reset();
if (instance)
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
return new boss_patchwerkAI (pCreature);
}
void KilledUnit(Unit* /*Victim*/)
struct boss_patchwerkAI : public BossAI
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
bool Enraged;
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
Enraged = false;
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me);
events.ScheduleEvent(EVENT_HATEFUL, 1200);
events.ScheduleEvent(EVENT_BERSERK, 360000);
if (instance)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void Reset()
{
switch(eventId)
_Reset();
if (instance)
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void KilledUnit(Unit* /*Victim*/)
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
Enraged = false;
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me);
events.ScheduleEvent(EVENT_HATEFUL, 1200);
events.ScheduleEvent(EVENT_BERSERK, 360000);
if (instance)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
case EVENT_HATEFUL:
switch(eventId)
{
//Cast Hateful strike on the player with the highest
//amount of HP within melee distance
uint32 MostHP = 0;
Unit* pMostHPTarget = NULL;
std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
case EVENT_HATEFUL:
{
Unit *pTarget = (*i)->getTarget();
if (pTarget->isAlive() && pTarget->GetHealth() > MostHP && me->IsWithinMeleeRange(pTarget))
//Cast Hateful strike on the player with the highest
//amount of HP within melee distance
uint32 MostHP = 0;
Unit* pMostHPTarget = NULL;
std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
{
MostHP = pTarget->GetHealth();
pMostHPTarget = pTarget;
Unit *pTarget = (*i)->getTarget();
if (pTarget->isAlive() && pTarget->GetHealth() > MostHP && me->IsWithinMeleeRange(pTarget))
{
MostHP = pTarget->GetHealth();
pMostHPTarget = pTarget;
}
}
if (pMostHPTarget)
DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE,H_SPELL_HATEFUL_STRIKE), true);
events.ScheduleEvent(EVENT_HATEFUL, 1200);
break;
}
if (pMostHPTarget)
DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE,H_SPELL_HATEFUL_STRIKE), true);
events.ScheduleEvent(EVENT_HATEFUL, 1200);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK, true);
DoScriptText(EMOTE_BERSERK, me);
events.ScheduleEvent(EVENT_SLIME, 2000);
break;
case EVENT_SLIME:
DoCast(me->getVictim(), SPELL_SLIME_BOLT);
events.ScheduleEvent(EVENT_SLIME, 2000);
break;
}
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK, true);
DoScriptText(EMOTE_BERSERK, me);
events.ScheduleEvent(EVENT_SLIME, 2000);
break;
case EVENT_SLIME:
DoCast(me->getVictim(), SPELL_SLIME_BOLT);
events.ScheduleEvent(EVENT_SLIME, 2000);
break;
}
}
if (!Enraged && HealthBelowPct(5))
{
DoCast(me, SPELL_FRENZY, true);
DoScriptText(EMOTE_ENRAGE, me);
Enraged = true;
}
if (!Enraged && HealthBelowPct(5))
{
DoCast(me, SPELL_FRENZY, true);
DoScriptText(EMOTE_ENRAGE, me);
Enraged = true;
}
DoMeleeAttackIfReady();
}
};
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_boss_patchwerk(Creature* pCreature)
{
return new boss_patchwerkAI (pCreature);
}
void AddSC_boss_patchwerk()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_patchwerk";
newscript->GetAI = &GetAI_boss_patchwerk;
newscript->RegisterSelf();
new boss_patchwerk();
}
@@ -51,88 +51,91 @@ enum Events
EVENT_KNIFE,
EVENT_COMMAND,
};
struct boss_razuviousAI : public BossAI
␍class boss_razuvious : public CreatureScript
{
boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {}
public:
boss_razuvious() : CreatureScript("boss_razuvious") { }
void KilledUnit(Unit* /*victim*/)
CreatureAI* GetAI(Creature* pCreature) const
{
if (!(rand()%3))
DoPlaySoundToSet(me, SOUND_SLAY);
return new boss_razuviousAI (pCreature);
}
void DamageTaken(Unit* pDone_by, uint32& uiDamage)
struct boss_razuviousAI : public BossAI
{
// Damage done by the controlled Death Knight understudies should also count toward damage done by players
if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941))
boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {}
void KilledUnit(Unit* /*victim*/)
{
me->LowerPlayerDamageReq(uiDamage);
if (!(rand()%3))
DoPlaySoundToSet(me, SOUND_SLAY);
}
}
void JustDied(Unit* /*killer*/)
{
_JustDied();
DoPlaySoundToSet(me, SOUND_DEATH);
me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoPlaySoundToSet(me, SOUND_AGGRO);
events.ScheduleEvent(EVENT_STRIKE, 30000);
events.ScheduleEvent(EVENT_SHOUT, 25000);
events.ScheduleEvent(EVENT_COMMAND, 40000);
events.ScheduleEvent(EVENT_KNIFE, 10000);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
void DamageTaken(Unit* pDone_by, uint32& uiDamage)
{
switch(eventId)
// Damage done by the controlled Death Knight understudies should also count toward damage done by players
if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941))
{
case EVENT_STRIKE:
DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE);
events.ScheduleEvent(EVENT_STRIKE, 30000);
return;
case EVENT_SHOUT:
DoCastAOE(SPELL_DISRUPTING_SHOUT);
events.ScheduleEvent(EVENT_SHOUT, 25000);
return;
case EVENT_KNIFE:
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(pTarget, SPELL_JAGGED_KNIFE);
events.ScheduleEvent(EVENT_KNIFE, 10000);
return;
case EVENT_COMMAND:
DoPlaySoundToSet(me, SOUND_COMMND);
events.ScheduleEvent(EVENT_COMMAND, 40000);
return;
me->LowerPlayerDamageReq(uiDamage);
}
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/)
{
_JustDied();
DoPlaySoundToSet(me, SOUND_DEATH);
me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoPlaySoundToSet(me, SOUND_AGGRO);
events.ScheduleEvent(EVENT_STRIKE, 30000);
events.ScheduleEvent(EVENT_SHOUT, 25000);
events.ScheduleEvent(EVENT_COMMAND, 40000);
events.ScheduleEvent(EVENT_KNIFE, 10000);
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_STRIKE:
DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE);
events.ScheduleEvent(EVENT_STRIKE, 30000);
return;
case EVENT_SHOUT:
DoCastAOE(SPELL_DISRUPTING_SHOUT);
events.ScheduleEvent(EVENT_SHOUT, 25000);
return;
case EVENT_KNIFE:
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(pTarget, SPELL_JAGGED_KNIFE);
events.ScheduleEvent(EVENT_KNIFE, 10000);
return;
case EVENT_COMMAND:
DoPlaySoundToSet(me, SOUND_COMMND);
events.ScheduleEvent(EVENT_COMMAND, 40000);
return;
}
}
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_razuvious(Creature* pCreature)
{
return new boss_razuviousAI (pCreature);
}
void AddSC_boss_razuvious()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_razuvious";
newscript->GetAI = &GetAI_boss_razuvious;
newscript->RegisterSelf();
new boss_razuvious();
}
@@ -68,335 +68,334 @@ enum Events
};
typedef std::map<uint64, uint64> IceBlockMap;
struct boss_sapphironAI : public BossAI
␍class boss_sapphiron : public CreatureScript
{
boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON)
, phase(PHASE_NULL)
public:
boss_sapphiron() : CreatureScript("boss_sapphiron") { }
CreatureAI* GetAI(Creature* pCreature) const
{
pMap = me->GetMap();
return new boss_sapphironAI (pCreature);
}
Phases phase;
uint32 iceboltCount;
IceBlockMap iceblocks;
bool CanTheHundredClub; // needed for achievement: The Hundred Club(2146, 2147)
uint32 CheckFrostResistTimer;
Map* pMap;
void InitializeAI()
struct boss_sapphironAI : public BossAI
{
float x, y, z;
me->GetPosition(x, y, z);
me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0);
me->SetVisibility(VISIBILITY_OFF);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
ScriptedAI::InitializeAI();
}
void Reset()
{
_Reset();
if (phase == PHASE_FLIGHT)
ClearIceBlock();
phase = PHASE_NULL;
CanTheHundredClub = true;
CheckFrostResistTimer = 5000;
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
me->CastSpell(me, SPELL_FROST_AURA, true);
events.ScheduleEvent(EVENT_BERSERK, 15*60000);
EnterPhaseGround();
CheckPlayersFrostResist();
}
void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
{
if (spell->Id == SPELL_ICEBOLT)
boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON)
, phase(PHASE_NULL)
{
IceBlockMap::iterator itr = iceblocks.find(pTarget->GetGUID());
if (itr != iceblocks.end() && !itr->second)
{
if (GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, 0, 0, 0, 0, 25000))
itr->second = iceblock->GetGUID();
}
pMap = me->GetMap();
}
}
void JustDied(Unit* /*who*/)
{
_JustDied();
me->CastSpell(me, SPELL_DIES, true);
Phases phase;
uint32 iceboltCount;
IceBlockMap iceblocks;
CheckPlayersFrostResist();
if (CanTheHundredClub)
bool CanTheHundredClub; // needed for achievement: The Hundred Club(2146, 2147)
uint32 CheckFrostResistTimer;
Map* pMap;
void InitializeAI()
{
AchievementEntry const *AchievTheHundredClub = GetAchievementStore()->LookupEntry(ACHIEVEMENT_THE_HUNDRED_CLUB);
if (AchievTheHundredClub)
float x, y, z;
me->GetPosition(x, y, z);
me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0);
me->SetVisibility(VISIBILITY_OFF);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
ScriptedAI::InitializeAI();
}
void Reset()
{
_Reset();
if (phase == PHASE_FLIGHT)
ClearIceBlock();
phase = PHASE_NULL;
CanTheHundredClub = true;
CheckFrostResistTimer = 5000;
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
me->CastSpell(me, SPELL_FROST_AURA, true);
events.ScheduleEvent(EVENT_BERSERK, 15*60000);
EnterPhaseGround();
CheckPlayersFrostResist();
}
void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
{
if (spell->Id == SPELL_ICEBOLT)
{
if (pMap && pMap->IsDungeon())
IceBlockMap::iterator itr = iceblocks.find(pTarget->GetGUID());
if (itr != iceblocks.end() && !itr->second)
{
Map::PlayerList const &players = pMap->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
itr->getSource()->CompletedAchievement(AchievTheHundredClub);
if (GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, 0, 0, 0, 0, 25000))
itr->second = iceblock->GetGUID();
}
}
}
}
void MovementInform(uint32, uint32 id)
{
if (id == 1)
events.ScheduleEvent(EVENT_LIFTOFF, 0);
}
void DoAction(const int32 param)
{
if (param == DATA_SAPPHIRON_BIRTH)
void JustDied(Unit* /*who*/)
{
phase = PHASE_BIRTH;
events.ScheduleEvent(EVENT_BIRTH, 23000);
}
}
_JustDied();
me->CastSpell(me, SPELL_DIES, true);
void CheckPlayersFrostResist()
{
if (CanTheHundredClub && pMap && pMap->IsDungeon())
{
Map::PlayerList const &players = pMap->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
CheckPlayersFrostResist();
if (CanTheHundredClub)
{
if (itr->getSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE)
AchievementEntry const *AchievTheHundredClub = GetAchievementStore()->LookupEntry(ACHIEVEMENT_THE_HUNDRED_CLUB);
if (AchievTheHundredClub)
{
CanTheHundredClub = false;
break;
}
}
}
}
void EnterPhaseGround()
{
phase = PHASE_GROUND;
me->SetReactState(REACT_AGGRESSIVE);
events.SetPhase(PHASE_GROUND);
events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_FLIGHT, 45000);
}
void ClearIceBlock()
{
for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr)
{
if (Player* pPlayer = Unit::GetPlayer(*me, itr->first))
pPlayer->RemoveAura(SPELL_ICEBOLT);
if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second))
pGo->Delete();
}
iceblocks.clear();
}
void UpdateAI(const uint32 diff)
{
if (!phase)
return;
events.Update(diff);
if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom())
return;
if (CanTheHundredClub)
{
if (CheckFrostResistTimer <= diff)
{
CheckPlayersFrostResist();
CheckFrostResistTimer = (rand() % 5 + 5) * 1000;
} else CheckFrostResistTimer -= diff;
}
if (phase == PHASE_GROUND)
{
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_BERSERK:
DoScriptText(EMOTE_ENRAGE, me);
DoCast(me, SPELL_BERSERK);
return;
case EVENT_CLEAVE:
DoCast(me->getVictim(), SPELL_CLEAVE);
events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND);
return;
case EVENT_TAIL:
DoCastAOE(SPELL_TAIL_SWEEP);
events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND);
return;
case EVENT_DRAIN:
DoCastAOE(SPELL_LIFE_DRAIN);
events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND);
return;
case EVENT_BLIZZARD:
if (pMap && pMap->IsDungeon())
{
//DoCastAOE(SPELL_SUMMON_BLIZZARD);
if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN))
pSummon->GetMotionMaster()->MoveRandom(40);
events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND);
Map::PlayerList const &players = pMap->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
itr->getSource()->CompletedAchievement(AchievTheHundredClub);
}
}
}
}
void MovementInform(uint32, uint32 id)
{
if (id == 1)
events.ScheduleEvent(EVENT_LIFTOFF, 0);
}
void DoAction(const int32 param)
{
if (param == DATA_SAPPHIRON_BIRTH)
{
phase = PHASE_BIRTH;
events.ScheduleEvent(EVENT_BIRTH, 23000);
}
}
void CheckPlayersFrostResist()
{
if (CanTheHundredClub && pMap && pMap->IsDungeon())
{
Map::PlayerList const &players = pMap->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
if (itr->getSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE)
{
CanTheHundredClub = false;
break;
}
case EVENT_FLIGHT:
phase = PHASE_FLIGHT;
events.SetPhase(PHASE_FLIGHT);
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->GetMotionMaster()->MovePoint(1, x, y, z);
return;
}
}
DoMeleeAttackIfReady();
}
else
void EnterPhaseGround()
{
if (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_LIFTOFF:
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->SendMovementFlagUpdate();
events.ScheduleEvent(EVENT_ICEBOLT, 1500);
iceboltCount = RAID_MODE(2,3);
return;
case EVENT_ICEBOLT:
{
std::vector<Unit*> targets;
std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT))
targets.push_back((*i)->getTarget());
phase = PHASE_GROUND;
me->SetReactState(REACT_AGGRESSIVE);
events.SetPhase(PHASE_GROUND);
events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_FLIGHT, 45000);
}
if (targets.empty())
iceboltCount = 0;
else
{
std::vector<Unit*>::const_iterator itr = targets.begin();
advance(itr, rand()%targets.size());
iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0));
DoCast(*itr, SPELL_ICEBOLT);
--iceboltCount;
}
if (iceboltCount)
events.ScheduleEvent(EVENT_ICEBOLT, 1000);
else
events.ScheduleEvent(EVENT_BREATH, 1000);
return;
}
case EVENT_BREATH:
{
DoScriptText(EMOTE_BREATH, me);
DoCastAOE(SPELL_FROST_MISSILE);
events.ScheduleEvent(EVENT_EXPLOSION, 8000);
return;
}
case EVENT_EXPLOSION:
CastExplosion();
ClearIceBlock();
events.ScheduleEvent(EVENT_LAND, 3000);
return;
case EVENT_LAND:
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->SendMovementFlagUpdate();
events.ScheduleEvent(EVENT_GROUND, 1500);
return;
case EVENT_GROUND:
EnterPhaseGround();
return;
case EVENT_BIRTH:
me->SetVisibility(VISIBILITY_ON);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_AGGRESSIVE);
return;
}
}//if (uint32 eventId = events.ExecuteEvent())
}//if (phase == PHASE_GROUND)
}
void CastExplosion()
{
DoZoneInCombat(); // make sure everyone is in threatlist
std::vector<Unit*> targets;
std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
void ClearIceBlock()
{
Unit *pTarget = (*i)->getTarget();
if (pTarget->GetTypeId() != TYPEID_PLAYER)
continue;
if (pTarget->HasAura(SPELL_ICEBOLT))
{
pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true);
targets.push_back(pTarget);
continue;
}
for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr)
{
if (Player* pPlayer = Unit::GetPlayer(*me, itr->first))
pPlayer->RemoveAura(SPELL_ICEBOLT);
if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second))
pGo->Delete();
}
iceblocks.clear();
}
void UpdateAI(const uint32 diff)
{
if (!phase)
return;
events.Update(diff);
if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom())
return;
if (CanTheHundredClub)
{
if (CheckFrostResistTimer <= diff)
{
if (pGo->IsInBetween(me, pTarget, 2.0f)
&& me->GetExactDist2d(pTarget->GetPositionX(), pTarget->GetPositionY()) - me->GetExactDist2d(pGo->GetPositionX(), pGo->GetPositionY()) < 5.0f)
CheckPlayersFrostResist();
CheckFrostResistTimer = (rand() % 5 + 5) * 1000;
} else CheckFrostResistTimer -= diff;
}
if (phase == PHASE_GROUND)
{
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true);
targets.push_back(pTarget);
break;
case EVENT_BERSERK:
DoScriptText(EMOTE_ENRAGE, me);
DoCast(me, SPELL_BERSERK);
return;
case EVENT_CLEAVE:
DoCast(me->getVictim(), SPELL_CLEAVE);
events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND);
return;
case EVENT_TAIL:
DoCastAOE(SPELL_TAIL_SWEEP);
events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND);
return;
case EVENT_DRAIN:
DoCastAOE(SPELL_LIFE_DRAIN);
events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND);
return;
case EVENT_BLIZZARD:
{
//DoCastAOE(SPELL_SUMMON_BLIZZARD);
if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN))
pSummon->GetMotionMaster()->MoveRandom(40);
events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND);
break;
}
case EVENT_FLIGHT:
phase = PHASE_FLIGHT;
events.SetPhase(PHASE_FLIGHT);
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->GetMotionMaster()->MovePoint(1, x, y, z);
return;
}
}
DoMeleeAttackIfReady();
}
else
{
if (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
{
case EVENT_LIFTOFF:
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->SendMovementFlagUpdate();
events.ScheduleEvent(EVENT_ICEBOLT, 1500);
iceboltCount = RAID_MODE(2,3);
return;
case EVENT_ICEBOLT:
{
std::vector<Unit*> targets;
std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT))
targets.push_back((*i)->getTarget());
if (targets.empty())
iceboltCount = 0;
else
{
std::vector<Unit*>::const_iterator itr = targets.begin();
advance(itr, rand()%targets.size());
iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0));
DoCast(*itr, SPELL_ICEBOLT);
--iceboltCount;
}
if (iceboltCount)
events.ScheduleEvent(EVENT_ICEBOLT, 1000);
else
events.ScheduleEvent(EVENT_BREATH, 1000);
return;
}
case EVENT_BREATH:
{
DoScriptText(EMOTE_BREATH, me);
DoCastAOE(SPELL_FROST_MISSILE);
events.ScheduleEvent(EVENT_EXPLOSION, 8000);
return;
}
case EVENT_EXPLOSION:
CastExplosion();
ClearIceBlock();
events.ScheduleEvent(EVENT_LAND, 3000);
return;
case EVENT_LAND:
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
me->SendMovementFlagUpdate();
events.ScheduleEvent(EVENT_GROUND, 1500);
return;
case EVENT_GROUND:
EnterPhaseGround();
return;
case EVENT_BIRTH:
me->SetVisibility(VISIBILITY_ON);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_AGGRESSIVE);
return;
}
}//if (uint32 eventId = events.ExecuteEvent())
}//if (phase == PHASE_GROUND)
}
void CastExplosion()
{
DoZoneInCombat(); // make sure everyone is in threatlist
std::vector<Unit*> targets;
std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
{
Unit *pTarget = (*i)->getTarget();
if (pTarget->GetTypeId() != TYPEID_PLAYER)
continue;
if (pTarget->HasAura(SPELL_ICEBOLT))
{
pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true);
targets.push_back(pTarget);
continue;
}
for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr)
{
if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second))
{
if (pGo->IsInBetween(me, pTarget, 2.0f)
&& me->GetExactDist2d(pTarget->GetPositionX(), pTarget->GetPositionY()) - me->GetExactDist2d(pGo->GetPositionX(), pGo->GetPositionY()) < 5.0f)
{
pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true);
targets.push_back(pTarget);
break;
}
}
}
}
me->CastSpell(me, SPELL_FROST_EXPLOSION, true);
for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
(*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false);
}
};
me->CastSpell(me, SPELL_FROST_EXPLOSION, true);
for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
(*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false);
}
};
CreatureAI* GetAI_boss_sapphiron(Creature* pCreature)
{
return new boss_sapphironAI (pCreature);
}
void AddSC_boss_sapphiron()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_sapphiron";
newscript->GetAI = &GetAI_boss_sapphiron;
newscript->RegisterSelf();
// Chill
GetAISpellInfo(28547)->cooldown = 1000;
GetAISpellInfo(55699)->cooldown = 1000;
new boss_sapphiron();
}
@@ -93,307 +93,316 @@ enum Events
EVENT_CHAIN,
EVENT_BERSERK,
};
struct boss_thaddiusAI : public BossAI
␍class boss_thaddius : public CreatureScript
{
boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS)
public:
boss_thaddius() : CreatureScript("boss_thaddius") { }
CreatureAI* GetAI(Creature* pCreature) const
{
// init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe
// and, in particular, if there was a crash after both adds were killed (should not respawn)
return new boss_thaddiusAI (pCreature);
}
// Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn
// and each mob will send its status at reset (meaning that it is alive)
checkFeugenAlive = false;
if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
checkFeugenAlive = pFeugen->isAlive();
checkStalaggAlive = false;
if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG)))
checkStalaggAlive = pStalagg->isAlive();
if (!checkFeugenAlive && !checkStalaggAlive)
struct boss_thaddiusAI : public BossAI
{
boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS)
{
// init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe
// and, in particular, if there was a crash after both adds were killed (should not respawn)
// Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn
// and each mob will send its status at reset (meaning that it is alive)
checkFeugenAlive = false;
if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
checkFeugenAlive = pFeugen->isAlive();
checkStalaggAlive = false;
if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG)))
checkStalaggAlive = pStalagg->isAlive();
if (!checkFeugenAlive && !checkStalaggAlive)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
me->SetReactState(REACT_AGGRESSIVE);
}
else
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
me->SetReactState(REACT_PASSIVE);
}
}
bool checkStalaggAlive;
bool checkFeugenAlive;
uint32 uiAddsTimer;
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
void DoAction(const int32 action)
{
switch(action)
{
case ACTION_FEUGEN_RESET:
checkFeugenAlive = true;
break;
case ACTION_FEUGEN_DIED:
checkFeugenAlive = false;
break;
case ACTION_STALAGG_RESET:
checkStalaggAlive = true;
break;
case ACTION_STALAGG_DIED:
checkStalaggAlive = false;
break;
}
if (!checkFeugenAlive && !checkStalaggAlive)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
// REACT_AGGRESSIVE only reset when he takes damage.
DoZoneInCombat();
}
else
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
me->SetReactState(REACT_PASSIVE);
}
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me);
events.ScheduleEvent(EVENT_SHIFT, 30000);
events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000));
events.ScheduleEvent(EVENT_BERSERK, 360000);
}
void DamageTaken(Unit * /*pDoneBy*/, uint32 & /*uiDamage*/)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
me->SetReactState(REACT_AGGRESSIVE);
}
else
void UpdateAI(const uint32 diff)
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
me->SetReactState(REACT_PASSIVE);
}
}
if (checkFeugenAlive && checkStalaggAlive)
uiAddsTimer = 0;
bool checkStalaggAlive;
bool checkFeugenAlive;
uint32 uiAddsTimer;
void KilledUnit(Unit* /*victim*/)
{
if (!(rand()%5))
DoScriptText(SAY_SLAY, me);
}
void JustDied(Unit* /*Killer*/)
{
_JustDied();
DoScriptText(SAY_DEATH, me);
}
void DoAction(const int32 action)
{
switch(action)
{
case ACTION_FEUGEN_RESET:
checkFeugenAlive = true;
break;
case ACTION_FEUGEN_DIED:
checkFeugenAlive = false;
break;
case ACTION_STALAGG_RESET:
checkStalaggAlive = true;
break;
case ACTION_STALAGG_DIED:
checkStalaggAlive = false;
break;
}
if (!checkFeugenAlive && !checkStalaggAlive)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
// REACT_AGGRESSIVE only reset when he takes damage.
DoZoneInCombat();
}
else
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED);
me->SetReactState(REACT_PASSIVE);
}
}
void EnterCombat(Unit * /*who*/)
{
_EnterCombat();
DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me);
events.ScheduleEvent(EVENT_SHIFT, 30000);
events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000));
events.ScheduleEvent(EVENT_BERSERK, 360000);
}
void DamageTaken(Unit * /*pDoneBy*/, uint32 & /*uiDamage*/)
{
me->SetReactState(REACT_AGGRESSIVE);
}
void UpdateAI(const uint32 diff)
{
if (checkFeugenAlive && checkStalaggAlive)
uiAddsTimer = 0;
if (checkStalaggAlive != checkFeugenAlive)
{
uiAddsTimer += diff;
if (uiAddsTimer > 5000)
if (checkStalaggAlive != checkFeugenAlive)
{
if (!checkStalaggAlive)
uiAddsTimer += diff;
if (uiAddsTimer > 5000)
{
if (instance)
if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG)))
pStalagg->Respawn();
}
else
{
if (instance)
if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
pFeugen->Respawn();
if (!checkStalaggAlive)
{
if (instance)
if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG)))
pStalagg->Respawn();
}
else
{
if (instance)
if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
pFeugen->Respawn();
}
}
}
}
if (!UpdateVictim())
return;
if (!UpdateVictim())
return;
events.Update(diff);
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch(eventId)
while (uint32 eventId = events.ExecuteEvent())
{
case EVENT_SHIFT:
DoCastAOE(SPELL_POLARITY_SHIFT);
events.ScheduleEvent(EVENT_SHIFT, 30000);
return;
case EVENT_CHAIN:
DoCast(me->getVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING));
events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000));
return;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK);
return;
switch(eventId)
{
case EVENT_SHIFT:
DoCastAOE(SPELL_POLARITY_SHIFT);
events.ScheduleEvent(EVENT_SHIFT, 30000);
return;
case EVENT_CHAIN:
DoCast(me->getVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING));
events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000));
return;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK);
return;
}
}
}
if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->getVictim()))
DoCast(me->getVictim(), SPELL_BALL_LIGHTNING);
else
DoMeleeAttackIfReady();
}
if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->getVictim()))
DoCast(me->getVictim(), SPELL_BALL_LIGHTNING);
else
DoMeleeAttackIfReady();
}
};
};
CreatureAI* GetAI_boss_thaddius(Creature* pCreature)
␍class mob_stalagg : public CreatureScript
{
return new boss_thaddiusAI (pCreature);
}
public:
mob_stalagg() : CreatureScript("mob_stalagg") { }
struct mob_stalaggAI : public ScriptedAI
{
mob_stalaggAI(Creature *c) : ScriptedAI(c)
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
return new mob_stalaggAI(pCreature);
}
ScriptedInstance* pInstance;
uint32 powerSurgeTimer;
uint32 magneticPullTimer;
void Reset()
struct mob_stalaggAI : public ScriptedAI
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_STALAGG_RESET);
powerSurgeTimer = urand(20000,25000);
magneticPullTimer = 20000;
}
void EnterCombat(Unit * /*pWho*/)
{
DoCast(SPELL_STALAGG_TESLA);
}
void JustDied(Unit * /*killer*/)
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_STALAGG_DIED);
}
void UpdateAI(const uint32 uiDiff)
{
if (!UpdateVictim())
return;
if (magneticPullTimer <= uiDiff)
mob_stalaggAI(Creature *c) : ScriptedAI(c)
{
if (Creature *pFeugen = me->GetCreature(*me, pInstance->GetData64(DATA_FEUGEN)))
{
Unit* pStalaggVictim = me->getVictim();
Unit* pFeugenVictim = pFeugen->getVictim();
pInstance = c->GetInstanceScript();
}
if (pFeugenVictim && pStalaggVictim)
{
// magnetic pull is not working. So just jump.
InstanceScript* pInstance;
// reset aggro to be sure that feugen will not follow the jump
pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100);
pFeugenVictim->JumpTo(me, 0.3f);
me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100);
pStalaggVictim->JumpTo(pFeugen, 0.3f);
}
}
uint32 powerSurgeTimer;
uint32 magneticPullTimer;
void Reset()
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_STALAGG_RESET);
powerSurgeTimer = urand(20000,25000);
magneticPullTimer = 20000;
}
else magneticPullTimer -= uiDiff;
if (powerSurgeTimer <= uiDiff)
void EnterCombat(Unit * /*pWho*/)
{
DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE));
powerSurgeTimer = urand(15000,20000);
} else powerSurgeTimer -= uiDiff;
DoCast(SPELL_STALAGG_TESLA);
}
void JustDied(Unit * /*killer*/)
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_STALAGG_DIED);
}
void UpdateAI(const uint32 uiDiff)
{
if (!UpdateVictim())
return;
if (magneticPullTimer <= uiDiff)
{
if (Creature *pFeugen = me->GetCreature(*me, pInstance->GetData64(DATA_FEUGEN)))
{
Unit* pStalaggVictim = me->getVictim();
Unit* pFeugenVictim = pFeugen->getVictim();
if (pFeugenVictim && pStalaggVictim)
{
// magnetic pull is not working. So just jump.
// reset aggro to be sure that feugen will not follow the jump
pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100);
pFeugenVictim->JumpTo(me, 0.3f);
me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100);
pStalaggVictim->JumpTo(pFeugen, 0.3f);
}
}
magneticPullTimer = 20000;
}
else magneticPullTimer -= uiDiff;
if (powerSurgeTimer <= uiDiff)
{
DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE));
powerSurgeTimer = urand(15000,20000);
} else powerSurgeTimer -= uiDiff;
DoMeleeAttackIfReady();
}
};
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_stalagg(Creature* pCreature)
␍class mob_feugen : public CreatureScript
{
return new mob_stalaggAI(pCreature);
}
public:
mob_feugen() : CreatureScript("mob_feugen") { }
struct mob_feugenAI : public ScriptedAI
{
mob_feugenAI(Creature *c) : ScriptedAI(c)
CreatureAI* GetAI(Creature* pCreature) const
{
pInstance = c->GetInstanceData();
return new mob_feugenAI(pCreature);
}
ScriptedInstance* pInstance;
uint32 staticFieldTimer;
void Reset()
struct mob_feugenAI : public ScriptedAI
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET);
staticFieldTimer = 5000;
}
void EnterCombat(Unit * /*pWho*/)
{
DoCast(SPELL_FEUGEN_TESLA);
}
void JustDied(Unit * /*killer*/)
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED);
}
void UpdateAI(const uint32 uiDiff)
{
if (!UpdateVictim())
return;
if (staticFieldTimer <= uiDiff)
mob_feugenAI(Creature *c) : ScriptedAI(c)
{
DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD));
pInstance = c->GetInstanceScript();
}
InstanceScript* pInstance;
uint32 staticFieldTimer;
void Reset()
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET);
staticFieldTimer = 5000;
} else staticFieldTimer -= uiDiff;
}
void EnterCombat(Unit * /*pWho*/)
{
DoCast(SPELL_FEUGEN_TESLA);
}
void JustDied(Unit * /*killer*/)
{
if (pInstance)
if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS)))
if (pThaddius->AI())
pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED);
}
void UpdateAI(const uint32 uiDiff)
{
if (!UpdateVictim())
return;
if (staticFieldTimer <= uiDiff)
{
DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD));
staticFieldTimer = 5000;
} else staticFieldTimer -= uiDiff;
DoMeleeAttackIfReady();
}
};
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_mob_feugen(Creature* pCreature)
{
return new mob_feugenAI(pCreature);
}
void AddSC_boss_thaddius()
{
Script *newscript;
newscript = new Script;
newscript->Name = "boss_thaddius";
newscript->GetAI = &GetAI_boss_thaddius;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_stalagg";
newscript->GetAI = &GetAI_mob_stalagg;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "mob_feugen";
newscript->GetAI = &GetAI_mob_feugen;
newscript->RegisterSelf();
new boss_thaddius();
new mob_stalagg();
new mob_feugen();
}
@@ -101,246 +101,249 @@ inline uint32 GetEruptionSection(float x, float y)
return i;
return 3;
}
struct instance_naxxramas : public InstanceData
␍class instance_naxxramas : public InstanceMapScript
{
instance_naxxramas(Map* pMap) : InstanceData(pMap)
public:
instance_naxxramas() : InstanceMapScript("instance_naxxramas") { }
InstanceScript* GetInstanceData_InstanceMapScript(Map* pMap)
{
SetBossNumber(MAX_BOSS_NUMBER);
LoadDoorData(doorData);
LoadMinionData(minionData);
return new instance_naxxramas_InstanceMapScript(pMap);
}
std::set<uint64> HeiganEruptionGUID[4];
uint64 GothikGateGUID;
uint64 HorsemenChestGUID;
uint64 SapphironGUID;
uint64 uiFaerlina;
uint64 uiThane;
uint64 uiLady;
uint64 uiBaron;
uint64 uiSir;
uint64 uiThaddius;
uint64 uiFeugen;
uint64 uiStalagg;
uint64 uiKelthuzad;
uint64 uiKelthuzadTrigger;
uint64 uiPortals[4];
GOState gothikDoorState;
time_t minHorsemenDiedTime;
time_t maxHorsemenDiedTime;
void OnCreatureCreate(Creature* pCreature, bool add)
struct instance_naxxramas_InstanceMapScript : public InstanceScript
{
switch(pCreature->GetEntry())
instance_naxxramas_InstanceMapScript(Map* pMap) : InstanceScript(pMap)
{
case 15989: SapphironGUID = add ? pCreature->GetGUID() : 0; return;
case 15953: uiFaerlina = pCreature->GetGUID(); return;
case 16064: uiThane = pCreature->GetGUID(); return;
case 16065: uiLady = pCreature->GetGUID(); return;
case 30549: uiBaron = pCreature->GetGUID(); return;
case 16063: uiSir = pCreature->GetGUID(); return;
case 15928: uiThaddius = pCreature->GetGUID(); return;
case 15930: uiFeugen = pCreature->GetGUID(); return;
case 15929: uiStalagg = pCreature->GetGUID(); return;
case 15990: uiKelthuzad = pCreature->GetGUID(); return;
SetBossNumber(MAX_BOSS_NUMBER);
LoadDoorData(doorData);
LoadMinionData(minionData);
}
AddMinion(pCreature, add);
}
std::set<uint64> HeiganEruptionGUID[4];
uint64 GothikGateGUID;
uint64 HorsemenChestGUID;
uint64 SapphironGUID;
uint64 uiFaerlina;
uint64 uiThane;
uint64 uiLady;
uint64 uiBaron;
uint64 uiSir;
void OnGameObjectCreate(GameObject* pGo, bool add)
{
if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287)
{
uint32 section = GetEruptionSection(pGo->GetPositionX(), pGo->GetPositionY());
if (add)
HeiganEruptionGUID[section].insert(pGo->GetGUID());
else
HeiganEruptionGUID[section].erase(pGo->GetGUID());
return;
}
uint64 uiThaddius;
uint64 uiFeugen;
uint64 uiStalagg;
switch(pGo->GetEntry())
uint64 uiKelthuzad;
uint64 uiKelthuzadTrigger;
uint64 uiPortals[4];
GOState gothikDoorState;
time_t minHorsemenDiedTime;
time_t maxHorsemenDiedTime;
void OnCreatureCreate(Creature* pCreature, bool add)
{
case GO_BIRTH:
if (!add && SapphironGUID)
switch(pCreature->GetEntry())
{
if (Creature *pSapphiron = instance->GetCreature(SapphironGUID))
pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH);
case 15989: SapphironGUID = add ? pCreature->GetGUID() : 0; return;
case 15953: uiFaerlina = pCreature->GetGUID(); return;
case 16064: uiThane = pCreature->GetGUID(); return;
case 16065: uiLady = pCreature->GetGUID(); return;
case 30549: uiBaron = pCreature->GetGUID(); return;
case 16063: uiSir = pCreature->GetGUID(); return;
case 15928: uiThaddius = pCreature->GetGUID(); return;
case 15930: uiFeugen = pCreature->GetGUID(); return;
case 15929: uiStalagg = pCreature->GetGUID(); return;
case 15990: uiKelthuzad = pCreature->GetGUID(); return;
}
AddMinion(pCreature, add);
}
void OnGameObjectCreate(GameObject* pGo, bool add)
{
if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287)
{
uint32 section = GetEruptionSection(pGo->GetPositionX(), pGo->GetPositionY());
if (add)
HeiganEruptionGUID[section].insert(pGo->GetGUID());
else
HeiganEruptionGUID[section].erase(pGo->GetGUID());
return;
}
case GO_GOTHIK_GATE:
GothikGateGUID = add ? pGo->GetGUID() : 0;
pGo->SetGoState(gothikDoorState);
break;
case GO_HORSEMEN_CHEST: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break;
case GO_HORSEMEN_CHEST_HERO: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break;
case GO_KELTHUZAD_PORTAL01: uiPortals[0] = pGo->GetGUID(); break;
case GO_KELTHUZAD_PORTAL02: uiPortals[1] = pGo->GetGUID(); break;
case GO_KELTHUZAD_PORTAL03: uiPortals[2] = pGo->GetGUID(); break;
case GO_KELTHUZAD_PORTAL04: uiPortals[3] = pGo->GetGUID(); break;
case GO_KELTHUZAD_TRIGGER: uiKelthuzadTrigger = pGo->GetGUID(); break;
}
AddDoor(pGo, add);
}
void SetData(uint32 id, uint32 value)
{
switch(id)
{
case DATA_HEIGAN_ERUPT:
HeiganErupt(value);
break;
case DATA_GOTHIK_GATE:
if (GameObject *pGothikGate = instance->GetGameObject(GothikGateGUID))
pGothikGate->SetGoState(GOState(value));
gothikDoorState = GOState(value);
break;
case DATA_HORSEMEN0:
case DATA_HORSEMEN1:
case DATA_HORSEMEN2:
case DATA_HORSEMEN3:
if (value == NOT_STARTED)
{
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
}
else if (value == DONE)
{
time_t now = time(NULL);
if (minHorsemenDiedTime == 0)
minHorsemenDiedTime = now;
maxHorsemenDiedTime = now;
}
break;
}
}
uint64 GetData64(uint32 id)
{
switch(id)
{
case DATA_FAERLINA:
return uiFaerlina;
case DATA_THANE:
return uiThane;
case DATA_LADY:
return uiLady;
case DATA_BARON:
return uiBaron;
case DATA_SIR:
return uiSir;
case DATA_THADDIUS:
return uiThaddius;
case DATA_FEUGEN:
return uiFeugen;
case DATA_STALAGG:
return uiStalagg;
case DATA_KELTHUZAD:
return uiKelthuzad;
case DATA_KELTHUZAD_PORTAL01:
return uiPortals[0];
case DATA_KELTHUZAD_PORTAL02:
return uiPortals[1];
case DATA_KELTHUZAD_PORTAL03:
return uiPortals[2];
case DATA_KELTHUZAD_PORTAL04:
return uiPortals[3];
case DATA_KELTHUZAD_TRIGGER:
return uiKelthuzadTrigger;
}
return 0;
}
bool SetBossState(uint32 id, EncounterState state)
{
if (!InstanceData::SetBossState(id, state))
return false;
if (id == BOSS_HORSEMEN && state == DONE)
{
if (GameObject *pHorsemenChest = instance->GetGameObject(HorsemenChestGUID))
pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay());
}
return true;
}
void HeiganErupt(uint32 section)
{
for (uint32 i = 0; i < 4; ++i)
{
if (i == section)
continue;
for (std::set<uint64>::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr)
switch(pGo->GetEntry())
{
if (GameObject *pHeiganEruption = instance->GetGameObject(*itr))
case GO_BIRTH:
if (!add && SapphironGUID)
{
pHeiganEruption->SendCustomAnim();
pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION);
if (Creature *pSapphiron = instance->GetCreature(SapphironGUID))
pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH);
return;
}
case GO_GOTHIK_GATE:
GothikGateGUID = add ? pGo->GetGUID() : 0;
pGo->SetGoState(gothikDoorState);
break;
case GO_HORSEMEN_CHEST: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break;
case GO_HORSEMEN_CHEST_HERO: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break;
case GO_KELTHUZAD_PORTAL01: uiPortals[0] = pGo->GetGUID(); break;
case GO_KELTHUZAD_PORTAL02: uiPortals[1] = pGo->GetGUID(); break;
case GO_KELTHUZAD_PORTAL03: uiPortals[2] = pGo->GetGUID(); break;
case GO_KELTHUZAD_PORTAL04: uiPortals[3] = pGo->GetGUID(); break;
case GO_KELTHUZAD_TRIGGER: uiKelthuzadTrigger = pGo->GetGUID(); break;
}
AddDoor(pGo, add);
}
void SetData(uint32 id, uint32 value)
{
switch(id)
{
case DATA_HEIGAN_ERUPT:
HeiganErupt(value);
break;
case DATA_GOTHIK_GATE:
if (GameObject *pGothikGate = instance->GetGameObject(GothikGateGUID))
pGothikGate->SetGoState(GOState(value));
gothikDoorState = GOState(value);
break;
case DATA_HORSEMEN0:
case DATA_HORSEMEN1:
case DATA_HORSEMEN2:
case DATA_HORSEMEN3:
if (value == NOT_STARTED)
{
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
}
else if (value == DONE)
{
time_t now = time(NULL);
if (minHorsemenDiedTime == 0)
minHorsemenDiedTime = now;
maxHorsemenDiedTime = now;
}
break;
}
}
uint64 GetData64(uint32 id)
{
switch(id)
{
case DATA_FAERLINA:
return uiFaerlina;
case DATA_THANE:
return uiThane;
case DATA_LADY:
return uiLady;
case DATA_BARON:
return uiBaron;
case DATA_SIR:
return uiSir;
case DATA_THADDIUS:
return uiThaddius;
case DATA_FEUGEN:
return uiFeugen;
case DATA_STALAGG:
return uiStalagg;
case DATA_KELTHUZAD:
return uiKelthuzad;
case DATA_KELTHUZAD_PORTAL01:
return uiPortals[0];
case DATA_KELTHUZAD_PORTAL02:
return uiPortals[1];
case DATA_KELTHUZAD_PORTAL03:
return uiPortals[2];
case DATA_KELTHUZAD_PORTAL04:
return uiPortals[3];
case DATA_KELTHUZAD_TRIGGER:
return uiKelthuzadTrigger;
}
return 0;
}
bool SetBossState(uint32 id, EncounterState state)
{
if (!InstanceScript::SetBossState(id, state))
return false;
if (id == BOSS_HORSEMEN && state == DONE)
{
if (GameObject *pHorsemenChest = instance->GetGameObject(HorsemenChestGUID))
pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay());
}
return true;
}
void HeiganErupt(uint32 section)
{
for (uint32 i = 0; i < 4; ++i)
{
if (i == section)
continue;
for (std::set<uint64>::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr)
{
if (GameObject *pHeiganEruption = instance->GetGameObject(*itr))
{
pHeiganEruption->SendCustomAnim();
pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION);
}
}
}
}
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/)
{
switch(criteria_id)
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/)
{
case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 13233: // Criteria for achievement 2186: The Immortal (25-man)
// TODO.
break;
case 13237: // Criteria for achievement 2187: The Undying (10-man)
// TODO.
break;
switch(criteria_id)
{
case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 13233: // Criteria for achievement 2186: The Immortal (25-man)
// TODO.
break;
case 13237: // Criteria for achievement 2187: The Undying (10-man)
// TODO.
break;
}
return false;
}
return false;
}
std::string GetSaveData()
{
std::ostringstream saveStream;
saveStream << GetBossSaveData() << " " << gothikDoorState;
return saveStream.str();
}
std::string GetSaveData()
{
std::ostringstream saveStream;
saveStream << GetBossSaveData() << " " << gothikDoorState;
return saveStream.str();
}
void Load(const char * data)
{
std::istringstream loadStream(LoadBossState(data));
uint32 buff;
loadStream >> buff;
gothikDoorState = GOState(buff);
}
};
void Load(const char * data)
{
std::istringstream loadStream(LoadBossState(data));
uint32 buff;
loadStream >> buff;
gothikDoorState = GOState(buff);
}
};
InstanceData* GetInstanceData_instance_naxxramas(Map* pMap)
{
return new instance_naxxramas(pMap);
}
void AddSC_instance_naxxramas()
{
Script *newscript;
newscript = new Script;
newscript->Name = "instance_naxxramas";
newscript->GetInstanceData = &GetInstanceData_instance_naxxramas;
newscript->RegisterSelf();
new instance_naxxramas();
}