fix(Scripts/HellfireCitadel): Mass struct/model update (#16264)

* init

* .

* check codestyle (ubuntu-20.04)

* ubuntu-20.04-clang-with-modules

* clang
This commit is contained in:
Eddy Vega
2023-05-14 16:13:42 -06:00
committed by GitHub
parent 9ce833a68a
commit 1724088e06
13 changed files with 1385 additions and 1554 deletions

View File

@@ -0,0 +1,9 @@
--
DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (19130,30925,12739,30500,30495);
INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`) VALUES
(19130, 19130, 40392),
(30925, 30925, 40059),
(12739, 12739, 15472),
(30500, 30500, 35954),
(30495, 30495, 35953);

View File

@@ -29,41 +29,41 @@ constexpr uint32 EncounterCount = 4;
enum bloodFurnace
{
DATA_THE_MAKER = 0,
DATA_BROGGOK = 1,
DATA_KELIDAN = 2,
MAX_ENCOUNTER = 3,
DATA_THE_MAKER = 0,
DATA_BROGGOK = 1,
DATA_KELIDAN = 2,
MAX_ENCOUNTER = 3,
DATA_DOOR1 = 10,
DATA_DOOR2 = 11,
DATA_DOOR3 = 12,
DATA_BROGGOK_REAR_DOOR = 13,
DATA_BROGGOK_LEVER = 14,
DATA_DOOR6 = 15,
DATA_DOOR1 = 10,
DATA_DOOR2 = 11,
DATA_DOOR3 = 12,
DATA_BROGGOK_REAR_DOOR = 13,
DATA_BROGGOK_LEVER = 14,
DATA_DOOR6 = 15,
DATA_PRISON_CELL1 = 20,
DATA_PRISON_CELL2 = 21,
DATA_PRISON_CELL3 = 22,
DATA_PRISON_CELL4 = 23,
DATA_PRISON_CELL1 = 20,
DATA_PRISON_CELL2 = 21,
DATA_PRISON_CELL3 = 22,
DATA_PRISON_CELL4 = 23,
ACTION_ACTIVATE_BROGGOK = 30,
ACTION_PREPARE_BROGGOK = 31
ACTION_ACTIVATE_BROGGOK = 30,
ACTION_PREPARE_BROGGOK = 31
};
enum bloodFurnaceNPC
{
NPC_THE_MAKER = 17381,
NPC_BROGGOK = 17380,
NPC_KELIDAN = 17377,
NPC_NASCENT_FEL_ORC = 17398,
NPC_CHANNELER = 17653
NPC_THE_MAKER = 17381,
NPC_BROGGOK = 17380,
NPC_KELIDAN = 17377,
NPC_NASCENT_FEL_ORC = 17398,
NPC_CHANNELER = 17653
};
enum BloodFurnaceGO
{
GO_BROGGOK_DOOR_FRONT = 181822,
GO_BROGGOK_DOOR_REAR = 181819,
GO_BROGGOK_LEVER = 181982
GO_BROGGOK_DOOR_FRONT = 181822,
GO_BROGGOK_DOOR_REAR = 181819,
GO_BROGGOK_LEVER = 181982
};
template <class AI, class T>

View File

@@ -21,14 +21,17 @@
#include "SpellScript.h"
#include "blood_furnace.h"
enum eEnums
enum Say
{
SAY_AGGRO = 0,
SAY_AGGRO = 0
};
enum Spells
{
SPELL_SLIME_SPRAY = 30913,
SPELL_POISON_CLOUD = 30916,
SPELL_POISON_BOLT = 30917,
SPELL_POISON = 30914,
SPELL_POISON = 30914
};
struct boss_broggok : public BossAI
@@ -52,7 +55,6 @@ struct boss_broggok : public BossAI
void JustSummoned(Creature* summoned) override
{
summons.Summon(summoned);
summoned->SetFaction(FACTION_MONSTER_2);
summoned->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
summoned->CastSpell(summoned, SPELL_POISON, true, 0, 0, me->GetGUID());
@@ -80,7 +82,6 @@ struct boss_broggok : public BossAI
DoCastSelf(SPELL_POISON_CLOUD);
context.Repeat(20s);
});
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToAll(false);
@@ -106,7 +107,6 @@ public:
}
}
}
go->UseDoorOrButton();
return false;
}
@@ -121,6 +121,7 @@ class spell_broggok_poison_cloud : public AuraScript
{
if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell))
return false;
return true;
}
@@ -142,6 +143,6 @@ class spell_broggok_poison_cloud : public AuraScript
void AddSC_boss_broggok()
{
RegisterBloodFurnaceCreatureAI(boss_broggok);
new go_broggok_lever();
RegisterSpellScript(spell_broggok_poison_cloud);
new go_broggok_lever();
}

View File

@@ -20,15 +20,18 @@
#include "SpellAuras.h"
#include "blood_furnace.h"
enum eKelidan
enum Says
{
SAY_WAKE = 0,
SAY_ADD_AGGRO = 1,
SAY_KILL = 2,
SAY_NOVA = 3,
SAY_DIE = 4,
SAY_DIE = 4
};
// Keldian spells
enum Spells
{
// Keldian
SPELL_CORRUPTION = 30938,
SPELL_EVOCATION = 30935,
SPELL_FIRE_NOVA = 33132,
@@ -36,23 +39,16 @@ enum eKelidan
SPELL_BURNING_NOVA = 30940,
SPELL_VORTEX = 37370,
// Channelers spells
SPELL_SHADOW_BOLT = 12739,
SPELL_SHADOW_BOLT_H = 15472,
SPELL_MARK_OF_SHADOW = 30937,
SPELL_CHANNELING = 39123,
// Channelers
SPELL_SHADOW_BOLT = 12739,
SPELL_MARK_OF_SHADOW = 30937,
SPELL_CHANNELING = 39123
};
// Events
EVENT_SPELL_VOLLEY = 1,
EVENT_SPELL_CORRUPTION = 2,
EVENT_SPELL_BURNING_NOVA = 3,
EVENT_SPELL_FIRE_NOVA = 4,
EVENT_SPELL_SHADOW_BOLT = 5,
EVENT_SPELL_MARK = 6,
// Actions
ACTION_CHANNELER_ENGAGED = 1,
ACTION_CHANNELER_DIED = 2,
enum Actions
{
ACTION_CHANNELER_ENGAGED = 1,
ACTION_CHANNELER_DIED = 2
};
const float ShadowmoonChannelers[5][4] =
@@ -64,299 +60,276 @@ const float ShadowmoonChannelers[5][4] =
{316.0f, -109.0f, -24.6f, 1.257f}
};
class boss_kelidan_the_breaker : public CreatureScript
struct boss_kelidan_the_breaker : public BossAI
{
public:
boss_kelidan_the_breaker() : CreatureScript("boss_kelidan_the_breaker")
boss_kelidan_the_breaker(Creature* creature) : BossAI(creature, DATA_KELIDAN)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
struct boss_kelidan_the_breakerAI : public ScriptedAI
ObjectGuid channelers[5];
uint32 checkTimer;
bool addYell;
void Reset() override
{
boss_kelidan_the_breakerAI(Creature* creature) : ScriptedAI(creature)
addYell = false;
checkTimer = 5000;
_Reset();
ApplyImmunities(true);
SummonChannelers();
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToAll(true);
if (instance)
{
instance = creature->GetInstanceScript();
instance->SetData(DATA_KELIDAN, NOT_STARTED);
}
}
InstanceScript* instance;
EventMap events;
ObjectGuid channelers[5];
uint32 checkTimer;
bool addYell;
void Reset() override
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_WAKE);
_JustEngagedWith();
me->InterruptNonMeleeSpells(false);
if (instance)
{
addYell = false;
checkTimer = 5000;
events.Reset();
instance->SetData(DATA_KELIDAN, IN_PROGRESS);
}
scheduler.Schedule(1s, [this](TaskContext context)
{
DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY);
context.Repeat(8s, 13s);
}).Schedule(5s, [this](TaskContext context)
{
DoCastAOE(SPELL_CORRUPTION);
context.Repeat(30s, 50s);
}).Schedule(15s, [this](TaskContext context)
{
Talk(SAY_NOVA);
ApplyImmunities(false);
me->AddAura(SPELL_BURNING_NOVA, me);
ApplyImmunities(true);
SummonChannelers();
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToAll(true);
if (instance)
instance->SetData(DATA_KELIDAN, NOT_STARTED);
}
void JustEngagedWith(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_SPELL_VOLLEY, 1000);
events.ScheduleEvent(EVENT_SPELL_CORRUPTION, 5000);
events.ScheduleEvent(EVENT_SPELL_BURNING_NOVA, 15000);
me->InterruptNonMeleeSpells(false);
Talk(SAY_WAKE);
if (instance)
instance->SetData(DATA_KELIDAN, IN_PROGRESS);
}
void KilledUnit(Unit* /*victim*/) override
{
if (urand(0, 1))
Talk(SAY_KILL);
}
void DoAction(int32 param) override
{
if (param == ACTION_CHANNELER_ENGAGED)
if (IsHeroic())
{
if (!addYell)
{
addYell = true;
Talk(SAY_ADD_AGGRO);
for (uint8 i = 0; i < 5; ++i)
{
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
if (channeler && !channeler->IsInCombat())
channeler->SetInCombatWithZone();
}
}
DoCastAOE(SPELL_VORTEX);
}
else if (param == ACTION_CHANNELER_DIED)
scheduler.DelayGroup(0, 6s);
scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_FIRE_NOVA, true);
});
context.Repeat(25s, 32s);
});
}
void KilledUnit(Unit* /*victim*/) override
{
if (urand(0, 1))
{
Talk(SAY_KILL);
}
}
void DoAction(int32 param) override
{
if (param == ACTION_CHANNELER_ENGAGED)
{
if (!addYell)
{
addYell = true;
Talk(SAY_ADD_AGGRO);
for (uint8 i = 0; i < 5; ++i)
{
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
if (channeler && channeler->IsAlive())
return;
}
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToAll(false);
if (Unit* target = me->SelectNearestPlayer(100.0f))
AttackStart(target);
}
}
void CheckChannelers()
{
if (addYell)
{
if (!SelectTargetFromPlayerList(100.0f))
EnterEvadeMode();
return;
}
SummonChannelers();
for (uint8 i = 0; i < 5; ++i)
{
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
if (channeler && !channeler->HasUnitState(UNIT_STATE_CASTING) && !channeler->IsInCombat())
{
Creature* target = ObjectAccessor::GetCreature(*me, channelers[(i + 2) % 5]);
if (target)
channeler->CastSpell(target, SPELL_CHANNELING, false);
if (channeler && !channeler->IsInCombat())
{
channeler->SetInCombatWithZone();
}
}
}
}
void SummonChannelers()
else if (param == ACTION_CHANNELER_DIED)
{
for (uint8 i = 0; i < 5; ++i)
{
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
if (channeler && channeler->isDead())
{
channeler->DespawnOrUnsummon(1);
channeler = nullptr;
}
if (!channeler)
channeler = me->SummonCreature(NPC_CHANNELER, ShadowmoonChannelers[i][0], ShadowmoonChannelers[i][1], ShadowmoonChannelers[i][2], ShadowmoonChannelers[i][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000);
channelers[i] = channeler ? channeler->GetGUID() : ObjectGuid::Empty;
if (channeler && channeler->IsAlive())
return;
}
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
if (instance)
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetImmuneToAll(false);
if (Unit* target = me->SelectNearestPlayer(100.0f))
{
// Xinef: load grid with start doors
me->GetMap()->LoadGrid(0, -111.0f);
instance->SetData(DATA_KELIDAN, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR1), true);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR6), true);
AttackStart(target);
}
}
}
void ApplyImmunities(bool apply)
{
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISTRACT, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_KNOCKOUT, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_BANISH, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SHACKLE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DAZE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
checkTimer += diff;
if (checkTimer >= 5000)
{
checkTimer = 0;
CheckChannelers();
if (!me->HasUnitState(UNIT_STATE_CASTING))
me->CastSpell(me, SPELL_EVOCATION, false);
}
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_VOLLEY:
me->CastSpell(me, SPELL_SHADOW_BOLT_VOLLEY, false);
events.RepeatEvent(urand(8000, 13000));
break;
case EVENT_SPELL_CORRUPTION:
me->CastSpell(me, SPELL_CORRUPTION, false);
events.RepeatEvent(urand(30000, 50000));
break;
case EVENT_SPELL_BURNING_NOVA:
Talk(SAY_NOVA);
ApplyImmunities(false);
me->AddAura(SPELL_BURNING_NOVA, me);
ApplyImmunities(true);
if (IsHeroic())
DoTeleportAll(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
events.DelayEvents(6000, 0);
events.RepeatEvent(urand(25000, 32000));
events.ScheduleEvent(EVENT_SPELL_FIRE_NOVA, 5000);
break;
case EVENT_SPELL_FIRE_NOVA:
me->CastSpell(me, SPELL_FIRE_NOVA, true);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void CheckChannelers()
{
return GetBloodFurnaceAI<boss_kelidan_the_breakerAI>(creature);
if (addYell)
{
if (!SelectTargetFromPlayerList(100.0f))
{
EnterEvadeMode();
}
return;
}
SummonChannelers();
for (uint8 i = 0; i < 5; ++i)
{
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
if (channeler && !channeler->HasUnitState(UNIT_STATE_CASTING) && !channeler->IsInCombat())
{
Creature* target = ObjectAccessor::GetCreature(*me, channelers[(i + 2) % 5]);
if (target)
{
channeler->CastSpell(target, SPELL_CHANNELING, false);
}
}
}
}
void SummonChannelers()
{
for (uint8 i = 0; i < 5; ++i)
{
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
if (channeler && channeler->isDead())
{
channeler->DespawnOrUnsummon(1);
channeler = nullptr;
}
if (!channeler)
{
channeler = me->SummonCreature(NPC_CHANNELER, ShadowmoonChannelers[i][0], ShadowmoonChannelers[i][1], ShadowmoonChannelers[i][2], ShadowmoonChannelers[i][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000);
}
channelers[i] = channeler ? channeler->GetGUID() : ObjectGuid::Empty;
}
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
if (instance)
{
me->GetMap()->LoadGrid(0, -111.0f);
instance->SetData(DATA_KELIDAN, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR1), true);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR6), true);
}
}
void ApplyImmunities(bool apply)
{
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISTRACT, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_KNOCKOUT, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_BANISH, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SHACKLE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DAZE, apply);
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
checkTimer += diff;
if (checkTimer >= 5000)
{
checkTimer = 0;
CheckChannelers();
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
me->CastSpell(me, SPELL_EVOCATION, false);
}
}
return;
}
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
};
class npc_shadowmoon_channeler : public CreatureScript
struct npc_shadowmoon_channeler : public ScriptedAI
{
public:
npc_shadowmoon_channeler() : CreatureScript("npc_shadowmoon_channeler") {}
npc_shadowmoon_channeler(Creature* creature) : ScriptedAI(creature) {}
struct npc_shadowmoon_channelerAI : public ScriptedAI
Creature* GetKelidan()
{
npc_shadowmoon_channelerAI(Creature* creature) : ScriptedAI(creature) {}
EventMap events;
void Reset() override
if (InstanceScript* instance = me->GetInstanceScript())
{
events.Reset();
return instance->GetCreature(DATA_KELIDAN);
}
Creature* GetKelidan()
{
if (InstanceScript* instance = me->GetInstanceScript())
return instance->GetCreature(DATA_KELIDAN);
return nullptr;
}
void JustEngagedWith(Unit* /*who*/) override
{
if (Creature* kelidan = GetKelidan())
kelidan->AI()->DoAction(ACTION_CHANNELER_ENGAGED);
me->InterruptNonMeleeSpells(false);
events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, urand(1200, 2400));
events.ScheduleEvent(EVENT_SPELL_MARK, urand(5000, 6500));
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* kelidan = GetKelidan())
kelidan->AI()->DoAction(ACTION_CHANNELER_DIED);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_SHADOW_BOLT:
me->CastSpell(me->GetVictim(), IsHeroic() ? SPELL_SHADOW_BOLT_H : SPELL_SHADOW_BOLT, false);
events.RepeatEvent(urand(6000, 7200));
break;
case EVENT_SPELL_MARK:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_MARK_OF_SHADOW, false);
events.RepeatEvent(urand(16000, 17500));
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBloodFurnaceAI<npc_shadowmoon_channelerAI>(creature);
return nullptr;
}
void JustEngagedWith(Unit* /*who*/) override
{
if (Creature* kelidan = GetKelidan())
{
kelidan->AI()->DoAction(ACTION_CHANNELER_ENGAGED);
}
me->InterruptNonMeleeSpells(false);
_scheduler.Schedule(1200ms, 2400ms, [this](TaskContext context)
{
DoCastVictim(SPELL_SHADOW_BOLT);
context.Repeat(6s, 7200ms);
}).Schedule(5s, 6500ms, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_MARK_OF_SHADOW);
context.Repeat(16s, 17500ms);
});
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* kelidan = GetKelidan())
{
kelidan->AI()->DoAction(ACTION_CHANNELER_DIED);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
TaskScheduler _scheduler;
};
void AddSC_boss_kelidan_the_breaker()
{
new boss_kelidan_the_breaker();
new npc_shadowmoon_channeler();
RegisterBloodFurnaceCreatureAI(boss_kelidan_the_breaker);
RegisterBloodFurnaceCreatureAI(npc_shadowmoon_channeler);
}

View File

@@ -19,111 +19,87 @@
#include "ScriptedCreature.h"
#include "blood_furnace.h"
enum eEnums
enum Says
{
SAY_AGGRO = 0,
SAY_KILL = 1,
SAY_DIE = 2,
SPELL_EXPLODING_BREAKER = 30925,
SPELL_DOMINATION = 30923,
EVENT_SPELL_EXPLODING = 1,
EVENT_SPELL_DOMINATION = 2
SAY_AGGRO = 0,
SAY_KILL = 1,
SAY_DIE = 2
};
class boss_the_maker : public CreatureScript
enum Spells
{
public:
boss_the_maker() : CreatureScript("boss_the_maker")
SPELL_EXPLODING_BEAKER = 30925,
SPELL_DOMINATION = 30923
};
struct boss_the_maker : public BossAI
{
boss_the_maker(Creature* creature) : BossAI(creature, DATA_THE_MAKER)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
struct boss_the_makerAI : public ScriptedAI
void Reset() override
{
boss_the_makerAI(Creature* creature) : ScriptedAI(creature)
_Reset();
if (instance)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
EventMap events;
void Reset() override
{
events.Reset();
if (!instance)
return;
instance->SetData(DATA_THE_MAKER, NOT_STARTED);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_EXPLODING, 6000);
events.ScheduleEvent(EVENT_SPELL_DOMINATION, 120000);
if (!instance)
return;
instance->SetData(DATA_THE_MAKER, IN_PROGRESS);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), false);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER && urand(0, 1))
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
if (!instance)
return;
instance->SetData(DATA_THE_MAKER, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR3), true);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_EXPLODING:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_EXPLODING_BREAKER, false);
events.RepeatEvent(urand(7000, 11000));
break;
case EVENT_SPELL_DOMINATION:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_DOMINATION, false);
events.RepeatEvent(120000);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustEngagedWith(Unit* /*who*/) override
{
return GetBloodFurnaceAI<boss_the_makerAI>(creature);
Talk(SAY_AGGRO);
_JustEngagedWith();
instance->SetData(DATA_THE_MAKER, IN_PROGRESS);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), false);
scheduler.Schedule(6s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_EXPLODING_BEAKER);
context.Repeat(7s, 11s);
}).Schedule(2min, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_DOMINATION);
context.Repeat(2min);
});
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER && urand(0, 1))
{
Talk(SAY_KILL);
}
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
instance->SetData(DATA_THE_MAKER, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR3), true);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
};
void AddSC_boss_the_maker()
{
new boss_the_maker();
RegisterBloodFurnaceCreatureAI(boss_the_maker);
}

View File

@@ -37,124 +37,111 @@ enum Spells
SPELL_DEMONIC_SHIELD = 31901
};
class boss_omor_the_unscarred : public CreatureScript
struct boss_omor_the_unscarred : public BossAI
{
public:
boss_omor_the_unscarred() : CreatureScript("boss_omor_the_unscarred") { }
struct boss_omor_the_unscarredAI : public BossAI
boss_omor_the_unscarred(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
{
boss_omor_the_unscarredAI(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
SetCombatMovement(false);
scheduler.SetValidator([this]
{
SetCombatMovement(false);
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
scheduler.SetValidator([this]
void Reset() override
{
Talk(SAY_WIPE);
_Reset();
_targetGUID.Clear();
ScheduleHealthCheckEvent(21, [&]{
DoCastSelf(SPELL_DEMONIC_SHIELD);
scheduler.Schedule(15s, [this](TaskContext context)
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
Talk(SAY_WIPE);
_Reset();
_targetGUID.Clear();
ScheduleHealthCheckEvent(21, [&]{
DoCastSelf(SPELL_DEMONIC_SHIELD);
scheduler.Schedule(15s, [this](TaskContext context)
{
DoCastSelf(SPELL_DEMONIC_SHIELD);
context.Repeat(15s);
});
});
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
scheduler.Schedule(6s, [this](TaskContext context)
{
if (roll_chance_i(33))
{
Talk(SAY_CURSE);
}
DoCastRandomTarget(SPELL_TREACHEROUS_AURA);
context.Repeat(12s, 18s);
}).Schedule(10s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
}).Schedule(25s, [this](TaskContext context)
{
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
context.Repeat(15s);
});
}
void KilledUnit(Unit*) override
{
if(!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void JustSummoned(Creature* summon) override
{
Talk(SAY_SUMMON);
summons.Summon(summon);
summon->SetInCombatWithZone();
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->GetVictim() || !me->isAttackReady())
return;
if (me->IsWithinMeleeRange(me->GetVictim()))
{
me->GetMotionMaster()->MoveChase(me->GetVictim());
DoMeleeAttackIfReady();
}
else
{
me->GetMotionMaster()->Clear();
me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT, false);
me->resetAttackTimer();
}
}
private:
ObjectGuid _targetGUID;
bool _hasSpoken;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHellfireRampartsAI<boss_omor_the_unscarredAI>(creature);
});
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
scheduler.Schedule(6s, [this](TaskContext context)
{
if (roll_chance_i(33))
{
Talk(SAY_CURSE);
}
DoCastRandomTarget(SPELL_TREACHEROUS_AURA);
context.Repeat(12s, 18s);
}).Schedule(10s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
}).Schedule(25s, [this](TaskContext context)
{
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
context.Repeat(15s);
});
}
void KilledUnit(Unit*) override
{
if(!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void JustSummoned(Creature* summon) override
{
Talk(SAY_SUMMON);
summons.Summon(summon);
summon->SetInCombatWithZone();
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->GetVictim() || !me->isAttackReady())
return;
if (me->IsWithinMeleeRange(me->GetVictim()))
{
me->GetMotionMaster()->MoveChase(me->GetVictim());
DoMeleeAttackIfReady();
}
else
{
me->GetMotionMaster()->Clear();
DoCastVictim(SPELL_SHADOW_BOLT);
me->resetAttackTimer();
}
}
private:
ObjectGuid _targetGUID;
bool _hasSpoken;
};
void AddSC_boss_omor_the_unscarred()
{
new boss_omor_the_unscarred();
RegisterHellfireRampartsCreatureAI(boss_omor_the_unscarred);
}

View File

@@ -21,36 +21,35 @@
enum Says
{
SAY_INTRO = 0,
SAY_WIPE = 0,
SAY_AGGRO = 1,
SAY_KILL = 2,
SAY_DIE = 3,
EMOTE_NAZAN = 0
SAY_INTRO = 0,
SAY_WIPE = 0,
SAY_AGGRO = 1,
SAY_KILL = 2,
SAY_DIE = 3,
EMOTE_NAZAN = 0
};
enum Spells
{
SPELL_FIREBALL = 33793,
SPELL_SUMMON_LIQUID_FIRE = 31706,
SPELL_REVENGE = 19130,
SPELL_REVENGE_H = 40392,
SPELL_CALL_NAZAN = 30693,
SPELL_BELLOWING_ROAR = 39427,
SPELL_CONE_OF_FIRE = 30926
SPELL_FIREBALL = 33793,
SPELL_SUMMON_LIQUID_FIRE = 31706,
SPELL_REVENGE = 19130,
SPELL_CALL_NAZAN = 30693,
SPELL_BELLOWING_ROAR = 39427,
SPELL_CONE_OF_FIRE = 30926
};
enum Misc
{
ACTION_FLY_DOWN = 0,
POINT_MIDDLE = 0,
POINT_FLIGHT = 1
ACTION_FLY_DOWN = 0,
POINT_MIDDLE = 0,
POINT_FLIGHT = 1
};
enum GroupPhase
{
GROUP_PHASE_1 = 0,
GROUP_PHASE_2 = 1
GROUP_PHASE_1 = 0,
GROUP_PHASE_2 = 1
};
const Position NazanPos[3] =
@@ -60,354 +59,302 @@ const Position NazanPos[3] =
{-1373.84f, 1771.57f, 111.0f, 0.0f}
};
class boss_vazruden_the_herald : public CreatureScript
struct boss_vazruden_the_herald : public BossAI
{
public:
boss_vazruden_the_herald() : CreatureScript("boss_vazruden_the_herald") { }
boss_vazruden_the_herald(Creature* creature) : BossAI(creature, DATA_VAZRUDEN) {}
struct boss_vazruden_the_heraldAI : public BossAI
void Reset() override
{
boss_vazruden_the_heraldAI(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
{
}
BossAI::Reset();
me->SetVisible(true);
me->SetReactState(REACT_PASSIVE);
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1372.56f, 1724.31f, 82.967f, 5.3058f);
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1383.39f, 1711.82f, 82.7961f, 5.67232f);
}
void Reset() override
{
BossAI::Reset();
me->SetVisible(true);
me->SetReactState(REACT_PASSIVE);
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1372.56f, 1724.31f, 82.967f, 5.3058f);
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1383.39f, 1711.82f, 82.7961f, 5.67232f);
}
void AttackStart(Unit*) override {}
void AttackStart(Unit*) override
{
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
summon->SetInCombatWithZone();
}
void JustDied(Unit*) override
{
instance->SetBossState(DATA_VAZRUDEN, DONE);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
{
me->SetVisible(false);
me->SummonCreature(NPC_VAZRUDEN, me->GetPositionX(), me->GetPositionY(), 81.2f, 5.46f);
me->SummonCreature(NPC_NAZAN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 5.46f);
}
}
void SummonedCreatureDies(Creature* summon, Unit*) override
{
summons.Despawn(summon);
if (summon->GetEntry() == NPC_HELLFIRE_SENTRY && summons.size() == 0)
{
Talk(SAY_INTRO);
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 85.0f, false);
me->setActive(true);
}
else if (summons.size() == 0)
{
me->KillSelf();
}
}
void SummonedCreatureDespawn(Creature* summon) override
{
summons.Despawn(summon);
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
BossAI::EnterEvadeMode();
}
void SetData(uint32 type, uint32 data) override
{
if (type == 0 && data == 1)
{
summons.DoZoneInCombat(NPC_HELLFIRE_SENTRY);
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (!me->IsVisible() && summons.size() == 0)
BossAI::EnterEvadeMode();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustSummoned(Creature* summon) override
{
return GetHellfireRampartsAI<boss_vazruden_the_heraldAI>(creature);
summons.Summon(summon);
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
{
summon->SetInCombatWithZone();
}
}
void JustDied(Unit*) override
{
instance->SetBossState(DATA_VAZRUDEN, DONE);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
{
me->SetVisible(false);
me->SummonCreature(NPC_VAZRUDEN, me->GetPositionX(), me->GetPositionY(), 81.2f, 5.46f);
me->SummonCreature(NPC_NAZAN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 5.46f);
}
}
void SummonedCreatureDies(Creature* summon, Unit*) override
{
summons.Despawn(summon);
if (summon->GetEntry() == NPC_HELLFIRE_SENTRY && summons.size() == 0)
{
Talk(SAY_INTRO);
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 85.0f, false);
me->setActive(true);
}
else if (summons.size() == 0)
{
me->KillSelf();
}
}
void SummonedCreatureDespawn(Creature* summon) override
{
summons.Despawn(summon);
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
{
BossAI::EnterEvadeMode();
}
}
void SetData(uint32 type, uint32 data) override
{
if (type == 0 && data == 1)
{
summons.DoZoneInCombat(NPC_HELLFIRE_SENTRY);
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (!me->IsVisible() && summons.size() == 0)
{
BossAI::EnterEvadeMode();
}
}
};
class boss_nazan : public CreatureScript
struct boss_nazan : public BossAI
{
public:
boss_nazan() : CreatureScript("boss_nazan") { }
struct boss_nazanAI : public BossAI
boss_nazan(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
{
boss_nazanAI(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
scheduler.SetValidator([this]
{
scheduler.SetValidator([this]
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
me->SetCanFly(true);
me->SetDisableGravity(true);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DespawnOrUnsummon(1);
}
void JustEngagedWith(Unit*) override
{
scheduler.CancelGroup(GROUP_PHASE_2);
scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
{
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
scheduler.DelayAll(7s);
context.Repeat(30s);
}).Schedule(5s, GROUP_PHASE_1, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_FIREBALL);
context.Repeat(4s, 6s);
});
}
void AttackStart(Unit* who) override
{
if (me->IsLevitating())
{
me->Attack(who, true);
}
else
{
ScriptedAI::AttackStart(who);
}
}
void DoAction(int32 param) override
{
if (param == ACTION_FLY_DOWN)
{
Talk(EMOTE_NAZAN);
me->SetReactState(REACT_PASSIVE);
me->InterruptNonMeleeSpells(true);
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 81.2f, false);
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
{
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetReactState(REACT_AGGRESSIVE);
scheduler.CancelGroup(GROUP_PHASE_1);
me->GetMotionMaster()->MoveChase(me->GetVictim());
scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
me->SetCanFly(true);
me->SetDisableGravity(true);
events.Reset();
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DespawnOrUnsummon(1);
}
void JustEngagedWith(Unit*) override
{
scheduler.CancelGroup(GROUP_PHASE_2);
scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
{
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
scheduler.DelayAll(7s);
context.Repeat(30s);
}).Schedule(5s, GROUP_PHASE_1, [this](TaskContext context)
DoCastVictim(SPELL_CONE_OF_FIRE);
context.Repeat(12s);
}).Schedule(6s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_FIREBALL);
context.Repeat(4s, 6s);
});
}
void AttackStart(Unit* who) override
{
if (me->IsLevitating())
me->Attack(who, true);
else
ScriptedAI::AttackStart(who);
}
void DoAction(int32 param) override
{
if (param == ACTION_FLY_DOWN)
if (IsHeroic())
{
Talk(EMOTE_NAZAN);
events.Reset();
me->SetReactState(REACT_PASSIVE);
me->InterruptNonMeleeSpells(true);
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 81.2f, false);
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
{
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetReactState(REACT_AGGRESSIVE);
scheduler.CancelGroup(GROUP_PHASE_1);
me->GetMotionMaster()->MoveChase(me->GetVictim());
scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastVictim(SPELL_CONE_OF_FIRE);
context.Repeat(12s);
}).Schedule(6s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_FIREBALL);
context.Repeat(4s, 6s);
DoCastSelf(SPELL_BELLOWING_ROAR);
context.Repeat(30s);
});
if (IsHeroic())
{
scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastSelf(SPELL_BELLOWING_ROAR);
context.Repeat(30s);
});
}
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->IsLevitating())
DoMeleeAttackIfReady();
}
private:
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHellfireRampartsAI<boss_nazanAI>(creature);
}
};
class boss_vazruden : public CreatureScript
{
public:
boss_vazruden() : CreatureScript("boss_vazruden") { }
struct boss_vazrudenAI : public BossAI
void UpdateAI(uint32 /*diff*/) override
{
boss_vazrudenAI(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
if (!UpdateVictim())
return;
void Reset() override
{
events.Reset();
_nazanCalled = false;
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
Talk(SAY_WIPE);
me->DespawnOrUnsummon(1);
}
void JustEngagedWith(Unit*) override
{
scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
Talk(SAY_AGGRO);
}).Schedule(4s, [this](TaskContext context)
{
DoCastVictim(DUNGEON_MODE(SPELL_REVENGE, SPELL_REVENGE_H));
context.Repeat(6s);
});
}
void KilledUnit(Unit*) override
{
if (!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
{
if (!_nazanCalled && me->HealthBelowPctDamaged(35, damage))
{
_nazanCalled = true;
me->CastSpell(me, SPELL_CALL_NAZAN, true);
}
}
void JustDied(Unit*) override
{
Talk(SAY_DIE);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->IsLevitating())
DoMeleeAttackIfReady();
}
private:
EventMap events;
bool _hasSpoken;
bool _nazanCalled;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHellfireRampartsAI<boss_vazrudenAI>(creature);
}
};
class spell_vazruden_fireball : public SpellScriptLoader
struct boss_vazruden : public BossAI
{
public:
spell_vazruden_fireball() : SpellScriptLoader("spell_vazruden_fireball") { }
class spell_vazruden_fireball_SpellScript : public SpellScript
boss_vazruden(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
{
PrepareSpellScript(spell_vazruden_fireball_SpellScript);
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
scheduler.SetValidator([this]
{
if (Unit* target = GetHitUnit())
target->CastSpell(target, SPELL_SUMMON_LIQUID_FIRE, true);
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_vazruden_fireball_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
void Reset() override
{
return new spell_vazruden_fireball_SpellScript();
_nazanCalled = false;
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
Talk(SAY_WIPE);
me->DespawnOrUnsummon(1);
}
void JustEngagedWith(Unit*) override
{
scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
Talk(SAY_AGGRO);
}).Schedule(4s, [this](TaskContext context)
{
DoCastVictim(SPELL_REVENGE);
context.Repeat(6s);
});
}
void KilledUnit(Unit*) override
{
if (!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
{
if (!_nazanCalled && me->HealthBelowPctDamaged(35, damage))
{
_nazanCalled = true;
DoCastSelf(SPELL_CALL_NAZAN, true);
}
}
void JustDied(Unit*) override
{
Talk(SAY_DIE);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
DoMeleeAttackIfReady();
}
private:
bool _hasSpoken;
bool _nazanCalled;
};
class spell_vazruden_fireball : public SpellScript
{
PrepareSpellScript(spell_vazruden_fireball);
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
{
target->CastSpell(target, SPELL_SUMMON_LIQUID_FIRE, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_vazruden_fireball::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_vazruden_call_nazan : public SpellScriptLoader
class spell_vazruden_call_nazan : public SpellScript
{
public:
spell_vazruden_call_nazan() : SpellScriptLoader("spell_vazruden_call_nazan") { }
PrepareSpellScript(spell_vazruden_call_nazan);
class spell_vazruden_call_nazan_SpellScript : public SpellScript
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
PrepareSpellScript(spell_vazruden_call_nazan_SpellScript);
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
if (Unit* target = GetHitUnit())
{
if (Unit* target = GetHitUnit())
target->GetAI()->DoAction(ACTION_FLY_DOWN);
target->GetAI()->DoAction(ACTION_FLY_DOWN);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_vazruden_call_nazan_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_vazruden_call_nazan_SpellScript();
OnEffectHitTarget += SpellEffectFn(spell_vazruden_call_nazan::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_boss_vazruden_the_herald()
{
new boss_vazruden_the_herald();
new boss_vazruden();
new boss_nazan();
new spell_vazruden_fireball();
new spell_vazruden_call_nazan();
RegisterHellfireRampartsCreatureAI(boss_vazruden_the_herald);
RegisterHellfireRampartsCreatureAI(boss_vazruden);
RegisterHellfireRampartsCreatureAI(boss_nazan);
RegisterSpellScript(spell_vazruden_fireball);
RegisterSpellScript(spell_vazruden_call_nazan);
}

View File

@@ -41,121 +41,110 @@ enum Misc
NPC_HELLFIRE_WATCHER = 17309
};
class boss_watchkeeper_gargolmar : public CreatureScript
struct boss_watchkeeper_gargolmar : public BossAI
{
public:
boss_watchkeeper_gargolmar() : CreatureScript("boss_watchkeeper_gargolmar") { }
struct boss_watchkeeper_gargolmarAI : public BossAI
boss_watchkeeper_gargolmar(Creature* creature) : BossAI(creature, DATA_WATCHKEEPER_GARGOLMAR)
{
boss_watchkeeper_gargolmarAI(Creature* creature) : BossAI(creature, DATA_WATCHKEEPER_GARGOLMAR)
_taunted = false;
scheduler.SetValidator([this]
{
_taunted = false;
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
_Reset();
ScheduleHealthCheckEvent(50, [&]{
Talk(SAY_HEAL);
std::list<Creature*> clist;
me->GetCreaturesWithEntryInRange(clist, 100.0f, NPC_HELLFIRE_WATCHER);
for (std::list<Creature*>::const_iterator itr = clist.begin(); itr != clist.end(); ++itr)
(*itr)->AI()->SetData(NPC_HELLFIRE_WATCHER, 0);
});
ScheduleHealthCheckEvent(20, [&]{
DoCastSelf(SPELL_RETALIATION);
scheduler.Schedule(30s, [this](TaskContext context)
{
DoCastSelf(SPELL_RETALIATION);
context.Repeat(30s);
});
});
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
scheduler.Schedule(5s, [this] (TaskContext context)
{
DoCastVictim(SPELL_MORTAL_WOUND);
context.Repeat(8s);
}).Schedule(3s, [this](TaskContext context)
{
Talk(SAY_SURGE);
if(Unit* target = SelectTarget((SelectTargetMethod::MinDistance), 0))
{
me->CastSpell(target, SPELL_SURGE);
}
context.Repeat(11s);
});
}
void MoveInLineOfSight(Unit* who) override
{
if (!_taunted)
{
if (who->GetTypeId() == TYPEID_PLAYER)
{
_taunted = true;
Talk(SAY_TAUNT);
}
}
BossAI::MoveInLineOfSight(who);
}
void KilledUnit(Unit*) override
{
if (!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
bool _taunted;
bool _hasSpoken;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetHellfireRampartsAI<boss_watchkeeper_gargolmarAI>(creature);
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
_Reset();
ScheduleHealthCheckEvent(50, [&]{
Talk(SAY_HEAL);
std::list<Creature*> clist;
me->GetCreaturesWithEntryInRange(clist, 100.0f, NPC_HELLFIRE_WATCHER);
for (std::list<Creature*>::const_iterator itr = clist.begin(); itr != clist.end(); ++itr)
{
(*itr)->AI()->SetData(NPC_HELLFIRE_WATCHER, 0);
}
});
ScheduleHealthCheckEvent(20, [&]{
DoCastSelf(SPELL_RETALIATION);
scheduler.Schedule(30s, [this](TaskContext context)
{
DoCastSelf(SPELL_RETALIATION);
context.Repeat(30s);
});
});
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
scheduler.Schedule(5s, [this] (TaskContext context)
{
DoCastVictim(SPELL_MORTAL_WOUND);
context.Repeat(8s);
}).Schedule(3s, [this](TaskContext context)
{
Talk(SAY_SURGE);
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
{
me->CastSpell(target, SPELL_SURGE);
}
context.Repeat(11s);
});
}
void MoveInLineOfSight(Unit* who) override
{
if (!_taunted)
{
if (who->GetTypeId() == TYPEID_PLAYER)
{
_taunted = true;
Talk(SAY_TAUNT);
}
}
BossAI::MoveInLineOfSight(who);
}
void KilledUnit(Unit*) override
{
if (!_hasSpoken)
{
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
bool _taunted;
bool _hasSpoken;
};
void AddSC_boss_watchkeeper_gargolmar()
{
new boss_watchkeeper_gargolmar();
RegisterHellfireRampartsCreatureAI(boss_watchkeeper_gargolmar);
}

View File

@@ -52,4 +52,6 @@ inline AI* GetHellfireRampartsAI(T* obj)
return GetInstanceAI<AI>(obj, HellfireRampartsScriptName);
}
#define RegisterHellfireRampartsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetHellfireRampartsAI)
#endif

View File

@@ -20,7 +20,7 @@
#include "ScriptedCreature.h"
#include "shattered_halls.h"
enum eGrandWarlockNethekurse
enum Says
{
SAY_INTRO = 0,
SAY_INTRO_2 = 1,
@@ -30,41 +30,42 @@ enum eGrandWarlockNethekurse
SAY_SHADOW_FISSURE = 5,
SAY_DEATH_COIL = 6,
SAY_SLAY = 7,
SAY_DIE = 8,
SAY_DIE = 8
};
SPELL_DEATH_COIL_N = 30500,
SPELL_DEATH_COIL_H = 35954,
enum Spells
{
SPELL_DEATH_COIL = 30500,
SPELL_DARK_SPIN = 30502,
SPELL_SHADOW_FISSURE = 30496,
SPELL_SHADOW_CLEAVE_N = 30495,
SPELL_SHADOW_SLAM_H = 35953,
SPELL_SHADOW_CLEAVE = 30495,
// Spells used exclusively in RP
SPELL_SHADOW_SEAR = 30735,
SPELL_DEATH_COIL = 30741,
SPELL_SHADOW_FISSURE_RP = 30745,
SPELL_DEATH_COIL_RP = 30741,
SPELL_SHADOW_FISSURE_RP = 30745
};
enum Events
{
EVENT_INTRO = 1,
EVENT_START_ATTACK = 2,
EVENT_STAGE_NONE = 0,
EVENT_STAGE_INTRO = 1,
EVENT_STAGE_TAUNT = 2,
EVENT_STAGE_MAIN = 3,
SETDATA_DATA = 1,
SETDATA_PEON_AGGRO = 1,
SETDATA_PEON_DEATH = 2,
EVENT_STAGE_MAIN = 3
};
enum Creatures
enum Data
{
NPC_PEON = 17083
SETDATA_DATA = 1,
SETDATA_PEON_AGGRO = 1,
SETDATA_PEON_DEATH = 2
};
enum Groups
{
GROUP_RP = 0,
GROUP_RP = 0
};
enum Actions
@@ -74,336 +75,306 @@ enum Actions
ACTION_START_COMBAT = 2,
};
// ########################################################
// Grand Warlock Nethekurse
// ########################################################
float NethekurseIntroPath[4][3] =
{
{184.78966f, 290.3699f, -8.18139f},
{184.78966f, 290.3699f, -8.18139f},
{178.51125f, 278.779022f, -8.183065f},
{171.82281f, 289.97687f, -8.185595f},
{178.51125f, 287.97794f, -8.183065f}
{171.82281f, 289.97687f, -8.185595f},
{178.51125f, 287.97794f, -8.183065f}
};
class boss_grand_warlock_nethekurse : public CreatureScript
struct boss_grand_warlock_nethekurse : public BossAI
{
public:
boss_grand_warlock_nethekurse() : CreatureScript("boss_grand_warlock_nethekurse") { }
struct boss_grand_warlock_nethekurseAI : public BossAI
boss_grand_warlock_nethekurse(Creature* creature) : BossAI(creature, DATA_NETHEKURSE)
{
boss_grand_warlock_nethekurseAI(Creature* creature) : BossAI(creature, DATA_NETHEKURSE)
scheduler.SetValidator([this]
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
EventMap events2;
void Reset() override
EventMap events2;
void Reset() override
{
EventStage = EVENT_STAGE_NONE;
_Reset();
events2.Reset();
ScheduleHealthCheckEvent(25, [&] {
DoCastSelf(SPELL_DARK_SPIN);
});
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
}
void SetData(uint32 data, uint32 value) override
{
if (data != SETDATA_DATA)
return;
switch (value)
{
EventStage = EVENT_STAGE_NONE;
_Reset();
events2.Reset();
case SETDATA_PEON_AGGRO:
if (PeonEngagedCount >= 4)
return;
ScheduleHealthCheckEvent(25, [&] {
DoCastSelf(SPELL_DARK_SPIN);
});
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DIE);
_JustDied();
}
void SetData(uint32 data, uint32 value) override
{
if (data != SETDATA_DATA)
return;
switch (value)
{
case SETDATA_PEON_AGGRO:
if (PeonEngagedCount >= 4)
return;
if (EventStage < EVENT_STAGE_TAUNT)
{
Talk(SAY_PEON_ATTACKED);
}
break;
case SETDATA_PEON_DEATH:
if (PeonKilledCount >= 4)
return;
if (EventStage < EVENT_STAGE_TAUNT)
{
PeonDieRP();
}
if (++PeonKilledCount == 4)
DoAction(ACTION_CANCEL_INTRO);
break;
}
}
void PeonDieRP()
{
me->GetMotionMaster()->Clear();
me->SetFacingTo(4.572762489318847656f);
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD);
Talk(SAY_PEON_DIES);
});
}
void AttackStart(Unit* who) override
{
if (EventStage < EVENT_STAGE_MAIN)
return;
if (me->Attack(who, true))
{
DoStartMovement(who);
CombatEventScheduler();
}
}
void CombatEventScheduler()
{
scheduler.Schedule(12150ms, 19850ms, [this](TaskContext context)
{
if (me->HealthBelowPct(90))
if (EventStage < EVENT_STAGE_TAUNT)
{
DoCastRandomTarget(DUNGEON_MODE(SPELL_DEATH_COIL_N, SPELL_DEATH_COIL_H), 0, 30.0f, true);
Talk(SAY_PEON_ATTACKED);
}
context.Repeat();
}).Schedule(8100ms, 17300ms, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_SHADOW_FISSURE, 0, 60.0f, true);
context.Repeat(8450ms, 9450ms);
}).Schedule(10950ms, 21850ms, [this](TaskContext context)
{
DoCastVictim(DUNGEON_MODE(SPELL_SHADOW_CLEAVE_N, SPELL_SHADOW_SLAM_H));
context.Repeat(1200ms, 23900ms);
});
}
break;
case SETDATA_PEON_DEATH:
if (PeonKilledCount >= 4)
return;
void MoveInLineOfSight(Unit* /*who*/) override
{
if (EventStage == EVENT_STAGE_NONE)
{
if (me->SelectNearestPlayer(30.0f))
if (EventStage < EVENT_STAGE_TAUNT)
{
PeonDieRP();
}
if (++PeonKilledCount == 4)
{
DoAction(ACTION_CANCEL_INTRO);
}
}
break;
}
}
void IntroRP()
void PeonDieRP()
{
me->GetMotionMaster()->Clear();
me->SetFacingTo(4.572762489318847656f);
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext context)
me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD);
Talk(SAY_PEON_DIES);
});
}
void AttackStart(Unit* who) override
{
if (EventStage < EVENT_STAGE_MAIN)
return;
if (me->Attack(who, true))
{
DoStartMovement(who);
CombatEventScheduler();
}
}
void CombatEventScheduler()
{
scheduler.Schedule(12150ms, 19850ms, [this](TaskContext context)
{
if (me->HealthBelowPct(90))
{
me->GetMotionMaster()->Clear();
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
uint32 choicelocation = urand(1, 3);
me->GetMotionMaster()->MoveIdle();
me->GetMotionMaster()->MovePoint(0, NethekurseIntroPath[choicelocation][0], NethekurseIntroPath[choicelocation][1], NethekurseIntroPath[choicelocation][2]);
scheduler.Schedule(2500ms, GROUP_RP, [this, choicelocation](TaskContext /*context*/)
{
CastRandomPeonSpell(choicelocation);
});
});
context.Repeat(16400ms, 28500ms);
});
}
void JustEngagedWith(Unit* /*who*/) override
DoCastRandomTarget(SPELL_DEATH_COIL, 0, 30.0f, true);
}
context.Repeat();
}).Schedule(8100ms, 17300ms, [this](TaskContext context)
{
_JustEngagedWith();
if (EventStage == EVENT_STAGE_NONE)
DoCastRandomTarget(SPELL_SHADOW_FISSURE, 0, 60.0f, true);
context.Repeat(8450ms, 9450ms);
}).Schedule(10950ms, 21850ms, [this](TaskContext context)
{
DoCastVictim(SPELL_SHADOW_CLEAVE);
context.Repeat(1200ms, 23900ms);
});
}
void MoveInLineOfSight(Unit* /*who*/) override
{
if (EventStage == EVENT_STAGE_NONE)
{
if (me->SelectNearestPlayer(30.0f))
{
DoAction(ACTION_CANCEL_INTRO);
CombatEventScheduler();
}
}
}
void CastRandomPeonSpell(uint32 choice)
void IntroRP()
{
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext context)
{
if (choice == 1)
me->GetMotionMaster()->Clear();
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
Talk(SAY_DEATH_COIL);
me->CastSpell(me, SPELL_DEATH_COIL, false);
}
else if (choice == 2)
{
Talk(SAY_SHADOW_FISSURE);
me->CastSpell(me, SPELL_SHADOW_FISSURE_RP, false);
}
else if (choice == 3)
{
Talk(SAY_SHADOW_SEAR);
me->CastSpell(me, SPELL_SHADOW_SEAR, false);
}
uint32 choicelocation = urand(1, 3);
me->GetMotionMaster()->MoveIdle();
me->GetMotionMaster()->MovePoint(0, NethekurseIntroPath[choicelocation][0], NethekurseIntroPath[choicelocation][1], NethekurseIntroPath[choicelocation][2]);
scheduler.Schedule(2500ms, GROUP_RP, [this, choicelocation](TaskContext /*context*/)
{
CastRandomPeonSpell(choicelocation);
});
});
context.Repeat(16400ms, 28500ms);
});
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
if (EventStage == EVENT_STAGE_NONE)
{
DoAction(ACTION_CANCEL_INTRO);
CombatEventScheduler();
}
}
void KilledUnit(Unit* /*victim*/) override
void CastRandomPeonSpell(uint32 choice)
{
if (choice == 1)
{
Talk(SAY_SLAY);
Talk(SAY_DEATH_COIL);
me->CastSpell(me, SPELL_DEATH_COIL_RP, false);
}
void DoAction(int32 action) override
else if (choice == 2)
{
if (action == ACTION_CANCEL_INTRO)
{
introDone = true;
scheduler.CancelGroup(GROUP_RP);
events2.ScheduleEvent(EVENT_START_ATTACK, 1000);
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
me->SetInCombatWithZone();
Talk(SAY_INTRO_2);
me->SetHomePosition(NethekurseIntroPath[3][0], NethekurseIntroPath[3][1], NethekurseIntroPath[3][2], 4.572762489318847656f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
return;
}
Talk(SAY_SHADOW_FISSURE);
me->CastSpell(me, SPELL_SHADOW_FISSURE_RP, false);
}
else if (choice == 3)
{
Talk(SAY_SHADOW_SEAR);
me->CastSpell(me, SPELL_SHADOW_SEAR, false);
}
}
if (action != ACTION_START_INTRO)
{
return;
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_SLAY);
}
if (ATreached == true)
{
return;
}
ATreached = true;
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
events2.ScheduleEvent(EVENT_INTRO, 90000);
Talk(SAY_INTRO);
EventStage = EVENT_STAGE_INTRO;
void DoAction(int32 action) override
{
if (action == ACTION_CANCEL_INTRO)
{
introDone = true;
scheduler.CancelGroup(GROUP_RP);
events2.ScheduleEvent(EVENT_START_ATTACK, 1000);
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
me->SetInCombatWithZone();
IntroRP();
Talk(SAY_INTRO_2);
me->SetHomePosition(NethekurseIntroPath[3][0], NethekurseIntroPath[3][1], NethekurseIntroPath[3][2], 4.572762489318847656f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
return;
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
scheduler.Update(diff);
uint32 eventId = events2.ExecuteEvent();
if (action != ACTION_START_INTRO)
return;
if (EventStage < EVENT_STAGE_MAIN && instance->GetBossState(DATA_NETHEKURSE) == IN_PROGRESS)
if (ATreached == true)
return;
ATreached = true;
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
events2.ScheduleEvent(EVENT_INTRO, 90000);
Talk(SAY_INTRO);
EventStage = EVENT_STAGE_INTRO;
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
me->SetInCombatWithZone();
IntroRP();
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
scheduler.Update(diff);
uint32 eventId = events2.ExecuteEvent();
if (EventStage < EVENT_STAGE_MAIN && instance->GetBossState(DATA_NETHEKURSE) == IN_PROGRESS)
{
if (eventId == EVENT_INTRO)
{
if (eventId == EVENT_INTRO)
{
EventStage = EVENT_STAGE_TAUNT;
}
else if (eventId == EVENT_START_ATTACK)
{
EventStage = EVENT_STAGE_MAIN;
if (Unit* target = me->SelectNearestPlayer(50.0f))
AttackStart(target);
DoAction(ACTION_CANCEL_INTRO);
return;
}
EventStage = EVENT_STAGE_TAUNT;
}
if (!UpdateVictim())
return;
if (EventStage < EVENT_STAGE_MAIN || me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->HealthBelowPct(25))
DoMeleeAttackIfReady();
}
private:
uint8 PeonEngagedCount = 0;
uint8 PeonKilledCount = 0;
uint8 EventStage;
bool introDone;
bool ATreached = false;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShatteredHallsAI<boss_grand_warlock_nethekurseAI>(creature);
}
};
class spell_tsh_shadow_sear : public SpellScriptLoader
{
public:
spell_tsh_shadow_sear() : SpellScriptLoader("spell_tsh_shadow_sear") { }
class spell_tsh_shadow_sear_AuraScript : public AuraScript
{
PrepareAuraScript(spell_tsh_shadow_sear_AuraScript);
void CalculateDamageAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
amount = 0;
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_tsh_shadow_sear_AuraScript::CalculateDamageAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_tsh_shadow_sear_AuraScript();
}
};
class spell_tsh_shadow_bolt : public SpellScriptLoader
{
public:
spell_tsh_shadow_bolt() : SpellScriptLoader("spell_tsh_shadow_bolt") { }
class spell_tsh_shadow_bolt_SpellScript : public SpellScript
{
PrepareSpellScript(spell_tsh_shadow_bolt_SpellScript);
void SelectRandomPlayer(WorldObject*& target)
{
if (Creature* caster = GetCaster()->ToCreature())
else if (eventId == EVENT_START_ATTACK)
{
std::list<Player*> playerList;
Map::PlayerList const& players = caster->GetMap()->GetPlayers();
for (auto itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource()->ToPlayer())
if (player->IsWithinDist(caster, 100.0f) && player->IsAlive())
playerList.push_back(player);
if (!playerList.empty())
target = Acore::Containers::SelectRandomContainerElement(playerList);
EventStage = EVENT_STAGE_MAIN;
if (Unit* target = me->SelectNearestPlayer(50.0f))
{
AttackStart(target);
}
DoAction(ACTION_CANCEL_INTRO);
return;
}
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_tsh_shadow_bolt_SpellScript::SelectRandomPlayer, EFFECT_0, TARGET_UNIT_TARGET_ENEMY);
}
};
if (!UpdateVictim())
return;
SpellScript* GetSpellScript() const override
if (EventStage < EVENT_STAGE_MAIN || me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->HealthBelowPct(25))
DoMeleeAttackIfReady();
}
private:
uint8 PeonEngagedCount = 0;
uint8 PeonKilledCount = 0;
uint8 EventStage;
bool introDone;
bool ATreached = false;
};
class spell_tsh_shadow_sear : public AuraScript
{
PrepareAuraScript(spell_tsh_shadow_sear);
void CalculateDamageAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
return new spell_tsh_shadow_bolt_SpellScript();
amount = 0;
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_tsh_shadow_sear::CalculateDamageAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
class spell_tsh_shadow_bolt : public SpellScript
{
PrepareSpellScript(spell_tsh_shadow_bolt);
void SelectRandomPlayer(WorldObject*& target)
{
if (Creature* caster = GetCaster()->ToCreature())
{
std::list<Player*> playerList;
Map::PlayerList const& players = caster->GetMap()->GetPlayers();
for (auto itr = players.begin(); itr != players.end(); ++itr)
{
if (Player* player = itr->GetSource()->ToPlayer())
{
if (player->IsWithinDist(caster, 100.0f) && player->IsAlive())
{
playerList.push_back(player);
}
}
}
if (!playerList.empty())
{
target = Acore::Containers::SelectRandomContainerElement(playerList);
}
}
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_tsh_shadow_bolt::SelectRandomPlayer, EFFECT_0, TARGET_UNIT_TARGET_ENEMY);
}
};
class at_rp_nethekurse : public AreaTriggerScript
{
public:
at_rp_nethekurse() : AreaTriggerScript
("at_rp_nethekurse") { }
at_rp_nethekurse() : AreaTriggerScript("at_rp_nethekurse") { }
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
{
@@ -427,8 +398,8 @@ public:
void AddSC_boss_grand_warlock_nethekurse()
{
new boss_grand_warlock_nethekurse();
new spell_tsh_shadow_sear();
new spell_tsh_shadow_bolt();
RegisterShatteredHallsCreatureAI(boss_grand_warlock_nethekurse);
RegisterSpellScript(spell_tsh_shadow_sear);
RegisterSpellScript(spell_tsh_shadow_bolt);
new at_rp_nethekurse();
}

View File

@@ -25,10 +25,13 @@ enum Spells
SPELL_FEAR = 30584,
SPELL_THUNDERCLAP = 30633,
SPELL_BEATDOWN = 30618,
SPELL_BURNING_MAUL_N = 30598,
SPELL_BURNING_MAUL_H = 36056,
SPELL_BURNING_MAUL = 30598
};
enum Equip
{
EQUIP_STANDARD = 1,
EQUIP_BURNING_MAUL = 2,
EQUIP_BURNING_MAUL = 2
};
enum Creatures
@@ -50,233 +53,219 @@ enum Events
EVENT_AGGRO_YELL_1 = 1,
EVENT_AGGRO_YELL_2 = 2,
EVENT_AGGRO_YELL_3 = 3,
EVENT_THREAT_YELL_L_1 = 4,
EVENT_THREAT_YELL_L_2 = 5,
EVENT_THREAT_YELL_L_3 = 6,
EVENT_THREAT_YELL_R_1 = 7,
EVENT_KILL_YELL_LEFT = 8,
EVENT_KILL_YELL_RIGHT = 9,
EVENT_DEATH_YELL = 10,
EVENT_DEATH_YELL = 10
};
enum Phase
{
GROUP_NON_BURNING_PHASE = 0,
GROUP_BURNING_PHASE = 1,
GROUP_FULL_PHASE = 2
GROUP_NON_BURNING_PHASE = 0,
GROUP_BURNING_PHASE = 1,
GROUP_FULL_PHASE = 2
};
// ########################################################
// Warbringer_Omrogg
// ########################################################
class boss_warbringer_omrogg : public CreatureScript
struct boss_warbringer_omrogg : public BossAI
{
public:
boss_warbringer_omrogg() : CreatureScript("boss_warbringer_omrogg") { }
struct boss_warbringer_omroggAI : public BossAI
boss_warbringer_omrogg(Creature* creature) : BossAI(creature, DATA_OMROGG)
{
boss_warbringer_omroggAI(Creature* creature) : BossAI(creature, DATA_OMROGG)
scheduler.SetValidator([this]
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
EventMap events2;
Creature* GetLeftHead()
{
return summons.GetCreatureWithEntry(NPC_LEFT_HEAD);
}
Creature* GetRightHead()
{
return summons.GetCreatureWithEntry(NPC_RIGHT_HEAD);
}
void JustEngagedWith(Unit* /*who*/) override
{
me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
if (Creature* LeftHead = GetLeftHead())
{
uint8 aggroYell = urand(EVENT_AGGRO_YELL_1, EVENT_AGGRO_YELL_3);
LeftHead->AI()->Talk(aggroYell - 1);
events2.ScheduleEvent(aggroYell, 3000);
}
EventMap events2;
Creature* GetLeftHead()
_JustEngagedWith();
scheduler.Schedule(500ms, GROUP_FULL_PHASE, [this](TaskContext context)
{
return summons.GetCreatureWithEntry(NPC_LEFT_HEAD);
}
Creature* GetRightHead()
{
return summons.GetCreatureWithEntry(NPC_RIGHT_HEAD);
}
void JustEngagedWith(Unit* /*who*/) override
{
me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
if (Creature* LeftHead = GetLeftHead())
scheduler.Schedule(12100ms, 17300ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context)
{
uint8 aggroYell = urand(EVENT_AGGRO_YELL_1, EVENT_AGGRO_YELL_3);
LeftHead->AI()->Talk(aggroYell - 1);
events2.ScheduleEvent(aggroYell, 3000);
}
_JustEngagedWith();
scheduler.Schedule(500ms, GROUP_FULL_PHASE, [this](TaskContext context)
DoCastAOE(SPELL_THUNDERCLAP);
context.Repeat(17200ms, 24200ms);
}).Schedule(20s, 30s, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
{
scheduler.Schedule(12100ms, 17300ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context)
DoCastSelf(SPELL_BEATDOWN);
me->SetUnitFlag(UNIT_FLAG_PACIFIED);
me->SetReactState(REACT_PASSIVE);
scheduler.Schedule(200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
{
DoCastAOE(SPELL_THUNDERCLAP);
context.Repeat(17200ms, 24200ms);
}).Schedule(20s, 30s, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1);
if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead())
{
head->AI()->Talk(threatYell - 1);
}
events.ScheduleEvent(threatYell, 3000);
DoResetThreatList();
me->AddThreat(target, 2250.0f);
scheduler.Schedule(1200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/)
{
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_PACIFIED);
});
}
}).Schedule(40s, 60s, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_BEATDOWN, false);
me->SetUnitFlag(UNIT_FLAG_PACIFIED);
me->SetReactState(REACT_PASSIVE);
scheduler.Schedule(200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
scheduler.Schedule(1200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCastSelf(SPELL_FEAR);
DoCastSelf(SPELL_BURNING_MAUL);
me->LoadEquipment(EQUIP_BURNING_MAUL);
scheduler.CancelGroup(GROUP_NON_BURNING_PHASE);
scheduler.Schedule(200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/)
{
uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1);
if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead())
head->AI()->Talk(threatYell - 1);
events.ScheduleEvent(threatYell, 3000);
DoResetThreatList();
me->AddThreat(target, 2250.0f);
scheduler.Schedule(1200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/)
me->Yell("%s roars!", LANG_UNIVERSAL);
scheduler.Schedule(2200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/)
{
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_PACIFIED);
});
}
}).Schedule(40s, 60s, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
{
me->SetUnitFlag(UNIT_FLAG_PACIFIED);
me->SetReactState(REACT_PASSIVE);
scheduler.Schedule(1200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_FEAR, false);
DoCastSelf(DUNGEON_MODE(SPELL_BURNING_MAUL_N, SPELL_BURNING_MAUL_H), false);
me->LoadEquipment(EQUIP_BURNING_MAUL);
scheduler.CancelGroup(GROUP_NON_BURNING_PHASE);
scheduler.Schedule(200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/)
{
me->Yell("%s roars!", LANG_UNIVERSAL);
scheduler.Schedule(2200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/)
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1);
if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead())
{
uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1);
if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead())
head->AI()->Talk(threatYell - 1);
events.ScheduleEvent(threatYell, 3000);
DoResetThreatList();
me->AddThreat(target, 2250.0f);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_PACIFIED);
head->AI()->Talk(threatYell - 1);
}
});
});
scheduler.Schedule(4850ms, 8500ms, GROUP_BURNING_PHASE, [this](TaskContext context)
{
DoCastAOE(SPELL_BLAST_WAVE, false);
context.Repeat(4850ms, 8500ms);
}).Schedule(45s, 60s, GROUP_BURNING_PHASE, [this](TaskContext context)
{
me->LoadEquipment(EQUIP_STANDARD);
context.CancelGroup(GROUP_BURNING_PHASE);
scheduler.RescheduleGroup(GROUP_NON_BURNING_PHASE, 5ms);
context.RescheduleGroup(GROUP_NON_BURNING_PHASE, 5ms);
context.RescheduleGroup(GROUP_FULL_PHASE, 1050ms);
events.ScheduleEvent(threatYell, 3000);
DoResetThreatList();
me->AddThreat(target, 2250.0f);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_PACIFIED);
}
});
});
scheduler.Schedule(4850ms, 8500ms, GROUP_BURNING_PHASE, [this](TaskContext context)
{
DoCastAOE(SPELL_BLAST_WAVE, false);
context.Repeat(4850ms, 8500ms);
}).Schedule(45s, 60s, GROUP_BURNING_PHASE, [this](TaskContext context)
{
me->LoadEquipment(EQUIP_STANDARD);
context.CancelGroup(GROUP_BURNING_PHASE);
scheduler.RescheduleGroup(GROUP_NON_BURNING_PHASE, 5ms);
context.RescheduleGroup(GROUP_NON_BURNING_PHASE, 5ms);
context.RescheduleGroup(GROUP_FULL_PHASE, 1050ms);
});
});
});
context.Repeat(130s, 150s);
});
}
context.Repeat(130s, 150s);
});
}
void JustSummoned(Creature* summoned) override
{
summons.Summon(summoned);
}
void KilledUnit(Unit* /*victim*/) override
{
Creature* head = nullptr;
uint32 eventId = EVENT_KILL_YELL_LEFT;
if (urand(0, 1))
{
head = GetLeftHead();
eventId = EVENT_KILL_YELL_LEFT;
}
else
{
head = GetRightHead();
eventId = EVENT_KILL_YELL_RIGHT;
}
if (head)
head->AI()->Talk(eventId - 1);
events2.ScheduleEvent(eventId, 3000);
}
void JustDied(Unit* /*killer*/) override
{
Creature* LeftHead = GetLeftHead();
Creature* RightHead = GetRightHead();
if (!LeftHead || !RightHead)
return;
LeftHead->DespawnOrUnsummon(5000);
RightHead->DespawnOrUnsummon(5000);
LeftHead->AI()->Talk(EVENT_DEATH_YELL - 1);
RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL);
instance->SetBossState(DATA_OMROGG, DONE);
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
scheduler.Update(diff);
switch (uint32 eventId = events2.ExecuteEvent())
{
case EVENT_AGGRO_YELL_1:
case EVENT_AGGRO_YELL_2:
case EVENT_AGGRO_YELL_3:
case EVENT_KILL_YELL_LEFT:
case EVENT_THREAT_YELL_L_1:
case EVENT_THREAT_YELL_L_2:
case EVENT_THREAT_YELL_L_3:
if (Creature* RightHead = GetRightHead())
RightHead->AI()->Talk(eventId - 1);
break;
case EVENT_KILL_YELL_RIGHT:
case EVENT_THREAT_YELL_R_1:
if (Creature* LeftHead = GetLeftHead())
LeftHead->AI()->Talk(eventId - 1);
break;
}
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustSummoned(Creature* summoned) override
{
return GetShatteredHallsAI<boss_warbringer_omroggAI>(creature);
summons.Summon(summoned);
}
void KilledUnit(Unit* /*victim*/) override
{
Creature* head = nullptr;
uint32 eventId = EVENT_KILL_YELL_LEFT;
if (urand(0, 1))
{
head = GetLeftHead();
eventId = EVENT_KILL_YELL_LEFT;
}
else
{
head = GetRightHead();
eventId = EVENT_KILL_YELL_RIGHT;
}
if (head)
{
head->AI()->Talk(eventId - 1);
}
events2.ScheduleEvent(eventId, 3000);
}
void JustDied(Unit* /*killer*/) override
{
Creature* LeftHead = GetLeftHead();
Creature* RightHead = GetRightHead();
if (!LeftHead || !RightHead)
return;
LeftHead->DespawnOrUnsummon(5000);
RightHead->DespawnOrUnsummon(5000);
LeftHead->AI()->Talk(EVENT_DEATH_YELL - 1);
RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL);
instance->SetBossState(DATA_OMROGG, DONE);
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
scheduler.Update(diff);
switch (uint32 eventId = events2.ExecuteEvent())
{
case EVENT_AGGRO_YELL_1:
case EVENT_AGGRO_YELL_2:
case EVENT_AGGRO_YELL_3:
case EVENT_KILL_YELL_LEFT:
case EVENT_THREAT_YELL_L_1:
case EVENT_THREAT_YELL_L_2:
case EVENT_THREAT_YELL_L_3:
if (Creature* RightHead = GetRightHead())
{
RightHead->AI()->Talk(eventId - 1);
}
break;
case EVENT_KILL_YELL_RIGHT:
case EVENT_THREAT_YELL_R_1:
if (Creature* LeftHead = GetLeftHead())
{
LeftHead->AI()->Talk(eventId - 1);
}
break;
}
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
};
class npc_omrogg_heads : public CreatureScript
struct npc_omrogg_heads : public NullCreatureAI
{
public:
npc_omrogg_heads() : CreatureScript("npc_omrogg_heads") { }
struct npc_omrogg_headsAI : public NullCreatureAI
{
npc_omrogg_headsAI(Creature* creature) : NullCreatureAI(creature) { timer = 0; }
npc_omrogg_heads(Creature* creature) : NullCreatureAI(creature)
{
timer = 0;
}
void SetData(uint32 data, uint32 value) override
{
@@ -297,16 +286,10 @@ public:
}
}
uint32 timer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShatteredHallsAI<npc_omrogg_headsAI>(creature);
}
};
void AddSC_boss_warbringer_omrogg()
{
new boss_warbringer_omrogg();
new npc_omrogg_heads();
RegisterShatteredHallsCreatureAI(boss_warbringer_omrogg);
RegisterShatteredHallsCreatureAI(npc_omrogg_heads);
}

View File

@@ -21,170 +21,161 @@
enum Says
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2
};
enum Spells
{
SPELL_BLADE_DANCE = 30739,
SPELL_CHARGE = 25821,
SPELL_SPRINT = 32720,
SPELL_BLADE_DANCE = 30739,
SPELL_CHARGE = 25821,
SPELL_SPRINT = 32720
};
enum Creatures
{
NPC_SHATTERED_ASSASSIN = 17695,
NPC_HEARTHEN_GUARD = 17621,
NPC_SHARPSHOOTER_GUARD = 17622,
NPC_REAVER_GUARD = 17623
NPC_SHATTERED_ASSASSIN = 17695,
NPC_HEARTHEN_GUARD = 17621,
NPC_SHARPSHOOTER_GUARD = 17622,
NPC_REAVER_GUARD = 17623
};
enum Misc
{
EVENT_SPELL_CHARGE = 1,
EVENT_MOVE_TO_NEXT_POINT = 2,
EVENT_BLADE_DANCE = 3,
EVENT_FINISH_BLADE_DANCE = 4
};
float AssassEntrance[3] = { 275.136f, -84.29f, 2.3f }; // y -8
float AssassExit[3] = { 184.233f, -84.29f, 2.3f }; // y -8
float AddsEntrance[3] = { 306.036f, -84.29f, 1.93f };
enum Misc
struct boss_warchief_kargath_bladefist : public BossAI
{
EVENT_CHECK_ROOM = 1,
EVENT_SUMMON_ADDS = 2,
EVENT_SUMMON_ASSASSINS = 3,
EVENT_SPELL_CHARGE = 4,
EVENT_MOVE_TO_NEXT_POINT = 5,
EVENT_BLADE_DANCE = 6,
EVENT_FINISH_BLADE_DANCE = 7
};
class boss_warchief_kargath_bladefist : public CreatureScript
{
public:
boss_warchief_kargath_bladefist() : CreatureScript("boss_warchief_kargath_bladefist") { }
struct boss_warchief_kargath_bladefistAI : public BossAI
boss_warchief_kargath_bladefist(Creature* creature) : BossAI(creature, DATA_KARGATH)
{
boss_warchief_kargath_bladefistAI(Creature* creature) : BossAI(creature, DATA_KARGATH) { }
void InitializeAI() override
scheduler.SetValidator([this]
{
BossAI::InitializeAI();
if (instance)
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
executioner->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void JustDied(Unit* /*killer*/) override
void InitializeAI() override
{
BossAI::InitializeAI();
if (instance)
{
Talk(SAY_DEATH);
_JustDied();
if (instance)
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
executioner->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
events.ScheduleEvent(EVENT_CHECK_ROOM, 5000);
events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000);
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 5000);
events.ScheduleEvent(EVENT_BLADE_DANCE, 30000);
events.ScheduleEvent(EVENT_SPELL_CHARGE, 0);
}
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() != NPC_SHATTERED_ASSASSIN)
summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random, 0));
summons.Summon(summon);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE || id != 1)
return;
me->CastSpell(me, SPELL_BLADE_DANCE, true);
events.ScheduleEvent(EVENT_MOVE_TO_NEXT_POINT, 0);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
{
case EVENT_CHECK_ROOM:
if (me->GetPositionX() > 255 || me->GetPositionX() < 205)
{
EnterEvadeMode();
return;
}
events.ScheduleEvent(EVENT_CHECK_ROOM, 5000);
break;
case EVENT_SUMMON_ASSASSINS:
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] + 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] - 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] + 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] - 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
break;
case EVENT_SUMMON_ADDS:
for (uint8 i = 0; i < 2; ++i)
me->SummonCreature(NPC_HEARTHEN_GUARD + urand(0, 2), AddsEntrance[0], AddsEntrance[1], AddsEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000);
break;
case EVENT_BLADE_DANCE:
events.DelayEvents(10001);
events.ScheduleEvent(EVENT_BLADE_DANCE, 40000);
events.ScheduleEvent(EVENT_MOVE_TO_NEXT_POINT, 0);
events.ScheduleEvent(EVENT_FINISH_BLADE_DANCE, 10000);
events.SetPhase(1);
me->CastSpell(me, SPELL_SPRINT, true);
break;
case EVENT_MOVE_TO_NEXT_POINT:
{
float x = 210 + frand(0.0f, 35.0f);
float y = -65.0f - frand(0.0f, 35.0f);
me->GetMotionMaster()->MovePoint(1, x, y, me->GetPositionZ());
break;
}
case EVENT_FINISH_BLADE_DANCE:
events.SetPhase(0);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveChase(me->GetVictim());
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_CHARGE, 3000);
break;
case EVENT_SPELL_CHARGE:
me->CastSpell(me->GetVictim(), SPELL_CHARGE, false);
break;
executioner->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
if (!events.IsInPhase(1))
DoMeleeAttackIfReady();
}
};
}
CreatureAI* GetAI(Creature* creature) const override
void JustDied(Unit* /*killer*/) override
{
return GetShatteredHallsAI<boss_warchief_kargath_bladefistAI>(creature);
Talk(SAY_DEATH);
_JustDied();
if (instance)
{
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
{
executioner->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
}
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] + 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] - 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] + 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] - 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
}).Schedule(30s, [this](TaskContext context)
{
for (uint8 i = 0; i < 2; ++i)
{
me->SummonCreature(NPC_HEARTHEN_GUARD + urand(0, 2), AddsEntrance[0], AddsEntrance[1], AddsEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
}
context.Repeat(30s);
}).Schedule(30s, [this](TaskContext context)
{
scheduler.DelayAll(10001ms);
context.Repeat(40s);
scheduler.Schedule(1ms, [this](TaskContext /*context*/)
{
float x = 210 + frand(0.0f, 35.0f);
float y = -65.0f - frand(0.0f, 35.0f);
me->GetMotionMaster()->MovePoint(1, x, y, me->GetPositionZ());
}).Schedule(10s, [this](TaskContext /*context*/)
{
//events.SetPhase(0); howToMigrate?
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveChase(me->GetVictim());
if (IsHeroic())
{
scheduler.Schedule(3s, [this](TaskContext context)
{
DoCastVictim(SPELL_CHARGE);
context.Repeat(30s);
});
}
});
//events.SetPhase(1); howToMigrate?
DoCastSelf(SPELL_SPRINT, true);
});
}
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() != NPC_SHATTERED_ASSASSIN)
{
summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random, 0));
}
summons.Summon(summon);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE || id != 1)
return;
me->CastSpell(me, SPELL_BLADE_DANCE, true);
events.ScheduleEvent(EVENT_MOVE_TO_NEXT_POINT, 0);
}
void UpdateAI(uint32 diff) override
{
if (me->GetPositionX() > 255 || me->GetPositionX() < 205)
{
EnterEvadeMode();
return;
}
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (!events.IsInPhase(1)) // howToMigrate?
DoMeleeAttackIfReady();
}
};
void AddSC_boss_warchief_kargath_bladefist()
{
new boss_warchief_kargath_bladefist();
RegisterShatteredHallsCreatureAI(boss_warchief_kargath_bladefist);
}

View File

@@ -73,4 +73,6 @@ inline AI* GetShatteredHallsAI(T* obj)
return GetInstanceAI<AI>(obj, ShatteredHallsLairScriptName);
}
#define RegisterShatteredHallsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetShatteredHallsAI)
#endif