Merge branch 'master' into Playerbot
This commit is contained in:
@@ -56,20 +56,6 @@ enum Spells
|
||||
|
||||
enum Misc
|
||||
{
|
||||
EVENT_INIT_COMBAT = 1,
|
||||
EVENT_SPELL_FIREBALL = 2,
|
||||
EVENT_SPELL_PHOENIX = 3,
|
||||
EVENT_SPELL_FLAMESTRIKE = 4,
|
||||
EVENT_SPELL_SHOCK_BARRIER = 5,
|
||||
EVENT_CHECK_HEALTH = 6,
|
||||
EVENT_GRAVITY_LAPSE_1_1 = 7,
|
||||
EVENT_GRAVITY_LAPSE_1_2 = 8,
|
||||
EVENT_GRAVITY_LAPSE_2 = 9,
|
||||
EVENT_GRAVITY_LAPSE_3 = 10,
|
||||
EVENT_GRAVITY_LAPSE_4 = 11,
|
||||
EVENT_GRAVITY_LAPSE_5 = 12,
|
||||
EVENT_FINISH_TALK = 13,
|
||||
|
||||
ACTION_TELEPORT_PLAYERS = 1,
|
||||
ACTION_KNOCKUP = 2,
|
||||
ACTION_ALLOW_FLY = 3,
|
||||
@@ -78,216 +64,176 @@ enum Misc
|
||||
CREATURE_ARCANE_SPHERE = 24708
|
||||
};
|
||||
|
||||
struct boss_felblood_kaelthas : public ScriptedAI
|
||||
struct boss_felblood_kaelthas : public BossAI
|
||||
{
|
||||
boss_felblood_kaelthas(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
boss_felblood_kaelthas(Creature* creature) : BossAI(creature, DATA_KAELTHAS)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
introSpeak = false;
|
||||
_hasDoneIntro = false;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
EventMap events2;
|
||||
SummonList summons;
|
||||
bool introSpeak;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
BossAI::Reset();
|
||||
_OOCScheduler.CancelAll();
|
||||
_gravityLapseCounter = 0;
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
|
||||
instance->SetBossState(DATA_KAELTHAS, NOT_STARTED);
|
||||
me->SetImmuneToAll(false);
|
||||
ScheduleHealthCheckEvent(50, [&]{
|
||||
me->CastStop();
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
|
||||
DoCastSelf(SPELL_TELEPORT_CENTER, true);
|
||||
scheduler.CancelAll();
|
||||
|
||||
me->StopMoving();
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
ScheduleTimedEvent(5s, [&]{
|
||||
summons.DoForAllSummons([&](WorldObject* summon){
|
||||
if (Unit* player = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
if (Creature* summonedCreature = summon->ToCreature())
|
||||
summonedCreature->GetMotionMaster()->MoveChase(player);
|
||||
});
|
||||
}, 10s, 15s);
|
||||
GravityLapseSequence(true);
|
||||
});
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
|
||||
if (*itr == summon->GetGUID())
|
||||
return;
|
||||
summons.Summon(summon);
|
||||
BossAI::JustSummoned(summon);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void GravityLapseSequence(bool firstTime)
|
||||
{
|
||||
Talk(firstTime ? SAY_GRAVITY_LAPSE : SAY_RECAST_GRAVITY);
|
||||
DoCastSelf(SPELL_GRAVITY_LAPSE_INITIAL);
|
||||
scheduler.Schedule(2s, [this](TaskContext){
|
||||
LapseAction(ACTION_TELEPORT_PLAYERS);
|
||||
}).Schedule(3s, [this](TaskContext){
|
||||
LapseAction(ACTION_KNOCKUP);
|
||||
}).Schedule(4s, [this](TaskContext){
|
||||
LapseAction(ACTION_ALLOW_FLY);
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
DoCastSelf(SPELL_SUMMON_ARCANE_SPHERE, true);
|
||||
DoCastSelf(SPELL_GRAVITY_LAPSE_CHANNEL);
|
||||
scheduler.Schedule(30s, [this](TaskContext){
|
||||
LapseAction(ACTION_REMOVE_FLY);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
Talk(SAY_TIRED);
|
||||
DoCastSelf(SPELL_POWER_FEEDBACK);
|
||||
scheduler.Schedule(10s, [this](TaskContext){
|
||||
GravityLapseSequence(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
ScriptedAI::InitializeAI();
|
||||
BossAI::InitializeAI();
|
||||
me->SetImmuneToAll(true);
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
instance->SetBossState(DATA_KAELTHAS, DONE);
|
||||
summons.DespawnAll();
|
||||
|
||||
BossAI::JustDied(killer);
|
||||
if (GameObject* orb = instance->GetGameObject(DATA_ESCAPE_ORB))
|
||||
orb->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS);
|
||||
me->SetInCombatWithZone();
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 0);
|
||||
events.ScheduleEvent(EVENT_SPELL_PHOENIX, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAMESTRIKE, 22000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
ScheduleTimedEvent(0ms, [&]{
|
||||
DoCastVictim(SPELL_FIREBALL);
|
||||
}, 3000ms, 4500ms);
|
||||
ScheduleTimedEvent(15s, [&]{
|
||||
Talk(SAY_PHOENIX);
|
||||
DoCastSelf(SPELL_PHOENIX);
|
||||
}, 60s);
|
||||
ScheduleTimedEvent(22s, [&]{
|
||||
DoCastRandomTarget(SPELL_FLAMESTRIKE_SUMMON, 0, 100.0f);
|
||||
Talk(SAY_FLAMESTRIKE);
|
||||
}, 25s);
|
||||
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SPELL_SHOCK_BARRIER, 50000);
|
||||
ScheduleTimedEvent(50s, [&]{
|
||||
DoCastSelf(SPELL_SHOCK_BARRIER, true);
|
||||
me->CastCustomSpell(SPELL_PYROBLAST, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
|
||||
}, 50s);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!introSpeak && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
|
||||
if (!_hasDoneIntro && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
introSpeak = true;
|
||||
events2.ScheduleEvent(EVENT_INIT_COMBAT, 35000);
|
||||
_hasDoneIntro = true;
|
||||
_OOCScheduler.Schedule(35s, [this](TaskContext){
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetInCombatWithZone();
|
||||
});
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
damage = me->GetHealth() - 1;
|
||||
if (me->isRegeneratingHealth())
|
||||
{
|
||||
me->CastStop();
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetStandState(UNIT_STAND_STATE_KNEEL);
|
||||
me->CombatStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
LapseAction(ACTION_REMOVE_FLY);
|
||||
events.Reset();
|
||||
events2.ScheduleEvent(EVENT_FINISH_TALK, 6000);
|
||||
scheduler.CancelAll();
|
||||
_OOCScheduler.Schedule(6s, [this](TaskContext){
|
||||
me->KillSelf();
|
||||
});
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
}
|
||||
BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
|
||||
}
|
||||
|
||||
void LapseAction(uint8 action)
|
||||
{
|
||||
uint8 counter = 0;
|
||||
Map::PlayerList const& playerList = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr, ++counter)
|
||||
if (Player* player = itr->GetSource())
|
||||
_gravityLapseCounter = 0;
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (action == ACTION_TELEPORT_PLAYERS)
|
||||
DoCast(player, SPELL_GRAVITY_LAPSE_PLAYER + _gravityLapseCounter, true);
|
||||
else if (action == ACTION_KNOCKUP)
|
||||
player->CastSpell(player, SPELL_GRAVITY_LAPSE_DOT, true, nullptr, nullptr, me->GetGUID());
|
||||
else if (action == ACTION_ALLOW_FLY)
|
||||
player->CastSpell(player, SPELL_GRAVITY_LAPSE_FLY, true, nullptr, nullptr, me->GetGUID());
|
||||
else if (action == ACTION_REMOVE_FLY)
|
||||
{
|
||||
if (action == ACTION_TELEPORT_PLAYERS)
|
||||
me->CastSpell(player, SPELL_GRAVITY_LAPSE_PLAYER + counter, true);
|
||||
else if (action == ACTION_KNOCKUP)
|
||||
player->CastSpell(player, SPELL_GRAVITY_LAPSE_DOT, true, nullptr, nullptr, me->GetGUID());
|
||||
else if (action == ACTION_ALLOW_FLY)
|
||||
player->CastSpell(player, SPELL_GRAVITY_LAPSE_FLY, true, nullptr, nullptr, me->GetGUID());
|
||||
else if (action == ACTION_REMOVE_FLY)
|
||||
{
|
||||
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
|
||||
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
|
||||
}
|
||||
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
|
||||
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
|
||||
}
|
||||
++_gravityLapseCounter;
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
switch (events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_INIT_COMBAT:
|
||||
me->SetImmuneToAll(false);
|
||||
if (Unit* target = SelectTargetFromPlayerList(50.0f))
|
||||
AttackStart(target);
|
||||
return;
|
||||
case EVENT_FINISH_TALK:
|
||||
me->KillSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_FIREBALL:
|
||||
me->CastSpell(me->GetVictim(), SPELL_FIREBALL, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBALL, urand(3000, 4500));
|
||||
break;
|
||||
case EVENT_SPELL_FLAMESTRIKE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
me->CastSpell(target, SPELL_FLAMESTRIKE_SUMMON, true);
|
||||
Talk(SAY_FLAMESTRIKE);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAMESTRIKE, 25000);
|
||||
break;
|
||||
case EVENT_SPELL_SHOCK_BARRIER:
|
||||
me->CastSpell(me, SPELL_SHOCK_BARRIER, true);
|
||||
me->CastCustomSpell(SPELL_PYROBLAST, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHOCK_BARRIER, 50000);
|
||||
break;
|
||||
case EVENT_SPELL_PHOENIX:
|
||||
Talk(SAY_PHOENIX);
|
||||
me->CastSpell(me, SPELL_PHOENIX, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_PHOENIX, 60000);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (HealthBelowPct(50))
|
||||
{
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
|
||||
me->CastSpell(me, SPELL_TELEPORT_CENTER, true);
|
||||
events.Reset();
|
||||
|
||||
me->StopMoving();
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
|
||||
events.SetPhase(1);
|
||||
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_1_1, 0);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500);
|
||||
break;
|
||||
case EVENT_GRAVITY_LAPSE_1_1:
|
||||
case EVENT_GRAVITY_LAPSE_1_2:
|
||||
Talk(eventId == EVENT_GRAVITY_LAPSE_1_1 ? SAY_GRAVITY_LAPSE : SAY_RECAST_GRAVITY);
|
||||
me->CastSpell(me, SPELL_GRAVITY_LAPSE_INITIAL, false);
|
||||
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_2, 2000);
|
||||
break;
|
||||
case EVENT_GRAVITY_LAPSE_2:
|
||||
LapseAction(ACTION_TELEPORT_PLAYERS);
|
||||
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_3, 1000);
|
||||
break;
|
||||
case EVENT_GRAVITY_LAPSE_3:
|
||||
LapseAction(ACTION_KNOCKUP);
|
||||
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_4, 1000);
|
||||
break;
|
||||
case EVENT_GRAVITY_LAPSE_4:
|
||||
LapseAction(ACTION_ALLOW_FLY);
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
me->CastSpell(me, SPELL_SUMMON_ARCANE_SPHERE, true);
|
||||
|
||||
me->CastSpell(me, SPELL_GRAVITY_LAPSE_CHANNEL, false);
|
||||
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_5, 30000);
|
||||
break;
|
||||
case EVENT_GRAVITY_LAPSE_5:
|
||||
LapseAction(ACTION_REMOVE_FLY);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
Talk(SAY_TIRED);
|
||||
me->CastSpell(me, SPELL_POWER_FEEDBACK, false);
|
||||
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_1_2, 10000);
|
||||
break;
|
||||
}
|
||||
|
||||
if (events.GetPhaseMask() == 0)
|
||||
DoMeleeAttackIfReady();
|
||||
_OOCScheduler.Update(diff);
|
||||
BossAI::UpdateAI(diff);
|
||||
}
|
||||
private:
|
||||
TaskScheduler _OOCScheduler;
|
||||
bool _hasDoneIntro;
|
||||
uint8 _gravityLapseCounter;
|
||||
};
|
||||
|
||||
class spell_mt_phoenix_burn : public SpellScript
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,76 +41,76 @@ enum Spells
|
||||
SPELL_DRAIN_MANA = 46153
|
||||
};
|
||||
|
||||
enum Events
|
||||
const Position crystalSummons[5] =
|
||||
{
|
||||
EVENT_SPELL_DRAIN_LIFE = 1,
|
||||
EVENT_SPELL_FEL_EXPLOSION = 2,
|
||||
EVENT_SPELL_DRAIN_MANA = 3,
|
||||
EVENT_DRAIN_CRYSTAL = 4,
|
||||
EVENT_EMPOWER = 5,
|
||||
EVENT_RESTORE_COMBAT = 6
|
||||
{248.053f, 14.592f, 3.74882f, 3.94444f},
|
||||
{225.969f, -20.0775f, -2.9731f, 0.942478f},
|
||||
{226.314f, 20.2183f, -2.98127f, 5.32325f},
|
||||
{247.888f, -14.6252f, 3.80777f, 2.33874f},
|
||||
{263.149f, 0.309245f, 1.32057f, 3.15905f}
|
||||
};
|
||||
|
||||
struct boss_selin_fireheart : public ScriptedAI
|
||||
struct boss_selin_fireheart : public BossAI
|
||||
{
|
||||
boss_selin_fireheart(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
ObjectGuid CrystalGUID;
|
||||
boss_selin_fireheart(Creature* creature) : BossAI(creature, DATA_SELIN_FIREHEART) { }
|
||||
|
||||
bool CanAIAttack(Unit const* who) const override
|
||||
{
|
||||
return who->GetPositionX() > 216.0f;
|
||||
}
|
||||
|
||||
void SpawnCrystals()
|
||||
{
|
||||
me->SummonCreature(NPC_FEL_CRYSTAL, 248.053f, 14.592f, 3.74882f, 3.94444f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
me->SummonCreature(NPC_FEL_CRYSTAL, 225.969f, -20.0775f, -2.9731f, 0.942478f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
me->SummonCreature(NPC_FEL_CRYSTAL, 226.314f, 20.2183f, -2.98127f, 5.32325f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
me->SummonCreature(NPC_FEL_CRYSTAL, 247.888f, -14.6252f, 3.80777f, 2.33874f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
me->SummonCreature(NPC_FEL_CRYSTAL, 263.149f, 0.309245f, 1.32057f, 3.15905f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit*) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (events.GetPhaseMask() & 0x01)
|
||||
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 0);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
BossAI::Reset();
|
||||
SpawnCrystals();
|
||||
instance->SetBossState(DATA_SELIN_FIREHEART, NOT_STARTED);
|
||||
CrystalGUID.Clear();
|
||||
me->SetPower(POWER_MANA, 0);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void SpawnCrystals()
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
instance->SetBossState(DATA_SELIN_FIREHEART, IN_PROGRESS);
|
||||
for (Position pos : crystalSummons)
|
||||
me->SummonCreature(NPC_FEL_CRYSTAL, pos, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_LIFE, 2500, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_FEL_EXPLOSION, 2000);
|
||||
events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, 14000);
|
||||
void SummonedCreatureDies(Creature* summon, Unit* killer) override
|
||||
{
|
||||
BossAI::SummonedCreatureDies(summon, killer);
|
||||
me->ResumeChasingVictim();
|
||||
}
|
||||
|
||||
void OnPowerUpdate(Powers /*power*/, int32 /*gain*/, int32 /*updateVal*/, uint32 currentPower) override
|
||||
{
|
||||
if (currentPower == me->GetMaxPower(POWER_MANA))
|
||||
{
|
||||
Talk(SAY_EMPOWERED);
|
||||
if (Creature* crystal = SelectNearestCrystal(false))
|
||||
crystal->KillSelf();
|
||||
scheduler.DelayAll(10s);
|
||||
me->ResumeChasingVictim();
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
ScheduleTimedEvent(2500ms, [&]{
|
||||
DoCastRandomTarget(SPELL_DRAIN_LIFE);
|
||||
}, 10000ms);
|
||||
ScheduleTimedEvent(2s, [&]{
|
||||
me->RemoveAuraFromStack(SPELL_MANA_RAGE_TRIGGER);
|
||||
DoCastAOE(SPELL_FEL_EXPLOSION);
|
||||
}, 2s);
|
||||
ScheduleTimedEvent(14s, [&]{
|
||||
scheduler.DelayAll(10s);
|
||||
SelectNearestCrystal(true);
|
||||
}, 30s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 7500, 1);
|
||||
{
|
||||
ScheduleTimedEvent(7500ms, [&]{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 40.0f, false)))
|
||||
DoCast(target, SPELL_DRAIN_MANA);
|
||||
}, 10s);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
@@ -119,106 +119,57 @@ struct boss_selin_fireheart : public ScriptedAI
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->SetBossState(DATA_SELIN_FIREHEART, DONE); // Encounter complete!
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void SelectNearestCrystal()
|
||||
Creature* SelectNearestCrystal(bool performMovement)
|
||||
{
|
||||
if (summons.empty())
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
CrystalGUID.Clear();
|
||||
Unit* crystal = nullptr;
|
||||
for (SummonList::const_iterator i = summons.begin(); i != summons.end(); )
|
||||
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i++))
|
||||
if (!crystal || me->GetDistanceOrder(summon, crystal, false))
|
||||
crystal = summon;
|
||||
|
||||
if (crystal)
|
||||
float closestDistance = 1000.0f;
|
||||
Creature* chosenCrystal = nullptr;
|
||||
summons.DoForAllSummons([&](WorldObject* summon)
|
||||
{
|
||||
if (Creature* summonedCreature = summon->ToCreature())
|
||||
{
|
||||
float checkDistance = me->GetDistance2d(summonedCreature);
|
||||
if (checkDistance < closestDistance)
|
||||
{
|
||||
closestDistance = checkDistance;
|
||||
chosenCrystal = summonedCreature;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (chosenCrystal && performMovement)
|
||||
{
|
||||
Talk(SAY_ENERGY);
|
||||
float x, y, z;
|
||||
crystal->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
|
||||
CrystalGUID = crystal->GetGUID();
|
||||
chosenCrystal->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
|
||||
me->GetMotionMaster()->MovePoint(2, x, y, z);
|
||||
}
|
||||
return chosenCrystal;
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == 2)
|
||||
{
|
||||
if (Unit* crystal = ObjectAccessor::GetUnit(*me, CrystalGUID))
|
||||
if (Creature* crystal = SelectNearestCrystal(false))
|
||||
{
|
||||
Talk(EMOTE_CRYSTAL);
|
||||
crystal->ReplaceAllUnitFlags(UNIT_FLAG_NONE);
|
||||
crystal->CastSpell(me, SPELL_MANA_RAGE, true);
|
||||
me->CastSpell(crystal, SPELL_FEL_CRYSTAL_COSMETIC, true);
|
||||
events.SetPhase(1);
|
||||
events.ScheduleEvent(EVENT_EMPOWER, 0, 0, 1);
|
||||
crystal->SetInCombatWithZone();
|
||||
crystal->AI()->DoCast(me, SPELL_MANA_RAGE, true);
|
||||
DoCast(crystal, SPELL_FEL_CRYSTAL_COSMETIC, true);
|
||||
}
|
||||
else
|
||||
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 0);
|
||||
me->ResumeChasingVictim();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_DRAIN_LIFE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_DRAIN_LIFE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_LIFE, 10000, 1);
|
||||
return;
|
||||
case EVENT_SPELL_DRAIN_MANA:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 40.0f, false)))
|
||||
me->CastSpell(target, SPELL_DRAIN_MANA, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 10000, 1);
|
||||
return;
|
||||
case EVENT_SPELL_FEL_EXPLOSION:
|
||||
me->RemoveAuraFromStack(SPELL_MANA_RAGE_TRIGGER);
|
||||
me->CastSpell(me, SPELL_FEL_EXPLOSION, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_FEL_EXPLOSION, 2000);
|
||||
break;
|
||||
case EVENT_DRAIN_CRYSTAL:
|
||||
events.DelayEvents(10001);
|
||||
events.ScheduleEvent(EVENT_EMPOWER, 10000);
|
||||
events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, 30000);
|
||||
SelectNearestCrystal();
|
||||
break;
|
||||
case EVENT_EMPOWER:
|
||||
if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA))
|
||||
{
|
||||
Talk(SAY_EMPOWERED);
|
||||
if (Unit* crystal = ObjectAccessor::GetUnit(*me, CrystalGUID))
|
||||
Unit::Kill(crystal, crystal);
|
||||
events.DelayEvents(10000, 1);
|
||||
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 0);
|
||||
}
|
||||
else
|
||||
events.ScheduleEvent(EVENT_EMPOWER, 0, 0, 1);
|
||||
break;
|
||||
case EVENT_RESTORE_COMBAT:
|
||||
events.SetPhase(0);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_selin_fireheart()
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_DELRISSA, DATA_DELRISSA },
|
||||
{ NPC_KAEL_THAS, DATA_KAELTHAS },
|
||||
{ NPC_KALECGOS, DATA_KALECGOS },
|
||||
{ 0, 0 }
|
||||
@@ -34,6 +35,13 @@ ObjectData const gameobjectData[] =
|
||||
{ 0, 0, }
|
||||
};
|
||||
|
||||
ObjectData const summonerData[] =
|
||||
{
|
||||
{ NPC_PHOENIX, DATA_KAELTHAS },
|
||||
{ NPC_PHOENIX_EGG, DATA_KAELTHAS },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_SELIN_DOOR, DATA_SELIN_FIREHEART, DOOR_TYPE_PASSAGE },
|
||||
@@ -58,10 +66,9 @@ public:
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
LoadObjectData(creatureData, gameobjectData);
|
||||
LoadDoorData(doorData);
|
||||
LoadSummonData(summonerData);
|
||||
}
|
||||
|
||||
ObjectGuid DelrissaGUID;
|
||||
|
||||
void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) override
|
||||
{
|
||||
if (eventId == EVENT_SPAWN_KALECGOS)
|
||||
@@ -74,31 +81,6 @@ public:
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_DELRISSA:
|
||||
DelrissaGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_PHOENIX:
|
||||
case NPC_PHOENIX_EGG:
|
||||
if (Creature* kael = GetCreature(DATA_KAELTHAS))
|
||||
kael->AI()->JustSummoned(creature);
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 identifier) const override
|
||||
{
|
||||
if (identifier == NPC_DELRISSA)
|
||||
return DelrissaGUID;
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
|
||||
@@ -1215,6 +1215,88 @@ class spell_death_knight_initiate_visual : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
enum spells_lich_king_whisper
|
||||
{
|
||||
SPELL_LICH_KING_VO_BLOCKER = 58207,
|
||||
SPELL_LICHKINGDK001 = 58208,
|
||||
SPELL_LICHKINGDK002 = 58209,
|
||||
SPELL_LICHKINGDK003 = 58210,
|
||||
SPELL_LICHKINGDK004 = 58211,
|
||||
SPELL_LICHKINGDK005 = 58212,
|
||||
SPELL_LICHKINGDK006 = 58213,
|
||||
SPELL_LICHKINGDK007 = 58214,
|
||||
SPELL_LICHKINGDK008 = 58215,
|
||||
SPELL_LICHKINGDK009 = 58216,
|
||||
SPELL_LICHKINGDK010 = 58217,
|
||||
SPELL_LICHKINGDK011 = 58218,
|
||||
SPELL_LICHKINGDK012 = 58219,
|
||||
SPELL_LICHKINGDK013 = 58220,
|
||||
SPELL_LICHKINGDK014 = 58221,
|
||||
SPELL_LICHKINGDK015 = 58222,
|
||||
SPELL_LICHKINGDK016 = 58223
|
||||
};
|
||||
|
||||
//spell 58207 rand Whisper
|
||||
class spell_lich_king_vo_blocker : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_lich_king_vo_blocker);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo
|
||||
({
|
||||
SPELL_LICHKINGDK001, SPELL_LICHKINGDK002, SPELL_LICHKINGDK003, SPELL_LICHKINGDK004,
|
||||
SPELL_LICHKINGDK005, SPELL_LICHKINGDK006, SPELL_LICHKINGDK007, SPELL_LICHKINGDK008,
|
||||
SPELL_LICHKINGDK009, SPELL_LICHKINGDK010, SPELL_LICHKINGDK011, SPELL_LICHKINGDK012,
|
||||
SPELL_LICHKINGDK013, SPELL_LICHKINGDK014, SPELL_LICHKINGDK015, SPELL_LICHKINGDK016
|
||||
});
|
||||
}
|
||||
|
||||
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* target = GetTarget()->ToPlayer())
|
||||
{
|
||||
//spell 58208-58223
|
||||
GetCaster()->CastSpell(target, urand(SPELL_LICHKINGDK001, SPELL_LICHKINGDK016), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_lich_king_vo_blocker::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 58208 - 58224 - Creature - The Lich King (28765) Whisper
|
||||
class spell_lich_king_whisper : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_lich_king_whisper);
|
||||
|
||||
bool Validate(SpellInfo const* spellInfo) override
|
||||
{
|
||||
return sObjectMgr->GetBroadcastText(uint32(spellInfo->GetEffect(EFFECT_0).CalcValue())) &&
|
||||
sSoundEntriesStore.LookupEntry(uint32(spellInfo->GetEffect(EFFECT_1).CalcValue()));
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Player* player = GetHitPlayer())
|
||||
GetCaster()->Whisper(uint32(GetEffectValue()), player, false);
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Player* player = GetHitPlayer())
|
||||
player->PlayDistanceSound(uint32(GetEffectValue()), player);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_lich_king_whisper::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_lich_king_whisper::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_the_scarlet_enclave_c1()
|
||||
{
|
||||
// Ours
|
||||
@@ -1237,4 +1319,6 @@ void AddSC_the_scarlet_enclave_c1()
|
||||
new go_inconspicuous_mine_car();
|
||||
|
||||
RegisterSpellScript(spell_death_knight_initiate_visual);
|
||||
RegisterSpellScript(spell_lich_king_whisper);
|
||||
RegisterSpellScript(spell_lich_king_vo_blocker);
|
||||
}
|
||||
|
||||
@@ -63,35 +63,6 @@ enum Spells
|
||||
|
||||
enum Misc
|
||||
{
|
||||
// Land
|
||||
EVENT_SPELL_BERSERK = 1,
|
||||
EVENT_SPELL_CLEAVE = 2,
|
||||
EVENT_SPELL_CORROSION = 3,
|
||||
EVENT_SPELL_GAS_NOVA = 4,
|
||||
EVENT_SPELL_ENCAPSULATE = 5,
|
||||
EVENT_FLIGHT = 6,
|
||||
EVENT_LAND = 7,
|
||||
EVENT_RESTORE_COMBAT = 8,
|
||||
EVENT_RESTORE_COMBAT2 = 9,
|
||||
|
||||
// Air
|
||||
EVENT_FLIGHT_SEQ = 100,
|
||||
EVENT_FLIGHT_VAPOR = 101,
|
||||
EVENT_FLIGHT_MOVE_UP = 102,
|
||||
EVENT_LAND_FIGHT = 103,
|
||||
EVENT_FLIGHT_EMOTE = 104,
|
||||
EVENT_FLIGHT_BREATH1 = 105,
|
||||
EVENT_FLIGHT_BREATH2 = 106,
|
||||
EVENT_FLIGHT_FLYOVER1 = 107,
|
||||
EVENT_FLIGHT_FLYOVER2 = 108,
|
||||
EVENT_CORRUPT_TRIGGERS = 109,
|
||||
|
||||
// Intro
|
||||
EVENT_INTRO_1 = 20,
|
||||
EVENT_INTRO_2 = 21,
|
||||
EVENT_INTRO_3 = 22,
|
||||
EVENT_INTRO_4 = 23,
|
||||
|
||||
// Misc
|
||||
ACTION_START_EVENT = 1,
|
||||
POINT_GROUND = 1,
|
||||
@@ -102,23 +73,24 @@ enum Misc
|
||||
POINT_AIR_BREATH_END2 = 6,
|
||||
POINT_MISC = 7,
|
||||
|
||||
GROUP_START_INTRO = 0,
|
||||
GROUP_BREATH = 1,
|
||||
|
||||
NPC_FOG_TRIGGER = 23472
|
||||
};
|
||||
|
||||
class CorruptTriggers : public BasicEvent
|
||||
{
|
||||
public:
|
||||
CorruptTriggers(Unit* caster) : _caster(caster)
|
||||
{
|
||||
}
|
||||
CorruptTriggers(Unit* caster) : _caster(caster) { }
|
||||
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
std::list<Creature*> cList;
|
||||
_caster->GetCreaturesWithEntryInRange(cList, 70.0f, NPC_FOG_TRIGGER);
|
||||
for (std::list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); ++itr)
|
||||
if (_caster->GetExactDist2d(*itr) <= 11.0f)
|
||||
(*itr)->CastSpell(*itr, SPELL_FOG_OF_CORRUPTION, true);
|
||||
std::list<Creature*> creatureList;
|
||||
_caster->GetCreaturesWithEntryInRange(creatureList, 70.0f, NPC_FOG_TRIGGER);
|
||||
for (auto const& creature : creatureList)
|
||||
if (_caster->GetExactDist2d(creature) <= 11.0f)
|
||||
creature->CastSpell(creature, SPELL_FOG_OF_CORRUPTION, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -136,15 +108,13 @@ struct boss_felmyst : public BossAI
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
EventMap events2;
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_START_EVENT)
|
||||
{
|
||||
me->SetVisible(true);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
events2.ScheduleEvent(EVENT_INTRO_1, 3000);
|
||||
StartIntro();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +124,7 @@ struct boss_felmyst : public BossAI
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetDisableGravity(false);
|
||||
events2.Reset();
|
||||
me->m_Events.KillAllEvents(false);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FOG_OF_CORRUPTION_CHARM);
|
||||
}
|
||||
|
||||
@@ -162,8 +132,9 @@ struct boss_felmyst : public BossAI
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
if (events.Empty() && events2.Empty())
|
||||
events2.ScheduleEvent(EVENT_INTRO_2, 3000);
|
||||
|
||||
if (!scheduler.IsGroupScheduled(GROUP_START_INTRO))
|
||||
StartIntro();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
@@ -193,36 +164,65 @@ struct boss_felmyst : public BossAI
|
||||
me->SetDisableGravity(false);
|
||||
me->SendMovementFlagUpdate();
|
||||
|
||||
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 0);
|
||||
events.ScheduleEvent(EVENT_RESTORE_COMBAT2, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_CLEAVE, 7500, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_CORROSION, 12000, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_GAS_NOVA, 18000, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_ENCAPSULATE, 25000, 1);
|
||||
events.ScheduleEvent(EVENT_FLIGHT, 60000, 1);
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
if (me->GetVictim())
|
||||
me->SetTarget(me->GetVictim()->GetGUID());
|
||||
|
||||
me->ResumeChasingVictim();
|
||||
}, 1s);
|
||||
|
||||
ScheduleTimedEvent(7500ms, [&] {
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
}, 7500ms);
|
||||
|
||||
ScheduleTimedEvent(12s, [&] {
|
||||
DoCastVictim(SPELL_CORROSION);
|
||||
}, 20s);
|
||||
|
||||
ScheduleTimedEvent(18s, [&] {
|
||||
DoCastSelf(SPELL_GAS_NOVA);
|
||||
}, 20s);
|
||||
|
||||
ScheduleTimedEvent(25s, [&] {
|
||||
DoCastRandomTarget(SPELL_ENCAPSULATE_CHANNEL, 0, 50.0f);
|
||||
}, 25s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
scheduler.CancelAll();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->StopMoving();
|
||||
me->GetMotionMaster()->Clear();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
ScheduleFlightSequence();
|
||||
}, 1s);
|
||||
}, 1min);
|
||||
}
|
||||
else if (point == POINT_AIR_BREATH_START1)
|
||||
{
|
||||
me->SetTarget();
|
||||
me->SetFacingTo(4.71f);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_EMOTE, 2000);
|
||||
events.ScheduleEvent(EVENT_CORRUPT_TRIGGERS, 5000);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_FLYOVER1, 5000);
|
||||
ScheduleFlightAbilities(point);
|
||||
}
|
||||
else if (point == POINT_AIR_BREATH_END1)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_FELMYST_SPEED_BURST);
|
||||
me->SetFacingTo(1.57f);
|
||||
if (events.GetNextEventTime(EVENT_FLIGHT_BREATH1) != 0)
|
||||
events.ScheduleEvent(EVENT_FLIGHT_BREATH2, 2000);
|
||||
if (!scheduler.IsGroupScheduled(GROUP_BREATH))
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Position pos = { 1447.0f + urand(0, 2) * 25.0f, 515.0f, 50.0f, 1.57f };
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_START2, pos, false, true);
|
||||
}, 2s);
|
||||
}
|
||||
}
|
||||
else if (point == POINT_AIR_BREATH_START2)
|
||||
{
|
||||
me->SetTarget();
|
||||
me->SetFacingTo(1.57f);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_EMOTE, 2000);
|
||||
events.ScheduleEvent(EVENT_CORRUPT_TRIGGERS, 5000);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_FLYOVER2, 5000);
|
||||
ScheduleFlightAbilities(point);
|
||||
}
|
||||
else if (point == POINT_AIR_BREATH_END2)
|
||||
{
|
||||
@@ -231,127 +231,50 @@ struct boss_felmyst : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
void ScheduleFlightSequence()
|
||||
{
|
||||
summons.Summon(summon);
|
||||
}
|
||||
Talk(YELL_TAKEOFF);
|
||||
me->SetTarget();
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
switch (events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_INTRO_1:
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
events2.ScheduleEvent(EVENT_INTRO_2, 4000);
|
||||
break;
|
||||
case EVENT_INTRO_2:
|
||||
Talk(YELL_BIRTH);
|
||||
me->SetDisableGravity(true);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SendMovementFlagUpdate();
|
||||
events2.ScheduleEvent(EVENT_INTRO_3, 1500);
|
||||
break;
|
||||
case EVENT_INTRO_3:
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, false, true);
|
||||
events2.ScheduleEvent(EVENT_INTRO_4, 2000);
|
||||
break;
|
||||
case EVENT_INTRO_4:
|
||||
events.ScheduleEvent(EVENT_LAND, 3000, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_BERSERK, 600000);
|
||||
me->SetInCombatWithZone();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->CastSpell(me, SPELL_NOXIOUS_FUMES, true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MISC, 1472.18f, 603.38f, 34.0f, false, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!events2.Empty())
|
||||
return;
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_RESTORE_COMBAT:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
break;
|
||||
case EVENT_RESTORE_COMBAT2:
|
||||
me->SetTarget(me->GetVictim()->GetGUID());
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
break;
|
||||
case EVENT_LAND:
|
||||
me->GetMotionMaster()->MovePoint(POINT_GROUND, me->GetPositionX(), me->GetPositionY(), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()), false, true);
|
||||
break;
|
||||
case EVENT_SPELL_BERSERK:
|
||||
Talk(YELL_BERSERK);
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
case EVENT_SPELL_CLEAVE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_CLEAVE, 7500, 1);
|
||||
break;
|
||||
case EVENT_SPELL_CORROSION:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CORROSION, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_CORROSION, 20000, 1);
|
||||
break;
|
||||
case EVENT_SPELL_GAS_NOVA:
|
||||
DoCast(me, SPELL_GAS_NOVA, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_GAS_NOVA, 20000, 1);
|
||||
break;
|
||||
case EVENT_SPELL_ENCAPSULATE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||
me->CastSpell(target, SPELL_ENCAPSULATE_CHANNEL, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_ENCAPSULATE, 25000, 1);
|
||||
break;
|
||||
case EVENT_FLIGHT:
|
||||
events.CancelEventGroup(1);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQ, 1000);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->StopMoving();
|
||||
me->GetMotionMaster()->Clear();
|
||||
break;
|
||||
case EVENT_FLIGHT_SEQ:
|
||||
Talk(YELL_TAKEOFF);
|
||||
me->SetTarget();
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
|
||||
events.ScheduleEvent(EVENT_FLIGHT_MOVE_UP, 2000);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_VAPOR, 8000);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_VAPOR, 21000);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_BREATH1, 35000);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_BREATH1, 72000);
|
||||
events.ScheduleEvent(EVENT_LAND_FIGHT, 86000);
|
||||
break;
|
||||
case EVENT_FLIGHT_MOVE_UP:
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 15.0f, false, true);
|
||||
break;
|
||||
case EVENT_FLIGHT_VAPOR:
|
||||
}, 2s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->CastCustomSpell(SPELL_SUMMON_DEMONIC_VAPOR, SPELLVALUE_MAX_TARGETS, 1, me, true);
|
||||
break;
|
||||
case EVENT_FLIGHT_BREATH1:
|
||||
}, 8s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->CastCustomSpell(SPELL_SUMMON_DEMONIC_VAPOR, SPELLVALUE_MAX_TARGETS, 1, me, true);
|
||||
}, 21s);
|
||||
|
||||
scheduler.Schedule(35s, GROUP_BREATH, [this](TaskContext)
|
||||
{
|
||||
Position pos = { 1447.0f + urand(0, 2) * 25.0f, 705.0f, 50.0f, 4.71f };
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_START1, pos, false, true);
|
||||
break;
|
||||
}
|
||||
case EVENT_FLIGHT_BREATH2:
|
||||
});
|
||||
|
||||
scheduler.Schedule(72s, GROUP_BREATH, [this](TaskContext)
|
||||
{
|
||||
Position pos = { 1447.0f + urand(0, 2) * 25.0f, 515.0f, 50.0f, 1.57f };
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_START2, pos, false, true);
|
||||
break;
|
||||
}
|
||||
case EVENT_FLIGHT_EMOTE:
|
||||
Position pos = { 1447.0f + urand(0, 2) * 25.0f, 705.0f, 50.0f, 4.71f };
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_START1, pos, false, true);
|
||||
});
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->GetMotionMaster()->MovePoint(POINT_GROUND, 1500.0f, 552.8f, 26.52f, false, true);
|
||||
}, 86s);
|
||||
}
|
||||
|
||||
void ScheduleFlightAbilities(uint8 point)
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(EMOTE_BREATH);
|
||||
break;
|
||||
case EVENT_CORRUPT_TRIGGERS:
|
||||
}, 2s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(YELL_BREATH);
|
||||
me->m_Events.AddEvent(new CorruptTriggers(me), me->m_Events.CalculateTime(0));
|
||||
me->m_Events.AddEvent(new CorruptTriggers(me), me->m_Events.CalculateTime(500));
|
||||
@@ -362,19 +285,58 @@ struct boss_felmyst : public BossAI
|
||||
me->m_Events.AddEvent(new CorruptTriggers(me), me->m_Events.CalculateTime(3000));
|
||||
me->m_Events.AddEvent(new CorruptTriggers(me), me->m_Events.CalculateTime(3500));
|
||||
me->m_Events.AddEvent(new CorruptTriggers(me), me->m_Events.CalculateTime(4000));
|
||||
break;
|
||||
case EVENT_FLIGHT_FLYOVER1:
|
||||
me->CastSpell(me, SPELL_FELMYST_SPEED_BURST, true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_END1, me->GetPositionX(), me->GetPositionY() - 200.0f, me->GetPositionZ() + 5.0f, false, true);
|
||||
break;
|
||||
case EVENT_FLIGHT_FLYOVER2:
|
||||
me->CastSpell(me, SPELL_FELMYST_SPEED_BURST, true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_END2, me->GetPositionX(), me->GetPositionY() + 200.0f, me->GetPositionZ() + 5.0f, false, true);
|
||||
break;
|
||||
case EVENT_LAND_FIGHT:
|
||||
me->GetMotionMaster()->MovePoint(POINT_GROUND, 1500.0f, 552.8f, 26.52f, false, true);
|
||||
break;
|
||||
}
|
||||
}, 5s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this, point] {
|
||||
DoCastSelf(SPELL_FELMYST_SPEED_BURST, true);
|
||||
if (point == POINT_AIR_BREATH_START1)
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_END1, me->GetPositionX(), me->GetPositionY() - 200.0f, me->GetPositionZ() + 5.0f, false, true);
|
||||
else if (point == POINT_AIR_BREATH_START2)
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR_BREATH_END2, me->GetPositionX(), me->GetPositionY() + 200.0f, me->GetPositionZ() + 5.0f, false, true);
|
||||
}, 5s);
|
||||
}
|
||||
|
||||
void StartIntro()
|
||||
{
|
||||
scheduler.Schedule(3s, GROUP_START_INTRO, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(YELL_BIRTH);
|
||||
me->SetDisableGravity(true);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->SendMovementFlagUpdate();
|
||||
}, 7s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->GetMotionMaster()->MovePoint(POINT_AIR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, false, true);
|
||||
}, 8500ms);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetInCombatWithZone();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->CastSpell(me, SPELL_NOXIOUS_FUMES, true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MISC, 1472.18f, 603.38f, 34.0f, false, true);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->GetMotionMaster()->MovePoint(POINT_GROUND, me->GetPositionX(), me->GetPositionY(), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()), false, true);
|
||||
}, 3s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(YELL_BERSERK);
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
}, 10min);
|
||||
}, 10500ms);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!me->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
|
||||
DoMeleeAttackIfReady();
|
||||
|
||||
@@ -84,50 +84,28 @@ enum SWPActions
|
||||
ACTION_ENRAGE_OTHER = 5,
|
||||
};
|
||||
|
||||
enum kalEvents
|
||||
{
|
||||
EVENT_ARCANE_BUFFET = 1,
|
||||
EVENT_FROST_BREATH = 2,
|
||||
EVENT_WILD_MAGIC = 3,
|
||||
EVENT_TAIL_LASH = 4,
|
||||
EVENT_SPECTRAL_BLAST = 5,
|
||||
EVENT_CHECK_HEALTH = 6,
|
||||
EVENT_CHECK_HEALTH2 = 7,
|
||||
EVENT_CHECK_POS = 8,
|
||||
EVENT_SPAWN_SPECTRALS = 9,
|
||||
|
||||
EVENT_SPELL_REVITALIZE = 10,
|
||||
EVENT_SPELL_HEROIC_STRIKE = 11,
|
||||
EVENT_SHADOW_BOLT = 12,
|
||||
EVENT_AGONY_CURSE = 13,
|
||||
EVENT_CORRUPTION_STRIKE = 14,
|
||||
|
||||
EVENT_TALK_GOOD_1 = 20,
|
||||
EVENT_TALK_GOOD_2 = 21,
|
||||
EVENT_TALK_GOOD_3 = 22,
|
||||
EVENT_TALK_GOOD_4 = 23,
|
||||
EVENT_TALK_GOOD_5 = 24,
|
||||
EVENT_TALK_BAD_1 = 25,
|
||||
EVENT_TALK_BAD_2 = 26,
|
||||
EVENT_TALK_BAD_3 = 27
|
||||
};
|
||||
|
||||
#define DRAGON_REALM_Z 53.079f
|
||||
|
||||
struct boss_kalecgos : public BossAI
|
||||
{
|
||||
boss_kalecgos(Creature* creature) : BossAI(creature, DATA_KALECGOS)
|
||||
{
|
||||
SetInvincibility(true);
|
||||
}
|
||||
|
||||
bool sathBanished;
|
||||
EventMap events2;
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
return target->GetPositionZ() > 50.0f;
|
||||
}
|
||||
|
||||
bool CheckInRoom() override
|
||||
{
|
||||
if (me->GetDistance(me->GetHomePosition()) > 50.0f)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
@@ -137,15 +115,24 @@ struct boss_kalecgos : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->SetHealth(me->GetMaxHealth());
|
||||
me->SetFullHealth();
|
||||
me->SetStandState(UNIT_STAND_STATE_SLEEP);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
events2.Reset();
|
||||
|
||||
sathBanished = false;
|
||||
_sathBanished = false;
|
||||
ClearPlayerAuras();
|
||||
|
||||
ScheduleHealthCheckEvent(10, [&] {
|
||||
if (Creature* Sath = instance->GetCreature(DATA_SATHROVARR))
|
||||
Sath->AI()->DoAction(ACTION_ENRAGE_OTHER);
|
||||
DoAction(ACTION_ENRAGE);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(1, [&] {
|
||||
DoAction(ACTION_BANISH);
|
||||
});
|
||||
}
|
||||
|
||||
void ClearPlayerAuras() const
|
||||
@@ -160,29 +147,75 @@ struct boss_kalecgos : public BossAI
|
||||
if (param == ACTION_ENRAGE || param == ACTION_ENRAGE_OTHER)
|
||||
{
|
||||
Talk(param == ACTION_ENRAGE ? SAY_KALEC_ENRAGE_SATH : SAY_SATH_ENRAGE_ME);
|
||||
me->CastSpell(me, SPELL_CRAZED_RAGE, true);
|
||||
events.CancelEvent(EVENT_CHECK_HEALTH);
|
||||
DoCastSelf(SPELL_CRAZED_RAGE, true);
|
||||
return;
|
||||
}
|
||||
else if (param == ACTION_BANISH)
|
||||
{
|
||||
me->CastSpell(me, SPELL_BANISH, true);
|
||||
events.Reset();
|
||||
DoCastSelf(SPELL_BANISH, true);
|
||||
scheduler.CancelAll();
|
||||
}
|
||||
else if (param == ACTION_SATH_BANISH)
|
||||
sathBanished = true;
|
||||
_sathBanished = true;
|
||||
else if (param == ACTION_KALEC_DIED)
|
||||
{
|
||||
events.Reset();
|
||||
events2.ScheduleEvent(EVENT_TALK_BAD_1, 0);
|
||||
scheduler.CancelAll();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->CombatStop();
|
||||
me->RemoveAllAuras();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
Talk(SAY_EVIL_ENRAGE);
|
||||
}, 1s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetDisableGravity(true);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
}, 4s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetVisible(false);
|
||||
EnterEvadeMode();
|
||||
}, 9s);
|
||||
|
||||
ClearPlayerAuras();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasAura(SPELL_BANISH) && sathBanished)
|
||||
if (me->HasAura(SPELL_BANISH) && _sathBanished)
|
||||
{
|
||||
events.Reset();
|
||||
events2.ScheduleEvent(EVENT_TALK_GOOD_1, 1000);
|
||||
scheduler.CancelAll();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->RemoveAllAuras();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->CombatStop();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
}, 1s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Creature* Sath = instance->GetCreature(DATA_SATHROVARR))
|
||||
{
|
||||
summons.Despawn(Sath);
|
||||
Unit::Kill(me, Sath);
|
||||
}
|
||||
}, 2s);
|
||||
|
||||
Talk(SAY_GOOD_PLRWIN, 10s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetDisableGravity(true);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
}, 15s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetVisible(false);
|
||||
me->KillSelf();
|
||||
}, 20s);
|
||||
|
||||
ClearPlayerAuras();
|
||||
if (Creature* Sath = instance->GetCreature(DATA_SATHROVARR))
|
||||
{
|
||||
@@ -194,160 +227,47 @@ struct boss_kalecgos : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BUFFET, 6000);
|
||||
events.ScheduleEvent(EVENT_FROST_BREATH, 15000);
|
||||
events.ScheduleEvent(EVENT_WILD_MAGIC, 10000);
|
||||
events.ScheduleEvent(EVENT_TAIL_LASH, 25000);
|
||||
events.ScheduleEvent(EVENT_SPECTRAL_BLAST, 20000);
|
||||
events.ScheduleEvent(EVENT_CHECK_POS, 5000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1000);
|
||||
events.ScheduleEvent(EVENT_SPAWN_SPECTRALS, 16000);
|
||||
|
||||
ScheduleTimedEvent(6s, [&] {
|
||||
DoCastAOE(SPELL_ARCANE_BUFFET);
|
||||
}, 8s);
|
||||
|
||||
ScheduleTimedEvent(15s, [&] {
|
||||
DoCastVictim(SPELL_FROST_BREATH);
|
||||
}, 15s);
|
||||
|
||||
ScheduleTimedEvent(10s, [&] {
|
||||
me->CastCustomSpell(RAND(44978, 45001, 45002, 45004, 45006, 45010), SPELLVALUE_MAX_TARGETS, 1, me, false);
|
||||
}, 20s);
|
||||
|
||||
ScheduleTimedEvent(25s, [&] {
|
||||
DoCastVictim(SPELL_TAIL_LASH);
|
||||
}, 15s);
|
||||
|
||||
ScheduleTimedEvent(20s, [&] {
|
||||
DoCastAOE(SPELL_SPECTRAL_BLAST);
|
||||
}, 15s, 25s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SummonCreature(NPC_KALEC, 1702.21f, 931.7f, -74.56f, 5.07f, TEMPSUMMON_MANUAL_DESPAWN);
|
||||
me->SummonCreature(NPC_SATHROVARR, 1704.62f, 927.78f, -73.9f, 2.0f, TEMPSUMMON_MANUAL_DESPAWN);
|
||||
}, 16s);
|
||||
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
Talk(SAY_EVIL_AGGRO);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && attacker != me)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer() && roll_chance_i(50))
|
||||
Talk(SAY_EVIL_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
switch (events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_TALK_GOOD_1:
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->RemoveAllAuras();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->CombatStop();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
events2.ScheduleEvent(EVENT_TALK_GOOD_2, 1000);
|
||||
break;
|
||||
case EVENT_TALK_GOOD_2:
|
||||
if (Creature* Sath = instance->GetCreature(DATA_SATHROVARR))
|
||||
{
|
||||
summons.Despawn(Sath);
|
||||
Unit::Kill(me, Sath);
|
||||
}
|
||||
events2.ScheduleEvent(EVENT_TALK_GOOD_3, 8000);
|
||||
break;
|
||||
case EVENT_TALK_GOOD_3:
|
||||
Talk(SAY_GOOD_PLRWIN);
|
||||
events2.ScheduleEvent(EVENT_TALK_GOOD_4, 10000);
|
||||
break;
|
||||
case EVENT_TALK_GOOD_4:
|
||||
me->SetDisableGravity(true);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
events2.ScheduleEvent(EVENT_TALK_GOOD_5, 10000);
|
||||
break;
|
||||
case EVENT_TALK_GOOD_5:
|
||||
me->SetVisible(false);
|
||||
me->KillSelf();
|
||||
break;
|
||||
case EVENT_TALK_BAD_1:
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->CombatStop();
|
||||
me->RemoveAllAuras();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
Talk(SAY_EVIL_ENRAGE);
|
||||
events2.ScheduleEvent(EVENT_TALK_BAD_2, 3000);
|
||||
break;
|
||||
case EVENT_TALK_BAD_2:
|
||||
me->SetDisableGravity(true);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
events2.ScheduleEvent(EVENT_TALK_BAD_3, 15000);
|
||||
break;
|
||||
case EVENT_TALK_BAD_3:
|
||||
me->SetVisible(false);
|
||||
EnterEvadeMode();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!events2.Empty())
|
||||
return;
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPAWN_SPECTRALS:
|
||||
me->SummonCreature(NPC_KALEC, 1702.21f, 931.7f, -74.56f, 5.07f, TEMPSUMMON_MANUAL_DESPAWN);
|
||||
me->SummonCreature(NPC_SATHROVARR, 1704.62f, 927.78f, -73.9f, 2.0f, TEMPSUMMON_MANUAL_DESPAWN);
|
||||
break;
|
||||
case EVENT_ARCANE_BUFFET:
|
||||
me->CastSpell(me, SPELL_ARCANE_BUFFET, false);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BUFFET, 8000);
|
||||
break;
|
||||
case EVENT_FROST_BREATH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_FROST_BREATH, false);
|
||||
events.ScheduleEvent(EVENT_FROST_BREATH, 15000);
|
||||
break;
|
||||
case EVENT_TAIL_LASH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_TAIL_LASH, false);
|
||||
events.ScheduleEvent(EVENT_TAIL_LASH, 15000);
|
||||
break;
|
||||
case EVENT_WILD_MAGIC:
|
||||
me->CastCustomSpell(RAND(44978, 45001, 45002, 45004, 45006, 45010), SPELLVALUE_MAX_TARGETS, 1, me, false);
|
||||
events.ScheduleEvent(EVENT_WILD_MAGIC, 20000);
|
||||
break;
|
||||
case EVENT_SPECTRAL_BLAST:
|
||||
me->CastSpell(me, SPELL_SPECTRAL_BLAST, false);
|
||||
events.ScheduleEvent(EVENT_SPECTRAL_BLAST, urand(15000, 25000));
|
||||
break;
|
||||
case EVENT_CHECK_POS:
|
||||
if (me->GetDistance(me->GetHomePosition()) > 50.0f)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_POS, 5000);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(10))
|
||||
{
|
||||
if (Creature* Sath = instance->GetCreature(DATA_SATHROVARR))
|
||||
Sath->AI()->DoAction(ACTION_ENRAGE_OTHER);
|
||||
DoAction(ACTION_ENRAGE);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH2:
|
||||
if (me->HealthBelowPct(1))
|
||||
{
|
||||
DoAction(ACTION_BANISH);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _sathBanished;
|
||||
};
|
||||
|
||||
enum Kalec
|
||||
@@ -362,41 +282,66 @@ enum Kalec
|
||||
|
||||
struct boss_kalec : public ScriptedAI
|
||||
{
|
||||
boss_kalec(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
EventMap events;
|
||||
EventMap events2;
|
||||
boss_kalec(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetInvincibility(true);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
events2.Reset();
|
||||
if (me->GetPositionY() < 750.0f)
|
||||
{
|
||||
me->SetSpeed(MOVE_RUN, 2.4f);
|
||||
me->SetDisplayId(MODEL_KALECGOS_DRAGON);
|
||||
me->SetDisableGravity(true);
|
||||
me->GetMotionMaster()->MovePoint(0, 1483.30f, 657.99f, 28.0f, false, true);
|
||||
events2.ScheduleEvent(EVENT_KALEC_SCENE_1, 9000);
|
||||
events2.ScheduleEvent(EVENT_KALEC_SCENE_2, 16000);
|
||||
events2.ScheduleEvent(EVENT_KALEC_SCENE_3, 22000);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(SAY_GOOD_MADRIGOSA);
|
||||
me->GetMotionMaster()->MovePoint(0, 1509.0f, 560.0f, 30.0f, false, true);
|
||||
}, 9s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
DoCastAOE(SPELL_OPEN_BRUTALLUS_BACK_DOOR, true);
|
||||
me->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, NOT_STARTED);
|
||||
me->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, DONE);
|
||||
}, 16s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->GetMotionMaster()->MovePoint(0, 1400.0f, 630.0f, 90.0f, false, true);
|
||||
me->DespawnOrUnsummon(6000);
|
||||
}, 22s);
|
||||
}
|
||||
else
|
||||
me->CastSpell(me, SPELL_SPECTRAL_INVISIBILITY, true);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!who || who->GetEntry() != NPC_SATHROVARR)
|
||||
damage = 0;
|
||||
DoCastSelf(SPELL_SPECTRAL_INVISIBILITY, true);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1000);
|
||||
events.ScheduleEvent(EVENT_SPELL_REVITALIZE, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_HEROIC_STRIKE, 3000);
|
||||
ScheduleTimedEvent(5s, [&] {
|
||||
DoCastSelf(SPELL_REVITALIZE);
|
||||
}, 10s);
|
||||
|
||||
ScheduleTimedEvent(3s, [&] {
|
||||
DoCastVictim(SPELL_HEROIC_STRIKE);
|
||||
}, 5s);
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (me->HealthBelowPct(50))
|
||||
Talk(SAY_GOOD_NEAR_DEATH);
|
||||
else
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (me->HealthBelowPct(10))
|
||||
Talk(SAY_GOOD_NEAR_DEATH2);
|
||||
else
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
Talk(SAY_GOOD_AGGRO);
|
||||
}
|
||||
|
||||
@@ -409,60 +354,11 @@ struct boss_kalec : public ScriptedAI
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
switch (events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_KALEC_SCENE_1:
|
||||
Talk(SAY_GOOD_MADRIGOSA);
|
||||
me->GetMotionMaster()->MovePoint(0, 1509.0f, 560.0f, 30.0f, false, true);
|
||||
break;
|
||||
case EVENT_KALEC_SCENE_2:
|
||||
me->CastSpell(me, SPELL_OPEN_BRUTALLUS_BACK_DOOR, true);
|
||||
me->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, NOT_STARTED);
|
||||
me->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, DONE);
|
||||
break;
|
||||
case EVENT_KALEC_SCENE_3:
|
||||
me->GetMotionMaster()->MovePoint(0, 1400.0f, 630.0f, 90.0f, false, true);
|
||||
me->DespawnOrUnsummon(6000);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(50))
|
||||
{
|
||||
Talk(SAY_GOOD_NEAR_DEATH);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH2:
|
||||
if (me->HealthBelowPct(10))
|
||||
{
|
||||
Talk(SAY_GOOD_NEAR_DEATH2);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1000);
|
||||
break;
|
||||
case EVENT_SPELL_REVITALIZE:
|
||||
me->CastSpell(me, SPELL_REVITALIZE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_REVITALIZE, 10000);
|
||||
break;
|
||||
case EVENT_SPELL_HEROIC_STRIKE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_HEROIC_STRIKE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_HEROIC_STRIKE, 5000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -470,12 +366,10 @@ struct boss_sathrovarr : public ScriptedAI
|
||||
{
|
||||
boss_sathrovarr(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
_instance = creature->GetInstanceScript();
|
||||
SetInvincibility(true);
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
return target->GetPositionZ() < 50.0f;
|
||||
@@ -483,26 +377,53 @@ struct boss_sathrovarr : public ScriptedAI
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
me->CastSpell(me, SPELL_DEMONIC_VISUAL, true);
|
||||
me->CastSpell(me, SPELL_SPECTRAL_INVISIBILITY, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 7000);
|
||||
events.ScheduleEvent(EVENT_AGONY_CURSE, 20000);
|
||||
events.ScheduleEvent(EVENT_CORRUPTION_STRIKE, 13000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1000);
|
||||
DoCastSelf(SPELL_DEMONIC_VISUAL, true);
|
||||
DoCastSelf(SPELL_SPECTRAL_INVISIBILITY, true);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_SATH_AGGRO);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && who != me)
|
||||
damage = 0;
|
||||
ScheduleTimedEvent(7s, [&] {
|
||||
if (roll_chance_i(20))
|
||||
Talk(SAY_SATH_SPELL1);
|
||||
DoCastVictim(SPELL_SHADOW_BOLT);
|
||||
}, 9s);
|
||||
|
||||
ScheduleTimedEvent(20s, [&] {
|
||||
me->CastCustomSpell(SPELL_CURSE_OF_BOUNDLESS_AGONY, SPELLVALUE_MAX_TARGETS, 1, me, false);
|
||||
}, 30s);
|
||||
|
||||
ScheduleTimedEvent(20s, [&] {
|
||||
if (roll_chance_i(20))
|
||||
Talk(SAY_SATH_SPELL2);
|
||||
DoCastVictim(SPELL_CORRUPTION_STRIKE);
|
||||
}, 9s);
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (me->HealthBelowPct(10))
|
||||
{
|
||||
if (Creature* kalecgos = _instance->GetCreature(DATA_KALECGOS))
|
||||
kalecgos->AI()->DoAction(ACTION_ENRAGE_OTHER);
|
||||
DoAction(ACTION_ENRAGE);
|
||||
}
|
||||
else
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (me->HealthBelowPct(1))
|
||||
{
|
||||
if (Creature* kalecgos = _instance->GetCreature(DATA_KALECGOS))
|
||||
kalecgos->AI()->DoAction(ACTION_SATH_BANISH);
|
||||
DoAction(ACTION_BANISH);
|
||||
}
|
||||
else
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* target) override
|
||||
@@ -519,15 +440,9 @@ struct boss_sathrovarr : public ScriptedAI
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_ENRAGE || param == ACTION_ENRAGE_OTHER)
|
||||
{
|
||||
me->CastSpell(me, SPELL_CRAZED_RAGE, true);
|
||||
events.CancelEvent(EVENT_CHECK_HEALTH);
|
||||
}
|
||||
DoCastSelf(SPELL_CRAZED_RAGE, true);
|
||||
else if (param == ACTION_BANISH)
|
||||
{
|
||||
me->CastSpell(me, SPELL_BANISH, true);
|
||||
events.Reset();
|
||||
}
|
||||
DoCastSelf(SPELL_BANISH, true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -535,58 +450,12 @@ struct boss_sathrovarr : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SHADOW_BOLT:
|
||||
if (roll_chance_i(20))
|
||||
Talk(SAY_SATH_SPELL1);
|
||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT, false);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 9000);
|
||||
break;
|
||||
case EVENT_AGONY_CURSE:
|
||||
me->CastCustomSpell(SPELL_CURSE_OF_BOUNDLESS_AGONY, SPELLVALUE_MAX_TARGETS, 1, me, false);
|
||||
events.ScheduleEvent(EVENT_AGONY_CURSE, 30000);
|
||||
break;
|
||||
case EVENT_CORRUPTION_STRIKE:
|
||||
if (roll_chance_i(20))
|
||||
Talk(SAY_SATH_SPELL2);
|
||||
me->CastSpell(me->GetVictim(), SPELL_CORRUPTION_STRIKE, false);
|
||||
events.ScheduleEvent(EVENT_CORRUPTION_STRIKE, 9000);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(10))
|
||||
{
|
||||
if (InstanceScript* instanceScript = me->GetInstanceScript())
|
||||
{
|
||||
if (Creature* kalecgos = ObjectAccessor::GetCreature(*me, instanceScript->GetGuidData(
|
||||
NPC_KALECGOS)))
|
||||
{
|
||||
kalecgos->AI()->DoAction(ACTION_ENRAGE_OTHER);
|
||||
}
|
||||
}
|
||||
DoAction(ACTION_ENRAGE);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH2:
|
||||
if (me->HealthBelowPct(1))
|
||||
{
|
||||
if (Creature* kalecgos = instance->GetCreature(DATA_KALECGOS))
|
||||
kalecgos->AI()->DoAction(ACTION_SATH_BANISH);
|
||||
DoAction(ACTION_BANISH);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 1000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
class SpectralBlastCheck
|
||||
|
||||
@@ -97,60 +97,14 @@ enum Misc
|
||||
PHASE_ARMAGEDDON = 4,
|
||||
PHASE_SACRIFICE = 5,
|
||||
|
||||
EVENT_GROUP_SPEACH = 1,
|
||||
ACTION_START_POST_EVENT = 1,
|
||||
ACTION_NO_KILL_TALK = 2,
|
||||
|
||||
// Text events
|
||||
EVENT_TEXT_SPEACH11 = 1,
|
||||
EVENT_TEXT_SPEACH21 = 2,
|
||||
EVENT_TEXT_SPEACH22 = 3,
|
||||
EVENT_TEXT_SPEACH23 = 4,
|
||||
EVENT_TEXT_SPEACH31 = 5,
|
||||
EVENT_TEXT_SPEACH32 = 6,
|
||||
EVENT_TEXT_SPEACH33 = 7,
|
||||
EVENT_TEXT_SPEACH41 = 8,
|
||||
EVENT_TEXT_SPEACH42 = 9,
|
||||
EVENT_TEXT_SPEACH43 = 10,
|
||||
EVENT_TEXT_SPEACH44 = 11,
|
||||
EVENT_TEXT_SPEACH45 = 12,
|
||||
EVENT_TEXT_SPEACH46 = 13,
|
||||
|
||||
// Controller events
|
||||
EVENT_RANDOM_TALK = 40,
|
||||
EVENT_CHECK_PLAYERS = 41,
|
||||
|
||||
// Misc fight events
|
||||
EVENT_REBIRTH = 50,
|
||||
EVENT_INIT_FIGHT = 51,
|
||||
EVENT_CHECK_HEALTH85 = 52,
|
||||
EVENT_CHECK_HEALTH55 = 53,
|
||||
EVENT_CHECK_HEALTH25 = 54,
|
||||
EVENT_EMPOWER_ORBS1 = 55,
|
||||
EVENT_EMPOWER_ORBS2 = 56,
|
||||
EVENT_EMPOWER_ORBS3 = 57,
|
||||
EVENT_RESTORE_MELEE = 58,
|
||||
EVENT_KILL_SELF = 59,
|
||||
EVENT_NO_KILL_TALK = 60,
|
||||
|
||||
// Abilities events
|
||||
EVENT_SPELL_SOUL_FLAY = 100,
|
||||
EVENT_SPELL_LEGION_LIGHTNING = 101,
|
||||
EVENT_SPELL_FIRE_BLOOM = 102,
|
||||
EVENT_SUMMON_ORBS = 103,
|
||||
EVENT_SPELL_SHADOW_SPIKE = 104,
|
||||
EVENT_SPELL_SINISTER_REFLECTION = 105,
|
||||
EVENT_SPELL_FLAME_DART = 106,
|
||||
EVENT_SPELL_DARKNESS = 107,
|
||||
EVENT_SPELL_ARMAGEDDON = 108,
|
||||
ACTION_NO_KILL_TALK = 2
|
||||
};
|
||||
|
||||
class CastArmageddon : public BasicEvent
|
||||
{
|
||||
public:
|
||||
CastArmageddon(Creature* caster) : _caster(caster)
|
||||
{
|
||||
}
|
||||
CastArmageddon(Creature* caster) : _caster(caster) { }
|
||||
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
@@ -168,12 +122,12 @@ struct npc_kiljaeden_controller : public NullCreatureAI
|
||||
npc_kiljaeden_controller(Creature* creature) : NullCreatureAI(creature), summons(me)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
SummonList summons;
|
||||
|
||||
void ResetOrbs()
|
||||
{
|
||||
for (uint8 i = DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1; i < DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4 + 1; ++i)
|
||||
@@ -184,7 +138,6 @@ struct npc_kiljaeden_controller : public NullCreatureAI
|
||||
void Reset() override
|
||||
{
|
||||
instance->SetBossState(DATA_KILJAEDEN, NOT_STARTED);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
ResetOrbs();
|
||||
|
||||
@@ -193,9 +146,15 @@ struct npc_kiljaeden_controller : public NullCreatureAI
|
||||
me->SummonCreature(NPC_HAND_OF_THE_DECEIVER, 1688.38f, 641.10f, 27.50f, 5.43f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
|
||||
me->SummonCreature(NPC_ANVEENA, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 40.0f, 0.0f);
|
||||
|
||||
me->CastSpell(me, SPELL_DESTROY_ALL_DRAKES, true);
|
||||
me->CastSpell(me, SPELL_ANVEENA_ENERGY_DRAIN, true);
|
||||
events.ScheduleEvent(EVENT_RANDOM_TALK, 60000);
|
||||
DoCastAOE(SPELL_DESTROY_ALL_DRAKES, true);
|
||||
DoCastSelf(SPELL_ANVEENA_ENERGY_DRAIN, true);
|
||||
|
||||
scheduler.Schedule(1min, [this](TaskContext context) {
|
||||
if (instance->GetBossState(DATA_KILJAEDEN) == NOT_STARTED)
|
||||
Talk(SAY_KJ_OFFCOMBAT);
|
||||
|
||||
context.Repeat(90s, 3min);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
@@ -206,7 +165,7 @@ struct npc_kiljaeden_controller : public NullCreatureAI
|
||||
summons.DoAction(ACTION_START_POST_EVENT, kalCheck);
|
||||
summons.DespawnIf(kalCheck);
|
||||
|
||||
me->CastSpell(me, SPELL_DESTROY_ALL_DRAKES, true);
|
||||
DoCastAOE(SPELL_DESTROY_ALL_DRAKES, true);
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
@@ -226,7 +185,19 @@ struct npc_kiljaeden_controller : public NullCreatureAI
|
||||
if (summon->GetEntry() == NPC_HAND_OF_THE_DECEIVER)
|
||||
{
|
||||
instance->SetBossState(DATA_KILJAEDEN, IN_PROGRESS);
|
||||
events.ScheduleEvent(EVENT_CHECK_PLAYERS, 1000);
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context) {
|
||||
auto const& playerList = me->GetMap()->GetPlayers();
|
||||
for (auto const& playerRef : playerList)
|
||||
if (Player* player = playerRef.GetSource())
|
||||
if (!player->IsGameMaster() && me->GetDistance2d(player) < 60.0f && player->IsAlive())
|
||||
{
|
||||
context.Repeat();
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureAI::EnterEvadeMode();
|
||||
});
|
||||
|
||||
if (!summons.HasEntry(NPC_HAND_OF_THE_DECEIVER))
|
||||
{
|
||||
@@ -239,61 +210,239 @@ struct npc_kiljaeden_controller : public NullCreatureAI
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_RANDOM_TALK:
|
||||
if (instance->GetBossState(DATA_KILJAEDEN) == NOT_STARTED)
|
||||
Talk(SAY_KJ_OFFCOMBAT);
|
||||
events.ScheduleEvent(EVENT_RANDOM_TALK, urand(90000, 180000));
|
||||
break;
|
||||
case EVENT_CHECK_PLAYERS:
|
||||
{
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
if (Player* player = itr->GetSource())
|
||||
if (!player->IsGameMaster() && me->GetDistance2d(player) < 60.0f && player->IsAlive())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_CHECK_PLAYERS, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureAI::EnterEvadeMode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
SummonList summons;
|
||||
};
|
||||
|
||||
struct boss_kiljaeden : public ScriptedAI
|
||||
struct boss_kiljaeden : public BossAI
|
||||
{
|
||||
boss_kiljaeden(Creature* creature) : ScriptedAI(creature)
|
||||
boss_kiljaeden(Creature* creature) : BossAI(creature, DATA_KILJAEDEN)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
EventMap events2;
|
||||
uint8 phase;
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
ScriptedAI::InitializeAI();
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
phase = PHASE_NORMAL;
|
||||
events.Reset();
|
||||
events2.Reset();
|
||||
events2.ScheduleEvent(EVENT_INIT_FIGHT, 11000);
|
||||
events2.ScheduleEvent(EVENT_REBIRTH, 0);
|
||||
me->SetVisible(false);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetVisible(true);
|
||||
DoCastSelf(SPELL_REBIRTH);
|
||||
}, 1s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetInCombatWithZone();
|
||||
}, 11s);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
_phase = PHASE_NORMAL;
|
||||
|
||||
ScheduleHealthCheckEvent(85, [&]{
|
||||
_phase = PHASE_DARKNESS;
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_AWAKEN, 16s);
|
||||
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
anveena->AI()->Talk(SAY_ANVEENA_IMPRISONED, 22s);
|
||||
|
||||
Talk(SAY_KJ_PHASE3, 28s);
|
||||
|
||||
scheduler.CancelAll();
|
||||
|
||||
ScheduleBasicAbilities();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_READY1);
|
||||
EmpowerOrb(false);
|
||||
}, 35s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(SAY_KJ_REFLECTION);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
}, 1s);
|
||||
|
||||
scheduler.Schedule(1s+200ms, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_SHADOW_SPIKE);
|
||||
});
|
||||
|
||||
ScheduleTimedEvent(3s, [&] {
|
||||
DoCastSelf(SPELL_FLAME_DART);
|
||||
}, 10s);
|
||||
|
||||
ScheduleTimedEvent(16s, [&] {
|
||||
Talk(EMOTE_KJ_DARKNESS);
|
||||
DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS);
|
||||
}, 45s);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(55, [&] {
|
||||
_phase = PHASE_ARMAGEDDON;
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_LETGO, 16s);
|
||||
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
anveena->AI()->Talk(SAY_ANVEENA_LOST, 22s);
|
||||
|
||||
Talk(SAY_KJ_PHASE4, 28s);
|
||||
|
||||
scheduler.CancelAll();
|
||||
|
||||
ScheduleBasicAbilities();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_READY2);
|
||||
EmpowerOrb(false);
|
||||
}, 35s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(SAY_KJ_REFLECTION);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
}, 1s);
|
||||
|
||||
scheduler.Schedule(1s + 200ms, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_SHADOW_SPIKE);
|
||||
});
|
||||
|
||||
ScheduleTimedEvent(15s, [&] {
|
||||
Talk(EMOTE_KJ_DARKNESS);
|
||||
DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS);
|
||||
}, 45s);
|
||||
|
||||
ScheduleTimedEvent(10s, [&] {
|
||||
DoCastSelf(SPELL_ARMAGEDDON_PERIODIC, true);
|
||||
}, 40s);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(25, [&] {
|
||||
_phase = PHASE_SACRIFICE;
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
{
|
||||
kalec->AI()->Talk(SAY_KALECGOS_FOCUS, 8s);
|
||||
kalec->AI()->Talk(SAY_KALECGOS_FATE, 20s + 200ms);
|
||||
}
|
||||
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
{
|
||||
anveena->AI()->Talk(SAY_ANVEENA_KALEC, 18s);
|
||||
anveena->AI()->Talk(SAY_ANVEENA_GOODBYE, 25s);
|
||||
}
|
||||
|
||||
scheduler.CancelAll();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
{
|
||||
anveena->RemoveAllAuras();
|
||||
anveena->DespawnOrUnsummon(3500);
|
||||
}
|
||||
}, 28s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
{
|
||||
anveena->CastSpell(anveena, SPELL_SACRIFICE_OF_ANVEENA, true);
|
||||
DoCastSelf(SPELL_CUSTOM_08_STATE, true);
|
||||
me->SetUnitFlag(UNIT_FLAG_PACIFIED);
|
||||
scheduler.DelayAll(7100ms);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->RemoveAurasDueToSpell(SPELL_CUSTOM_08_STATE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_PACIFIED);
|
||||
|
||||
ScheduleBasicAbilities();
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(SAY_KJ_REFLECTION);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
}, 1s);
|
||||
|
||||
ScheduleTimedEvent(15s, [&] {
|
||||
Talk(EMOTE_KJ_DARKNESS);
|
||||
DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS);
|
||||
}, 25s);
|
||||
|
||||
ScheduleTimedEvent(1500ms, [&] {
|
||||
DoCastSelf(SPELL_ARMAGEDDON_PERIODIC, true);
|
||||
}, 20s);
|
||||
}, 7s);
|
||||
}
|
||||
Talk(SAY_KJ_PHASE5);
|
||||
}, 30s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_READY_ALL);
|
||||
EmpowerOrb(true);
|
||||
}, 61s);
|
||||
});
|
||||
}
|
||||
|
||||
void ScheduleBasicAbilities()
|
||||
{
|
||||
ScheduleTimedEvent(1s, [&] {
|
||||
DoCastVictim(SPELL_SOUL_FLAY);
|
||||
}, 4s, 5s);
|
||||
|
||||
ScheduleTimedEvent(7s, [&] {
|
||||
DoCastRandomTarget(SPELL_LEGION_LIGHTNING, 0, 40.0f);
|
||||
}, _phase == PHASE_SACRIFICE ? 15s : 30s);
|
||||
|
||||
ScheduleTimedEvent(9s, [&] {
|
||||
me->CastCustomSpell(SPELL_FIRE_BLOOM, SPELLVALUE_MAX_TARGETS, 5, me, TRIGGERED_NONE);
|
||||
me->SetTarget(me->GetVictim()->GetGUID());
|
||||
}, _phase == PHASE_SACRIFICE ? 20s : 40s);
|
||||
|
||||
if (_phase != PHASE_SACRIFICE)
|
||||
{
|
||||
ScheduleTimedEvent(10s, [&] {
|
||||
for (uint8 i = 1; i < _phase; ++i)
|
||||
{
|
||||
float x = me->GetPositionX() + 18.0f * cos((i * 2.0f - 1.0f) * M_PI / 3.0f);
|
||||
float y = me->GetPositionY() + 18.0f * std::sin((i * 2.0f - 1.0f) * M_PI / 3.0f);
|
||||
if (Creature* orb = me->SummonCreature(NPC_SHIELD_ORB, x, y, 40.0f, 0, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
{
|
||||
Movement::PointsArray movementArray;
|
||||
movementArray.push_back(G3D::Vector3(x, y, 40.0f));
|
||||
|
||||
// generate movement array
|
||||
for (uint8 j = 1; j < 20; ++j)
|
||||
{
|
||||
x = me->GetPositionX() + 18.0f * cos(((i * 2.0f - 1.0f) * M_PI / 3.0f) + (j / 20.0f * 2 * M_PI));
|
||||
y = me->GetPositionY() + 18.0f * std::sin(((i * 2.0f - 1.0f) * M_PI / 3.0f) + (j / 20.0f * 2 * M_PI));
|
||||
movementArray.push_back(G3D::Vector3(x, y, 40.0f));
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(orb);
|
||||
init.MovebyPath(movementArray);
|
||||
init.SetCyclic();
|
||||
init.Launch();
|
||||
}
|
||||
}
|
||||
}, 40s);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
@@ -310,8 +459,10 @@ struct boss_kiljaeden : public ScriptedAI
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
void DamageTaken(Unit* unit, uint32& damage, DamageEffectType damageType, SpellSchoolMask schoolMask) override
|
||||
{
|
||||
BossAI::DamageTaken(unit, damage, damageType, schoolMask);
|
||||
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
me->SetTarget();
|
||||
@@ -323,9 +474,10 @@ struct boss_kiljaeden : public ScriptedAI
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_DROWN);
|
||||
me->resetAttackTimer();
|
||||
events.Reset();
|
||||
events2.Reset();
|
||||
events2.ScheduleEvent(EVENT_KILL_SELF, 500);
|
||||
damage = 0;
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
me->KillSelf();
|
||||
}, 1s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,37 +486,28 @@ struct boss_kiljaeden : public ScriptedAI
|
||||
Talk(SAY_KJ_DEATH);
|
||||
instance->SetBossState(DATA_KILJAEDEN, DONE);
|
||||
if (Creature* controller = instance->GetCreature(DATA_KJ_CONTROLLER))
|
||||
Unit::Kill(controller, controller);
|
||||
controller->KillSelf();
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_NO_KILL_TALK)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_NO_KILL_TALK, 0);
|
||||
Talk(SAY_KJ_DARKNESS);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer() && events.GetNextEventTime(EVENT_NO_KILL_TALK) == 0)
|
||||
if (victim->IsPlayer())
|
||||
Talk(SAY_KJ_SLAY);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH11, 26000, EVENT_GROUP_SPEACH);
|
||||
Talk(SAY_KJ_EMERGE);
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_JOIN, 26s);
|
||||
|
||||
events.SetTimer(200000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH85, 1000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH55, 1000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH25, 1000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SOUL_FLAY, 0);
|
||||
events.ScheduleEvent(EVENT_SPELL_LEGION_LIGHTNING, 7000);
|
||||
events.ScheduleEvent(EVENT_SPELL_FIRE_BLOOM, 9000);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ORBS, 10000);
|
||||
Talk(SAY_KJ_EMERGE);
|
||||
ScheduleBasicAbilities();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
@@ -382,247 +525,14 @@ struct boss_kiljaeden : public ScriptedAI
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
switch (events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_KILL_SELF:
|
||||
me->KillSelf();
|
||||
break;
|
||||
case EVENT_REBIRTH:
|
||||
me->SetVisible(true);
|
||||
me->CastSpell(me, SPELL_REBIRTH, false);
|
||||
break;
|
||||
case EVENT_EMPOWER_ORBS1:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_READY1);
|
||||
EmpowerOrb(false);
|
||||
break;
|
||||
case EVENT_EMPOWER_ORBS2:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_READY2);
|
||||
EmpowerOrb(false);
|
||||
break;
|
||||
case EVENT_EMPOWER_ORBS3:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_READY_ALL);
|
||||
EmpowerOrb(true);
|
||||
break;
|
||||
case EVENT_INIT_FIGHT:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetInCombatWithZone();
|
||||
return;
|
||||
case EVENT_TEXT_SPEACH11:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_JOIN);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH21:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_AWAKEN);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH22:
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
sCreatureTextMgr->SendChat(anveena, SAY_ANVEENA_IMPRISONED, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH23:
|
||||
Talk(SAY_KJ_PHASE3);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH31:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_LETGO);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH32:
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
sCreatureTextMgr->SendChat(anveena, SAY_ANVEENA_LOST, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH33:
|
||||
Talk(SAY_KJ_PHASE4);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH41:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_FOCUS);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH42:
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
sCreatureTextMgr->SendChat(anveena, SAY_ANVEENA_KALEC, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH43:
|
||||
if (Creature* kalec = instance->GetCreature(DATA_KALECGOS_KJ))
|
||||
kalec->AI()->Talk(SAY_KALECGOS_FATE);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH44:
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
sCreatureTextMgr->SendChat(anveena, SAY_ANVEENA_GOODBYE, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE);
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH45:
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
{
|
||||
anveena->RemoveAllAuras();
|
||||
anveena->DespawnOrUnsummon(3500);
|
||||
}
|
||||
break;
|
||||
case EVENT_TEXT_SPEACH46:
|
||||
if (Creature* anveena = instance->GetCreature(DATA_ANVEENA))
|
||||
{
|
||||
anveena->CastSpell(anveena, SPELL_SACRIFICE_OF_ANVEENA, true);
|
||||
me->CastSpell(me, SPELL_CUSTOM_08_STATE, true);
|
||||
me->SetUnitFlag(UNIT_FLAG_PACIFIED);
|
||||
events.DelayEvents(7001);
|
||||
events2.ScheduleEvent(EVENT_RESTORE_MELEE, 7000);
|
||||
}
|
||||
Talk(SAY_KJ_PHASE5);
|
||||
break;
|
||||
case EVENT_RESTORE_MELEE:
|
||||
me->RemoveAurasDueToSpell(SPELL_CUSTOM_08_STATE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_PACIFIED);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->GetReactState() != REACT_AGGRESSIVE)
|
||||
return;
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_CHECK_HEALTH85:
|
||||
if (me->HealthBelowPct(85))
|
||||
{
|
||||
phase = PHASE_DARKNESS;
|
||||
events2.CancelEvent(EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH21, 16000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH22, 22000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH23, 28000, EVENT_GROUP_SPEACH);
|
||||
events2.RescheduleEvent(EVENT_EMPOWER_ORBS1, 35000);
|
||||
|
||||
events.DelayEvents(2000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SINISTER_REFLECTION, 500);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOW_SPIKE, 1200);
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAME_DART, 3000);
|
||||
events.RescheduleEvent(EVENT_SPELL_DARKNESS, 16000); // will be delayed by 29 secs
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH85, 0);
|
||||
break;
|
||||
|
||||
case EVENT_CHECK_HEALTH55:
|
||||
if (me->HealthBelowPct(55))
|
||||
{
|
||||
phase = PHASE_ARMAGEDDON;
|
||||
events2.CancelEventGroup(EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH31, 16000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH32, 22000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH33, 28000, EVENT_GROUP_SPEACH);
|
||||
events2.RescheduleEvent(EVENT_EMPOWER_ORBS2, 35000);
|
||||
|
||||
events.DelayEvents(2000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SINISTER_REFLECTION, 500);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOW_SPIKE, 1200);
|
||||
events.RescheduleEvent(EVENT_SPELL_DARKNESS, 15000); // will be delayed by 29 secs
|
||||
events.ScheduleEvent(EVENT_SPELL_ARMAGEDDON, 10000);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH55, 0);
|
||||
break;
|
||||
|
||||
case EVENT_CHECK_HEALTH25:
|
||||
if (me->HealthBelowPct(25))
|
||||
{
|
||||
phase = PHASE_SACRIFICE;
|
||||
events2.CancelEventGroup(EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH41, 8000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH42, 18000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH43, 20200, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH44, 25000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH45, 28000, EVENT_GROUP_SPEACH);
|
||||
events2.ScheduleEvent(EVENT_TEXT_SPEACH46, 30000, EVENT_GROUP_SPEACH);
|
||||
events2.RescheduleEvent(EVENT_EMPOWER_ORBS3, 61000);
|
||||
|
||||
events.CancelEvent(EVENT_SUMMON_ORBS);
|
||||
events.DelayEvents(4000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SINISTER_REFLECTION, 500);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOW_SPIKE, 1200);
|
||||
events.RescheduleEvent(EVENT_SPELL_DARKNESS, 15000); // will be delayed by 29 secs
|
||||
events.ScheduleEvent(EVENT_SPELL_ARMAGEDDON, 1500);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH25, 0);
|
||||
break;
|
||||
case EVENT_SPELL_SOUL_FLAY:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SOUL_FLAY, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_SOUL_FLAY, urand(4000, 5000));
|
||||
break;
|
||||
case EVENT_SPELL_LEGION_LIGHTNING:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
me->CastSpell(target, SPELL_LEGION_LIGHTNING, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_LEGION_LIGHTNING, phase == PHASE_SACRIFICE ? 15000 : 30000);
|
||||
events.RescheduleEvent(EVENT_SPELL_SOUL_FLAY, 2000);
|
||||
break;
|
||||
case EVENT_SPELL_FIRE_BLOOM:
|
||||
me->CastCustomSpell(SPELL_FIRE_BLOOM, SPELLVALUE_MAX_TARGETS, 5, me, TRIGGERED_NONE);
|
||||
me->SetTarget(me->GetVictim()->GetGUID());
|
||||
events.ScheduleEvent(EVENT_SPELL_FIRE_BLOOM, phase == PHASE_SACRIFICE ? 20000 : 40000);
|
||||
events.RescheduleEvent(EVENT_SPELL_SOUL_FLAY, 1500);
|
||||
break;
|
||||
case EVENT_SUMMON_ORBS:
|
||||
for (uint8 i = 1; i < phase; ++i)
|
||||
{
|
||||
float x = me->GetPositionX() + 18.0f * cos((i * 2.0f - 1.0f) * M_PI / 3.0f);
|
||||
float y = me->GetPositionY() + 18.0f * std::sin((i * 2.0f - 1.0f) * M_PI / 3.0f);
|
||||
if (Creature* orb = me->SummonCreature(NPC_SHIELD_ORB, x, y, 40.0f, 0, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
{
|
||||
Movement::PointsArray movementArray;
|
||||
movementArray.push_back(G3D::Vector3(x, y, 40.0f));
|
||||
|
||||
// generate movement array
|
||||
for (uint8 j = 1; j < 20; ++j)
|
||||
{
|
||||
x = me->GetPositionX() + 18.0f * cos(((i * 2.0f - 1.0f) * M_PI / 3.0f) + (j / 20.0f * 2 * M_PI));
|
||||
y = me->GetPositionY() + 18.0f * std::sin(((i * 2.0f - 1.0f) * M_PI / 3.0f) + (j / 20.0f * 2 * M_PI));
|
||||
movementArray.push_back(G3D::Vector3(x, y, 40.0f));
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(orb);
|
||||
init.MovebyPath(movementArray);
|
||||
init.SetCyclic();
|
||||
init.Launch();
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUMMON_ORBS, 40000);
|
||||
break;
|
||||
case EVENT_SPELL_SHADOW_SPIKE:
|
||||
events.DelayEvents(27000);
|
||||
me->CastSpell(me, SPELL_SHADOW_SPIKE, false);
|
||||
break;
|
||||
case EVENT_SPELL_SINISTER_REFLECTION:
|
||||
Talk(SAY_KJ_REFLECTION);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
me->CastCustomSpell(SPELL_SINISTER_REFLECTION, SPELLVALUE_MAX_TARGETS, 1, me, TRIGGERED_NONE);
|
||||
break;
|
||||
case EVENT_SPELL_FLAME_DART:
|
||||
me->CastSpell(me, SPELL_FLAME_DART, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAME_DART, 10000);
|
||||
break;
|
||||
case EVENT_SPELL_DARKNESS:
|
||||
Talk(EMOTE_KJ_DARKNESS);
|
||||
me->CastSpell(me, SPELL_DARKNESS_OF_A_THOUSAND_SOULS, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_DARKNESS, phase == PHASE_SACRIFICE ? 20000 : 45000);
|
||||
events.DelayEvents(8000);
|
||||
break;
|
||||
case EVENT_SPELL_ARMAGEDDON:
|
||||
me->CastSpell(me, SPELL_ARMAGEDDON_PERIODIC, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_ARMAGEDDON, phase == PHASE_SACRIFICE ? 20000 : 40000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
void EmpowerOrb(bool empowerAll)
|
||||
@@ -647,6 +557,9 @@ struct boss_kiljaeden : public ScriptedAI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _phase;
|
||||
};
|
||||
|
||||
enum postEvent
|
||||
@@ -712,9 +625,7 @@ enum postEvent
|
||||
class MoveDelayed : public BasicEvent
|
||||
{
|
||||
public:
|
||||
MoveDelayed(Creature* owner, float x, float y, float z, float o) : _owner(owner), _x(x), _y(y), _z(z), _o(o)
|
||||
{
|
||||
}
|
||||
MoveDelayed(Creature* owner, float x, float y, float z, float o) : _owner(owner), _x(x), _y(y), _z(z), _o(o) { }
|
||||
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
@@ -733,9 +644,7 @@ private:
|
||||
class FixOrientation : public BasicEvent
|
||||
{
|
||||
public:
|
||||
FixOrientation(Creature* owner) : _owner(owner)
|
||||
{
|
||||
}
|
||||
FixOrientation(Creature* owner) : _owner(owner) { }
|
||||
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@ ObjectData const creatureData[] =
|
||||
{ NPC_KILJAEDEN_CONTROLLER, DATA_KJ_CONTROLLER },
|
||||
{ NPC_ANVEENA, DATA_ANVEENA },
|
||||
{ NPC_KALECGOS_KJ, DATA_KALECGOS_KJ },
|
||||
{ 0, 0, }
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
ObjectData const gameObjectData[] =
|
||||
@@ -59,6 +59,20 @@ ObjectData const gameObjectData[] =
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
ObjectData const summonData[] =
|
||||
{
|
||||
{ NPC_DEMONIC_VAPOR_TRAIL, DATA_FELMYST },
|
||||
{ NPC_UNYIELDING_DEAD, DATA_FELMYST },
|
||||
{ NPC_DARKNESS, DATA_MURU },
|
||||
{ NPC_VOID_SENTINEL, DATA_MURU },
|
||||
{ NPC_VOID_SPAWN, DATA_MURU },
|
||||
{ NPC_FELFIRE_PORTAL, DATA_KJ_CONTROLLER },
|
||||
{ NPC_VOLATILE_FELFIRE_FIEND, DATA_KJ_CONTROLLER },
|
||||
{ NPC_SHIELD_ORB, DATA_KJ_CONTROLLER },
|
||||
{ NPC_SINISTER_REFLECTION, DATA_KJ_CONTROLLER },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
class instance_sunwell_plateau : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -72,6 +86,7 @@ public:
|
||||
SetBossNumber(MAX_ENCOUNTERS);
|
||||
LoadDoorData(doorData);
|
||||
LoadObjectData(creatureData, gameObjectData);
|
||||
LoadSummonData(summonData);
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
@@ -87,32 +102,6 @@ public:
|
||||
if (creature->GetSpawnId() > 0 || !creature->GetOwnerGUID().IsPlayer())
|
||||
creature->CastSpell(creature, SPELL_SUNWELL_RADIANCE, true);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_DEMONIC_VAPOR_TRAIL:
|
||||
case NPC_UNYIELDING_DEAD:
|
||||
if (Creature* felmyst = GetCreature(DATA_FELMYST))
|
||||
felmyst->AI()->JustSummoned(creature);
|
||||
break;
|
||||
|
||||
case NPC_DARKNESS:
|
||||
case NPC_VOID_SENTINEL:
|
||||
case NPC_VOID_SPAWN:
|
||||
if (Creature* muru = GetCreature(DATA_MURU))
|
||||
muru->AI()->JustSummoned(creature);
|
||||
break;
|
||||
|
||||
case NPC_FELFIRE_PORTAL:
|
||||
case NPC_VOLATILE_FELFIRE_FIEND:
|
||||
case NPC_SHIELD_ORB:
|
||||
case NPC_SINISTER_REFLECTION:
|
||||
if (Creature* kiljaedenC = GetCreature(DATA_KJ_CONTROLLER))
|
||||
kiljaedenC->AI()->JustSummoned(creature);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,24 +52,22 @@ enum Says
|
||||
|
||||
enum Misc
|
||||
{
|
||||
ACTION_INCREASE_STORM_COUNT = 1
|
||||
ACTION_STORM_EXPIRE = 1,
|
||||
GROUP_ELECTRICAL_STORM = 1
|
||||
};
|
||||
|
||||
constexpr auto NPC_SOARING_EAGLE = 24858;
|
||||
|
||||
struct boss_akilzon : public BossAI
|
||||
{
|
||||
boss_akilzon(Creature* creature) : BossAI(creature, DATA_AKILZON), _stormCount(0), _isRaining(false) { }
|
||||
boss_akilzon(Creature* creature) : BossAI(creature, DATA_AKILZON), _isRaining(false) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
_targetGUID.Clear();
|
||||
_cloudGUID.Clear();
|
||||
_cycloneGUID.Clear();
|
||||
|
||||
_stormCount = 0;
|
||||
_isRaining = false;
|
||||
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
@@ -94,18 +92,16 @@ struct boss_akilzon : public BossAI
|
||||
}, 10s, 18s);
|
||||
|
||||
ScheduleTimedEvent(20s, 30s, [&] {
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 1);
|
||||
if (!target)
|
||||
target = me->GetVictim();
|
||||
if (target)
|
||||
DoCast(target, SPELL_GUST_OF_WIND);
|
||||
if (scheduler.GetNextGroupOcurrence(GROUP_ELECTRICAL_STORM) > 5s)
|
||||
DoCastRandomTarget(SPELL_GUST_OF_WIND, 1);
|
||||
}, 20s, 30s);
|
||||
|
||||
ScheduleTimedEvent(10s, 20s, [&] {
|
||||
DoCastVictim(SPELL_CALL_LIGHTNING);
|
||||
}, 12s, 17s);
|
||||
|
||||
ScheduleTimedEvent(1min, [&] {
|
||||
scheduler.Schedule(1min, GROUP_ELECTRICAL_STORM, [this](TaskContext context)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50, true);
|
||||
if (!target)
|
||||
{
|
||||
@@ -114,29 +110,14 @@ struct boss_akilzon : public BossAI
|
||||
}
|
||||
target->CastSpell(target, SPELL_ELECTRICAL_STORM_AREA, true); // cloud visual
|
||||
DoCast(target, SPELL_ELECTRICAL_STORM); // storm cyclon + visual
|
||||
|
||||
float x, y, z;
|
||||
target->GetPosition(x, y, z);
|
||||
target->GetMotionMaster()->MoveJump(x, y, target->GetPositionZ() + 16.0f, 1.0f, 1.0f);
|
||||
|
||||
Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ() + 16, 0, 15000);
|
||||
if (Cloud)
|
||||
{
|
||||
target->GetMotionMaster()->MoveJump(Cloud->GetPosition(), 1.0f, 1.0f);
|
||||
|
||||
_cloudGUID = Cloud->GetGUID();
|
||||
Cloud->SetDisableGravity(true);
|
||||
Cloud->StopMoving();
|
||||
Cloud->SetObjectScale(1.0f);
|
||||
Cloud->SetFaction(FACTION_FRIENDLY);
|
||||
Cloud->SetMaxHealth(9999999);
|
||||
Cloud->SetHealth(9999999);
|
||||
Cloud->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
HandleStormSequence();
|
||||
}, 3s);
|
||||
}
|
||||
|
||||
_stormCount = 1;
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
HandleStormSequence();
|
||||
}, 3s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (!_isRaining)
|
||||
@@ -145,7 +126,9 @@ struct boss_akilzon : public BossAI
|
||||
_isRaining = true;
|
||||
}
|
||||
}, Seconds(urand(47, 52)));
|
||||
}, 1min);
|
||||
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
ScheduleTimedEvent(47s, 52s, [&] {
|
||||
if (!_isRaining)
|
||||
@@ -181,42 +164,26 @@ struct boss_akilzon : public BossAI
|
||||
me->GetMap()->SetZoneWeather(me->GetZoneId(), WeatherState(weather), grade);
|
||||
}
|
||||
|
||||
void HandleStormSequence() // 1: begin, 2-9: tick, 10: end
|
||||
void HandleStormSequence()
|
||||
{
|
||||
Creature* Cloud = ObjectAccessor::GetCreature(*me, _cloudGUID);
|
||||
if (!Cloud)
|
||||
return;
|
||||
|
||||
if (_stormCount > 10)
|
||||
{
|
||||
_stormCount = 0; // finish
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
SummonEagles();
|
||||
}, 5s);
|
||||
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
_cloudGUID.Clear();
|
||||
if (Cloud)
|
||||
Cloud->KillSelf();
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
_isRaining = false;
|
||||
}
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, _cloudGUID);
|
||||
if (!target || !target->IsAlive())
|
||||
return;
|
||||
else if (Unit* Cyclone = ObjectAccessor::GetUnit(*me, _cycloneGUID))
|
||||
Cyclone->CastSpell(target, SPELL_SAND_STORM, true); // keep casting or...
|
||||
HandleStormSequence();
|
||||
}, 1s);
|
||||
}
|
||||
|
||||
void DoAction(int32 actionId) override
|
||||
{
|
||||
if (actionId == ACTION_INCREASE_STORM_COUNT)
|
||||
++_stormCount;
|
||||
if (actionId == ACTION_STORM_EXPIRE)
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
SummonEagles();
|
||||
}, 5s);
|
||||
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
_isRaining = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SummonEagles()
|
||||
@@ -254,8 +221,6 @@ private:
|
||||
ObjectGuid _birdGUIDs[8];
|
||||
ObjectGuid _targetGUID;
|
||||
ObjectGuid _cycloneGUID;
|
||||
ObjectGuid _cloudGUID;
|
||||
uint8 _stormCount;
|
||||
bool _isRaining;
|
||||
};
|
||||
|
||||
@@ -339,15 +304,15 @@ class spell_electrial_storm : public AuraScript
|
||||
return GetCaster() && GetCaster()->IsCreature();
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetCaster())
|
||||
GetCaster()->ToCreature()->AI()->DoAction(ACTION_INCREASE_STORM_COUNT);
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
GetCaster()->ToCreature()->AI()->DoAction(ACTION_STORM_EXPIRE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_electrial_storm::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_electrial_storm::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,56 +27,61 @@ enum Spells
|
||||
SPELL_FRENZY = 43139,
|
||||
SPELL_FLAMESHOCK = 43303,
|
||||
SPELL_EARTHSHOCK = 43305,
|
||||
SPELL_TRANSFORM_SPLIT = 43142,
|
||||
SPELL_TRANSFORM_SPLIT2 = 43573,
|
||||
SPELL_TRANSFORM_MERGE = 43271,
|
||||
SPELL_SUMMON_LYNX = 43143,
|
||||
SPELL_SUMMON_TOTEM = 43302,
|
||||
SPELL_BERSERK = 45078,
|
||||
SPELL_LYNX_FRENZY = 43290, // Used by Spirit Lynx
|
||||
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
|
||||
SPELL_SHRED_ARMOR = 43243, // Used by Spirit Lynx
|
||||
SPELL_TRANSFORM_DUMMY = 43615, // Used by Spirit Lynx
|
||||
|
||||
SPELL_TRANSFIGURE = 44054,
|
||||
SPELL_TRANSFORM_TO_LYNX_75 = 43145,
|
||||
SPELL_TRANSFORM_TO_LYNX_50 = 43271,
|
||||
SPELL_TRANSFORM_TO_LYNX_25 = 43272
|
||||
};
|
||||
|
||||
enum UniqueEvents
|
||||
{
|
||||
EVENT_BERSERK = 0
|
||||
EVENT_BERSERK = 1
|
||||
};
|
||||
|
||||
enum Hal_CreatureIds
|
||||
{
|
||||
NPC_TOTEM = 24224
|
||||
NPC_HALAZZI_TROLL = 24144, // dummy creature - used to update model, stats
|
||||
NPC_TOTEM = 24224
|
||||
};
|
||||
|
||||
enum PhaseHalazzi
|
||||
{
|
||||
PHASE_NONE = 0,
|
||||
PHASE_LYNX = 1,
|
||||
PHASE_SPLIT = 2,
|
||||
PHASE_HUMAN = 3,
|
||||
PHASE_MERGE = 4,
|
||||
PHASE_ENRAGE = 5
|
||||
PHASE_NONE = 0,
|
||||
PHASE_LYNX = 1,
|
||||
PHASE_SPLIT = 2,
|
||||
PHASE_HUMAN = 3,
|
||||
PHASE_MERGE = 4,
|
||||
PHASE_ENRAGE = 5
|
||||
};
|
||||
|
||||
enum Yells
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_KILL = 1,
|
||||
SAY_SABER = 2,
|
||||
SAY_SPLIT = 3,
|
||||
SAY_MERGE = 4,
|
||||
SAY_DEATH = 5
|
||||
SAY_AGGRO = 0,
|
||||
SAY_KILL = 1,
|
||||
SAY_SABER = 2,
|
||||
SAY_SPLIT = 3,
|
||||
SAY_MERGE = 4,
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
|
||||
enum Groups
|
||||
{
|
||||
GROUP_LYNX = 0,
|
||||
GROUP_HUMAN = 1,
|
||||
GROUP_MERGE = 2
|
||||
GROUP_LYNX = 0,
|
||||
GROUP_HUMAN = 1,
|
||||
GROUP_MERGE = 3,
|
||||
GROUP_SPLIT = 4
|
||||
};
|
||||
|
||||
enum Actions
|
||||
{
|
||||
ACTION_MERGE = 0
|
||||
ACTION_MERGE = 0
|
||||
};
|
||||
|
||||
struct boss_halazzi : public BossAI
|
||||
@@ -91,22 +96,11 @@ struct boss_halazzi : public BossAI
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->UpdateEntry(NPC_HALAZZI);
|
||||
BossAI::Reset();
|
||||
_transformCount = 0;
|
||||
_healthCheckPercentage = 0;
|
||||
_phase = PHASE_NONE;
|
||||
_lynxFormHealth = me->GetMaxHealth();
|
||||
_healthPortion = _lynxFormHealth/4;
|
||||
_humanFormHealth = (me->GetMaxHealth())/0.66666666;
|
||||
EnterPhase(PHASE_LYNX);
|
||||
DoCastSelf(SPELL_DUAL_WIELD, true);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
summon->Attack(me->GetVictim(), false);
|
||||
summon->SetInCombatWithZone();
|
||||
SetInvincibility(true);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
@@ -120,30 +114,35 @@ struct boss_halazzi : public BossAI
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && _phase != PHASE_ENRAGE)
|
||||
damage = 0;
|
||||
else
|
||||
BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
|
||||
|
||||
if (_phase == PHASE_LYNX || _phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (_phase == PHASE_LYNX || _phase == PHASE_ENRAGE)
|
||||
{
|
||||
_healthCheckPercentage = 25 * (3 - _transformCount);
|
||||
if (!HealthAbovePct(_healthCheckPercentage))
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
}
|
||||
else if (_phase == PHASE_HUMAN)
|
||||
{
|
||||
if (!HealthAbovePct(20))
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
uint32 _healthCheckPercentage = 25 * (3 - _transformCount);
|
||||
if (!HealthAbovePct(_healthCheckPercentage))
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
}
|
||||
else if (_phase == PHASE_HUMAN)
|
||||
{
|
||||
if (!HealthAbovePct(20))
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit*, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||
EnterPhase(PHASE_HUMAN);
|
||||
if (spell->Id == SPELL_TRANSFORM_DUMMY)
|
||||
me->UpdateEntry(NPC_HALAZZI_TROLL);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
|
||||
if (summon->GetEntry() == NPC_TOTEM)
|
||||
summon->Attack(me->GetVictim(), false);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
@@ -156,17 +155,39 @@ struct boss_halazzi : public BossAI
|
||||
{
|
||||
switch (nextPhase)
|
||||
{
|
||||
case PHASE_LYNX:
|
||||
case PHASE_ENRAGE:
|
||||
if (_phase == PHASE_MERGE)
|
||||
SetInvincibility(false);
|
||||
scheduler.Schedule(12s, GROUP_LYNX, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_TRANSFORM_MERGE, true);
|
||||
me->RemoveAurasDueToSpell(SPELL_TRANSFORM_SPLIT2);
|
||||
DoCastSelf(SPELL_SUMMON_TOTEM);
|
||||
context.Repeat(20s);
|
||||
});
|
||||
[[fallthrough]];
|
||||
case PHASE_LYNX:
|
||||
{
|
||||
if (_phase == PHASE_MERGE)
|
||||
me->ResumeChasingVictim();
|
||||
}
|
||||
summons.DespawnAll();
|
||||
me->SetMaxHealth(_lynxFormHealth);
|
||||
me->SetHealth(_lynxFormHealth - _healthPortion * _transformCount);
|
||||
|
||||
if (_transformCount)
|
||||
{
|
||||
me->UpdateEntry(NPC_HALAZZI);
|
||||
switch (_transformCount)
|
||||
{
|
||||
case 1:
|
||||
DoCastSelf(SPELL_TRANSFORM_TO_LYNX_75, true);
|
||||
break;
|
||||
case 2:
|
||||
DoCastSelf(SPELL_TRANSFORM_TO_LYNX_50, true);
|
||||
break;
|
||||
case 3:
|
||||
DoCastSelf(SPELL_TRANSFORM_TO_LYNX_25, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scheduler.CancelGroup(GROUP_MERGE);
|
||||
scheduler.Schedule(16s, GROUP_LYNX, [this](TaskContext context)
|
||||
{
|
||||
@@ -179,15 +200,18 @@ struct boss_halazzi : public BossAI
|
||||
context.Repeat(30s);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PHASE_SPLIT:
|
||||
Talk(SAY_SPLIT);
|
||||
DoCastSelf(SPELL_TRANSFORM_SPLIT, true);
|
||||
break;
|
||||
DoCastSelf(SPELL_TRANSFIGURE, true);
|
||||
scheduler.Schedule(3s, GROUP_SPLIT, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_LYNX, true);
|
||||
});
|
||||
nextPhase = PHASE_HUMAN;
|
||||
[[fallthrough]];
|
||||
case PHASE_HUMAN:
|
||||
scheduler.CancelGroup(GROUP_MERGE);
|
||||
DoCastSelf(SPELL_SUMMON_LYNX, true);
|
||||
me->SetMaxHealth(_humanFormHealth);
|
||||
me->SetHealth(_humanFormHealth);
|
||||
scheduler.CancelGroup(GROUP_LYNX);
|
||||
scheduler.Schedule(10s, GROUP_HUMAN, [this](TaskContext context)
|
||||
{
|
||||
@@ -255,11 +279,7 @@ struct boss_halazzi : public BossAI
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
private:
|
||||
uint32 _lynxFormHealth;
|
||||
uint32 _humanFormHealth;
|
||||
uint32 _healthPortion;
|
||||
uint8 _transformCount;
|
||||
uint32 _healthCheckPercentage;
|
||||
PhaseHalazzi _phase;
|
||||
};
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ enum Spells
|
||||
|
||||
// Rogue
|
||||
SPELL_RO_BLIND = 43433,
|
||||
SPELL_RO_SLICE_DICE = 43457,
|
||||
SPELL_RO_SLICE_DICE = 43547,
|
||||
SPELL_RO_WOUND_POISON = 43461,
|
||||
|
||||
// Shaman
|
||||
@@ -154,8 +154,14 @@ struct PlayerAbilityStruct
|
||||
std::chrono::milliseconds cooldown;
|
||||
};
|
||||
|
||||
static PlayerAbilityStruct PlayerAbility[12][3] =
|
||||
static PlayerAbilityStruct PlayerAbility[13][3] =
|
||||
{
|
||||
// 0 UNK class (should never be set)
|
||||
{
|
||||
{ 0, ABILITY_TARGET_SELF, 0ms},
|
||||
{ 0, ABILITY_TARGET_SELF, 0ms},
|
||||
{ 0, ABILITY_TARGET_SELF, 0ms}
|
||||
},
|
||||
// 1 warrior
|
||||
{ { SPELL_WR_SPELL_REFLECT, ABILITY_TARGET_SELF, 10000ms },
|
||||
{ SPELL_WR_WHIRLWIND, ABILITY_TARGET_SELF, 10000ms },
|
||||
@@ -268,7 +274,7 @@ struct boss_hexlord_malacrass : public BossAI
|
||||
siphonTrigger->AI()->DoCast(target, SPELL_SIPHON_SOUL, true);
|
||||
siphonTrigger->GetMotionMaster()->MoveChase(me);
|
||||
if (Player* player = target->ToPlayer())
|
||||
_currentClass = player->HasAura(AURA_SHADOW_FORM) ? ADDITIONAL_CLASS_SPRIEST : player->getClass() - 1;
|
||||
_currentClass = player->HasAura(AURA_SHADOW_FORM) ? uint8(ADDITIONAL_CLASS_SPRIEST) : player->getClass();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -65,7 +65,6 @@ enum Spells
|
||||
enum Creatures
|
||||
{
|
||||
NPC_AMANI_HATCHER = 23818,
|
||||
NPC_HATCHLING = 23598, // 42493
|
||||
NPC_EGG = 23817,
|
||||
NPC_FIRE_BOMB = 23920
|
||||
};
|
||||
@@ -110,10 +109,9 @@ enum HatchActions
|
||||
enum Misc
|
||||
{
|
||||
MAX_BOMB_COUNT = 40,
|
||||
|
||||
SCHEDULER_GROUP_HATCHING = 1,
|
||||
|
||||
EVENT_BERSERK = 0
|
||||
GROUP_ENRAGE = 1,
|
||||
GROUP_HATCHING = 2,
|
||||
DATA_ALL_EGGS_HATCHED = 0
|
||||
};
|
||||
|
||||
struct boss_janalai : public BossAI
|
||||
@@ -142,9 +140,15 @@ struct boss_janalai : public BossAI
|
||||
DoCastAOE(SPELL_HATCH_ALL);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(25, [&] {
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
ScheduleHealthCheckEvent(20, [&] {
|
||||
if (!me->HasAura(SPELL_ENRAGE))
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
me->m_Events.CancelEventGroup(GROUP_ENRAGE);
|
||||
});
|
||||
|
||||
me->m_Events.KillAllEvents(false);
|
||||
_sideHatched[0] = false;
|
||||
_sideHatched[1] = false;
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
@@ -153,6 +157,19 @@ struct boss_janalai : public BossAI
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_AMANI_HATCHLING)
|
||||
{
|
||||
if (summon->GetPositionY() > 1150)
|
||||
summon->GetMotionMaster()->MovePoint(0, hatcherway[0][3].GetPositionX() + rand() % 4 - 2, 1150.0f + rand() % 4 - 2, hatcherway[0][3].GetPositionY());
|
||||
else
|
||||
summon->GetMotionMaster()->MovePoint(0, hatcherway[1][3].GetPositionX() + rand() % 4 - 2, 1150.0f + rand() % 4 - 2, hatcherway[1][3].GetPositionY());
|
||||
}
|
||||
|
||||
BossAI::JustSummoned(summon);
|
||||
}
|
||||
|
||||
void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damagetype*/) override
|
||||
{
|
||||
if (_isFlameBreathing)
|
||||
@@ -170,14 +187,33 @@ struct boss_janalai : public BossAI
|
||||
ScheduleTimedEvent(30s, [&]{
|
||||
StartBombing();
|
||||
}, 20s, 40s);
|
||||
ScheduleTimedEvent(10s, [&]{
|
||||
if (HatchAllEggs(HATCH_RESET))
|
||||
|
||||
scheduler.Schedule(10s, GROUP_HATCHING, [this](TaskContext context)
|
||||
{
|
||||
if (_sideHatched[0] && _sideHatched[1])
|
||||
return;
|
||||
|
||||
Talk(SAY_SUMMON_HATCHER);
|
||||
|
||||
if (_sideHatched[0] && !_sideHatched[1])
|
||||
{
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[1][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[1][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
}
|
||||
else if (!_sideHatched[0] && _sideHatched[1])
|
||||
{
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[0][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[0][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_SUMMON_HATCHER);
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[0][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[1][0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
}
|
||||
}, 90s);
|
||||
|
||||
context.Repeat(90s);
|
||||
});
|
||||
|
||||
ScheduleTimedEvent(8s, [&]{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
@@ -193,10 +229,21 @@ struct boss_janalai : public BossAI
|
||||
});
|
||||
}
|
||||
}, 8s);
|
||||
ScheduleUniqueTimedEvent(5min, [&]{
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
}, 5min, 5min, GROUP_ENRAGE);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
Talk(SAY_BERSERK);
|
||||
DoCastSelf(SPELL_BERSERK);
|
||||
}, EVENT_BERSERK);
|
||||
}, 10min);
|
||||
}
|
||||
|
||||
void SetData(uint32 index, uint32 data) override
|
||||
{
|
||||
if (index == DATA_ALL_EGGS_HATCHED)
|
||||
_sideHatched[data] = true;
|
||||
}
|
||||
|
||||
bool HatchAllEggs(uint32 hatchAction)
|
||||
@@ -211,11 +258,7 @@ struct boss_janalai : public BossAI
|
||||
for (Creature* egg : eggList)
|
||||
egg->Respawn();
|
||||
|
||||
std::list<Creature* > hatchlingList;
|
||||
me->GetCreaturesWithEntryInRange(hatchlingList, 100.0f, NPC_HATCHLING);
|
||||
for (Creature* hatchling : hatchlingList)
|
||||
hatchling->DespawnOrUnsummon();
|
||||
hatchlingList.clear();
|
||||
summons.DespawnEntry(NPC_AMANI_HATCHLING);
|
||||
}
|
||||
else if (hatchAction == HATCH_ALL)
|
||||
DoCastSelf(SPELL_HATCH_EGG_ALL);
|
||||
@@ -325,6 +368,7 @@ struct boss_janalai : public BossAI
|
||||
private:
|
||||
bool _isBombing;
|
||||
bool _isFlameBreathing;
|
||||
bool _sideHatched[2];
|
||||
};
|
||||
|
||||
struct npc_janalai_hatcher : public ScriptedAI
|
||||
@@ -337,6 +381,7 @@ struct npc_janalai_hatcher : public ScriptedAI
|
||||
scheduler.CancelAll();
|
||||
_side = (me->GetPositionY() < 1150);
|
||||
_waypoint = 0;
|
||||
_repeatCount = 1;
|
||||
_isHatching = false;
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MovePoint(0, hatcherway[_side][0]);
|
||||
@@ -348,12 +393,25 @@ struct npc_janalai_hatcher : public ScriptedAI
|
||||
{
|
||||
_isHatching = true;
|
||||
|
||||
scheduler.Schedule(1500ms, SCHEDULER_GROUP_HATCHING, [this](TaskContext context)
|
||||
scheduler.Schedule(1500ms, [this](TaskContext context)
|
||||
{
|
||||
me->CastCustomSpell(SPELL_HATCH_EGG_ALL, SPELLVALUE_MAX_TARGETS, context.GetRepeatCounter() + 1);
|
||||
me->CastCustomSpell(SPELL_HATCH_EGG_ALL, SPELLVALUE_MAX_TARGETS, _repeatCount);
|
||||
|
||||
++_repeatCount;
|
||||
|
||||
if (me->FindNearestCreature(NPC_EGG, 100.0f))
|
||||
context.Repeat(4s);
|
||||
else
|
||||
{
|
||||
if (WorldObject* summoner = GetSummoner())
|
||||
if (Creature* janalai = summoner->ToCreature())
|
||||
janalai->AI()->SetData(DATA_ALL_EGGS_HATCHED, _side);
|
||||
|
||||
_side = _side ? 0 : 1;
|
||||
_isHatching = false;
|
||||
_waypoint = 3;
|
||||
MoveToNewWaypoint(_waypoint);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -387,46 +445,12 @@ struct npc_janalai_hatcher : public ScriptedAI
|
||||
private:
|
||||
uint8 _side;
|
||||
uint8 _waypoint;
|
||||
uint32 _repeatCount;
|
||||
bool _isHatching;
|
||||
};
|
||||
|
||||
struct npc_janalai_hatchling : public ScriptedAI
|
||||
{
|
||||
npc_janalai_hatchling(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
scheduler.CancelAll();
|
||||
if (me->GetPositionY() > 1150)
|
||||
me->GetMotionMaster()->MovePoint(0, hatcherway[0][3].GetPositionX() + rand() % 4 - 2, 1150.0f + rand() % 4 - 2, hatcherway[0][3].GetPositionY());
|
||||
else
|
||||
me->GetMotionMaster()->MovePoint(0, hatcherway[1][3].GetPositionX() + rand() % 4 - 2, 1150.0f + rand() % 4 - 2, hatcherway[1][3].GetPositionY());
|
||||
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
ScriptedAI::JustEngagedWith(who);
|
||||
ScheduleTimedEvent(7s, [&]{
|
||||
DoCastVictim(SPELL_FLAMEBUFFET);
|
||||
}, 10s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_janalai()
|
||||
{
|
||||
RegisterZulAmanCreatureAI(boss_janalai);
|
||||
RegisterZulAmanCreatureAI(npc_janalai_hatcher);
|
||||
RegisterZulAmanCreatureAI(npc_janalai_hatchling);
|
||||
}
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Nalorakk
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Zul'Aman
|
||||
EndScriptData */
|
||||
|
||||
#include "CellImpl.h"
|
||||
#include "CreatureScript.h"
|
||||
#include "GridNotifiers.h"
|
||||
@@ -111,7 +104,6 @@ struct boss_nalorakk : public BossAI
|
||||
_phase = PHASE_START_COMBAT;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
_active = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,22 +191,12 @@ struct boss_nalorakk : public BossAI
|
||||
me->GetCreaturesWithEntryInRange(_waveList, 25.0f, NPC_AMANISHI_MEDICINE_MAN);
|
||||
GroupedAttack(_waveList);
|
||||
Talk(SAY_WAVE4);
|
||||
_introScheduler.Schedule(5s, GROUP_CHECK_DEAD, [this](TaskContext context)
|
||||
{
|
||||
if (CheckFullyDeadGroup(_waveList))
|
||||
if (_phase == PHASE_SEND_GUARDS_4)
|
||||
{
|
||||
_introScheduler.CancelGroup(GROUP_CHECK_DEAD);
|
||||
me->SetHomePosition(me->GetPosition());
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetInCombatWithZone();
|
||||
_waveList.clear();
|
||||
_phase = PHASE_START_COMBAT;
|
||||
_ranIntro = true;
|
||||
}
|
||||
context.Repeat(5s);
|
||||
});
|
||||
_waveList.clear();
|
||||
_phase = PHASE_START_COMBAT;
|
||||
_ranIntro = true;
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetHomePosition(me->GetPosition());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -236,7 +218,7 @@ struct boss_nalorakk : public BossAI
|
||||
context.Repeat();
|
||||
}).Schedule(10s, 15s, GROUP_HUMAN, [this](TaskContext context)
|
||||
{
|
||||
if (me->GetVictim() && !me->GetVictim()->HasAura(SPELL_MANGLEEFFECT))
|
||||
if (me->GetVictim() && !me->GetVictim()->HasAura(SPELL_MANGLE))
|
||||
{
|
||||
DoCastVictim(SPELL_MANGLE);
|
||||
context.Repeat(1s);
|
||||
@@ -258,9 +240,11 @@ struct boss_nalorakk : public BossAI
|
||||
if (currentlyInBearForm)
|
||||
{
|
||||
Talk(SAY_SHIFTEDTOTROLL);
|
||||
me->RemoveAurasDueToSpell(SPELL_BEARFORM);
|
||||
scheduler.CancelGroup(GROUP_BEAR);
|
||||
_bearForm = false;
|
||||
|
||||
me->SetCanDualWield(true);
|
||||
|
||||
scheduler.Schedule(15s, 20s, GROUP_HUMAN, [this](TaskContext context)
|
||||
{
|
||||
Talk(SAY_SURGE);
|
||||
@@ -290,6 +274,9 @@ struct boss_nalorakk : public BossAI
|
||||
DoCastSelf(SPELL_BEARFORM, true);
|
||||
scheduler.CancelGroup(GROUP_HUMAN);
|
||||
_bearForm = true;
|
||||
|
||||
me->SetCanDualWield(false);
|
||||
|
||||
scheduler.Schedule(2s, GROUP_BEAR, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_LACERATINGSLASH);
|
||||
@@ -302,10 +289,9 @@ struct boss_nalorakk : public BossAI
|
||||
{
|
||||
DoCastSelf(SPELL_DEAFENINGROAR);
|
||||
context.Repeat(15s, 20s);
|
||||
}).Schedule(25s, 30s, GROUP_BEAR, [this](TaskContext context)
|
||||
}).Schedule(30s, GROUP_BEAR, [this](TaskContext)
|
||||
{
|
||||
ShapeShift(_bearForm);
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ struct boss_zuljin : public BossAI
|
||||
ScheduleHealthCheckEvent({ 40 }, [&] {
|
||||
EnterPhase(PHASE_LYNX);
|
||||
me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_STORM);
|
||||
me->RemoveOwnedAura(SPELL_ENERGY_STORM);
|
||||
summons.DespawnEntry(CREATURE_FEATHER_VORTEX);
|
||||
me->ResumeChasingVictim();
|
||||
|
||||
@@ -268,6 +268,10 @@ struct boss_zuljin : public BossAI
|
||||
instance->SetBossState(DATA_ZULJIN, DONE);
|
||||
Talk(SAY_DEATH);
|
||||
summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE);
|
||||
|
||||
me->m_Events.AddEventAtOffset( [this] {
|
||||
summons.DespawnAll();
|
||||
}, 3s);
|
||||
}
|
||||
|
||||
void SpawnAdds()
|
||||
|
||||
@@ -49,15 +49,17 @@ Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_ZULJIN_FIREWALL, DATA_ZULJIN, DOOR_TYPE_ROOM },
|
||||
{ GO_DOOR_HALAZZI, DATA_HALAZZI, DOOR_TYPE_ROOM },
|
||||
{ GO_DOOR_AKILZON, DATA_AKILZON, DOOR_TYPE_ROOM },
|
||||
{ GO_GATE_ZULJIN, DATA_HEXLORD, DOOR_TYPE_PASSAGE },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
{ GO_ZULJIN_FIREWALL, DATA_ZULJIN, DOOR_TYPE_ROOM },
|
||||
{ GO_DOOR_HALAZZI, DATA_HALAZZI, DOOR_TYPE_PASSAGE },
|
||||
{ GO_LYNX_TEMPLE_ENTRANCE, DATA_HALAZZI, DOOR_TYPE_ROOM },
|
||||
{ GO_DOOR_AKILZON, DATA_AKILZON, DOOR_TYPE_ROOM },
|
||||
{ GO_GATE_ZULJIN, DATA_HEXLORD, DOOR_TYPE_PASSAGE },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_JANALAI, DATA_JANALAI },
|
||||
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
|
||||
{ NPC_HARRISON_JONES, DATA_HARRISON_JONES },
|
||||
{ 0, 0 }
|
||||
@@ -71,6 +73,12 @@ ObjectData const gameObjectData[] =
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
ObjectData const summonData[] =
|
||||
{
|
||||
{ NPC_AMANI_HATCHLING, DATA_JANALAI },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ DATA_HEXLORD, new RectangleBoundary(80.50557f, 920.9858f, 155.88986f, 1015.27563f)}
|
||||
@@ -93,6 +101,7 @@ public:
|
||||
LoadObjectData(creatureData, gameObjectData);
|
||||
LoadBossBoundaries(boundaries);
|
||||
LoadDoorData(doorData);
|
||||
LoadSummonData(summonData);
|
||||
|
||||
for (uint8 i = 0; i < RAND_VENDOR; ++i)
|
||||
RandVendor[i] = NOT_STARTED;
|
||||
|
||||
@@ -323,31 +323,23 @@ enum Spells
|
||||
SPELL_COSMETIC_SPEAR_THROW = 43647
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum Phases
|
||||
{
|
||||
GONG_EVENT_1 = 1,
|
||||
GONG_EVENT_2 = 2,
|
||||
GONG_EVENT_3 = 3,
|
||||
GONG_EVENT_4 = 4,
|
||||
GONG_EVENT_5 = 5,
|
||||
GONG_EVENT_6 = 6,
|
||||
GONG_EVENT_7 = 7,
|
||||
GONG_EVENT_8 = 8,
|
||||
GONG_EVENT_9 = 9,
|
||||
GONG_EVENT_10 = 10,
|
||||
GONG_EVENT_11 = 11
|
||||
PHASE_GONG = 0,
|
||||
PHASE_GATE_CLOSED = 1,
|
||||
PHASE_GATE_OPENED = 2
|
||||
};
|
||||
|
||||
enum Actions
|
||||
{
|
||||
ACTION_COMPLETE_EVENT_3 = 0,
|
||||
ACTION_COMPLETE_GONG_RITUAL = 0
|
||||
};
|
||||
|
||||
enum Waypoints
|
||||
{
|
||||
HARRISON_MOVE_1 = 860440,
|
||||
HARRISON_MOVE_2 = 860441,
|
||||
HARRISON_MOVE_3 = 860442
|
||||
HARRISON_MOVE_1 = 2435800,
|
||||
HARRISON_MOVE_2 = 2435801,
|
||||
HARRISON_MOVE_3 = 2435802
|
||||
};
|
||||
|
||||
enum DisplayIds
|
||||
@@ -379,9 +371,8 @@ struct npc_harrison_jones : public ScriptedAI
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_gongEvent = 0;
|
||||
_gongTimer = 0;
|
||||
uiTargetGUID.Clear();
|
||||
_phase = PHASE_GONG;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
@@ -394,8 +385,10 @@ struct npc_harrison_jones : public ScriptedAI
|
||||
me->SetFacingToObject(player);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
Talk(SAY_HARRISON_0);
|
||||
_gongEvent = GONG_EVENT_1;
|
||||
_gongTimer = 4000;
|
||||
scheduler.Schedule(2s, [this](TaskContext /*task*/)
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_1, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,12 +396,16 @@ struct npc_harrison_jones : public ScriptedAI
|
||||
{
|
||||
if (spell->Id == SPELL_COSMETIC_SPEAR_THROW)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->RemoveAllAuras(); // remove stealth
|
||||
me->SetEntry(NPC_HARRISON_JONES_2);
|
||||
me->SetDisplayId(MODEL_HARRISON_JONES_2);
|
||||
me->SetTarget();
|
||||
me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_DEAD);
|
||||
me->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->PlayDistanceSound(1332); // human male death
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_WOUND_CRITICAL);
|
||||
me->StopMoving();
|
||||
scheduler.Schedule(1s, [this](TaskContext /*task*/)
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_DEAD);
|
||||
});
|
||||
_instance->StorePersistentData(DATA_TIMED_RUN, 21);
|
||||
_instance->DoAction(ACTION_START_TIMED_RUN);
|
||||
me->DespawnOrUnsummon(3min+30s, 0s);
|
||||
@@ -417,132 +414,103 @@ struct npc_harrison_jones : public ScriptedAI
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_COMPLETE_EVENT_3)
|
||||
if (action == ACTION_COMPLETE_GONG_RITUAL)
|
||||
{
|
||||
me->GetMap()->ToInstanceMap()->PermBindAllPlayers();
|
||||
_gongEvent = GONG_EVENT_4;
|
||||
_gongTimer = 0;
|
||||
_phase = PHASE_GATE_CLOSED;
|
||||
me->RemoveAura(SPELL_BANGING_THE_GONG);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(0));
|
||||
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
|
||||
gong->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
// Players are Now Saved to instance at SPECIAL (Player should be notified?)
|
||||
scheduler.Schedule(500ms, [this](TaskContext /*task*/)
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_2, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void OpenMassiveGateAndCallGuards()
|
||||
{
|
||||
if (GameObject* gate = _instance->GetGameObject(DATA_MASSIVE_GATE))
|
||||
{
|
||||
gate->AllowSaveToDB(true);
|
||||
gate->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
std::list<Creature*> targetList;
|
||||
GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f);
|
||||
if (!targetList.empty())
|
||||
{
|
||||
for (auto const& creature : targetList)
|
||||
{
|
||||
if (creature)
|
||||
{
|
||||
creature->SetImmuneToPC(true);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
|
||||
if (creature->GetPositionX() > 120)
|
||||
{
|
||||
creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_SPEAR));
|
||||
creature->AI()->SetData(0, 1);
|
||||
}
|
||||
else
|
||||
creature->AI()->SetData(0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
// at gong
|
||||
if (type == WAYPOINT_MOTION_TYPE && id == 2 && _phase == PHASE_GONG)
|
||||
{
|
||||
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
|
||||
me->SetFacingToObject(gong);
|
||||
scheduler.Schedule(2s, [this](TaskContext /*task*/)
|
||||
{
|
||||
Talk(SAY_HARRISON_1);
|
||||
}).Schedule(7s, [this](TaskContext /*task*/)
|
||||
{
|
||||
DoCastSelf(SPELL_BANGING_THE_GONG);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_MACE));
|
||||
me->SetFacingTo(5.9696f);
|
||||
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
|
||||
gong->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
});
|
||||
}
|
||||
// to the massive gate
|
||||
else if (type == WAYPOINT_MOTION_TYPE && id == 1 && _phase == PHASE_GATE_CLOSED)
|
||||
{
|
||||
me->SetEntry(NPC_HARRISON_JONES_1);
|
||||
Talk(SAY_HARRISON_2);
|
||||
}
|
||||
// at massive gate
|
||||
else if (type == WAYPOINT_MOTION_TYPE && id == 2 && _phase == PHASE_GATE_CLOSED)
|
||||
{
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
|
||||
Talk(SAY_HARRISON_3);
|
||||
scheduler.Schedule(8s, [this](TaskContext /*task*/)
|
||||
{
|
||||
OpenMassiveGateAndCallGuards();
|
||||
_phase = PHASE_GATE_OPENED;
|
||||
}).Schedule(10s, [this](TaskContext /*task*/)
|
||||
{
|
||||
DoCastSelf(SPELL_STEALTH);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_3, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_gongEvent)
|
||||
{
|
||||
if (_gongTimer <= diff)
|
||||
{
|
||||
switch (_gongEvent)
|
||||
{
|
||||
case GONG_EVENT_1:
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_1, false);
|
||||
_gongEvent = GONG_EVENT_2;
|
||||
_gongTimer = 12000;
|
||||
break;
|
||||
case GONG_EVENT_2:
|
||||
me->SetFacingTo(6.235659f);
|
||||
Talk(SAY_HARRISON_1);
|
||||
DoCastSelf(SPELL_BANGING_THE_GONG);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_MACE));
|
||||
me->SetSheath(SHEATH_STATE_MELEE);
|
||||
_gongEvent = GONG_EVENT_3;
|
||||
_gongTimer = 4000;
|
||||
break;
|
||||
case GONG_EVENT_3:
|
||||
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
|
||||
gong->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
case GONG_EVENT_4:
|
||||
me->RemoveAura(SPELL_BANGING_THE_GONG);
|
||||
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
|
||||
gong->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
|
||||
// Players are Now Saved to instance at SPECIAL (Player should be notified?)
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_2, false);
|
||||
_gongEvent = GONG_EVENT_5;
|
||||
_gongTimer = 5000;
|
||||
break;
|
||||
case GONG_EVENT_5:
|
||||
me->SetEntry(NPC_HARRISON_JONES_1);
|
||||
me->SetDisplayId(MODEL_HARRISON_JONES_1);
|
||||
Talk(SAY_HARRISON_2);
|
||||
_gongTimer = 12000;
|
||||
_gongEvent = GONG_EVENT_6;
|
||||
break;
|
||||
case GONG_EVENT_6:
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
|
||||
Talk(SAY_HARRISON_3);
|
||||
_gongTimer = 7000;
|
||||
_gongEvent = GONG_EVENT_7;
|
||||
break;
|
||||
case GONG_EVENT_7:
|
||||
if (!uiTargetGUID)
|
||||
{
|
||||
std::list<Creature*> targetList;
|
||||
GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f);
|
||||
if (!targetList.empty())
|
||||
{
|
||||
for (auto const& creature : targetList)
|
||||
{
|
||||
if (creature)
|
||||
{
|
||||
creature->SetImmuneToPC(true);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
|
||||
if (creature->GetPositionX() > 120)
|
||||
{
|
||||
creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_SPEAR));
|
||||
creature->AI()->SetData(0, 1);
|
||||
}
|
||||
else
|
||||
creature->AI()->SetData(0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GameObject* gate = _instance->GetGameObject(DATA_MASSIVE_GATE))
|
||||
{
|
||||
gate->AllowSaveToDB(true);
|
||||
gate->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
_gongTimer = 2000;
|
||||
_gongEvent = GONG_EVENT_8;
|
||||
break;
|
||||
case GONG_EVENT_8:
|
||||
DoCastSelf(SPELL_STEALTH);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(0));
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_3, false);
|
||||
_gongTimer = 1000;
|
||||
_gongEvent = 0;
|
||||
break;
|
||||
case GONG_EVENT_9:
|
||||
me->GetMotionMaster()->MovePoint(0, 120.687f, 1674.0f, 42.0217f);
|
||||
_gongTimer = 12000;
|
||||
_gongEvent = GONG_EVENT_10;
|
||||
break;
|
||||
case GONG_EVENT_10:
|
||||
me->SetFacingTo(1.59044f);
|
||||
_gongEvent = 11;
|
||||
_gongTimer = 6000;
|
||||
break;
|
||||
case GONG_EVENT_11:
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
_gongEvent = 0;
|
||||
_gongTimer = 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_gongTimer -= diff;
|
||||
}
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
uint8 _gongEvent;
|
||||
uint32 _gongTimer;
|
||||
ObjectGuid uiTargetGUID;
|
||||
uint32 _phase;
|
||||
};
|
||||
|
||||
class spell_ritual_of_power : public SpellScript
|
||||
@@ -553,7 +521,7 @@ class spell_ritual_of_power : public SpellScript
|
||||
{
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
if (Creature* creature = instance->GetCreature(DATA_HARRISON_JONES))
|
||||
creature->AI()->DoAction(ACTION_COMPLETE_EVENT_3);
|
||||
creature->AI()->DoAction(ACTION_COMPLETE_GONG_RITUAL);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -53,14 +53,16 @@ enum CreatureIds
|
||||
NPC_AMANISHI_WARBRINGER = 23580,
|
||||
NPC_AMANISHI_TRIBESMAN = 23582,
|
||||
NPC_AMANISHI_MEDICINE_MAN = 23581,
|
||||
NPC_AMANISHI_AXE_THROWER = 23542
|
||||
NPC_AMANISHI_AXE_THROWER = 23542,
|
||||
NPC_AMANI_HATCHLING = 23598 // 42493
|
||||
};
|
||||
|
||||
enum GameobjectIds
|
||||
{
|
||||
GO_DOOR_HALAZZI = 186303,
|
||||
GO_GATE_ZULJIN = 186304,
|
||||
GO_LYNX_TEMPLE_ENTRANCE = 186304,
|
||||
GO_GATE_HEXLORD = 186305,
|
||||
GO_GATE_ZULJIN = 186306,
|
||||
GO_MASSIVE_GATE = 186728,
|
||||
GO_DOOR_AKILZON = 186858,
|
||||
GO_ZULJIN_FIREWALL = 186859,
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "zulgurub.h"
|
||||
/* ScriptData
|
||||
SDName: Boss_Gahz'ranka
|
||||
SD%Complete: 85
|
||||
SDComment: Massive Geyser with knockback not working. Spell buggy.
|
||||
SDCategory: Zul'Gurub
|
||||
EndScriptData */
|
||||
|
||||
enum Spells
|
||||
{
|
||||
@@ -36,89 +30,39 @@ enum Spells
|
||||
SPELL_SPLASH = 24593
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_FROSTBREATH = 1,
|
||||
EVENT_MASSIVEGEYSER = 2,
|
||||
EVENT_SLAM = 3
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
GAMEOBJECT_MUDSKUNK_LURE = 180346
|
||||
};
|
||||
|
||||
class boss_gahzranka : public CreatureScript
|
||||
struct boss_gahzranka : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_gahzranka() : CreatureScript("boss_gahzranka") { }
|
||||
boss_gahzranka(Creature* creature) : BossAI(creature, DATA_GAHZRANKA) {}
|
||||
|
||||
struct boss_gahzrankaAI : public BossAI
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
boss_gahzrankaAI(Creature* creature) : BossAI(creature, DATA_GAHZRANKA) { }
|
||||
me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false);
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
me->AddAura(SPELL_THRASH, me);
|
||||
events.ScheduleEvent(EVENT_FROSTBREATH, 8s);
|
||||
events.ScheduleEvent(EVENT_MASSIVEGEYSER, 25s);
|
||||
events.ScheduleEvent(EVENT_SLAM, 15s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FROSTBREATH:
|
||||
DoCastVictim(SPELL_FROSTBREATH);
|
||||
events.ScheduleEvent(EVENT_FROSTBREATH, 8s, 20s);
|
||||
break;
|
||||
case EVENT_MASSIVEGEYSER:
|
||||
DoCastVictim(SPELL_MASSIVEGEYSER);
|
||||
events.ScheduleEvent(EVENT_MASSIVEGEYSER, 22s, 32s);
|
||||
break;
|
||||
case EVENT_SLAM:
|
||||
DoCastVictim(SPELL_SLAM, true);
|
||||
events.ScheduleEvent(EVENT_SLAM, 12s, 20s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetZulGurubAI<boss_gahzrankaAI>(creature);
|
||||
_JustEngagedWith();
|
||||
me->AddAura(SPELL_THRASH, me);
|
||||
|
||||
ScheduleTimedEvent(8s, [&]
|
||||
{
|
||||
DoCastVictim(SPELL_FROSTBREATH);
|
||||
}, 8s, 20s);
|
||||
|
||||
ScheduleTimedEvent(25s, [&]
|
||||
{
|
||||
DoCastVictim(SPELL_MASSIVEGEYSER);
|
||||
}, 22s, 32s);
|
||||
|
||||
ScheduleTimedEvent(15s, [&]
|
||||
{
|
||||
DoCastVictim(SPELL_SLAM, true);
|
||||
}, 12s, 20s);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -129,23 +73,15 @@ class spell_gahzranka_slam : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
_wipeThreat = targets.size() < caster->GetThreatMgr().GetThreatListSize();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleWipeThreat(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (_wipeThreat)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
caster->GetThreatMgr().ModifyThreatByPercent(target, -100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
@@ -198,7 +134,7 @@ class spell_pagles_point_cast : public SpellScript
|
||||
|
||||
void AddSC_boss_gahzranka()
|
||||
{
|
||||
new boss_gahzranka();
|
||||
RegisterZulGurubCreatureAI(boss_gahzranka);
|
||||
RegisterSpellScript(spell_gahzranka_slam);
|
||||
RegisterSpellScript(spell_pagles_point_cast);
|
||||
}
|
||||
|
||||
@@ -501,7 +501,14 @@ class spell_pilgrims_bounty_feast_on_generic : public SpellScript
|
||||
|
||||
// Cast spirit of sharing
|
||||
if (count >= 5)
|
||||
{
|
||||
player->RemoveAurasDueToSpell(SPELL_PLAYER_TURKEY);
|
||||
player->RemoveAurasDueToSpell(SPELL_PLAYER_STUFFING);
|
||||
player->RemoveAurasDueToSpell(SPELL_PLAYER_PIE);
|
||||
player->RemoveAurasDueToSpell(SPELL_PLAYER_CRANBERRY);
|
||||
player->RemoveAurasDueToSpell(SPELL_PLAYER_SWEET_POTATOES);
|
||||
player->CastSpell(player, SPELL_SPIRIT_OF_SHARING, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,14 +33,6 @@ enum Spells
|
||||
SPELL_BERSERK = 26662
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_IMPALE = 1,
|
||||
EVENT_LOCUST_SWARM = 2,
|
||||
EVENT_BERSERK = 3,
|
||||
EVENT_SPAWN_GUARD = 4
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
NPC_CORPSE_SCARAB = 16698,
|
||||
@@ -61,17 +53,11 @@ public:
|
||||
|
||||
struct boss_anubrekhanAI : public BossAI
|
||||
{
|
||||
explicit boss_anubrekhanAI(Creature* c) : BossAI(c, BOSS_ANUB), summons(me)
|
||||
boss_anubrekhanAI(Creature* c) : BossAI(c, BOSS_ANUB)
|
||||
{
|
||||
pInstance = c->GetInstanceScript();
|
||||
sayGreet = false;
|
||||
}
|
||||
|
||||
InstanceScript* pInstance;
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
bool sayGreet;
|
||||
|
||||
void SummonCryptGuards()
|
||||
{
|
||||
if (Is25ManRaid())
|
||||
@@ -84,16 +70,8 @@ public:
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
SummonCryptGuards();
|
||||
if (pInstance)
|
||||
{
|
||||
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_ANUB_GATE)))
|
||||
{
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
}
|
||||
me->m_Events.KillAllEvents(false);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* cr) override
|
||||
@@ -102,9 +80,7 @@ public:
|
||||
{
|
||||
cr->SetInCombatWithZone();
|
||||
if (cr->GetEntry() == NPC_CRYPT_GUARD)
|
||||
{
|
||||
cr->AI()->Talk(EMOTE_SPAWN, me);
|
||||
}
|
||||
}
|
||||
summons.Summon(cr);
|
||||
}
|
||||
@@ -118,19 +94,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* cr) override
|
||||
{
|
||||
summons.Despawn(cr);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
summons.DespawnAll();
|
||||
if (pInstance)
|
||||
{
|
||||
pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
||||
}
|
||||
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
@@ -140,10 +107,7 @@ public:
|
||||
|
||||
Talk(SAY_SLAY);
|
||||
victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCRABS_5, true, nullptr, nullptr, me->GetGUID());
|
||||
if (pInstance)
|
||||
{
|
||||
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
|
||||
}
|
||||
instance->SetData(DATA_IMMORTAL_FAIL, 0);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
@@ -151,24 +115,36 @@ public:
|
||||
BossAI::JustEngagedWith(who);
|
||||
me->CallForHelp(30.0f);
|
||||
Talk(SAY_AGGRO);
|
||||
if (pInstance)
|
||||
{
|
||||
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_ANUB_GATE)))
|
||||
{
|
||||
go->SetGoState(GO_STATE_READY);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_IMPALE, 15s);
|
||||
events.ScheduleEvent(EVENT_LOCUST_SWARM, 70s, 120s);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 10min);
|
||||
|
||||
if (!summons.HasEntry(NPC_CRYPT_GUARD))
|
||||
{
|
||||
SummonCryptGuards();
|
||||
}
|
||||
if (!Is25ManRaid())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPAWN_GUARD, 15s, 20s);
|
||||
me->m_Events.AddEventAtOffset([&]
|
||||
{
|
||||
me->SummonCreature(NPC_CRYPT_GUARD, 3331.217f, -3476.607f, 287.074f, 3.269f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
}, Milliseconds(urand(15000, 20000)));
|
||||
}
|
||||
|
||||
ScheduleTimedEvent(15s, [&] {
|
||||
DoCastRandomTarget(RAID_MODE(SPELL_IMPALE_10, SPELL_IMPALE_25));
|
||||
}, 20s);
|
||||
|
||||
ScheduleTimedEvent(70s, 2min, [&] {
|
||||
Talk(EMOTE_LOCUST);
|
||||
DoCastSelf(RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25));
|
||||
|
||||
me->m_Events.AddEventAtOffset([&]
|
||||
{
|
||||
me->SummonCreature(NPC_CRYPT_GUARD, 3331.217f, -3476.607f, 287.074f, 3.269f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
}, 3s);
|
||||
|
||||
}, 90s);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&]
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
}, 10min);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
@@ -181,54 +157,8 @@ public:
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->IsInCombat() && sayGreet)
|
||||
{
|
||||
for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr)
|
||||
{
|
||||
if (pInstance)
|
||||
{
|
||||
if (Creature* cr = pInstance->instance->GetCreature(*itr))
|
||||
{
|
||||
if (cr->IsInCombat())
|
||||
DoZoneInCombat();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_IMPALE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
me->CastSpell(target, RAID_MODE(SPELL_IMPALE_10, SPELL_IMPALE_25), false);
|
||||
}
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
case EVENT_LOCUST_SWARM:
|
||||
Talk(EMOTE_LOCUST);
|
||||
me->CastSpell(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25), false);
|
||||
events.ScheduleEvent(EVENT_SPAWN_GUARD, 3s);
|
||||
events.Repeat(90s);
|
||||
break;
|
||||
case EVENT_SPAWN_GUARD:
|
||||
me->SummonCreature(NPC_CRYPT_GUARD, 3331.217f, -3476.607f, 287.074f, 3.269f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
break;
|
||||
case EVENT_BERSERK:
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool sayGreet;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -52,6 +52,12 @@ inline uint8 GetEruptionSection(float x, float y)
|
||||
return 3;
|
||||
}
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_ANUB_GATE, BOSS_ANUB, DOOR_TYPE_ROOM },
|
||||
{ 0, 0, DOOR_TYPE_ROOM },
|
||||
};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_RAZUVIOUS, DATA_RAZUVIOUS },
|
||||
@@ -79,6 +85,7 @@ public:
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_ENCOUNTERS);
|
||||
LoadDoorData(doorData);
|
||||
LoadObjectData(creatureData, gameObjectData);
|
||||
for (auto& i : HeiganEruption)
|
||||
i.clear();
|
||||
@@ -115,7 +122,6 @@ public:
|
||||
ObjectGuid _heiganGateGUID;
|
||||
ObjectGuid _heiganGateExitGUID;
|
||||
ObjectGuid _loathebGateGUID;
|
||||
ObjectGuid _anubGateGUID;
|
||||
ObjectGuid _anubNextGateGUID;
|
||||
ObjectGuid _faerlinaWebGUID;
|
||||
ObjectGuid _faerlinaGateGUID;
|
||||
@@ -328,13 +334,6 @@ public:
|
||||
pGo->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
break;
|
||||
case GO_ANUB_GATE:
|
||||
_anubGateGUID = pGo->GetGUID();
|
||||
if (GetBossState(BOSS_ANUB) == DONE)
|
||||
{
|
||||
pGo->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
break;
|
||||
case GO_ANUB_NEXT_GATE:
|
||||
_anubNextGateGUID = pGo->GetGUID();
|
||||
if (GetBossState(BOSS_ANUB) == DONE)
|
||||
@@ -880,10 +879,6 @@ public:
|
||||
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6s);
|
||||
break;
|
||||
case BOSS_ANUB:
|
||||
if (GameObject* go = instance->GetGameObject(_anubGateGUID))
|
||||
{
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
if (GameObject* go = instance->GetGameObject(_anubNextGateGUID))
|
||||
{
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
@@ -1074,8 +1069,6 @@ public:
|
||||
return _heiganGateGUID;
|
||||
case DATA_LOATHEB_GATE:
|
||||
return _loathebGateGUID;
|
||||
case DATA_ANUB_GATE:
|
||||
return _anubGateGUID;
|
||||
case DATA_FAERLINA_WEB:
|
||||
return _faerlinaWebGUID;
|
||||
case DATA_MAEXXNA_GATE:
|
||||
|
||||
@@ -50,7 +50,6 @@ enum NXData
|
||||
DATA_HEIGAN_ERUPTION = 101,
|
||||
DATA_HEIGAN_ENTER_GATE = 102,
|
||||
DATA_LOATHEB_GATE = 103,
|
||||
DATA_ANUB_GATE = 104,
|
||||
DATA_FAERLINA_WEB = 105,
|
||||
DATA_MAEXXNA_GATE = 106,
|
||||
DATA_THADDIUS_BOSS = 107,
|
||||
|
||||
@@ -67,146 +67,131 @@ private:
|
||||
Creature* _caster;
|
||||
};
|
||||
|
||||
class boss_anomalus : public CreatureScript
|
||||
struct boss_anomalus : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_anomalus() : CreatureScript("boss_anomalus") { }
|
||||
boss_anomalus(Creature* creature) : BossAI(creature, DATA_ANOMALUS_EVENT) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool achievement;
|
||||
uint16 activeRifts;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<boss_anomalusAI>(creature);
|
||||
BossAI::Reset();
|
||||
achievement = true;
|
||||
me->CastSpell(me, SPELL_CLOSE_RIFTS, true);
|
||||
}
|
||||
|
||||
struct boss_anomalusAI : public BossAI
|
||||
uint32 GetData(uint32 data) const override
|
||||
{
|
||||
boss_anomalusAI(Creature* creature) : BossAI(creature, DATA_ANOMALUS_EVENT)
|
||||
{
|
||||
}
|
||||
if (data == me->GetEntry())
|
||||
return achievement;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool achievement;
|
||||
uint16 activeRifts;
|
||||
|
||||
void Reset() override
|
||||
void SetData(uint32 type, uint32) override
|
||||
{
|
||||
if (type == me->GetEntry())
|
||||
{
|
||||
BossAI::Reset();
|
||||
achievement = true;
|
||||
me->CastSpell(me, SPELL_CLOSE_RIFTS, true);
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const override
|
||||
{
|
||||
if (data == me->GetEntry())
|
||||
return achievement;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32) override
|
||||
{
|
||||
if (type == me->GetEntry())
|
||||
if (activeRifts > 0 && --activeRifts == 0 && me->HasAura(SPELL_RIFT_SHIELD))
|
||||
{
|
||||
if (activeRifts > 0 && --activeRifts == 0 && me->HasAura(SPELL_RIFT_SHIELD))
|
||||
{
|
||||
events.DelayEvents(me->GetAura(SPELL_RIFT_SHIELD)->GetDuration() - 46000);
|
||||
me->RemoveAura(SPELL_RIFT_SHIELD);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
}
|
||||
achievement = false;
|
||||
events.DelayEvents(me->GetAura(SPELL_RIFT_SHIELD)->GetDuration() - 46000);
|
||||
me->RemoveAura(SPELL_RIFT_SHIELD);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
}
|
||||
achievement = false;
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
activeRifts++;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
activeRifts = 0;
|
||||
events.SetTimer(45000);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPARK, 5s);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_HEALTH, 1s);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPAWN_RIFT, IsHeroic() ? 15s : 25s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_ARCANE_ATTRACTION, 8s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
me->CastSpell(me, SPELL_CLOSE_RIFTS, true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
summons.Summon(summon);
|
||||
activeRifts++;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
activeRifts = 0;
|
||||
events.SetTimer(45000);
|
||||
case EVENT_ANOMALUS_SPARK:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SPARK, false);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPARK, 5s);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_HEALTH, 1s);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPAWN_RIFT, IsHeroic() ? 15s : 25s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_ARCANE_ATTRACTION, 8s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
me->CastSpell(me, SPELL_CLOSE_RIFTS, true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
break;
|
||||
case EVENT_ANOMALUS_HEALTH:
|
||||
if (me->HealthBelowPct(51))
|
||||
{
|
||||
case EVENT_ANOMALUS_SPARK:
|
||||
me->CastSpell(me->GetVictim(), SPELL_SPARK, false);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPARK, 5s);
|
||||
break;
|
||||
case EVENT_ANOMALUS_HEALTH:
|
||||
if (me->HealthBelowPct(51))
|
||||
{
|
||||
//First time we reach 51%, the next rift going to be empowered following timings.
|
||||
events.CancelEvent(EVENT_ANOMALUS_SPAWN_RIFT);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPAWN_RIFT_EMPOWERED, 1s);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_HEALTH, 1s);
|
||||
break;
|
||||
case EVENT_ANOMALUS_ARCANE_ATTRACTION:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||
me->CastSpell(target, SPELL_ARCANE_ATTRACTION, false);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_ARCANE_ATTRACTION, 15s);
|
||||
break;
|
||||
case EVENT_ANOMALUS_SPAWN_RIFT:
|
||||
Talk(SAY_RIFT);
|
||||
Talk(EMOTE_RIFT);
|
||||
me->CastSpell(me, SPELL_CREATE_RIFT, false);
|
||||
//Once we hit 51% hp mark, after each rift we spawn an empowered
|
||||
events.ScheduleEvent(me->HealthBelowPct(51) ? EVENT_ANOMALUS_SPAWN_RIFT_EMPOWERED : EVENT_ANOMALUS_SPAWN_RIFT, IsHeroic() ? 15000 : 25000);
|
||||
break;
|
||||
case EVENT_ANOMALUS_SPAWN_RIFT_EMPOWERED:
|
||||
Talk(SAY_RIFT);
|
||||
Talk(EMOTE_RIFT);
|
||||
|
||||
me->CastSpell(me, SPELL_CREATE_RIFT, false);
|
||||
me->CastSpell(me, SPELL_RIFT_SHIELD, true);
|
||||
me->m_Events.AddEvent(new ChargeRifts(me), me->m_Events.CalculateTime(1000));
|
||||
events.DelayEvents(46s);
|
||||
//As we just spawned an empowered spawn a normal one
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPAWN_RIFT, IsHeroic() ? 15s : 25s);
|
||||
break;
|
||||
//First time we reach 51%, the next rift going to be empowered following timings.
|
||||
events.CancelEvent(EVENT_ANOMALUS_SPAWN_RIFT);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPAWN_RIFT_EMPOWERED, 1s);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_HEALTH, 1s);
|
||||
break;
|
||||
case EVENT_ANOMALUS_ARCANE_ATTRACTION:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||
me->CastSpell(target, SPELL_ARCANE_ATTRACTION, false);
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_ARCANE_ATTRACTION, 15s);
|
||||
break;
|
||||
case EVENT_ANOMALUS_SPAWN_RIFT:
|
||||
Talk(SAY_RIFT);
|
||||
Talk(EMOTE_RIFT);
|
||||
me->CastSpell(me, SPELL_CREATE_RIFT, false);
|
||||
//Once we hit 51% hp mark, after each rift we spawn an empowered
|
||||
events.ScheduleEvent(me->HealthBelowPct(51) ? EVENT_ANOMALUS_SPAWN_RIFT_EMPOWERED : EVENT_ANOMALUS_SPAWN_RIFT, IsHeroic() ? 15000 : 25000);
|
||||
break;
|
||||
case EVENT_ANOMALUS_SPAWN_RIFT_EMPOWERED:
|
||||
Talk(SAY_RIFT);
|
||||
Talk(EMOTE_RIFT);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
me->CastSpell(me, SPELL_CREATE_RIFT, false);
|
||||
me->CastSpell(me, SPELL_RIFT_SHIELD, true);
|
||||
me->m_Events.AddEvent(new ChargeRifts(me), me->m_Events.CalculateTime(1000));
|
||||
events.DelayEvents(46s);
|
||||
//As we just spawned an empowered spawn a normal one
|
||||
events.ScheduleEvent(EVENT_ANOMALUS_SPAWN_RIFT, IsHeroic() ? 15s : 25s);
|
||||
break;
|
||||
}
|
||||
|
||||
bool CheckEvadeIfOutOfCombatArea() const override
|
||||
{
|
||||
return me->GetHomePosition().GetExactDist2d(me) > 60.0f;
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool CheckEvadeIfOutOfCombatArea() const override
|
||||
{
|
||||
return me->GetHomePosition().GetExactDist2d(me) > 60.0f;
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_chaos_theory : public AchievementCriteriaScript
|
||||
{
|
||||
public:
|
||||
achievement_chaos_theory() : AchievementCriteriaScript("achievement_chaos_theory")
|
||||
{
|
||||
}
|
||||
achievement_chaos_theory() : AchievementCriteriaScript("achievement_chaos_theory") { }
|
||||
|
||||
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
|
||||
{
|
||||
@@ -219,6 +204,6 @@ public:
|
||||
|
||||
void AddSC_boss_anomalus()
|
||||
{
|
||||
new boss_anomalus();
|
||||
RegisterNexusCreatureAI(boss_anomalus);
|
||||
new achievement_chaos_theory();
|
||||
}
|
||||
|
||||
@@ -43,90 +43,77 @@ enum Says
|
||||
SAY_KILL = 2
|
||||
};
|
||||
|
||||
class boss_commander_stoutbeard : public CreatureScript
|
||||
struct boss_commander_stoutbeard : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_commander_stoutbeard() : CreatureScript("boss_commander_stoutbeard") { }
|
||||
boss_commander_stoutbeard(Creature* creature) : BossAI(creature, DATA_COMMANDER_EVENT) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<boss_commander_stoutbeardAI>(creature);
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
struct boss_commander_stoutbeardAI : public BossAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_commander_stoutbeardAI(Creature* creature) : BossAI(creature, DATA_COMMANDER_EVENT)
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_BATTLE_SHOUT, 0ms);
|
||||
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 10s);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 15s);
|
||||
events.ScheduleEvent(EVENT_COMMANDER_CHARGE, 1s);
|
||||
me->RemoveAllAuras();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BATTLE_SHOUT:
|
||||
me->CastSpell(me, SPELL_BATTLE_SHOUT, true);
|
||||
events.ScheduleEvent(EVENT_BATTLE_SHOUT, 2min);
|
||||
break;
|
||||
case EVENT_FRIGHTENING_SHOUT:
|
||||
me->CastSpell(me->GetVictim(), SPELL_FRIGHTENING_SHOUT, false);
|
||||
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 15s, 20s);
|
||||
break;
|
||||
case EVENT_WHIRLWIND:
|
||||
me->CastSpell(me, SPELL_WHIRLWIND, false);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 16s);
|
||||
break;
|
||||
case EVENT_COMMANDER_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 25.0f))
|
||||
me->CastSpell(target, SPELL_CHARGE, false);
|
||||
events.ScheduleEvent(EVENT_COMMANDER_CHARGE, 20s);
|
||||
break;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_BATTLE_SHOUT, 0ms);
|
||||
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 10s);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 15s);
|
||||
events.ScheduleEvent(EVENT_COMMANDER_CHARGE, 1s);
|
||||
me->RemoveAllAuras();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BATTLE_SHOUT:
|
||||
me->CastSpell(me, SPELL_BATTLE_SHOUT, true);
|
||||
events.ScheduleEvent(EVENT_BATTLE_SHOUT, 2min);
|
||||
break;
|
||||
case EVENT_FRIGHTENING_SHOUT:
|
||||
me->CastSpell(me->GetVictim(), SPELL_FRIGHTENING_SHOUT, false);
|
||||
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 15s, 20s);
|
||||
break;
|
||||
case EVENT_WHIRLWIND:
|
||||
me->CastSpell(me, SPELL_WHIRLWIND, false);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 16s);
|
||||
break;
|
||||
case EVENT_COMMANDER_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 25.0f))
|
||||
me->CastSpell(target, SPELL_CHARGE, false);
|
||||
events.ScheduleEvent(EVENT_COMMANDER_CHARGE, 20s);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_commander_stoutbeard()
|
||||
{
|
||||
new boss_commander_stoutbeard();
|
||||
RegisterNexusCreatureAI(boss_commander_stoutbeard);
|
||||
}
|
||||
|
||||
@@ -55,152 +55,137 @@ enum Events
|
||||
EVENT_KILL_TALK = 6
|
||||
};
|
||||
|
||||
class boss_keristrasza : public CreatureScript
|
||||
struct boss_keristrasza : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_keristrasza() : CreatureScript("boss_keristrasza") { }
|
||||
boss_keristrasza(Creature* creature) : BossAI(creature, DATA_KERISTRASZA_EVENT) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
std::set<uint32> aGuids;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<boss_keristraszaAI>(creature);
|
||||
BossAI::Reset();
|
||||
RemovePrison(CanRemovePrison());
|
||||
aGuids.clear();
|
||||
}
|
||||
|
||||
struct boss_keristraszaAI : public BossAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_keristraszaAI(Creature* creature) : BossAI(creature, DATA_KERISTRASZA_EVENT)
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
me->CastSpell(me, SPELL_INTENSE_COLD, true);
|
||||
events.ScheduleEvent(EVENT_CRYSTALFIRE_BREATH, 14s);
|
||||
events.ScheduleEvent(EVENT_CRYSTAL_CHAINS, DUNGEON_MODE(20000, 11000));
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 5s);
|
||||
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1s);
|
||||
events.ScheduleEvent(EVENT_ACHIEVEMENT_CHECK, 1s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<uint32> aGuids;
|
||||
void SetData(uint32 type, uint32) override
|
||||
{
|
||||
if (type == me->GetEntry() && CanRemovePrison())
|
||||
RemovePrison(true);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
bool CanRemovePrison()
|
||||
{
|
||||
for (uint8 i = DATA_TELESTRA_ORB; i <= DATA_ORMOROK_ORB; ++i)
|
||||
if (instance->GetBossState(i) != DONE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemovePrison(bool remove)
|
||||
{
|
||||
if (remove)
|
||||
{
|
||||
BossAI::Reset();
|
||||
RemovePrison(CanRemovePrison());
|
||||
aGuids.clear();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
else
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->CastSpell(me, SPELL_FROZEN_PRISON, true);
|
||||
}
|
||||
}
|
||||
|
||||
me->CastSpell(me, SPELL_INTENSE_COLD, true);
|
||||
events.ScheduleEvent(EVENT_CRYSTALFIRE_BREATH, 14s);
|
||||
events.ScheduleEvent(EVENT_CRYSTAL_CHAINS, DUNGEON_MODE(20000, 11000));
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 5s);
|
||||
uint32 GetData(uint32 guid) const override
|
||||
{
|
||||
return aGuids.find(guid) == aGuids.end();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_HEALTH_CHECK:
|
||||
if (me->HealthBelowPct(26))
|
||||
{
|
||||
Talk(SAY_ENRAGE);
|
||||
Talk(EMOTE_FRENZY);
|
||||
me->CastSpell(me, SPELL_ENRAGE, true);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1s);
|
||||
events.ScheduleEvent(EVENT_ACHIEVEMENT_CHECK, 1s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
break;
|
||||
case EVENT_ACHIEVEMENT_CHECK:
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
|
||||
if (Aura* aur = itr->GetSource()->GetAura(SPELL_INTENSE_COLD_TRIGGER))
|
||||
if (aur->GetStackAmount() > 2)
|
||||
aGuids.insert(itr->GetSource()->GetGUID().GetCounter());
|
||||
events.ScheduleEvent(EVENT_ACHIEVEMENT_CHECK, 500ms);
|
||||
break;
|
||||
}
|
||||
case EVENT_CRYSTALFIRE_BREATH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CRYSTALFIRE_BREATH, false);
|
||||
events.ScheduleEvent(EVENT_CRYSTALFIRE_BREATH, 14s);
|
||||
break;
|
||||
case EVENT_TAIL_SWEEP:
|
||||
me->CastSpell(me, SPELL_TAIL_SWEEP, false);
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 5s);
|
||||
break;
|
||||
case EVENT_CRYSTAL_CHAINS:
|
||||
Talk(SAY_CRYSTAL_NOVA);
|
||||
if (IsHeroic())
|
||||
me->CastSpell(me, SPELL_CRYSTALIZE, false);
|
||||
else if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
me->CastSpell(target, SPELL_CRYSTAL_CHAINS, false);
|
||||
events.ScheduleEvent(EVENT_CRYSTAL_CHAINS, DUNGEON_MODE(20000, 11000));
|
||||
break;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32) override
|
||||
{
|
||||
if (type == me->GetEntry() && CanRemovePrison())
|
||||
RemovePrison(true);
|
||||
}
|
||||
|
||||
bool CanRemovePrison()
|
||||
{
|
||||
for (uint8 i = DATA_TELESTRA_ORB; i <= DATA_ORMOROK_ORB; ++i)
|
||||
if (instance->GetBossState(i) != DONE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemovePrison(bool remove)
|
||||
{
|
||||
if (remove)
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->CastSpell(me, SPELL_FROZEN_PRISON, true);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 guid) const override
|
||||
{
|
||||
return aGuids.find(guid) == aGuids.end();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_HEALTH_CHECK:
|
||||
if (me->HealthBelowPct(26))
|
||||
{
|
||||
Talk(SAY_ENRAGE);
|
||||
Talk(EMOTE_FRENZY);
|
||||
me->CastSpell(me, SPELL_ENRAGE, true);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1s);
|
||||
break;
|
||||
case EVENT_ACHIEVEMENT_CHECK:
|
||||
{
|
||||
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
|
||||
for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
|
||||
if (Aura* aur = itr->GetSource()->GetAura(SPELL_INTENSE_COLD_TRIGGER))
|
||||
if (aur->GetStackAmount() > 2)
|
||||
aGuids.insert(itr->GetSource()->GetGUID().GetCounter());
|
||||
events.ScheduleEvent(EVENT_ACHIEVEMENT_CHECK, 500ms);
|
||||
break;
|
||||
}
|
||||
case EVENT_CRYSTALFIRE_BREATH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CRYSTALFIRE_BREATH, false);
|
||||
events.ScheduleEvent(EVENT_CRYSTALFIRE_BREATH, 14s);
|
||||
break;
|
||||
case EVENT_TAIL_SWEEP:
|
||||
me->CastSpell(me, SPELL_TAIL_SWEEP, false);
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 5s);
|
||||
break;
|
||||
case EVENT_CRYSTAL_CHAINS:
|
||||
Talk(SAY_CRYSTAL_NOVA);
|
||||
if (IsHeroic())
|
||||
me->CastSpell(me, SPELL_CRYSTALIZE, false);
|
||||
else if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
me->CastSpell(target, SPELL_CRYSTAL_CHAINS, false);
|
||||
events.ScheduleEvent(EVENT_CRYSTAL_CHAINS, DUNGEON_MODE(20000, 11000));
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_intense_cold : public AchievementCriteriaScript
|
||||
{
|
||||
public:
|
||||
achievement_intense_cold() : AchievementCriteriaScript("achievement_intense_cold")
|
||||
{
|
||||
}
|
||||
achievement_intense_cold() : AchievementCriteriaScript("achievement_intense_cold") { }
|
||||
|
||||
bool OnCheck(Player* player, Unit* target, uint32 /*criteria_id*/) override
|
||||
{
|
||||
@@ -213,6 +198,6 @@ public:
|
||||
|
||||
void AddSC_boss_keristrasza()
|
||||
{
|
||||
new boss_keristrasza();
|
||||
RegisterNexusCreatureAI(boss_keristrasza);
|
||||
new achievement_intense_cold();
|
||||
}
|
||||
|
||||
@@ -79,159 +79,146 @@ enum Events
|
||||
EVENT_KILL_TALK = 9
|
||||
};
|
||||
|
||||
class boss_magus_telestra : public CreatureScript
|
||||
struct boss_magus_telestra : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_magus_telestra() : CreatureScript("boss_magus_telestra") { }
|
||||
boss_magus_telestra(Creature* creature) : BossAI(creature, DATA_MAGUS_TELESTRA_EVENT) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
uint8 copiesDied;
|
||||
bool achievement;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<boss_magus_telestraAI>(creature);
|
||||
BossAI::Reset();
|
||||
copiesDied = 0;
|
||||
achievement = true;
|
||||
|
||||
if (IsHeroic() && sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL) && !me->HasAura(SPELL_WEAR_CHRISTMAS_HAT))
|
||||
me->AddAura(SPELL_WEAR_CHRISTMAS_HAT, me);
|
||||
}
|
||||
|
||||
struct boss_magus_telestraAI : public BossAI
|
||||
uint32 GetData(uint32 data) const override
|
||||
{
|
||||
boss_magus_telestraAI(Creature* creature) : BossAI(creature, DATA_MAGUS_TELESTRA_EVENT)
|
||||
if (data == me->GetEntry())
|
||||
return achievement;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_MAGUS_ICE_NOVA, 10s);
|
||||
events.ScheduleEvent(EVENT_MAGUS_FIREBOMB, 0ms);
|
||||
events.ScheduleEvent(EVENT_MAGUS_GRAVITY_WELL, 20s);
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH1, 1s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH2, 1s);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (who && me->Attack(who, true))
|
||||
me->GetMotionMaster()->MoveChase(who, 20.0f);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 copiesDied;
|
||||
bool achievement;
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id >= SPELL_FIRE_MAGUS_DEATH && spellInfo->Id <= SPELL_ARCANE_MAGUS_DEATH && caster->ToCreature())
|
||||
{
|
||||
BossAI::Reset();
|
||||
copiesDied = 0;
|
||||
achievement = true;
|
||||
events.ScheduleEvent(EVENT_MAGUS_FAIL_ACHIEVEMENT, 5s);
|
||||
caster->ToCreature()->DespawnOrUnsummon(1000);
|
||||
|
||||
if (IsHeroic() && sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL) && !me->HasAura(SPELL_WEAR_CHRISTMAS_HAT))
|
||||
me->AddAura(SPELL_WEAR_CHRISTMAS_HAT, me);
|
||||
if (++copiesDied >= 3)
|
||||
{
|
||||
copiesDied = 0;
|
||||
events.CancelEvent(EVENT_MAGUS_FAIL_ACHIEVEMENT);
|
||||
events.ScheduleEvent(EVENT_MAGUS_MERGED, 5s);
|
||||
me->CastSpell(me, SPELL_BURNING_WINDS, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
if (data == me->GetEntry())
|
||||
return achievement;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_MAGUS_ICE_NOVA, 10s);
|
||||
events.ScheduleEvent(EVENT_MAGUS_FIREBOMB, 0ms);
|
||||
events.ScheduleEvent(EVENT_MAGUS_GRAVITY_WELL, 20s);
|
||||
case EVENT_MAGUS_HEALTH1:
|
||||
if (me->HealthBelowPct(51))
|
||||
{
|
||||
me->CastSpell(me, SPELL_START_SUMMON_CLONES, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_RELOCATE, 3500ms);
|
||||
Talk(SAY_SPLIT);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH1, 1s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH2, 1s);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (who && me->Attack(who, true))
|
||||
me->GetMotionMaster()->MoveChase(who, 20.0f);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
break;
|
||||
case EVENT_MAGUS_HEALTH2:
|
||||
if (me->HealthBelowPct(11))
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
me->CastSpell(me, SPELL_START_SUMMON_CLONES, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_RELOCATE, 3500ms);
|
||||
Talk(SAY_SPLIT);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH2, 1s);
|
||||
break;
|
||||
case EVENT_MAGUS_FIREBOMB:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_FIREBOMB, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_FIREBOMB, 3s);
|
||||
break;
|
||||
case EVENT_MAGUS_ICE_NOVA:
|
||||
me->CastSpell(me, SPELL_ICE_NOVA, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_ICE_NOVA, 15s);
|
||||
break;
|
||||
case EVENT_MAGUS_GRAVITY_WELL:
|
||||
me->CastSpell(me, SPELL_GRAVITY_WELL, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_GRAVITY_WELL, 15s);
|
||||
break;
|
||||
case EVENT_MAGUS_FAIL_ACHIEVEMENT:
|
||||
achievement = false;
|
||||
break;
|
||||
case EVENT_MAGUS_RELOCATE:
|
||||
me->NearTeleportTo(505.04f, 88.915f, -16.13f, 2.98f);
|
||||
break;
|
||||
case EVENT_MAGUS_MERGED:
|
||||
me->CastSpell(me, SPELL_TELESTRA_BACK, true);
|
||||
me->RemoveAllAuras();
|
||||
Talk(SAY_MERGE);
|
||||
break;
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id >= SPELL_FIRE_MAGUS_DEATH && spellInfo->Id <= SPELL_ARCANE_MAGUS_DEATH && caster->ToCreature())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_MAGUS_FAIL_ACHIEVEMENT, 5s);
|
||||
caster->ToCreature()->DespawnOrUnsummon(1000);
|
||||
|
||||
if (++copiesDied >= 3)
|
||||
{
|
||||
copiesDied = 0;
|
||||
events.CancelEvent(EVENT_MAGUS_FAIL_ACHIEVEMENT);
|
||||
events.ScheduleEvent(EVENT_MAGUS_MERGED, 5s);
|
||||
me->CastSpell(me, SPELL_BURNING_WINDS, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_MAGUS_HEALTH1:
|
||||
if (me->HealthBelowPct(51))
|
||||
{
|
||||
me->CastSpell(me, SPELL_START_SUMMON_CLONES, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_RELOCATE, 3500ms);
|
||||
Talk(SAY_SPLIT);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH1, 1s);
|
||||
break;
|
||||
case EVENT_MAGUS_HEALTH2:
|
||||
if (me->HealthBelowPct(11))
|
||||
{
|
||||
me->CastSpell(me, SPELL_START_SUMMON_CLONES, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_RELOCATE, 3500ms);
|
||||
Talk(SAY_SPLIT);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_MAGUS_HEALTH2, 1s);
|
||||
break;
|
||||
case EVENT_MAGUS_FIREBOMB:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_FIREBOMB, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_FIREBOMB, 3s);
|
||||
break;
|
||||
case EVENT_MAGUS_ICE_NOVA:
|
||||
me->CastSpell(me, SPELL_ICE_NOVA, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_ICE_NOVA, 15s);
|
||||
break;
|
||||
case EVENT_MAGUS_GRAVITY_WELL:
|
||||
me->CastSpell(me, SPELL_GRAVITY_WELL, false);
|
||||
events.ScheduleEvent(EVENT_MAGUS_GRAVITY_WELL, 15s);
|
||||
break;
|
||||
case EVENT_MAGUS_FAIL_ACHIEVEMENT:
|
||||
achievement = false;
|
||||
break;
|
||||
case EVENT_MAGUS_RELOCATE:
|
||||
me->NearTeleportTo(505.04f, 88.915f, -16.13f, 2.98f);
|
||||
break;
|
||||
case EVENT_MAGUS_MERGED:
|
||||
me->CastSpell(me, SPELL_TELESTRA_BACK, true);
|
||||
me->RemoveAllAuras();
|
||||
Talk(SAY_MERGE);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_boss_magus_telestra_summon_telestra_clones_aura : public AuraScript
|
||||
@@ -331,7 +318,7 @@ public:
|
||||
|
||||
void AddSC_boss_magus_telestra()
|
||||
{
|
||||
new boss_magus_telestra();
|
||||
RegisterNexusCreatureAI(boss_magus_telestra);
|
||||
RegisterSpellScript(spell_boss_magus_telestra_summon_telestra_clones_aura);
|
||||
RegisterSpellScript(spell_boss_magus_telestra_gravity_well);
|
||||
new achievement_split_personality();
|
||||
|
||||
@@ -60,173 +60,147 @@ enum Misc
|
||||
GO_CRYSTAL_SPIKE = 188537
|
||||
};
|
||||
|
||||
class boss_ormorok : public CreatureScript
|
||||
struct boss_ormorok : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_ormorok() : CreatureScript("boss_ormorok") { }
|
||||
boss_ormorok(Creature* creature) : BossAI(creature, DATA_ORMOROK_EVENT) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
uint8 _spikesCount;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<boss_ormorokAI>(creature);
|
||||
_spikesCount = 0;
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
struct boss_ormorokAI : public BossAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK_EVENT)
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_ORMOROK_CRYSTAL_SPIKES, 12s);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_TRAMPLE, 10s);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SPELL_REFLECTION, 30s);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_HEALTH, 1s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON, 17s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 _spikesCount;
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
_spikesCount = 0;
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_ORMOROK_CRYSTAL_SPIKES, 12s);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_TRAMPLE, 10s);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SPELL_REFLECTION, 30s);
|
||||
case EVENT_ORMOROK_HEALTH:
|
||||
if (me->HealthBelowPct(26))
|
||||
{
|
||||
me->CastSpell(me, SPELL_FRENZY, true);
|
||||
Talk(EMOTE_FRENZY);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ORMOROK_HEALTH, 1s);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON, 17s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
break;
|
||||
case EVENT_ORMOROK_TRAMPLE:
|
||||
me->CastSpell(me, SPELL_TRAMPLE, false);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_TRAMPLE, 10s);
|
||||
break;
|
||||
case EVENT_ORMOROK_SPELL_REFLECTION:
|
||||
Talk(SAY_REFLECT);
|
||||
me->CastSpell(me, SPELL_SPELL_REFLECTION, false);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SPELL_REFLECTION, 30s);
|
||||
break;
|
||||
case EVENT_ORMOROK_SUMMON:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 50.0f, true))
|
||||
me->CastSpell(target, SPELL_SUMMON_CRYSTALLINE_TANGLER, true);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON, 17s);
|
||||
break;
|
||||
case EVENT_ORMOROK_CRYSTAL_SPIKES:
|
||||
Talk(SAY_CRYSTAL_SPIKES);
|
||||
me->CastSpell(me, SPELL_CRYSTAL_SPIKES, false);
|
||||
_spikesCount = 0;
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON_SPIKES, 300ms);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_CRYSTAL_SPIKES, 20s);
|
||||
break;
|
||||
case EVENT_ORMOROK_SUMMON_SPIKES:
|
||||
if (++_spikesCount > 9)
|
||||
break;
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6s);
|
||||
float o = rand_norm() * 2.0f * M_PI;
|
||||
float x = me->GetPositionX() + 5.0f * _spikesCount * cos(o);
|
||||
float y = me->GetPositionY() + 5.0f * _spikesCount * std::sin(o);
|
||||
float h = me->GetMapHeight(x, y, me->GetPositionZ());
|
||||
|
||||
if (h != INVALID_HEIGHT)
|
||||
me->SummonCreature(NPC_CRYSTAL_SPIKE, x, y, h, 0, TEMPSUMMON_TIMED_DESPAWN, 7000);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON_SPIKES, 200ms);
|
||||
break;
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ORMOROK_HEALTH:
|
||||
if (me->HealthBelowPct(26))
|
||||
{
|
||||
me->CastSpell(me, SPELL_FRENZY, true);
|
||||
Talk(EMOTE_FRENZY);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ORMOROK_HEALTH, 1s);
|
||||
break;
|
||||
case EVENT_ORMOROK_TRAMPLE:
|
||||
me->CastSpell(me, SPELL_TRAMPLE, false);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_TRAMPLE, 10s);
|
||||
break;
|
||||
case EVENT_ORMOROK_SPELL_REFLECTION:
|
||||
Talk(SAY_REFLECT);
|
||||
me->CastSpell(me, SPELL_SPELL_REFLECTION, false);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SPELL_REFLECTION, 30s);
|
||||
break;
|
||||
case EVENT_ORMOROK_SUMMON:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 50.0f, true))
|
||||
me->CastSpell(target, SPELL_SUMMON_CRYSTALLINE_TANGLER, true);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON, 17s);
|
||||
break;
|
||||
case EVENT_ORMOROK_CRYSTAL_SPIKES:
|
||||
Talk(SAY_CRYSTAL_SPIKES);
|
||||
me->CastSpell(me, SPELL_CRYSTAL_SPIKES, false);
|
||||
_spikesCount = 0;
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON_SPIKES, 300ms);
|
||||
events.ScheduleEvent(EVENT_ORMOROK_CRYSTAL_SPIKES, 20s);
|
||||
break;
|
||||
case EVENT_ORMOROK_SUMMON_SPIKES:
|
||||
if (++_spikesCount > 9)
|
||||
break;
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
float o = rand_norm() * 2.0f * M_PI;
|
||||
float x = me->GetPositionX() + 5.0f * _spikesCount * cos(o);
|
||||
float y = me->GetPositionY() + 5.0f * _spikesCount * std::sin(o);
|
||||
float h = me->GetMapHeight(x, y, me->GetPositionZ());
|
||||
|
||||
if (h != INVALID_HEIGHT)
|
||||
me->SummonCreature(NPC_CRYSTAL_SPIKE, x, y, h, 0, TEMPSUMMON_TIMED_DESPAWN, 7000);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ORMOROK_SUMMON_SPIKES, 200ms);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
class npc_crystal_spike : public CreatureScript
|
||||
struct npc_crystal_spike : public NullCreatureAI
|
||||
{
|
||||
public:
|
||||
npc_crystal_spike() : CreatureScript("npc_crystal_spike") { }
|
||||
npc_crystal_spike(Creature* c) : NullCreatureAI(c) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const override
|
||||
int32 _damageTimer;
|
||||
ObjectGuid _gameObjectGUID;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<npc_crystal_spikeAI>(pCreature);
|
||||
if (GameObject* gameobject = me->SummonGameObject(GO_CRYSTAL_SPIKE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3500))
|
||||
_gameObjectGUID = gameobject->GetGUID();
|
||||
|
||||
_damageTimer = 1;
|
||||
}
|
||||
|
||||
struct npc_crystal_spikeAI : public NullCreatureAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
npc_crystal_spikeAI(Creature* c) : NullCreatureAI(c)
|
||||
if (_damageTimer)
|
||||
{
|
||||
}
|
||||
|
||||
int32 _damageTimer;
|
||||
ObjectGuid _gameObjectGUID;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (GameObject* gameobject = me->SummonGameObject(GO_CRYSTAL_SPIKE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3500))
|
||||
_gameObjectGUID = gameobject->GetGUID();
|
||||
|
||||
_damageTimer = 1;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_damageTimer)
|
||||
_damageTimer += diff;
|
||||
if (_damageTimer >= 2000)
|
||||
{
|
||||
_damageTimer += diff;
|
||||
if (_damageTimer >= 2000)
|
||||
{
|
||||
if (GameObject* gameobject = ObjectAccessor::GetGameObject(*me, _gameObjectGUID))
|
||||
gameobject->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* gameobject = ObjectAccessor::GetGameObject(*me, _gameObjectGUID))
|
||||
gameobject->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
me->CastSpell(me, SPELL_CRYSTAL_SPIKE_DAMAGE, false);
|
||||
_damageTimer = 0;
|
||||
}
|
||||
me->CastSpell(me, SPELL_CRYSTAL_SPIKE_DAMAGE, false);
|
||||
_damageTimer = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_ormorok()
|
||||
{
|
||||
new boss_ormorok();
|
||||
new npc_crystal_spike();
|
||||
RegisterNexusCreatureAI(boss_ormorok);
|
||||
RegisterNexusCreatureAI(npc_crystal_spike);
|
||||
}
|
||||
|
||||
@@ -166,110 +166,97 @@ enum eFrayer
|
||||
SPELL_ENSNARE = 48053
|
||||
};
|
||||
|
||||
class npc_crystalline_frayer : public CreatureScript
|
||||
struct npc_crystalline_frayer : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_crystalline_frayer() : CreatureScript("npc_crystalline_frayer") { }
|
||||
npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool _allowDeath;
|
||||
uint32 restoreTimer;
|
||||
uint32 abilityTimer1;
|
||||
uint32 abilityTimer2;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetNexusAI<npc_crystalline_frayerAI>(creature);
|
||||
restoreTimer = 0;
|
||||
abilityTimer1 = 0;
|
||||
abilityTimer2 = 30000;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
struct npc_crystalline_frayerAI : public ScriptedAI
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
npc_crystalline_frayerAI(Creature* creature) : ScriptedAI(creature)
|
||||
_allowDeath = me->GetInstanceScript()->GetBossState(DATA_ORMOROK_EVENT) == DONE;
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (me->isRegeneratingHealth())
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
if (!_allowDeath)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
damage = 0;
|
||||
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->CastSpell(me, SPELL_SUMMON_SEED_POD, true);
|
||||
me->CastSpell(me, SPELL_SEED_POD, true);
|
||||
me->CastSpell(me, SPELL_AURA_OF_REGENERATION, false);
|
||||
restoreTimer = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (restoreTimer)
|
||||
{
|
||||
restoreTimer += diff;
|
||||
if (restoreTimer >= 90 * IN_MILLISECONDS)
|
||||
{
|
||||
Talk(0);
|
||||
me->SetRegeneratingHealth(true);
|
||||
restoreTimer = 0;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool _allowDeath;
|
||||
uint32 restoreTimer;
|
||||
uint32 abilityTimer1;
|
||||
uint32 abilityTimer2;
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
void Reset() override
|
||||
abilityTimer1 += diff;
|
||||
abilityTimer2 += diff;
|
||||
|
||||
if (abilityTimer1 >= 5000)
|
||||
{
|
||||
restoreTimer = 0;
|
||||
me->CastSpell(me->GetVictim(), SPELL_ENSNARE, false);
|
||||
abilityTimer1 = 0;
|
||||
abilityTimer2 = 30000;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
if (abilityTimer2 >= 30000)
|
||||
{
|
||||
_allowDeath = me->GetInstanceScript()->GetBossState(DATA_ORMOROK_EVENT) == DONE;
|
||||
me->CastSpell(me->GetVictim(), SPELL_CRYSTAL_BLOOM, false);
|
||||
abilityTimer2 = 0;
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (me->isRegeneratingHealth())
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
if (!_allowDeath)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
damage = 0;
|
||||
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->CastSpell(me, SPELL_SUMMON_SEED_POD, true);
|
||||
me->CastSpell(me, SPELL_SEED_POD, true);
|
||||
me->CastSpell(me, SPELL_AURA_OF_REGENERATION, false);
|
||||
restoreTimer = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (restoreTimer)
|
||||
{
|
||||
restoreTimer += diff;
|
||||
if (restoreTimer >= 90 * IN_MILLISECONDS)
|
||||
{
|
||||
Talk(0);
|
||||
me->SetRegeneratingHealth(true);
|
||||
restoreTimer = 0;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
abilityTimer1 += diff;
|
||||
abilityTimer2 += diff;
|
||||
|
||||
if (abilityTimer1 >= 5000)
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_ENSNARE, false);
|
||||
abilityTimer1 = 0;
|
||||
}
|
||||
|
||||
if (abilityTimer2 >= 30000)
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_CRYSTAL_BLOOM, false);
|
||||
abilityTimer2 = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_nexus()
|
||||
{
|
||||
new instance_nexus();
|
||||
new npc_crystalline_frayer();
|
||||
RegisterNexusCreatureAI(npc_crystalline_frayer);
|
||||
}
|
||||
|
||||
@@ -62,4 +62,6 @@ inline AI* GetNexusAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, NexusScriptName);
|
||||
}
|
||||
|
||||
#define RegisterNexusCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetNexusAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -817,7 +817,12 @@ struct npc_lord_sanguinar : public advisor_baseAI
|
||||
{
|
||||
npc_lord_sanguinar(Creature* creature) : advisor_baseAI(creature) { };
|
||||
|
||||
void ScheduleEvents() override {}
|
||||
void ScheduleEvents() override
|
||||
{
|
||||
ScheduleTimedEvent(0s, 2s, [&]{
|
||||
DoCastSelf(SPELL_BELLOWING_ROAR);
|
||||
}, 30s, 40s);
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_capernian : public advisor_baseAI
|
||||
|
||||
@@ -5298,6 +5298,28 @@ class spell_gen_steal_weapon : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 43536 - Serverside - SetHealth (75%)
|
||||
// 43537 - Serverside - SetHealth (50%)
|
||||
// 43538 - Serverside - SetHealth (25%)
|
||||
class spell_gen_set_health : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_gen_set_health);
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
uint32 value = GetSpellInfo()->Effects[EFFECT_0].CalcValue();
|
||||
target->SetHealth(target->CountPctFromMaxHealth(value));
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_gen_set_health::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_generic_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_silithyst);
|
||||
@@ -5455,4 +5477,5 @@ void AddSC_generic_spell_scripts()
|
||||
RegisterSpellScript(spell_gen_consumption);
|
||||
RegisterSpellScript(spell_gen_sober_up);
|
||||
RegisterSpellScript(spell_gen_steal_weapon);
|
||||
RegisterSpellScript(spell_gen_set_health);
|
||||
}
|
||||
|
||||
@@ -4162,6 +4162,30 @@ class spell_item_spell_reflectors: public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 46273 - Multiphase Goggles
|
||||
class spell_item_multiphase_goggles : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_item_multiphase_goggles);
|
||||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetTarget()->ToPlayer())
|
||||
player->SetFlag(PLAYER_TRACK_CREATURES, uint32(1) << (CREATURE_TYPE_GAS_CLOUD - 1));
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetTarget()->ToPlayer())
|
||||
player->RemoveFlag(PLAYER_TRACK_CREATURES, uint32(1) << (CREATURE_TYPE_GAS_CLOUD - 1));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_item_multiphase_goggles::OnApply, EFFECT_0, SPELL_AURA_MOD_INVISIBILITY_DETECT , AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_item_multiphase_goggles::OnRemove, EFFECT_0, SPELL_AURA_MOD_INVISIBILITY_DETECT , AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_item_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_item_massive_seaforium_charge);
|
||||
@@ -4289,4 +4313,5 @@ void AddSC_item_spell_scripts()
|
||||
RegisterSpellScript(spell_item_skyguard_blasting_charges);
|
||||
RegisterSpellScript(spell_item_luffa);
|
||||
RegisterSpellScript(spell_item_spell_reflectors);
|
||||
RegisterSpellScript(spell_item_multiphase_goggles);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user