mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 13:46:24 +00:00
Big re-organization of repository [W.I.P]
This commit is contained in:
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum Curator
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SUMMON = 1,
|
||||
SAY_EVOCATE = 2,
|
||||
SAY_ENRAGE = 3,
|
||||
SAY_KILL = 4,
|
||||
SAY_DEATH = 5,
|
||||
|
||||
SPELL_HATEFUL_BOLT = 30383,
|
||||
SPELL_EVOCATION = 30254,
|
||||
SPELL_ARCANE_INFUSION = 30403,
|
||||
SPELL_ASTRAL_DECONSTRUCTION = 30407,
|
||||
|
||||
SPELL_SUMMON_ASTRAL_FLARE1 = 30236,
|
||||
SPELL_SUMMON_ASTRAL_FLARE2 = 30239,
|
||||
SPELL_SUMMON_ASTRAL_FLARE3 = 30240,
|
||||
SPELL_SUMMON_ASTRAL_FLARE4 = 30241,
|
||||
|
||||
EVENT_KILL_TALK = 1,
|
||||
EVENT_SPELL_HATEFUL_BOLT = 2,
|
||||
EVENT_SPELL_EVOCATION = 3,
|
||||
EVENT_SPELL_ASTRAL_FLARE = 4,
|
||||
EVENT_SPELL_BERSERK = 5,
|
||||
EVENT_CHECK_HEALTH = 6
|
||||
};
|
||||
|
||||
class boss_curator : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_curator() : CreatureScript("boss_curator") { }
|
||||
|
||||
struct boss_curatorAI : public BossAI
|
||||
{
|
||||
boss_curatorAI(Creature* creature) : BossAI(creature, TYPE_CURATOR) { }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_PERIODIC_MANA_LEECH, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_POWER_BURN, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_POWER_BURN, true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim)
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer)
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who)
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_HATEFUL_BOLT, 10000);
|
||||
events.ScheduleEvent(EVENT_SPELL_ASTRAL_FLARE, 6000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BERSERK, 600000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (Unit* target = summon->SelectNearbyTarget(NULL, 40.0f))
|
||||
{
|
||||
summon->AI()->AttackStart(target);
|
||||
summon->AddThreat(target, 1000.0f);
|
||||
}
|
||||
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(16))
|
||||
{
|
||||
events.CancelEvent(EVENT_SPELL_ASTRAL_FLARE);
|
||||
me->CastSpell(me, SPELL_ARCANE_INFUSION, true);
|
||||
Talk(SAY_ENRAGE);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
break;
|
||||
case EVENT_SPELL_BERSERK:
|
||||
Talk(SAY_ENRAGE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->CastSpell(me, SPELL_ASTRAL_DECONSTRUCTION, true);
|
||||
break;
|
||||
case EVENT_SPELL_HATEFUL_BOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1, 2), 40.0f))
|
||||
me->CastSpell(target, SPELL_HATEFUL_BOLT, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_HATEFUL_BOLT, urand(5000, 7500) * (events.GetNextEventTime(EVENT_SPELL_BERSERK) == 0 ? 1 : 2));
|
||||
break;
|
||||
case EVENT_SPELL_ASTRAL_FLARE:
|
||||
{
|
||||
me->CastSpell(me, RAND(SPELL_SUMMON_ASTRAL_FLARE1, SPELL_SUMMON_ASTRAL_FLARE2, SPELL_SUMMON_ASTRAL_FLARE3, SPELL_SUMMON_ASTRAL_FLARE4), false);
|
||||
int32 mana = CalculatePct(me->GetMaxPower(POWER_MANA), 10);
|
||||
me->ModifyPower(POWER_MANA, -mana);
|
||||
if (me->GetPowerPct(POWER_MANA) < 10.0f)
|
||||
{
|
||||
Talk(SAY_EVOCATE);
|
||||
me->CastSpell(me, SPELL_EVOCATION, false);
|
||||
|
||||
events.DelayEvents(20000);
|
||||
events.ScheduleEvent(EVENT_SPELL_ASTRAL_FLARE, 20000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (roll_chance_i(50))
|
||||
Talk(SAY_SUMMON);
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_ASTRAL_FLARE, 10000);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_curatorAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_curator()
|
||||
{
|
||||
new boss_curator();
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum MaidenOfVirtue
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_REPENTANCE = 2,
|
||||
SAY_DEATH = 3,
|
||||
|
||||
SPELL_REPENTANCE = 29511,
|
||||
SPELL_HOLY_FIRE = 29522,
|
||||
SPELL_HOLY_WRATH = 32445,
|
||||
SPELL_HOLY_GROUND = 29523,
|
||||
SPELL_BERSERK = 26662,
|
||||
|
||||
EVENT_SPELL_REPENTANCE = 1,
|
||||
EVENT_SPELL_HOLY_FIRE = 2,
|
||||
EVENT_SPELL_HOLY_WRATH = 3,
|
||||
EVENT_SPELL_ENRAGE = 4,
|
||||
EVENT_KILL_TALK = 5
|
||||
};
|
||||
|
||||
class boss_maiden_of_virtue : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_maiden_of_virtue() : CreatureScript("boss_maiden_of_virtue") { }
|
||||
|
||||
struct boss_maiden_of_virtueAI : public BossAI
|
||||
{
|
||||
boss_maiden_of_virtueAI(Creature* creature) : BossAI(creature, TYPE_MAIDEN) { }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer)
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who)
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
me->CastSpell(me, SPELL_HOLY_GROUND, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_REPENTANCE, 25000);
|
||||
events.ScheduleEvent(EVENT_SPELL_HOLY_FIRE, 8000);
|
||||
events.ScheduleEvent(EVENT_SPELL_HOLY_WRATH, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 600000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_REPENTANCE:
|
||||
me->CastSpell(me, SPELL_REPENTANCE, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_REPENTANCE, urand(25000, 35000));
|
||||
break;
|
||||
case EVENT_SPELL_HOLY_FIRE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
|
||||
me->CastSpell(target, SPELL_HOLY_FIRE, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_HOLY_FIRE, urand(8000, 18000));
|
||||
break;
|
||||
case EVENT_SPELL_HOLY_WRATH:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
|
||||
me->CastSpell(target, SPELL_HOLY_WRATH, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_HOLY_WRATH, urand(20000, 25000));
|
||||
break;
|
||||
case EVENT_SPELL_ENRAGE:
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_maiden_of_virtueAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_maiden_of_virtue()
|
||||
{
|
||||
new boss_maiden_of_virtue();
|
||||
}
|
||||
@@ -1,451 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum eSay
|
||||
{
|
||||
SAY_ATTUMEN1_APPEAR = 0,
|
||||
SAY_ATTUMEN1_MOUNT = 2,
|
||||
|
||||
SAY_ATTUMEN2_DEATH = 0,
|
||||
|
||||
SAY_ATTUMEN_KILL = 1,
|
||||
SAY_ATTUMEN_DISARM = 3,
|
||||
SAY_ATTUMEN_RANDOM = 4,
|
||||
SAY_ATTUMEN_MIDNIGHT_KILL = 5,
|
||||
|
||||
SAY_MIDNIGHT_EMOTE = 0
|
||||
};
|
||||
|
||||
enum eSpells
|
||||
{
|
||||
// Midnight
|
||||
SPELL_KNOCKDOWN = 29711,
|
||||
SPELL_SUMMON_ATTUMEN = 29714,
|
||||
SPELL_SUMMON_ATTUMEN_MOUNTED = 29799,
|
||||
|
||||
// Attumen
|
||||
SPELL_SHADOW_CLEAVE = 29832,
|
||||
SPELL_INTANGIBLE_PRESENCE = 29833,
|
||||
SPELL_SPAWN_SMOKE1 = 29802,
|
||||
|
||||
// Attumen 2
|
||||
SPELL_CHARGE_MIDNIGHT = 29847,
|
||||
SPELL_SPAWN_SMOKE2 = 10389,
|
||||
|
||||
// Generic
|
||||
SPELL_MOUNT_TARGET_ATTUMEN = 29769,
|
||||
SPELL_MOUNT_TARGET_MIDNIGHT = 29770
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
{
|
||||
EVENT_CHECK_HEALTH_95 = 1,
|
||||
EVENT_CHECK_HEALTH_25 = 2,
|
||||
EVENT_SPELL_KNOCKDOWN = 3,
|
||||
EVENT_SUMMON_ATTUMEN_MOUNTED = 4,
|
||||
|
||||
EVENT_SPELL_SHADOW_CLEAVE = 10,
|
||||
EVENT_SPELL_INTANGIBLE_PRESENCE = 11,
|
||||
EVENT_RANDOM_YELL = 12,
|
||||
|
||||
EVENT_SPELL_CHARGE = 20,
|
||||
|
||||
EVENT_KILL_TALK = 30
|
||||
};
|
||||
|
||||
enum eMisc
|
||||
{
|
||||
POINT_MOVE_TO_MIDNIGHT = 1,
|
||||
DATA_ATTUMEN_READY = 1
|
||||
};
|
||||
|
||||
class boss_midnight : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_midnight() : CreatureScript("boss_midnight") { }
|
||||
|
||||
struct boss_midnightAI : public BossAI
|
||||
{
|
||||
boss_midnightAI(Creature* creature) : BossAI(creature, TYPE_ATTUMEN) { }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->SetVisible(true);
|
||||
_healthPct = 100.0f;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who)
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_95, 0);
|
||||
events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 6000);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (Creature* attumen = summons.GetCreatureWithEntry(NPC_ATTUMEN_THE_HUNTSMAN))
|
||||
attumen->AI()->Talk(SAY_ATTUMEN_MIDNIGHT_KILL);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
|
||||
if (summon->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED)
|
||||
{
|
||||
summon->SetHealth(summon->CountPctFromMaxHealth(_healthPct));
|
||||
summon->CastSpell(summon, SPELL_SPAWN_SMOKE2, true);
|
||||
}
|
||||
else
|
||||
summon->CastSpell(summon, SPELL_SPAWN_SMOKE1, true);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 /*data*/)
|
||||
{
|
||||
if (type == DATA_ATTUMEN_READY)
|
||||
events.ScheduleEvent(EVENT_SUMMON_ATTUMEN_MOUNTED, 0);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/)
|
||||
{
|
||||
if (summon->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED)
|
||||
{
|
||||
summons.clear();
|
||||
Unit::Kill(me, me);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_HEALTH_95:
|
||||
if (me->HealthBelowPct(96))
|
||||
{
|
||||
me->CastSpell(me, SPELL_SUMMON_ATTUMEN, true);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 0);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_95, 500);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH_25:
|
||||
if (me->HealthBelowPct(25))
|
||||
{
|
||||
Talk(SAY_MIDNIGHT_EMOTE);
|
||||
me->CastSpell(me, SPELL_MOUNT_TARGET_ATTUMEN, true);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 500);
|
||||
break;
|
||||
case EVENT_SPELL_KNOCKDOWN:
|
||||
me->CastSpell(me->GetVictim(), SPELL_KNOCKDOWN, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 20000);
|
||||
break;
|
||||
case EVENT_SUMMON_ATTUMEN_MOUNTED:
|
||||
if (Creature* attumen = summons.GetCreatureWithEntry(NPC_ATTUMEN_THE_HUNTSMAN))
|
||||
{
|
||||
_healthPct = std::max<float>(me->GetHealthPct(), attumen->GetHealthPct());
|
||||
attumen->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
me->CastSpell(me, SPELL_SUMMON_ATTUMEN_MOUNTED, true);
|
||||
me->SetVisible(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->IsVisible())
|
||||
DoMeleeAttackIfReady();
|
||||
EnterEvadeIfOutOfCombatArea();
|
||||
}
|
||||
|
||||
bool CheckEvadeIfOutOfCombatArea() const
|
||||
{
|
||||
return me->GetHomePosition().GetExactDist2d(me) > 50.0f || me->GetPositionZ() > 60.0f;
|
||||
}
|
||||
|
||||
private:
|
||||
float _healthPct;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_midnightAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class boss_attumen : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_attumen() : CreatureScript("boss_attumen") { }
|
||||
|
||||
struct boss_attumenAI : public ScriptedAI
|
||||
{
|
||||
boss_attumenAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
Talk(SAY_ATTUMEN1_APPEAR);
|
||||
_events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 0);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, 6000);
|
||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 15000);
|
||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(25000, 45000));
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (_events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
Talk(SAY_ATTUMEN_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, const SpellInfo* spellInfo)
|
||||
{
|
||||
if (spellInfo->Mechanic == MECHANIC_DISARM && _events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
Talk(SAY_ATTUMEN_DISARM);
|
||||
}
|
||||
else if (spellInfo->Id == SPELL_MOUNT_TARGET_ATTUMEN)
|
||||
{
|
||||
me->CastSpell(me, SPELL_MOUNT_TARGET_MIDNIGHT, true);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, const SpellInfo* spellInfo)
|
||||
{
|
||||
if (spellInfo->Id == SPELL_MOUNT_TARGET_MIDNIGHT)
|
||||
{
|
||||
Talk(SAY_ATTUMEN1_MOUNT);
|
||||
_events.Reset();
|
||||
me->GetMotionMaster()->MovePoint(POINT_MOVE_TO_MIDNIGHT, target->GetPositionX() + 2.0f*cos(target->GetAngle(me)), target->GetPositionY() + 2.0f*sin(target->GetAngle(me)), target->GetPositionZ()+0.2f, true, true, MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 point)
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && point == POINT_MOVE_TO_MIDNIGHT)
|
||||
{
|
||||
if (TempSummon* summon = me->ToTempSummon())
|
||||
if (Unit* midnight = summon->GetSummoner())
|
||||
midnight->GetAI()->SetData(DATA_ATTUMEN_READY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOW_CLEAVE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_CLEAVE, false);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, urand(9000, 14000));
|
||||
break;
|
||||
case EVENT_SPELL_INTANGIBLE_PRESENCE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_INTANGIBLE_PRESENCE, false);
|
||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 30000);
|
||||
break;
|
||||
case EVENT_RANDOM_YELL:
|
||||
Talk(SAY_ATTUMEN_RANDOM);
|
||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(30000, 70000));
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH_25:
|
||||
if (me->HealthBelowPct(25))
|
||||
{
|
||||
me->CastSpell(me, SPELL_MOUNT_TARGET_MIDNIGHT, true);
|
||||
break;
|
||||
}
|
||||
_events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 500);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_attumenAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class boss_attumen_midnight : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_attumen_midnight() : CreatureScript("boss_attumen_midnight") { }
|
||||
|
||||
struct boss_attumen_midnightAI : public ScriptedAI
|
||||
{
|
||||
boss_attumen_midnightAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, 6000);
|
||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 15000);
|
||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(25000, 45000));
|
||||
_events.ScheduleEvent(EVENT_SPELL_CHARGE, 20000);
|
||||
_events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 11000);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (_events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
Talk(SAY_ATTUMEN_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
Talk(SAY_ATTUMEN2_DEATH);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, const SpellInfo* spellInfo)
|
||||
{
|
||||
if (spellInfo->Mechanic == MECHANIC_DISARM && _events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
Talk(SAY_ATTUMEN_DISARM);
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 point)
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && point == POINT_MOVE_TO_MIDNIGHT)
|
||||
{
|
||||
if (TempSummon* summon = me->ToTempSummon())
|
||||
if (Unit* midnight = summon->GetSummoner())
|
||||
midnight->GetAI()->SetData(DATA_ATTUMEN_READY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOW_CLEAVE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_CLEAVE, false);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, urand(9000, 14000));
|
||||
break;
|
||||
case EVENT_SPELL_INTANGIBLE_PRESENCE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_INTANGIBLE_PRESENCE, false);
|
||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 30000);
|
||||
break;
|
||||
case EVENT_RANDOM_YELL:
|
||||
Talk(SAY_ATTUMEN_RANDOM);
|
||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(30000, 70000));
|
||||
break;
|
||||
case EVENT_SPELL_CHARGE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 24.0f, true))
|
||||
me->CastSpell(target, SPELL_CHARGE_MIDNIGHT, false);
|
||||
_events.ScheduleEvent(EVENT_SPELL_CHARGE, 20000);
|
||||
break;
|
||||
case EVENT_SPELL_KNOCKDOWN:
|
||||
me->CastSpell(me->GetVictim(), SPELL_KNOCKDOWN, false);
|
||||
_events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 20000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_attumen_midnightAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_midnight_fixate : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_midnight_fixate() : SpellScriptLoader("spell_midnight_fixate") { }
|
||||
|
||||
class spell_midnight_fixate_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_midnight_fixate_AuraScript);
|
||||
|
||||
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->TauntApply(target);
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->TauntFadeOut(target);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_midnight_fixate_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_midnight_fixate_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_midnight_fixate_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_attumen()
|
||||
{
|
||||
new boss_midnight();
|
||||
new boss_attumen();
|
||||
new boss_attumen_midnight();
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum Yells
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SPECIAL = 1,
|
||||
SAY_KILL = 2,
|
||||
SAY_DEATH = 3,
|
||||
SAY_OUT_OF_COMBAT = 4,
|
||||
|
||||
SAY_GUEST = 0
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_VANISH = 29448,
|
||||
SPELL_GARROTE_DUMMY = 29433,
|
||||
SPELL_GARROTE = 37066,
|
||||
SPELL_BLIND = 34694,
|
||||
SPELL_GOUGE = 29425,
|
||||
SPELL_FRENZY = 37023,
|
||||
SPELL_DUAL_WIELD = 29651,
|
||||
SPELL_BERSERK = 26662,
|
||||
SPELL_VANISH_TELEPORT = 29431,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
EVENT_GUEST_TALK = 1,
|
||||
EVENT_GUEST_TALK2 = 2,
|
||||
EVENT_SPELL_VANISH = 3,
|
||||
EVENT_SPELL_GARROTE = 4,
|
||||
EVENT_SPELL_BLIND = 5,
|
||||
EVENT_SPELL_GOUGE = 6,
|
||||
EVENT_CHECK_HEALTH = 7,
|
||||
EVENT_SPELL_ENRAGE = 8,
|
||||
EVENT_KILL_TALK = 9,
|
||||
|
||||
ACTIVE_GUEST_COUNT = 4,
|
||||
MAX_GUEST_COUNT = 6
|
||||
};
|
||||
|
||||
const Position GuestsPosition[4] =
|
||||
{
|
||||
{-10987.38f, -1883.38f, 81.73f, 1.50f},
|
||||
{-10989.60f, -1881.27f, 81.73f, 0.73f},
|
||||
{-10978.81f, -1884.08f, 81.73f, 1.50f},
|
||||
{-10976.38f, -1882.59f, 81.73f, 2.31f},
|
||||
};
|
||||
|
||||
const uint32 GuestEntries[6]=
|
||||
{
|
||||
17007,
|
||||
19872,
|
||||
19873,
|
||||
19874,
|
||||
19875,
|
||||
19876,
|
||||
};
|
||||
|
||||
class boss_moroes : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_moroes() : CreatureScript("boss_moroes") { }
|
||||
|
||||
struct boss_moroesAI : public BossAI
|
||||
{
|
||||
boss_moroesAI(Creature* creature) : BossAI(creature, TYPE_MOROES)
|
||||
{
|
||||
_activeGuests = 0;
|
||||
}
|
||||
|
||||
void InitializeAI()
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
InitializeGuests();
|
||||
}
|
||||
|
||||
void JustReachedHome()
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
InitializeGuests();
|
||||
}
|
||||
|
||||
void InitializeGuests()
|
||||
{
|
||||
if (!me->IsAlive())
|
||||
return;
|
||||
|
||||
if (_activeGuests == 0)
|
||||
{
|
||||
_activeGuests |= 0x3F;
|
||||
uint8 rand1 = RAND(0x01, 0x02, 0x04);
|
||||
uint8 rand2 = RAND(0x08, 0x10, 0x20);
|
||||
_activeGuests &= ~(rand1|rand2);
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < MAX_GUEST_COUNT; ++i)
|
||||
if ((1 << i) & _activeGuests)
|
||||
me->SummonCreature(GuestEntries[i], GuestsPosition[summons.size()], TEMPSUMMON_MANUAL_DESPAWN);
|
||||
|
||||
_events2.Reset();
|
||||
_events2.ScheduleEvent(EVENT_GUEST_TALK, 10000);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->CastSpell(me, SPELL_DUAL_WIELD, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who)
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_VANISH, 30000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BLIND, 20000);
|
||||
events.ScheduleEvent(EVENT_SPELL_GOUGE, 13000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 600000);
|
||||
|
||||
_events2.Reset();
|
||||
me->CallForHelp(20.0f);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer)
|
||||
{
|
||||
summons.clear();
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GARROTE);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
Creature* GetRandomGuest()
|
||||
{
|
||||
std::list<Creature*> guestList;
|
||||
for (SummonList::const_iterator i = summons.begin(); i != summons.end(); ++i)
|
||||
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i))
|
||||
guestList.push_back(summon);
|
||||
|
||||
return Trinity::Containers::SelectRandomContainerElement(guestList);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
_events2.Update(diff);
|
||||
switch (_events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_GUEST_TALK:
|
||||
if (Creature* guest = GetRandomGuest())
|
||||
guest->AI()->Talk(SAY_GUEST);
|
||||
_events2.ScheduleEvent(EVENT_GUEST_TALK2, 5000);
|
||||
break;
|
||||
case EVENT_GUEST_TALK2:
|
||||
Talk(SAY_OUT_OF_COMBAT);
|
||||
_events2.ScheduleEvent(EVENT_GUEST_TALK, urand(60000, 120000));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(31))
|
||||
{
|
||||
me->CastSpell(me, SPELL_FRENZY, true);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
break;
|
||||
case EVENT_SPELL_ENRAGE:
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
case EVENT_SPELL_BLIND:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1, 10.0f, true))
|
||||
me->CastSpell(target, SPELL_BLIND, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_BLIND, urand(25000, 40000));
|
||||
break;
|
||||
case EVENT_SPELL_GOUGE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_GOUGE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_GOUGE, urand(25000, 40000));
|
||||
return;
|
||||
case EVENT_SPELL_VANISH:
|
||||
events.DelayEvents(9000);
|
||||
events.SetPhase(1);
|
||||
me->CastSpell(me, SPELL_VANISH, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_VANISH, 30000);
|
||||
events.ScheduleEvent(EVENT_SPELL_GARROTE, urand(5000, 7000));
|
||||
return;
|
||||
case EVENT_SPELL_GARROTE:
|
||||
me->CastSpell(me, SPELL_VANISH_TELEPORT, false);
|
||||
break;
|
||||
}
|
||||
|
||||
// Xinef: not in vanish
|
||||
if (events.GetPhaseMask() == 0)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events2;
|
||||
uint8 _activeGuests;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_moroesAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moroes_vanish : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_moroes_vanish() : SpellScriptLoader("spell_moroes_vanish") { }
|
||||
|
||||
class spell_moroes_vanish_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_moroes_vanish_SpellScript);
|
||||
|
||||
void HandleDummy(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
Position pos;
|
||||
target->GetFirstCollisionPosition(pos, 5.0f, M_PI);
|
||||
GetCaster()->CastSpell(target, SPELL_GARROTE_DUMMY, true);
|
||||
GetCaster()->RemoveAurasDueToSpell(SPELL_VANISH);
|
||||
GetCaster()->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), target->GetOrientation());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_moroes_vanish_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_moroes_vanish_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_moroes()
|
||||
{
|
||||
new boss_moroes();
|
||||
new spell_moroes_vanish();
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Netherspite
|
||||
SD%Complete: 90
|
||||
SDComment: Not sure about timing and portals placing
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
#include "Player.h"
|
||||
|
||||
enum Netherspite
|
||||
{
|
||||
EMOTE_PHASE_PORTAL = 0,
|
||||
EMOTE_PHASE_BANISH = 1,
|
||||
|
||||
SPELL_NETHERBURN_AURA = 30522,
|
||||
SPELL_VOIDZONE = 37063,
|
||||
SPELL_NETHER_INFUSION = 38688,
|
||||
SPELL_NETHERBREATH = 38523,
|
||||
SPELL_BANISH_VISUAL = 39833,
|
||||
SPELL_BANISH_ROOT = 42716,
|
||||
SPELL_EMPOWERMENT = 38549,
|
||||
SPELL_NETHERSPITE_ROAR = 38684,
|
||||
};
|
||||
|
||||
|
||||
const float PortalCoord[3][3] =
|
||||
{
|
||||
{-11195.353516f, -1613.237183f, 278.237258f}, // Left side
|
||||
{-11137.846680f, -1685.607422f, 278.239258f}, // Right side
|
||||
{-11094.493164f, -1591.969238f, 279.949188f} // Back side
|
||||
};
|
||||
|
||||
enum Netherspite_Portal{
|
||||
RED_PORTAL = 0, // Perseverence
|
||||
GREEN_PORTAL = 1, // Serenity
|
||||
BLUE_PORTAL = 2 // Dominance
|
||||
};
|
||||
|
||||
const uint32 PortalID[3] = {17369, 17367, 17368};
|
||||
const uint32 PortalVisual[3] = {30487, 30490, 30491};
|
||||
const uint32 PortalBeam[3] = {30465, 30464, 30463};
|
||||
const uint32 PlayerBuff[3] = {30421, 30422, 30423};
|
||||
const uint32 NetherBuff[3] = {30466, 30467, 30468};
|
||||
const uint32 PlayerDebuff[3] = {38637, 38638, 38639};
|
||||
|
||||
class boss_netherspite : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_netherspite() : CreatureScript("boss_netherspite") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_netherspiteAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_netherspiteAI : public ScriptedAI
|
||||
{
|
||||
boss_netherspiteAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
PortalGUID[i] = 0;
|
||||
BeamTarget[i] = 0;
|
||||
BeamerGUID[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
bool PortalPhase;
|
||||
bool Berserk;
|
||||
uint32 PhaseTimer; // timer for phase switching
|
||||
uint32 VoidZoneTimer;
|
||||
uint32 NetherInfusionTimer; // berserking timer
|
||||
uint32 NetherbreathTimer;
|
||||
uint32 EmpowermentTimer;
|
||||
uint32 PortalTimer; // timer for beam checking
|
||||
uint64 PortalGUID[3]; // guid's of portals
|
||||
uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals
|
||||
uint64 BeamTarget[3]; // guid's of portals' current targets
|
||||
|
||||
bool IsBetween(WorldObject* u1, WorldObject* target, WorldObject* u2) // the in-line checker
|
||||
{
|
||||
if (!u1 || !u2 || !target)
|
||||
return false;
|
||||
|
||||
float xn, yn, xp, yp, xh, yh;
|
||||
xn = u1->GetPositionX();
|
||||
yn = u1->GetPositionY();
|
||||
xp = u2->GetPositionX();
|
||||
yp = u2->GetPositionY();
|
||||
xh = target->GetPositionX();
|
||||
yh = target->GetPositionY();
|
||||
|
||||
// check if target is between (not checking distance from the beam yet)
|
||||
if (dist(xn, yn, xh, yh) >= dist(xn, yn, xp, yp) || dist(xp, yp, xh, yh) >= dist(xn, yn, xp, yp))
|
||||
return false;
|
||||
// check distance from the beam
|
||||
return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn, yn, xp, yp) < 1.5f);
|
||||
}
|
||||
|
||||
float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance
|
||||
{
|
||||
return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb));
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Berserk = false;
|
||||
NetherInfusionTimer = 540000;
|
||||
VoidZoneTimer = 15000;
|
||||
NetherbreathTimer = 3000;
|
||||
|
||||
HandleDoors(true);
|
||||
DestroyPortals();
|
||||
}
|
||||
|
||||
void SummonPortals()
|
||||
{
|
||||
uint8 r = rand()%4;
|
||||
uint8 pos[3];
|
||||
pos[RED_PORTAL] = ((r % 2) ? (r > 1 ? 2 : 1) : 0);
|
||||
pos[GREEN_PORTAL] = ((r % 2) ? 0 : (r > 1 ? 2 : 1));
|
||||
pos[BLUE_PORTAL] = (r > 1 ? 1 : 2); // Blue Portal not on the left side (0)
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
if (Creature* portal = me->SummonCreature(PortalID[i], PortalCoord[pos[i]][0], PortalCoord[pos[i]][1], PortalCoord[pos[i]][2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
{
|
||||
PortalGUID[i] = portal->GetGUID();
|
||||
portal->AddAura(PortalVisual[i], portal);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyPortals()
|
||||
{
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, PortalGUID[i]))
|
||||
portal->DisappearAndDie();
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, BeamerGUID[i]))
|
||||
portal->DisappearAndDie();
|
||||
PortalGUID[i] = 0;
|
||||
BeamTarget[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePortals() // Here we handle the beams' behavior
|
||||
{
|
||||
for (int j=0; j<3; ++j) // j = color
|
||||
if (Creature* portal = ObjectAccessor::GetCreature(*me, PortalGUID[j]))
|
||||
{
|
||||
// the one who's been cast upon before
|
||||
Unit* current = ObjectAccessor::GetUnit(*portal, BeamTarget[j]);
|
||||
// temporary store for the best suitable beam reciever
|
||||
Unit* target = me;
|
||||
|
||||
if (Map* map = me->GetMap())
|
||||
{
|
||||
Map::PlayerList const& players = map->GetPlayers();
|
||||
|
||||
// get the best suitable target
|
||||
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
|
||||
{
|
||||
Player* p = i->GetSource();
|
||||
if (p && p->IsAlive() // alive
|
||||
&& (!target || target->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best
|
||||
&& !p->HasAura(PlayerDebuff[j], 0) // not exhausted
|
||||
&& !p->HasAura(PlayerBuff[(j+1)%3], 0) // not on another beam
|
||||
&& !p->HasAura(PlayerBuff[(j+2)%3], 0)
|
||||
&& IsBetween(me, p, portal)) // on the beam
|
||||
target = p;
|
||||
}
|
||||
}
|
||||
// buff the target
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
target->AddAura(PlayerBuff[j], target);
|
||||
else
|
||||
target->AddAura(NetherBuff[j], target);
|
||||
// cast visual beam on the chosen target if switched
|
||||
// simple target switching isn't working -> using BeamerGUID to cast (workaround)
|
||||
if (!current || target != current)
|
||||
{
|
||||
BeamTarget[j] = target->GetGUID();
|
||||
// remove currently beaming portal
|
||||
if (Creature* beamer = ObjectAccessor::GetCreature(*portal, BeamerGUID[j]))
|
||||
{
|
||||
beamer->CastSpell(target, PortalBeam[j], false);
|
||||
beamer->DisappearAndDie();
|
||||
BeamerGUID[j] = 0;
|
||||
}
|
||||
// create new one and start beaming on the target
|
||||
if (Creature* beamer = portal->SummonCreature(PortalID[j], portal->GetPositionX(), portal->GetPositionY(), portal->GetPositionZ(), portal->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
{
|
||||
beamer->CastSpell(target, PortalBeam[j], false);
|
||||
BeamerGUID[j] = beamer->GetGUID();
|
||||
}
|
||||
}
|
||||
// aggro target if Red Beam
|
||||
if (j == RED_PORTAL && me->GetVictim() != target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
me->getThreatManager().addThreat(target, 100000.0f+DoGetThreat(me->GetVictim()));
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchToPortalPhase()
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT);
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL);
|
||||
SummonPortals();
|
||||
PhaseTimer = 60000;
|
||||
PortalPhase = true;
|
||||
PortalTimer = 10000;
|
||||
EmpowermentTimer = 10000;
|
||||
Talk(EMOTE_PHASE_PORTAL);
|
||||
}
|
||||
|
||||
void SwitchToBanishPhase()
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT);
|
||||
me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA);
|
||||
DoCast(me, SPELL_BANISH_VISUAL, true);
|
||||
DoCast(me, SPELL_BANISH_ROOT, true);
|
||||
DestroyPortals();
|
||||
PhaseTimer = 30000;
|
||||
PortalPhase = false;
|
||||
Talk(EMOTE_PHASE_BANISH);
|
||||
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
me->RemoveAurasDueToSpell(NetherBuff[i]);
|
||||
}
|
||||
|
||||
void HandleDoors(bool open) // Massive Door switcher
|
||||
{
|
||||
if (GameObject* Door = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_GO_MASSIVE_DOOR) ))
|
||||
Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
HandleDoors(false);
|
||||
SwitchToPortalPhase();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
HandleDoors(true);
|
||||
DestroyPortals();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// Void Zone
|
||||
if (VoidZoneTimer <= diff)
|
||||
{
|
||||
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true), SPELL_VOIDZONE, true);
|
||||
VoidZoneTimer = 15000;
|
||||
} else VoidZoneTimer -= diff;
|
||||
|
||||
// NetherInfusion Berserk
|
||||
if (!Berserk && NetherInfusionTimer <= diff)
|
||||
{
|
||||
me->AddAura(SPELL_NETHER_INFUSION, me);
|
||||
DoCast(me, SPELL_NETHERSPITE_ROAR);
|
||||
Berserk = true;
|
||||
} else NetherInfusionTimer -= diff;
|
||||
|
||||
if (PortalPhase) // PORTAL PHASE
|
||||
{
|
||||
// Distribute beams and buffs
|
||||
if (PortalTimer <= diff)
|
||||
{
|
||||
UpdatePortals();
|
||||
PortalTimer = 1000;
|
||||
} else PortalTimer -= diff;
|
||||
|
||||
// Empowerment & Nether Burn
|
||||
if (EmpowermentTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_EMPOWERMENT);
|
||||
me->AddAura(SPELL_NETHERBURN_AURA, me);
|
||||
EmpowermentTimer = 90000;
|
||||
} else EmpowermentTimer -= diff;
|
||||
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
SwitchToBanishPhase();
|
||||
return;
|
||||
}
|
||||
} else PhaseTimer -= diff;
|
||||
}
|
||||
else // BANISH PHASE
|
||||
{
|
||||
// Netherbreath
|
||||
if (NetherbreathTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
|
||||
DoCast(target, SPELL_NETHERBREATH);
|
||||
NetherbreathTimer = urand(5000, 7000);
|
||||
} else NetherbreathTimer -= diff;
|
||||
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
SwitchToPortalPhase();
|
||||
return;
|
||||
}
|
||||
} else PhaseTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_netherspite()
|
||||
{
|
||||
new boss_netherspite();
|
||||
}
|
||||
@@ -1,434 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Nightbane
|
||||
SD%Complete: 80
|
||||
SDComment: SDComment: Timers may incorrect
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// phase 1
|
||||
SPELL_BELLOWING_ROAR = 39427,
|
||||
SPELL_CHARRED_EARTH = 30129,
|
||||
SPELL_DISTRACTING_ASH = 30130,
|
||||
SPELL_SMOLDERING_BREATH = 30210,
|
||||
SPELL_TAIL_SWEEP = 25653,
|
||||
// phase 2
|
||||
SPELL_RAIN_OF_BONES = 37098,
|
||||
SPELL_SMOKING_BLAST = 37057,
|
||||
SPELL_FIREBALL_BARRAGE = 30282,
|
||||
SPELL_SEARING_CINDERS = 30127,
|
||||
SPELL_SUMMON_SKELETON = 30170
|
||||
};
|
||||
|
||||
enum Says
|
||||
{
|
||||
EMOTE_SUMMON = 0, // Not used in script
|
||||
YELL_AGGRO = 1,
|
||||
YELL_FLY_PHASE = 2,
|
||||
YELL_LAND_PHASE = 3,
|
||||
EMOTE_BREATH = 4
|
||||
};
|
||||
|
||||
float IntroWay[8][3] =
|
||||
{
|
||||
{-11053.37f, -1794.48f, 149.00f},
|
||||
{-11141.07f, -1841.40f, 125.00f},
|
||||
{-11187.28f, -1890.23f, 125.00f},
|
||||
{-11189.20f, -1931.25f, 125.00f},
|
||||
{-11153.76f, -1948.93f, 125.00f},
|
||||
{-11128.73f, -1929.75f, 125.00f},
|
||||
{-11140.00f, -1915.00f, 122.00f},
|
||||
{-11163.00f, -1903.00f, 91.473f}
|
||||
};
|
||||
|
||||
class boss_nightbane : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_nightbane() : CreatureScript("boss_nightbane") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new boss_nightbaneAI (creature);
|
||||
}
|
||||
|
||||
struct boss_nightbaneAI : public ScriptedAI
|
||||
{
|
||||
boss_nightbaneAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
Intro = true;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 Phase;
|
||||
|
||||
bool RainBones;
|
||||
bool Skeletons;
|
||||
|
||||
uint32 BellowingRoarTimer;
|
||||
uint32 CharredEarthTimer;
|
||||
uint32 DistractingAshTimer;
|
||||
uint32 SmolderingBreathTimer;
|
||||
uint32 TailSweepTimer;
|
||||
uint32 RainofBonesTimer;
|
||||
uint32 SmokingBlastTimer;
|
||||
uint32 FireballBarrageTimer;
|
||||
uint32 SearingCindersTimer;
|
||||
|
||||
uint32 FlyCount;
|
||||
uint32 FlyTimer;
|
||||
|
||||
bool Intro;
|
||||
bool Flying;
|
||||
bool Movement;
|
||||
|
||||
uint32 MovePhase;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
BellowingRoarTimer = 30000;
|
||||
CharredEarthTimer = 15000;
|
||||
DistractingAshTimer = 20000;
|
||||
SmolderingBreathTimer = 10000;
|
||||
TailSweepTimer = 12000;
|
||||
RainofBonesTimer = 10000;
|
||||
SmokingBlastTimer = 20000;
|
||||
FireballBarrageTimer = 13000;
|
||||
SearingCindersTimer = 14000;
|
||||
|
||||
Phase = 1;
|
||||
FlyCount = 0;
|
||||
MovePhase = 0;
|
||||
|
||||
me->SetSpeed(MOVE_RUN, 2.0f);
|
||||
me->SetDisableGravity(Intro);
|
||||
me->SetWalk(false);
|
||||
me->setActive(true);
|
||||
|
||||
if (instance)
|
||||
{
|
||||
if (instance->GetData(TYPE_NIGHTBANE) == DONE)
|
||||
me->DisappearAndDie();
|
||||
else
|
||||
instance->SetData(TYPE_NIGHTBANE, NOT_STARTED);
|
||||
}
|
||||
|
||||
HandleTerraceDoors(true);
|
||||
|
||||
Flying = false;
|
||||
Movement = false;
|
||||
|
||||
if (!Intro)
|
||||
{
|
||||
me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleTerraceDoors(bool open)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
instance->HandleGameObject(instance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open);
|
||||
instance->HandleGameObject(instance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
if (instance)
|
||||
instance->SetData(TYPE_NIGHTBANE, IN_PROGRESS);
|
||||
|
||||
HandleTerraceDoors(false);
|
||||
Talk(YELL_AGGRO);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who)
|
||||
{
|
||||
if (!Intro && !Flying)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
if (instance)
|
||||
instance->SetData(TYPE_NIGHTBANE, DONE);
|
||||
|
||||
HandleTerraceDoors(true);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who)
|
||||
{
|
||||
if (!Intro && !Flying)
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id)
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (Intro)
|
||||
{
|
||||
if (id >= 8)
|
||||
{
|
||||
Intro = false;
|
||||
me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
MovePhase = id+1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Flying)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
Talk(EMOTE_BREATH);
|
||||
Flying = false;
|
||||
Phase = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id < 8)
|
||||
MovePhase = id+1;
|
||||
else
|
||||
{
|
||||
Phase = 1;
|
||||
Flying = false;
|
||||
Movement = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned)
|
||||
{
|
||||
summoned->AI()->AttackStart(me->GetVictim());
|
||||
}
|
||||
|
||||
void TakeOff()
|
||||
{
|
||||
Talk(YELL_FLY_PHASE);
|
||||
|
||||
me->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SetDisableGravity(true);
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MovePoint(0, IntroWay[2][0], IntroWay[2][1], IntroWay[2][2]);
|
||||
|
||||
Flying = true;
|
||||
|
||||
FlyTimer = urand(45000, 60000); //timer wrong between 45 and 60 seconds
|
||||
++FlyCount;
|
||||
|
||||
RainofBonesTimer = 5000; //timer wrong (maybe)
|
||||
RainBones = false;
|
||||
Skeletons = false;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (Intro)
|
||||
{
|
||||
if (MovePhase)
|
||||
{
|
||||
if (MovePhase >= 7)
|
||||
{
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
|
||||
}
|
||||
MovePhase = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Flying && MovePhase)
|
||||
{
|
||||
if (MovePhase >= 7)
|
||||
{
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
|
||||
}
|
||||
else
|
||||
me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
|
||||
|
||||
MovePhase = 0;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Flying)
|
||||
return;
|
||||
|
||||
// Phase 1 "GROUND FIGHT"
|
||||
if (Phase == 1)
|
||||
{
|
||||
if (Movement)
|
||||
{
|
||||
DoStartMovement(me->GetVictim());
|
||||
Movement = false;
|
||||
}
|
||||
|
||||
if (BellowingRoarTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_BELLOWING_ROAR);
|
||||
BellowingRoarTimer = urand(30000, 40000);
|
||||
} else BellowingRoarTimer -= diff;
|
||||
|
||||
if (SmolderingBreathTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SMOLDERING_BREATH);
|
||||
SmolderingBreathTimer = 20000;
|
||||
} else SmolderingBreathTimer -= diff;
|
||||
|
||||
if (CharredEarthTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_CHARRED_EARTH);
|
||||
CharredEarthTimer = 20000;
|
||||
} else CharredEarthTimer -= diff;
|
||||
|
||||
if (TailSweepTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
if (!me->HasInArc(M_PI, target))
|
||||
DoCast(target, SPELL_TAIL_SWEEP);
|
||||
TailSweepTimer = 15000;
|
||||
} else TailSweepTimer -= diff;
|
||||
|
||||
if (SearingCindersTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_SEARING_CINDERS);
|
||||
SearingCindersTimer = 10000;
|
||||
} else SearingCindersTimer -= diff;
|
||||
|
||||
uint32 Prozent = uint32(me->GetHealthPct());
|
||||
|
||||
if (Prozent < 75 && FlyCount == 0) // first take off 75%
|
||||
TakeOff();
|
||||
|
||||
if (Prozent < 50 && FlyCount == 1) // secound take off 50%
|
||||
TakeOff();
|
||||
|
||||
if (Prozent < 25 && FlyCount == 2) // third take off 25%
|
||||
TakeOff();
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
//Phase 2 "FLYING FIGHT"
|
||||
if (Phase == 2)
|
||||
{
|
||||
if (!RainBones)
|
||||
{
|
||||
if (!Skeletons)
|
||||
{
|
||||
for (uint8 i = 0; i <= 3; ++i)
|
||||
{
|
||||
DoCastVictim(SPELL_SUMMON_SKELETON);
|
||||
Skeletons = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2
|
||||
{
|
||||
DoCastVictim(SPELL_RAIN_OF_BONES);
|
||||
RainBones = true;
|
||||
SmokingBlastTimer = 20000;
|
||||
} else RainofBonesTimer -= diff;
|
||||
|
||||
if (DistractingAshTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_DISTRACTING_ASH);
|
||||
DistractingAshTimer = 2000; //timer wrong
|
||||
} else DistractingAshTimer -= diff;
|
||||
}
|
||||
|
||||
if (RainBones)
|
||||
{
|
||||
if (SmokingBlastTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SMOKING_BLAST);
|
||||
SmokingBlastTimer = 1500; //timer wrong
|
||||
} else SmokingBlastTimer -= diff;
|
||||
}
|
||||
|
||||
if (FireballBarrageTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0))
|
||||
DoCast(target, SPELL_FIREBALL_BARRAGE);
|
||||
FireballBarrageTimer = 20000;
|
||||
} else FireballBarrageTimer -= diff;
|
||||
|
||||
if (FlyTimer <= diff) //landing
|
||||
{
|
||||
Talk(YELL_LAND_PHASE);
|
||||
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]);
|
||||
|
||||
Flying = true;
|
||||
} else FlyTimer -= diff;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
class go_blackened_urn : public GameObjectScript
|
||||
{
|
||||
public:
|
||||
go_blackened_urn() : GameObjectScript("go_blackened_urn") { }
|
||||
|
||||
bool OnGossipHello(Player* pPlayer, GameObject *pGo)
|
||||
{
|
||||
if (InstanceScript* pInstance = pGo->GetInstanceScript())
|
||||
{
|
||||
if (pInstance->GetData(TYPE_NIGHTBANE) != DONE && !pGo->FindNearestCreature(17225, 40.0f))
|
||||
if (Creature *cr = ObjectAccessor::GetCreature(*pPlayer, pInstance->GetData64(DATA_NIGHTBANE)))
|
||||
cr->GetMotionMaster()->MovePoint(0, IntroWay[0][0], IntroWay[0][1], IntroWay[0][2]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_nightbane()
|
||||
{
|
||||
new boss_nightbane();
|
||||
new go_blackened_urn();
|
||||
}
|
||||
@@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Prince_Malchezzar
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
#include "SpellInfo.h"
|
||||
|
||||
// 18 Coordinates for Infernal spawns
|
||||
struct InfernalPoint
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
#define INFERNAL_Z 275.5f
|
||||
|
||||
static InfernalPoint InfernalPoints[] =
|
||||
{
|
||||
{-10922.8f, -1985.2f},
|
||||
{-10916.2f, -1996.2f},
|
||||
{-10932.2f, -2008.1f},
|
||||
{-10948.8f, -2022.1f},
|
||||
{-10958.7f, -1997.7f},
|
||||
{-10971.5f, -1997.5f},
|
||||
{-10990.8f, -1995.1f},
|
||||
{-10989.8f, -1976.5f},
|
||||
{-10971.6f, -1973.0f},
|
||||
{-10955.5f, -1974.0f},
|
||||
{-10939.6f, -1969.8f},
|
||||
{-10958.0f, -1952.2f},
|
||||
{-10941.7f, -1954.8f},
|
||||
{-10943.1f, -1988.5f},
|
||||
{-10948.8f, -2005.1f},
|
||||
{-10984.0f, -2019.3f},
|
||||
{-10932.8f, -1979.6f},
|
||||
{-10935.7f, -1996.0f}
|
||||
};
|
||||
|
||||
//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends
|
||||
//Along with reducing healing and regen while enfeebled to 0%
|
||||
//This spell effect will only reduce healing
|
||||
enum PrinceMalchezaar
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_AXE_TOSS1 = 1,
|
||||
SAY_AXE_TOSS2 = 2,
|
||||
// SAY_SPECIAL1 = 3, Not used, needs to be implemented, but I don't know where it should be used.
|
||||
// SAY_SPECIAL2 = 4, Not used, needs to be implemented, but I don't know where it should be used.
|
||||
// SAY_SPECIAL3 = 5, Not used, needs to be implemented, but I don't know where it should be used.
|
||||
SAY_SLAY = 6,
|
||||
SAY_SUMMON = 7,
|
||||
SAY_DEATH = 8,
|
||||
|
||||
TOTAL_INFERNAL_POINTS = 18,
|
||||
|
||||
SPELL_ENFEEBLE = 30843, //Enfeeble during phase 1 and 2
|
||||
SPELL_ENFEEBLE_EFFECT = 41624,
|
||||
|
||||
SPELL_SHADOWNOVA = 30852, //Shadownova used during all phases
|
||||
SPELL_SW_PAIN = 30854, //Shadow word pain during phase 1 and 3 (different targeting rules though)
|
||||
SPELL_THRASH_PASSIVE = 12787, //Extra attack chance during phase 2
|
||||
SPELL_SUNDER_ARMOR = 30901, //Sunder armor during phase 2
|
||||
SPELL_THRASH_AURA = 12787, //Passive proc chance for thrash
|
||||
SPELL_EQUIP_AXES = 30857, //Visual for axe equiping
|
||||
SPELL_AMPLIFY_DAMAGE = 39095, //Amplifiy during phase 3
|
||||
SPELL_CLEAVE = 30131, //Same as Nightbane.
|
||||
SPELL_HELLFIRE = 30859, //Infenals' hellfire aura
|
||||
NETHERSPITE_INFERNAL = 17646, //The netherspite infernal creature
|
||||
MALCHEZARS_AXE = 17650, //Malchezar's axes (creatures), summoned during phase 3
|
||||
|
||||
INFERNAL_MODEL_INVISIBLE = 11686, //Infernal Effects
|
||||
SPELL_INFERNAL_RELAY = 30834,
|
||||
|
||||
EQUIP_ID_AXE = 33542 //Axes info
|
||||
};
|
||||
|
||||
//---------Infernal code first
|
||||
class netherspite_infernal : public CreatureScript
|
||||
{
|
||||
public:
|
||||
netherspite_infernal() : CreatureScript("netherspite_infernal") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new netherspite_infernalAI(creature);
|
||||
}
|
||||
|
||||
struct netherspite_infernalAI : public ScriptedAI
|
||||
{
|
||||
netherspite_infernalAI(Creature* creature) : ScriptedAI(creature),
|
||||
HellfireTimer(0), CleanupTimer(0), malchezaar(0), point(NULL) { }
|
||||
|
||||
uint32 HellfireTimer;
|
||||
uint32 CleanupTimer;
|
||||
uint64 malchezaar;
|
||||
InfernalPoint *point;
|
||||
|
||||
void Reset() { }
|
||||
void EnterCombat(Unit* /*who*/) { }
|
||||
void MoveInLineOfSight(Unit* /*who*/) { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (HellfireTimer)
|
||||
{
|
||||
if (HellfireTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_HELLFIRE);
|
||||
HellfireTimer = 0;
|
||||
}
|
||||
else HellfireTimer -= diff;
|
||||
}
|
||||
|
||||
if (CleanupTimer)
|
||||
{
|
||||
if (CleanupTimer <= diff)
|
||||
{
|
||||
Cleanup();
|
||||
CleanupTimer = 0;
|
||||
} else CleanupTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* who)
|
||||
{
|
||||
if (Unit* unit = ObjectAccessor::GetUnit(*me, malchezaar))
|
||||
if (Creature* creature = unit->ToCreature())
|
||||
creature->AI()->KilledUnit(who);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*who*/, const SpellInfo* spell)
|
||||
{
|
||||
if (spell->Id == SPELL_INFERNAL_RELAY)
|
||||
{
|
||||
me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID));
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
HellfireTimer = 4000;
|
||||
CleanupTimer = 170000;
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* done_by, uint32 &damage, DamageEffectType, SpellSchoolMask)
|
||||
{
|
||||
if (!done_by || done_by->GetGUID() != malchezaar)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void Cleanup();
|
||||
};
|
||||
};
|
||||
|
||||
class boss_malchezaar : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_malchezaar() : CreatureScript("boss_malchezaar") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_malchezaarAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_malchezaarAI : public ScriptedAI
|
||||
{
|
||||
boss_malchezaarAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
memset(axes, 0, sizeof(axes));
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
uint32 EnfeebleTimer;
|
||||
uint32 EnfeebleResetTimer;
|
||||
uint32 ShadowNovaTimer;
|
||||
uint32 SWPainTimer;
|
||||
uint32 SunderArmorTimer;
|
||||
uint32 AmplifyDamageTimer;
|
||||
uint32 Cleave_Timer;
|
||||
uint32 InfernalTimer;
|
||||
uint32 AxesTargetSwitchTimer;
|
||||
uint32 InfernalCleanupTimer;
|
||||
|
||||
std::vector<uint64> infernals;
|
||||
std::vector<InfernalPoint*> positions;
|
||||
|
||||
uint64 axes[2];
|
||||
uint64 enfeeble_targets[5];
|
||||
uint32 enfeeble_health[5];
|
||||
|
||||
uint32 phase;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
AxesCleanup();
|
||||
ClearWeapons();
|
||||
InfernalCleanup();
|
||||
positions.clear();
|
||||
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
enfeeble_targets[i] = 0;
|
||||
enfeeble_health[i] = 0;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
|
||||
positions.push_back(&InfernalPoints[i]);
|
||||
|
||||
EnfeebleTimer = 30000;
|
||||
EnfeebleResetTimer = 38000;
|
||||
ShadowNovaTimer = 35500;
|
||||
SWPainTimer = 20000;
|
||||
AmplifyDamageTimer = 5000;
|
||||
Cleave_Timer = 8000;
|
||||
InfernalTimer = 40000;
|
||||
InfernalCleanupTimer = 47000;
|
||||
AxesTargetSwitchTimer = urand(7500, 20000);
|
||||
SunderArmorTimer = urand(5000, 10000);
|
||||
phase = 1;
|
||||
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_NETHER_DOOR), true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
AxesCleanup();
|
||||
ClearWeapons();
|
||||
InfernalCleanup();
|
||||
positions.clear();
|
||||
|
||||
for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
|
||||
positions.push_back(&InfernalPoints[i]);
|
||||
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_NETHER_DOOR), true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in
|
||||
}
|
||||
|
||||
void InfernalCleanup()
|
||||
{
|
||||
//Infernal Cleanup
|
||||
for (std::vector<uint64>::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr)
|
||||
if (Unit* pInfernal = ObjectAccessor::GetUnit(*me, *itr))
|
||||
if (pInfernal->IsAlive())
|
||||
{
|
||||
pInfernal->SetVisible(false);
|
||||
pInfernal->setDeathState(JUST_DIED);
|
||||
}
|
||||
|
||||
infernals.clear();
|
||||
}
|
||||
|
||||
void AxesCleanup()
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
Unit* axe = ObjectAccessor::GetUnit(*me, axes[i]);
|
||||
if (axe && axe->IsAlive())
|
||||
Unit::Kill(axe, axe);
|
||||
axes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearWeapons()
|
||||
{
|
||||
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
|
||||
me->SetCanDualWield(false);
|
||||
}
|
||||
|
||||
void EnfeebleHealthEffect()
|
||||
{
|
||||
const SpellInfo* info = sSpellMgr->GetSpellInfo(SPELL_ENFEEBLE_EFFECT);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
|
||||
std::vector<Unit*> targets;
|
||||
|
||||
if (t_list.empty())
|
||||
return;
|
||||
|
||||
//begin + 1, so we don't target the one with the highest threat
|
||||
ThreatContainer::StorageType::const_iterator itr = t_list.begin();
|
||||
std::advance(itr, 1);
|
||||
for (; itr != t_list.end(); ++itr) //store the threat list in a different container
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
if (target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targets.push_back(target);
|
||||
|
||||
//cut down to size if we have more than 5 targets
|
||||
while (targets.size() > 5)
|
||||
targets.erase(targets.begin()+rand()%targets.size());
|
||||
|
||||
uint32 i = 0;
|
||||
for (std::vector<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i)
|
||||
if (Unit* target = *iter)
|
||||
{
|
||||
enfeeble_targets[i] = target->GetGUID();
|
||||
enfeeble_health[i] = target->GetHealth();
|
||||
|
||||
target->CastSpell(target, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID());
|
||||
target->SetHealth(1);
|
||||
}
|
||||
}
|
||||
|
||||
void EnfeebleResetHealth()
|
||||
{
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, enfeeble_targets[i]);
|
||||
if (target && target->IsAlive())
|
||||
target->SetHealth(enfeeble_health[i]);
|
||||
enfeeble_targets[i] = 0;
|
||||
enfeeble_health[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SummonInfernal(const uint32 /*diff*/)
|
||||
{
|
||||
InfernalPoint *point = NULL;
|
||||
Position pos;
|
||||
if ((me->GetMapId() != 532) || positions.empty())
|
||||
me->GetRandomNearPosition(pos, 60);
|
||||
else
|
||||
{
|
||||
point = Trinity::Containers::SelectRandomContainerElement(positions);
|
||||
pos.Relocate(point->x, point->y, INFERNAL_Z, frand(0.0f, float(M_PI * 2)));
|
||||
}
|
||||
|
||||
Creature* infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000);
|
||||
|
||||
if (infernal)
|
||||
{
|
||||
infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE);
|
||||
infernal->setFaction(me->getFaction());
|
||||
if (point)
|
||||
CAST_AI(netherspite_infernal::netherspite_infernalAI, infernal->AI())->point=point;
|
||||
CAST_AI(netherspite_infernal::netherspite_infernalAI, infernal->AI())->malchezaar=me->GetGUID();
|
||||
|
||||
infernals.push_back(infernal->GetGUID());
|
||||
DoCast(infernal, SPELL_INFERNAL_RELAY);
|
||||
}
|
||||
|
||||
Talk(SAY_SUMMON);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that
|
||||
{
|
||||
EnfeebleResetHealth();
|
||||
EnfeebleResetTimer = 0;
|
||||
} else EnfeebleResetTimer -= diff;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_STUNNED)) // While shifting to phase 2 malchezaar stuns himself
|
||||
return;
|
||||
|
||||
if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->GetVictim()->GetGUID())
|
||||
me->SetTarget(me->GetVictim()->GetGUID());
|
||||
|
||||
if (phase == 1)
|
||||
{
|
||||
if (HealthBelowPct(60))
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
phase = 2;
|
||||
|
||||
//animation
|
||||
DoCast(me, SPELL_EQUIP_AXES);
|
||||
|
||||
//text
|
||||
Talk(SAY_AXE_TOSS1);
|
||||
|
||||
//passive thrash aura
|
||||
DoCast(me, SPELL_THRASH_AURA, true);
|
||||
|
||||
//models
|
||||
SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
|
||||
|
||||
me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100);
|
||||
me->SetCanDualWield(true);
|
||||
}
|
||||
}
|
||||
else if (phase == 2)
|
||||
{
|
||||
if (HealthBelowPct(30))
|
||||
{
|
||||
InfernalTimer = 15000;
|
||||
|
||||
phase = 3;
|
||||
|
||||
ClearWeapons();
|
||||
|
||||
//remove thrash
|
||||
me->RemoveAurasDueToSpell(SPELL_THRASH_AURA);
|
||||
|
||||
Talk(SAY_AXE_TOSS2);
|
||||
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
Creature* axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
|
||||
if (axe)
|
||||
{
|
||||
axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
axe->setFaction(me->getFaction());
|
||||
axes[i] = axe->GetGUID();
|
||||
if (target)
|
||||
{
|
||||
axe->AI()->AttackStart(target);
|
||||
//axe->getThreatManager().tauntApply(target); //Taunt Apply and fade out does not work properly
|
||||
// So we'll use a hack to add a lot of threat to our target
|
||||
axe->AddThreat(target, 10000000.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ShadowNovaTimer > 35000)
|
||||
ShadowNovaTimer = EnfeebleTimer + 5000;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (SunderArmorTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SUNDER_ARMOR);
|
||||
SunderArmorTimer = urand(10000, 18000);
|
||||
} else SunderArmorTimer -= diff;
|
||||
|
||||
if (Cleave_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
Cleave_Timer = urand(6000, 12000);
|
||||
} else Cleave_Timer -= diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AxesTargetSwitchTimer <= diff)
|
||||
{
|
||||
AxesTargetSwitchTimer = urand(7500, 20000);
|
||||
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (Unit* axe = ObjectAccessor::GetUnit(*me, axes[i]))
|
||||
{
|
||||
if (axe->GetVictim())
|
||||
DoModifyThreatPercent(axe->GetVictim(), -100);
|
||||
if (target)
|
||||
axe->AddThreat(target, 1000000.0f);
|
||||
//axe->getThreatManager().tauntFadeOut(axe->GetVictim());
|
||||
//axe->getThreatManager().tauntApply(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else AxesTargetSwitchTimer -= diff;
|
||||
|
||||
if (AmplifyDamageTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_AMPLIFY_DAMAGE);
|
||||
AmplifyDamageTimer = urand(20000, 30000);
|
||||
} else AmplifyDamageTimer -= diff;
|
||||
}
|
||||
|
||||
//Time for global and double timers
|
||||
if (InfernalTimer <= diff)
|
||||
{
|
||||
SummonInfernal(diff);
|
||||
InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise
|
||||
} else InfernalTimer -= diff;
|
||||
|
||||
if (ShadowNovaTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOWNOVA);
|
||||
ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1);
|
||||
} else ShadowNovaTimer -= diff;
|
||||
|
||||
if (phase != 2)
|
||||
{
|
||||
if (SWPainTimer <= diff)
|
||||
{
|
||||
Unit* target = NULL;
|
||||
if (phase == 1)
|
||||
target = me->GetVictim(); // the tank
|
||||
else // anyone but the tank
|
||||
target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
|
||||
|
||||
if (target)
|
||||
DoCast(target, SPELL_SW_PAIN);
|
||||
|
||||
SWPainTimer = 20000;
|
||||
} else SWPainTimer -= diff;
|
||||
}
|
||||
|
||||
if (phase != 3)
|
||||
{
|
||||
if (EnfeebleTimer <= diff)
|
||||
{
|
||||
EnfeebleHealthEffect();
|
||||
EnfeebleTimer = 30000;
|
||||
ShadowNovaTimer = 5000;
|
||||
EnfeebleResetTimer = 9000;
|
||||
} else EnfeebleTimer -= diff;
|
||||
}
|
||||
|
||||
if (phase == 2)
|
||||
DoMeleeAttacksIfReady();
|
||||
else
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void DoMeleeAttacksIfReady()
|
||||
{
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()) && !me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
//Check for base attack
|
||||
if (me->isAttackReady() && me->GetVictim())
|
||||
{
|
||||
me->AttackerStateUpdate(me->GetVictim());
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
//Check for offhand attack
|
||||
if (me->isAttackReady(OFF_ATTACK) && me->GetVictim())
|
||||
{
|
||||
me->AttackerStateUpdate(me->GetVictim(), OFF_ATTACK);
|
||||
me->resetAttackTimer(OFF_ATTACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cleanup(Creature* infernal, InfernalPoint *point)
|
||||
{
|
||||
for (std::vector<uint64>::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr)
|
||||
if (*itr == infernal->GetGUID())
|
||||
{
|
||||
infernals.erase(itr);
|
||||
break;
|
||||
}
|
||||
|
||||
positions.push_back(point);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void netherspite_infernal::netherspite_infernalAI::Cleanup()
|
||||
{
|
||||
Creature* pMalchezaar = ObjectAccessor::GetCreature(*me, malchezaar);
|
||||
|
||||
if (pMalchezaar && pMalchezaar->IsAlive())
|
||||
CAST_AI(boss_malchezaar::boss_malchezaarAI, pMalchezaar->AI())->Cleanup(me, point);
|
||||
}
|
||||
|
||||
void AddSC_boss_malchezaar()
|
||||
{
|
||||
new boss_malchezaar();
|
||||
new netherspite_infernal();
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum ServantQuartersSpells
|
||||
{
|
||||
SPELL_SNEAK = 22766,
|
||||
SPELL_ACIDIC_FANG = 29901,
|
||||
SPELL_HYAKISS_WEB = 29896,
|
||||
|
||||
SPELL_DIVE = 29903,
|
||||
SPELL_SONIC_BURST = 29904,
|
||||
SPELL_WING_BUFFET = 29905,
|
||||
SPELL_FEAR = 29321,
|
||||
|
||||
SPELL_RAVAGE = 29906
|
||||
};
|
||||
|
||||
enum ServantQuertersMisc
|
||||
{
|
||||
EVENT_SPELL_ACIDIC_FANG = 1,
|
||||
EVENT_SPELL_HYAKISS_WEB = 2,
|
||||
|
||||
EVENT_SPELL_DIVE = 10,
|
||||
EVENT_SPELL_SONIC_BURST = 11,
|
||||
EVENT_SPELL_WING_BUFFET = 12,
|
||||
EVENT_SPELL_FEAR = 13,
|
||||
|
||||
EVENT_SPELL_RAVAGE = 20,
|
||||
|
||||
EVENT_CHECK_VISIBILITY = 30
|
||||
};
|
||||
|
||||
class boss_servant_quarters : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_servant_quarters() : CreatureScript("boss_servant_quarters") { }
|
||||
|
||||
struct boss_servant_quartersAI : public BossAI
|
||||
{
|
||||
boss_servant_quartersAI(Creature* creature) : BossAI(creature, TYPE_SERVANT_QUARTERS) { }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
events.Reset();
|
||||
me->SetVisible(false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->setFaction(35);
|
||||
_events2.Reset();
|
||||
_events2.ScheduleEvent(EVENT_CHECK_VISIBILITY, 5000);
|
||||
if (me->GetEntry() == NPC_HYAKISS_THE_LURKER)
|
||||
me->CastSpell(me, SPELL_SNEAK, true);
|
||||
|
||||
if (instance->GetData(DATA_SELECTED_RARE) != me->GetEntry())
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who)
|
||||
{
|
||||
me->setActive(true);
|
||||
if (me->GetEntry() == NPC_HYAKISS_THE_LURKER)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_ACIDIC_FANG, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_HYAKISS_WEB, 9000);
|
||||
}
|
||||
else if (me->GetEntry() == NPC_SHADIKITH_THE_GLIDER)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_SONIC_BURST, 4000);
|
||||
events.ScheduleEvent(EVENT_SPELL_WING_BUFFET, 7000);
|
||||
events.ScheduleEvent(EVENT_SPELL_DIVE, 10000);
|
||||
}
|
||||
else // if (me->GetEntry() == NPC_ROKAD_THE_RAVAGER)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_RAVAGE, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*who*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 point)
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && point == EVENT_CHARGE)
|
||||
events.ScheduleEvent(EVENT_SPELL_FEAR, 0);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
_events2.Update(diff);
|
||||
switch (_events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_VISIBILITY:
|
||||
if (instance->GetBossState(TYPE_SERVANT_QUARTERS) == DONE)
|
||||
{
|
||||
me->SetVisible(true);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RestoreFaction();
|
||||
}
|
||||
else
|
||||
_events2.ScheduleEvent(EVENT_CHECK_VISIBILITY, 5000);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_ACIDIC_FANG:
|
||||
me->CastSpell(me->GetVictim(), SPELL_ACIDIC_FANG, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_ACIDIC_FANG, urand(12000, 18000));
|
||||
break;
|
||||
case EVENT_SPELL_HYAKISS_WEB:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f))
|
||||
me->CastSpell(target, SPELL_HYAKISS_WEB, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_HYAKISS_WEB, 15000);
|
||||
break;
|
||||
case EVENT_SPELL_SONIC_BURST:
|
||||
me->CastSpell(me, SPELL_SONIC_BURST, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_SONIC_BURST, urand(12000, 18000));
|
||||
break;
|
||||
case EVENT_SPELL_WING_BUFFET:
|
||||
me->CastSpell(me, SPELL_WING_BUFFET, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_WING_BUFFET, urand(12000, 18000));
|
||||
break;
|
||||
case EVENT_SPELL_DIVE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, FarthestTargetSelector(me, 40.0f, false, true)))
|
||||
me->CastSpell(target, SPELL_DIVE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_DIVE, 20000);
|
||||
break;
|
||||
case EVENT_SPELL_FEAR:
|
||||
me->CastSpell(me->GetVictim(), SPELL_FEAR, false);
|
||||
break;
|
||||
case EVENT_SPELL_RAVAGE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_RAVAGE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_RAVAGE, 10500);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events2;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_servant_quartersAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_servant_quarters()
|
||||
{
|
||||
new boss_servant_quarters();
|
||||
}
|
||||
@@ -1,514 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
#include "GameObject.h"
|
||||
#include "SpellInfo.h"
|
||||
|
||||
enum ShadeOfAran
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_FLAMEWREATH = 1,
|
||||
SAY_BLIZZARD = 2,
|
||||
SAY_EXPLOSION = 3,
|
||||
SAY_DRINK = 4,
|
||||
SAY_ELEMENTALS = 5,
|
||||
SAY_KILL = 6,
|
||||
SAY_TIMEOVER = 7,
|
||||
SAY_DEATH = 8,
|
||||
|
||||
//Spells
|
||||
SPELL_FROSTBOLT = 29954,
|
||||
SPELL_FIREBALL = 29953,
|
||||
SPELL_ARCMISSLE = 29955,
|
||||
SPELL_CHAINSOFICE = 29991,
|
||||
SPELL_DRAGONSBREATH = 29964,
|
||||
SPELL_MASSSLOW = 30035,
|
||||
SPELL_FLAME_WREATH = 29946,
|
||||
SPELL_AOE_CS = 29961,
|
||||
SPELL_PLAYERPULL = 32265,
|
||||
SPELL_AEXPLOSION = 29973,
|
||||
SPELL_MASS_POLY = 29963,
|
||||
SPELL_BLINK_CENTER = 29967,
|
||||
SPELL_ELEMENTALS = 29962,
|
||||
SPELL_CONJURE = 29975,
|
||||
SPELL_DRINK = 30024,
|
||||
SPELL_POTION = 32453,
|
||||
SPELL_AOE_PYROBLAST = 29978,
|
||||
|
||||
//Creature Spells
|
||||
SPELL_CIRCULAR_BLIZZARD = 29951,
|
||||
SPELL_WATERBOLT = 31012,
|
||||
SPELL_SHADOW_PYRO = 29978,
|
||||
|
||||
//Creatures
|
||||
CREATURE_WATER_ELEMENTAL = 17167,
|
||||
CREATURE_SHADOW_OF_ARAN = 18254,
|
||||
CREATURE_ARAN_BLIZZARD = 17161,
|
||||
};
|
||||
|
||||
enum SuperSpell
|
||||
{
|
||||
SUPER_FLAME = 0,
|
||||
SUPER_BLIZZARD,
|
||||
SUPER_AE,
|
||||
};
|
||||
|
||||
class boss_shade_of_aran : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_shade_of_aran() : CreatureScript("boss_shade_of_aran") { }
|
||||
|
||||
struct boss_aranAI : public BossAI
|
||||
{
|
||||
boss_aranAI(Creature* creature) : BossAI(creature, TYPE_ARAN)
|
||||
{
|
||||
}
|
||||
|
||||
uint32 SecondarySpellTimer;
|
||||
uint32 NormalCastTimer;
|
||||
uint32 SuperCastTimer;
|
||||
uint32 BerserkTimer;
|
||||
uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering.
|
||||
|
||||
uint8 LastSuperSpell;
|
||||
|
||||
uint32 FlameWreathTimer;
|
||||
uint32 FlameWreathCheckTime;
|
||||
uint64 FlameWreathTarget[3];
|
||||
float FWTargPosX[3];
|
||||
float FWTargPosY[3];
|
||||
|
||||
uint32 CurrentNormalSpell;
|
||||
uint32 ArcaneCooldown;
|
||||
uint32 FireCooldown;
|
||||
uint32 FrostCooldown;
|
||||
|
||||
uint32 DrinkInterruptTimer;
|
||||
|
||||
bool ElementalsSpawned;
|
||||
bool Drinking;
|
||||
bool DrinkInturrupted;
|
||||
void Reset()
|
||||
{
|
||||
SecondarySpellTimer = 5000;
|
||||
NormalCastTimer = 0;
|
||||
SuperCastTimer = 35000;
|
||||
BerserkTimer = 720000;
|
||||
CloseDoorTimer = 15000;
|
||||
|
||||
LastSuperSpell = rand()%3;
|
||||
|
||||
FlameWreathTimer = 0;
|
||||
FlameWreathCheckTime = 0;
|
||||
|
||||
CurrentNormalSpell = 0;
|
||||
ArcaneCooldown = 0;
|
||||
FireCooldown = 0;
|
||||
FrostCooldown = 0;
|
||||
|
||||
DrinkInterruptTimer = 10000;
|
||||
|
||||
ElementalsSpawned = false;
|
||||
Drinking = false;
|
||||
DrinkInturrupted = false;
|
||||
|
||||
// Not in progress
|
||||
instance->SetData(TYPE_ARAN, NOT_STARTED);
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_LIBRARY_DOOR), true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->SetData(TYPE_ARAN, DONE);
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_LIBRARY_DOOR), true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
instance->SetData(TYPE_ARAN, IN_PROGRESS);
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_LIBRARY_DOOR), false);
|
||||
}
|
||||
|
||||
void FlameWreathEffect()
|
||||
{
|
||||
std::vector<Unit*> targets;
|
||||
ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
|
||||
|
||||
if (t_list.empty())
|
||||
return;
|
||||
|
||||
//store the threat list in a different container
|
||||
for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
//only on alive players
|
||||
if (target && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
//cut down to size if we have more than 3 targets
|
||||
while (targets.size() > 3)
|
||||
targets.erase(targets.begin()+rand()%targets.size());
|
||||
|
||||
uint32 i = 0;
|
||||
for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr)
|
||||
{
|
||||
if (*itr)
|
||||
{
|
||||
FlameWreathTarget[i] = (*itr)->GetGUID();
|
||||
FWTargPosX[i] = (*itr)->GetPositionX();
|
||||
FWTargPosY[i] = (*itr)->GetPositionY();
|
||||
DoCast((*itr), SPELL_FLAME_WREATH, true);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (CloseDoorTimer)
|
||||
{
|
||||
if (CloseDoorTimer <= diff)
|
||||
{
|
||||
instance->HandleGameObject(instance->GetData64(DATA_GO_LIBRARY_DOOR), false);
|
||||
CloseDoorTimer = 0;
|
||||
} else CloseDoorTimer -= diff;
|
||||
}
|
||||
|
||||
//Cooldowns for casts
|
||||
if (ArcaneCooldown)
|
||||
{
|
||||
if (ArcaneCooldown >= diff)
|
||||
ArcaneCooldown -= diff;
|
||||
else ArcaneCooldown = 0;
|
||||
}
|
||||
|
||||
if (FireCooldown)
|
||||
{
|
||||
if (FireCooldown >= diff)
|
||||
FireCooldown -= diff;
|
||||
else FireCooldown = 0;
|
||||
}
|
||||
|
||||
if (FrostCooldown)
|
||||
{
|
||||
if (FrostCooldown >= diff)
|
||||
FrostCooldown -= diff;
|
||||
else FrostCooldown = 0;
|
||||
}
|
||||
|
||||
if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20)
|
||||
{
|
||||
Drinking = true;
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
Talk(SAY_DRINK);
|
||||
|
||||
if (!DrinkInturrupted)
|
||||
{
|
||||
DoCast(me, SPELL_MASS_POLY, true);
|
||||
DoCast(me, SPELL_CONJURE, false);
|
||||
DoCast(me, SPELL_DRINK, false);
|
||||
me->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
DrinkInterruptTimer = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
//Drink Interrupt
|
||||
if (Drinking && DrinkInturrupted)
|
||||
{
|
||||
Drinking = false;
|
||||
me->RemoveAurasDueToSpell(SPELL_DRINK);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000);
|
||||
DoCast(me, SPELL_POTION, false);
|
||||
}
|
||||
|
||||
//Drink Interrupt Timer
|
||||
if (Drinking && !DrinkInturrupted)
|
||||
{
|
||||
if (DrinkInterruptTimer >= diff)
|
||||
DrinkInterruptTimer -= diff;
|
||||
else
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
DoCast(me, SPELL_POTION, true);
|
||||
DoCast(me, SPELL_AOE_PYROBLAST, false);
|
||||
DrinkInturrupted = true;
|
||||
Drinking = false;
|
||||
}
|
||||
}
|
||||
|
||||
//Don't execute any more code if we are drinking
|
||||
if (Drinking)
|
||||
return;
|
||||
|
||||
//Normal casts
|
||||
if (NormalCastTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
uint32 Spells[3];
|
||||
uint8 AvailableSpells = 0;
|
||||
|
||||
//Check for what spells are not on cooldown
|
||||
if (!ArcaneCooldown)
|
||||
{
|
||||
Spells[AvailableSpells] = SPELL_ARCMISSLE;
|
||||
++AvailableSpells;
|
||||
}
|
||||
if (!FireCooldown)
|
||||
{
|
||||
Spells[AvailableSpells] = SPELL_FIREBALL;
|
||||
++AvailableSpells;
|
||||
}
|
||||
if (!FrostCooldown)
|
||||
{
|
||||
Spells[AvailableSpells] = SPELL_FROSTBOLT;
|
||||
++AvailableSpells;
|
||||
}
|
||||
|
||||
//If no available spells wait 1 second and try again
|
||||
if (AvailableSpells)
|
||||
{
|
||||
CurrentNormalSpell = Spells[rand() % AvailableSpells];
|
||||
DoCast(target, CurrentNormalSpell);
|
||||
}
|
||||
}
|
||||
NormalCastTimer = 1000;
|
||||
} else NormalCastTimer -= diff;
|
||||
|
||||
if (SecondarySpellTimer <= diff)
|
||||
{
|
||||
switch (urand(0, 1))
|
||||
{
|
||||
case 0:
|
||||
DoCast(me, SPELL_AOE_CS);
|
||||
break;
|
||||
case 1:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_CHAINSOFICE);
|
||||
break;
|
||||
}
|
||||
SecondarySpellTimer = urand(5000, 20000);
|
||||
} else SecondarySpellTimer -= diff;
|
||||
|
||||
if (SuperCastTimer <= diff)
|
||||
{
|
||||
uint8 Available[2];
|
||||
|
||||
switch (LastSuperSpell)
|
||||
{
|
||||
case SUPER_AE:
|
||||
Available[0] = SUPER_FLAME;
|
||||
Available[1] = SUPER_BLIZZARD;
|
||||
break;
|
||||
case SUPER_FLAME:
|
||||
Available[0] = SUPER_AE;
|
||||
Available[1] = SUPER_BLIZZARD;
|
||||
break;
|
||||
case SUPER_BLIZZARD:
|
||||
Available[0] = SUPER_FLAME;
|
||||
Available[1] = SUPER_AE;
|
||||
break;
|
||||
}
|
||||
|
||||
LastSuperSpell = Available[urand(0, 1)];
|
||||
|
||||
switch (LastSuperSpell)
|
||||
{
|
||||
case SUPER_AE:
|
||||
Talk(SAY_EXPLOSION);
|
||||
|
||||
DoCast(me, SPELL_BLINK_CENTER, true);
|
||||
DoCast(me, SPELL_PLAYERPULL, true);
|
||||
DoCast(me, SPELL_MASSSLOW, true);
|
||||
DoCast(me, SPELL_AEXPLOSION, false);
|
||||
break;
|
||||
|
||||
case SUPER_FLAME:
|
||||
Talk(SAY_FLAMEWREATH);
|
||||
|
||||
FlameWreathTimer = 20000;
|
||||
FlameWreathCheckTime = 500;
|
||||
|
||||
FlameWreathTarget[0] = 0;
|
||||
FlameWreathTarget[1] = 0;
|
||||
FlameWreathTarget[2] = 0;
|
||||
|
||||
FlameWreathEffect();
|
||||
break;
|
||||
|
||||
case SUPER_BLIZZARD:
|
||||
Talk(SAY_BLIZZARD);
|
||||
|
||||
if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000))
|
||||
{
|
||||
pSpawn->setFaction(me->getFaction());
|
||||
pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
SuperCastTimer = urand(35000, 40000);
|
||||
} else SuperCastTimer -= diff;
|
||||
|
||||
if (!ElementalsSpawned && HealthBelowPct(40))
|
||||
{
|
||||
ElementalsSpawned = true;
|
||||
|
||||
for (uint32 i = 0; i < 4; ++i)
|
||||
{
|
||||
if (Creature* unit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000))
|
||||
{
|
||||
unit->Attack(me->GetVictim(), true);
|
||||
unit->setFaction(me->getFaction());
|
||||
}
|
||||
}
|
||||
|
||||
Talk(SAY_ELEMENTALS);
|
||||
}
|
||||
|
||||
if (BerserkTimer <= diff)
|
||||
{
|
||||
for (uint32 i = 0; i < 5; ++i)
|
||||
{
|
||||
if (Creature* unit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
|
||||
{
|
||||
unit->Attack(me->GetVictim(), true);
|
||||
unit->setFaction(me->getFaction());
|
||||
}
|
||||
}
|
||||
|
||||
Talk(SAY_TIMEOVER);
|
||||
|
||||
BerserkTimer = 60000;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
//Flame Wreath check
|
||||
if (FlameWreathTimer)
|
||||
{
|
||||
if (FlameWreathTimer >= diff)
|
||||
FlameWreathTimer -= diff;
|
||||
else FlameWreathTimer = 0;
|
||||
|
||||
if (FlameWreathCheckTime <= diff)
|
||||
{
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
{
|
||||
if (!FlameWreathTarget[i])
|
||||
continue;
|
||||
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, FlameWreathTarget[i]);
|
||||
if (unit && !unit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
|
||||
{
|
||||
unit->CastSpell(unit, 20476, true, 0, 0, me->GetGUID());
|
||||
unit->CastSpell(unit, 11027, true);
|
||||
FlameWreathTarget[i] = 0;
|
||||
}
|
||||
}
|
||||
FlameWreathCheckTime = 500;
|
||||
} else FlameWreathCheckTime -= diff;
|
||||
}
|
||||
|
||||
if (ArcaneCooldown && FireCooldown && FrostCooldown)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
|
||||
{
|
||||
if (!DrinkInturrupted && Drinking && damage)
|
||||
DrinkInturrupted = true;
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*pAttacker*/, const SpellInfo* Spell)
|
||||
{
|
||||
//We only care about interrupt effects and only if they are durring a spell currently being cast
|
||||
if ((Spell->Effects[0].Effect != SPELL_EFFECT_INTERRUPT_CAST &&
|
||||
Spell->Effects[1].Effect != SPELL_EFFECT_INTERRUPT_CAST &&
|
||||
Spell->Effects[2].Effect != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false))
|
||||
return;
|
||||
|
||||
//Interrupt effect
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
//Normally we would set the cooldown equal to the spell duration
|
||||
//but we do not have access to the DurationStore
|
||||
|
||||
switch (CurrentNormalSpell)
|
||||
{
|
||||
case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break;
|
||||
case SPELL_FIREBALL: FireCooldown = 5000; break;
|
||||
case SPELL_FROSTBOLT: FrostCooldown = 5000; break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_aranAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_aran_elemental : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_aran_elemental() : CreatureScript("npc_aran_elemental") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new water_elementalAI(creature);
|
||||
}
|
||||
|
||||
struct water_elementalAI : public ScriptedAI
|
||||
{
|
||||
water_elementalAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
uint32 CastTimer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
CastTimer = 2000 + (rand()%3000);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) { }
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (CastTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_WATERBOLT);
|
||||
CastTimer = urand(2000, 5000);
|
||||
} else CastTimer -= diff;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_shade_of_aran()
|
||||
{
|
||||
new boss_shade_of_aran();
|
||||
new npc_aran_elemental();
|
||||
}
|
||||
@@ -1,426 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Terestian_Illhoof
|
||||
SD%Complete: 95
|
||||
SDComment: Complete! Needs adjustments to use spell though.
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "karazhan.h"
|
||||
#include "PassiveAI.h"
|
||||
|
||||
enum TerestianIllhoof
|
||||
{
|
||||
SAY_SLAY = 1,
|
||||
SAY_DEATH = 2,
|
||||
SAY_AGGRO = 3,
|
||||
SAY_SACRIFICE = 4,
|
||||
SAY_SUMMON = 5
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SUMMON_DEMONCHAINS = 30120, // Summons demonic chains that maintain the ritual of sacrifice.
|
||||
SPELL_DEMON_CHAINS = 30206, // Instant - Visual Effect
|
||||
SPELL_ENRAGE = 23537, // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min.
|
||||
SPELL_SHADOW_BOLT = 30055, // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage.
|
||||
SPELL_SACRIFICE = 30115, // Teleports and adds the debuff
|
||||
SPELL_BERSERK = 32965, // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley.
|
||||
SPELL_SUMMON_FIENDISIMP = 30184, // Summons a Fiendish Imp.
|
||||
SPELL_SUMMON_IMP = 30066, // Summons Kil'rek
|
||||
|
||||
SPELL_FIENDISH_PORTAL = 30171, // Opens portal and summons Fiendish Portal, 2 sec cast
|
||||
SPELL_FIENDISH_PORTAL_1 = 30179, // Opens portal and summons Fiendish Portal, instant cast
|
||||
|
||||
SPELL_FIREBOLT = 30050, // Blasts a target for 150 Fire damage.
|
||||
SPELL_BROKEN_PACT = 30065, // All damage taken increased by 25%.
|
||||
SPELL_AMPLIFY_FLAMES = 30053, // Increases the Fire damage taken by an enemy by 500 for 25 sec.
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_DEMONCHAINS = 17248,
|
||||
NPC_FIENDISHIMP = 17267,
|
||||
NPC_PORTAL = 17265,
|
||||
NPC_KILREK = 17229
|
||||
};
|
||||
|
||||
|
||||
class npc_kilrek : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_kilrek() : CreatureScript("npc_kilrek") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<npc_kilrekAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_kilrekAI : public ScriptedAI
|
||||
{
|
||||
npc_kilrekAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint64 TerestianGUID;
|
||||
|
||||
uint32 AmplifyTimer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
TerestianGUID = 0;
|
||||
AmplifyTimer = 2000;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
uint64 TerestianGUID = instance->GetData64(DATA_TERESTIAN);
|
||||
if (TerestianGUID)
|
||||
{
|
||||
Unit* Terestian = ObjectAccessor::GetUnit(*me, TerestianGUID);
|
||||
if (Terestian && Terestian->IsAlive())
|
||||
DoCast(Terestian, SPELL_BROKEN_PACT, true);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (AmplifyTimer <= diff)
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCastVictim(SPELL_AMPLIFY_FLAMES);
|
||||
|
||||
AmplifyTimer = urand(10000, 20000);
|
||||
} else AmplifyTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class npc_demon_chain : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_demon_chain() : CreatureScript("npc_demon_chain") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_demon_chainAI(creature);
|
||||
}
|
||||
|
||||
struct npc_demon_chainAI : public ScriptedAI
|
||||
{
|
||||
npc_demon_chainAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
uint64 SacrificeGUID;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
SacrificeGUID = 0;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) { }
|
||||
void AttackStart(Unit* /*who*/) { }
|
||||
void MoveInLineOfSight(Unit* /*who*/) { }
|
||||
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
if (SacrificeGUID)
|
||||
{
|
||||
Unit* Sacrifice = ObjectAccessor::GetUnit(*me, SacrificeGUID);
|
||||
if (Sacrifice)
|
||||
Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class npc_fiendish_portal : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_fiendish_portal() : CreatureScript("npc_fiendish_portal") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_fiendish_portalAI(creature);
|
||||
}
|
||||
|
||||
struct npc_fiendish_portalAI : public PassiveAI
|
||||
{
|
||||
npc_fiendish_portalAI(Creature* creature) : PassiveAI(creature), summons(me){ }
|
||||
|
||||
SummonList summons;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
DespawnAllImp();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
|
||||
void DespawnAllImp()
|
||||
{
|
||||
summons.DespawnAll();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class npc_fiendish_imp : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_fiendish_imp() : CreatureScript("npc_fiendish_imp") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_fiendish_impAI(creature);
|
||||
}
|
||||
|
||||
struct npc_fiendish_impAI : public ScriptedAI
|
||||
{
|
||||
npc_fiendish_impAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
uint32 FireboltTimer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
FireboltTimer = 2000;
|
||||
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) { }
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (FireboltTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FIREBOLT);
|
||||
FireboltTimer = 2200;
|
||||
} else FireboltTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class boss_terestian_illhoof : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_terestian_illhoof() : CreatureScript("boss_terestian_illhoof") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetInstanceAI<boss_terestianAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_terestianAI : public ScriptedAI
|
||||
{
|
||||
boss_terestianAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
PortalGUID[i] = 0;
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint64 PortalGUID[2];
|
||||
uint8 PortalsCount;
|
||||
|
||||
uint32 SacrificeTimer;
|
||||
uint32 ShadowboltTimer;
|
||||
uint32 SummonTimer;
|
||||
uint32 BerserkTimer;
|
||||
|
||||
bool SummonedPortals;
|
||||
bool Berserk;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (PortalGUID[i])
|
||||
{
|
||||
if (Creature* pPortal = ObjectAccessor::GetCreature(*me, PortalGUID[i]))
|
||||
{
|
||||
CAST_AI(npc_fiendish_portal::npc_fiendish_portalAI, pPortal->AI())->DespawnAllImp();
|
||||
pPortal->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
PortalGUID[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PortalsCount = 0;
|
||||
SacrificeTimer = 30000;
|
||||
ShadowboltTimer = 5000;
|
||||
SummonTimer = 10000;
|
||||
BerserkTimer = 600000;
|
||||
|
||||
SummonedPortals = false;
|
||||
Berserk = false;
|
||||
|
||||
instance->SetData(TYPE_TERESTIAN, NOT_STARTED);
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);
|
||||
|
||||
if (Minion* Kilrek = me->GetFirstMinion())
|
||||
{
|
||||
if (!Kilrek->IsAlive())
|
||||
{
|
||||
Kilrek->UnSummon();
|
||||
DoCast(me, SPELL_SUMMON_IMP, true);
|
||||
}
|
||||
}
|
||||
else DoCast(me, SPELL_SUMMON_IMP, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned)
|
||||
{
|
||||
if (summoned->GetEntry() == NPC_PORTAL)
|
||||
{
|
||||
PortalGUID[PortalsCount] = summoned->GetGUID();
|
||||
++PortalsCount;
|
||||
|
||||
if (summoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1)
|
||||
{
|
||||
Talk(SAY_SUMMON);
|
||||
SummonedPortals = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (PortalGUID[i])
|
||||
{
|
||||
if (Creature* pPortal = ObjectAccessor::GetCreature((*me), PortalGUID[i]))
|
||||
pPortal->DespawnOrUnsummon();
|
||||
|
||||
PortalGUID[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->SetData(TYPE_TERESTIAN, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (SacrificeTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
|
||||
if (target && target->IsAlive())
|
||||
{
|
||||
DoCast(target, SPELL_SACRIFICE, true);
|
||||
DoCast(target, SPELL_SUMMON_DEMONCHAINS, true);
|
||||
|
||||
if (Creature* Chains = me->FindNearestCreature(NPC_DEMONCHAINS, 5000))
|
||||
{
|
||||
CAST_AI(npc_demon_chain::npc_demon_chainAI, Chains->AI())->SacrificeGUID = target->GetGUID();
|
||||
Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true);
|
||||
Talk(SAY_SACRIFICE);
|
||||
SacrificeTimer = 30000;
|
||||
}
|
||||
}
|
||||
} else SacrificeTimer -= diff;
|
||||
|
||||
if (ShadowboltTimer <= diff)
|
||||
{
|
||||
DoCast(SelectTarget(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT);
|
||||
ShadowboltTimer = 10000;
|
||||
} else ShadowboltTimer -= diff;
|
||||
|
||||
if (SummonTimer <= diff)
|
||||
{
|
||||
if (!PortalGUID[0])
|
||||
DoCastVictim(SPELL_FIENDISH_PORTAL, false);
|
||||
|
||||
if (!PortalGUID[1])
|
||||
DoCastVictim(SPELL_FIENDISH_PORTAL_1, false);
|
||||
|
||||
if (PortalGUID[0] && PortalGUID[1])
|
||||
{
|
||||
if (Creature* pPortal = ObjectAccessor::GetCreature(*me, PortalGUID[urand(0, 1)]))
|
||||
pPortal->CastSpell(me->GetVictim(), SPELL_SUMMON_FIENDISIMP, false);
|
||||
SummonTimer = 5000;
|
||||
}
|
||||
} else SummonTimer -= diff;
|
||||
|
||||
if (!Berserk)
|
||||
{
|
||||
if (BerserkTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_BERSERK);
|
||||
Berserk = true;
|
||||
} else BerserkTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_terestian_illhoof()
|
||||
{
|
||||
new boss_terestian_illhoof();
|
||||
new npc_fiendish_imp();
|
||||
new npc_fiendish_portal();
|
||||
new npc_kilrek();
|
||||
new npc_demon_chain();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
|
||||
class instance_karazhan : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_karazhan() : InstanceMapScript("instance_karazhan", 532) { }
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const
|
||||
{
|
||||
return new instance_karazhan_InstanceMapScript(map);
|
||||
}
|
||||
|
||||
struct instance_karazhan_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_karazhan_InstanceMapScript(Map* map) : InstanceScript(map) { }
|
||||
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
SetBossNumber(MAX_ENCOUNTERS);
|
||||
_servantQuartersKills = 0;
|
||||
_selectedRare = RAND(NPC_HYAKISS_THE_LURKER, NPC_SHADIKITH_THE_GLIDER, NPC_ROKAD_THE_RAVAGER);
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 uiData)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_COUNT_SERVANT_QUARTERS_KILLS:
|
||||
if (++_servantQuartersKills > 52) // 56 in total, not all have to be killed, almost all
|
||||
{
|
||||
SetBossState(TYPE_SERVANT_QUARTERS, NOT_STARTED);
|
||||
SetBossState(TYPE_SERVANT_QUARTERS, DONE);
|
||||
}
|
||||
SaveToDB();
|
||||
break;
|
||||
|
||||
/*
|
||||
case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break;
|
||||
case TYPE_MOROES:
|
||||
if (m_auiEncounter[1] == DONE)
|
||||
break;
|
||||
m_auiEncounter[1] = uiData;
|
||||
break;
|
||||
case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break;
|
||||
case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break;
|
||||
case TYPE_OPERA:
|
||||
m_auiEncounter[4] = uiData;
|
||||
if (uiData == DONE)
|
||||
instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, 16812, NULL);
|
||||
break;
|
||||
case TYPE_CURATOR: m_auiEncounter[5] = uiData; break;
|
||||
case TYPE_ARAN: m_auiEncounter[6] = uiData; break;
|
||||
case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break;
|
||||
case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break;
|
||||
case TYPE_CHESS:
|
||||
if (uiData == DONE)
|
||||
DoRespawnGameObject(DustCoveredChest, DAY);
|
||||
m_auiEncounter[9] = uiData;
|
||||
break;
|
||||
case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break;
|
||||
case TYPE_NIGHTBANE:
|
||||
if (m_auiEncounter[11] != DONE)
|
||||
m_auiEncounter[11] = uiData;
|
||||
break;
|
||||
case DATA_OPERA_OZ_DEATHCOUNT:
|
||||
if (uiData == SPECIAL)
|
||||
++m_uiOzDeathCount;
|
||||
else if (uiData == IN_PROGRESS)
|
||||
m_uiOzDeathCount = 0;
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void SetData64(uint32 identifier, uint64 data)
|
||||
{
|
||||
// switch (identifier)
|
||||
// {
|
||||
//case DATA_IMAGE_OF_MEDIVH: ImageGUID = data;
|
||||
// }
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go)
|
||||
{
|
||||
/*switch (go->GetEntry())
|
||||
{
|
||||
case 183932: m_uiCurtainGUID = go->GetGUID(); break;
|
||||
case 184278:
|
||||
m_uiStageDoorLeftGUID = go->GetGUID();
|
||||
if (m_auiEncounter[4] == DONE)
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
break;
|
||||
case 184279:
|
||||
m_uiStageDoorRightGUID = go->GetGUID();
|
||||
if (m_auiEncounter[4] == DONE)
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
break;
|
||||
case 184517: m_uiLibraryDoor = go->GetGUID(); break;
|
||||
case 185521: m_uiMassiveDoor = go->GetGUID(); break;
|
||||
case 184276: m_uiGamesmansDoor = go->GetGUID(); break;
|
||||
case 184277: m_uiGamesmansExitDoor = go->GetGUID(); break;
|
||||
case 185134: m_uiNetherspaceDoor = go->GetGUID(); break;
|
||||
case 184274: MastersTerraceDoor[0] = go->GetGUID(); break;
|
||||
case 184280: MastersTerraceDoor[1] = go->GetGUID(); break;
|
||||
case 184275:
|
||||
m_uiSideEntranceDoor = go->GetGUID();
|
||||
if (m_auiEncounter[4] == DONE)
|
||||
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
|
||||
else
|
||||
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
|
||||
break;
|
||||
case 185119: DustCoveredChest = go->GetGUID(); break;
|
||||
}*/
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case DATA_SELECTED_RARE:
|
||||
return _selectedRare;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 GetData64(uint32 data) const
|
||||
{
|
||||
/*switch (uiData)
|
||||
{
|
||||
case DATA_KILREK: return m_uiKilrekGUID;
|
||||
case DATA_TERESTIAN: return m_uiTerestianGUID;
|
||||
case DATA_MOROES: return m_uiMoroesGUID;
|
||||
case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID;
|
||||
case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID;
|
||||
case DATA_GO_CURTAINS: return m_uiCurtainGUID;
|
||||
case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor;
|
||||
case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor;
|
||||
case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor;
|
||||
case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor;
|
||||
case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor;
|
||||
case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor;
|
||||
case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0];
|
||||
case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1];
|
||||
case DATA_IMAGE_OF_MEDIVH: return ImageGUID;
|
||||
case DATA_NIGHTBANE: return m_uiNightbaneGUID;
|
||||
}
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string GetSaveData()
|
||||
{
|
||||
std::ostringstream saveStream;
|
||||
saveStream << "K A " << GetBossSaveData() << _servantQuartersKills << ' ' << _selectedRare;
|
||||
return saveStream.str();
|
||||
}
|
||||
|
||||
void Load(char const* str)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
char dataHead1, dataHead2;
|
||||
|
||||
std::istringstream loadStream(str);
|
||||
loadStream >> dataHead1 >> dataHead2;
|
||||
|
||||
if (dataHead1 == 'K' && dataHead2 == 'A')
|
||||
{
|
||||
for (uint32 i = 0; i < MAX_ENCOUNTERS; ++i)
|
||||
{
|
||||
uint32 tmpState;
|
||||
loadStream >> tmpState;
|
||||
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
|
||||
tmpState = NOT_STARTED;
|
||||
SetBossState(i, EncounterState(tmpState));
|
||||
}
|
||||
|
||||
loadStream >> _servantQuartersKills;
|
||||
loadStream >> _selectedRare;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _servantQuartersKills;
|
||||
uint32 _selectedRare;
|
||||
};
|
||||
};
|
||||
|
||||
class spell_karazhan_brittle_bones : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_karazhan_brittle_bones() : SpellScriptLoader("spell_karazhan_brittle_bones") { }
|
||||
|
||||
class spell_karazhan_brittle_bones_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_karazhan_brittle_bones_AuraScript);
|
||||
|
||||
void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude)
|
||||
{
|
||||
isPeriodic = true;
|
||||
amplitude = 5000;
|
||||
}
|
||||
|
||||
void Update(AuraEffect const* effect)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (roll_chance_i(35))
|
||||
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_RATTLED, true);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_karazhan_brittle_bones_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_karazhan_brittle_bones_AuraScript::Update, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_karazhan_brittle_bones_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_karazhan_overload : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_karazhan_overload() : SpellScriptLoader("spell_karazhan_overload") { }
|
||||
|
||||
class spell_karazhan_overload_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_karazhan_overload_AuraScript);
|
||||
|
||||
void PeriodicTick(AuraEffect const* auraEffect)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
GetUnitOwner()->CastCustomSpell(SPELL_OVERLOAD, SPELLVALUE_BASE_POINT0, int32(auraEffect->GetAmount() * (2.0, auraEffect->GetTickNumber())), GetUnitOwner(), true);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_karazhan_overload_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_karazhan_overload_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_karazhan_blink : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_karazhan_blink() : SpellScriptLoader("spell_karazhan_blink") { }
|
||||
|
||||
class spell_karazhan_blink_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_karazhan_blink_SpellScript);
|
||||
|
||||
void HandleDummy(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
GetCaster()->getThreatManager().resetAllAggro();
|
||||
if (Unit* target = GetHitUnit())
|
||||
GetCaster()->CastSpell(target, SPELL_BLINK, true);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_karazhan_blink_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_karazhan_blink_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_karazhan()
|
||||
{
|
||||
new instance_karazhan();
|
||||
new spell_karazhan_brittle_bones();
|
||||
new spell_karazhan_overload();
|
||||
new spell_karazhan_blink();
|
||||
}
|
||||
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Karazhan
|
||||
SD%Complete: 100
|
||||
SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645.
|
||||
SDCategory: Karazhan
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
npc_barnes
|
||||
npc_berthold
|
||||
npc_image_of_medivh
|
||||
EndContentData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "karazhan.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "Player.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Barnes
|
||||
SPELL_SPOTLIGHT = 25824,
|
||||
SPELL_TUXEDO = 32616,
|
||||
|
||||
// Berthold
|
||||
SPELL_TELEPORT = 39567,
|
||||
|
||||
// Image of Medivh
|
||||
SPELL_FIRE_BALL = 30967,
|
||||
SPELL_UBER_FIREBALL = 30971,
|
||||
SPELL_CONFLAGRATION_BLAST = 30977,
|
||||
SPELL_MANA_SHIELD = 31635
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_ARCANAGOS = 17652,
|
||||
NPC_SPOTLIGHT = 19525
|
||||
};
|
||||
|
||||
/*######
|
||||
# npc_barnesAI
|
||||
######*/
|
||||
|
||||
#define GOSSIP_READY "I'm not an actor."
|
||||
|
||||
#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!"
|
||||
#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?"
|
||||
#define OZ_GOSSIP1 "I'm not an actor."
|
||||
#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!"
|
||||
#define OZ_GOSSIP2 "Ok, I'll give it a try, then."
|
||||
|
||||
#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?"
|
||||
#define RAJ_GOSSIP1 "I've never been more ready."
|
||||
|
||||
#define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ"
|
||||
#define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD"
|
||||
#define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ"
|
||||
|
||||
struct Dialogue
|
||||
{
|
||||
int32 textid;
|
||||
uint32 timer;
|
||||
};
|
||||
|
||||
static Dialogue OzDialogue[]=
|
||||
{
|
||||
{0, 6000},
|
||||
{1, 18000},
|
||||
{2, 9000},
|
||||
{3, 15000}
|
||||
};
|
||||
|
||||
static Dialogue HoodDialogue[]=
|
||||
{
|
||||
{4, 6000},
|
||||
{5, 10000},
|
||||
{6, 14000},
|
||||
{7, 15000}
|
||||
};
|
||||
|
||||
static Dialogue RAJDialogue[]=
|
||||
{
|
||||
{8, 5000},
|
||||
{9, 7000},
|
||||
{10, 14000},
|
||||
{11, 14000}
|
||||
};
|
||||
|
||||
// Entries and spawn locations for creatures in Oz event
|
||||
float Spawns[6][2]=
|
||||
{
|
||||
{17535, -10896}, // Dorothee
|
||||
{17546, -10891}, // Roar
|
||||
{17547, -10884}, // Tinhead
|
||||
{17543, -10902}, // Strawman
|
||||
{17603, -10892}, // Grandmother
|
||||
{17534, -10900}, // Julianne
|
||||
};
|
||||
|
||||
#define SPAWN_Z 90.5f
|
||||
#define SPAWN_Y -1758
|
||||
#define SPAWN_O 4.738f
|
||||
|
||||
class npc_barnes : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_barnes() : CreatureScript("npc_barnes") { }
|
||||
|
||||
struct npc_barnesAI : public npc_escortAI
|
||||
{
|
||||
npc_barnesAI(Creature* creature) : npc_escortAI(creature)
|
||||
{
|
||||
RaidWiped = false;
|
||||
m_uiEventId = 0;
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint64 m_uiSpotlightGUID;
|
||||
|
||||
uint32 TalkCount;
|
||||
uint32 TalkTimer;
|
||||
uint32 WipeTimer;
|
||||
uint32 m_uiEventId;
|
||||
|
||||
bool PerformanceReady;
|
||||
bool RaidWiped;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_uiSpotlightGUID = 0;
|
||||
|
||||
TalkCount = 0;
|
||||
TalkTimer = 2000;
|
||||
WipeTimer = 5000;
|
||||
|
||||
PerformanceReady = false;
|
||||
|
||||
m_uiEventId = instance->GetData(DATA_OPERA_PERFORMANCE);
|
||||
}
|
||||
|
||||
void StartEvent()
|
||||
{
|
||||
instance->SetData(TYPE_OPERA, IN_PROGRESS);
|
||||
|
||||
//resets count for this event, in case earlier failed
|
||||
if (m_uiEventId == EVENT_OZ)
|
||||
instance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS);
|
||||
|
||||
Start(false, false);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) { }
|
||||
|
||||
void WaypointReached(uint32 waypointId)
|
||||
{
|
||||
switch (waypointId)
|
||||
{
|
||||
case 0:
|
||||
DoCast(me, SPELL_TUXEDO, false);
|
||||
instance->DoUseDoorOrButton(instance->GetData64(DATA_GO_STAGEDOORLEFT));
|
||||
break;
|
||||
case 4:
|
||||
TalkCount = 0;
|
||||
SetEscortPaused(true);
|
||||
|
||||
if (Creature* spotlight = me->SummonCreature(NPC_SPOTLIGHT,
|
||||
me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f,
|
||||
TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
|
||||
{
|
||||
spotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
spotlight->CastSpell(spotlight, SPELL_SPOTLIGHT, false);
|
||||
m_uiSpotlightGUID = spotlight->GetGUID();
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
instance->DoUseDoorOrButton(instance->GetData64(DATA_GO_STAGEDOORLEFT));
|
||||
PerformanceReady = true;
|
||||
break;
|
||||
case 9:
|
||||
PrepareEncounter();
|
||||
instance->DoUseDoorOrButton(instance->GetData64(DATA_GO_CURTAINS));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Talk(uint32 count)
|
||||
{
|
||||
int32 text = 0;
|
||||
|
||||
switch (m_uiEventId)
|
||||
{
|
||||
case EVENT_OZ:
|
||||
if (OzDialogue[count].textid)
|
||||
text = OzDialogue[count].textid;
|
||||
if (OzDialogue[count].timer)
|
||||
TalkTimer = OzDialogue[count].timer;
|
||||
break;
|
||||
|
||||
case EVENT_HOOD:
|
||||
if (HoodDialogue[count].textid)
|
||||
text = HoodDialogue[count].textid;
|
||||
if (HoodDialogue[count].timer)
|
||||
TalkTimer = HoodDialogue[count].timer;
|
||||
break;
|
||||
|
||||
case EVENT_RAJ:
|
||||
if (RAJDialogue[count].textid)
|
||||
text = RAJDialogue[count].textid;
|
||||
if (RAJDialogue[count].timer)
|
||||
TalkTimer = RAJDialogue[count].timer;
|
||||
break;
|
||||
}
|
||||
|
||||
if (text)
|
||||
CreatureAI::Talk(text);
|
||||
}
|
||||
|
||||
void PrepareEncounter()
|
||||
{
|
||||
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId);
|
||||
uint8 index = 0;
|
||||
uint8 count = 0;
|
||||
|
||||
switch (m_uiEventId)
|
||||
{
|
||||
case EVENT_OZ:
|
||||
index = 0;
|
||||
count = 4;
|
||||
break;
|
||||
case EVENT_HOOD:
|
||||
index = 4;
|
||||
count = index+1;
|
||||
break;
|
||||
case EVENT_RAJ:
|
||||
index = 5;
|
||||
count = index+1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
uint32 entry = ((uint32)Spawns[index][0]);
|
||||
float PosX = Spawns[index][1];
|
||||
|
||||
if (Creature* creature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS))
|
||||
{
|
||||
// In case database has bad flags
|
||||
creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
}
|
||||
|
||||
RaidWiped = false;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
if (HasEscortState(STATE_ESCORT_PAUSED))
|
||||
{
|
||||
if (TalkTimer <= diff)
|
||||
{
|
||||
if (TalkCount > 3)
|
||||
{
|
||||
if (Creature* pSpotlight = ObjectAccessor::GetCreature(*me, m_uiSpotlightGUID))
|
||||
pSpotlight->DespawnOrUnsummon();
|
||||
|
||||
SetEscortPaused(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(TalkCount);
|
||||
++TalkCount;
|
||||
} else TalkTimer -= diff;
|
||||
}
|
||||
|
||||
if (PerformanceReady)
|
||||
{
|
||||
if (!RaidWiped)
|
||||
{
|
||||
if (WipeTimer <= diff)
|
||||
{
|
||||
Map* map = me->GetMap();
|
||||
if (!map->IsDungeon())
|
||||
return;
|
||||
|
||||
Map::PlayerList const &PlayerList = map->GetPlayers();
|
||||
if (PlayerList.isEmpty())
|
||||
return;
|
||||
|
||||
RaidWiped = true;
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
{
|
||||
if (i->GetSource()->IsAlive() && !i->GetSource()->IsGameMaster())
|
||||
{
|
||||
RaidWiped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (RaidWiped)
|
||||
{
|
||||
RaidWiped = true;
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
WipeTimer = 15000;
|
||||
} else WipeTimer -= diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
|
||||
{
|
||||
player->PlayerTalkClass->ClearMenus();
|
||||
npc_barnesAI* pBarnesAI = CAST_AI(npc_barnes::npc_barnesAI, creature->AI());
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
|
||||
player->SEND_GOSSIP_MENU(8971, creature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
pBarnesAI->StartEvent();
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
pBarnesAI->m_uiEventId = EVENT_OZ;
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+4:
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
pBarnesAI->m_uiEventId = EVENT_HOOD;
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+5:
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
pBarnesAI->m_uiEventId = EVENT_RAJ;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature)
|
||||
{
|
||||
if (InstanceScript* instance = creature->GetInstanceScript())
|
||||
{
|
||||
// Check for death of Moroes and if opera event is not done already
|
||||
if (instance->GetData(TYPE_MOROES) == DONE && instance->GetData(TYPE_OPERA) != DONE)
|
||||
{
|
||||
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
|
||||
if (player->IsGameMaster())
|
||||
{
|
||||
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
|
||||
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
|
||||
}
|
||||
|
||||
if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnes::npc_barnesAI, creature->AI()))
|
||||
{
|
||||
if (!pBarnesAI->RaidWiped)
|
||||
player->SEND_GOSSIP_MENU(8970, creature->GetGUID());
|
||||
else
|
||||
player->SEND_GOSSIP_MENU(8975, creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player->SEND_GOSSIP_MENU(8978, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_barnesAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
/*###
|
||||
# npc_image_of_medivh
|
||||
####*/
|
||||
|
||||
#define SAY_DIALOG_MEDIVH_1 "You've got my attention, dragon. You'll find I'm not as easily scared as the villagers below."
|
||||
#define SAY_DIALOG_ARCANAGOS_2 "Your dabbling in the arcane has gone too far, Medivh. You've attracted the attention of powers beyond your understanding. You must leave Karazhan at once!"
|
||||
#define SAY_DIALOG_MEDIVH_3 "You dare challenge me at my own dwelling? Your arrogance is astounding, even for a dragon!"
|
||||
#define SAY_DIALOG_ARCANAGOS_4 "A dark power seeks to use you, Medivh! If you stay, dire days will follow. You must hurry, we don't have much time!"
|
||||
#define SAY_DIALOG_MEDIVH_5 "I do not know what you speak of, dragon... but I will not be bullied by this display of insolence. I'll leave Karazhan when it suits me!"
|
||||
#define SAY_DIALOG_ARCANAGOS_6 "You leave me no alternative. I will stop you by force if you won't listen to reason!"
|
||||
#define EMOTE_DIALOG_MEDIVH_7 "begins to cast a spell of great power, weaving his own essence into the magic."
|
||||
#define SAY_DIALOG_ARCANAGOS_8 "What have you done, wizard? This cannot be! I'm burning from... within!"
|
||||
#define SAY_DIALOG_MEDIVH_9 "He should not have angered me. I must go... recover my strength now..."
|
||||
|
||||
|
||||
static float MedivPos[4] = {-11161.49f, -1902.24f, 91.48f, 1.94f};
|
||||
static float ArcanagosPos[4] = {-11169.75f, -1881.48f, 107.39f, 4.83f};
|
||||
|
||||
class npc_image_of_medivh : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_image_of_medivh() : CreatureScript("npc_image_of_medivh") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_image_of_medivhAI(creature);
|
||||
}
|
||||
|
||||
struct npc_image_of_medivhAI : public ScriptedAI
|
||||
{
|
||||
npc_image_of_medivhAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
Step = 1;
|
||||
YellTimer = 5000;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint64 ArcanagosGUID;
|
||||
|
||||
uint32 YellTimer;
|
||||
uint8 Step;
|
||||
int32 MTimer;
|
||||
int32 ATimer;
|
||||
|
||||
bool EventStarted;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ArcanagosGUID = 0;
|
||||
MTimer = 0;
|
||||
ATimer = 0;
|
||||
|
||||
if (instance && instance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0)
|
||||
{
|
||||
Creature* Arcanagos = me->SummonCreature(NPC_ARCANAGOS, ArcanagosPos[0], ArcanagosPos[1], ArcanagosPos[2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
|
||||
if (!Arcanagos)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
instance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID());
|
||||
EventStarted = true;
|
||||
ArcanagosGUID = Arcanagos->GetGUID();
|
||||
|
||||
Arcanagos->SetFacingToObject(me);
|
||||
me->SetFacingToObject(Arcanagos);
|
||||
|
||||
Arcanagos->SetCanFly(true);
|
||||
}
|
||||
else
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) {}
|
||||
|
||||
uint32 NextStep(uint32 Step)
|
||||
{
|
||||
switch(Step)
|
||||
{
|
||||
case 1:
|
||||
me->MonsterYell(SAY_DIALOG_MEDIVH_1, LANG_UNIVERSAL, 0);
|
||||
return 10000;
|
||||
case 2:
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
arca->MonsterYell(SAY_DIALOG_ARCANAGOS_2, LANG_UNIVERSAL, 0);
|
||||
return 20000;
|
||||
case 3:
|
||||
me->MonsterYell(SAY_DIALOG_MEDIVH_3, LANG_UNIVERSAL, 0);
|
||||
return 10000;
|
||||
case 4:
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
arca->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, 0);
|
||||
return 20000;
|
||||
case 5:
|
||||
me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, 0);
|
||||
return 20000;
|
||||
case 6:
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
arca->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, 0);
|
||||
|
||||
ATimer = 5500;
|
||||
MTimer = 6600;
|
||||
return 10000;
|
||||
case 7:
|
||||
return 1000;
|
||||
case 8:
|
||||
me->CastSpell(me, SPELL_MANA_SHIELD, true);
|
||||
return 5500;
|
||||
case 9:
|
||||
me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false);
|
||||
me->CastSpell(me, 30972, true);
|
||||
return 10000;
|
||||
case 10:
|
||||
me->RemoveAurasDueToSpell(30972);
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
me->CastSpell(arca, SPELL_CONFLAGRATION_BLAST, false);
|
||||
return 1000;
|
||||
case 11:
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
arca->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, 0);
|
||||
return 5000;
|
||||
case 12:
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
{
|
||||
arca->SetSpeed(MOVE_RUN, 2.0f);
|
||||
arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f);
|
||||
arca->InterruptNonMeleeSpells(true);
|
||||
}
|
||||
return 10000;
|
||||
case 13:
|
||||
me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, 0);
|
||||
return 10000;
|
||||
case 14:
|
||||
if (me->GetMap()->IsDungeon())
|
||||
{
|
||||
InstanceMap::PlayerList const &PlayerList = me->GetMap()->GetPlayers();
|
||||
for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
{
|
||||
if (i->GetSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
i->GetSource()->GroupEventHappens(9645, me);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
me->DespawnOrUnsummon(100);
|
||||
if (Creature* arca = ObjectAccessor::GetCreature((*me), ArcanagosGUID))
|
||||
arca->DespawnOrUnsummon(100);
|
||||
|
||||
return 5000;
|
||||
default:
|
||||
return 2000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff)
|
||||
{
|
||||
|
||||
if (YellTimer <= diff)
|
||||
{
|
||||
if (EventStarted)
|
||||
YellTimer = NextStep(Step++);
|
||||
} else YellTimer -= diff;
|
||||
|
||||
if (Step >= 7 && Step <= 8)
|
||||
{
|
||||
ATimer += diff;
|
||||
MTimer += diff;
|
||||
if (ATimer >= 6000)
|
||||
{
|
||||
if (Unit* arca = ObjectAccessor::GetUnit((*me), ArcanagosGUID))
|
||||
arca->CastSpell(me, SPELL_FIRE_BALL, false);
|
||||
ATimer = 0;
|
||||
}
|
||||
if (MTimer >= 6000)
|
||||
{
|
||||
if (Unit* arca = ObjectAccessor::GetUnit((*me), ArcanagosGUID))
|
||||
me->CastSpell(arca, SPELL_FIRE_BALL, false);
|
||||
MTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void AddSC_karazhan()
|
||||
{
|
||||
new npc_barnes();
|
||||
new npc_image_of_medivh();
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
REWRITTEN BY XINEF
|
||||
*/
|
||||
|
||||
#ifndef DEF_KARAZHAN_H
|
||||
#define DEF_KARAZHAN_H
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
TYPE_SERVANT_QUARTERS = 0,
|
||||
TYPE_ATTUMEN = 1,
|
||||
TYPE_MOROES = 2,
|
||||
TYPE_MAIDEN = 3,
|
||||
TYPE_OPTIONAL_BOSS = 4,
|
||||
TYPE_OPERA = 5,
|
||||
TYPE_CURATOR = 6,
|
||||
TYPE_ARAN = 7,
|
||||
TYPE_TERESTIAN = 8,
|
||||
TYPE_NETHERSPITE = 9,
|
||||
TYPE_CHESS = 10,
|
||||
TYPE_MALCHEZZAR = 11,
|
||||
TYPE_NIGHTBANE = 12,
|
||||
MAX_ENCOUNTERS = 13,
|
||||
|
||||
DATA_OPERA_PERFORMANCE = 13,
|
||||
DATA_OPERA_OZ_DEATHCOUNT = 14,
|
||||
|
||||
DATA_KILREK = 15,
|
||||
DATA_TERESTIAN = 16,
|
||||
DATA_MOROES = 17,
|
||||
DATA_GO_CURTAINS = 18,
|
||||
DATA_GO_STAGEDOORLEFT = 19,
|
||||
DATA_GO_STAGEDOORRIGHT = 20,
|
||||
DATA_GO_LIBRARY_DOOR = 21,
|
||||
DATA_GO_MASSIVE_DOOR = 22,
|
||||
DATA_GO_NETHER_DOOR = 23,
|
||||
DATA_GO_GAME_DOOR = 24,
|
||||
DATA_GO_GAME_EXIT_DOOR = 25,
|
||||
|
||||
DATA_IMAGE_OF_MEDIVH = 26,
|
||||
DATA_MASTERS_TERRACE_DOOR_1 = 27,
|
||||
DATA_MASTERS_TERRACE_DOOR_2 = 28,
|
||||
DATA_GO_SIDE_ENTRANCE_DOOR = 29,
|
||||
|
||||
DATA_NIGHTBANE = 30,
|
||||
|
||||
DATA_COUNT_SERVANT_QUARTERS_KILLS = 100,
|
||||
DATA_SELECTED_RARE = 101,
|
||||
};
|
||||
|
||||
enum OperaEvents
|
||||
{
|
||||
EVENT_OZ = 1,
|
||||
EVENT_HOOD = 2,
|
||||
EVENT_RAJ = 3
|
||||
};
|
||||
|
||||
enum KarazhanNPCs
|
||||
{
|
||||
NPC_HYAKISS_THE_LURKER = 16179,
|
||||
NPC_SHADIKITH_THE_GLIDER = 16180,
|
||||
NPC_ROKAD_THE_RAVAGER = 16181,
|
||||
|
||||
NPC_ATTUMEN_THE_HUNTSMAN = 15550,
|
||||
NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED = 16152
|
||||
};
|
||||
|
||||
enum KarazhanSpells
|
||||
{
|
||||
SPELL_RATTLED = 32437,
|
||||
SPELL_OVERLOAD = 29766,
|
||||
SPELL_BLINK = 29884
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user