aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp466
1 files changed, 181 insertions, 285 deletions
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp
index 8e619864201..539f1c4abfb 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp
@@ -18,7 +18,7 @@
/* ScriptData
SDName: Boss_Skarvald_Dalronn
SD%Complete: 95
-SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB
+SDComment: Needs adjustments to blizzlike timers
SDCategory: Utgarde Keep
EndScriptData */
@@ -26,21 +26,15 @@ EndScriptData */
#include "ScriptedCreature.h"
#include "utgarde_keep.h"
-enum Yells
+enum Texts
{
- // signed for 24200, but used by 24200, 27390
- YELL_SKARVALD_AGGRO = 0,
- YELL_SKARVALD_DAL_DIED = 1,
- YELL_SKARVALD_SKA_DIEDFIRST = 2,
- YELL_SKARVALD_KILL = 3,
- YELL_SKARVALD_DAL_DIEDFIRST = 4,
-
- // signed for 24201, but used by 24201, 27389
- YELL_DALRONN_AGGRO = 0,
- YELL_DALRONN_SKA_DIED = 1,
- YELL_DALRONN_DAL_DIEDFIRST = 2,
- YELL_DALRONN_KILL = 3,
- YELL_DALRONN_SKA_DIEDFIRST = 4
+ // Texts are common for both bosses and their ghosts.
+ SAY_AGGRO = 0,
+ SAY_DEATH = 1, // Said once both bosses are dead.
+ SAY_DIED_FIRST = 2, // Said by the first boss that dies.
+ SAY_KILL = 3,
+ SAY_DEATH_RESPONSE = 4 // Said by the boss alive after the first one dies.
+
};
enum Spells
@@ -48,16 +42,38 @@ enum Spells
// Spells of Skarvald and his Ghost
SPELL_CHARGE = 43651,
SPELL_STONE_STRIKE = 48583,
- SPELL_SUMMON_SKARVALD_GHOST = 48613,
SPELL_ENRAGE = 48193,
+ SPELL_SUMMON_SKARVALD_GHOST = 48613,
// Spells of Dalronn and his Ghost
SPELL_SHADOW_BOLT = 43649,
- H_SPELL_SHADOW_BOLT = 59575,
- H_SPELL_SUMMON_SKELETONS = 52611,
+ SPELL_SUMMON_SKELETONS = 52611,
SPELL_DEBILITATE = 43650,
SPELL_SUMMON_DALRONN_GHOST = 48612,
};
+enum Events
+{
+ // Skarvald the Constructor
+ EVENT_SKARVALD_CHARGE = 1,
+ EVENT_STONE_STRIKE,
+
+ // Dalronn the Controller
+ EVENT_SHADOW_BOLT,
+ EVENT_DEBILITATE,
+ EVENT_SUMMON_SKELETONS,
+ EVENT_DELAYED_AGGRO_SAY, // Dalronn's SAY_AGGRO is delayed so it doesn't overlap Skarvald's one.
+
+ // Common event to both bosses.
+ // Delays SAY_DEATH_RESPONSE so it doesn't overlap with the SAY_DIED_FIRST from the boss that has just died.
+ EVENT_DEATH_RESPONSE
+};
+
+enum Actions
+{
+ ACTION_OTHER_JUST_DIED = 1,
+ ACTION_DESPAWN_SUMMONS = 2 // Only needed to clear off the ghosts when the second boss dies.
+};
+
class SkarvaldChargePredicate
{
public:
@@ -72,151 +88,142 @@ class SkarvaldChargePredicate
Unit* me;
};
-class boss_skarvald_the_constructor : public CreatureScript
+struct generic_boss_controllerAI : public BossAI
{
- public:
- boss_skarvald_the_constructor() : CreatureScript("boss_skarvald_the_constructor") { }
+ generic_boss_controllerAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN)
+ {
+ OtherBossData = 0;
+ IsInGhostForm = false;
+ }
- struct boss_skarvald_the_constructorAI : public BossAI
+ void Reset() override
+ {
+ if (me->GetEntry() == NPC_SKARVALD_GHOST || me->GetEntry() == NPC_DALRONN_GHOST)
{
- boss_skarvald_the_constructorAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN) { }
+ IsInGhostForm = true;
+ // Call this here since ghosts aren't set in combat as they spawn.
+ DoZoneInCombat(me, 50.0f);
+ }
+ else
+ _Reset();
+ }
- bool ghost;
- uint32 Charge_Timer;
- uint32 StoneStrike_Timer;
- uint32 Response_Timer;
- uint32 Check_Timer;
- bool Dalronn_isDead;
- bool Enraged;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ if (!IsInGhostForm)
+ _EnterCombat();
+ }
- void Reset() override
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Creature* otherBoss = ObjectAccessor::GetCreature(*me, instance->GetData64(OtherBossData)))
+ {
+ if (otherBoss->IsAlive())
{
- Charge_Timer = 5000;
- StoneStrike_Timer = 10000;
- Dalronn_isDead = false;
- Response_Timer = 0;
- Check_Timer = 5000;
- Enraged = false;
-
- ghost = me->GetEntry() == NPC_SKARVALD_GHOST;
- if (!ghost)
- _Reset();
+ Talk(SAY_DIED_FIRST);
+ me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ otherBoss->AI()->DoAction(ACTION_OTHER_JUST_DIED);
+ DoCast(me, OtherBossData == DATA_DALRONN ? SPELL_SUMMON_SKARVALD_GHOST : SPELL_SUMMON_DALRONN_GHOST, true);
}
-
- void EnterCombat(Unit* /*who*/) override
+ else
{
- if (!ghost)
- {
- _EnterCombat();
- Talk(YELL_SKARVALD_AGGRO);
- }
- }
-
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage))
- {
- Enraged = true;
- DoCast(me, SPELL_ENRAGE);
- }
+ Talk(SAY_DEATH);
+ otherBoss->AI()->DoAction(ACTION_DESPAWN_SUMMONS);
+ _JustDied();
}
+ }
+ }
- void DoAction(int32 /*actionId*/)
- {
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_OTHER_JUST_DIED:
+ events.ScheduleEvent(EVENT_DEATH_RESPONSE, 2000);
+ break;
+ case ACTION_DESPAWN_SUMMONS:
summons.DespawnAll();
- }
+ break;
+ default:
+ break;
+ }
+ }
- void JustDied(Unit* killer) override
- {
- if (!ghost)
- {
- if (Creature* dalronn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALRONN)))
- {
- if (dalronn->IsAlive())
- {
- Talk(YELL_SKARVALD_SKA_DIEDFIRST);
+ void ExecuteEvent(uint32 eventId) override
+ {
+ if (eventId == EVENT_DEATH_RESPONSE)
+ Talk(SAY_DEATH_RESPONSE);
+ }
- me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ void KilledUnit(Unit* who) override
+ {
+ if (!IsInGhostForm && who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ protected:
+ uint32 OtherBossData;
+ bool IsInGhostForm;
+};
- //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true);
- if (Creature* temp = me->SummonCreature(NPC_SKARVALD_GHOST, *me, TEMPSUMMON_CORPSE_DESPAWN, 5000))
- {
- temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- temp->AI()->AttackStart(killer);
- }
- }
- else
- {
- dalronn->AI()->DoAction(0);
- _JustDied();
- Talk(YELL_SKARVALD_DAL_DIED);
- }
- }
- }
+class boss_skarvald_the_constructor : public CreatureScript
+{
+ public:
+ boss_skarvald_the_constructor() : CreatureScript("boss_skarvald_the_constructor") { }
+
+ struct boss_skarvald_the_constructorAI : public generic_boss_controllerAI
+ {
+ boss_skarvald_the_constructorAI(Creature* creature) : generic_boss_controllerAI(creature)
+ {
+ Enraged = false;
}
- void KilledUnit(Unit* who) override
+ void Reset() override
{
- if (!ghost && who->GetTypeId() == TYPEID_PLAYER)
- Talk(YELL_SKARVALD_KILL);
+ OtherBossData = DATA_DALRONN;
+ Enraged = false;
+ generic_boss_controllerAI::Reset();
}
- void UpdateAI(uint32 diff) override
+ void EnterCombat(Unit* who) override
{
- if (!UpdateVictim())
- return;
-
- if (!ghost)
- {
- if (Check_Timer)
- {
- if (Check_Timer <= diff)
- {
- Check_Timer = 5000;
- Creature* dalronn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALRONN));
- if (dalronn && dalronn->isDead())
- {
- Dalronn_isDead = true;
- Response_Timer = 2000;
- Check_Timer = 0;
- }
- }
- else
- Check_Timer -= diff;
- }
- if (Response_Timer && Dalronn_isDead)
- {
- if (Response_Timer <= diff)
- {
- Talk(YELL_SKARVALD_DAL_DIEDFIRST);
+ if (!IsInGhostForm)
+ Talk(SAY_AGGRO);
- Response_Timer = 0;
- }
- else
- Response_Timer -= diff;
- }
- }
+ events.ScheduleEvent(EVENT_SKARVALD_CHARGE, 5000);
+ events.ScheduleEvent(EVENT_STONE_STRIKE, 10000);
+ generic_boss_controllerAI::EnterCombat(who);
+ }
- if (Charge_Timer <= diff)
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)))
- DoCast(target, SPELL_CHARGE);
- Charge_Timer = 5000 + rand32() % 5000;
+ case EVENT_SKARVALD_CHARGE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)))
+ DoCast(target, SPELL_CHARGE);
+ events.ScheduleEvent(EVENT_CHARGE, urand(5000, 10000));
+ break;
+ case EVENT_STONE_STRIKE:
+ DoCastVictim(SPELL_STONE_STRIKE);
+ events.ScheduleEvent(EVENT_STONE_STRIKE, urand(5000, 10000));
+ break;
+ default:
+ generic_boss_controllerAI::ExecuteEvent(eventId);
+ break;
}
- else
- Charge_Timer -= diff;
+ }
- if (StoneStrike_Timer <= diff)
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (!Enraged && !IsInGhostForm && me->HealthBelowPctDamaged(15, damage))
{
- DoCastVictim(SPELL_STONE_STRIKE);
- StoneStrike_Timer = 5000 + rand32() % 5000;
+ Enraged = true;
+ DoCast(me, SPELL_ENRAGE);
}
- else
- StoneStrike_Timer -= diff;
-
- if (!me->HasUnitState(UNIT_STATE_CASTING))
- DoMeleeAttackIfReady();
}
+ private:
+ bool Enraged;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -230,171 +237,60 @@ class boss_dalronn_the_controller : public CreatureScript
public:
boss_dalronn_the_controller() : CreatureScript("boss_dalronn_the_controller") { }
- struct boss_dalronn_the_controllerAI : public BossAI
+ struct boss_dalronn_the_controllerAI : public generic_boss_controllerAI
{
- boss_dalronn_the_controllerAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN) { }
-
- bool ghost;
- uint32 ShadowBolt_Timer;
- uint32 Debilitate_Timer;
- uint32 Summon_Timer;
-
- uint32 Response_Timer;
- uint32 Check_Timer;
- uint32 AggroYell_Timer;
- bool Skarvald_isDead;
+ boss_dalronn_the_controllerAI(Creature* creature) : generic_boss_controllerAI(creature) { }
void Reset() override
{
- ShadowBolt_Timer = 1000;
- Debilitate_Timer = 5000;
- Summon_Timer = 10000;
- Check_Timer = 5000;
- Skarvald_isDead = false;
- Response_Timer = 0;
- AggroYell_Timer = 0;
-
- ghost = me->GetEntry() == NPC_DALRONN_GHOST;
- if (!ghost)
- _Reset();
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- if (!ghost)
- {
- _EnterCombat();
- AggroYell_Timer = 5000;
- }
- }
-
- void DoAction(int32 /*actionId*/)
- {
- summons.DespawnAll();
- }
-
- void JustDied(Unit* killer) override
- {
- if (!ghost)
- {
- if (Creature* skarvald = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SKARVALD)))
- {
- if (skarvald->IsAlive())
- {
- Talk(YELL_DALRONN_DAL_DIEDFIRST);
-
- me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
-
- //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true);
- if (Creature* temp = me->SummonCreature(NPC_DALRONN_GHOST, *me, TEMPSUMMON_CORPSE_DESPAWN, 5000))
- {
- temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- temp->AI()->AttackStart(killer);
- }
- }
- else
- {
- skarvald->AI()->DoAction(0);
- _JustDied();
- Talk(YELL_DALRONN_SKA_DIED);
- }
- }
- }
+ OtherBossData = DATA_SKARVALD;
+ generic_boss_controllerAI::Reset();
}
- void KilledUnit(Unit* who) override
+ void EnterCombat(Unit* who) override
{
- if (!ghost && who->GetTypeId() == TYPEID_PLAYER)
- Talk(YELL_DALRONN_KILL);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 1000);
+ events.ScheduleEvent(EVENT_DEBILITATE, 5000);
+
+ if (!IsInGhostForm)
+ events.ScheduleEvent(EVENT_DELAYED_AGGRO_SAY, 5000);
+
+ if (IsHeroic())
+ events.ScheduleEvent(EVENT_SUMMON_SKELETONS, 10000);
+
+ generic_boss_controllerAI::EnterCombat(who);
}
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
{
- if (!UpdateVictim())
- return;
-
- if (AggroYell_Timer)
- {
- if (AggroYell_Timer <= diff)
- {
- Talk(YELL_DALRONN_AGGRO);
-
- AggroYell_Timer = 0;
- }
- else
- AggroYell_Timer -= diff;
- }
-
- if (!ghost)
- {
- if (Check_Timer)
- {
- if (Check_Timer <= diff)
- {
- Check_Timer = 5000;
- Creature* skarvald = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SKARVALD));
- if (skarvald && skarvald->isDead())
- {
- Skarvald_isDead = true;
- Response_Timer = 2000;
- Check_Timer = 0;
- }
- }
- else
- Check_Timer -= diff;
- }
-
- if (Response_Timer && Skarvald_isDead)
- {
- if (Response_Timer <= diff)
- {
- Talk(YELL_DALRONN_SKA_DIEDFIRST);
- Response_Timer = 0;
- }
- else
- Response_Timer -= diff;
- }
- }
-
- if (ShadowBolt_Timer <= diff)
+ switch (eventId)
{
- if (!me->IsNonMeleeSpellCast(false))
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_SHADOW_BOLT);
- ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells
- }
- }
- else
- ShadowBolt_Timer -= diff;
-
- if (Debilitate_Timer <= diff)
- {
- if (!me->IsNonMeleeSpellCast(false))
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_DEBILITATE);
- Debilitate_Timer = 5000 + rand32() % 5000;
- }
- }
- else
- Debilitate_Timer -= diff;
-
- if (IsHeroic())
- {
- if (Summon_Timer <= diff)
- {
+ case EVENT_SHADOW_BOLT:
+ if (!me->IsNonMeleeSpellCast(false))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_SHADOW_BOLT);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 2100); //give a 100ms pause to try cast other spells
+ break;
+ case EVENT_DEBILITATE:
if (!me->IsNonMeleeSpellCast(false))
{
- DoCast(me, H_SPELL_SUMMON_SKELETONS);
- Summon_Timer = (rand32() % 10000) + 20000;
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_DEBILITATE);
}
- }
- else
- Summon_Timer -= diff;
+ events.ScheduleEvent(EVENT_DEBILITATE, urand(5000, 10000));
+ break;
+ case EVENT_SUMMON_SKELETONS:
+ if (!me->IsNonMeleeSpellCast(false))
+ DoCast(SPELL_SUMMON_SKELETONS);
+ events.ScheduleEvent(EVENT_SUMMON_SKELETONS, urand(10000, 30000));
+ break;
+ case EVENT_DELAYED_AGGRO_SAY:
+ Talk(SAY_AGGRO);
+ break;
+ default:
+ generic_boss_controllerAI::ExecuteEvent(eventId);
+ break;
}
-
- DoMeleeAttackIfReady();
}
};