mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-18 16:38:42 +01:00
Merge pull request #12992 from Nyeriah/patch-uk
Scripts/UtgardeKeep: Update Skarvald & Dalronn scripts to EventMaps
This commit is contained in:
@@ -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,
|
||||
// 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.
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct generic_boss_controllerAI : public BossAI
|
||||
{
|
||||
generic_boss_controllerAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN)
|
||||
{
|
||||
OtherBossData = 0;
|
||||
IsInGhostForm = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (me->GetEntry() == NPC_SKARVALD_GHOST || me->GetEntry() == NPC_DALRONN_GHOST)
|
||||
{
|
||||
IsInGhostForm = true;
|
||||
// Call this here since ghosts aren't set in combat as they spawn.
|
||||
DoZoneInCombat(me, 50.0f);
|
||||
}
|
||||
else
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (!IsInGhostForm)
|
||||
_EnterCombat();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (Creature* otherBoss = ObjectAccessor::GetCreature(*me, instance->GetData64(OtherBossData)))
|
||||
{
|
||||
if (otherBoss->IsAlive())
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
otherBoss->AI()->DoAction(ACTION_DESPAWN_SUMMONS);
|
||||
_JustDied();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
if (eventId == EVENT_DEATH_RESPONSE)
|
||||
Talk(SAY_DEATH_RESPONSE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* who) override
|
||||
{
|
||||
if (!IsInGhostForm && who->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32 OtherBossData;
|
||||
bool IsInGhostForm;
|
||||
};
|
||||
|
||||
class boss_skarvald_the_constructor : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_skarvald_the_constructor() : CreatureScript("boss_skarvald_the_constructor") { }
|
||||
|
||||
struct boss_skarvald_the_constructorAI : public BossAI
|
||||
struct boss_skarvald_the_constructorAI : public generic_boss_controllerAI
|
||||
{
|
||||
boss_skarvald_the_constructorAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN) { }
|
||||
|
||||
bool ghost;
|
||||
uint32 Charge_Timer;
|
||||
uint32 StoneStrike_Timer;
|
||||
uint32 Response_Timer;
|
||||
uint32 Check_Timer;
|
||||
bool Dalronn_isDead;
|
||||
bool Enraged;
|
||||
boss_skarvald_the_constructorAI(Creature* creature) : generic_boss_controllerAI(creature)
|
||||
{
|
||||
Enraged = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Charge_Timer = 5000;
|
||||
StoneStrike_Timer = 10000;
|
||||
Dalronn_isDead = false;
|
||||
Response_Timer = 0;
|
||||
Check_Timer = 5000;
|
||||
OtherBossData = DATA_DALRONN;
|
||||
Enraged = false;
|
||||
|
||||
ghost = me->GetEntry() == NPC_SKARVALD_GHOST;
|
||||
if (!ghost)
|
||||
_Reset();
|
||||
generic_boss_controllerAI::Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
if (!ghost)
|
||||
if (!IsInGhostForm)
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_SKARVALD_CHARGE, 5000);
|
||||
events.ScheduleEvent(EVENT_STONE_STRIKE, 10000);
|
||||
generic_boss_controllerAI::EnterCombat(who);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(YELL_SKARVALD_AGGRO);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
|
||||
{
|
||||
if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage))
|
||||
if (!Enraged && !IsInGhostForm && me->HealthBelowPctDamaged(15, damage))
|
||||
{
|
||||
Enraged = true;
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 /*actionId*/)
|
||||
{
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* who) override
|
||||
{
|
||||
if (!ghost && who->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(YELL_SKARVALD_KILL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) 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);
|
||||
|
||||
Response_Timer = 0;
|
||||
}
|
||||
else
|
||||
Response_Timer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (Charge_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)))
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
Charge_Timer = 5000 + rand32() % 5000;
|
||||
}
|
||||
else
|
||||
Charge_Timer -= diff;
|
||||
|
||||
if (StoneStrike_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_STONE_STRIKE);
|
||||
StoneStrike_Timer = 5000 + rand32() % 5000;
|
||||
}
|
||||
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();
|
||||
OtherBossData = DATA_SKARVALD;
|
||||
generic_boss_controllerAI::Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
if (!ghost)
|
||||
{
|
||||
_EnterCombat();
|
||||
AggroYell_Timer = 5000;
|
||||
}
|
||||
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 DoAction(int32 /*actionId*/)
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (!ghost)
|
||||
switch (eventId)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* who) override
|
||||
{
|
||||
if (!ghost && who->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(YELL_DALRONN_KILL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user