fix(Scripts/Karazhan): Rewrite Terestian Illhoof (#16755)

* init

* m

* .
This commit is contained in:
Eddy Vega
2023-07-15 14:13:38 -06:00
committed by GitHub
parent 601d036295
commit 1184b3a693
@@ -15,44 +15,38 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* ScriptData
SDName: Boss_Terestian_Illhoof
SD%Complete: 95
SDComment: Complete! Needs adjustments to use spell though.
SDCategory: Karazhan
EndScriptData */
#include "PassiveAI.h" #include "PassiveAI.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SpellInfo.h"
#include "karazhan.h" #include "karazhan.h"
enum TerestianIllhoof enum Text
{ {
SAY_SLAY = 1, SAY_SLAY = 0,
SAY_DEATH = 2, SAY_DEATH = 1,
SAY_AGGRO = 3, SAY_AGGRO = 2,
SAY_SACRIFICE = 4, SAY_SACRIFICE = 3,
SAY_SUMMON = 5 SAY_SUMMON = 4
}; };
enum Spells enum Spells
{ {
SPELL_SUMMON_DEMONCHAINS = 30120, // Summons demonic chains that maintain the ritual of sacrifice. SPELL_SUMMON_DEMONCHAINS = 30120,
SPELL_DEMON_CHAINS = 30206, // Instant - Visual Effect SPELL_DEMON_CHAINS = 30206,
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_ENRAGE = 23537,
SPELL_SHADOW_BOLT = 30055, // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. SPELL_SHADOW_BOLT = 30055,
SPELL_SACRIFICE = 30115, // Teleports and adds the debuff SPELL_SACRIFICE = 30115,
SPELL_BERSERK = 32965, // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. SPELL_BERSERK = 32965,
SPELL_SUMMON_FIENDISIMP = 30184, // Summons a Fiendish Imp. SPELL_SUMMON_FIENDISIMP = 30184,
SPELL_SUMMON_IMP = 30066, // Summons Kil'rek SPELL_SUMMON_IMP = 30066,
SPELL_FIENDISH_PORTAL = 30171, // Opens portal and summons Fiendish Portal, 2 sec cast SPELL_FIENDISH_PORTAL = 30171,
SPELL_FIENDISH_PORTAL_1 = 30179, // Opens portal and summons Fiendish Portal, instant cast SPELL_FIENDISH_PORTAL_1 = 30179,
SPELL_FIREBOLT = 30050, // Blasts a target for 150 Fire damage. SPELL_FIREBOLT = 30050,
SPELL_BROKEN_PACT = 30065, // All damage taken increased by 25%. SPELL_BROKEN_PACT = 30065,
SPELL_AMPLIFY_FLAMES = 30053, // Increases the Fire damage taken by an enemy by 500 for 25 sec. SPELL_AMPLIFY_FLAMES = 30053
}; };
enum Creatures enum Creatures
@@ -62,390 +56,306 @@ enum Creatures
NPC_PORTAL = 17265 NPC_PORTAL = 17265
}; };
class npc_kilrek : public CreatureScript struct npc_kilrek : public ScriptedAI
{ {
public: npc_kilrek(Creature* creature) : ScriptedAI(creature)
npc_kilrek() : CreatureScript("npc_kilrek") { }
CreatureAI* GetAI(Creature* creature) const override
{ {
return GetKarazhanAI<npc_kilrekAI>(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; void JustDied(Unit* /*killer*/) override
{
ObjectGuid TerestianGUID; ObjectGuid TerestianGuid = instance->GetGuidData(DATA_TERESTIAN);
if (TerestianGuid)
uint32 AmplifyTimer;
void Reset() override
{ {
TerestianGUID.Clear(); Unit* Terestian = ObjectAccessor::GetUnit(*me, TerestianGuid);
AmplifyTimer = 2000; if (Terestian && Terestian->IsAlive())
}
void JustEngagedWith(Unit* /*who*/) override
{
}
void JustDied(Unit* /*killer*/) override
{
ObjectGuid TerestianGuid = instance->GetGuidData(DATA_TERESTIAN);
if (TerestianGuid)
{ {
Unit* Terestian = ObjectAccessor::GetUnit(*me, TerestianGuid); DoCast(Terestian, SPELL_BROKEN_PACT, true);
if (Terestian && Terestian->IsAlive())
DoCast(Terestian, SPELL_BROKEN_PACT, true);
} }
} }
me->DespawnOrUnsummon(15000);
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<npc_demon_chainAI>(creature);
} }
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(); Unit* Sacrifice = ObjectAccessor::GetUnit(*me, sacrificeGUID);
} if (Sacrifice)
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); Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE);
if (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<npc_fiendish_portalAI>(creature);
} }
struct npc_fiendish_portalAI : public PassiveAI private:
{ ObjectGuid sacrificeGUID;
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();
}
};
}; };
class npc_fiendish_imp : public CreatureScript struct npc_fiendish_portal : public PassiveAI
{ {
public: npc_fiendish_portal(Creature* creature) : PassiveAI(creature), summons(me) {}
npc_fiendish_imp() : CreatureScript("npc_fiendish_imp") { }
CreatureAI* GetAI(Creature* creature) const override void Reset() override
{ {
return GetKarazhanAI<npc_fiendish_impAI>(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 return !me->HasUnitState(UNIT_STATE_CASTING);
if (!UpdateVictim()) });
return; }
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); if (Creature* pPortal = ObjectAccessor::GetCreature(*me, portalGUID[i]))
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<boss_terestianAI>(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])) pPortal->AI()->Reset();
{ pPortal->DespawnOrUnsummon();
CAST_AI(npc_fiendish_portal::npc_fiendish_portalAI, pPortal->AI())->DespawnAllImp();
pPortal->DespawnOrUnsummon();
}
PortalGUID[i].Clear();
} }
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); scheduler.Schedule(45s, [this](TaskContext /*context*/) {
DoZoneInCombat(); 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(); DoCast(target, SPELL_SACRIFICE, true);
++PortalsCount; target->CastSpell(target, SPELL_SUMMON_DEMONCHAINS, true);
Talk(SAY_SACRIFICE);
if (summoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) 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); pPortal->CastSpell(me->GetVictim(), SPELL_SUMMON_FIENDISIMP);
SummonedPortals = true;
} }
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); 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->AI()->Reset();
pPortal->DespawnOrUnsummon(); pPortal->DespawnOrUnsummon();
PortalGUID[i].Clear();
} }
portalGUID[i].Clear();
} }
Talk(SAY_DEATH);
instance->SetData(DATA_TERESTIAN, DONE);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
if (Minion* Kilrek = me->GetFirstMinion()) scheduler.Update(diff);
{ if (me->HasUnitState(UNIT_STATE_CASTING))
if (!Kilrek->IsAlive()) return;
{
Kilrek->UnSummon();
SummonKilrekTimer = 45000;
}
}
if (SummonKilrekTimer <= diff) DoMeleeAttackIfReady();
{ }
DoCast(me, SPELL_SUMMON_IMP, true);
me->RemoveAura(SPELL_BROKEN_PACT);
}
else
SummonKilrekTimer -= diff;
if (SacrificeTimer <= diff) private:
{ bool berserk;
Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true); ObjectGuid portalGUID[2];
if (target && target->IsAlive()) uint8 portalsCount;
{
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();
}
};
}; };
void AddSC_boss_terestian_illhoof() void AddSC_boss_terestian_illhoof()
{ {
new boss_terestian_illhoof(); RegisterKarazhanCreatureAI(boss_terestian_illhoof);
new npc_fiendish_imp(); RegisterKarazhanCreatureAI(npc_fiendish_imp);
new npc_fiendish_portal(); RegisterKarazhanCreatureAI(npc_fiendish_portal);
new npc_kilrek(); RegisterKarazhanCreatureAI(npc_kilrek);
new npc_demon_chain(); RegisterKarazhanCreatureAI(npc_demon_chain);
} }