From 1184b3a6930fc25c2fda6f725c49c28534aae0ac Mon Sep 17 00:00:00 2001
From: Eddy Vega <61223313+Si1ker@users.noreply.github.com>
Date: Sat, 15 Jul 2023 14:13:38 -0600
Subject: [PATCH] fix(Scripts/Karazhan): Rewrite Terestian Illhoof (#16755)
* init
* m
* .
---
.../Karazhan/boss_terestian_illhoof.cpp | 592 ++++++++----------
1 file changed, 251 insertions(+), 341 deletions(-)
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);
}