aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoroffl <11556157+offl@users.noreply.github.com>2021-12-09 17:10:24 +0200
committerGitHub <noreply@github.com>2021-12-09 17:10:24 +0200
commit36ee9714157e3af4e2b6b3bb9a753e28360ccd58 (patch)
tree835b5bc6c5e067130ee6a82a2bba2e5dcc4afae5 /src
parent8516984ffe1a0241b5cfc47f2d0124291503aec1 (diff)
Scripts/HoS: Update Sjonnir (#27357)
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp427
1 files changed, 315 insertions, 112 deletions
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp
index 58654003721..4cb30ef4b87 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp
@@ -21,100 +21,157 @@
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "SpellInfo.h"
+#include "SpellMgr.h"
+#include "SpellScript.h"
-enum Spells
+enum Texts
{
- SPELL_LIGHTING_RING = 51849, // Periodic Trigger (interval 2s) spell = 50841
- SPELL_LIGHTING_RING_1 = 50840, // Periodic Trigger (interval 2s) spell = 50841
- SPELL_STATIC_CHARGE = 50834, // Periodic Trigger 2s interval, spell =50835
- SPELL_CHAIN_LIGHTING = 50830,
- SPELL_LIGHTING_SHIELD = 50831,
- SPELL_FRENZY = 28747
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_DEATH = 2,
+ EMOTE_FRENZY = 3
};
-enum Yells
+enum Spells
{
- SAY_AGGRO = 0,
- SAY_SLAY = 1,
- SAY_DEATH = 2
+ SPELL_LIGHTNING_RING_1 = 50840,
+ SPELL_LIGHTNING_RING_2 = 51849,
+ SPELL_STATIC_CHARGE = 50834,
+ SPELL_CHAIN_LIGHTNING = 50830,
+ SPELL_LIGHTNING_SHIELD = 50831,
+ SPELL_FRENZY = 28747,
+
+ SPELL_SUMMON_IRON_DWARF_PERIODIC = 50789, // 59860 not used
+ SPELL_SUMMON_IRON_DWARF_1 = 50790,
+ SPELL_SUMMON_IRON_DWARF_2 = 50791,
+ SPELL_SUMMON_IRON_TROGG_PERIODIC = 50792,
+ SPELL_SUMMON_IRON_TROGG_1 = 50793,
+ SPELL_SUMMON_IRON_TROGG_2 = 50794,
+ SPELL_SUMMON_MALFORMED_OOZE_PERIODIC = 50801,
+ SPELL_SUMMON_MALFORMED_OOZE_1 = 50802,
+ SPELL_SUMMON_MALFORMED_OOZE_2 = 50803,
+ SPELL_SUMMON_EARTHEN_DWARF_PERIODIC = 50824,
+ SPELL_SUMMON_EARTHEN_DWARF_1 = 50825,
+ SPELL_SUMMON_EARTHEN_DWARF_2 = 50826,
+
+ // Malformed Ooze
+ SPELL_OOZE_COMBINE_PERIODIC = 50741,
+ SPELL_OOZE_COMBINE_EFFECT = 50742,
+ SPELL_SUMMON_IRON_SLUDGE = 50747,
+
+ // Iron Sludge
+ SPELL_IRON_SLUDGE_SPAWN_VISUAL = 50777,
+ SPELL_TOXIC_VOLLEY = 50838
};
-enum SjonnirCreatures
+enum Creatures
{
- NPC_FORGED_IRON_TROGG = 27979,
- NPC_MALFORMED_OOZE = 27981,
- NPC_FORGED_IRON_DWARF = 27982,
- NPC_IRON_SLUDGE = 28165,
- NPC_EARTHEN_DWARF = 27980
+ NPC_FORGED_IRON_TROGG = 27979,
+ NPC_FORGED_IRON_DWARF = 27982,
+ NPC_EARTHEN_DWARF = 27980
};
enum Misc
{
- ACTION_OOZE_DEAD = 1,
- DATA_ABUSE_THE_OOZE = 2
+ POINT_CENTER = 0,
+ POINT_COMBINE = 1,
+
+ ACTION_SLUDGE_DEAD = 1,
+ DATA_ABUSE_THE_OOZE = 2
};
enum Events
{
- EVENT_CHAIN_LIGHTNING = 1,
+ EVENT_CHAIN_LIGHTNING = 1,
EVENT_LIGHTNING_SHIELD,
EVENT_STATIC_CHARGE,
- EVENT_LIGHTNING_RING,
- EVENT_SUMMON,
- EVENT_FRENZY,
+ EVENT_LIGHTNING_RING_1,
+ EVENT_LIGHTNING_RING_2,
+ EVENT_FRENZY
};
-Position const PipeLocations[] =
-{
- { 1295.44f, 734.07f, 200.3f, 0.0f }, // left
- { 1297.7f, 595.6f, 199.9f, 0.0f } // right
-};
-
-Position const CenterPoint = { 1295.21f, 667.157f, 189.691f, 0.0f };
+Position const CenterPoint = { 1293.8799f, 666.942f, 189.60754f, 0.0f };
struct boss_sjonnir : public BossAI
{
- boss_sjonnir(Creature* creature) : BossAI(creature, DATA_SJONNIR)
- {
- Initialize();
- }
+ boss_sjonnir(Creature* creature) : BossAI(creature, DATA_SJONNIR),
+ _sludgesKilled(0), _summonsTroggs(false), _summonsOozes(false), _summonsDwarfs(false), _frenzied(false) { }
- void Initialize()
+ void JustEngagedWith(Unit* who) override
{
- abuseTheOoze = 0;
+ if (!instance->CheckRequiredBosses(DATA_SJONNIR, who->ToPlayer()))
+ {
+ EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK);
+ return;
+ }
+
+ BossAI::JustEngagedWith(who);
+ Talk(SAY_AGGRO);
+ DoCastSelf(SPELL_SUMMON_IRON_DWARF_PERIODIC);
+
+ events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 10s, 15s);
+ events.ScheduleEvent(EVENT_STATIC_CHARGE, 15s, 20s);
+ events.ScheduleEvent(EVENT_LIGHTNING_RING_1, 30s);
+ /// @todo: Schedule both in combat and out of combat
+ events.ScheduleEvent(EVENT_LIGHTNING_SHIELD, 5s, 15s);
}
- void Reset() override
+ void JustSummoned(Creature* summoned) override
{
- _Reset();
- Initialize();
+ switch (summoned->GetEntry())
+ {
+ case NPC_FORGED_IRON_DWARF:
+ case NPC_FORGED_IRON_TROGG:
+ // AttackStart(me->GetVictim()) does not work in case of very first spawn
+ if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat))
+ summoned->AI()->AttackStart(target);
+ break;
+ case NPC_EARTHEN_DWARF:
+ summoned->AI()->AttackStart(me);
+ break;
+ }
+ summons.Summon(summoned);
}
- void JustEngagedWith(Unit* who) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
- if (!instance->CheckRequiredBosses(DATA_SJONNIR, who->ToPlayer()))
+ if (me->HealthBelowPctDamaged(75, damage) && !_summonsTroggs)
{
- EnterEvadeMode();
- return;
+ _summonsTroggs = true;
+ me->RemoveAurasDueToSpell(SPELL_SUMMON_IRON_DWARF_PERIODIC);
+ DoCastSelf(SPELL_SUMMON_IRON_TROGG_PERIODIC, true);
}
- BossAI::JustEngagedWith(who);
- Talk(SAY_AGGRO);
+ if (me->HealthBelowPctDamaged(50, damage) && !_summonsOozes)
+ {
+ _summonsOozes = true;
+ me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_SUMMON_IRON_TROGG_PERIODIC, me));
+ DoCastSelf(SPELL_SUMMON_MALFORMED_OOZE_PERIODIC, true);
+ }
+
+ if (me->HealthBelowPctDamaged(25, damage) && !_summonsDwarfs)
+ {
+ _summonsDwarfs = true;
+ me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_SUMMON_MALFORMED_OOZE_PERIODIC, me));
+ DoCastSelf(SPELL_SUMMON_EARTHEN_DWARF_PERIODIC, true);
+ }
- events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 3s, 8s);
- events.ScheduleEvent(EVENT_LIGHTNING_SHIELD, 20s, 25s);
- events.ScheduleEvent(EVENT_STATIC_CHARGE, 20s, 25s);
- events.ScheduleEvent(EVENT_LIGHTNING_RING, 30s, 35s);
- events.ScheduleEvent(EVENT_SUMMON, 5s);
- events.ScheduleEvent(EVENT_FRENZY, 5min);
+ if (me->HealthBelowPctDamaged(20, damage) && !_frenzied)
+ {
+ _frenzied = true;
+ // Old removed, more powerful added
+ events.CancelEvent(EVENT_LIGHTNING_RING_1);
+ events.ScheduleEvent(EVENT_FRENZY, 0s);
+ events.ScheduleEvent(EVENT_LIGHTNING_RING_2, 0s);
+ }
}
- void JustSummoned(Creature* summon) override
+ void EnterEvadeMode(EvadeReason /*why*/) override
{
- summon->GetMotionMaster()->MovePoint(0, CenterPoint);
- /*if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
- summon->AI()->AttackStart(target);*/
- summons.Summon(summon);
+ summons.DespawnAll();
+ /// @todo: Despawn Brann too but respawn his pre-fight version (https://www.youtube.com/watch?v=hxAxbjGfuDw)
+ _DespawnAtEvade();
}
void JustDied(Unit* /*killer*/) override
@@ -131,14 +188,14 @@ struct boss_sjonnir : public BossAI
void DoAction(int32 action) override
{
- if (action == ACTION_OOZE_DEAD)
- ++abuseTheOoze;
+ if (action == ACTION_SLUDGE_DEAD)
+ ++_sludgesKilled;
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_ABUSE_THE_OOZE)
- return abuseTheOoze;
+ return _sludgesKilled;
return 0;
}
@@ -158,39 +215,30 @@ struct boss_sjonnir : public BossAI
switch (eventId)
{
case EVENT_CHAIN_LIGHTNING:
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
- DoCast(target, SPELL_CHAIN_LIGHTING);
- events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 10s, 15s);
+ DoCastVictim(SPELL_CHAIN_LIGHTNING);
+ events.Repeat(10s, 15s);
break;
case EVENT_LIGHTNING_SHIELD:
- DoCast(me, SPELL_LIGHTING_SHIELD);
+ if (!me->HasAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_LIGHTNING_SHIELD, me)))
+ DoCastSelf(SPELL_LIGHTNING_SHIELD);
+ events.Repeat(5s, 15s);
break;
case EVENT_STATIC_CHARGE:
- DoCastVictim(SPELL_STATIC_CHARGE);
- events.ScheduleEvent(EVENT_STATIC_CHARGE, 20s, 25s);
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true, true))
+ DoCast(target, SPELL_STATIC_CHARGE);
+ events.Repeat(20s, 27s);
break;
- case EVENT_LIGHTNING_RING:
- DoCast(me, SPELL_LIGHTING_RING);
- events.ScheduleEvent(EVENT_LIGHTNING_RING, 30s, 35s);
+ case EVENT_LIGHTNING_RING_1:
+ DoCastSelf(SPELL_LIGHTNING_RING_1);
+ events.Repeat(50s);
break;
- case EVENT_SUMMON:
- {
- uint8 summonPipe = urand(0, 1);
- if (HealthAbovePct(75))
- me->SummonCreature(NPC_FORGED_IRON_DWARF, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
- else if (HealthAbovePct(50))
- me->SummonCreature(NPC_FORGED_IRON_TROGG, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
- else if (HealthAbovePct(25))
- me->SummonCreature(NPC_MALFORMED_OOZE, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
- else
- me->SummonCreature(NPC_EARTHEN_DWARF, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30s);
-
- events.ScheduleEvent(EVENT_SUMMON, 20s);
+ case EVENT_LIGHTNING_RING_2:
+ DoCastSelf(SPELL_LIGHTNING_RING_2);
+ events.Repeat(15s);
break;
- }
case EVENT_FRENZY:
- /// @todo: add emote
- DoCast(me, SPELL_FRENZY, true);
+ Talk(EMOTE_FRENZY);
+ DoCastSelf(SPELL_FRENZY);
break;
default:
break;
@@ -203,65 +251,215 @@ struct boss_sjonnir : public BossAI
DoMeleeAttackIfReady();
}
- private:
- uint8 abuseTheOoze;
+private:
+ uint8 _sludgesKilled;
+ bool _summonsTroggs;
+ bool _summonsOozes;
+ bool _summonsDwarfs;
+ bool _frenzied;
};
struct npc_malformed_ooze : public ScriptedAI
{
- npc_malformed_ooze(Creature* creature) : ScriptedAI(creature)
+ npc_malformed_ooze(Creature* creature) : ScriptedAI(creature) { }
+
+ void InitializeAI() override
{
- Initialize();
+ me->SetCorpseDelay(5, true);
+ me->SetReactState(REACT_PASSIVE);
}
- void Initialize()
+ void JustAppeared() override
{
- _mergeTimer = 10000;
+ me->GetMotionMaster()->MovePoint(POINT_CENTER, CenterPoint);
}
- void Reset() override
+ void MovementInform(uint32 type, uint32 id) override
{
- Initialize();
+ if (type == POINT_MOTION_TYPE && id == POINT_CENTER)
+ {
+ DoCastSelf(SPELL_OOZE_COMBINE_PERIODIC);
+ me->GetMotionMaster()->MoveRandom(10);
+ }
}
- void UpdateAI(uint32 diff) override
+ /* This is far from correct implementation. Once ooze reaches center point, it casts periodic aura. When spell hits another ooze, both
+ caster and target removes periodic aura and caster starts moving to target. Target does not stop random movement. Once caster is close
+ enough to target, caster casts a spell to combine with target. Target despawns instantly, caster despawns after 1sec.
+
+ Since target does not stop random movement, that causes problems because combine spell is used when oozes are close enough to each other
+ but with current implementation it takes too much time to reach target, as result there may be too much oozes trying to combine at
+ the same time.
+ Increasing radius at which combine spell can be used or trying to change the way oozes chases target only creates more problems because
+ combine spell may target not required target but just ooze which was closer to caster. That leaves multiple spawns which can't combine
+ anymore since combining process was started(auras were removed) but wasn't finished sucessfully
+
+ Currently target is forced to stop random movement and caster just casts spell when is close enough to target. Spells has additional
+ conditions in DB. That makes oozes combine every time sucessfully but not too fast and give players more time too kill sludges
+ Ideally both spells should be scripted, filtering targets(if possible) and casting spell on target which was stored previously may look
+ overcomplicated but saves from casting spell on wrong target. Or maybe solving the problem with moving to stored target will be enough */
+ void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
{
- if (_mergeTimer <= diff)
+ Creature* creatureTarget = target->ToCreature();
+ if (!creatureTarget)
+ return;
+
+ switch (spellInfo->Id)
{
- if (Creature* temp = me->FindNearestCreature(NPC_MALFORMED_OOZE, 3.0f, true))
- {
- DoSpawnCreature(NPC_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20s);
- temp->DisappearAndDie();
- me->DisappearAndDie();
- }
- _mergeTimer = 3000;
+ case SPELL_OOZE_COMBINE_EFFECT:
+ _combineTarget = creatureTarget->GetGUID();
+ me->RemoveAurasDueToSpell(SPELL_OOZE_COMBINE_PERIODIC);
+ creatureTarget->RemoveAurasDueToSpell(SPELL_OOZE_COMBINE_PERIODIC);
+ creatureTarget->GetMotionMaster()->MoveIdle();
+ me->GetMotionMaster()->MoveIdle();
+ me->GetMotionMaster()->MovePoint(POINT_COMBINE, creatureTarget->GetPosition());
+
+ _scheduler.Schedule(1s, [this](TaskContext task)
+ {
+ Creature* combineTarget = ObjectAccessor::GetCreature(*me, _combineTarget);
+ // Completely unclear what should happen in this case or in case when caster dies
+ if (!combineTarget || !combineTarget->IsAlive())
+ {
+ me->DespawnOrUnsummon();
+ return;
+ }
+
+ if (me->GetExactDist2d(combineTarget) <= 0.1f)
+ DoCast(combineTarget, SPELL_SUMMON_IRON_SLUDGE);
+ else
+ {
+ me->GetMotionMaster()->MovePoint(POINT_COMBINE, combineTarget->GetPosition());
+ task.Repeat();
+ }
+ });
+ break;
+ case SPELL_SUMMON_IRON_SLUDGE:
+ creatureTarget->DespawnOrUnsummon();
+ me->DespawnOrUnsummon(1s);
+ break;
}
- else
- _mergeTimer -= diff;
+ }
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler _scheduler;
+ ObjectGuid _combineTarget;
+};
+
+struct npc_iron_sludge : public ScriptedAI
+{
+ npc_iron_sludge(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void JustAppeared() override
+ {
+ me->SetCorpseDelay(4, true);
+ DoCastSelf(SPELL_IRON_SLUDGE_SPAWN_VISUAL);
+
+ if (Creature* sjonnir = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SJONNIR)))
+ sjonnir->AI()->JustSummoned(me);
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _scheduler.Schedule(3s, 6s, [this](TaskContext task)
+ {
+ DoCastSelf(SPELL_TOXIC_VOLLEY);
+ task.Repeat(3s, 6s);
+ });
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Creature* sjonnir = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SJONNIR)))
+ sjonnir->AI()->DoAction(ACTION_SLUDGE_DEAD);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
if (!UpdateVictim())
return;
- DoMeleeAttackIfReady();
+ _scheduler.Update(diff, [this]
+ {
+ DoMeleeAttackIfReady();
+ });
}
private:
- uint32 _mergeTimer;
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
};
-struct npc_iron_sludge : public ScriptedAI
+/* 50789 - Summon Iron Dwarf
+ 50792 - Summon Iron Trogg
+ 59859 - Summon Iron Trogg
+ 50801 - Summon Malformed Ooze
+ 59858 - Summon Malformed Ooze
+ 50824 - Summon Earthen Dwarf */
+class spell_sjonnir_periodic_summon : public AuraScript
{
- npc_iron_sludge(Creature* creature) : ScriptedAI(creature)
+ PrepareAuraScript(spell_sjonnir_periodic_summon);
+
+public:
+ spell_sjonnir_periodic_summon(uint32 leftPipeSpell, uint32 rightPipeSpell)
+ : AuraScript(), _leftPipeSpell(leftPipeSpell), _rightPipeSpell(rightPipeSpell) { }
+
+private:
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
- instance = creature->GetInstanceScript();
+ return ValidateSpellInfo({ _leftPipeSpell, _rightPipeSpell });
}
- InstanceScript* instance;
+ void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), RAND(_leftPipeSpell, _rightPipeSpell), true);
+ }
- void JustDied(Unit* /*killer*/) override
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), RAND(_leftPipeSpell, _rightPipeSpell), true);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_sjonnir_periodic_summon::AfterApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_sjonnir_periodic_summon::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+
+ uint32 _leftPipeSpell;
+ uint32 _rightPipeSpell;
+};
+
+// 50777 - Iron Sludge Spawn Visual
+class spell_sjonnir_iron_sludge_spawn_visual : public AuraScript
+{
+ PrepareAuraScript(spell_sjonnir_iron_sludge_spawn_visual);
+
+ void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ // They're indeed passive but I'm not sure enough if it's handled by this aura or directly in script
+ if (Creature* creature = GetTarget()->ToCreature())
+ creature->SetReactState(REACT_PASSIVE);
+ }
+
+ void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* creature = GetTarget()->ToCreature())
+ {
+ creature->SetReactState(REACT_AGGRESSIVE);
+ if (creature->IsAIEnabled() && creature->IsAlive())
+ creature->AI()->DoZoneInCombat();
+ }
+ }
+
+ void Register() override
{
- if (Creature* sjonnir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SJONNIR)))
- sjonnir->AI()->DoAction(ACTION_OOZE_DEAD);
+ AfterEffectApply += AuraEffectApplyFn(spell_sjonnir_iron_sludge_spawn_visual::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_sjonnir_iron_sludge_spawn_visual::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
@@ -290,5 +488,10 @@ void AddSC_boss_sjonnir()
RegisterHallsOfStoneCreatureAI(boss_sjonnir);
RegisterHallsOfStoneCreatureAI(npc_malformed_ooze);
RegisterHallsOfStoneCreatureAI(npc_iron_sludge);
+ RegisterSpellScriptWithArgs(spell_sjonnir_periodic_summon, "spell_sjonnir_periodic_summon_iron_dwarf", SPELL_SUMMON_IRON_DWARF_1, SPELL_SUMMON_IRON_DWARF_2);
+ RegisterSpellScriptWithArgs(spell_sjonnir_periodic_summon, "spell_sjonnir_periodic_summon_iron_trogg", SPELL_SUMMON_IRON_TROGG_1, SPELL_SUMMON_IRON_TROGG_2);
+ RegisterSpellScriptWithArgs(spell_sjonnir_periodic_summon, "spell_sjonnir_periodic_summon_malformed_ooze", SPELL_SUMMON_MALFORMED_OOZE_1, SPELL_SUMMON_MALFORMED_OOZE_2);
+ RegisterSpellScriptWithArgs(spell_sjonnir_periodic_summon, "spell_sjonnir_periodic_summon_earthen_dwarf", SPELL_SUMMON_EARTHEN_DWARF_1, SPELL_SUMMON_EARTHEN_DWARF_2);
+ RegisterSpellScript(spell_sjonnir_iron_sludge_spawn_visual);
new achievement_abuse_the_ooze();
}