diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp index 6b2cef92b..a47d16bda 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp @@ -70,29 +70,20 @@ enum Spells enum Misc { ACTION_SISTER_DIED = 1, - - EVENT_SPELL_SHADOW_BLADES = 1, - EVENT_SPELL_SHADOW_NOVA = 2, - EVENT_SPELL_CONFOUNDING_BLOW = 3, - EVENT_SHADOW_IMAGE = 4, - EVENT_SPELL_ENRAGE = 5, - EVENT_SPELL_CONFLAGRATION = 6, - EVENT_SPELL_BLAZE = 7, - EVENT_SPELL_PYROGENICS = 8, - EVENT_SPELL_FLAME_SEAR = 9 + GROUP_SPECIAL_ABILITY = 1 }; struct boss_sacrolash : public BossAI { - boss_sacrolash(Creature* creature) : BossAI(creature, DATA_EREDAR_TWINS) {} + boss_sacrolash(Creature* creature) : BossAI(creature, DATA_EREDAR_TWINS), _isSisterDead(false) {} - bool sisterDied; void Reset() override { - me->CastSpell(me, SPELL_SHADOWFORM, true); - sisterDied = false; + DoCastSelf(SPELL_SHADOWFORM, true); + _isSisterDead = false; BossAI::Reset(); me->SetLootMode(0); + me->m_Events.KillAllEvents(false); } void DoAction(int32 param) override @@ -100,20 +91,24 @@ struct boss_sacrolash : public BossAI if (param == ACTION_SISTER_DIED) { me->ResetLootMode(); - sisterDied = true; + _isSisterDead = true; Talk(YELL_SISTER_ALYTHESS_DEAD); me->CastSpell(me, SPELL_EMPOWER, true); - uint32 timer = events.GetNextEventTime(EVENT_SPELL_SHADOW_NOVA); - events.CancelEvent(EVENT_SPELL_SHADOW_NOVA); - events.ScheduleEvent(EVENT_SPELL_CONFLAGRATION, timer - events.GetTimer()); + scheduler.CancelGroup(GROUP_SPECIAL_ABILITY); + ScheduleTimedEvent(20s, [&] { + Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); + if (!target) + target = me->GetVictim(); + me->CastSpell(target, SPELL_CONFLAGRATION, false); + }, 30s, 35s); } } void EnterEvadeMode(EvadeReason why) override { BossAI::EnterEvadeMode(why); - if (Creature* alythess = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GRAND_WARLOCK_ALYTHESS))) + if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS)) { if (!alythess->IsAlive()) alythess->Respawn(true); @@ -125,15 +120,36 @@ struct boss_sacrolash : public BossAI void JustEngagedWith(Unit* who) override { BossAI::JustEngagedWith(who); - if (Creature* alythess = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GRAND_WARLOCK_ALYTHESS))) + if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS)) if (alythess->IsAlive() && !alythess->IsInCombat()) alythess->AI()->AttackStart(who); - events.ScheduleEvent(EVENT_SPELL_SHADOW_BLADES, 10000); - events.ScheduleEvent(EVENT_SPELL_SHADOW_NOVA, 36000); - events.ScheduleEvent(EVENT_SPELL_CONFOUNDING_BLOW, 25000); - events.ScheduleEvent(EVENT_SHADOW_IMAGE, 20000); - events.ScheduleEvent(EVENT_SPELL_ENRAGE, 360000); + me->m_Events.AddEventAtOffset([&] { + Talk(YELL_BERSERK); + DoCastSelf(SPELL_ENRAGE, true); + }, 6min); + + ScheduleTimedEvent(10s, [&] { + DoCastSelf(SPELL_SHADOW_BLADES); + }, 10s); + + ScheduleTimedEvent(25s, [&] { + DoCastVictim(SPELL_CONFOUNDING_BLOW); + }, 20s, 25s); + + ScheduleTimedEvent(20s, [&] { + me->SummonCreature(NPC_SHADOW_IMAGE, me->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 12000); + }, 6s); + + scheduler.Schedule(36s, GROUP_SPECIAL_ABILITY, [this](TaskContext context) { + Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); + if (!target) + target = me->GetVictim(); + Talk(EMOTE_SHADOW_NOVA, target); + Talk(YELL_SHADOW_NOVA); + DoCast(target, SPELL_SHADOW_NOVA); + context.Repeat(30s, 35s); + }); } void KilledUnit(Unit* victim) override @@ -144,15 +160,14 @@ struct boss_sacrolash : public BossAI void JustDied(Unit* /*killer*/) override { - events.Reset(); summons.DespawnAll(); - if (sisterDied) + if (_isSisterDead) { Talk(YELL_SAC_DEAD); instance->SetBossState(DATA_EREDAR_TWINS, DONE); } - else if (Creature* alythess = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GRAND_WARLOCK_ALYTHESS))) + else if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS)) alythess->AI()->DoAction(ACTION_SISTER_DIED); } @@ -166,70 +181,21 @@ struct boss_sacrolash : public BossAI } } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_ENRAGE: - Talk(YELL_ENRAGE); - me->CastSpell(me, SPELL_ENRAGE, true); - break; - case EVENT_SPELL_CONFOUNDING_BLOW: - me->CastSpell(me->GetVictim(), SPELL_CONFOUNDING_BLOW, false); - events.ScheduleEvent(EVENT_SPELL_CONFOUNDING_BLOW, urand(20000, 25000)); - break; - case EVENT_SPELL_SHADOW_BLADES: - me->CastSpell(me, SPELL_SHADOW_BLADES, false); - events.ScheduleEvent(EVENT_SPELL_SHADOW_BLADES, 10000); - break; - case EVENT_SPELL_SHADOW_NOVA: - { - Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); - if (!target) - target = me->GetVictim(); - Talk(EMOTE_SHADOW_NOVA, target); - Talk(YELL_SHADOW_NOVA); - me->CastSpell(target, SPELL_SHADOW_NOVA, false); - events.ScheduleEvent(EVENT_SPELL_SHADOW_NOVA, urand(30000, 35000)); - break; - } - case EVENT_SHADOW_IMAGE: - me->SummonCreature(NPC_SHADOW_IMAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 12000); - events.ScheduleEvent(EVENT_SHADOW_IMAGE, 6000); - break; - case EVENT_SPELL_CONFLAGRATION: - { - Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); - if (!target) - target = me->GetVictim(); - me->CastSpell(target, SPELL_CONFLAGRATION, false); - events.ScheduleEvent(EVENT_SPELL_CONFLAGRATION, urand(30000, 35000)); - break; - } - } - - DoMeleeAttackIfReady(); - } + private: + bool _isSisterDead; }; struct boss_alythess : public BossAI { - boss_alythess(Creature* creature) : BossAI(creature, DATA_EREDAR_TWINS) { } + boss_alythess(Creature* creature) : BossAI(creature, DATA_EREDAR_TWINS), _isSisterDead(false) { } - bool sisterDied; void Reset() override { - me->CastSpell(me, SPELL_FIREFORM, true); - sisterDied = false; + DoCastSelf(SPELL_FIREFORM, true); + _isSisterDead = false; BossAI::Reset(); me->SetLootMode(0); + me->m_Events.KillAllEvents(false); } void DoAction(int32 param) override @@ -237,40 +203,65 @@ struct boss_alythess : public BossAI if (param == ACTION_SISTER_DIED) { me->ResetLootMode(); - sisterDied = true; + _isSisterDead = true; Talk(YELL_SISTER_SACROLASH_DEAD); me->CastSpell(me, SPELL_EMPOWER, true); - uint32 timer = events.GetNextEventTime(EVENT_SPELL_CONFLAGRATION); - events.CancelEvent(EVENT_SPELL_CONFLAGRATION); - events.ScheduleEvent(EVENT_SPELL_SHADOW_NOVA, timer - events.GetTimer()); + scheduler.CancelGroup(GROUP_SPECIAL_ABILITY); + ScheduleTimedEvent(20s, [&] { + Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); + if (!target) + target = me->GetVictim(); + DoCast(target, SPELL_SHADOW_NOVA); + }, 30s, 35s); } } void EnterEvadeMode(EvadeReason why) override { BossAI::EnterEvadeMode(why); - if (Creature* scorlash = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_LADY_SACROLASH))) + if (Creature* sacrolash = instance->GetCreature(DATA_SACROLASH)) { - if (!scorlash->IsAlive()) - scorlash->Respawn(true); - else if (!scorlash->IsInEvadeMode()) - scorlash->AI()->EnterEvadeMode(why); + if (!sacrolash->IsAlive()) + sacrolash->Respawn(true); + else if (!sacrolash->IsInEvadeMode()) + sacrolash->AI()->EnterEvadeMode(why); } } void JustEngagedWith(Unit* who) override { BossAI::JustEngagedWith(who); - if (Creature* scorlash = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_LADY_SACROLASH))) - if (scorlash->IsAlive() && !scorlash->IsInCombat()) - scorlash->AI()->AttackStart(who); + if (Creature* sacrolash = instance->GetCreature(DATA_SACROLASH)) + if (sacrolash->IsAlive() && !sacrolash->IsInCombat()) + sacrolash->AI()->AttackStart(who); - events.ScheduleEvent(EVENT_SPELL_BLAZE, 100); - events.ScheduleEvent(EVENT_SPELL_PYROGENICS, 15000); - events.ScheduleEvent(EVENT_SPELL_FLAME_SEAR, 20000); - events.ScheduleEvent(EVENT_SPELL_CONFLAGRATION, 30000); - events.ScheduleEvent(EVENT_SPELL_ENRAGE, 360000); + me->m_Events.AddEventAtOffset([&] { + Talk(YELL_BERSERK); + DoCastSelf(SPELL_ENRAGE, true); + }, 6min); + + ScheduleTimedEvent(1s, [&] { + DoCastVictim(SPELL_BLAZE); + }, 3800ms); + + ScheduleTimedEvent(15s, [&] { + DoCastSelf(SPELL_PYROGENICS); + }, 15s); + + ScheduleTimedEvent(20s, [&] { + me->CastCustomSpell(SPELL_FLAME_SEAR, SPELLVALUE_MAX_TARGETS, 5, me, TRIGGERED_NONE); + }, 15s); + + scheduler.Schedule(20s, GROUP_SPECIAL_ABILITY, [this](TaskContext context) { + Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); + if (!target) + target = me->GetVictim(); + Talk(EMOTE_CONFLAGRATION, target); + Talk(YELL_CANFLAGRATION); + DoCast(target, SPELL_CONFLAGRATION); + context.Repeat(30s, 35s); + }); } void KilledUnit(Unit* victim) override @@ -281,111 +272,46 @@ struct boss_alythess : public BossAI void JustDied(Unit* /*killer*/) override { - events.Reset(); summons.DespawnAll(); - if (sisterDied) + if (_isSisterDead) { Talk(YELL_SAC_DEAD); instance->SetBossState(DATA_EREDAR_TWINS, DONE); } - else if (Creature* scorlash = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_LADY_SACROLASH))) - scorlash->AI()->DoAction(ACTION_SISTER_DIED); + else if (Creature* sacrolash = instance->GetCreature(DATA_SACROLASH)) + sacrolash->AI()->DoAction(ACTION_SISTER_DIED); } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_ENRAGE: - Talk(YELL_BERSERK); - me->CastSpell(me, SPELL_ENRAGE, true); - break; - case EVENT_SPELL_PYROGENICS: - me->CastSpell(me, SPELL_PYROGENICS, false); - events.ScheduleEvent(EVENT_SPELL_PYROGENICS, 15000); - break; - case EVENT_SPELL_FLAME_SEAR: - me->CastCustomSpell(SPELL_FLAME_SEAR, SPELLVALUE_MAX_TARGETS, 5, me, TRIGGERED_NONE); - events.ScheduleEvent(EVENT_SPELL_FLAME_SEAR, 15000); - break; - case EVENT_SPELL_BLAZE: - me->CastSpell(me->GetVictim(), SPELL_BLAZE, false); - events.ScheduleEvent(EVENT_SPELL_BLAZE, 3800); - break; - case EVENT_SPELL_SHADOW_NOVA: - { - Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); - if (!target) - target = me->GetVictim(); - me->CastSpell(target, SPELL_SHADOW_NOVA, false); - events.ScheduleEvent(EVENT_SPELL_SHADOW_NOVA, urand(30000, 35000)); - break; - } - case EVENT_SPELL_CONFLAGRATION: - { - Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); - if (!target) - target = me->GetVictim(); - Talk(EMOTE_CONFLAGRATION, target); - Talk(YELL_CANFLAGRATION); - me->CastSpell(target, SPELL_CONFLAGRATION, false); - events.ScheduleEvent(EVENT_SPELL_CONFLAGRATION, urand(30000, 35000)); - break; - } - } - - DoMeleeAttackIfReady(); - } + private: + bool _isSisterDead; }; -class spell_eredar_twins_apply_dark_touched : public SpellScript +class spell_eredar_twins_apply_touch : public SpellScript { - PrepareSpellScript(spell_eredar_twins_apply_dark_touched); + PrepareSpellScript(spell_eredar_twins_apply_touch); + +public: + spell_eredar_twins_apply_touch(uint32 touchSpell) : SpellScript(), _touchSpell(touchSpell) { } bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo({ SPELL_DARK_TOUCHED }); + return ValidateSpellInfo({ _touchSpell }); } void HandleApplyTouch() { if (Player* target = GetHitPlayer()) - target->CastSpell(target, SPELL_DARK_TOUCHED, true); + target->CastSpell(target, _touchSpell, true); } void Register() override { - AfterHit += SpellHitFn(spell_eredar_twins_apply_dark_touched::HandleApplyTouch); - } -}; - -class spell_eredar_twins_apply_flame_touched : public SpellScript -{ - PrepareSpellScript(spell_eredar_twins_apply_flame_touched); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({ SPELL_FLAME_TOUCHED }); + AfterHit += SpellHitFn(spell_eredar_twins_apply_touch::HandleApplyTouch); } - void HandleApplyTouch() - { - if (Player* target = GetHitPlayer()) - target->CastSpell(target, SPELL_FLAME_TOUCHED, true); - } - - void Register() override - { - AfterHit += SpellHitFn(spell_eredar_twins_apply_flame_touched::HandleApplyTouch); - } +private: + uint32 _touchSpell; }; class spell_eredar_twins_handle_touch : public SpellScript @@ -474,8 +400,8 @@ void AddSC_boss_eredar_twins() { RegisterSunwellPlateauCreatureAI(boss_sacrolash); RegisterSunwellPlateauCreatureAI(boss_alythess); - RegisterSpellScript(spell_eredar_twins_apply_dark_touched); - RegisterSpellScript(spell_eredar_twins_apply_flame_touched); + RegisterSpellScriptWithArgs(spell_eredar_twins_apply_touch, "spell_eredar_twins_apply_dark_touched", SPELL_DARK_TOUCHED); + RegisterSpellScriptWithArgs(spell_eredar_twins_apply_touch, "spell_eredar_twins_apply_flame_touched", SPELL_FLAME_TOUCHED); RegisterSpellScript(spell_eredar_twins_handle_touch); RegisterSpellScript(spell_eredar_twins_blaze); new at_sunwell_eredar_twins();