diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp index f85e4301b..b81b7cd8b 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp @@ -15,44 +15,38 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Boss_Terestian_Illhoof -SD%Complete: 95 -SDComment: Complete! Needs adjustments to use spell though. -SDCategory: Karazhan -EndScriptData */ - #include "PassiveAI.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellInfo.h" #include "karazhan.h" -enum TerestianIllhoof +enum Text { - SAY_SLAY = 1, - SAY_DEATH = 2, - SAY_AGGRO = 3, - SAY_SACRIFICE = 4, - SAY_SUMMON = 5 + SAY_SLAY = 0, + SAY_DEATH = 1, + SAY_AGGRO = 2, + SAY_SACRIFICE = 3, + SAY_SUMMON = 4 }; enum Spells { - SPELL_SUMMON_DEMONCHAINS = 30120, // Summons demonic chains that maintain the ritual of sacrifice. - SPELL_DEMON_CHAINS = 30206, // Instant - Visual Effect - SPELL_ENRAGE = 23537, // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min. - SPELL_SHADOW_BOLT = 30055, // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. - SPELL_SACRIFICE = 30115, // Teleports and adds the debuff - SPELL_BERSERK = 32965, // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. - SPELL_SUMMON_FIENDISIMP = 30184, // Summons a Fiendish Imp. - SPELL_SUMMON_IMP = 30066, // Summons Kil'rek + SPELL_SUMMON_DEMONCHAINS = 30120, + SPELL_DEMON_CHAINS = 30206, + SPELL_ENRAGE = 23537, + SPELL_SHADOW_BOLT = 30055, + SPELL_SACRIFICE = 30115, + SPELL_BERSERK = 32965, + SPELL_SUMMON_FIENDISIMP = 30184, + SPELL_SUMMON_IMP = 30066, - SPELL_FIENDISH_PORTAL = 30171, // Opens portal and summons Fiendish Portal, 2 sec cast - SPELL_FIENDISH_PORTAL_1 = 30179, // Opens portal and summons Fiendish Portal, instant cast + SPELL_FIENDISH_PORTAL = 30171, + SPELL_FIENDISH_PORTAL_1 = 30179, - SPELL_FIREBOLT = 30050, // Blasts a target for 150 Fire damage. - SPELL_BROKEN_PACT = 30065, // All damage taken increased by 25%. - SPELL_AMPLIFY_FLAMES = 30053, // Increases the Fire damage taken by an enemy by 500 for 25 sec. + SPELL_FIREBOLT = 30050, + SPELL_BROKEN_PACT = 30065, + SPELL_AMPLIFY_FLAMES = 30053 }; enum Creatures @@ -62,390 +56,306 @@ enum Creatures NPC_PORTAL = 17265 }; -class npc_kilrek : public CreatureScript +struct npc_kilrek : public ScriptedAI { -public: - npc_kilrek() : CreatureScript("npc_kilrek") { } - - CreatureAI* GetAI(Creature* creature) const override + npc_kilrek(Creature* creature) : ScriptedAI(creature) { - return GetKarazhanAI(creature); + instance = creature->GetInstanceScript(); } - struct npc_kilrekAI : public ScriptedAI + void Reset() override { - npc_kilrekAI(Creature* creature) : ScriptedAI(creature) + _scheduler.CancelAll(); + TerestianGUID.Clear(); + } + + void JustEngagedWith(Unit* /*who*/) override + { + _scheduler.Schedule(2s, [this](TaskContext context) { - instance = creature->GetInstanceScript(); - } + me->InterruptNonMeleeSpells(false); + DoCastVictim(SPELL_AMPLIFY_FLAMES); + context.Repeat(10s, 20s); + }); + } - InstanceScript* instance; - - ObjectGuid TerestianGUID; - - uint32 AmplifyTimer; - - void Reset() override + void JustDied(Unit* /*killer*/) override + { + ObjectGuid TerestianGuid = instance->GetGuidData(DATA_TERESTIAN); + if (TerestianGuid) { - TerestianGUID.Clear(); - AmplifyTimer = 2000; - } - - void JustEngagedWith(Unit* /*who*/) override - { - } - - void JustDied(Unit* /*killer*/) override - { - ObjectGuid TerestianGuid = instance->GetGuidData(DATA_TERESTIAN); - if (TerestianGuid) + Unit* Terestian = ObjectAccessor::GetUnit(*me, TerestianGuid); + if (Terestian && Terestian->IsAlive()) { - Unit* Terestian = ObjectAccessor::GetUnit(*me, TerestianGuid); - if (Terestian && Terestian->IsAlive()) - DoCast(Terestian, SPELL_BROKEN_PACT, true); + DoCast(Terestian, SPELL_BROKEN_PACT, true); } } - - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (AmplifyTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCastVictim(SPELL_AMPLIFY_FLAMES); - - AmplifyTimer = urand(10000, 20000); - } - else - AmplifyTimer -= diff; - - DoMeleeAttackIfReady(); - } - }; -}; - -class npc_demon_chain : public CreatureScript -{ -public: - npc_demon_chain() : CreatureScript("npc_demon_chain") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetKarazhanAI(creature); + me->DespawnOrUnsummon(15000); } - struct npc_demon_chainAI : public ScriptedAI + void UpdateAI(uint32 diff) override { - npc_demon_chainAI(Creature* creature) : ScriptedAI(creature) { } + if (!UpdateVictim()) + return; - ObjectGuid SacrificeGUID; + _scheduler.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void Reset() override + DoMeleeAttackIfReady(); + } + +private: + TaskScheduler _scheduler; + InstanceScript* instance; + ObjectGuid TerestianGUID; +}; + +struct npc_demon_chain : public ScriptedAI +{ + npc_demon_chain(Creature* creature) : ScriptedAI(creature) { } + + void Reset() override + { + sacrificeGUID.Clear(); + } + + void IsSummonedBy(WorldObject* summoner) override + { + sacrificeGUID = summoner->GetGUID(); + DoCastSelf(SPELL_DEMON_CHAINS, true); + } + + void JustEngagedWith(Unit* /*who*/) override { } + void AttackStart(Unit* /*who*/) override { } + void MoveInLineOfSight(Unit* /*who*/) override { } + + void JustDied(Unit* /*killer*/) override + { + if (sacrificeGUID) { - SacrificeGUID.Clear(); - } - - void JustEngagedWith(Unit* /*who*/) override { } - void AttackStart(Unit* /*who*/) override { } - void MoveInLineOfSight(Unit* /*who*/) override { } - - void JustDied(Unit* /*killer*/) override - { - if (SacrificeGUID) + Unit* Sacrifice = ObjectAccessor::GetUnit(*me, sacrificeGUID); + if (Sacrifice) { - Unit* Sacrifice = ObjectAccessor::GetUnit(*me, SacrificeGUID); - if (Sacrifice) - Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); + Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); } } - }; -}; - -class npc_fiendish_portal : public CreatureScript -{ -public: - npc_fiendish_portal() : CreatureScript("npc_fiendish_portal") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetKarazhanAI(creature); } - struct npc_fiendish_portalAI : public PassiveAI - { - npc_fiendish_portalAI(Creature* creature) : PassiveAI(creature), summons(me) { } - - SummonList summons; - - void Reset() override - { - DespawnAllImp(); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - DoZoneInCombat(summon); - } - - void DespawnAllImp() - { - summons.DespawnAll(); - } - }; +private: + ObjectGuid sacrificeGUID; }; -class npc_fiendish_imp : public CreatureScript +struct npc_fiendish_portal : public PassiveAI { -public: - npc_fiendish_imp() : CreatureScript("npc_fiendish_imp") { } + npc_fiendish_portal(Creature* creature) : PassiveAI(creature), summons(me) {} - CreatureAI* GetAI(Creature* creature) const override + void Reset() override { - return GetKarazhanAI(creature); + DespawnAllImp(); } - struct npc_fiendish_impAI : public ScriptedAI + void JustSummoned(Creature* summon) override { - npc_fiendish_impAI(Creature* creature) : ScriptedAI(creature) { } + summons.Summon(summon); + DoZoneInCombat(summon); + } - uint32 FireboltTimer; + void DespawnAllImp() + { + summons.DespawnAll(); + } - void Reset() override +private: + SummonList summons; +}; + +struct npc_fiendish_imp : public ScriptedAI +{ + npc_fiendish_imp(Creature* creature) : ScriptedAI(creature) {} + + void Reset() override + { + _scheduler.CancelAll(); + } + + void JustEngagedWith(Unit* /*who*/) override + { + _scheduler.Schedule(2s, [this](TaskContext context) { - FireboltTimer = 2000; - } + DoCastVictim(SPELL_FIREBOLT); + context.Repeat(2200ms); + }); + } - void JustEngagedWith(Unit* /*who*/) override { } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void UpdateAI(uint32 diff) override + _scheduler.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + DoMeleeAttackIfReady(); + } + +private: + TaskScheduler _scheduler; +}; + +struct boss_terestian_illhoof : public BossAI +{ + boss_terestian_illhoof(Creature* creature) : BossAI(creature, DATA_TERESTIAN) + { + scheduler.SetValidator([this] { - //Return since we have no target - if (!UpdateVictim()) - return; + return !me->HasUnitState(UNIT_STATE_CASTING); + }); + } - if (FireboltTimer <= diff) + void Reset() override + { + _Reset(); + SummonKilrek(); + portalsCount = 0; + berserk = false; + for (uint8 i = 0; i < 2; ++i) + { + if (portalGUID[i]) { - DoCastVictim(SPELL_FIREBOLT); - FireboltTimer = 2200; - } - else - FireboltTimer -= diff; - - DoMeleeAttackIfReady(); - } - }; -}; - -class boss_terestian_illhoof : public CreatureScript -{ -public: - boss_terestian_illhoof() : CreatureScript("boss_terestian_illhoof") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetKarazhanAI(creature); - } - - struct boss_terestianAI : public ScriptedAI - { - boss_terestianAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; - - ObjectGuid PortalGUID[2]; - uint8 PortalsCount; - - uint32 SacrificeTimer; - uint32 ShadowboltTimer; - uint32 SummonTimer; - uint32 BerserkTimer; - uint32 SummonKilrekTimer; - - bool SummonedPortals; - bool Berserk; - - void Reset() override - { - for (uint8 i = 0; i < 2; ++i) - { - if (PortalGUID[i]) + if (Creature* pPortal = ObjectAccessor::GetCreature(*me, portalGUID[i])) { - if (Creature* pPortal = ObjectAccessor::GetCreature(*me, PortalGUID[i])) - { - CAST_AI(npc_fiendish_portal::npc_fiendish_portalAI, pPortal->AI())->DespawnAllImp(); - pPortal->DespawnOrUnsummon(); - } - - PortalGUID[i].Clear(); + pPortal->AI()->Reset(); + pPortal->DespawnOrUnsummon(); } + portalGUID[i].Clear(); } - - PortalsCount = 0; - SacrificeTimer = 30000; - ShadowboltTimer = 5000; - SummonTimer = 10000; - BerserkTimer = 600000; - SummonKilrekTimer = 0; - - SummonedPortals = false; - Berserk = false; - - instance->SetData(DATA_TERESTIAN, NOT_STARTED); - - me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); - - if (Minion* Kilrek = me->GetFirstMinion()) - { - if (!Kilrek->IsAlive()) - { - Kilrek->UnSummon(); - DoCast(me, SPELL_SUMMON_IMP, true); - } - } - else - DoCast(me, SPELL_SUMMON_IMP, true); } + } - void JustEngagedWith(Unit* /*who*/) override + void SummonKilrek() + { + me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); + DoCastSelf(SPELL_SUMMON_IMP); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_BROKEN_PACT) { - Talk(SAY_AGGRO); - DoZoneInCombat(); + scheduler.Schedule(45s, [this](TaskContext /*context*/) { + SummonKilrek(); + }); } + } - void JustSummoned(Creature* summoned) override + void JustEngagedWith(Unit* /*who*/) override + { + Talk(SAY_AGGRO); + DoZoneInCombat(); + scheduler.Schedule(30s, [this](TaskContext context) { - if (summoned->GetEntry() == NPC_PORTAL) + if (Unit * target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, false)) { - PortalGUID[PortalsCount] = summoned->GetGUID(); - ++PortalsCount; - - if (summoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) + DoCast(target, SPELL_SACRIFICE, true); + target->CastSpell(target, SPELL_SUMMON_DEMONCHAINS, true); + Talk(SAY_SACRIFICE); + context.Repeat(30s); + } + }).Schedule(5s, [this](TaskContext context) + { + DoCastVictim(SPELL_SHADOW_BOLT); + context.Repeat(10s); + }).Schedule(10s, [this](TaskContext context) + { + if (!portalGUID[0]) + { + DoCastVictim(SPELL_FIENDISH_PORTAL); + } + if (!portalGUID[1]) + { + DoCastVictim(SPELL_FIENDISH_PORTAL_1); + } + if (portalGUID[0] && portalGUID[1]) + { + if (Creature* pPortal = ObjectAccessor::GetCreature(*me, portalGUID[urand(0, 1)])) { - Talk(SAY_SUMMON); - SummonedPortals = true; + pPortal->CastSpell(me->GetVictim(), SPELL_SUMMON_FIENDISIMP); } + context.Repeat(5s); + } + }).Schedule(10min, [this](TaskContext /*context*/) + { + if (!berserk) + { + DoCastSelf(SPELL_BERSERK); + berserk = true; + } + }); + } + + void JustSummoned(Creature* summoned) override + { + if (summoned->GetEntry() == NPC_PORTAL) + { + portalGUID[portalsCount] = summoned->GetGUID(); + ++portalsCount; + if (summoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) + { + Talk(SAY_SUMMON); } } + } - void KilledUnit(Unit* /*victim*/) override + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) { Talk(SAY_SLAY); } + } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + for (uint8 i = 0; i < 2; ++i) { - for (uint8 i = 0; i < 2; ++i) + if (portalGUID[i]) { - if (PortalGUID[i]) + if (Creature* pPortal = ObjectAccessor::GetCreature((*me), portalGUID[i])) { - if (Creature* pPortal = ObjectAccessor::GetCreature((*me), PortalGUID[i])) - pPortal->DespawnOrUnsummon(); - - PortalGUID[i].Clear(); + pPortal->AI()->Reset(); + pPortal->DespawnOrUnsummon(); } + portalGUID[i].Clear(); } - - Talk(SAY_DEATH); - instance->SetData(DATA_TERESTIAN, DONE); } + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - if (Minion* Kilrek = me->GetFirstMinion()) - { - if (!Kilrek->IsAlive()) - { - Kilrek->UnSummon(); - SummonKilrekTimer = 45000; - } - } + scheduler.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (SummonKilrekTimer <= diff) - { - DoCast(me, SPELL_SUMMON_IMP, true); - me->RemoveAura(SPELL_BROKEN_PACT); - } - else - SummonKilrekTimer -= diff; + DoMeleeAttackIfReady(); + } - if (SacrificeTimer <= diff) - { - Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true); - if (target && target->IsAlive()) - { - DoCast(target, SPELL_SACRIFICE, true); - DoCast(target, SPELL_SUMMON_DEMONCHAINS, true); - - if (Creature* Chains = me->FindNearestCreature(NPC_DEMONCHAINS, 5000)) - { - CAST_AI(npc_demon_chain::npc_demon_chainAI, Chains->AI())->SacrificeGUID = target->GetGUID(); - Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true); - - Talk(SAY_SACRIFICE); - SacrificeTimer = 30000; - } - } - } - else - SacrificeTimer -= diff; - - if (ShadowboltTimer <= diff) - { - DoCast(SelectTarget(SelectTargetMethod::MaxThreat, 0), SPELL_SHADOW_BOLT); - ShadowboltTimer = 10000; - } - else - ShadowboltTimer -= diff; - - if (SummonTimer <= diff) - { - if (!PortalGUID[0]) - DoCastVictim(SPELL_FIENDISH_PORTAL, false); - - if (!PortalGUID[1]) - DoCastVictim(SPELL_FIENDISH_PORTAL_1, false); - - if (PortalGUID[0] && PortalGUID[1]) - { - if (Creature* pPortal = ObjectAccessor::GetCreature(*me, PortalGUID[urand(0, 1)])) - pPortal->CastSpell(me->GetVictim(), SPELL_SUMMON_FIENDISIMP, false); - SummonTimer = 5000; - } - } - else - SummonTimer -= diff; - - if (!Berserk) - { - if (BerserkTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - Berserk = true; - } - else - BerserkTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - }; +private: + bool berserk; + ObjectGuid portalGUID[2]; + uint8 portalsCount; }; void AddSC_boss_terestian_illhoof() { - new boss_terestian_illhoof(); - new npc_fiendish_imp(); - new npc_fiendish_portal(); - new npc_kilrek(); - new npc_demon_chain(); + RegisterKarazhanCreatureAI(boss_terestian_illhoof); + RegisterKarazhanCreatureAI(npc_fiendish_imp); + RegisterKarazhanCreatureAI(npc_fiendish_portal); + RegisterKarazhanCreatureAI(npc_kilrek); + RegisterKarazhanCreatureAI(npc_demon_chain); }