refactor(Scripts/MagistersTerrace): Update scripts to new register model (#17725)

This commit is contained in:
Andrew
2023-11-15 21:04:14 -03:00
committed by GitHub
parent 01c21539f9
commit 8fbed6c30e
4 changed files with 1111 additions and 1254 deletions

View File

@@ -76,259 +76,237 @@ enum Misc
CREATURE_ARCANE_SPHERE = 24708
};
class boss_felblood_kaelthas : public CreatureScript
struct boss_felblood_kaelthas : public ScriptedAI
{
public:
boss_felblood_kaelthas() : CreatureScript("boss_felblood_kaelthas") { }
CreatureAI* GetAI(Creature* creature) const override
boss_felblood_kaelthas(Creature* creature) : ScriptedAI(creature), summons(me)
{
return GetMagistersTerraceAI<boss_felblood_kaelthasAI>(creature);
instance = creature->GetInstanceScript();
introSpeak = false;
}
struct boss_felblood_kaelthasAI : public ScriptedAI
InstanceScript* instance;
EventMap events;
EventMap events2;
SummonList summons;
bool introSpeak;
void Reset() override
{
boss_felblood_kaelthasAI(Creature* creature) : ScriptedAI(creature), summons(me)
events.Reset();
summons.DespawnAll();
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
instance->SetBossState(DATA_KAELTHAS, NOT_STARTED);
me->SetImmuneToAll(false);
}
void JustSummoned(Creature* summon) override
{
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (*itr == summon->GetGUID())
return;
summons.Summon(summon);
}
void InitializeAI() override
{
ScriptedAI::InitializeAI();
me->SetImmuneToAll(true);
}
void JustDied(Unit*) override
{
instance->SetBossState(DATA_KAELTHAS, DONE);
if (GameObject* orb = instance->GetGameObject(DATA_ESCAPE_ORB))
{
instance = creature->GetInstanceScript();
introSpeak = false;
orb->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 0);
events.ScheduleEvent(EVENT_SPELL_PHOENIX, 15000);
events.ScheduleEvent(EVENT_SPELL_FLAMESTRIKE, 22000);
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_SHOCK_BARRIER, 50000);
}
void MoveInLineOfSight(Unit* who) override
{
if (!introSpeak && me->IsWithinDistInMap(who, 40.0f) && who->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_AGGRO);
introSpeak = true;
events2.ScheduleEvent(EVENT_INIT_COMBAT, 35000);
}
InstanceScript* instance;
EventMap events;
EventMap events2;
SummonList summons;
bool introSpeak;
ScriptedAI::MoveInLineOfSight(who);
}
void Reset() override
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage >= me->GetHealth())
{
events.Reset();
summons.DespawnAll();
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
instance->SetBossState(DATA_KAELTHAS, NOT_STARTED);
damage = me->GetHealth() - 1;
if (me->isRegeneratingHealth())
{
me->SetRegeneratingHealth(false);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->SetImmuneToAll(true);
me->CombatStop();
me->SetReactState(REACT_PASSIVE);
LapseAction(ACTION_REMOVE_FLY);
events.Reset();
events2.ScheduleEvent(EVENT_FINISH_TALK, 6000);
Talk(SAY_DEATH);
}
}
}
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())
{
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);
}
}
}
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;
}
void JustSummoned(Creature* summon) override
{
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (*itr == summon->GetGUID())
return;
summons.Summon(summon);
}
if (!UpdateVictim())
return;
void InitializeAI() override
{
ScriptedAI::InitializeAI();
me->SetImmuneToAll(true);
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
void JustDied(Unit*) override
switch (uint32 eventId = events.ExecuteEvent())
{
instance->SetBossState(DATA_KAELTHAS, DONE);
if (GameObject* orb = instance->GetGameObject(DATA_ESCAPE_ORB))
case EVENT_SPELL_FIREBALL:
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_FIREBALL_N, SPELL_FIREBALL_H), false);
events.ScheduleEvent(EVENT_SPELL_FIREBALL, urand(3000, 4500));
break;
case EVENT_SPELL_FLAMESTRIKE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
{
orb->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
me->CastSpell(target, SPELL_FLAMESTRIKE_SUMMON, true);
Talk(SAY_FLAMESTRIKE);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 0);
events.ScheduleEvent(EVENT_SPELL_PHOENIX, 15000);
events.ScheduleEvent(EVENT_SPELL_FLAMESTRIKE, 22000);
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_SHOCK_BARRIER, 50000);
}
void MoveInLineOfSight(Unit* who) override
{
if (!introSpeak && me->IsWithinDistInMap(who, 40.0f) && who->GetTypeId() == TYPEID_PLAYER)
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))
{
Talk(SAY_AGGRO);
introSpeak = true;
events2.ScheduleEvent(EVENT_INIT_COMBAT, 35000);
}
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
me->CastSpell(me, SPELL_TELEPORT_CENTER, true);
events.Reset();
ScriptedAI::MoveInLineOfSight(who);
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;
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage >= me->GetHealth())
{
damage = me->GetHealth() - 1;
if (me->isRegeneratingHealth())
{
me->SetRegeneratingHealth(false);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->SetImmuneToAll(true);
me->CombatStop();
me->SetReactState(REACT_PASSIVE);
LapseAction(ACTION_REMOVE_FLY);
events.Reset();
events2.ScheduleEvent(EVENT_FINISH_TALK, 6000);
Talk(SAY_DEATH);
}
}
}
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())
{
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);
}
}
}
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(), DUNGEON_MODE(SPELL_FIREBALL_N, SPELL_FIREBALL_H), 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();
}
};
if (events.GetPhaseMask() == 0)
DoMeleeAttackIfReady();
}
};
class spell_mt_phoenix_burn : public SpellScriptLoader
class spell_mt_phoenix_burn : public SpellScript
{
public:
spell_mt_phoenix_burn() : SpellScriptLoader("spell_mt_phoenix_burn") { }
PrepareSpellScript(spell_mt_phoenix_burn);
class spell_mt_phoenix_burn_SpellScript : public SpellScript
void HandleAfterCast()
{
PrepareSpellScript(spell_mt_phoenix_burn_SpellScript);
uint32 damage = CalculatePct(GetCaster()->GetMaxHealth(), 5);
Unit::DealDamage(GetCaster(), GetCaster(), damage);
}
void HandleAfterCast()
{
uint32 damage = CalculatePct(GetCaster()->GetMaxHealth(), 5);
Unit::DealDamage(GetCaster(), GetCaster(), damage);
}
void Register() override
{
AfterCast += SpellCastFn(spell_mt_phoenix_burn_SpellScript::HandleAfterCast);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_mt_phoenix_burn_SpellScript();
AfterCast += SpellCastFn(spell_mt_phoenix_burn::HandleAfterCast);
}
};
void AddSC_boss_felblood_kaelthas()
{
new boss_felblood_kaelthas();
new spell_mt_phoenix_burn();
RegisterMagistersTerraceCreatureAI(boss_felblood_kaelthas);
RegisterSpellScript(spell_mt_phoenix_burn);
}

View File

@@ -52,188 +52,177 @@ enum Events
EVENT_RESTORE_COMBAT = 6
};
class boss_selin_fireheart : public CreatureScript
struct boss_selin_fireheart : public ScriptedAI
{
public:
boss_selin_fireheart() : CreatureScript("boss_selin_fireheart") { }
CreatureAI* GetAI(Creature* creature) const override
boss_selin_fireheart(Creature* creature) : ScriptedAI(creature), summons(me)
{
return GetMagistersTerraceAI<boss_selin_fireheartAI>(creature);
};
instance = creature->GetInstanceScript();
}
struct boss_selin_fireheartAI : public ScriptedAI
InstanceScript* instance;
EventMap events;
SummonList summons;
ObjectGuid CrystalGUID;
bool CanAIAttack(Unit const* who) const override
{
boss_selin_fireheartAI(Creature* creature) : ScriptedAI(creature), summons(me)
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();
SpawnCrystals();
instance->SetBossState(DATA_SELIN_FIREHEART, NOT_STARTED);
CrystalGUID.Clear();
me->SetPower(POWER_MANA, 0);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetBossState(DATA_SELIN_FIREHEART, IN_PROGRESS);
events.ScheduleEvent(EVENT_SPELL_DRAIN_LIFE, 2500, 1);
events.ScheduleEvent(EVENT_SPELL_FEL_EXPLOSION, 2000);
events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, 14000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 7500, 1);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_SELIN_FIREHEART, DONE); // Encounter complete!
summons.DespawnAll();
}
void SelectNearestCrystal()
{
if (summons.empty())
return;
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)
{
instance = creature->GetInstanceScript();
Talk(SAY_ENERGY);
float x, y, z;
crystal->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
CrystalGUID = crystal->GetGUID();
me->GetMotionMaster()->MovePoint(2, x, y, z);
}
}
InstanceScript* instance;
EventMap events;
SummonList summons;
ObjectGuid CrystalGUID;
bool CanAIAttack(Unit const* who) const override
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == 2)
{
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)
if (Unit* crystal = ObjectAccessor::GetUnit(*me, CrystalGUID))
{
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);
}
else
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 0);
}
}
void Reset() override
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
events.Reset();
summons.DespawnAll();
SpawnCrystals();
instance->SetBossState(DATA_SELIN_FIREHEART, NOT_STARTED);
CrystalGUID.Clear();
me->SetPower(POWER_MANA, 0);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetBossState(DATA_SELIN_FIREHEART, IN_PROGRESS);
events.ScheduleEvent(EVENT_SPELL_DRAIN_LIFE, 2500, 1);
case EVENT_SPELL_DRAIN_LIFE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, DUNGEON_MODE(SPELL_DRAIN_LIFE_N, SPELL_DRAIN_LIFE_H), 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);
events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, 14000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 7500, 1);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_SELIN_FIREHEART, DONE); // Encounter complete!
summons.DespawnAll();
}
void SelectNearestCrystal()
{
if (summons.empty())
return;
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)
{
Talk(SAY_ENERGY);
float x, y, z;
crystal->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
CrystalGUID = crystal->GetGUID();
me->GetMotionMaster()->MovePoint(2, x, y, z);
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == 2)
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))
{
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);
}
else
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 0);
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;
}
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, DUNGEON_MODE(SPELL_DRAIN_LIFE_N, SPELL_DRAIN_LIFE_H), 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();
}
};
DoMeleeAttackIfReady();
}
};
void AddSC_boss_selin_fireheart()
{
new boss_selin_fireheart();
RegisterMagistersTerraceCreatureAI(boss_selin_fireheart);
}

View File

@@ -58,133 +58,122 @@ enum Misc
EVENT_HEALTH_CHECK = 3,
};
class boss_vexallus : public CreatureScript
struct boss_vexallus : public ScriptedAI
{
public:
boss_vexallus() : CreatureScript("boss_vexallus") { }
CreatureAI* GetAI(Creature* creature) const override
boss_vexallus(Creature* creature) : ScriptedAI(creature), summons(me)
{
return GetMagistersTerraceAI<boss_vexallusAI>(creature);
};
instance = creature->GetInstanceScript();
}
struct boss_vexallusAI : public ScriptedAI
InstanceScript* instance;
EventMap events;
SummonList summons;
uint8 IntervalHealthAmount;
bool Enraged;
void Reset() override
{
boss_vexallusAI(Creature* creature) : ScriptedAI(creature), summons(me)
summons.DespawnAll();
IntervalHealthAmount = 1;
instance->SetBossState(DATA_VEXALLUS, NOT_STARTED);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_FEEDBACK);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
summons.DespawnAll();
instance->SetBossState(DATA_VEXALLUS, DONE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_FEEDBACK);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetBossState(DATA_VEXALLUS, IN_PROGRESS);
events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 8000);
events.ScheduleEvent(EVENT_SPELL_ARCANE_SHOCK, 5000);
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
}
void JustSummoned(Creature* summon) override
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
instance = creature->GetInstanceScript();
summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
summon->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false);
}
summons.Summon(summon);
}
InstanceScript* instance;
EventMap events;
SummonList summons;
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
summons.Despawn(summon);
summon->DespawnOrUnsummon(1);
if (killer)
killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID());
}
uint8 IntervalHealthAmount;
bool Enraged;
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
void Reset() override
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
summons.DespawnAll();
IntervalHealthAmount = 1;
case EVENT_HEALTH_CHECK:
//used for check, when Vexallus cast adds 85%, 70%, 55%, 40%
if (!HealthAbovePct(100 - INTERVAL_MODIFIER * IntervalHealthAmount))
{
if (IntervalHealthAmount++ == INTERVAL_SWITCH)
{
events.Reset();
me->CastSpell(me, SPELL_OVERLOAD, true);
return;
}
instance->SetBossState(DATA_VEXALLUS, NOT_STARTED);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_FEEDBACK);
}
Talk(SAY_ENERGY);
Talk(EMOTE_DISCHARGE_ENERGY);
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
summons.DespawnAll();
instance->SetBossState(DATA_VEXALLUS, DONE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_FEEDBACK);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetBossState(DATA_VEXALLUS, IN_PROGRESS);
events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 8000);
events.ScheduleEvent(EVENT_SPELL_ARCANE_SHOCK, 5000);
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
}
void JustSummoned(Creature* summon) override
{
if (IsHeroic())
{
me->CastSpell(me, SPELL_SUMMON_PURE_ENERGY_H1, false);
me->CastSpell(me, SPELL_SUMMON_PURE_ENERGY_H2, false);
}
else
me->CastSpell(me, SPELL_SUMMON_PURE_ENERGY_N, false);
}
events.ScheduleEvent(EVENT_HEALTH_CHECK, 0);
break;
case EVENT_SPELL_CHAIN_LIGHTNING:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
summon->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false);
}
summons.Summon(summon);
me->CastSpell(target, DUNGEON_MODE(SPELL_CHAIN_LIGHTNING_N, SPELL_CHAIN_LIGHTNING_H), false);
events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 8000);
break;
case EVENT_SPELL_ARCANE_SHOCK:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 20.0f))
me->CastSpell(target, DUNGEON_MODE(SPELL_ARCANE_SHOCK_N, SPELL_ARCANE_SHOCK_H), false);
events.ScheduleEvent(EVENT_SPELL_ARCANE_SHOCK, 8000);
break;
}
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
summons.Despawn(summon);
summon->DespawnOrUnsummon(1);
if (killer)
killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID());
}
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:
//used for check, when Vexallus cast adds 85%, 70%, 55%, 40%
if (!HealthAbovePct(100 - INTERVAL_MODIFIER * IntervalHealthAmount))
{
if (IntervalHealthAmount++ == INTERVAL_SWITCH)
{
events.Reset();
me->CastSpell(me, SPELL_OVERLOAD, true);
return;
}
Talk(SAY_ENERGY);
Talk(EMOTE_DISCHARGE_ENERGY);
if (IsHeroic())
{
me->CastSpell(me, SPELL_SUMMON_PURE_ENERGY_H1, false);
me->CastSpell(me, SPELL_SUMMON_PURE_ENERGY_H2, false);
}
else
me->CastSpell(me, SPELL_SUMMON_PURE_ENERGY_N, false);
}
events.ScheduleEvent(EVENT_HEALTH_CHECK, 0);
break;
case EVENT_SPELL_CHAIN_LIGHTNING:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, DUNGEON_MODE(SPELL_CHAIN_LIGHTNING_N, SPELL_CHAIN_LIGHTNING_H), false);
events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 8000);
break;
case EVENT_SPELL_ARCANE_SHOCK:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 20.0f))
me->CastSpell(target, DUNGEON_MODE(SPELL_ARCANE_SHOCK_N, SPELL_ARCANE_SHOCK_H), false);
events.ScheduleEvent(EVENT_SPELL_ARCANE_SHOCK, 8000);
break;
}
DoMeleeAttackIfReady();
}
};
DoMeleeAttackIfReady();
}
};
void AddSC_boss_vexallus()
{
new boss_vexallus();
RegisterMagistersTerraceCreatureAI(boss_vexallus);
}