refactor(Core/Scripts): convert Blackrock Mountain scripts to register macros (#25178)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f63a93276e
commit
2c4b7c3cd4
55 changed files with 6659 additions and 7938 deletions
|
|
@ -18,6 +18,7 @@
|
|||
#include "blackrock_depths.h"
|
||||
#include "AreaTriggerScript.h"
|
||||
#include "CreatureScript.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "GameObjectScript.h"
|
||||
#include "GameTime.h"
|
||||
#include "Player.h"
|
||||
|
|
@ -34,93 +35,76 @@ enum IronhandData
|
|||
constexpr Milliseconds IRONHAND_FLAMES_TIMER = 16s;
|
||||
constexpr Milliseconds IRONHAND_FLAMES_TIMER_RAND = 3s;
|
||||
|
||||
class go_shadowforge_brazier : public GameObjectScript
|
||||
struct go_shadowforge_brazier : public GameObjectAI
|
||||
{
|
||||
public:
|
||||
go_shadowforge_brazier() : GameObjectScript("go_shadowforge_brazier") {}
|
||||
go_shadowforge_brazier(GameObject* go) : GameObjectAI(go) {}
|
||||
|
||||
bool OnGossipHello(Player* /*player*/, GameObject* go) override
|
||||
bool GossipHello(Player* /*player*/, bool /*reportUse*/) override
|
||||
{
|
||||
if (InstanceScript* instance = go->GetInstanceScript())
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
{
|
||||
GameObject* northBrazier = ObjectAccessor::GetGameObject(*go, instance->GetGuidData(DATA_SF_BRAZIER_N));
|
||||
GameObject* southBrazier = ObjectAccessor::GetGameObject(*go, instance->GetGuidData(DATA_SF_BRAZIER_S));
|
||||
GameObject* northBrazier = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SF_BRAZIER_N));
|
||||
GameObject* southBrazier = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SF_BRAZIER_S));
|
||||
|
||||
if (!northBrazier || !southBrazier)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// should only happen on first brazier
|
||||
if (instance->GetData(TYPE_LYCEUM) == NOT_STARTED)
|
||||
{
|
||||
instance->SetData(TYPE_LYCEUM, IN_PROGRESS);
|
||||
}
|
||||
|
||||
// Check if the opposite brazier is lit - if it is, open the gates.
|
||||
if ((go->GetGUID() == northBrazier->GetGUID() && southBrazier->GetGoState() == GO_STATE_ACTIVE) || (go->GetGUID() == southBrazier->GetGUID() && northBrazier->GetGoState() == GO_STATE_ACTIVE))
|
||||
if ((me->GetGUID() == northBrazier->GetGUID() && southBrazier->GetGoState() == GO_STATE_ACTIVE) || (me->GetGUID() == southBrazier->GetGUID() && northBrazier->GetGoState() == GO_STATE_ACTIVE))
|
||||
{
|
||||
instance->SetData(TYPE_LYCEUM, DONE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class ironhand_guardian : public CreatureScript
|
||||
struct brd_ironhand_guardian : public CreatureAI
|
||||
{
|
||||
public:
|
||||
ironhand_guardian() : CreatureScript("brd_ironhand_guardian") {}
|
||||
brd_ironhand_guardian(Creature* creature) : CreatureAI(creature) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void SetData(uint32 id, uint32 value) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<ironhand_guardianAI>(creature);
|
||||
if (id == 0)
|
||||
if (value == 0 || value == 1)
|
||||
{
|
||||
_flamesEnabled = (bool) (value);
|
||||
events.ScheduleEvent(SPELL_GOUT_OF_FLAMES, urand(1, IRONHAND_N_GROUPS) * IRONHAND_FLAMES_TIMER / IRONHAND_N_GROUPS);
|
||||
}
|
||||
}
|
||||
|
||||
struct ironhand_guardianAI : public CreatureAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
ironhand_guardianAI(Creature* creature) : CreatureAI(creature) {}
|
||||
bool flames_enabled = false;
|
||||
events.Update(diff);
|
||||
|
||||
void SetData(uint32 id, uint32 value) override
|
||||
if (_flamesEnabled)
|
||||
{
|
||||
if (id == 0)
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
if (value == 0 || value == 1)
|
||||
switch (eventId)
|
||||
{
|
||||
flames_enabled = (bool) (value);
|
||||
events.ScheduleEvent(SPELL_GOUT_OF_FLAMES, urand(1, IRONHAND_N_GROUPS) * IRONHAND_FLAMES_TIMER / IRONHAND_N_GROUPS);
|
||||
case SPELL_GOUT_OF_FLAMES:
|
||||
DoCast(SPELL_GOUT_OF_FLAMES);
|
||||
events.RescheduleEvent(SPELL_GOUT_OF_FLAMES, IRONHAND_FLAMES_TIMER - IRONHAND_FLAMES_TIMER_RAND, IRONHAND_FLAMES_TIMER + IRONHAND_FLAMES_TIMER_RAND);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
if (flames_enabled)
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_GOUT_OF_FLAMES:
|
||||
DoCast(SPELL_GOUT_OF_FLAMES);
|
||||
events.RescheduleEvent(SPELL_GOUT_OF_FLAMES, IRONHAND_FLAMES_TIMER - IRONHAND_FLAMES_TIMER_RAND, IRONHAND_FLAMES_TIMER + IRONHAND_FLAMES_TIMER_RAND);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EventMap events;
|
||||
};
|
||||
private:
|
||||
bool _flamesEnabled = false;
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
struct WaveCreature
|
||||
|
|
@ -159,13 +143,10 @@ public:
|
|||
{
|
||||
time_t now = GameTime::GetGameTime().count();
|
||||
if (instance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || instance->GetData(TYPE_RING_OF_LAW) == DONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (now - instance->GetData(DATA_TIME_RING_FAIL) < 2 * 60) // in case of wipe, so people can rez.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->SetData(TYPE_RING_OF_LAW, IN_PROGRESS);
|
||||
return true;
|
||||
|
|
@ -185,249 +166,232 @@ enum GrimstoneTexts
|
|||
SAY_TEXT6 = 5
|
||||
};
|
||||
|
||||
class npc_grimstone : public CreatureScript
|
||||
struct npc_grimstone : public npc_escortAI
|
||||
{
|
||||
public:
|
||||
npc_grimstone() : CreatureScript("npc_grimstone") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
npc_grimstone(Creature* creature) : npc_escortAI(creature), summons(me)
|
||||
{
|
||||
return GetBlackrockDepthsAI<npc_grimstoneAI>(creature);
|
||||
instance = creature->GetInstanceScript();
|
||||
MobSpawnId = instance ? instance->GetData(DATA_ARENA_MOBS) : urand(0, 5);
|
||||
BossSpawnId = instance ? instance->GetData(DATA_ARENA_BOSS) : urand(0, 5);
|
||||
eventPhase = 0;
|
||||
eventTimer = 1000;
|
||||
resetTimer = 0;
|
||||
theldrenEvent = false;
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
struct npc_grimstoneAI : public npc_escortAI
|
||||
InstanceScript* instance;
|
||||
SummonList summons;
|
||||
|
||||
uint8 eventPhase;
|
||||
uint32 eventTimer;
|
||||
uint32 resetTimer;
|
||||
uint8 MobSpawnId;
|
||||
uint8 BossSpawnId;
|
||||
bool theldrenEvent;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
npc_grimstoneAI(Creature* creature) : npc_escortAI(creature), summons(me)
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (Unit* target = SelectTargetFromPlayerList(100.0f))
|
||||
summon->AI()->AttackStart(target);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit*) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
// All Summons killed, next phase
|
||||
if (summons.empty())
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
MobSpawnId = instance ? instance->GetData(DATA_ARENA_MOBS) : urand(0, 5);
|
||||
BossSpawnId = instance ? instance->GetData(DATA_ARENA_BOSS) : urand(0, 5);
|
||||
eventPhase = 0;
|
||||
eventTimer = 1000;
|
||||
resetTimer = 0;
|
||||
theldrenEvent = false;
|
||||
summons.DespawnAll();
|
||||
eventTimer = 5000;
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
SummonList summons;
|
||||
|
||||
uint8 eventPhase;
|
||||
uint32 eventTimer;
|
||||
uint32 resetTimer;
|
||||
uint8 MobSpawnId;
|
||||
uint8 BossSpawnId;
|
||||
bool theldrenEvent;
|
||||
|
||||
void Reset() override
|
||||
void WaypointReached(uint32 waypointId) override
|
||||
{
|
||||
switch (waypointId)
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (Unit* target = SelectTargetFromPlayerList(100.0f))
|
||||
summon->AI()->AttackStart(target);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit*) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
// All Summons killed, next phase
|
||||
if (summons.empty())
|
||||
{
|
||||
resetTimer = 0;
|
||||
case 0:
|
||||
Talk(SAY_TEXT1);
|
||||
SetEscortPaused(true);
|
||||
eventTimer = 5000;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
Talk(SAY_TEXT2);
|
||||
SetEscortPaused(true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 2:
|
||||
SetEscortPaused(true);
|
||||
break;
|
||||
case 3:
|
||||
Talk(SAY_TEXT3);
|
||||
break;
|
||||
case 4:
|
||||
Talk(SAY_TEXT4);
|
||||
SetEscortPaused(true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 5:
|
||||
if (instance)
|
||||
{
|
||||
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_GRIMSTONE, me);
|
||||
instance->SetData(TYPE_RING_OF_LAW, DONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WaypointReached(uint32 waypointId) override
|
||||
void HandleGameObject(uint32 id, bool open)
|
||||
{
|
||||
instance->HandleGameObject(instance->GetGuidData(id), open);
|
||||
}
|
||||
|
||||
void SummonBoss()
|
||||
{
|
||||
if (me->FindNearestGameObject(GO_BANNER_OF_PROVOCATION, 100.0f))
|
||||
{
|
||||
switch (waypointId)
|
||||
theldrenEvent = true;
|
||||
me->SummonCreature(NPC_THELDREN, 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
uint8 rand = urand(0, 4);
|
||||
for (uint8 i = rand; i < rand + 4; ++i)
|
||||
me->SummonCreature(theldrenTeam[i], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
}
|
||||
else
|
||||
me->SummonCreature(RingBoss[BossSpawnId], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
resetTimer = 30000;
|
||||
}
|
||||
|
||||
bool updateReset(uint32 diff)
|
||||
{
|
||||
// as long as the summoned creatures have someone to attack, we reset the timer.
|
||||
// once they don't find anyone, the timer will count down until it is smaller than diff and reset.
|
||||
bool doReset = false;
|
||||
if (resetTimer > 0)
|
||||
{
|
||||
for (auto const& sum : summons)
|
||||
{
|
||||
case 0:
|
||||
Talk(SAY_TEXT1);
|
||||
SetEscortPaused(true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 1:
|
||||
Talk(SAY_TEXT2);
|
||||
SetEscortPaused(true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 2:
|
||||
SetEscortPaused(true);
|
||||
break;
|
||||
case 3:
|
||||
Talk(SAY_TEXT3);
|
||||
break;
|
||||
case 4:
|
||||
Talk(SAY_TEXT4);
|
||||
SetEscortPaused(true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 5:
|
||||
if (instance)
|
||||
if (Creature* creature = ObjectAccessor::GetCreature(*me, sum))
|
||||
{
|
||||
if (creature->IsAlive() && creature->GetVictim())
|
||||
{
|
||||
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_GRIMSTONE, me);
|
||||
instance->SetData(TYPE_RING_OF_LAW, DONE);
|
||||
resetTimer = 30000;
|
||||
break; // only need to find one.
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resetTimer -= diff;
|
||||
if (resetTimer <= diff)
|
||||
doReset = true;
|
||||
}
|
||||
return doReset;
|
||||
}
|
||||
|
||||
void SpawnWave(uint32 mobId)
|
||||
{
|
||||
for (uint32 i = 0; i < RingMobs[mobId].amount; i++)
|
||||
me->SummonCreature(RingMobs[mobId].entry, 608.960f + 0.4f * i, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
resetTimer = 30000;
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
// reset if our mobs don't have a target.
|
||||
if (updateReset(diff))
|
||||
{
|
||||
summons.DespawnAll();
|
||||
HandleGameObject(DATA_ARENA4, true);
|
||||
HandleGameObject(DATA_ARENA3, false);
|
||||
HandleGameObject(DATA_ARENA2, false);
|
||||
HandleGameObject(DATA_ARENA1, false);
|
||||
instance->SetData(TYPE_RING_OF_LAW, FAIL);
|
||||
}
|
||||
|
||||
void HandleGameObject(uint32 id, bool open)
|
||||
if (eventTimer)
|
||||
{
|
||||
instance->HandleGameObject(instance->GetGuidData(id), open);
|
||||
}
|
||||
|
||||
void SummonBoss()
|
||||
{
|
||||
if (me->FindNearestGameObject(GO_BANNER_OF_PROVOCATION, 100.0f))
|
||||
if (eventTimer <= diff)
|
||||
{
|
||||
theldrenEvent = true;
|
||||
me->SummonCreature(NPC_THELDREN, 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
uint8 rand = urand(0, 4);
|
||||
for (uint8 i = rand; i < rand + 4; ++i)
|
||||
me->SummonCreature(theldrenTeam[i], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
switch (eventPhase)
|
||||
{
|
||||
case 0:
|
||||
Talk(SAY_TEXT5);
|
||||
HandleGameObject(DATA_ARENA4, false);
|
||||
me->SetWalk(true);
|
||||
Start(false);
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 1:
|
||||
SetEscortPaused(false);
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 2:
|
||||
eventTimer = 2000;
|
||||
break;
|
||||
case 3:
|
||||
HandleGameObject(DATA_ARENA1, true);
|
||||
eventTimer = 3000;
|
||||
break;
|
||||
case 4:
|
||||
SetEscortPaused(false);
|
||||
me->SetVisible(false);
|
||||
SpawnWave(MobSpawnId); // wave 1
|
||||
eventTimer = 15000;
|
||||
break;
|
||||
case 5:
|
||||
SpawnWave(MobSpawnId); // wave 2
|
||||
eventTimer = 0; // will be set from SummonedCreatureDies
|
||||
break;
|
||||
case 6:
|
||||
me->SetVisible(true);
|
||||
HandleGameObject(DATA_ARENA1, false);
|
||||
Talk(SAY_TEXT6);
|
||||
SetEscortPaused(false);
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 7:
|
||||
HandleGameObject(DATA_ARENA2, true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 8:
|
||||
me->SetVisible(false);
|
||||
SummonBoss();
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 9:
|
||||
if (theldrenEvent)
|
||||
{
|
||||
// All objects are removed from world once tempsummons despawn, so have a player spawn it instead.
|
||||
Player* player = me->SelectNearestPlayer(100.0f);
|
||||
if (GameObject* go = player->SummonGameObject(GO_ARENA_SPOILS, 596.48f, -187.91f, -54.14f, 4.9f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
|
||||
go->SetOwnerGUID(ObjectGuid::Empty);
|
||||
|
||||
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
||||
itr->GetSource()->KilledMonsterCredit(16166);
|
||||
}
|
||||
|
||||
HandleGameObject(DATA_ARENA2, false);
|
||||
HandleGameObject(DATA_ARENA3, true);
|
||||
HandleGameObject(DATA_ARENA4, true);
|
||||
SetEscortPaused(false);
|
||||
break;
|
||||
}
|
||||
++eventPhase;
|
||||
}
|
||||
else
|
||||
me->SummonCreature(RingBoss[BossSpawnId], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
resetTimer = 30000;
|
||||
eventTimer -= diff;
|
||||
}
|
||||
|
||||
bool updateReset(uint32 diff)
|
||||
{
|
||||
// as long as the summoned creatures have someone to attack, we reset the timer.
|
||||
// once they don't find anyone, the timer will count down until it is smaller than diff and reset.
|
||||
bool doReset = false;
|
||||
if (resetTimer > 0)
|
||||
{
|
||||
for (auto const& sum : summons)
|
||||
{
|
||||
if (Creature* creature = ObjectAccessor::GetCreature(*me, sum))
|
||||
{
|
||||
if (creature->IsAlive() && creature->GetVictim())
|
||||
{
|
||||
resetTimer = 30000;
|
||||
break; // only need to find one.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetTimer -= diff;
|
||||
if (resetTimer <= diff)
|
||||
{
|
||||
doReset = true;
|
||||
}
|
||||
}
|
||||
return doReset;
|
||||
}
|
||||
|
||||
void SpawnWave(uint32 mobId)
|
||||
{
|
||||
for (uint32 i = 0; i < RingMobs[mobId].amount; i++)
|
||||
{
|
||||
me->SummonCreature(RingMobs[mobId].entry, 608.960f + 0.4f * i, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
}
|
||||
resetTimer = 30000;
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
// reset if our mobs don't have a target.
|
||||
if (updateReset(diff))
|
||||
{
|
||||
summons.DespawnAll();
|
||||
HandleGameObject(DATA_ARENA4, true);
|
||||
HandleGameObject(DATA_ARENA3, false);
|
||||
HandleGameObject(DATA_ARENA2, false);
|
||||
HandleGameObject(DATA_ARENA1, false);
|
||||
instance->SetData(TYPE_RING_OF_LAW, FAIL);
|
||||
}
|
||||
|
||||
if (eventTimer)
|
||||
{
|
||||
if (eventTimer <= diff)
|
||||
{
|
||||
switch (eventPhase)
|
||||
{
|
||||
case 0:
|
||||
Talk(SAY_TEXT5);
|
||||
HandleGameObject(DATA_ARENA4, false);
|
||||
me->SetWalk(true);
|
||||
Start(false);
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 1:
|
||||
SetEscortPaused(false);
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 2:
|
||||
eventTimer = 2000;
|
||||
break;
|
||||
case 3:
|
||||
HandleGameObject(DATA_ARENA1, true);
|
||||
eventTimer = 3000;
|
||||
break;
|
||||
case 4:
|
||||
SetEscortPaused(false);
|
||||
me->SetVisible(false);
|
||||
SpawnWave(MobSpawnId); // wave 1
|
||||
eventTimer = 15000;
|
||||
break;
|
||||
case 5:
|
||||
SpawnWave(MobSpawnId); // wave 2
|
||||
eventTimer = 0; // will be set from SummonedCreatureDies
|
||||
break;
|
||||
case 6:
|
||||
me->SetVisible(true);
|
||||
HandleGameObject(DATA_ARENA1, false);
|
||||
Talk(SAY_TEXT6);
|
||||
SetEscortPaused(false);
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 7:
|
||||
HandleGameObject(DATA_ARENA2, true);
|
||||
eventTimer = 5000;
|
||||
break;
|
||||
case 8:
|
||||
me->SetVisible(false);
|
||||
SummonBoss();
|
||||
eventTimer = 0;
|
||||
break;
|
||||
case 9:
|
||||
if (theldrenEvent)
|
||||
{
|
||||
// All objects are removed from world once tempsummons despawn, so have a player spawn it instead.
|
||||
Player* player = me->SelectNearestPlayer(100.0f);
|
||||
if (GameObject* go = player->SummonGameObject(GO_ARENA_SPOILS, 596.48f, -187.91f, -54.14f, 4.9f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
|
||||
{
|
||||
go->SetOwnerGUID(ObjectGuid::Empty);
|
||||
}
|
||||
|
||||
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
||||
itr->GetSource()->KilledMonsterCredit(16166);
|
||||
}
|
||||
|
||||
HandleGameObject(DATA_ARENA2, false);
|
||||
HandleGameObject(DATA_ARENA3, true);
|
||||
HandleGameObject(DATA_ARENA4, true);
|
||||
SetEscortPaused(false);
|
||||
break;
|
||||
}
|
||||
++eventPhase;
|
||||
}
|
||||
else
|
||||
eventTimer -= diff;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// npc_phalanx
|
||||
|
|
@ -438,67 +402,53 @@ enum PhalanxSpells
|
|||
SPELL_MIGHTYBLOW = 14099
|
||||
};
|
||||
|
||||
class npc_phalanx : public CreatureScript
|
||||
struct npc_phalanx : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_phalanx() : CreatureScript("npc_phalanx") { }
|
||||
npc_phalanx(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockDepthsAI<npc_phalanxAI>(creature);
|
||||
_thunderClapTimer = 12000;
|
||||
_fireballVolleyTimer = 0;
|
||||
_mightyBlowTimer = 15000;
|
||||
}
|
||||
|
||||
struct npc_phalanxAI : public ScriptedAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
npc_phalanxAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
uint32 ThunderClap_Timer;
|
||||
uint32 FireballVolley_Timer;
|
||||
uint32 MightyBlow_Timer;
|
||||
|
||||
void Reset() override
|
||||
if (_thunderClapTimer <= diff)
|
||||
{
|
||||
ThunderClap_Timer = 12000;
|
||||
FireballVolley_Timer = 0;
|
||||
MightyBlow_Timer = 15000;
|
||||
DoCastVictim(SPELL_THUNDERCLAP);
|
||||
_thunderClapTimer = 10000;
|
||||
}
|
||||
else _thunderClapTimer -= diff;
|
||||
|
||||
if (HealthBelowPct(51))
|
||||
{
|
||||
if (_fireballVolleyTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FIREBALLVOLLEY);
|
||||
_fireballVolleyTimer = 15000;
|
||||
}
|
||||
else _fireballVolleyTimer -= diff;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
if (_mightyBlowTimer <= diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//ThunderClap_Timer
|
||||
if (ThunderClap_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_THUNDERCLAP);
|
||||
ThunderClap_Timer = 10000;
|
||||
}
|
||||
else ThunderClap_Timer -= diff;
|
||||
|
||||
//FireballVolley_Timer
|
||||
if (HealthBelowPct(51))
|
||||
{
|
||||
if (FireballVolley_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FIREBALLVOLLEY);
|
||||
FireballVolley_Timer = 15000;
|
||||
}
|
||||
else FireballVolley_Timer -= diff;
|
||||
}
|
||||
|
||||
//MightyBlow_Timer
|
||||
if (MightyBlow_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_MIGHTYBLOW);
|
||||
MightyBlow_Timer = 10000;
|
||||
}
|
||||
else MightyBlow_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
DoCastVictim(SPELL_MIGHTYBLOW);
|
||||
_mightyBlowTimer = 10000;
|
||||
}
|
||||
};
|
||||
else _mightyBlowTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _thunderClapTimer;
|
||||
uint32 _fireballVolleyTimer;
|
||||
uint32 _mightyBlowTimer;
|
||||
};
|
||||
|
||||
// npc_lokhtos_darkbargainer
|
||||
|
|
@ -518,12 +468,11 @@ enum LokhtosSpells
|
|||
SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059
|
||||
};
|
||||
|
||||
class npc_lokhtos_darkbargainer : public CreatureScript
|
||||
struct npc_lokhtos_darkbargainer : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_lokhtos_darkbargainer() : CreatureScript("npc_lokhtos_darkbargainer") { }
|
||||
npc_lokhtos_darkbargainer(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
|
|
@ -532,32 +481,26 @@ public:
|
|||
player->CastSpell(player, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false);
|
||||
}
|
||||
if (action == GOSSIP_ACTION_TRADE)
|
||||
player->GetSession()->SendListInventory(creature->GetGUID());
|
||||
|
||||
return true;
|
||||
player->GetSession()->SendListInventory(me->GetGUID());
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
if (creature->IsQuestGiver())
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
if (me->IsQuestGiver())
|
||||
player->PrepareQuestMenu(me->GetGUID());
|
||||
|
||||
if (creature->IsVendor() && player->GetReputationRank(59) >= REP_FRIENDLY)
|
||||
if (me->IsVendor() && player->GetReputationRank(59) >= REP_FRIENDLY)
|
||||
AddGossipItemFor(player, 4781, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
|
||||
if (player->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 &&
|
||||
!player->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) &&
|
||||
player->HasItemCount(ITEM_SULFURON_INGOT))
|
||||
{
|
||||
AddGossipItemFor(player, 4781, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
}
|
||||
|
||||
if (player->GetReputationRank(59) < REP_FRIENDLY)
|
||||
SendGossipMenuFor(player, 3673, creature->GetGUID());
|
||||
SendGossipMenuFor(player, 3673, me->GetGUID());
|
||||
else
|
||||
SendGossipMenuFor(player, 3677, creature->GetGUID());
|
||||
|
||||
return true;
|
||||
SendGossipMenuFor(player, 3677, me->GetGUID());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -577,19 +520,29 @@ enum RocknotQuests
|
|||
QUEST_ALE = 4295
|
||||
};
|
||||
|
||||
class npc_rocknot : public CreatureScript
|
||||
struct npc_rocknot : public npc_escortAI
|
||||
{
|
||||
public:
|
||||
npc_rocknot() : CreatureScript("npc_rocknot") { }
|
||||
|
||||
bool OnQuestReward(Player* /*player*/, Creature* creature, Quest const* quest, uint32 /*item*/) override
|
||||
npc_rocknot(Creature* creature) : npc_escortAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (HasEscortState(STATE_ESCORT_ESCORTING))
|
||||
return;
|
||||
|
||||
_breakKegTimer = 0;
|
||||
_breakDoorTimer = 0;
|
||||
}
|
||||
|
||||
void sQuestReward(Player* /*player*/, Quest const* quest, uint32 /*opt*/) override
|
||||
{
|
||||
InstanceScript* instance = creature->GetInstanceScript();
|
||||
if (!instance)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (instance->GetData(TYPE_BAR) == DONE || instance->GetData(TYPE_BAR) == SPECIAL)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (quest->GetQuestId() == QUEST_ALE)
|
||||
{
|
||||
|
|
@ -601,120 +554,92 @@ public:
|
|||
//keep track of amount in instance script, returns SPECIAL if amount ok and event in progress
|
||||
if (instance->GetData(TYPE_BAR) == SPECIAL)
|
||||
{
|
||||
creature->AI()->Talk(SAY_GOT_BEER);
|
||||
creature->CastSpell(creature, SPELL_DRUNKEN_RAGE, false);
|
||||
|
||||
if (npc_escortAI* escortAI = CAST_AI(npc_rocknot::npc_rocknotAI, creature->AI()))
|
||||
{
|
||||
creature->SetWalk(true);
|
||||
escortAI->Start(false);
|
||||
}
|
||||
Talk(SAY_GOT_BEER);
|
||||
me->CastSpell(me, SPELL_DRUNKEN_RAGE, false);
|
||||
me->SetWalk(true);
|
||||
Start(false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void DoGo(uint32 id, uint32 state)
|
||||
{
|
||||
return GetBlackrockDepthsAI<npc_rocknotAI>(creature);
|
||||
if (GameObject* go = instance->instance->GetGameObject(instance->GetGuidData(id)))
|
||||
go->SetGoState((GOState)state);
|
||||
}
|
||||
|
||||
struct npc_rocknotAI : public npc_escortAI
|
||||
void WaypointReached(uint32 waypointId) override
|
||||
{
|
||||
npc_rocknotAI(Creature* creature) : npc_escortAI(creature)
|
||||
switch (waypointId)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
case 1:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
||||
break;
|
||||
case 2:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
|
||||
break;
|
||||
case 3:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
|
||||
break;
|
||||
case 4:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
||||
break;
|
||||
case 5:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
||||
_breakKegTimer = 2000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 BreakKeg_Timer;
|
||||
uint32 BreakDoor_Timer;
|
||||
|
||||
void Reset() override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_breakKegTimer)
|
||||
{
|
||||
if (HasEscortState(STATE_ESCORT_ESCORTING))
|
||||
return;
|
||||
|
||||
BreakKeg_Timer = 0;
|
||||
BreakDoor_Timer = 0;
|
||||
}
|
||||
|
||||
void DoGo(uint32 id, uint32 state)
|
||||
{
|
||||
if (GameObject* go = instance->instance->GetGameObject(instance->GetGuidData(id)))
|
||||
go->SetGoState((GOState)state);
|
||||
}
|
||||
|
||||
void WaypointReached(uint32 waypointId) override
|
||||
{
|
||||
switch (waypointId)
|
||||
if (_breakKegTimer <= diff)
|
||||
{
|
||||
case 1:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
||||
break;
|
||||
case 2:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
|
||||
break;
|
||||
case 3:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
|
||||
break;
|
||||
case 4:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
||||
break;
|
||||
case 5:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
||||
BreakKeg_Timer = 2000;
|
||||
break;
|
||||
DoGo(DATA_GO_BAR_KEG, 0);
|
||||
_breakKegTimer = 0;
|
||||
_breakDoorTimer = 1000;
|
||||
}
|
||||
else _breakKegTimer -= diff;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
if (_breakDoorTimer)
|
||||
{
|
||||
if (BreakKeg_Timer)
|
||||
if (_breakDoorTimer <= diff)
|
||||
{
|
||||
if (BreakKeg_Timer <= diff)
|
||||
{
|
||||
DoGo(DATA_GO_BAR_KEG, 0);
|
||||
BreakKeg_Timer = 0;
|
||||
BreakDoor_Timer = 1000;
|
||||
}
|
||||
else BreakKeg_Timer -= diff;
|
||||
DoGo(DATA_GO_BAR_DOOR, 2);
|
||||
DoGo(DATA_GO_BAR_KEG_TRAP, 0); //doesn't work very well, leaving code here for future
|
||||
//spell by trap has effect61, this indicate the bar go hostile
|
||||
|
||||
if (Unit* tmp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PHALANX)))
|
||||
tmp->SetFaction(FACTION_MONSTER);
|
||||
|
||||
//for later, this event(s) has alot more to it.
|
||||
//optionally, DONE can trigger bar to go hostile.
|
||||
instance->SetData(TYPE_BAR, DONE);
|
||||
|
||||
_breakDoorTimer = 0;
|
||||
}
|
||||
|
||||
if (BreakDoor_Timer)
|
||||
{
|
||||
if (BreakDoor_Timer <= diff)
|
||||
{
|
||||
DoGo(DATA_GO_BAR_DOOR, 2);
|
||||
DoGo(DATA_GO_BAR_KEG_TRAP, 0); //doesn't work very well, leaving code here for future
|
||||
//spell by trap has effect61, this indicate the bar go hostile
|
||||
|
||||
if (Unit* tmp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PHALANX)))
|
||||
tmp->SetFaction(FACTION_MONSTER);
|
||||
|
||||
//for later, this event(s) has alot more to it.
|
||||
//optionally, DONE can trigger bar to go hostile.
|
||||
instance->SetData(TYPE_BAR, DONE);
|
||||
|
||||
BreakDoor_Timer = 0;
|
||||
}
|
||||
else BreakDoor_Timer -= diff;
|
||||
}
|
||||
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
else _breakDoorTimer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 _breakKegTimer;
|
||||
uint32 _breakDoorTimer;
|
||||
};
|
||||
|
||||
void AddSC_blackrock_depths()
|
||||
{
|
||||
new go_shadowforge_brazier();
|
||||
RegisterBlackrockDepthsGameObjectAI(go_shadowforge_brazier);
|
||||
new at_ring_of_law();
|
||||
new npc_grimstone();
|
||||
new npc_phalanx();
|
||||
new npc_lokhtos_darkbargainer();
|
||||
new npc_rocknot();
|
||||
new ironhand_guardian();
|
||||
RegisterBlackrockDepthsCreatureAI(npc_grimstone);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_phalanx);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_lokhtos_darkbargainer);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_rocknot);
|
||||
RegisterBlackrockDepthsCreatureAI(brd_ironhand_guardian);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,4 +151,7 @@ inline AI* GetBlackrockDepthsAI(T* obj)
|
|||
return GetInstanceAI<AI>(obj, BRDScriptName);
|
||||
}
|
||||
|
||||
#define RegisterBlackrockDepthsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackrockDepthsAI)
|
||||
#define RegisterBlackrockDepthsGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetBlackrockDepthsAI)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,219 +50,184 @@ const Position SummonPositions[7] =
|
|||
|
||||
std::vector<int> gobjectDwarfRunesEntry { 170578, 170579, 170580, 170581, 170582, 170583, 170584 };
|
||||
|
||||
class boss_ambassador_flamelash : public CreatureScript
|
||||
struct boss_ambassador_flamelash : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_ambassador_flamelash() : CreatureScript("boss_ambassador_flamelash") { }
|
||||
boss_ambassador_flamelash(Creature* creature) : BossAI(creature, BOSS_AMBASSADOR_FLAMELASH) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_ambassador_flamelashAI>(creature);
|
||||
switch (param)
|
||||
{
|
||||
case EVENT_SUMMON_SPIRITS:
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 12s, 14s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct boss_ambassador_flamelashAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_ambassador_flamelashAI(Creature* creature) : BossAI(creature, BOSS_AMBASSADOR_FLAMELASH), summons(me) { }
|
||||
_Reset();
|
||||
TurnRunes(false);
|
||||
_foundValidPosition = false;
|
||||
_validPosition.clear();
|
||||
}
|
||||
|
||||
EventMap _events;
|
||||
void TurnRunes(bool mode)
|
||||
{
|
||||
// Active makes the runes burn, ready turns them off
|
||||
GOState state = mode ? GO_STATE_ACTIVE : GO_STATE_READY;
|
||||
|
||||
// This will help reseting the boss
|
||||
SummonList summons;
|
||||
for (int RuneEntry : gobjectDwarfRunesEntry)
|
||||
if (GameObject* dwarfRune = me->FindNearestGameObject(RuneEntry, 200.0f))
|
||||
dwarfRune->SetGoState(state);
|
||||
}
|
||||
|
||||
// This will allow to find a valid position to spawn them
|
||||
std::vector<int> validPosition;
|
||||
bool foundValidPosition = false;
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 2s);
|
||||
|
||||
void JustSummoned(Creature* cr) override { summons.Summon(cr); }
|
||||
// Spawn 7 Embers initially
|
||||
for (int i = 0; i < 4; ++i)
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 4s);
|
||||
|
||||
void DoAction(int32 param) override
|
||||
// Activate the runes (Start burning)
|
||||
TurnRunes(true);
|
||||
|
||||
Talk(AGGRO_TEXT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
TurnRunes(false);
|
||||
}
|
||||
|
||||
int getValidRandomPosition()
|
||||
{
|
||||
/* Generate a random position which
|
||||
* have not been used in 4 summonings.
|
||||
* Since we are calling the event whenever the Spirit
|
||||
* dies and not all at the time, we need to save at
|
||||
* least 4 positions until reseting the vector
|
||||
*/
|
||||
|
||||
// Searching a new position so reset this bool check
|
||||
_foundValidPosition = false;
|
||||
int randomPosition;
|
||||
|
||||
while (!_foundValidPosition)
|
||||
{
|
||||
switch (param)
|
||||
/* When we have summoned 4 creatures, reset the vector
|
||||
* so we can summon new spirits in other positions.*/
|
||||
if (_validPosition.size() == 4)
|
||||
_validPosition.clear();
|
||||
|
||||
// The random ranges from the position 0 to the position 6
|
||||
randomPosition = urand(0, 6);
|
||||
|
||||
// When we have an empty vector we can use any random position generated.
|
||||
if (_validPosition.empty())
|
||||
_foundValidPosition = true;
|
||||
|
||||
/* This check is done to avoid running the vector
|
||||
* when it is empty. Because if it is empty, then any
|
||||
* position can be used to summon Spirits.
|
||||
*/
|
||||
if (!_foundValidPosition)
|
||||
{
|
||||
case EVENT_SUMMON_SPIRITS:
|
||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 12s, 14s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_events.Reset();
|
||||
summons.DespawnAll();
|
||||
TurnRunes(false);
|
||||
foundValidPosition = false;
|
||||
validPosition.clear();
|
||||
}
|
||||
|
||||
void TurnRunes(bool mode)
|
||||
{
|
||||
// Active makes the runes burn, ready turns them off
|
||||
GOState state = mode ? GO_STATE_ACTIVE : GO_STATE_READY;
|
||||
|
||||
for (int RuneEntry : gobjectDwarfRunesEntry)
|
||||
if (GameObject* dwarfRune = me->FindNearestGameObject(RuneEntry, 200.0f))
|
||||
dwarfRune->SetGoState(state);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 2s);
|
||||
|
||||
// Spawn 7 Embers initially
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 4s);
|
||||
|
||||
// Activate the runes (Start burning)
|
||||
TurnRunes(true);
|
||||
|
||||
Talk(AGGRO_TEXT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
TurnRunes(false);
|
||||
_events.Reset();
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
int getValidRandomPosition()
|
||||
{
|
||||
/* Generate a random position which
|
||||
* have not been used in 4 summonings.
|
||||
* Since we are calling the event whenever the Spirit
|
||||
* dies and not all at the time, we need to save at
|
||||
* least 4 positions until reseting the vector
|
||||
*/
|
||||
|
||||
// Searching a new position so reset this bool check
|
||||
foundValidPosition = false;
|
||||
int randomPosition;
|
||||
|
||||
while (!foundValidPosition)
|
||||
{
|
||||
/* When we have summoned 4 creatures, reset the vector
|
||||
* so we can summon new spirits in other positions.*/
|
||||
if (validPosition.size() == 4)
|
||||
validPosition.clear();
|
||||
|
||||
// The random ranges from the position 0 to the position 6
|
||||
randomPosition = urand(0, 6);
|
||||
|
||||
// When we have an empty vector we can use any random position generated.
|
||||
if (validPosition.empty())
|
||||
foundValidPosition = true;
|
||||
|
||||
/* This check is done to avoid running the vector
|
||||
* when it is empty. Because if it is empty, then any
|
||||
* position can be used to summon Spirits.
|
||||
*/
|
||||
if (!foundValidPosition)
|
||||
// Check every position inside the vector
|
||||
for (int pos : _validPosition)
|
||||
{
|
||||
// Check every position inside the vector
|
||||
for (int pos : validPosition)
|
||||
// If the random is different, we found a temporary true,
|
||||
// until we find one that is equal, which means it has been used.
|
||||
if (pos != randomPosition)
|
||||
_foundValidPosition = true;
|
||||
else
|
||||
{
|
||||
// If the random is different, we found a temporary true,
|
||||
// until we find one that is equal, which means it has been used.
|
||||
if (pos != randomPosition)
|
||||
foundValidPosition = true;
|
||||
else
|
||||
{
|
||||
foundValidPosition = false;
|
||||
break;
|
||||
}
|
||||
_foundValidPosition = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We found a valid position. Save it and return it to summon.
|
||||
validPosition.emplace_back(randomPosition);
|
||||
return randomPosition;
|
||||
}
|
||||
|
||||
void SummonSpirits()
|
||||
// We found a valid position. Save it and return it to summon.
|
||||
_validPosition.emplace_back(randomPosition);
|
||||
return randomPosition;
|
||||
}
|
||||
|
||||
void SummonSpirits()
|
||||
{
|
||||
// Make the Spirits chase Ambassador Flamelash
|
||||
me->SummonCreature(NPC_FIRE_SPIRIT, SummonPositions[getValidRandomPosition()], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60 * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 12s, 14s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
// Make the Spirits chase Ambassador Flamelash
|
||||
me->SummonCreature(NPC_FIRE_SPIRIT, SummonPositions[getValidRandomPosition()], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60 * IN_MILLISECONDS);
|
||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 12s, 14s);
|
||||
case EVENT_SPELL_FIREBLAST:
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 7s);
|
||||
break;
|
||||
case EVENT_SUMMON_SPIRITS:
|
||||
SummonSpirits();
|
||||
break;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_FIREBLAST:
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
_events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 7s);
|
||||
break;
|
||||
case EVENT_SUMMON_SPIRITS:
|
||||
SummonSpirits();
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
private:
|
||||
// This will allow to find a valid position to spawn them
|
||||
std::vector<int> _validPosition;
|
||||
bool _foundValidPosition = false;
|
||||
};
|
||||
|
||||
class npc_burning_spirit : public CreatureScript
|
||||
struct npc_burning_spirit : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_burning_spirit() : CreatureScript("npc_burning_spirit") { }
|
||||
npc_burning_spirit(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
struct npc_burning_spiritAI : public ScriptedAI
|
||||
void IsSummonedBy(WorldObject* summoner) override
|
||||
{
|
||||
npc_burning_spiritAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
if (!summoner->IsCreature())
|
||||
return;
|
||||
|
||||
void IsSummonedBy(WorldObject* summoner) override
|
||||
{
|
||||
if (!summoner->IsCreature())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_flamelasherGUID = summoner->GetGUID();
|
||||
me->GetMotionMaster()->MoveFollow(summoner->ToCreature(), 0.f, 0.f);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
if (Creature* flamelasher = ObjectAccessor::GetCreature(*me, _flamelasherGUID))
|
||||
{
|
||||
me->GetMotionMaster()->MoveFollow(flamelasher, 5.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
{
|
||||
if (type != FOLLOW_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (Creature* flamelasher = ObjectAccessor::GetCreature(*me, _flamelasherGUID))
|
||||
{
|
||||
flamelasher->CastSpell(flamelasher, SPELL_BURNING_SPIRIT);
|
||||
Unit::Kill(flamelasher, me);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
ObjectGuid _flamelasherGUID;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockDepthsAI<npc_burning_spiritAI>(creature);
|
||||
_flamelasherGUID = summoner->GetGUID();
|
||||
me->GetMotionMaster()->MoveFollow(summoner->ToCreature(), 0.f, 0.f);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
if (Creature* flamelasher = ObjectAccessor::GetCreature(*me, _flamelasherGUID))
|
||||
me->GetMotionMaster()->MoveFollow(flamelasher, 5.f, 0.f);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
{
|
||||
if (type != FOLLOW_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (Creature* flamelasher = ObjectAccessor::GetCreature(*me, _flamelasherGUID))
|
||||
{
|
||||
flamelasher->CastSpell(flamelasher, SPELL_BURNING_SPIRIT);
|
||||
Unit::Kill(flamelasher, me);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _flamelasherGUID;
|
||||
};
|
||||
|
||||
void AddSC_boss_ambassador_flamelash()
|
||||
{
|
||||
new boss_ambassador_flamelash();
|
||||
new npc_burning_spirit();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_ambassador_flamelash);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_burning_spirit);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,84 +34,67 @@ constexpr Milliseconds TIMER_CURSE_WEAKNESS = 12s;
|
|||
constexpr Milliseconds TIMER_DEMON_ARMOR = 3s; //virtually only cast once
|
||||
constexpr Milliseconds TIMER_ENVELOPING_WEB = 16s;
|
||||
|
||||
class boss_anubshiah : public CreatureScript
|
||||
struct boss_anubshiah : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_anubshiah() : CreatureScript("boss_anubshiah") { }
|
||||
boss_anubshiah(Creature* creature) : BossAI(creature, DATA_ANUBSHIAH) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_anubshiahAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT / 5);
|
||||
events.ScheduleEvent(SPELL_CURSE_TONGUES, TIMER_CURSE_TONGUES / 5);
|
||||
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, TIMER_CURSE_WEAKNESS / 5);
|
||||
events.ScheduleEvent(SPELL_DEMON_ARMOR, TIMER_DEMON_ARMOR / 5);
|
||||
events.ScheduleEvent(SPELL_ENVELOPING_WEB, TIMER_ENVELOPING_WEB / 5);
|
||||
}
|
||||
|
||||
struct boss_anubshiahAI : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_anubshiahAI(Creature* creature) : BossAI(creature, DATA_ANUBSHIAH) { }
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT / 5);
|
||||
events.ScheduleEvent(SPELL_CURSE_TONGUES, TIMER_CURSE_TONGUES / 5);
|
||||
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, TIMER_CURSE_WEAKNESS / 5);
|
||||
events.ScheduleEvent(SPELL_DEMON_ARMOR, TIMER_DEMON_ARMOR / 5);
|
||||
events.ScheduleEvent(SPELL_ENVELOPING_WEB, TIMER_ENVELOPING_WEB / 5);
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_SHADOWBOLT:
|
||||
DoCastVictim(SPELL_SHADOWBOLT);
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT - 2s, TIMER_SHADOWBOLT + 2s);
|
||||
break;
|
||||
case SPELL_CURSE_TONGUES:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_CURSE_TONGUES);
|
||||
events.ScheduleEvent(SPELL_CURSE_TONGUES, TIMER_CURSE_TONGUES - 2s, TIMER_CURSE_TONGUES + 2s);
|
||||
break;
|
||||
case SPELL_CURSE_WEAKNESS:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_CURSE_WEAKNESS);
|
||||
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, TIMER_CURSE_WEAKNESS - 2s, TIMER_CURSE_WEAKNESS + 2s);
|
||||
break;
|
||||
case SPELL_DEMON_ARMOR:
|
||||
DoCast(me, SPELL_DEMON_ARMOR);
|
||||
events.ScheduleEvent(SPELL_DEMON_ARMOR, TIMER_DEMON_ARMOR);
|
||||
break;
|
||||
case SPELL_ENVELOPING_WEB:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_ENVELOPING_WEB);
|
||||
events.ScheduleEvent(SPELL_ENVELOPING_WEB, TIMER_ENVELOPING_WEB - 2s, TIMER_ENVELOPING_WEB + 2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_SHADOWBOLT:
|
||||
DoCastVictim(SPELL_SHADOWBOLT);
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT - 2s, TIMER_SHADOWBOLT + 2s);
|
||||
break;
|
||||
case SPELL_CURSE_TONGUES:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoCast(target, SPELL_CURSE_TONGUES);
|
||||
}
|
||||
events.ScheduleEvent(SPELL_CURSE_TONGUES, TIMER_CURSE_TONGUES - 2s, TIMER_CURSE_TONGUES + 2s);
|
||||
break;
|
||||
case SPELL_CURSE_WEAKNESS:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoCast(target, SPELL_CURSE_WEAKNESS);
|
||||
}
|
||||
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, TIMER_CURSE_WEAKNESS - 2s, TIMER_CURSE_WEAKNESS + 2s);
|
||||
break;
|
||||
case SPELL_DEMON_ARMOR:
|
||||
DoCast(me, SPELL_DEMON_ARMOR);
|
||||
events.ScheduleEvent(SPELL_DEMON_ARMOR, TIMER_DEMON_ARMOR);
|
||||
break;
|
||||
case SPELL_ENVELOPING_WEB:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_ENVELOPING_WEB);
|
||||
events.ScheduleEvent(SPELL_ENVELOPING_WEB, TIMER_ENVELOPING_WEB - 2s, TIMER_ENVELOPING_WEB + 2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_anubshiah()
|
||||
{
|
||||
new boss_anubshiah();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_anubshiah);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,106 +34,87 @@ enum Spells
|
|||
|
||||
#define DATA_PERCENT_DEAD_SENATORS 0
|
||||
|
||||
class boss_emperor_dagran_thaurissan : public CreatureScript
|
||||
struct boss_emperor_dagran_thaurissan : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") { }
|
||||
uint32 hasYelled = 0;
|
||||
uint32 SenatorYells[5] = {3, 4, 5, 6, 7}; // IDs in creature_text database
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_emperor_dagran_thaurissan(Creature* creature) : BossAI(creature, DATA_EMPEROR){}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_draganthaurissanAI>(creature);
|
||||
if (hasYelled != 5)
|
||||
Talk(YELL_SENATORS_ALIVE);
|
||||
else
|
||||
Talk(YELL_SENATORS_DEAD);
|
||||
|
||||
me->CallForHelp(VISIBLE_RANGE);
|
||||
events.ScheduleEvent(SPELL_HANDOFTHAURISSAN, 4s, 7s);
|
||||
events.ScheduleEvent(SPELL_AVATAROFFLAME, 10s, 12s);
|
||||
}
|
||||
|
||||
struct boss_draganthaurissanAI : public BossAI
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
uint32 hasYelled = 0;
|
||||
uint32 SenatorYells[5] = {3, 4, 5, 6, 7}; // IDs in creature_text database
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
boss_draganthaurissanAI(Creature* creature) : BossAI(creature, DATA_EMPEROR){}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == DATA_PERCENT_DEAD_SENATORS)
|
||||
{
|
||||
if (hasYelled != 5)
|
||||
if (data >= 20 * (hasYelled + 1)) // map the 5 yells to %. Yell after 20,40,60,80,100%
|
||||
{
|
||||
Talk(YELL_SENATORS_ALIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(YELL_SENATORS_DEAD);
|
||||
}
|
||||
|
||||
me->CallForHelp(VISIBLE_RANGE);
|
||||
events.ScheduleEvent(SPELL_HANDOFTHAURISSAN, 4s, 7s);
|
||||
events.ScheduleEvent(SPELL_AVATAROFFLAME, 10s, 12s);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == DATA_PERCENT_DEAD_SENATORS)
|
||||
{
|
||||
if (data >= 20 * (hasYelled + 1)) // map the 5 yells to %. Yell after 20,40,60,80,100%
|
||||
{
|
||||
if (hasYelled < 5)
|
||||
{
|
||||
if (me->IsAlive())
|
||||
{
|
||||
Talk(SenatorYells[hasYelled]);
|
||||
}
|
||||
}
|
||||
hasYelled++;
|
||||
}
|
||||
if (hasYelled < 5)
|
||||
if (me->IsAlive())
|
||||
Talk(SenatorYells[hasYelled]);
|
||||
hasYelled++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOIRA)))
|
||||
{
|
||||
if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOIRA)))
|
||||
Moira->AI()->EnterEvadeMode();
|
||||
Moira->AI()->Talk(0);
|
||||
Moira->SetFaction(FACTION_FRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
Moira->AI()->EnterEvadeMode();
|
||||
Moira->AI()->Talk(0);
|
||||
Moira->SetFaction(FACTION_FRIENDLY);
|
||||
case SPELL_HANDOFTHAURISSAN:
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random), SPELL_HANDOFTHAURISSAN);
|
||||
//DoCastVictim(SPELL_HANDOFTHAURISSAN);
|
||||
events.ScheduleEvent(SPELL_HANDOFTHAURISSAN, 4s, 7s);
|
||||
break;
|
||||
case SPELL_AVATAROFFLAME:
|
||||
DoCastSelf(SPELL_AVATAROFFLAME);
|
||||
events.ScheduleEvent(SPELL_AVATAROFFLAME, 23s, 27s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_HANDOFTHAURISSAN:
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random), SPELL_HANDOFTHAURISSAN);
|
||||
//DoCastVictim(SPELL_HANDOFTHAURISSAN);
|
||||
events.ScheduleEvent(SPELL_HANDOFTHAURISSAN, 4s, 7s);
|
||||
break;
|
||||
case SPELL_AVATAROFFLAME:
|
||||
DoCastSelf(SPELL_AVATAROFFLAME);
|
||||
events.ScheduleEvent(SPELL_AVATAROFFLAME, 23s, 27s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_draganthaurissan()
|
||||
{
|
||||
new boss_emperor_dagran_thaurissan();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_emperor_dagran_thaurissan);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,78 +30,65 @@ constexpr Milliseconds TIMER_SHADOWBOLT_VOLLEY = 7s;
|
|||
constexpr Milliseconds TIMER_REND = 20s;
|
||||
constexpr Milliseconds TIMER_SHIELD = 12s;
|
||||
|
||||
class boss_eviscerator : public CreatureScript
|
||||
struct boss_eviscerator : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_eviscerator() : CreatureScript("boss_eviscerator") {}
|
||||
boss_eviscerator(Creature* creature) : BossAI(creature, DATA_EVISCERATOR) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool SpellShieldReady = false;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_evisceratorAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, TIMER_SHADOWBOLT_VOLLEY / 5);
|
||||
events.ScheduleEvent(SPELL_REND, TIMER_REND / 5);
|
||||
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD / 5);
|
||||
}
|
||||
|
||||
struct boss_evisceratorAI : public BossAI
|
||||
void DamageTaken(Unit* /* doneBy */, uint32& /* damage */, DamageEffectType /* damagetype */, SpellSchoolMask damageSchoolMask) override
|
||||
{
|
||||
boss_evisceratorAI(Creature* creature) : BossAI(creature, DATA_EVISCERATOR) {}
|
||||
|
||||
bool SpellShieldReady = false;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
if ((damageSchoolMask & SPELL_SCHOOL_MASK_MAGIC) && SpellShieldReady)
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, TIMER_SHADOWBOLT_VOLLEY / 5);
|
||||
events.ScheduleEvent(SPELL_REND, TIMER_REND / 5);
|
||||
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD / 5);
|
||||
DoCast(SPELL_SHIELD);
|
||||
SpellShieldReady = false;
|
||||
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /* doneBy */, uint32& /* damage */, DamageEffectType /* damagetype */, SpellSchoolMask damageSchoolMask) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
if ((damageSchoolMask & SPELL_SCHOOL_MASK_MAGIC) && SpellShieldReady)
|
||||
switch (eventId)
|
||||
{
|
||||
DoCast(SPELL_SHIELD);
|
||||
SpellShieldReady = false;
|
||||
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD);
|
||||
case SPELL_SHADOWBOLT_VOLLEY:
|
||||
DoCastVictim(SPELL_SHADOWBOLT_VOLLEY);
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, TIMER_SHADOWBOLT_VOLLEY - 2s, TIMER_SHADOWBOLT_VOLLEY + 2s);
|
||||
break;
|
||||
case SPELL_REND:
|
||||
DoCastVictim(SPELL_REND);
|
||||
events.ScheduleEvent(SPELL_REND, TIMER_REND - 2s, TIMER_REND + 2s);
|
||||
break;
|
||||
case SPELL_SHIELD:
|
||||
SpellShieldReady = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_SHADOWBOLT_VOLLEY:
|
||||
DoCastVictim(SPELL_SHADOWBOLT_VOLLEY);
|
||||
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, TIMER_SHADOWBOLT_VOLLEY - 2s, TIMER_SHADOWBOLT_VOLLEY + 2s);
|
||||
break;
|
||||
case SPELL_REND:
|
||||
DoCastVictim(SPELL_REND);
|
||||
events.ScheduleEvent(SPELL_REND, TIMER_REND - 2s, TIMER_REND + 2s);
|
||||
break;
|
||||
case SPELL_SHIELD:
|
||||
SpellShieldReady = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_eviscerator()
|
||||
{
|
||||
new boss_eviscerator();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_eviscerator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,108 +26,94 @@ enum Spells
|
|||
SPELL_CLEAVE = 20691
|
||||
};
|
||||
|
||||
class boss_general_angerforge : public CreatureScript
|
||||
struct boss_general_angerforge : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
boss_general_angerforge() : CreatureScript("boss_general_angerforge") { }
|
||||
boss_general_angerforge(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_general_angerforgeAI>(creature);
|
||||
_mightyBlowTimer = 8000;
|
||||
_hamStringTimer = 12000;
|
||||
_cleaveTimer = 16000;
|
||||
_addsTimer = 0;
|
||||
_medics = false;
|
||||
}
|
||||
|
||||
struct boss_general_angerforgeAI : public ScriptedAI
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void SummonAdds(Unit* victim)
|
||||
{
|
||||
boss_general_angerforgeAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
|
||||
SummonedAdd->AI()->AttackStart(victim);
|
||||
}
|
||||
|
||||
uint32 MightyBlow_Timer;
|
||||
uint32 HamString_Timer;
|
||||
uint32 Cleave_Timer;
|
||||
uint32 Adds_Timer;
|
||||
bool Medics;
|
||||
void SummonMedics(Unit* victim)
|
||||
{
|
||||
if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
|
||||
SummonedMedic->AI()->AttackStart(victim);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (_mightyBlowTimer <= diff)
|
||||
{
|
||||
MightyBlow_Timer = 8000;
|
||||
HamString_Timer = 12000;
|
||||
Cleave_Timer = 16000;
|
||||
Adds_Timer = 0;
|
||||
Medics = false;
|
||||
DoCastVictim(SPELL_MIGHTYBLOW);
|
||||
_mightyBlowTimer = 18000;
|
||||
}
|
||||
else _mightyBlowTimer -= diff;
|
||||
|
||||
if (_hamStringTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_HAMSTRING);
|
||||
_hamStringTimer = 15000;
|
||||
}
|
||||
else _hamStringTimer -= diff;
|
||||
|
||||
if (_cleaveTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
_cleaveTimer = 9000;
|
||||
}
|
||||
else _cleaveTimer -= diff;
|
||||
|
||||
if (HealthBelowPct(21))
|
||||
{
|
||||
if (_addsTimer <= diff)
|
||||
{
|
||||
// summon 3 Adds every 25s
|
||||
SummonAdds(me->GetVictim());
|
||||
SummonAdds(me->GetVictim());
|
||||
SummonAdds(me->GetVictim());
|
||||
|
||||
_addsTimer = 25000;
|
||||
}
|
||||
else _addsTimer -= diff;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void SummonAdds(Unit* victim)
|
||||
//Summon Medics
|
||||
if (!_medics && HealthBelowPct(21))
|
||||
{
|
||||
if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
|
||||
SummonedAdd->AI()->AttackStart(victim);
|
||||
SummonMedics(me->GetVictim());
|
||||
SummonMedics(me->GetVictim());
|
||||
_medics = true;
|
||||
}
|
||||
|
||||
void SummonMedics(Unit* victim)
|
||||
{
|
||||
if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
|
||||
SummonedMedic->AI()->AttackStart(victim);
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//MightyBlow_Timer
|
||||
if (MightyBlow_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_MIGHTYBLOW);
|
||||
MightyBlow_Timer = 18000;
|
||||
}
|
||||
else MightyBlow_Timer -= diff;
|
||||
|
||||
//HamString_Timer
|
||||
if (HamString_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_HAMSTRING);
|
||||
HamString_Timer = 15000;
|
||||
}
|
||||
else HamString_Timer -= diff;
|
||||
|
||||
//Cleave_Timer
|
||||
if (Cleave_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
Cleave_Timer = 9000;
|
||||
}
|
||||
else Cleave_Timer -= diff;
|
||||
|
||||
//Adds_Timer
|
||||
if (HealthBelowPct(21))
|
||||
{
|
||||
if (Adds_Timer <= diff)
|
||||
{
|
||||
// summon 3 Adds every 25s
|
||||
SummonAdds(me->GetVictim());
|
||||
SummonAdds(me->GetVictim());
|
||||
SummonAdds(me->GetVictim());
|
||||
|
||||
Adds_Timer = 25000;
|
||||
}
|
||||
else Adds_Timer -= diff;
|
||||
}
|
||||
|
||||
//Summon Medics
|
||||
if (!Medics && HealthBelowPct(21))
|
||||
{
|
||||
SummonMedics(me->GetVictim());
|
||||
SummonMedics(me->GetVictim());
|
||||
Medics = true;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
private:
|
||||
uint32 _mightyBlowTimer;
|
||||
uint32 _hamStringTimer;
|
||||
uint32 _cleaveTimer;
|
||||
uint32 _addsTimer;
|
||||
bool _medics;
|
||||
};
|
||||
|
||||
void AddSC_boss_general_angerforge()
|
||||
{
|
||||
new boss_general_angerforge();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_general_angerforge);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,78 +30,65 @@ constexpr Milliseconds TIMER_WHIRLWIND = 12s;
|
|||
constexpr Milliseconds TIMER_MORTAL = 22s;
|
||||
constexpr Milliseconds TIMER_BLOODLUST = 30s;
|
||||
|
||||
class boss_gorosh_the_dervish : public CreatureScript
|
||||
struct boss_gorosh_the_dervish : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { }
|
||||
boss_gorosh_the_dervish(Creature* creature) : BossAI(creature, DATA_GOROSH) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
Milliseconds nextWhirlwindTime;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_gorosh_the_dervishAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_WHIRLWIND, TIMER_WHIRLWIND / 5);
|
||||
events.ScheduleEvent(SPELL_MORTALSTRIKE, TIMER_MORTAL / 5);
|
||||
events.ScheduleEvent(SPELL_BLOODLUST, TIMER_BLOODLUST / 5);
|
||||
}
|
||||
|
||||
struct boss_gorosh_the_dervishAI : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_gorosh_the_dervishAI(Creature* creature) : BossAI(creature, DATA_GOROSH) { }
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Milliseconds nextWhirlwindTime;
|
||||
events.Update(diff);
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_WHIRLWIND, TIMER_WHIRLWIND / 5);
|
||||
events.ScheduleEvent(SPELL_MORTALSTRIKE, TIMER_MORTAL / 5);
|
||||
events.ScheduleEvent(SPELL_BLOODLUST, TIMER_BLOODLUST / 5);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
case SPELL_WHIRLWIND:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
||||
{
|
||||
case SPELL_WHIRLWIND:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
||||
{
|
||||
DoCastVictim(SPELL_WHIRLWIND);
|
||||
nextWhirlwindTime = randtime(TIMER_WHIRLWIND - 2s, TIMER_WHIRLWIND + 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
// reschedule sooner
|
||||
nextWhirlwindTime = randtime(TIMER_WHIRLWIND - 2s, TIMER_WHIRLWIND + 2s) / 3;
|
||||
}
|
||||
events.ScheduleEvent(SPELL_WHIRLWIND, nextWhirlwindTime);
|
||||
break;
|
||||
case SPELL_MORTALSTRIKE:
|
||||
DoCastVictim(SPELL_MORTALSTRIKE);
|
||||
events.ScheduleEvent(SPELL_MORTALSTRIKE, TIMER_MORTAL - 2s, TIMER_MORTAL + 2s);
|
||||
break;
|
||||
case SPELL_BLOODLUST:
|
||||
DoCastSelf(SPELL_BLOODLUST);
|
||||
events.ScheduleEvent(SPELL_BLOODLUST, TIMER_BLOODLUST - 2s, TIMER_BLOODLUST + 2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
DoCastVictim(SPELL_WHIRLWIND);
|
||||
nextWhirlwindTime = randtime(TIMER_WHIRLWIND - 2s, TIMER_WHIRLWIND + 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
// reschedule sooner
|
||||
nextWhirlwindTime = randtime(TIMER_WHIRLWIND - 2s, TIMER_WHIRLWIND + 2s) / 3;
|
||||
}
|
||||
events.ScheduleEvent(SPELL_WHIRLWIND, nextWhirlwindTime);
|
||||
break;
|
||||
case SPELL_MORTALSTRIKE:
|
||||
DoCastVictim(SPELL_MORTALSTRIKE);
|
||||
events.ScheduleEvent(SPELL_MORTALSTRIKE, TIMER_MORTAL - 2s, TIMER_MORTAL + 2s);
|
||||
break;
|
||||
case SPELL_BLOODLUST:
|
||||
DoCastSelf(SPELL_BLOODLUST);
|
||||
events.ScheduleEvent(SPELL_BLOODLUST, TIMER_BLOODLUST - 2s, TIMER_BLOODLUST + 2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_gorosh_the_dervish()
|
||||
{
|
||||
new boss_gorosh_the_dervish();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_gorosh_the_dervish);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,74 +29,60 @@ enum Grizzle
|
|||
constexpr Milliseconds TIMER_GROUNDTREMOR = 10s;
|
||||
constexpr Milliseconds TIMER_FRENZY = 15s;
|
||||
|
||||
class boss_grizzle : public CreatureScript
|
||||
struct boss_grizzle : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_grizzle() : CreatureScript("boss_grizzle") { }
|
||||
boss_grizzle(Creature* creature) : BossAI(creature, DATA_GRIZZLE) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
Milliseconds nextTremorTime;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_grizzleAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_GROUNDTREMOR, TIMER_GROUNDTREMOR / 5);
|
||||
events.ScheduleEvent(SPELL_FRENZY, TIMER_FRENZY / 5);
|
||||
}
|
||||
|
||||
struct boss_grizzleAI : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_grizzleAI(Creature* creature) : BossAI(creature, DATA_GRIZZLE) {}
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Milliseconds nextTremorTime;
|
||||
events.Update(diff);
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_GROUNDTREMOR, TIMER_GROUNDTREMOR / 5);
|
||||
events.ScheduleEvent(SPELL_FRENZY, TIMER_FRENZY / 5);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
case SPELL_GROUNDTREMOR:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
||||
{
|
||||
case SPELL_GROUNDTREMOR:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
||||
{
|
||||
DoCastVictim(SPELL_GROUNDTREMOR);
|
||||
nextTremorTime = randtime(TIMER_GROUNDTREMOR - 2s, TIMER_GROUNDTREMOR + 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextTremorTime = randtime(TIMER_GROUNDTREMOR - 2s, TIMER_GROUNDTREMOR + 2s) / 3;
|
||||
}
|
||||
events.ScheduleEvent(SPELL_GROUNDTREMOR, nextTremorTime);
|
||||
break;
|
||||
case SPELL_FRENZY:
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
events.ScheduleEvent(SPELL_FRENZY, TIMER_FRENZY - 2s, TIMER_FRENZY + 2s);
|
||||
Talk(EMOTE_FRENZY_KILL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
DoCastVictim(SPELL_GROUNDTREMOR);
|
||||
nextTremorTime = randtime(TIMER_GROUNDTREMOR - 2s, TIMER_GROUNDTREMOR + 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextTremorTime = randtime(TIMER_GROUNDTREMOR - 2s, TIMER_GROUNDTREMOR + 2s) / 3;
|
||||
}
|
||||
events.ScheduleEvent(SPELL_GROUNDTREMOR, nextTremorTime);
|
||||
break;
|
||||
case SPELL_FRENZY:
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
events.ScheduleEvent(SPELL_FRENZY, TIMER_FRENZY - 2s, TIMER_FRENZY + 2s);
|
||||
Talk(EMOTE_FRENZY_KILL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_grizzle()
|
||||
{
|
||||
new boss_grizzle();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_grizzle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,70 +30,55 @@ constexpr Milliseconds TIMER_PARALYZING = 20s;
|
|||
constexpr Milliseconds TIMER_BANEFUL = 24s;
|
||||
constexpr Milliseconds TIMER_WEB_EXPLOSION = 20s;
|
||||
|
||||
class boss_hedrum : public CreatureScript
|
||||
struct boss_hedrum : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_hedrum() : CreatureScript("boss_hedrum") {}
|
||||
boss_hedrum(Creature* creature) : BossAI(creature, DATA_HEDRUM) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_hedrumAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_PARALYZING, TIMER_PARALYZING / 5);
|
||||
events.ScheduleEvent(SPELL_BANEFUL, TIMER_BANEFUL / 5);
|
||||
events.ScheduleEvent(SPELL_WEB_EXPLOSION, TIMER_WEB_EXPLOSION / 5);
|
||||
}
|
||||
|
||||
struct boss_hedrumAI : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_hedrumAI(Creature* creature) : BossAI(creature, DATA_HEDRUM) {}
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_PARALYZING, TIMER_PARALYZING / 5);
|
||||
events.ScheduleEvent(SPELL_BANEFUL, TIMER_BANEFUL / 5);
|
||||
events.ScheduleEvent(SPELL_WEB_EXPLOSION, TIMER_WEB_EXPLOSION / 5);
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_PARALYZING:
|
||||
DoCastVictim(SPELL_PARALYZING);
|
||||
events.ScheduleEvent(SPELL_PARALYZING, TIMER_PARALYZING - 2s, TIMER_PARALYZING + 2s);
|
||||
break;
|
||||
case SPELL_BANEFUL:
|
||||
DoCastVictim(SPELL_BANEFUL);
|
||||
events.ScheduleEvent(SPELL_BANEFUL, TIMER_BANEFUL - 2s, TIMER_BANEFUL + 2s);
|
||||
break;
|
||||
case SPELL_WEB_EXPLOSION:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 100.0f)
|
||||
DoCast(SPELL_WEB_EXPLOSION);
|
||||
events.ScheduleEvent(SPELL_WEB_EXPLOSION, TIMER_WEB_EXPLOSION - 2s, TIMER_WEB_EXPLOSION + 2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_PARALYZING:
|
||||
DoCastVictim(SPELL_PARALYZING);
|
||||
events.ScheduleEvent(SPELL_PARALYZING, TIMER_PARALYZING - 2s, TIMER_PARALYZING + 2s);
|
||||
break;
|
||||
case SPELL_BANEFUL:
|
||||
DoCastVictim(SPELL_BANEFUL);
|
||||
events.ScheduleEvent(SPELL_BANEFUL, TIMER_BANEFUL - 2s, TIMER_BANEFUL + 2s);
|
||||
break;
|
||||
case SPELL_WEB_EXPLOSION:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 100.0f)
|
||||
{
|
||||
DoCast(SPELL_WEB_EXPLOSION);
|
||||
}
|
||||
events.ScheduleEvent(SPELL_WEB_EXPLOSION, TIMER_WEB_EXPLOSION - 2s, TIMER_WEB_EXPLOSION + 2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_hedrum()
|
||||
{
|
||||
new boss_hedrum();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_hedrum);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,81 +27,67 @@ enum Spells
|
|||
SPELL_SHADOWSHIELD = 22417
|
||||
};
|
||||
|
||||
class boss_high_interrogator_gerstahn : public CreatureScript
|
||||
struct boss_high_interrogator_gerstahn : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") { }
|
||||
boss_high_interrogator_gerstahn(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_high_interrogator_gerstahnAI>(creature);
|
||||
_shadowWordPainTimer = 4000;
|
||||
_manaBurnTimer = 14000;
|
||||
_psychicScreamTimer = 32000;
|
||||
_shadowShieldTimer = 8000;
|
||||
}
|
||||
|
||||
struct boss_high_interrogator_gerstahnAI : public ScriptedAI
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_high_interrogator_gerstahnAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
uint32 ShadowWordPain_Timer;
|
||||
uint32 ManaBurn_Timer;
|
||||
uint32 PsychicScream_Timer;
|
||||
uint32 ShadowShield_Timer;
|
||||
|
||||
void Reset() override
|
||||
if (_shadowWordPainTimer <= diff)
|
||||
{
|
||||
ShadowWordPain_Timer = 4000;
|
||||
ManaBurn_Timer = 14000;
|
||||
PsychicScream_Timer = 32000;
|
||||
ShadowShield_Timer = 8000;
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_SHADOWWORDPAIN);
|
||||
_shadowWordPainTimer = 7000;
|
||||
}
|
||||
else _shadowWordPainTimer -= diff;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
if (_manaBurnTimer <= diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//ShadowWordPain_Timer
|
||||
if (ShadowWordPain_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_SHADOWWORDPAIN);
|
||||
ShadowWordPain_Timer = 7000;
|
||||
}
|
||||
else ShadowWordPain_Timer -= diff;
|
||||
|
||||
//ManaBurn_Timer
|
||||
if (ManaBurn_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_MANABURN);
|
||||
ManaBurn_Timer = 10000;
|
||||
}
|
||||
else ManaBurn_Timer -= diff;
|
||||
|
||||
//PsychicScream_Timer
|
||||
if (PsychicScream_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_PSYCHICSCREAM);
|
||||
PsychicScream_Timer = 30000;
|
||||
}
|
||||
else PsychicScream_Timer -= diff;
|
||||
|
||||
//ShadowShield_Timer
|
||||
if (ShadowShield_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_SHADOWSHIELD);
|
||||
ShadowShield_Timer = 25000;
|
||||
}
|
||||
else ShadowShield_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_MANABURN);
|
||||
_manaBurnTimer = 10000;
|
||||
}
|
||||
};
|
||||
else _manaBurnTimer -= diff;
|
||||
|
||||
if (_psychicScreamTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_PSYCHICSCREAM);
|
||||
_psychicScreamTimer = 30000;
|
||||
}
|
||||
else _psychicScreamTimer -= diff;
|
||||
|
||||
if (_shadowShieldTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_SHADOWSHIELD);
|
||||
_shadowShieldTimer = 25000;
|
||||
}
|
||||
else _shadowShieldTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _shadowWordPainTimer;
|
||||
uint32 _manaBurnTimer;
|
||||
uint32 _psychicScreamTimer;
|
||||
uint32 _shadowShieldTimer;
|
||||
};
|
||||
|
||||
void AddSC_boss_high_interrogator_gerstahn()
|
||||
{
|
||||
new boss_high_interrogator_gerstahn();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_high_interrogator_gerstahn);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,66 +25,54 @@ enum Spells
|
|||
SPELL_WARSTOMP = 24375
|
||||
};
|
||||
|
||||
class boss_magmus : public CreatureScript
|
||||
struct boss_magmus : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_magmus() : CreatureScript("boss_magmus") { }
|
||||
boss_magmus(Creature* creature) : BossAI(creature, TYPE_IRON_HALL) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_magmusAI>(creature);
|
||||
_Reset();
|
||||
instance->SetData(TYPE_IRON_HALL, NOT_STARTED);
|
||||
}
|
||||
|
||||
struct boss_magmusAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_magmusAI(Creature* creature) : BossAI(creature, TYPE_IRON_HALL) {}
|
||||
instance->SetData(TYPE_IRON_HALL, IN_PROGRESS);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_WARSTOMP, 8s, 12s);
|
||||
events.ScheduleEvent(SPELL_FIERYBURST, 4s, 8s);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
instance->SetData(TYPE_IRON_HALL, NOT_STARTED);
|
||||
}
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
instance->SetData(TYPE_IRON_HALL, IN_PROGRESS);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_WARSTOMP, 8s, 12s);
|
||||
events.ScheduleEvent(SPELL_FIERYBURST, 4s, 8s);
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
case SPELL_WARSTOMP:
|
||||
DoCastVictim(SPELL_WARSTOMP);
|
||||
events.ScheduleEvent(SPELL_WARSTOMP, 8s, 12s);
|
||||
break;
|
||||
case SPELL_FIERYBURST:
|
||||
DoCastVictim(SPELL_FIERYBURST);
|
||||
events.ScheduleEvent(SPELL_FIERYBURST, 4s, 8s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_WARSTOMP:
|
||||
DoCastVictim(SPELL_WARSTOMP);
|
||||
events.ScheduleEvent(SPELL_WARSTOMP, 8s, 12s);
|
||||
break;
|
||||
case SPELL_FIERYBURST:
|
||||
DoCastVictim(SPELL_FIERYBURST);
|
||||
events.ScheduleEvent(SPELL_FIERYBURST, 4s, 8s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_magmus()
|
||||
{
|
||||
new boss_magmus();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_magmus);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ constexpr Milliseconds TIMER_RENEW = 12s;
|
|||
constexpr Milliseconds TIMER_SHADOWBOLT = 16s;
|
||||
constexpr Milliseconds TIMER_WORDPAIN = 12s;
|
||||
|
||||
struct boss_moira_bronzebeardAI : public BossAI
|
||||
struct boss_moira_bronzebeard : public BossAI
|
||||
{
|
||||
// use a default value so we can inherit for priestess
|
||||
boss_moira_bronzebeardAI(Creature* creature, uint32 data = DATA_MOIRA) : BossAI(creature, data) {}
|
||||
boss_moira_bronzebeard(Creature* creature, uint32 data = DATA_MOIRA) : BossAI(creature, data) {}
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
|
@ -49,15 +49,13 @@ struct boss_moira_bronzebeardAI : public BossAI
|
|||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
|
|
@ -83,22 +81,18 @@ struct boss_moira_bronzebeardAI : public BossAI
|
|||
{
|
||||
Creature* emperor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EMPEROR));
|
||||
if (emperor && emperor->HealthBelowPct(90))
|
||||
{
|
||||
DoCast(emperor, spell);
|
||||
}
|
||||
else if (HealthBelowPct(90))
|
||||
{
|
||||
DoCastSelf(spell);
|
||||
}
|
||||
events.ScheduleEvent(spell, timer - 2s, timer + 2s);
|
||||
}
|
||||
};
|
||||
|
||||
// high priestess should be fairly identical to Moira.
|
||||
// Running away when emperor dies is handled through GUID from emperor, therefore not relevant here.
|
||||
struct boss_high_priestess_thaurissanAI : public boss_moira_bronzebeardAI
|
||||
struct boss_high_priestess_thaurissan : public boss_moira_bronzebeard
|
||||
{
|
||||
boss_high_priestess_thaurissanAI(Creature* creature) : boss_moira_bronzebeardAI(creature, DATA_PRIESTESS) {}
|
||||
boss_high_priestess_thaurissan(Creature* creature) : boss_moira_bronzebeard(creature, DATA_PRIESTESS) {}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
|
|
@ -110,18 +104,16 @@ struct boss_high_priestess_thaurissanAI : public boss_moira_bronzebeardAI
|
|||
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT / 2);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
|
|
@ -148,34 +140,12 @@ struct boss_high_priestess_thaurissanAI : public boss_moira_bronzebeardAI
|
|||
}
|
||||
};
|
||||
|
||||
class boss_moira_bronzebeard : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_moira_bronzebeard() : CreatureScript("boss_moira_bronzebeard") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_moira_bronzebeardAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class boss_high_priestess_thaurissan : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_high_priestess_thaurissan() : CreatureScript("boss_high_priestess_thaurissan") {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_high_priestess_thaurissanAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_moira_bronzebeard()
|
||||
{
|
||||
new boss_moira_bronzebeard();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_moira_bronzebeard);
|
||||
}
|
||||
|
||||
void AddSC_boss_high_priestess_thaurissan()
|
||||
{
|
||||
new boss_high_priestess_thaurissan();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_high_priestess_thaurissan);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,92 +32,74 @@ constexpr Milliseconds TIMER_ARCANE_EXPLOSION = 24s;
|
|||
constexpr Milliseconds TIMER_POLYMORPH = 12s;
|
||||
constexpr Milliseconds TIMER_SLOW = 15s;
|
||||
|
||||
class boss_okthor : public CreatureScript
|
||||
struct boss_okthor : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_okthor() : CreatureScript("boss_okthor") {}
|
||||
boss_okthor(Creature* creature) : BossAI(creature, DATA_OKTHOR) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_okthorAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_ARCANE_BOLT, TIMER_ARCANE_BOLT / 5);
|
||||
events.ScheduleEvent(SPELL_ARCANE_EXPLOSION, TIMER_ARCANE_EXPLOSION / 5);
|
||||
events.ScheduleEvent(SPELL_POLYMORPH, TIMER_POLYMORPH / 5);
|
||||
events.ScheduleEvent(SPELL_SLOW, 500ms);
|
||||
}
|
||||
|
||||
struct boss_okthorAI : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_okthorAI(Creature* creature) : BossAI(creature, DATA_OKTHOR) {}
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Milliseconds nextArcaneExplosionTime;
|
||||
events.Update(diff);
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_ARCANE_BOLT, TIMER_ARCANE_BOLT / 5);
|
||||
events.ScheduleEvent(SPELL_ARCANE_EXPLOSION, TIMER_ARCANE_EXPLOSION / 5);
|
||||
events.ScheduleEvent(SPELL_POLYMORPH, TIMER_POLYMORPH / 5);
|
||||
events.ScheduleEvent(SPELL_SLOW, 500ms);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
case SPELL_ARCANE_BOLT:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_ARCANE_BOLT);
|
||||
events.ScheduleEvent(SPELL_ARCANE_BOLT, TIMER_ARCANE_BOLT - 2s, TIMER_ARCANE_BOLT + 2s);
|
||||
break;
|
||||
case SPELL_ARCANE_EXPLOSION:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
|
||||
{
|
||||
case SPELL_ARCANE_BOLT:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoCast(target, SPELL_ARCANE_BOLT);
|
||||
}
|
||||
events.ScheduleEvent(SPELL_ARCANE_BOLT, TIMER_ARCANE_BOLT - 2s, TIMER_ARCANE_BOLT + 2s);
|
||||
break;
|
||||
case SPELL_ARCANE_EXPLOSION:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
|
||||
{
|
||||
DoCast(SPELL_ARCANE_EXPLOSION);
|
||||
nextArcaneExplosionTime = randtime(TIMER_ARCANE_EXPLOSION - 2s, TIMER_ARCANE_EXPLOSION + 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextArcaneExplosionTime = randtime(TIMER_ARCANE_EXPLOSION - 2s, TIMER_ARCANE_EXPLOSION + 2s) / 3;
|
||||
}
|
||||
events.ScheduleEvent(SPELL_ARCANE_EXPLOSION, nextArcaneExplosionTime);
|
||||
break;
|
||||
case SPELL_POLYMORPH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoCast(target, SPELL_POLYMORPH);
|
||||
}
|
||||
events.ScheduleEvent(SPELL_POLYMORPH, TIMER_POLYMORPH - 2s, TIMER_POLYMORPH + 2s);
|
||||
break;
|
||||
case SPELL_SLOW:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
|
||||
{
|
||||
DoCast(SPELL_SLOW);
|
||||
}
|
||||
events.ScheduleEvent(SPELL_SLOW, TIMER_SLOW);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
DoCast(SPELL_ARCANE_EXPLOSION);
|
||||
_nextArcaneExplosionTime = randtime(TIMER_ARCANE_EXPLOSION - 2s, TIMER_ARCANE_EXPLOSION + 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextArcaneExplosionTime = randtime(TIMER_ARCANE_EXPLOSION - 2s, TIMER_ARCANE_EXPLOSION + 2s) / 3;
|
||||
}
|
||||
events.ScheduleEvent(SPELL_ARCANE_EXPLOSION, _nextArcaneExplosionTime);
|
||||
break;
|
||||
case SPELL_POLYMORPH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
DoCast(target, SPELL_POLYMORPH);
|
||||
events.ScheduleEvent(SPELL_POLYMORPH, TIMER_POLYMORPH - 2s, TIMER_POLYMORPH + 2s);
|
||||
break;
|
||||
case SPELL_SLOW:
|
||||
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
|
||||
DoCast(SPELL_SLOW);
|
||||
events.ScheduleEvent(SPELL_SLOW, TIMER_SLOW);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
Milliseconds _nextArcaneExplosionTime;
|
||||
};
|
||||
|
||||
void AddSC_boss_okthor()
|
||||
{
|
||||
new boss_okthor();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_okthor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,19 +53,18 @@ enum Gossip
|
|||
SAY_QUEST_COMPLETED_END = 2606, // You have shown me your desire, and have payed with precious stone. I will teach you...
|
||||
};
|
||||
|
||||
class boss_gloomrel : public CreatureScript
|
||||
struct boss_gloomrel : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
boss_gloomrel() : CreatureScript("boss_gloomrel") { }
|
||||
boss_gloomrel(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
AddGossipItemFor(player, GOSSIP_TEXT_CONTINUE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
|
||||
SendGossipMenuFor(player, SAY_QUEST_COMPLETED_END, creature->GetGUID());
|
||||
SendGossipMenuFor(player, SAY_QUEST_COMPLETED_END, me->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+11:
|
||||
CloseGossipMenuFor(player);
|
||||
|
|
@ -73,33 +72,29 @@ public:
|
|||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
AddGossipItemFor(player, GOSSIP_TEXT_CONTINUE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
|
||||
SendGossipMenuFor(player, SAY_QUEST_ACCEPTED, creature->GetGUID());
|
||||
SendGossipMenuFor(player, SAY_QUEST_ACCEPTED, me->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+22:
|
||||
CloseGossipMenuFor(player);
|
||||
if (InstanceScript* instance = creature->GetInstanceScript())
|
||||
{
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
//are 5 minutes expected? go template may have data to despawn when used at quest
|
||||
instance->DoRespawnGameObject(instance->GetGuidData(DATA_GO_CHALICE), MINUTE * 5);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
if (player->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 1 && player->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN && !player->HasSpell(SPELL_SMELT_DARK_IRON))
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_GROOMREL, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, SAY_QUEST_COMPLETED, creature->GetGUID());
|
||||
SendGossipMenuFor(player, SAY_QUEST_COMPLETED, me->GetGUID());
|
||||
}
|
||||
|
||||
if (player->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 0 && player->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN)
|
||||
AddGossipItemFor(player, GOSSIP_GROOMREL, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
return true;
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -120,145 +115,124 @@ enum DoomrelEvents
|
|||
EVENT_SPELL_SUMMON_VOIDWALKERS = 5,
|
||||
};
|
||||
|
||||
class boss_doomrel : public CreatureScript
|
||||
struct boss_doomrel : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
boss_doomrel() : CreatureScript("boss_doomrel") { }
|
||||
boss_doomrel(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
InstanceScript* instance;
|
||||
EventMap _events;
|
||||
bool Voidwalkers;
|
||||
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
AddGossipItemFor(player, GOSSIP_TEXT_CONTINUE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, SAY_QUEST_COMPLETED, creature->GetGUID());
|
||||
SendGossipMenuFor(player, SAY_QUEST_COMPLETED, me->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
CloseGossipMenuFor(player);
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
// Start encounter
|
||||
InstanceScript* instance = creature->GetInstanceScript();
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS);
|
||||
}
|
||||
creature->AI()->Talk(SAY_START_FIGHT);
|
||||
Talk(SAY_START_FIGHT);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_DOOMREL_START_COMBAT, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, SAY_DOOMREL_HELLO, creature->GetGUID());
|
||||
|
||||
return true;
|
||||
SendGossipMenuFor(player, SAY_DOOMREL_HELLO, me->GetGUID());
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockDepthsAI<boss_doomrelAI>(creature);
|
||||
Voidwalkers = false;
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
|
||||
// was set before event start, so set again
|
||||
me->SetImmuneToPC(true);
|
||||
|
||||
if (instance->GetData(TYPE_TOMB_OF_SEVEN) == DONE) // what is this trying to do? Probably some kind of crash recovery
|
||||
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE);
|
||||
else
|
||||
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
|
||||
struct boss_doomrelAI : public ScriptedAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_doomrelAI(Creature* creature) : ScriptedAI(creature)
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOWBOLTVOLLEY, 10s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_IMMOLATE, 18s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_CURSEOFWEAKNESS, 5s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_DEMONARMOR, 16s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SUMMON_VOIDWALKERS, 1s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->LoadCreaturesAddon(true);
|
||||
if (me->IsAlive())
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
me->SetLootRecipient(nullptr);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
case EVENT_SPELL_SHADOWBOLTVOLLEY:
|
||||
DoCastVictim(SPELL_SHADOWBOLTVOLLEY);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOWBOLTVOLLEY, 12s);
|
||||
break;
|
||||
case EVENT_SPELL_IMMOLATE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
_events.ScheduleEvent(EVENT_SPELL_IMMOLATE, 25s);
|
||||
}
|
||||
// Didn't get a target, try again in 1s
|
||||
_events.ScheduleEvent(EVENT_SPELL_IMMOLATE, 1s);
|
||||
break;
|
||||
case EVENT_SPELL_CURSEOFWEAKNESS:
|
||||
DoCastVictim(SPELL_CURSEOFWEAKNESS);
|
||||
_events.ScheduleEvent(EVENT_SPELL_CURSEOFWEAKNESS, 45s);
|
||||
break;
|
||||
case EVENT_SPELL_DEMONARMOR:
|
||||
DoCast(me, SPELL_DEMONARMOR);
|
||||
_events.ScheduleEvent(EVENT_SPELL_DEMONARMOR, 300s);
|
||||
break;
|
||||
case EVENT_SPELL_SUMMON_VOIDWALKERS:
|
||||
if (!Voidwalkers && HealthBelowPct(51))
|
||||
{
|
||||
DoCastVictim(SPELL_SUMMON_VOIDWALKERS, true);
|
||||
Voidwalkers = true;
|
||||
}
|
||||
// Not ready yet, try again in 1s
|
||||
_events.ScheduleEvent(EVENT_SPELL_SUMMON_VOIDWALKERS, 1s);
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap _events;
|
||||
bool Voidwalkers;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Voidwalkers = false;
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
|
||||
// was set before event start, so set again
|
||||
me->SetImmuneToPC(true);
|
||||
|
||||
if (instance->GetData(TYPE_TOMB_OF_SEVEN) == DONE) // what is this trying to do? Probably some kind of crash recovery
|
||||
{
|
||||
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOWBOLTVOLLEY, 10s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_IMMOLATE, 18s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_CURSEOFWEAKNESS, 5s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_DEMONARMOR, 16s);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SUMMON_VOIDWALKERS, 1s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->LoadCreaturesAddon(true);
|
||||
if (me->IsAlive())
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
me->SetLootRecipient(nullptr);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOWBOLTVOLLEY:
|
||||
DoCastVictim(SPELL_SHADOWBOLTVOLLEY);
|
||||
_events.ScheduleEvent(EVENT_SPELL_SHADOWBOLTVOLLEY, 12s);
|
||||
break;
|
||||
case EVENT_SPELL_IMMOLATE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
_events.ScheduleEvent(EVENT_SPELL_IMMOLATE, 25s);
|
||||
}
|
||||
// Didn't get a target, try again in 1s
|
||||
_events.ScheduleEvent(EVENT_SPELL_IMMOLATE, 1s);
|
||||
break;
|
||||
case EVENT_SPELL_CURSEOFWEAKNESS:
|
||||
DoCastVictim(SPELL_CURSEOFWEAKNESS);
|
||||
_events.ScheduleEvent(EVENT_SPELL_CURSEOFWEAKNESS, 45s);
|
||||
break;
|
||||
case EVENT_SPELL_DEMONARMOR:
|
||||
DoCast(me, SPELL_DEMONARMOR);
|
||||
_events.ScheduleEvent(EVENT_SPELL_DEMONARMOR, 300s);
|
||||
break;
|
||||
case EVENT_SPELL_SUMMON_VOIDWALKERS:
|
||||
if (!Voidwalkers && HealthBelowPct(51))
|
||||
{
|
||||
DoCastVictim(SPELL_SUMMON_VOIDWALKERS, true);
|
||||
Voidwalkers = true;
|
||||
}
|
||||
// Not ready yet, try again in 1s
|
||||
_events.ScheduleEvent(EVENT_SPELL_SUMMON_VOIDWALKERS, 1s);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_tomb_of_seven()
|
||||
{
|
||||
new boss_gloomrel();
|
||||
new boss_doomrel();
|
||||
RegisterBlackrockDepthsCreatureAI(boss_gloomrel);
|
||||
RegisterBlackrockDepthsCreatureAI(boss_doomrel);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -155,5 +155,6 @@ inline AI* GetBlackrockSpireAI(T* obj)
|
|||
}
|
||||
|
||||
#define RegisterBlackrockSpireCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackrockSpireAI)
|
||||
#define RegisterBlackrockSpireGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetBlackrockSpireAI)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,98 +40,85 @@ enum Events
|
|||
EVENT_CHECK_CONFLAGRATION_TARGET
|
||||
};
|
||||
|
||||
class boss_drakkisath : public CreatureScript
|
||||
struct boss_drakkisath : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_drakkisath() : CreatureScript("boss_drakkisath") { }
|
||||
|
||||
struct boss_drakkisathAI : public BossAI
|
||||
boss_drakkisath(Creature* creature) : BossAI(creature, DATA_GENERAL_DRAKKISATH)
|
||||
{
|
||||
boss_drakkisathAI(Creature* creature) : BossAI(creature, DATA_GENERAL_DRAKKISATH)
|
||||
{
|
||||
_conflagrateThreat = 0.0f;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FLAMESTRIKE, 6s);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 15s);
|
||||
events.ScheduleEvent(EVENT_THUNDERCLAP, 17s);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, 5s);
|
||||
events.ScheduleEvent(EVENT_RAGE, 1s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FLAMESTRIKE:
|
||||
DoCastAOE(SPELL_FLAMESTRIKE);
|
||||
events.ScheduleEvent(EVENT_FLAMESTRIKE, 10s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||
break;
|
||||
case EVENT_CONFLAGRATION:
|
||||
DoCastVictim(SPELL_CONFLAGRATION);
|
||||
|
||||
if (Unit* target = me->GetVictim())
|
||||
{
|
||||
_conflagrateTarget = me->GetVictim()->GetGUID();
|
||||
_conflagrateThreat = me->GetThreatMgr().GetThreat(me->GetVictim());
|
||||
me->GetThreatMgr().ModifyThreatByPercent(target, -100);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 18s, 25s);
|
||||
events.ScheduleEvent(EVENT_CHECK_CONFLAGRATION_TARGET, 10s);
|
||||
break;
|
||||
case EVENT_THUNDERCLAP:
|
||||
DoCastVictim(SPELL_THUNDERCLAP);
|
||||
events.ScheduleEvent(EVENT_THUNDERCLAP, 20s);
|
||||
break;
|
||||
case EVENT_PIERCE_ARMOR:
|
||||
DoCastVictim(SPELL_PIERCE_ARMOR);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, 40s);
|
||||
break;
|
||||
case EVENT_RAGE:
|
||||
DoCastSelf(SPELL_RAGE);
|
||||
events.ScheduleEvent(EVENT_RAGE, 35s);
|
||||
break;
|
||||
case EVENT_CHECK_CONFLAGRATION_TARGET:
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, _conflagrateTarget))
|
||||
{
|
||||
me->GetThreatMgr().AddThreat(target, _conflagrateThreat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
float _conflagrateThreat;
|
||||
ObjectGuid _conflagrateTarget;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_drakkisathAI>(creature);
|
||||
_conflagrateThreat = 0.0f;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FLAMESTRIKE, 6s);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 15s);
|
||||
events.ScheduleEvent(EVENT_THUNDERCLAP, 17s);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, 5s);
|
||||
events.ScheduleEvent(EVENT_RAGE, 1s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FLAMESTRIKE:
|
||||
DoCastAOE(SPELL_FLAMESTRIKE);
|
||||
events.ScheduleEvent(EVENT_FLAMESTRIKE, 10s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||
break;
|
||||
case EVENT_CONFLAGRATION:
|
||||
DoCastVictim(SPELL_CONFLAGRATION);
|
||||
|
||||
if (Unit* target = me->GetVictim())
|
||||
{
|
||||
_conflagrateTarget = me->GetVictim()->GetGUID();
|
||||
_conflagrateThreat = me->GetThreatMgr().GetThreat(me->GetVictim());
|
||||
me->GetThreatMgr().ModifyThreatByPercent(target, -100);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 18s, 25s);
|
||||
events.ScheduleEvent(EVENT_CHECK_CONFLAGRATION_TARGET, 10s);
|
||||
break;
|
||||
case EVENT_THUNDERCLAP:
|
||||
DoCastVictim(SPELL_THUNDERCLAP);
|
||||
events.ScheduleEvent(EVENT_THUNDERCLAP, 20s);
|
||||
break;
|
||||
case EVENT_PIERCE_ARMOR:
|
||||
DoCastVictim(SPELL_PIERCE_ARMOR);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, 40s);
|
||||
break;
|
||||
case EVENT_RAGE:
|
||||
DoCastSelf(SPELL_RAGE);
|
||||
events.ScheduleEvent(EVENT_RAGE, 35s);
|
||||
break;
|
||||
case EVENT_CHECK_CONFLAGRATION_TARGET:
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, _conflagrateTarget))
|
||||
me->GetThreatMgr().AddThreat(target, _conflagrateThreat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
float _conflagrateThreat;
|
||||
ObjectGuid _conflagrateTarget;
|
||||
};
|
||||
|
||||
void AddSC_boss_drakkisath()
|
||||
{
|
||||
new boss_drakkisath();
|
||||
RegisterBlackrockSpireCreatureAI(boss_drakkisath);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,125 +51,114 @@ enum Events
|
|||
EVENT_SUMMONED_2 = 6
|
||||
};
|
||||
|
||||
class boss_gyth : public CreatureScript
|
||||
struct boss_gyth : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_gyth() : CreatureScript("boss_gyth") { }
|
||||
boss_gyth(Creature* creature) : BossAI(creature, DATA_GYTH) { }
|
||||
|
||||
struct boss_gythAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_gythAI(Creature* creature) : BossAI(creature, DATA_GYTH) { }
|
||||
|
||||
void Reset() override
|
||||
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
||||
{
|
||||
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
||||
{
|
||||
instance->SetBossState(DATA_GYTH, NOT_STARTED);
|
||||
summons.DespawnAll();
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
SetInvincibility(true); // Don't let boss die before summoning Rend.
|
||||
|
||||
ScheduleHealthCheckEvent(25, [&] {
|
||||
DoCastAOE(SPELL_SUMMON_REND, true);
|
||||
me->RemoveAura(SPELL_REND_MOUNTS);
|
||||
SetInvincibility(false);
|
||||
});
|
||||
instance->SetBossState(DATA_GYTH, NOT_STARTED);
|
||||
summons.DespawnAll();
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
SetInvincibility(true); // Don't let boss die before summoning Rend.
|
||||
|
||||
ScheduleHealthCheckEvent(25, [&] {
|
||||
DoCastAOE(SPELL_SUMMON_REND, true);
|
||||
me->RemoveAura(SPELL_REND_MOUNTS);
|
||||
SetInvincibility(false);
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_ACID, 8s, 16s);
|
||||
events.ScheduleEvent(EVENT_FREEZE, 8s, 16s);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 8s, 16s);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s, 18s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SUMMONED_1, 1s);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->AI()->AttackStart(me->SelectVictim());
|
||||
}
|
||||
|
||||
// Prevent clearing summon list, otherwise Rend despawns if the drake is killed first.
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_GYTH, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_ACID, 8s, 16s);
|
||||
events.ScheduleEvent(EVENT_FREEZE, 8s, 16s);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 8s, 16s);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s, 18s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SUMMONED_1, 1s);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->AI()->AttackStart(me->SelectVictim());
|
||||
}
|
||||
|
||||
// Prevent clearing summon list, otherwise Rend despawns if the drake is killed first.
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_GYTH, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SUMMONED_1:
|
||||
me->AddAura(SPELL_REND_MOUNTS, me);
|
||||
if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 40.0f))
|
||||
portcullis->UseDoorOrButton();
|
||||
events.ScheduleEvent(EVENT_SUMMONED_2, 2s);
|
||||
break;
|
||||
case EVENT_SUMMONED_2:
|
||||
me->GetMotionMaster()->MoveWaypoint(GYTH_PATH_1, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CORROSIVE_ACID:
|
||||
DoCast(me, SPELL_CORROSIVE_ACID);
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_ACID, 10s, 16s);
|
||||
case EVENT_SUMMONED_1:
|
||||
me->AddAura(SPELL_REND_MOUNTS, me);
|
||||
if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 40.0f))
|
||||
portcullis->UseDoorOrButton();
|
||||
events.ScheduleEvent(EVENT_SUMMONED_2, 2s);
|
||||
break;
|
||||
case EVENT_FREEZE:
|
||||
DoCast(me, SPELL_FREEZE);
|
||||
events.ScheduleEvent(EVENT_FREEZE, 10s, 16s);
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCast(me, SPELL_FLAMEBREATH);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 10s, 16s);
|
||||
break;
|
||||
case EVENT_KNOCK_AWAY:
|
||||
DoCastVictim(SPELL_KNOCK_AWAY);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 14s, 20s);
|
||||
case EVENT_SUMMONED_2:
|
||||
me->GetMotionMaster()->MoveWaypoint(GYTH_PATH_1, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_gythAI>(creature);
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CORROSIVE_ACID:
|
||||
DoCast(me, SPELL_CORROSIVE_ACID);
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_ACID, 10s, 16s);
|
||||
break;
|
||||
case EVENT_FREEZE:
|
||||
DoCast(me, SPELL_FREEZE);
|
||||
events.ScheduleEvent(EVENT_FREEZE, 10s, 16s);
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCast(me, SPELL_FLAMEBREATH);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 10s, 16s);
|
||||
break;
|
||||
case EVENT_KNOCK_AWAY:
|
||||
DoCastVictim(SPELL_KNOCK_AWAY);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 14s, 20s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -231,6 +220,6 @@ class spell_gyth_chromatic_protection : public AuraScript
|
|||
|
||||
void AddSC_boss_gyth()
|
||||
{
|
||||
new boss_gyth();
|
||||
RegisterBlackrockSpireCreatureAI(boss_gyth);
|
||||
RegisterSpellScript(spell_gyth_chromatic_protection);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,70 +38,59 @@ enum Events
|
|||
|
||||
const Position SummonLocation = { -167.9561f, -411.7844f, 76.23057f, 1.53589f };
|
||||
|
||||
class boss_halycon : public CreatureScript
|
||||
struct boss_halycon : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_halycon() : CreatureScript("boss_halycon") { }
|
||||
boss_halycon(Creature* creature) : BossAI(creature, DATA_HALYCON) { }
|
||||
|
||||
struct boss_halyconAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_halyconAI(Creature* creature) : BossAI(creature, DATA_HALYCON) { }
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_REND, 17s, 20s);
|
||||
events.ScheduleEvent(EVENT_THRASH, 10s, 12s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
me->SummonCreature(NPC_GIZRUL_THE_SLAVENER, SummonLocation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000);
|
||||
Talk(EMOTE_DEATH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_REND, 17s, 20s);
|
||||
events.ScheduleEvent(EVENT_THRASH, 10s, 12s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
me->SummonCreature(NPC_GIZRUL_THE_SLAVENER, SummonLocation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000);
|
||||
Talk(EMOTE_DEATH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_REND:
|
||||
DoCastVictim(SPELL_REND);
|
||||
events.ScheduleEvent(EVENT_REND, 8s, 10s);
|
||||
break;
|
||||
case EVENT_THRASH:
|
||||
DoCast(me, SPELL_THRASH);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case EVENT_REND:
|
||||
DoCastVictim(SPELL_REND);
|
||||
events.ScheduleEvent(EVENT_REND, 8s, 10s);
|
||||
break;
|
||||
case EVENT_THRASH:
|
||||
DoCast(me, SPELL_THRASH);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_halyconAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_halycon()
|
||||
{
|
||||
new boss_halycon();
|
||||
RegisterBlackrockSpireCreatureAI(boss_halycon);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,69 +31,58 @@ enum Events
|
|||
EVENT_KNOCK_AWAY = 2
|
||||
};
|
||||
|
||||
class boss_highlord_omokk : public CreatureScript
|
||||
struct boss_highlord_omokk : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_highlord_omokk() : CreatureScript("boss_highlord_omokk") { }
|
||||
boss_highlord_omokk(Creature* creature) : BossAI(creature, DATA_HIGHLORD_OMOKK) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_highlordomokkAI>(creature);
|
||||
_Reset();
|
||||
}
|
||||
|
||||
struct boss_highlordomokkAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_highlordomokkAI(Creature* creature) : BossAI(creature, DATA_HIGHLORD_OMOKK) { }
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FRENZY, 20s);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 18s);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FRENZY, 20s);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 18s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FRENZY:
|
||||
DoCastVictim(SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 60s);
|
||||
break;
|
||||
case EVENT_KNOCK_AWAY:
|
||||
DoCastVictim(SPELL_KNOCK_AWAY);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case EVENT_FRENZY:
|
||||
DoCastVictim(SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 60s);
|
||||
break;
|
||||
case EVENT_KNOCK_AWAY:
|
||||
DoCastVictim(SPELL_KNOCK_AWAY);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_highlordomokk()
|
||||
{
|
||||
new boss_highlord_omokk();
|
||||
RegisterBlackrockSpireCreatureAI(boss_highlord_omokk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,145 +49,130 @@ enum EventPhase
|
|||
EVENT_PHASE_FIGHT = 2
|
||||
};
|
||||
|
||||
class boss_lord_valthalak : public CreatureScript
|
||||
struct boss_lord_valthalak : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_lord_valthalak() : CreatureScript("boss_lord_valthalak") { }
|
||||
boss_lord_valthalak(Creature* creature) : BossAI(creature, DATA_LORD_VALTHALAK) { }
|
||||
|
||||
struct boss_lord_valthalakAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_lord_valthalakAI(Creature* creature) : BossAI(creature, DATA_LORD_VALTHALAK) { }
|
||||
BossAI::Reset();
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
frenzy40 = false;
|
||||
frenzy15 = false;
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
StartTalking(TALK_SUMMON, 8s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
Talk(TALK_AGGRO);
|
||||
|
||||
events.SetPhase(EVENT_PHASE_FIGHT);
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPECTRAL_ASSASSIN, 6s, 8s, 0, EVENT_PHASE_FIGHT);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WRATH, 9s, 18s, 0, EVENT_PHASE_FIGHT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
|
||||
instance->SetData(DATA_LORD_VALTHALAK, DONE);
|
||||
}
|
||||
|
||||
void StartTalking(uint32 talkGroupId, Milliseconds timer)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->AttackStop();
|
||||
|
||||
Talk(talkGroupId);
|
||||
|
||||
events.SetPhase(EVENT_PHASE_TALK);
|
||||
events.ScheduleEvent(EVENT_FIGHT, timer, 0, EVENT_PHASE_TALK);
|
||||
}
|
||||
|
||||
void StartFighting()
|
||||
{
|
||||
events.SetPhase(EVENT_PHASE_FIGHT);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!frenzy40 && me->HealthBelowPctDamaged(40, damage))
|
||||
{
|
||||
frenzy40 = true;
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
|
||||
events.CancelEvent(EVENT_SUMMON_SPECTRAL_ASSASSIN);
|
||||
|
||||
StartTalking(TALK_40_HP, 5s);
|
||||
}
|
||||
|
||||
if (!frenzy15 && me->HealthBelowPctDamaged(15, damage))
|
||||
{
|
||||
frenzy15 = true;
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 12s, 19s, 0, EVENT_PHASE_FIGHT);
|
||||
|
||||
StartTalking(TALK_15_HP, 5s);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() && !events.IsInPhase(EVENT_PHASE_TALK))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FIGHT:
|
||||
StartFighting();
|
||||
break;
|
||||
case EVENT_SUMMON_SPECTRAL_ASSASSIN:
|
||||
DoCast(me, SPELL_SUMMON_SPECTRAL_ASSASSIN);
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPECTRAL_ASSASSIN, 30s, 35s, 0, EVENT_PHASE_FIGHT);
|
||||
break;
|
||||
case EVENT_SHADOW_BOLT_VOLLEY:
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 4s, 6s, 0, EVENT_PHASE_FIGHT);
|
||||
break;
|
||||
case EVENT_SHADOW_WRATH:
|
||||
DoCastVictim(SPELL_SHADOW_WRATH);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WRATH, 19s, 24s, 0, EVENT_PHASE_FIGHT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool frenzy40;
|
||||
bool frenzy15;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_lord_valthalakAI>(creature);
|
||||
_frenzy40 = false;
|
||||
_frenzy15 = false;
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
StartTalking(TALK_SUMMON, 8s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
Talk(TALK_AGGRO);
|
||||
|
||||
events.SetPhase(EVENT_PHASE_FIGHT);
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPECTRAL_ASSASSIN, 6s, 8s, 0, EVENT_PHASE_FIGHT);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WRATH, 9s, 18s, 0, EVENT_PHASE_FIGHT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
|
||||
instance->SetData(DATA_LORD_VALTHALAK, DONE);
|
||||
}
|
||||
|
||||
void StartTalking(uint32 talkGroupId, Milliseconds timer)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->AttackStop();
|
||||
|
||||
Talk(talkGroupId);
|
||||
|
||||
events.SetPhase(EVENT_PHASE_TALK);
|
||||
events.ScheduleEvent(EVENT_FIGHT, timer, 0, EVENT_PHASE_TALK);
|
||||
}
|
||||
|
||||
void StartFighting()
|
||||
{
|
||||
events.SetPhase(EVENT_PHASE_FIGHT);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!_frenzy40 && me->HealthBelowPctDamaged(40, damage))
|
||||
{
|
||||
_frenzy40 = true;
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
|
||||
events.CancelEvent(EVENT_SUMMON_SPECTRAL_ASSASSIN);
|
||||
|
||||
StartTalking(TALK_40_HP, 5s);
|
||||
}
|
||||
|
||||
if (!_frenzy15 && me->HealthBelowPctDamaged(15, damage))
|
||||
{
|
||||
_frenzy15 = true;
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 12s, 19s, 0, EVENT_PHASE_FIGHT);
|
||||
|
||||
StartTalking(TALK_15_HP, 5s);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() && !events.IsInPhase(EVENT_PHASE_TALK))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FIGHT:
|
||||
StartFighting();
|
||||
break;
|
||||
case EVENT_SUMMON_SPECTRAL_ASSASSIN:
|
||||
DoCast(me, SPELL_SUMMON_SPECTRAL_ASSASSIN);
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPECTRAL_ASSASSIN, 30s, 35s, 0, EVENT_PHASE_FIGHT);
|
||||
break;
|
||||
case EVENT_SHADOW_BOLT_VOLLEY:
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 4s, 6s, 0, EVENT_PHASE_FIGHT);
|
||||
break;
|
||||
case EVENT_SHADOW_WRATH:
|
||||
DoCastVictim(SPELL_SHADOW_WRATH);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WRATH, 19s, 24s, 0, EVENT_PHASE_FIGHT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _frenzy40;
|
||||
bool _frenzy15;
|
||||
};
|
||||
|
||||
void AddSC_boss_lord_valthalak()
|
||||
{
|
||||
new boss_lord_valthalak();
|
||||
RegisterBlackrockSpireCreatureAI(boss_lord_valthalak);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,13 +96,9 @@ struct boss_mor_grayhoof : public BossAI
|
|||
case PHASE_HUMAN:
|
||||
spell = Acore::Containers::SelectRandomContainerElement(humanSpells);
|
||||
if (spell == SPELL_REJUVENATION || spell == SPELL_HEALING_TOUCH)
|
||||
{
|
||||
DoCastSelf(spell);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastAOE(spell);
|
||||
}
|
||||
break;
|
||||
case PHASE_BEAR:
|
||||
spell = Acore::Containers::SelectRandomContainerElement(bearSpells);
|
||||
|
|
@ -155,9 +151,7 @@ struct boss_mor_grayhoof : public BossAI
|
|||
{
|
||||
CastRandomSpell(PHASE_BEAR);
|
||||
if (context.GetRepeatCounter() <= 3)
|
||||
{
|
||||
context.Repeat();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (_phase == PHASE_BEAR && me->HealthBelowPct(50.f))
|
||||
|
|
@ -170,9 +164,7 @@ struct boss_mor_grayhoof : public BossAI
|
|||
{
|
||||
CastRandomSpell(PHASE_CAT);
|
||||
if (context.GetRepeatCounter() <= 3)
|
||||
{
|
||||
context.Repeat();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (_phase == PHASE_CAT && me->HealthBelowPct(25.f))
|
||||
|
|
@ -203,9 +195,7 @@ struct boss_mor_grayhoof : public BossAI
|
|||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,93 +46,83 @@ constexpr uint32 CALL_HELP = 0;
|
|||
const Position SummonLocation1 = {-49.43f, -455.82f, 77.82f, 4.61f};
|
||||
const Position SummonLocation2 = {-58.48f, -456.29f, 77.82f, 4.613f};
|
||||
|
||||
class boss_overlord_wyrmthalak : public CreatureScript
|
||||
struct boss_overlord_wyrmthalak : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_overlord_wyrmthalak() : CreatureScript("boss_overlord_wyrmthalak") { }
|
||||
boss_overlord_wyrmthalak(Creature* creature) : BossAI(creature, DATA_OVERLORD_WYRMTHALAK) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_overlordwyrmthalakAI>(creature);
|
||||
_Reset();
|
||||
_summoned = false;
|
||||
}
|
||||
|
||||
struct boss_overlordwyrmthalakAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_overlordwyrmthalakAI(Creature* creature) : BossAI(creature, DATA_OVERLORD_WYRMTHALAK) { }
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 20s);
|
||||
events.ScheduleEvent(EVENT_SHOUT, 2s);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 6s);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s);
|
||||
}
|
||||
|
||||
bool Summoned;
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_OVERLORD_WYRMTHALAK, DONE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!_summoned && HealthBelowPct(51))
|
||||
{
|
||||
_Reset();
|
||||
Summoned = false;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 20s);
|
||||
events.ScheduleEvent(EVENT_SHOUT, 2s);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 6s);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_OVERLORD_WYRMTHALAK, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!Summoned && HealthBelowPct(51))
|
||||
Talk(CALL_HELP);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
Talk(CALL_HELP);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
if (Creature* warlord = me->SummonCreature(NPC_SPIRESTONE_WARLORD, SummonLocation1, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
||||
warlord->AI()->AttackStart(target);
|
||||
if (Creature* berserker = me->SummonCreature(NPC_SMOLDERTHORN_BERSERKER, SummonLocation2, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
||||
berserker->AI()->AttackStart(target);
|
||||
Summoned = true;
|
||||
}
|
||||
if (Creature* warlord = me->SummonCreature(NPC_SPIRESTONE_WARLORD, SummonLocation1, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
||||
warlord->AI()->AttackStart(target);
|
||||
if (Creature* berserker = me->SummonCreature(NPC_SMOLDERTHORN_BERSERKER, SummonLocation2, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
||||
berserker->AI()->AttackStart(target);
|
||||
_summoned = true;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BLAST_WAVE:
|
||||
DoCastVictim(SPELL_BLASTWAVE);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 20s);
|
||||
break;
|
||||
case EVENT_SHOUT:
|
||||
DoCastVictim(SPELL_SHOUT);
|
||||
events.ScheduleEvent(EVENT_SHOUT, 10s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 7s);
|
||||
break;
|
||||
case EVENT_KNOCK_AWAY:
|
||||
DoCastVictim(SPELL_KNOCKAWAY);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 14s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BLAST_WAVE:
|
||||
DoCastVictim(SPELL_BLASTWAVE);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 20s);
|
||||
break;
|
||||
case EVENT_SHOUT:
|
||||
DoCastVictim(SPELL_SHOUT);
|
||||
events.ScheduleEvent(EVENT_SHOUT, 10s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 7s);
|
||||
break;
|
||||
case EVENT_KNOCK_AWAY:
|
||||
DoCastVictim(SPELL_KNOCKAWAY);
|
||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 14s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _summoned;
|
||||
};
|
||||
|
||||
void AddSC_boss_overlordwyrmthalak()
|
||||
{
|
||||
new boss_overlord_wyrmthalak();
|
||||
RegisterBlackrockSpireCreatureAI(boss_overlord_wyrmthalak);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,241 +68,226 @@ enum Events
|
|||
EVENT_ENTER_COMBAT = 10
|
||||
};
|
||||
|
||||
class boss_pyroguard_emberseer : public CreatureScript
|
||||
struct boss_pyroguard_emberseer : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_pyroguard_emberseer() : CreatureScript("boss_pyroguard_emberseer") { }
|
||||
boss_pyroguard_emberseer(Creature* creature) : BossAI(creature, DATA_PYROGAURD_EMBERSEER) { }
|
||||
|
||||
struct boss_pyroguard_emberseerAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_pyroguard_emberseerAI(Creature* creature) : BossAI(creature, DATA_PYROGAURD_EMBERSEER) { }
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(true);
|
||||
events.Reset();
|
||||
// Apply auras on spawn and reset
|
||||
// DoCast(me, SPELL_FIRE_SHIELD_TRIGGER); // Need to find this in old DBC if possible
|
||||
me->RemoveAura(SPELL_EMBERSEER_FULL_STRENGTH);
|
||||
me->RemoveAura(SPELL_EMBERSEER_GROWING);
|
||||
me->RemoveAura(SPELL_EMBERSEER_GROWING_TRIGGER);
|
||||
events.ScheduleEvent(EVENT_RESPAWN, 5s);
|
||||
// Hack for missing trigger spell
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||
|
||||
void Reset() override
|
||||
// Open doors on reset
|
||||
if (instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS)
|
||||
OpenDoors(false); // Opens 2 entrance doors
|
||||
}
|
||||
|
||||
void SetData(uint32 /*type*/, uint32 data) override
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(true);
|
||||
events.Reset();
|
||||
// Apply auras on spawn and reset
|
||||
// DoCast(me, SPELL_FIRE_SHIELD_TRIGGER); // Need to find this in old DBC if possible
|
||||
me->RemoveAura(SPELL_EMBERSEER_FULL_STRENGTH);
|
||||
me->RemoveAura(SPELL_EMBERSEER_GROWING);
|
||||
me->RemoveAura(SPELL_EMBERSEER_GROWING_TRIGGER);
|
||||
events.ScheduleEvent(EVENT_RESPAWN, 5s);
|
||||
// Hack for missing trigger spell
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||
|
||||
// Open doors on reset
|
||||
if (instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS)
|
||||
OpenDoors(false); // Opens 2 entrance doors
|
||||
case 1:
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_1, 2s);
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS);
|
||||
break;
|
||||
case 2:
|
||||
// Close these two doors on Blackhand Incarcerators aggro
|
||||
if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_IN)))
|
||||
if (door1->GetGoState() == GO_STATE_ACTIVE)
|
||||
door1->SetGoState(GO_STATE_READY);
|
||||
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_DOORS)))
|
||||
if (door2->GetGoState() == GO_STATE_ACTIVE)
|
||||
door2->SetGoState(GO_STATE_READY);
|
||||
break;
|
||||
case 3:
|
||||
Reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 /*type*/, uint32 data) override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
// ### TODO Check combat timing ###
|
||||
events.ScheduleEvent(EVENT_FIRENOVA, 6s);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 3s);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 14s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
// Activate all the runes
|
||||
UpdateRunes(GO_STATE_READY);
|
||||
// Opens all 3 doors
|
||||
OpenDoors(true);
|
||||
// Complete encounter
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, DONE);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_ENCAGE_EMBERSEER)
|
||||
if (!me->GetAuraCount(SPELL_ENCAGED_EMBERSEER))
|
||||
me->CastSpell(me, SPELL_ENCAGED_EMBERSEER);
|
||||
|
||||
if (spell->Id == SPELL_EMBERSEER_GROWING_TRIGGER)
|
||||
{
|
||||
switch (data)
|
||||
if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 10)
|
||||
Talk(EMOTE_TEN_STACK);
|
||||
|
||||
if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 20)
|
||||
{
|
||||
case 1:
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_1, 2s);
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS);
|
||||
break;
|
||||
case 2:
|
||||
// Close these two doors on Blackhand Incarcerators aggro
|
||||
if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_IN)))
|
||||
if (door1->GetGoState() == GO_STATE_ACTIVE)
|
||||
door1->SetGoState(GO_STATE_READY);
|
||||
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_DOORS)))
|
||||
if (door2->GetGoState() == GO_STATE_ACTIVE)
|
||||
door2->SetGoState(GO_STATE_READY);
|
||||
break;
|
||||
case 3:
|
||||
Reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
events.CancelEvent(EVENT_FIRE_SHIELD); // temporarily cancel fire shield to keep it from interrupting combat start
|
||||
|
||||
// Schedule out the pre-combat scene
|
||||
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_1, 0s);
|
||||
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_2, 2s);
|
||||
events.ScheduleEvent(EVENT_ENTER_COMBAT, 5s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void OpenDoors(bool Boss_Killed)
|
||||
{
|
||||
// These two doors reopen on reset or boss kill
|
||||
if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_IN)))
|
||||
door1->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_DOORS)))
|
||||
door2->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
// This door opens on boss kill
|
||||
if (Boss_Killed)
|
||||
if (GameObject* door3 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_OUT)))
|
||||
door3->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
void UpdateRunes(GOState state)
|
||||
{
|
||||
// update all runes
|
||||
if (GameObject* rune1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_1)))
|
||||
rune1->SetGoState(state);
|
||||
if (GameObject* rune2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_2)))
|
||||
rune2->SetGoState(state);
|
||||
if (GameObject* rune3 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_3)))
|
||||
rune3->SetGoState(state);
|
||||
if (GameObject* rune4 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_4)))
|
||||
rune4->SetGoState(state);
|
||||
if (GameObject* rune5 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_5)))
|
||||
rune5->SetGoState(state);
|
||||
if (GameObject* rune6 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_6)))
|
||||
rune6->SetGoState(state);
|
||||
if (GameObject* rune7 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_7)))
|
||||
rune7->SetGoState(state);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
// ### TODO Check combat timing ###
|
||||
events.ScheduleEvent(EVENT_FIRENOVA, 6s);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 3s);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 14s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
// Activate all the runes
|
||||
UpdateRunes(GO_STATE_READY);
|
||||
// Opens all 3 doors
|
||||
OpenDoors(true);
|
||||
// Complete encounter
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, DONE);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_ENCAGE_EMBERSEER)
|
||||
{
|
||||
if (!me->GetAuraCount(SPELL_ENCAGED_EMBERSEER))
|
||||
me->CastSpell(me, SPELL_ENCAGED_EMBERSEER);
|
||||
}
|
||||
|
||||
if (spell->Id == SPELL_EMBERSEER_GROWING_TRIGGER)
|
||||
{
|
||||
if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 10)
|
||||
Talk(EMOTE_TEN_STACK);
|
||||
|
||||
if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 20)
|
||||
{
|
||||
events.CancelEvent(EVENT_FIRE_SHIELD); // temporarily cancel fire shield to keep it from interrupting combat start
|
||||
|
||||
// Schedule out the pre-combat scene
|
||||
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_1, 0s);
|
||||
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_2, 2s);
|
||||
events.ScheduleEvent(EVENT_ENTER_COMBAT, 5s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenDoors(bool Boss_Killed)
|
||||
{
|
||||
// These two doors reopen on reset or boss kill
|
||||
if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_IN)))
|
||||
door1->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_DOORS)))
|
||||
door2->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
// This door opens on boss kill
|
||||
if (Boss_Killed)
|
||||
if (GameObject* door3 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_OUT)))
|
||||
door3->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
void UpdateRunes(GOState state)
|
||||
{
|
||||
// update all runes
|
||||
if (GameObject* rune1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_1)))
|
||||
rune1->SetGoState(state);
|
||||
if (GameObject* rune2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_2)))
|
||||
rune2->SetGoState(state);
|
||||
if (GameObject* rune3 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_3)))
|
||||
rune3->SetGoState(state);
|
||||
if (GameObject* rune4 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_4)))
|
||||
rune4->SetGoState(state);
|
||||
if (GameObject* rune5 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_5)))
|
||||
rune5->SetGoState(state);
|
||||
if (GameObject* rune6 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_6)))
|
||||
rune6->SetGoState(state);
|
||||
if (GameObject* rune7 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_RUNE_7)))
|
||||
rune7->SetGoState(state);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RESPAWN:
|
||||
{
|
||||
// Respawn all Blackhand Incarcerators
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 35.0f);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
if (Creature* creature = *itr)
|
||||
{
|
||||
if (!creature->IsAlive())
|
||||
creature->Respawn();
|
||||
|
||||
creature->AI()->SetData(1, 2);
|
||||
}
|
||||
me->AddAura(SPELL_ENCAGED_EMBERSEER, me);
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, NOT_STARTED);
|
||||
break;
|
||||
}
|
||||
case EVENT_PRE_FIGHT_1:
|
||||
{
|
||||
// Set data on all Blackhand Incarcerators
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 35.0f);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
{
|
||||
if (Creature* creature = *itr)
|
||||
creature->AI()->SetData(1, 1);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_2, 2s);
|
||||
break;
|
||||
}
|
||||
case EVENT_PRE_FIGHT_2:
|
||||
me->CastSpell(me, SPELL_FREEZE_ANIM);
|
||||
me->CastSpell(me, SPELL_EMBERSEER_GROWING);
|
||||
Talk(EMOTE_ONE_STACK);
|
||||
break;
|
||||
case EVENT_FIRE_SHIELD:
|
||||
// #### Spell isn't doing any damage ??? ####
|
||||
DoCast(me, SPELL_FIRE_SHIELD);
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||
break;
|
||||
case EVENT_PRE_ENTER_COMBAT_1:
|
||||
me->RemoveAura(SPELL_ENCAGED_EMBERSEER);
|
||||
me->RemoveAura(SPELL_FREEZE_ANIM);
|
||||
me->CastSpell(me, SPELL_EMBERSEER_FULL_STRENGTH);
|
||||
Talk(EMOTE_FREE_OF_BONDS);
|
||||
break;
|
||||
case EVENT_PRE_ENTER_COMBAT_2:
|
||||
Talk(YELL_FREE_OF_BONDS);
|
||||
break;
|
||||
case EVENT_ENTER_COMBAT:
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(false);
|
||||
DoZoneInCombat();
|
||||
// re-enable fire shield
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 0s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RESPAWN:
|
||||
{
|
||||
// Respawn all Blackhand Incarcerators
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 35.0f);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
if (Creature* creature = *itr)
|
||||
{
|
||||
if (!creature->IsAlive())
|
||||
creature->Respawn();
|
||||
|
||||
creature->AI()->SetData(1, 2);
|
||||
}
|
||||
me->AddAura(SPELL_ENCAGED_EMBERSEER, me);
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, NOT_STARTED);
|
||||
break;
|
||||
}
|
||||
case EVENT_PRE_FIGHT_1:
|
||||
{
|
||||
// Set data on all Blackhand Incarcerators
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 35.0f);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
if (Creature* creature = *itr)
|
||||
creature->AI()->SetData(1, 1);
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_2, 2s);
|
||||
break;
|
||||
}
|
||||
case EVENT_PRE_FIGHT_2:
|
||||
me->CastSpell(me, SPELL_FREEZE_ANIM);
|
||||
me->CastSpell(me, SPELL_EMBERSEER_GROWING);
|
||||
Talk(EMOTE_ONE_STACK);
|
||||
break;
|
||||
case EVENT_FIRE_SHIELD:
|
||||
// #### Spell isn't doing any damage ??? ####
|
||||
DoCast(me, SPELL_FIRE_SHIELD);
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||
break;
|
||||
case EVENT_FIRENOVA:
|
||||
DoCast(me, SPELL_FIRENOVA);
|
||||
events.ScheduleEvent(EVENT_FIRENOVA, 6s);
|
||||
case EVENT_PRE_ENTER_COMBAT_1:
|
||||
me->RemoveAura(SPELL_ENCAGED_EMBERSEER);
|
||||
me->RemoveAura(SPELL_FREEZE_ANIM);
|
||||
me->CastSpell(me, SPELL_EMBERSEER_FULL_STRENGTH);
|
||||
Talk(EMOTE_FREE_OF_BONDS);
|
||||
break;
|
||||
case EVENT_FLAMEBUFFET:
|
||||
DoCast(me, SPELL_FLAMEBUFFET);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 14s);
|
||||
case EVENT_PRE_ENTER_COMBAT_2:
|
||||
Talk(YELL_FREE_OF_BONDS);
|
||||
break;
|
||||
case EVENT_PYROBLAST:
|
||||
DoCastRandomTarget(SPELL_PYROBLAST, 0, 100.0f);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 15s);
|
||||
case EVENT_ENTER_COMBAT:
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(false);
|
||||
DoZoneInCombat();
|
||||
// re-enable fire shield
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 0s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_pyroguard_emberseerAI>(creature);
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FIRE_SHIELD:
|
||||
DoCast(me, SPELL_FIRE_SHIELD);
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||
break;
|
||||
case EVENT_FIRENOVA:
|
||||
DoCast(me, SPELL_FIRENOVA);
|
||||
events.ScheduleEvent(EVENT_FIRENOVA, 6s);
|
||||
break;
|
||||
case EVENT_FLAMEBUFFET:
|
||||
DoCast(me, SPELL_FLAMEBUFFET);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 14s);
|
||||
break;
|
||||
case EVENT_PYROBLAST:
|
||||
DoCastRandomTarget(SPELL_PYROBLAST, 0, 100.0f);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 15s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -321,127 +306,114 @@ enum IncarceratorData
|
|||
EMOTE_FLEE = 0
|
||||
};
|
||||
|
||||
class npc_blackhand_incarcerator : public CreatureScript
|
||||
struct npc_blackhand_incarcerator : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_blackhand_incarcerator() : CreatureScript("npc_blackhand_incarcerator") { }
|
||||
|
||||
struct npc_blackhand_incarceratorAI : public ScriptedAI
|
||||
npc_blackhand_incarcerator(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
npc_blackhand_incarceratorAI(Creature* creature) : ScriptedAI(creature)
|
||||
_fleedForAssistance = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetImmuneToAll(true);
|
||||
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||
Emberseer->AI()->SetData(1, 3);
|
||||
|
||||
_fleedForAssistance = false;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!_fleedForAssistance && me->HealthBelowPctDamaged(30, damage))
|
||||
{
|
||||
_fleedForAssistance = false;
|
||||
_fleedForAssistance = true;
|
||||
me->DoFleeToGetAssistance();
|
||||
Talk(EMOTE_FLEE);
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 data, uint32 value) override
|
||||
{
|
||||
if (data == 1 && value == 1)
|
||||
{
|
||||
me->SetImmuneToAll(false);
|
||||
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||
DoZoneInCombat();
|
||||
_events.CancelEvent(EVENT_ENCAGED_EMBERSEER);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
if (data == 1 && value == 2)
|
||||
_events.ScheduleEvent(EVENT_ENCAGED_EMBERSEER, 1s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
// Used to close doors
|
||||
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||
Emberseer->AI()->SetData(1, 2);
|
||||
|
||||
// Had to do this because CallForHelp will ignore any npcs without LOS
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 60.0f);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
if (Creature* creature = *itr)
|
||||
creature->SetInCombatWithZone(); // AI()->AttackStart(me->GetVictim());
|
||||
|
||||
_events.ScheduleEvent(EVENT_STRIKE, 8s, 16s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
me->SetImmuneToAll(true);
|
||||
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||
Emberseer->AI()->SetData(1, 3);
|
||||
|
||||
_fleedForAssistance = false;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!_fleedForAssistance && me->HealthBelowPctDamaged(30, damage))
|
||||
{
|
||||
_fleedForAssistance = true;
|
||||
me->DoFleeToGetAssistance();
|
||||
Talk(EMOTE_FLEE);
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 data, uint32 value) override
|
||||
{
|
||||
if (data == 1 && value == 1)
|
||||
{
|
||||
me->SetImmuneToAll(false);
|
||||
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||
DoZoneInCombat();
|
||||
_events.CancelEvent(EVENT_ENCAGED_EMBERSEER);
|
||||
}
|
||||
|
||||
if (data == 1 && value == 2)
|
||||
_events.ScheduleEvent(EVENT_ENCAGED_EMBERSEER, 1s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
// Used to close doors
|
||||
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||
Emberseer->AI()->SetData(1, 2);
|
||||
|
||||
// Had to do this because CallForHelp will ignore any npcs without LOS
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 60.0f);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
{
|
||||
if (Creature* creature = *itr)
|
||||
creature->SetInCombatWithZone(); // AI()->AttackStart(me->GetVictim());
|
||||
}
|
||||
|
||||
_events.ScheduleEvent(EVENT_STRIKE, 8s, 16s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_ENCAGED_EMBERSEER:
|
||||
{
|
||||
if (me->GetPositionX() == me->GetHomePosition().GetPositionX())
|
||||
if (!me->HasAura(SPELL_ENCAGE_EMBERSEER))
|
||||
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||
DoCast(Emberseer, SPELL_ENCAGE_EMBERSEER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_STRIKE:
|
||||
DoCastVictim(SPELL_STRIKE, true);
|
||||
_events.ScheduleEvent(EVENT_STRIKE, 14s, 23s);
|
||||
break;
|
||||
case EVENT_ENCAGE:
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 100, true), EVENT_ENCAGE, true);
|
||||
_events.ScheduleEvent(EVENT_ENCAGE, 6s, 12s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case EVENT_ENCAGED_EMBERSEER:
|
||||
{
|
||||
if (me->GetPositionX() == me->GetHomePosition().GetPositionX())
|
||||
if (!me->HasAura(SPELL_ENCAGE_EMBERSEER))
|
||||
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||
DoCast(Emberseer, SPELL_ENCAGE_EMBERSEER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
bool _fleedForAssistance;
|
||||
};
|
||||
_events.Update(diff);
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<npc_blackhand_incarceratorAI>(creature);
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_STRIKE:
|
||||
DoCastVictim(SPELL_STRIKE, true);
|
||||
_events.ScheduleEvent(EVENT_STRIKE, 14s, 23s);
|
||||
break;
|
||||
case EVENT_ENCAGE:
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 100, true), EVENT_ENCAGE, true);
|
||||
_events.ScheduleEvent(EVENT_ENCAGE, 6s, 12s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
bool _fleedForAssistance;
|
||||
};
|
||||
|
||||
void AddSC_boss_pyroguard_emberseer()
|
||||
{
|
||||
new boss_pyroguard_emberseer();
|
||||
new npc_blackhand_incarcerator();
|
||||
RegisterBlackrockSpireCreatureAI(boss_pyroguard_emberseer);
|
||||
RegisterBlackrockSpireCreatureAI(npc_blackhand_incarcerator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,16 +87,12 @@ struct boss_quartermaster_zigris : public BossAI
|
|||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
|
|
@ -135,9 +131,7 @@ struct boss_quartermaster_zigris : public BossAI
|
|||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
|
|
|
|||
|
|
@ -99,346 +99,327 @@ enum Events
|
|||
EVENT_MORTAL_STRIKE = 32,
|
||||
};
|
||||
|
||||
class boss_rend_blackhand : public CreatureScript
|
||||
struct boss_rend_blackhand : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_rend_blackhand() : CreatureScript("boss_rend_blackhand") { }
|
||||
boss_rend_blackhand(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND) { }
|
||||
|
||||
struct boss_rend_blackhandAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_rend_blackhandAI(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND) { }
|
||||
_Reset();
|
||||
|
||||
void Reset() override
|
||||
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
||||
{
|
||||
_Reset();
|
||||
|
||||
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PREPARATION);
|
||||
me->SetImmuneToAll(false);
|
||||
return;
|
||||
}
|
||||
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PREPARATION);
|
||||
me->SetImmuneToAll(true);
|
||||
gythEvent = false;
|
||||
victorGUID.Clear();
|
||||
waveDoorGUID.Clear();
|
||||
_currentWave = 0;
|
||||
|
||||
summons.DespawnAll();
|
||||
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f, true))
|
||||
victor->Respawn(true);
|
||||
|
||||
if (GameObject* exitDoor = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GYTH_ENTRY_DOOR)))
|
||||
exitDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, NOT_STARTED);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PREPARATION);
|
||||
me->SetImmuneToAll(false);
|
||||
return;
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* /*creature*/, Unit* /*killer*/) override
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PREPARATION);
|
||||
me->SetImmuneToAll(true);
|
||||
_gythEvent = false;
|
||||
_victorGUID.Clear();
|
||||
_waveDoorGUID.Clear();
|
||||
_currentWave = 0;
|
||||
|
||||
summons.DespawnAll();
|
||||
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f, true))
|
||||
victor->Respawn(true);
|
||||
|
||||
if (GameObject* exitDoor = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GYTH_ENTRY_DOOR)))
|
||||
exitDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, NOT_STARTED);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* /*creature*/, Unit* /*killer*/) override
|
||||
{
|
||||
if (!summons.IsAnyCreatureAlive())
|
||||
events.ScheduleEvent(EVENT_WAVES_TEXT_1 + _currentWave, 10s);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
|
||||
if (summon->GetEntry() == NPC_GYTH)
|
||||
{
|
||||
if (!summons.IsAnyCreatureAlive())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_WAVES_TEXT_1 + _currentWave, 10s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
|
||||
if (summon->GetEntry() == NPC_GYTH)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
summon->AI()->DoZoneInCombat(nullptr, 100.0f);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 13s, 15s);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 15s, 17s);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 17s, 19s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
|
||||
instance->SetBossState(DATA_GYTH, FAIL);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
summon->AI()->DoZoneInCombat(nullptr, 100.0f);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 13s, 15s);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 15s, 17s);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 17s, 19s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
|
||||
instance->SetBossState(DATA_GYTH, FAIL);
|
||||
BossAI::EnterEvadeMode(why);
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
Talk(EMOTE_BLACKHAND_DISMOUNT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 75.0f, true))
|
||||
victor->AI()->SetData(1, 2);
|
||||
|
||||
if (GameObject* exitDoor = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GYTH_ENTRY_DOOR)))
|
||||
exitDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, DONE);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* creature) override
|
||||
{
|
||||
if (creature->IsAlive() && !summons.IsAnyCreatureInCombat())
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
|
||||
|
||||
BossAI::SummonedCreatureDespawn(creature);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == AREATRIGGER && data == AREATRIGGER_BLACKROCK_STADIUM)
|
||||
{
|
||||
Talk(EMOTE_BLACKHAND_DISMOUNT);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 75.0f, true))
|
||||
victor->AI()->SetData(1, 2);
|
||||
|
||||
if (GameObject* exitDoor = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GYTH_ENTRY_DOOR)))
|
||||
exitDoor->SetGoState(GO_STATE_ACTIVE);
|
||||
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, DONE);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* creature) override
|
||||
{
|
||||
if (creature->IsAlive() && !summons.IsAnyCreatureInCombat())
|
||||
if (!_gythEvent)
|
||||
{
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
|
||||
}
|
||||
_gythEvent = true;
|
||||
|
||||
BossAI::SummonedCreatureDespawn(creature);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == AREATRIGGER && data == AREATRIGGER_BLACKROCK_STADIUM)
|
||||
{
|
||||
if (!gythEvent)
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f))
|
||||
{
|
||||
gythEvent = true;
|
||||
if (!victor->IsAlive())
|
||||
victor->Respawn(true);
|
||||
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f))
|
||||
{
|
||||
if (!victor->IsAlive())
|
||||
{
|
||||
victor->Respawn(true);
|
||||
}
|
||||
|
||||
victorGUID = victor->GetGUID();
|
||||
}
|
||||
|
||||
if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 50.0f))
|
||||
waveDoorGUID = portcullis->GetGUID();
|
||||
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
events.ScheduleEvent(EVENT_START_1, 1s);
|
||||
_victorGUID = victor->GetGUID();
|
||||
}
|
||||
|
||||
if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 50.0f))
|
||||
_waveDoorGUID = portcullis->GetGUID();
|
||||
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
events.ScheduleEvent(EVENT_START_1, 1s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == WAYPOINT_MOTION_TYPE)
|
||||
{
|
||||
if (type == WAYPOINT_MOTION_TYPE)
|
||||
switch (id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 6:
|
||||
events.ScheduleEvent(EVENT_TELEPORT_1, 2s);
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
events.ScheduleEvent(EVENT_TELEPORT_1, 2s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_gythEvent)
|
||||
{
|
||||
if (gythEvent)
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_START_1:
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, IN_PROGRESS);
|
||||
instance->SetData(DATA_VAELASTRASZ, NOT_STARTED);
|
||||
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_0);
|
||||
|
||||
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GYTH_ENTRY_DOOR)))
|
||||
door2->SetGoState(GO_STATE_READY);
|
||||
|
||||
events.ScheduleEvent(EVENT_START_2, 4s);
|
||||
break;
|
||||
case EVENT_START_2:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
|
||||
events.ScheduleEvent(EVENT_START_3, 4s);
|
||||
break;
|
||||
case EVENT_START_3:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_1);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 2s);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_REND, 4s);
|
||||
break;
|
||||
case EVENT_TURN_TO_REND:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
{
|
||||
victor->SetFacingToObject(me);
|
||||
victor->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
}
|
||||
break;
|
||||
case EVENT_TURN_TO_PLAYER:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
if (Unit* player = victor->SelectNearestPlayer(60.0f))
|
||||
victor->SetFacingToObject(player);
|
||||
break;
|
||||
case EVENT_TURN_TO_FACING_1:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->SetFacingTo(1.518436f);
|
||||
break;
|
||||
case EVENT_TURN_TO_FACING_2:
|
||||
me->SetFacingTo(1.658063f);
|
||||
break;
|
||||
case EVENT_TURN_TO_FACING_3:
|
||||
me->SetFacingTo(1.500983f);
|
||||
break;
|
||||
case EVENT_WAVES_EMOTE_1:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->HandleEmoteCommand(EMOTE_ONESHOT_QUESTION);
|
||||
break;
|
||||
case EVENT_WAVES_EMOTE_2:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_1:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_2);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_WAVES_EMOTE_1, 5s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_2:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_3);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_3:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_4);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_4:
|
||||
Talk(SAY_BLACKHAND_1);
|
||||
events.ScheduleEvent(EVENT_WAVES_EMOTE_2, 4s);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_3, 8s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_5:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_5);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_COMPLETE_TEXT_1:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_6);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_WAVES_COMPLETE_TEXT_2, 13s);
|
||||
break;
|
||||
case EVENT_WAVES_COMPLETE_TEXT_2:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_7);
|
||||
Talk(SAY_BLACKHAND_2);
|
||||
events.ScheduleEvent(EVENT_PATH_REND, 1s);
|
||||
events.ScheduleEvent(EVENT_WAVES_COMPLETE_TEXT_3, 4s);
|
||||
break;
|
||||
case EVENT_WAVES_COMPLETE_TEXT_3:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_8);
|
||||
events.ScheduleEvent(EVENT_PATH_NEFARIUS, 1s);
|
||||
events.ScheduleEvent(EVENT_PATH_REND, 1s);
|
||||
break;
|
||||
case EVENT_PATH_NEFARIUS:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_1, true);
|
||||
break;
|
||||
case EVENT_PATH_REND:
|
||||
me->GetMotionMaster()->MoveWaypoint(REND_PATH_1, false);
|
||||
break;
|
||||
case EVENT_TELEPORT_1:
|
||||
me->NearTeleportTo(194.2993f, -474.0814f, 121.4505f, -0.01225555f);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_2, 13s);
|
||||
break;
|
||||
case EVENT_TELEPORT_2:
|
||||
me->NearTeleportTo(216.485f, -434.93f, 110.888f, -0.01225555f);
|
||||
me->SummonCreature(NPC_GYTH, 211.762f, -397.5885f, 111.1817f, 4.747295f);
|
||||
break;
|
||||
case EVENT_SPAWN_WAVE:
|
||||
SummonWave();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_WHIRLWIND:
|
||||
DoCast(SPELL_WHIRLWIND);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 13s, 18s);
|
||||
case EVENT_START_1:
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, IN_PROGRESS);
|
||||
instance->SetData(DATA_VAELASTRASZ, NOT_STARTED);
|
||||
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_0);
|
||||
|
||||
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_GYTH_ENTRY_DOOR)))
|
||||
door2->SetGoState(GO_STATE_READY);
|
||||
|
||||
events.ScheduleEvent(EVENT_START_2, 4s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 10s, 14s);
|
||||
case EVENT_START_2:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
|
||||
events.ScheduleEvent(EVENT_START_3, 4s);
|
||||
break;
|
||||
case EVENT_MORTAL_STRIKE:
|
||||
DoCastVictim(SPELL_MORTAL_STRIKE);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 14s, 18s);
|
||||
case EVENT_START_3:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_1);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 2s);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_REND, 4s);
|
||||
break;
|
||||
case EVENT_TURN_TO_REND:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
{
|
||||
victor->SetFacingToObject(me);
|
||||
victor->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
}
|
||||
break;
|
||||
case EVENT_TURN_TO_PLAYER:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
if (Unit* player = victor->SelectNearestPlayer(60.0f))
|
||||
victor->SetFacingToObject(player);
|
||||
break;
|
||||
case EVENT_TURN_TO_FACING_1:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->SetFacingTo(1.518436f);
|
||||
break;
|
||||
case EVENT_TURN_TO_FACING_2:
|
||||
me->SetFacingTo(1.658063f);
|
||||
break;
|
||||
case EVENT_TURN_TO_FACING_3:
|
||||
me->SetFacingTo(1.500983f);
|
||||
break;
|
||||
case EVENT_WAVES_EMOTE_1:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->HandleEmoteCommand(EMOTE_ONESHOT_QUESTION);
|
||||
break;
|
||||
case EVENT_WAVES_EMOTE_2:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_1:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_2);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_WAVES_EMOTE_1, 5s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_2:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_3);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_3:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_4);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_4:
|
||||
Talk(SAY_BLACKHAND_1);
|
||||
events.ScheduleEvent(EVENT_WAVES_EMOTE_2, 4s);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_3, 8s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_TEXT_5:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_5);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_WAVE, 3s);
|
||||
break;
|
||||
case EVENT_WAVES_COMPLETE_TEXT_1:
|
||||
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_6);
|
||||
events.ScheduleEvent(EVENT_TURN_TO_FACING_1, 4s);
|
||||
events.ScheduleEvent(EVENT_WAVES_COMPLETE_TEXT_2, 13s);
|
||||
break;
|
||||
case EVENT_WAVES_COMPLETE_TEXT_2:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_7);
|
||||
Talk(SAY_BLACKHAND_2);
|
||||
events.ScheduleEvent(EVENT_PATH_REND, 1s);
|
||||
events.ScheduleEvent(EVENT_WAVES_COMPLETE_TEXT_3, 4s);
|
||||
break;
|
||||
case EVENT_WAVES_COMPLETE_TEXT_3:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_8);
|
||||
events.ScheduleEvent(EVENT_PATH_NEFARIUS, 1s);
|
||||
events.ScheduleEvent(EVENT_PATH_REND, 1s);
|
||||
break;
|
||||
case EVENT_PATH_NEFARIUS:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
victor->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_1, true);
|
||||
break;
|
||||
case EVENT_PATH_REND:
|
||||
me->GetMotionMaster()->MoveWaypoint(REND_PATH_1, false);
|
||||
break;
|
||||
case EVENT_TELEPORT_1:
|
||||
me->NearTeleportTo(194.2993f, -474.0814f, 121.4505f, -0.01225555f);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_2, 13s);
|
||||
break;
|
||||
case EVENT_TELEPORT_2:
|
||||
me->NearTeleportTo(216.485f, -434.93f, 110.888f, -0.01225555f);
|
||||
me->SummonCreature(NPC_GYTH, 211.762f, -397.5885f, 111.1817f, 4.747295f);
|
||||
break;
|
||||
case EVENT_SPAWN_WAVE:
|
||||
SummonWave();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void SummonWave()
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
me->SummonCreatureGroup(_currentWave);
|
||||
|
||||
if (GameObject* waveDoor = me->GetMap()->GetGameObject(waveDoorGUID))
|
||||
switch (eventId)
|
||||
{
|
||||
waveDoor->UseDoorOrButton();
|
||||
case EVENT_WHIRLWIND:
|
||||
DoCast(SPELL_WHIRLWIND);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 13s, 18s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 10s, 14s);
|
||||
break;
|
||||
case EVENT_MORTAL_STRIKE:
|
||||
DoCastVictim(SPELL_MORTAL_STRIKE);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 14s, 18s);
|
||||
break;
|
||||
}
|
||||
|
||||
++_currentWave;
|
||||
}
|
||||
|
||||
private:
|
||||
bool gythEvent;
|
||||
uint8 _currentWave;
|
||||
ObjectGuid victorGUID;
|
||||
ObjectGuid waveDoorGUID;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_rend_blackhandAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void SummonWave()
|
||||
{
|
||||
me->SummonCreatureGroup(_currentWave);
|
||||
|
||||
if (GameObject* waveDoor = me->GetMap()->GetGameObject(_waveDoorGUID))
|
||||
waveDoor->UseDoorOrButton();
|
||||
|
||||
++_currentWave;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _gythEvent;
|
||||
uint8 _currentWave;
|
||||
ObjectGuid _victorGUID;
|
||||
ObjectGuid _waveDoorGUID;
|
||||
};
|
||||
|
||||
void AddSC_boss_rend_blackhand()
|
||||
{
|
||||
new boss_rend_blackhand();
|
||||
RegisterBlackrockSpireCreatureAI(boss_rend_blackhand);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,211 +38,178 @@ enum Says
|
|||
SAY_SUMMON = 0,
|
||||
};
|
||||
|
||||
class npc_rookery_hatcher : public CreatureScript
|
||||
struct npc_rookery_hatcher : public CreatureAI
|
||||
{
|
||||
public:
|
||||
npc_rookery_hatcher() : CreatureScript("npc_rookery_hatcher") {}
|
||||
npc_rookery_hatcher(Creature* creature) : CreatureAI(creature) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
EventMap events;
|
||||
GameObject* targetEgg;
|
||||
Position targetPosition;
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
return GetBlackrockSpireAI<npc_rookery_hatcherAI>(creature);
|
||||
CreatureAI::InitializeAI();
|
||||
DoZoneInCombat(nullptr, 100.0f);
|
||||
targetEgg = nullptr;
|
||||
}
|
||||
|
||||
struct npc_rookery_hatcherAI : public CreatureAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
npc_rookery_hatcherAI(Creature* creature) : CreatureAI(creature) {}
|
||||
events.ScheduleEvent(SPELL_HATCH_EGG, 1s);
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
std::list<GameObject*> nearbyEggs;
|
||||
GameObject* targetEgg;
|
||||
Position targetPosition;
|
||||
float tempDist = 20;
|
||||
float minDist = 25;
|
||||
std::list<Creature*> nearbyWhelps;
|
||||
|
||||
void InitializeAI() override
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
GetCreatureListWithEntryInGrid(nearbyWhelps, me, NPC_ROOKERY_WHELP, RANGE_WHELP_CALL_HELP);
|
||||
for (auto const& whelp : nearbyWhelps)
|
||||
{
|
||||
CreatureAI::InitializeAI();
|
||||
DoZoneInCombat(nullptr, 100.0f);
|
||||
nearbyEggs.clear();
|
||||
targetEgg = nullptr;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(SPELL_HATCH_EGG, 1s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
std::list<GameObject*> nearbyEggs;
|
||||
float tempDist = 20;
|
||||
float minDist = 25;
|
||||
std::list<Creature*> nearbyWhelps;
|
||||
|
||||
if (!UpdateVictim())
|
||||
if (!whelp->IsInCombat())
|
||||
{
|
||||
return;
|
||||
whelp->SetInCombatWith(me->GetVictim());
|
||||
whelp->AI()->AttackStart(me->GetVictim());
|
||||
}
|
||||
|
||||
GetCreatureListWithEntryInGrid(nearbyWhelps, me, NPC_ROOKERY_WHELP, RANGE_WHELP_CALL_HELP);
|
||||
for (auto const& whelp : nearbyWhelps)
|
||||
{
|
||||
if (!whelp->IsInCombat())
|
||||
{
|
||||
whelp->SetInCombatWith(me->GetVictim());
|
||||
whelp->AI()->AttackStart(me->GetVictim());
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_HATCH_EGG:
|
||||
if (!targetEgg) // no target, try to find one
|
||||
{
|
||||
minDist = 50;
|
||||
tempDist = 50;
|
||||
me->GetGameObjectListWithEntryInGrid(nearbyEggs, GO_ROOKERY_EGG, 40);
|
||||
for (auto const& egg : nearbyEggs)
|
||||
{
|
||||
if (egg->isSpawned() && egg->getLootState() == GO_READY)
|
||||
{
|
||||
tempDist = me->GetDistance2d(egg);
|
||||
if (tempDist < minDist)
|
||||
{
|
||||
minDist = tempDist;
|
||||
targetEgg = egg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetEgg) //have a target, go to it and cast it
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(0, targetEgg->GetPosition());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// cast takes 1.5second, during which we don't have a target
|
||||
if (targetEgg && targetEgg->getLootState() == GO_READY && me->GetDistance2d(targetEgg) < RANGE_SPELL_HATCH_EGG)
|
||||
{
|
||||
me->StopMovingOnCurrentPos();
|
||||
me->SetFacingToObject(targetEgg);
|
||||
targetPosition = me->GetPosition();
|
||||
DoCast(SPELL_HATCH_EGG);
|
||||
targetEgg = nullptr;
|
||||
events.ScheduleEvent(SPELL_HATCH_EGG, 6s, 8s);
|
||||
}
|
||||
else if (!me->HasUnitState(UNIT_STATE_CASTING) && !targetEgg)
|
||||
{
|
||||
if (Unit* victim = me->GetVictim())
|
||||
{
|
||||
AttackStart(victim);
|
||||
}
|
||||
|
||||
if (me->GetDistance2d(me->GetVictim()) > me->GetMeleeReach())
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(0, me->GetVictim()->GetPosition()); // a bit hacky, but needed to start moving once we've summoned an egg
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class boss_solakar_flamewreath : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_solakar_flamewreath() : CreatureScript("boss_solakar_flamewreath") { }
|
||||
|
||||
struct boss_solakar_flamewreathAI : public BossAI
|
||||
{
|
||||
boss_solakar_flamewreathAI(Creature* creature) : BossAI(creature, DATA_SOLAKAR_FLAMEWREATH) {}
|
||||
|
||||
uint32 resetTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
resetTimer = 10000;
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
Talk(SAY_SUMMON);
|
||||
DoZoneInCombat(nullptr, 100.0f);
|
||||
}
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
events.Update(diff);
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_WAR_STOMP, 17s, 20s);
|
||||
resetTimer = 0;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SetData(DATA_SOLAKAR_FLAMEWREATH, DONE);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_WAR_STOMP:
|
||||
DoCastVictim(SPELL_WAR_STOMP);
|
||||
events.ScheduleEvent(SPELL_WAR_STOMP, 17s, 20s);
|
||||
break;
|
||||
case SPELL_HATCH_EGG:
|
||||
if (!targetEgg) // no target, try to find one
|
||||
{
|
||||
minDist = 50;
|
||||
tempDist = 50;
|
||||
me->GetGameObjectListWithEntryInGrid(nearbyEggs, GO_ROOKERY_EGG, 40);
|
||||
for (auto const& egg : nearbyEggs)
|
||||
{
|
||||
if (egg->isSpawned() && egg->getLootState() == GO_READY)
|
||||
{
|
||||
tempDist = me->GetDistance2d(egg);
|
||||
if (tempDist < minDist)
|
||||
{
|
||||
minDist = tempDist;
|
||||
targetEgg = egg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetEgg) //have a target, go to it and cast it
|
||||
me->GetMotionMaster()->MovePoint(0, targetEgg->GetPosition());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
// cast takes 1.5second, during which we don't have a target
|
||||
if (targetEgg && targetEgg->getLootState() == GO_READY && me->GetDistance2d(targetEgg) < RANGE_SPELL_HATCH_EGG)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
resetTimer -= diff;
|
||||
if (resetTimer < diff)
|
||||
{
|
||||
instance->SetData(DATA_SOLAKAR_FLAMEWREATH, FAIL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
resetTimer = 10000;
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
ExecuteEvent(eventId);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
me->StopMovingOnCurrentPos();
|
||||
me->SetFacingToObject(targetEgg);
|
||||
targetPosition = me->GetPosition();
|
||||
DoCast(SPELL_HATCH_EGG);
|
||||
targetEgg = nullptr;
|
||||
events.ScheduleEvent(SPELL_HATCH_EGG, 6s, 8s);
|
||||
}
|
||||
};
|
||||
else if (!me->HasUnitState(UNIT_STATE_CASTING) && !targetEgg)
|
||||
{
|
||||
if (Unit* victim = me->GetVictim())
|
||||
AttackStart(victim);
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
if (me->GetDistance2d(me->GetVictim()) > me->GetMeleeReach())
|
||||
me->GetMotionMaster()->MovePoint(0, me->GetVictim()->GetPosition()); // a bit hacky, but needed to start moving once we've summoned an egg
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
struct boss_solakar_flamewreath : public BossAI
|
||||
{
|
||||
boss_solakar_flamewreath(Creature* creature) : BossAI(creature, DATA_SOLAKAR_FLAMEWREATH) {}
|
||||
|
||||
uint32 resetTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_solakar_flamewreathAI>(creature);
|
||||
_Reset();
|
||||
resetTimer = 10000;
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
Talk(SAY_SUMMON);
|
||||
DoZoneInCombat(nullptr, 100.0f);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_WAR_STOMP, 17s, 20s);
|
||||
resetTimer = 0;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SetData(DATA_SOLAKAR_FLAMEWREATH, DONE);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_WAR_STOMP:
|
||||
DoCastVictim(SPELL_WAR_STOMP);
|
||||
events.ScheduleEvent(SPELL_WAR_STOMP, 17s, 20s);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (resetTimer <= diff)
|
||||
{
|
||||
instance->SetData(DATA_SOLAKAR_FLAMEWREATH, FAIL);
|
||||
return;
|
||||
}
|
||||
resetTimer -= diff;
|
||||
return;
|
||||
}
|
||||
resetTimer = 10000;
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
ExecuteEvent(eventId);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_solakar_flamewreath()
|
||||
{
|
||||
new boss_solakar_flamewreath();
|
||||
new npc_rookery_hatcher();
|
||||
RegisterBlackrockSpireCreatureAI(boss_solakar_flamewreath);
|
||||
RegisterBlackrockSpireCreatureAI(npc_rookery_hatcher);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,185 +90,152 @@ private:
|
|||
// Used to make Hodir disengage whenever he leaves his room
|
||||
constexpr static float FirewalPositionY = -505.f;
|
||||
|
||||
class boss_the_beast : public CreatureScript
|
||||
struct boss_the_beast : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_the_beast() : CreatureScript("boss_the_beast") { }
|
||||
boss_the_beast(Creature* creature) : BossAI(creature, DATA_THE_BEAST), _beastReached(false), _orcYelled(false) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_thebeastAI>(creature);
|
||||
_Reset();
|
||||
|
||||
if (_beastReached)
|
||||
me->GetMotionMaster()->MoveWaypoint(BEAST_MOVEMENT_ID, true);
|
||||
}
|
||||
|
||||
struct boss_thebeastAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_thebeastAI(Creature* creature) : BossAI(creature, DATA_THE_BEAST), _beastReached(false), _orcYelled(false) {}
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, 12s);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 3s);
|
||||
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 23s);
|
||||
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, 2s);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 8s, 21s);
|
||||
events.ScheduleEvent(EVENT_FIREBLAST, 5s, 8s);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void SetData(uint32 type, uint32 /*data*/) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
_Reset();
|
||||
|
||||
if (_beastReached)
|
||||
case DATA_BEAST_ROOM:
|
||||
{
|
||||
me->GetMotionMaster()->MoveWaypoint(BEAST_MOVEMENT_ID, true);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, 12s);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 3s);
|
||||
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 23s);
|
||||
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, 2s);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 8s, 21s);
|
||||
events.ScheduleEvent(EVENT_FIREBLAST, 5s, 8s);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 /*data*/) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_BEAST_ROOM:
|
||||
if (!_orcYelled)
|
||||
{
|
||||
if (!_orcYelled)
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
FindNearbyOrcs();
|
||||
|
||||
//! vector still empty, creatures are missing
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
return;
|
||||
|
||||
_orcYelled = true;
|
||||
|
||||
bool yelled = false;
|
||||
for (ObjectGuid guid : _nearbyOrcsGUIDs)
|
||||
{
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
if (Creature* orc = ObjectAccessor::GetCreature(*me, guid))
|
||||
{
|
||||
FindNearbyOrcs();
|
||||
}
|
||||
|
||||
//! vector still empty, creatures are missing
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_orcYelled = true;
|
||||
|
||||
bool yelled = false;
|
||||
for (ObjectGuid guid : _nearbyOrcsGUIDs)
|
||||
{
|
||||
if (Creature* orc = ObjectAccessor::GetCreature(*me, guid))
|
||||
if (!yelled)
|
||||
{
|
||||
if (!yelled)
|
||||
{
|
||||
yelled = true;
|
||||
orc->AI()->Talk(SAY_BLACKHAND_DOOMED);
|
||||
}
|
||||
|
||||
orc->m_Events.AddEventAtOffset(new OrcMoveEvent(orc), 3s);
|
||||
orc->m_Events.AddEventAtOffset(new OrcDeathEvent(orc), 9s);
|
||||
yelled = true;
|
||||
orc->AI()->Talk(SAY_BLACKHAND_DOOMED);
|
||||
}
|
||||
|
||||
orc->m_Events.AddEventAtOffset(new OrcMoveEvent(orc), 3s);
|
||||
orc->m_Events.AddEventAtOffset(new OrcDeathEvent(orc), 9s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_BEAST_REACHED:
|
||||
break;
|
||||
}
|
||||
case DATA_BEAST_REACHED:
|
||||
{
|
||||
if (!_beastReached)
|
||||
{
|
||||
if (!_beastReached)
|
||||
{
|
||||
_beastReached = true;
|
||||
me->GetMotionMaster()->MoveWaypoint(BEAST_MOVEMENT_ID, true);
|
||||
_beastReached = true;
|
||||
me->GetMotionMaster()->MoveWaypoint(BEAST_MOVEMENT_ID, true);
|
||||
|
||||
// There is a chance player logged in between areatriggers (realm crash or restart)
|
||||
// executing part of script which happens when player enters boss room
|
||||
// otherwise we will see weird behaviour when someone steps on the previous areatrigger (dead mob yelling/moving)
|
||||
SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
||||
}
|
||||
break;
|
||||
// There is a chance player logged in between areatriggers (realm crash or restart)
|
||||
// executing part of script which happens when player enters boss room
|
||||
// otherwise we will see weird behaviour when someone steps on the previous areatrigger (dead mob yelling/moving)
|
||||
SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->GetPositionY() > FirewalPositionY)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->GetPositionY() > FirewalPositionY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FLAME_BREAK:
|
||||
DoCastVictim(SPELL_FLAMEBREAK);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, 10s);
|
||||
break;
|
||||
case EVENT_IMMOLATE:
|
||||
DoCastRandomTarget(SPELL_IMMOLATE, 0, 100.0f);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 8s);
|
||||
break;
|
||||
case EVENT_TERRIFYING_ROAR:
|
||||
DoCastVictim(SPELL_TERRIFYINGROAR);
|
||||
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 20s);
|
||||
break;
|
||||
case EVENT_BERSERKER_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 38.f, true))
|
||||
DoCast(target, SPELL_BERSERKER_CHARGE);
|
||||
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, 15s, 23s);
|
||||
break;
|
||||
case EVENT_FIREBALL:
|
||||
DoCastVictim(SPELL_FIREBALL);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 8s, 21s);
|
||||
if (events.GetTimeUntilEvent(EVENT_FIREBLAST) < 3s)
|
||||
events.RescheduleEvent(EVENT_FIREBLAST, 3s);
|
||||
break;
|
||||
case EVENT_FIREBLAST:
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
events.ScheduleEvent(EVENT_FIREBLAST, 5s, 8s);
|
||||
if (events.GetTimeUntilEvent(EVENT_FIREBALL) < 3s)
|
||||
events.RescheduleEvent(EVENT_FIREBALL, 3s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FLAME_BREAK:
|
||||
DoCastVictim(SPELL_FLAMEBREAK);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, 10s);
|
||||
break;
|
||||
case EVENT_IMMOLATE:
|
||||
DoCastRandomTarget(SPELL_IMMOLATE, 0, 100.0f);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 8s);
|
||||
break;
|
||||
case EVENT_TERRIFYING_ROAR:
|
||||
DoCastVictim(SPELL_TERRIFYINGROAR);
|
||||
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 20s);
|
||||
break;
|
||||
case EVENT_BERSERKER_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 38.f, true))
|
||||
{
|
||||
DoCast(target, SPELL_BERSERKER_CHARGE);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, 15s, 23s);
|
||||
break;
|
||||
case EVENT_FIREBALL:
|
||||
DoCastVictim(SPELL_FIREBALL);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 8s, 21s);
|
||||
if (events.GetTimeUntilEvent(EVENT_FIREBLAST) < 3s)
|
||||
{
|
||||
events.RescheduleEvent(EVENT_FIREBLAST, 3s);
|
||||
}
|
||||
break;
|
||||
case EVENT_FIREBLAST:
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
events.ScheduleEvent(EVENT_FIREBLAST, 5s, 8s);
|
||||
if (events.GetTimeUntilEvent(EVENT_FIREBALL) < 3s)
|
||||
{
|
||||
events.RescheduleEvent(EVENT_FIREBALL, 3s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void FindNearbyOrcs()
|
||||
{
|
||||
std::list<Creature*> temp;
|
||||
me->GetCreatureListWithEntryInGrid(temp, NPC_BLACKHAND_ELITE, 50.0f);
|
||||
for (Creature* creature : temp)
|
||||
{
|
||||
if (creature->IsAlive())
|
||||
{
|
||||
_nearbyOrcsGUIDs.push_back(creature->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _beastReached;
|
||||
bool _orcYelled;
|
||||
GuidVector _nearbyOrcsGUIDs;
|
||||
};
|
||||
void FindNearbyOrcs()
|
||||
{
|
||||
std::list<Creature*> temp;
|
||||
me->GetCreatureListWithEntryInGrid(temp, NPC_BLACKHAND_ELITE, 50.0f);
|
||||
for (Creature* creature : temp)
|
||||
if (creature->IsAlive())
|
||||
_nearbyOrcsGUIDs.push_back(creature->GetGUID());
|
||||
}
|
||||
|
||||
private:
|
||||
bool _beastReached;
|
||||
bool _orcYelled;
|
||||
GuidVector _nearbyOrcsGUIDs;
|
||||
};
|
||||
|
||||
//! The beast room areatrigger, this one triggers boss pathing. (AT Id 2066)
|
||||
|
|
@ -280,16 +247,12 @@ public:
|
|||
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
||||
{
|
||||
if (player->IsGameMaster())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (InstanceScript* instance = player->GetInstanceScript())
|
||||
{
|
||||
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
|
||||
{
|
||||
beast->AI()->SetData(DATA_BEAST_REACHED, DATA_BEAST_REACHED);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -306,16 +269,12 @@ public:
|
|||
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
||||
{
|
||||
if (player->IsGameMaster())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (InstanceScript* instance = player->GetInstanceScript())
|
||||
{
|
||||
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
|
||||
{
|
||||
beast->AI()->SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -326,7 +285,7 @@ public:
|
|||
|
||||
void AddSC_boss_thebeast()
|
||||
{
|
||||
new boss_the_beast();
|
||||
RegisterBlackrockSpireCreatureAI(boss_the_beast);
|
||||
new at_trigger_the_beast_movement();
|
||||
new at_the_beast_room();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,82 +40,67 @@ enum Events
|
|||
EVENT_INTIMIDATING_ROAR = 3
|
||||
};
|
||||
|
||||
class boss_urok_doomhowl : public CreatureScript
|
||||
struct boss_urok_doomhowl : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_urok_doomhowl() : CreatureScript("boss_urok_doomhowl") { }
|
||||
boss_urok_doomhowl(Creature* creature) : BossAI(creature, DATA_UROK_DOOMHOWL) {}
|
||||
|
||||
struct boss_urok_doomhowlAI : public BossAI
|
||||
void InitializeAI() override
|
||||
{
|
||||
boss_urok_doomhowlAI(Creature* creature) : BossAI(creature, DATA_UROK_DOOMHOWL) {}
|
||||
me->CastSpell(me, SPELL_UROK_SPAWN, true);
|
||||
BossAI::InitializeAI();
|
||||
Talk(SAY_SUMMON);
|
||||
DoZoneInCombat(nullptr, 100.0f);
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
me->CastSpell(me, SPELL_UROK_SPAWN, true);
|
||||
BossAI::InitializeAI();
|
||||
Talk(SAY_SUMMON);
|
||||
DoZoneInCombat(nullptr, 100.0f);
|
||||
if (GameObject* challenge = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_CHALLENGE)))
|
||||
challenge->Delete();
|
||||
|
||||
if (GameObject* challenge = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_CHALLENGE)))
|
||||
{
|
||||
challenge->Delete();
|
||||
}
|
||||
if (GameObject* pile = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_PILE)))
|
||||
pile->DespawnOrUnsummon(0ms, Seconds(MONTH));
|
||||
}
|
||||
|
||||
if (GameObject* pile = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_PILE)))
|
||||
{
|
||||
pile->DespawnOrUnsummon(0ms, Seconds(MONTH));
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_REND, 17s, 20s);
|
||||
events.ScheduleEvent(SPELL_STRIKE, 10s, 12s);
|
||||
events.ScheduleEvent(SPELL_INTIMIDATING_ROAR, 25s, 30s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_REND:
|
||||
DoCastVictim(SPELL_REND);
|
||||
events.ScheduleEvent(SPELL_REND, 8s, 10s);
|
||||
break;
|
||||
case SPELL_STRIKE:
|
||||
DoCastVictim(SPELL_STRIKE);
|
||||
events.ScheduleEvent(SPELL_STRIKE, 8s, 10s);
|
||||
break;
|
||||
case SPELL_INTIMIDATING_ROAR:
|
||||
DoCastVictim(SPELL_INTIMIDATING_ROAR);
|
||||
events.ScheduleEvent(SPELL_INTIMIDATING_ROAR, 40s, 45s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_urok_doomhowlAI>(creature);
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(SPELL_REND, 17s, 20s);
|
||||
events.ScheduleEvent(SPELL_STRIKE, 10s, 12s);
|
||||
events.ScheduleEvent(SPELL_INTIMIDATING_ROAR, 25s, 30s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case SPELL_REND:
|
||||
DoCastVictim(SPELL_REND);
|
||||
events.ScheduleEvent(SPELL_REND, 8s, 10s);
|
||||
break;
|
||||
case SPELL_STRIKE:
|
||||
DoCastVictim(SPELL_STRIKE);
|
||||
events.ScheduleEvent(SPELL_STRIKE, 8s, 10s);
|
||||
break;
|
||||
case SPELL_INTIMIDATING_ROAR:
|
||||
DoCastVictim(SPELL_INTIMIDATING_ROAR);
|
||||
events.ScheduleEvent(SPELL_INTIMIDATING_ROAR, 40s, 45s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_urok_doomhowl()
|
||||
{
|
||||
new boss_urok_doomhowl();
|
||||
RegisterBlackrockSpireCreatureAI(boss_urok_doomhowl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,86 +55,75 @@ enum EventGroups
|
|||
GROUP_WARMASTER
|
||||
};
|
||||
|
||||
class boss_warmaster_voone : public CreatureScript
|
||||
struct boss_warmaster_voone : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_warmaster_voone() : CreatureScript("boss_warmaster_voone") { }
|
||||
boss_warmaster_voone(Creature* creature) : BossAI(creature, DATA_WARMASTER_VOONE) { }
|
||||
|
||||
struct boss_warmastervooneAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_warmastervooneAI(Creature* creature) : BossAI(creature, DATA_WARMASTER_VOONE) { }
|
||||
_JustEngagedWith();
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.SetPhase(PHASE_BRAWLER);
|
||||
events.ScheduleEvent(EVENT_THRASH, 3s, GROUP_BRAWLER, PHASE_BRAWLER);
|
||||
events.ScheduleEvent(EVENT_THROW_AXE, 1s, GROUP_BRAWLER, PHASE_BRAWLER);
|
||||
}
|
||||
|
||||
events.SetPhase(PHASE_BRAWLER);
|
||||
events.ScheduleEvent(EVENT_THRASH, 3s, GROUP_BRAWLER, PHASE_BRAWLER);
|
||||
events.ScheduleEvent(EVENT_THROW_AXE, 1s, GROUP_BRAWLER, PHASE_BRAWLER);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(65, damage) && events.IsInPhase(PHASE_BRAWLER))
|
||||
{
|
||||
events.SetPhase(PHASE_THRASHER);
|
||||
events.CancelEventGroup(GROUP_BRAWLER);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 14s, GROUP_THRASHER, PHASE_THRASHER);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 12s, GROUP_THRASHER, PHASE_THRASHER);
|
||||
}
|
||||
else if (me->HealthBelowPctDamaged(40, damage) && events.IsInPhase(PHASE_THRASHER))
|
||||
{
|
||||
events.SetPhase(PHASE_WARMASTER);
|
||||
events.CancelEventGroup(GROUP_THRASHER);
|
||||
events.ScheduleEvent(EVENT_SNAP_KICK, 8s, GROUP_WARMASTER, PHASE_WARMASTER);
|
||||
events.ScheduleEvent(EVENT_UPPERCUT, 20s, GROUP_WARMASTER, PHASE_WARMASTER);
|
||||
events.ScheduleEvent(EVENT_PUMMEL, 32s, GROUP_WARMASTER, PHASE_WARMASTER);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SNAP_KICK:
|
||||
DoCastVictim(SPELL_SNAPKICK);
|
||||
events.Repeat(6s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.Repeat(12s);
|
||||
break;
|
||||
case EVENT_UPPERCUT:
|
||||
DoCastVictim(SPELL_UPPERCUT);
|
||||
events.Repeat(14s);
|
||||
break;
|
||||
case EVENT_MORTAL_STRIKE:
|
||||
DoCastVictim(SPELL_MORTALSTRIKE);
|
||||
events.Repeat(10s);
|
||||
break;
|
||||
case EVENT_PUMMEL:
|
||||
DoCastVictim(SPELL_PUMMEL);
|
||||
events.Repeat(16s);
|
||||
break;
|
||||
case EVENT_THROW_AXE:
|
||||
DoCastRandomTarget(SPELL_THROWAXE);
|
||||
events.Repeat(8s);
|
||||
break;
|
||||
case EVENT_THRASH:
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
events.Repeat(10s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_warmastervooneAI>(creature);
|
||||
if (me->HealthBelowPctDamaged(65, damage) && events.IsInPhase(PHASE_BRAWLER))
|
||||
{
|
||||
events.SetPhase(PHASE_THRASHER);
|
||||
events.CancelEventGroup(GROUP_BRAWLER);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 14s, GROUP_THRASHER, PHASE_THRASHER);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 12s, GROUP_THRASHER, PHASE_THRASHER);
|
||||
}
|
||||
else if (me->HealthBelowPctDamaged(40, damage) && events.IsInPhase(PHASE_THRASHER))
|
||||
{
|
||||
events.SetPhase(PHASE_WARMASTER);
|
||||
events.CancelEventGroup(GROUP_THRASHER);
|
||||
events.ScheduleEvent(EVENT_SNAP_KICK, 8s, GROUP_WARMASTER, PHASE_WARMASTER);
|
||||
events.ScheduleEvent(EVENT_UPPERCUT, 20s, GROUP_WARMASTER, PHASE_WARMASTER);
|
||||
events.ScheduleEvent(EVENT_PUMMEL, 32s, GROUP_WARMASTER, PHASE_WARMASTER);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SNAP_KICK:
|
||||
DoCastVictim(SPELL_SNAPKICK);
|
||||
events.Repeat(6s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.Repeat(12s);
|
||||
break;
|
||||
case EVENT_UPPERCUT:
|
||||
DoCastVictim(SPELL_UPPERCUT);
|
||||
events.Repeat(14s);
|
||||
break;
|
||||
case EVENT_MORTAL_STRIKE:
|
||||
DoCastVictim(SPELL_MORTALSTRIKE);
|
||||
events.Repeat(10s);
|
||||
break;
|
||||
case EVENT_PUMMEL:
|
||||
DoCastVictim(SPELL_PUMMEL);
|
||||
events.Repeat(16s);
|
||||
break;
|
||||
case EVENT_THROW_AXE:
|
||||
DoCastRandomTarget(SPELL_THROWAXE);
|
||||
events.Repeat(8s);
|
||||
break;
|
||||
case EVENT_THRASH:
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
events.Repeat(10s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_warmastervoone()
|
||||
{
|
||||
new boss_warmaster_voone();
|
||||
RegisterBlackrockSpireCreatureAI(boss_warmaster_voone);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -127,5 +127,6 @@ inline AI* GetBlackwingLairAI(T* obj)
|
|||
}
|
||||
|
||||
#define RegisterBlackwingLairCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackwingLairAI)
|
||||
#define RegisterBlackwingLairGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetBlackwingLairAI)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -58,196 +58,157 @@ enum Actions
|
|||
ACTION_DISARMED = 1
|
||||
};
|
||||
|
||||
class boss_broodlord : public CreatureScript
|
||||
struct boss_broodlord : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_broodlord() : CreatureScript("boss_broodlord") { }
|
||||
boss_broodlord(Creature* creature) : BossAI(creature, DATA_BROODLORD_LASHLAYER) { }
|
||||
|
||||
struct boss_broodlordAI : public BossAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_broodlordAI(Creature* creature) : BossAI(creature, DATA_BROODLORD_LASHLAYER) { }
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||
events.ScheduleEvent(EVENT_BLASTWAVE, 12s);
|
||||
events.ScheduleEvent(EVENT_MORTALSTRIKE, 20s);
|
||||
events.ScheduleEvent(EVENT_KNOCKBACK, 30s);
|
||||
events.ScheduleEvent(EVENT_CHECK, 1s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
|
||||
std::list<GameObject*> _goList;
|
||||
GetGameObjectListWithEntryInGrid(_goList, me, GO_SUPPRESSION_DEVICE, 200.0f);
|
||||
for (std::list<GameObject*>::const_iterator itr = _goList.begin(); itr != _goList.end(); itr++)
|
||||
{
|
||||
((*itr)->AI()->DoAction(ACTION_DEACTIVATE));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 7s);
|
||||
break;
|
||||
case EVENT_BLASTWAVE:
|
||||
DoCastVictim(SPELL_BLASTWAVE);
|
||||
events.ScheduleEvent(EVENT_BLASTWAVE, 20s, 35s);
|
||||
break;
|
||||
case EVENT_MORTALSTRIKE:
|
||||
DoCastVictim(SPELL_MORTALSTRIKE);
|
||||
events.ScheduleEvent(EVENT_MORTALSTRIKE, 25s, 35s);
|
||||
break;
|
||||
case EVENT_KNOCKBACK:
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatByPercent(me->GetVictim(), -50);
|
||||
events.ScheduleEvent(EVENT_KNOCKBACK, 15s, 30s);
|
||||
break;
|
||||
case EVENT_CHECK:
|
||||
if (me->GetDistance(me->GetHomePosition()) > 150.0f)
|
||||
{
|
||||
Talk(SAY_LEASH);
|
||||
EnterEvadeMode();
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK, 1s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_broodlordAI>(creature);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||
events.ScheduleEvent(EVENT_BLASTWAVE, 12s);
|
||||
events.ScheduleEvent(EVENT_MORTALSTRIKE, 20s);
|
||||
events.ScheduleEvent(EVENT_KNOCKBACK, 30s);
|
||||
events.ScheduleEvent(EVENT_CHECK, 1s);
|
||||
}
|
||||
};
|
||||
|
||||
class go_suppression_device : public GameObjectScript
|
||||
{
|
||||
public:
|
||||
go_suppression_device() : GameObjectScript("go_suppression_device") { }
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
|
||||
void OnLootStateChanged(GameObject* go, uint32 state, Unit* /*unit*/) override
|
||||
std::list<GameObject*> _goList;
|
||||
GetGameObjectListWithEntryInGrid(_goList, me, GO_SUPPRESSION_DEVICE, 200.0f);
|
||||
for (std::list<GameObject*>::const_iterator itr = _goList.begin(); itr != _goList.end(); itr++)
|
||||
((*itr)->AI()->DoAction(ACTION_DEACTIVATE));
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (state)
|
||||
switch (eventId)
|
||||
{
|
||||
case GO_JUST_DEACTIVATED: // This case prevents the Gameobject despawn by Disarm Trap
|
||||
go->SetLootState(GO_READY);
|
||||
[[fallthrough]];
|
||||
case GO_ACTIVATED:
|
||||
go->AI()->DoAction(ACTION_DISARMED);
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 7s);
|
||||
break;
|
||||
case EVENT_BLASTWAVE:
|
||||
DoCastVictim(SPELL_BLASTWAVE);
|
||||
events.ScheduleEvent(EVENT_BLASTWAVE, 20s, 35s);
|
||||
break;
|
||||
case EVENT_MORTALSTRIKE:
|
||||
DoCastVictim(SPELL_MORTALSTRIKE);
|
||||
events.ScheduleEvent(EVENT_MORTALSTRIKE, 25s, 35s);
|
||||
break;
|
||||
case EVENT_KNOCKBACK:
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatByPercent(me->GetVictim(), -50);
|
||||
events.ScheduleEvent(EVENT_KNOCKBACK, 15s, 30s);
|
||||
break;
|
||||
case EVENT_CHECK:
|
||||
if (me->GetDistance(me->GetHomePosition()) > 150.0f)
|
||||
{
|
||||
Talk(SAY_LEASH);
|
||||
EnterEvadeMode();
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK, 1s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct go_suppression_deviceAI : public GameObjectAI
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
struct go_suppression_device : public GameObjectAI
|
||||
{
|
||||
go_suppression_device(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()), _active(true) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
if (_instance->GetBossState(DATA_BROODLORD_LASHLAYER) == DONE)
|
||||
{
|
||||
go_suppression_deviceAI(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()), _active(true) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
if (_instance->GetBossState(DATA_BROODLORD_LASHLAYER) == DONE)
|
||||
{
|
||||
Deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SUPPRESSION_CAST:
|
||||
if (me->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
me->CastSpell(nullptr, SPELL_SUPPRESSION_AURA);
|
||||
me->SendCustomAnim(0);
|
||||
}
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5s);
|
||||
break;
|
||||
case EVENT_SUPPRESSION_RESET:
|
||||
Activate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_DEACTIVATE)
|
||||
{
|
||||
_events.CancelEvent(EVENT_SUPPRESSION_RESET);
|
||||
}
|
||||
else if (action == ACTION_DISARMED)
|
||||
{
|
||||
Deactivate();
|
||||
_events.CancelEvent(EVENT_SUPPRESSION_CAST);
|
||||
|
||||
if (_instance->GetBossState(DATA_BROODLORD_LASHLAYER) != DONE)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_RESET, 30s, 120s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Activate()
|
||||
{
|
||||
if (_active)
|
||||
return;
|
||||
_active = true;
|
||||
if (me->GetGoState() == GO_STATE_ACTIVE)
|
||||
me->SetGoState(GO_STATE_READY);
|
||||
me->SetLootState(GO_READY);
|
||||
me->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5s);
|
||||
me->Respawn();
|
||||
}
|
||||
|
||||
void Deactivate()
|
||||
{
|
||||
if (!_active)
|
||||
return;
|
||||
_active = false;
|
||||
me->SetGoState(GO_STATE_ACTIVE);
|
||||
me->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
_events.CancelEvent(EVENT_SUPPRESSION_CAST);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
EventMap _events;
|
||||
bool _active;
|
||||
};
|
||||
|
||||
GameObjectAI* GetAI(GameObject* go) const override
|
||||
{
|
||||
return new go_suppression_deviceAI(go);
|
||||
Deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SUPPRESSION_CAST:
|
||||
if (me->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
me->CastSpell(nullptr, SPELL_SUPPRESSION_AURA);
|
||||
me->SendCustomAnim(0);
|
||||
}
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5s);
|
||||
break;
|
||||
case EVENT_SUPPRESSION_RESET:
|
||||
Activate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_DEACTIVATE)
|
||||
{
|
||||
_events.CancelEvent(EVENT_SUPPRESSION_RESET);
|
||||
}
|
||||
else if (action == ACTION_DISARMED)
|
||||
{
|
||||
Deactivate();
|
||||
_events.CancelEvent(EVENT_SUPPRESSION_CAST);
|
||||
|
||||
if (_instance->GetBossState(DATA_BROODLORD_LASHLAYER) != DONE)
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_RESET, 30s, 120s);
|
||||
}
|
||||
}
|
||||
|
||||
void Activate()
|
||||
{
|
||||
if (_active)
|
||||
return;
|
||||
_active = true;
|
||||
if (me->GetGoState() == GO_STATE_ACTIVE)
|
||||
me->SetGoState(GO_STATE_READY);
|
||||
me->SetLootState(GO_READY);
|
||||
me->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
_events.ScheduleEvent(EVENT_SUPPRESSION_CAST, 5s);
|
||||
me->Respawn();
|
||||
}
|
||||
|
||||
void Deactivate()
|
||||
{
|
||||
if (!_active)
|
||||
return;
|
||||
_active = false;
|
||||
me->SetGoState(GO_STATE_ACTIVE);
|
||||
me->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
_events.CancelEvent(EVENT_SUPPRESSION_CAST);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
EventMap _events;
|
||||
bool _active;
|
||||
};
|
||||
|
||||
class spell_suppression_aura : public SpellScript
|
||||
|
|
@ -271,7 +232,7 @@ class spell_suppression_aura : public SpellScript
|
|||
|
||||
void AddSC_boss_broodlord()
|
||||
{
|
||||
new boss_broodlord();
|
||||
new go_suppression_device();
|
||||
RegisterBlackwingLairCreatureAI(boss_broodlord);
|
||||
RegisterBlackwingLairGameObjectAI(go_suppression_device);
|
||||
RegisterSpellScript(spell_suppression_aura);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,203 +70,171 @@ enum Misc
|
|||
|
||||
Position const homePos = { -7491.1587f, -1069.718f, 476.59094, 476.59094f };
|
||||
|
||||
class boss_chromaggus : public CreatureScript
|
||||
struct boss_chromaggus : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_chromaggus() : CreatureScript("boss_chromaggus") { }
|
||||
|
||||
struct boss_chromaggusAI : public BossAI
|
||||
boss_chromaggus(Creature* creature) : BossAI(creature, DATA_CHROMAGGUS)
|
||||
{
|
||||
boss_chromaggusAI(Creature* creature) : BossAI(creature, DATA_CHROMAGGUS)
|
||||
Initialize();
|
||||
|
||||
// Select the 2 breaths that we are going to use until despawned so we don't end up casting 2 of the same breath.
|
||||
_breathSpells = { SPELL_INCINERATE, SPELL_TIMELAPSE, SPELL_CORROSIVEACID, SPELL_IGNITEFLESH, SPELL_FROSTBURN };
|
||||
|
||||
Acore::Containers::RandomResize(_breathSpells, 2);
|
||||
|
||||
// Hack fix: This is here to prevent him from being pulled from the floor underneath, remove it once maps are fixed.
|
||||
creature->SetImmuneToAll(true);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Enraged = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHIMMER, 1s);
|
||||
events.ScheduleEvent(EVENT_BREATH, 30s);
|
||||
events.ScheduleEvent(EVENT_BREATH, 60s);
|
||||
events.ScheduleEvent(EVENT_AFFLICTION, 10s);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 15s);
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
return !victim->HasAura(SPELL_TIMELAPSE);
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 id) override
|
||||
{
|
||||
if (id == GUID_LEVER_USER)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
// Select the 2 breaths that we are going to use until despawned so we don't end up casting 2 of the same breath.
|
||||
_breathSpells = { SPELL_INCINERATE, SPELL_TIMELAPSE, SPELL_CORROSIVEACID, SPELL_IGNITEFLESH, SPELL_FROSTBURN };
|
||||
|
||||
Acore::Containers::RandomResize(_breathSpells, 2);
|
||||
|
||||
_playerGUID = guid;
|
||||
// Hack fix: This is here to prevent him from being pulled from the floor underneath, remove it once maps are fixed.
|
||||
creature->SetImmuneToAll(true);
|
||||
me->SetImmuneToAll(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
void PathEndReached(uint32 /*pathId*/) override
|
||||
{
|
||||
if (Unit* player = ObjectAccessor::GetUnit(*me, _playerGUID))
|
||||
me->SetInCombatWith(player);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
Enraged = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHIMMER, 1s);
|
||||
events.ScheduleEvent(EVENT_BREATH, 30s);
|
||||
events.ScheduleEvent(EVENT_BREATH, 60s);
|
||||
events.ScheduleEvent(EVENT_AFFLICTION, 10s);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 15s);
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
return !victim->HasAura(SPELL_TIMELAPSE);
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 id) override
|
||||
{
|
||||
if (id == GUID_LEVER_USER)
|
||||
switch (eventId)
|
||||
{
|
||||
_playerGUID = guid;
|
||||
// Hack fix: This is here to prevent him from being pulled from the floor underneath, remove it once maps are fixed.
|
||||
me->SetImmuneToAll(false);
|
||||
case EVENT_SHIMMER:
|
||||
{
|
||||
// Cast new random vulnerabilty on self
|
||||
DoCast(me, SPELL_ELEMENTAL_SHIELD);
|
||||
Talk(EMOTE_SHIMMER);
|
||||
events.ScheduleEvent(EVENT_SHIMMER, 17s, 25s);
|
||||
break;
|
||||
}
|
||||
case EVENT_BREATH:
|
||||
DoCastVictim(_breathSpells.front());
|
||||
_breathSpells.reverse();
|
||||
events.ScheduleEvent(EVENT_BREATH, 60s);
|
||||
break;
|
||||
case EVENT_AFFLICTION:
|
||||
{
|
||||
uint32 afflictionSpellID = RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN);
|
||||
std::vector<Player*> playerTargets;
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
if (Player* player = itr->GetSource()->ToPlayer())
|
||||
if (!player->IsGameMaster() && !player->IsSpectator() && player->IsAlive())
|
||||
playerTargets.push_back(player);
|
||||
|
||||
if (playerTargets.size() > 12)
|
||||
Acore::Containers::RandomResize(playerTargets, 12);
|
||||
|
||||
for (Player* player : playerTargets)
|
||||
{
|
||||
DoCast(player, afflictionSpellID, true);
|
||||
|
||||
if (player->HasAllAuras(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN))
|
||||
DoCast(player, SPELL_CHROMATIC_MUT_1);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_AFFLICTION, 10s);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 10s, 15s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PathEndReached(uint32 /*pathId*/) override
|
||||
{
|
||||
if (Unit* player = ObjectAccessor::GetUnit(*me, _playerGUID))
|
||||
{
|
||||
me->SetInCombatWith(player);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHIMMER:
|
||||
{
|
||||
// Cast new random vulnerabilty on self
|
||||
DoCast(me, SPELL_ELEMENTAL_SHIELD);
|
||||
Talk(EMOTE_SHIMMER);
|
||||
events.ScheduleEvent(EVENT_SHIMMER, 17s, 25s);
|
||||
break;
|
||||
}
|
||||
case EVENT_BREATH:
|
||||
DoCastVictim(_breathSpells.front());
|
||||
_breathSpells.reverse();
|
||||
events.ScheduleEvent(EVENT_BREATH, 60s);
|
||||
break;
|
||||
case EVENT_AFFLICTION:
|
||||
{
|
||||
uint32 afflictionSpellID = RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN);
|
||||
std::vector<Player*> playerTargets;
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
{
|
||||
if (Player* player = itr->GetSource()->ToPlayer())
|
||||
{
|
||||
if (!player->IsGameMaster() && !player->IsSpectator() && player->IsAlive())
|
||||
{
|
||||
playerTargets.push_back(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerTargets.size() > 12)
|
||||
{
|
||||
Acore::Containers::RandomResize(playerTargets, 12);
|
||||
}
|
||||
|
||||
for (Player* player : playerTargets)
|
||||
{
|
||||
DoCast(player, afflictionSpellID, true);
|
||||
|
||||
if (player->HasAllAuras(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN))
|
||||
DoCast(player, SPELL_CHROMATIC_MUT_1);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_AFFLICTION, 10s);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 10s, 15s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
// Enrage if not already enraged and below 20%
|
||||
if (!Enraged && HealthBelowPct(20))
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
Enraged = true;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<uint32> _breathSpells;
|
||||
bool Enraged;
|
||||
ObjectGuid _playerGUID;
|
||||
};
|
||||
// Enrage if not already enraged and below 20%
|
||||
if (!Enraged && HealthBelowPct(20))
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
Enraged = true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_chromaggusAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<uint32> _breathSpells;
|
||||
bool Enraged;
|
||||
ObjectGuid _playerGUID;
|
||||
};
|
||||
|
||||
class go_chromaggus_lever : public GameObjectScript
|
||||
struct go_chromaggus_lever : public GameObjectAI
|
||||
{
|
||||
public:
|
||||
go_chromaggus_lever() : GameObjectScript("go_chromaggus_lever") { }
|
||||
go_chromaggus_lever(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
|
||||
|
||||
struct go_chromaggus_leverAI : public GameObjectAI
|
||||
bool GossipHello(Player* player, bool reportUse) override
|
||||
{
|
||||
if (reportUse)
|
||||
{
|
||||
go_chromaggus_leverAI(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
|
||||
|
||||
bool GossipHello(Player* player, bool reportUse) override
|
||||
if (_instance->GetBossState(DATA_CHROMAGGUS) != DONE && _instance->GetBossState(DATA_CHROMAGGUS) != IN_PROGRESS)
|
||||
{
|
||||
if (reportUse)
|
||||
if (Creature* creature = _instance->GetCreature(DATA_CHROMAGGUS))
|
||||
{
|
||||
if (_instance->GetBossState(DATA_CHROMAGGUS) != DONE && _instance->GetBossState(DATA_CHROMAGGUS) != IN_PROGRESS)
|
||||
{
|
||||
if (Creature* creature = _instance->GetCreature(DATA_CHROMAGGUS))
|
||||
{
|
||||
creature->SetHomePosition(homePos);
|
||||
creature->GetMotionMaster()->MoveWaypoint(creature->GetEntry() * 10, false);
|
||||
creature->AI()->SetGUID(player->GetGUID(), GUID_LEVER_USER);
|
||||
}
|
||||
|
||||
if (GameObject* go = _instance->GetGameObject(DATA_GO_CHROMAGGUS_DOOR))
|
||||
_instance->HandleGameObject(ObjectGuid::Empty, true, go);
|
||||
}
|
||||
|
||||
me->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE | GO_FLAG_IN_USE);
|
||||
me->SetGoState(GO_STATE_ACTIVE);
|
||||
creature->SetHomePosition(homePos);
|
||||
creature->GetMotionMaster()->MoveWaypoint(creature->GetEntry() * 10, false);
|
||||
creature->AI()->SetGUID(player->GetGUID(), GUID_LEVER_USER);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (GameObject* go = _instance->GetGameObject(DATA_GO_CHROMAGGUS_DOOR))
|
||||
_instance->HandleGameObject(ObjectGuid::Empty, true, go);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
GameObjectAI* GetAI(GameObject* go) const override
|
||||
{
|
||||
return GetBlackwingLairAI<go_chromaggus_leverAI>(go);
|
||||
me->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE | GO_FLAG_IN_USE);
|
||||
me->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
enum ElementalShieldSpells
|
||||
|
|
@ -306,9 +274,7 @@ class spell_gen_elemental_shield : public SpellScript
|
|||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
for (uint32 spell = SPELL_FIRE_ELEMENTAL_SHIELD; spell <= SPELL_ARCANE_ELEMENTAL_SHIELD; ++spell)
|
||||
{
|
||||
caster->RemoveAurasDueToSpell(spell);
|
||||
}
|
||||
|
||||
caster->CastSpell(caster, SPELL_FIRE_ELEMENTAL_SHIELD + urand(0, 4), true);
|
||||
}
|
||||
|
|
@ -341,9 +307,7 @@ class spell_gen_brood_power : public SpellScript
|
|||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
for (uint32 spell = SPELL_RED_BROOD_POWER; spell <= SPELL_GREEN_BROOD_POWER; ++spell)
|
||||
{
|
||||
caster->RemoveAurasDueToSpell(spell);
|
||||
}
|
||||
|
||||
caster->CastSpell(caster, RAND(SPELL_RED_BROOD_POWER, SPELL_BLUE_BROOD_POWER, SPELL_BRONZE_BROOD_POWER, SPELL_BLACK_BROOD_POWER, SPELL_GREEN_BROOD_POWER), true);
|
||||
}
|
||||
|
|
@ -357,8 +321,8 @@ class spell_gen_brood_power : public SpellScript
|
|||
|
||||
void AddSC_boss_chromaggus()
|
||||
{
|
||||
new boss_chromaggus();
|
||||
new go_chromaggus_lever();
|
||||
RegisterBlackwingLairCreatureAI(boss_chromaggus);
|
||||
RegisterBlackwingLairGameObjectAI(go_chromaggus_lever);
|
||||
RegisterSpellScript(spell_gen_elemental_shield);
|
||||
RegisterSpellScript(spell_gen_brood_power);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,82 +33,69 @@ enum Events
|
|||
EVENT_SHADOWOFEBONROC = 3
|
||||
};
|
||||
|
||||
class boss_ebonroc : public CreatureScript
|
||||
struct boss_ebonroc : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_ebonroc() : CreatureScript("boss_ebonroc") { }
|
||||
boss_ebonroc(Creature* creature) : BossAI(creature, DATA_EBONROC) { }
|
||||
|
||||
struct boss_ebonrocAI : public BossAI
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
boss_ebonrocAI(Creature* creature) : BossAI(creature, DATA_EBONROC) { }
|
||||
if (type != WAYPOINT_MOTION_TYPE || id != 13)
|
||||
return;
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
me->GetMotionMaster()->MoveRandom(10.f);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
if (type != WAYPOINT_MOTION_TYPE || id != 13)
|
||||
me->GetMotionMaster()->Initialize();
|
||||
}, 15s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, 8s, 10s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
case EVENT_SHADOWFLAME:
|
||||
DoCastVictim(SPELL_SHADOWFLAME);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
break;
|
||||
case EVENT_SHADOWOFEBONROC:
|
||||
DoCastVictim(SPELL_SHADOWOFEBONROC);
|
||||
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, 8s, 10s);
|
||||
break;
|
||||
}
|
||||
|
||||
me->GetMotionMaster()->MoveRandom(10.f);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
me->GetMotionMaster()->Initialize();
|
||||
}, 15s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, 8s, 10s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOWFLAME:
|
||||
DoCastVictim(SPELL_SHADOWFLAME);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
break;
|
||||
case EVENT_SHADOWOFEBONROC:
|
||||
DoCastVictim(SPELL_SHADOWOFEBONROC);
|
||||
events.ScheduleEvent(EVENT_SHADOWOFEBONROC, 8s, 10s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_ebonrocAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_ebonroc()
|
||||
{
|
||||
new boss_ebonroc();
|
||||
RegisterBlackwingLairCreatureAI(boss_ebonroc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,69 +33,58 @@ enum Events
|
|||
EVENT_FLAMEBUFFET = 3
|
||||
};
|
||||
|
||||
class boss_firemaw : public CreatureScript
|
||||
struct boss_firemaw : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_firemaw() : CreatureScript("boss_firemaw") { }
|
||||
boss_firemaw(Creature* creature) : BossAI(creature, DATA_FIREMAW) { }
|
||||
|
||||
struct boss_firemawAI : public BossAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_firemawAI(Creature* creature) : BossAI(creature, DATA_FIREMAW) { }
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOWFLAME:
|
||||
DoCastVictim(SPELL_SHADOWFLAME);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
break;
|
||||
case EVENT_FLAMEBUFFET:
|
||||
DoCastVictim(SPELL_FLAMEBUFFET);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOWFLAME:
|
||||
DoCastVictim(SPELL_SHADOWFLAME);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
break;
|
||||
case EVENT_FLAMEBUFFET:
|
||||
DoCastVictim(SPELL_FLAMEBUFFET);
|
||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_firemawAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_firemaw()
|
||||
{
|
||||
new boss_firemaw();
|
||||
RegisterBlackwingLairCreatureAI(boss_firemaw);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,70 +38,59 @@ enum Events
|
|||
EVENT_FRENZY = 3
|
||||
};
|
||||
|
||||
class boss_flamegor : public CreatureScript
|
||||
struct boss_flamegor : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_flamegor() : CreatureScript("boss_flamegor") { }
|
||||
boss_flamegor(Creature* creature) : BossAI(creature, DATA_FLAMEGOR) { }
|
||||
|
||||
struct boss_flamegorAI : public BossAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_flamegorAI(Creature* creature) : BossAI(creature, DATA_FLAMEGOR) { }
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 10s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 10s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOWFLAME:
|
||||
DoCastVictim(SPELL_SHADOWFLAME);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 8s, 10s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOWFLAME:
|
||||
DoCastVictim(SPELL_SHADOWFLAME);
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||
break;
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 8s, 10s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_flamegorAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_flamegor()
|
||||
{
|
||||
new boss_flamegor();
|
||||
RegisterBlackwingLairCreatureAI(boss_flamegor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,14 +214,10 @@ struct ClassCallSelector : public Acore::unary_function<Unit*, bool>
|
|||
bool operator()(Unit const* target) const
|
||||
{
|
||||
if (!_me || !target || !target->IsPlayer())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target->getClass() != _targetClass)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -231,304 +227,291 @@ private:
|
|||
uint8 _targetClass;
|
||||
};
|
||||
|
||||
class boss_victor_nefarius : public CreatureScript
|
||||
struct boss_victor_nefarius : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_victor_nefarius() : CreatureScript("boss_victor_nefarius") { }
|
||||
|
||||
struct boss_victor_nefariusAI : public BossAI
|
||||
boss_victor_nefarius(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
|
||||
{
|
||||
boss_victor_nefariusAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
|
||||
Initialize();
|
||||
|
||||
_nefarianLeftTunnel = instance->GetData(DATA_NEFARIAN_LEFT_TUNNEL);
|
||||
_nefarianRightTunnel = instance->GetData(DATA_NEFARIAN_RIGHT_TUNNEL);
|
||||
|
||||
if (!_nefarianLeftTunnel || !_nefarianRightTunnel)
|
||||
{
|
||||
Initialize();
|
||||
// Victor Nefarius weekly mechanic drakonid spawn
|
||||
// Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated).
|
||||
std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER };
|
||||
Acore::Containers::RandomResize(nefarianDrakonidSpawners, 2);
|
||||
|
||||
_nefarianLeftTunnel = instance->GetData(DATA_NEFARIAN_LEFT_TUNNEL);
|
||||
_nefarianRightTunnel = instance->GetData(DATA_NEFARIAN_RIGHT_TUNNEL);
|
||||
_nefarianRightTunnel = nefarianDrakonidSpawners[0];
|
||||
_nefarianLeftTunnel = nefarianDrakonidSpawners[1];
|
||||
|
||||
if (!_nefarianLeftTunnel || !_nefarianRightTunnel)
|
||||
{
|
||||
// Victor Nefarius weekly mechanic drakonid spawn
|
||||
// Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated).
|
||||
std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER };
|
||||
Acore::Containers::RandomResize(nefarianDrakonidSpawners, 2);
|
||||
|
||||
_nefarianRightTunnel = nefarianDrakonidSpawners[0];
|
||||
_nefarianLeftTunnel = nefarianDrakonidSpawners[1];
|
||||
|
||||
// save it to instance
|
||||
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
|
||||
instance->SetData(DATA_NEFARIAN_RIGHT_TUNNEL, _nefarianRightTunnel);
|
||||
}
|
||||
// save it to instance
|
||||
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
|
||||
instance->SetData(DATA_NEFARIAN_RIGHT_TUNNEL, _nefarianRightTunnel);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
void Initialize()
|
||||
{
|
||||
_killedAdds = 0;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
if (me->GetMapId() == MAP_BLACKWING_LAIR)
|
||||
{
|
||||
KilledAdds = 0;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
if (me->GetMapId() == MAP_BLACKWING_LAIR)
|
||||
if (Creature* nefarian = me->FindNearestCreature(NPC_NEFARIAN, 1000.0f, true))
|
||||
{
|
||||
if (Creature* nefarian = me->FindNearestCreature(NPC_NEFARIAN, 1000.0f, true))
|
||||
// Nefarian is spawned and he didn't finish his intro path yet, despawn it manually.
|
||||
if (nefarian->GetMotionMaster()->GetCurrentMovementGeneratorType() == MovementGeneratorType::WAYPOINT_MOTION_TYPE)
|
||||
{
|
||||
// Nefarian is spawned and he didn't finish his intro path yet, despawn it manually.
|
||||
if (nefarian->GetMotionMaster()->GetCurrentMovementGeneratorType() == MovementGeneratorType::WAYPOINT_MOTION_TYPE)
|
||||
{
|
||||
nefarian->DespawnOrUnsummon();
|
||||
}
|
||||
std::list<GameObject*> drakonidBones;
|
||||
me->GetGameObjectListWithEntryInGrid(drakonidBones, GO_DRAKONID_BONES, DEFAULT_VISIBILITY_INSTANCE);
|
||||
for (auto const& bones : drakonidBones)
|
||||
{
|
||||
bones->DespawnOrUnsummon();
|
||||
}
|
||||
nefarian->DespawnOrUnsummon();
|
||||
}
|
||||
else
|
||||
std::list<GameObject*> drakonidBones;
|
||||
me->GetGameObjectListWithEntryInGrid(drakonidBones, GO_DRAKONID_BONES, DEFAULT_VISIBILITY_INSTANCE);
|
||||
for (auto const& bones : drakonidBones)
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
me->SetVisible(true);
|
||||
me->SetPhaseMask(1, true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetStandState(UNIT_STAND_STATE_SIT_HIGH_CHAIR);
|
||||
me->RemoveAura(SPELL_NEFARIANS_BARRIER);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() != NPC_NEFARIAN)
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_NEFARIAN)
|
||||
{
|
||||
summons.DespawnEntry(_nefarianLeftTunnel);
|
||||
summons.DespawnEntry(_nefarianRightTunnel);
|
||||
me->KillSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_RESET)
|
||||
{
|
||||
me->RemoveAura(SPELL_ROOT_SELF);
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
if (action == ACTION_ADD_KILLED)
|
||||
{
|
||||
KilledAdds++;
|
||||
|
||||
if (KilledAdds == MAX_DRAKONID_KILLED)
|
||||
{
|
||||
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
|
||||
{
|
||||
nefarian->setActive(true);
|
||||
nefarian->SetCanFly(true);
|
||||
nefarian->SetDisableGravity(true);
|
||||
nefarian->GetMotionMaster()->MoveWaypoint(NEFARIAN_PATH, false);
|
||||
}
|
||||
|
||||
events.Reset();
|
||||
DoCastSelf(SPELL_ROOT_SELF, true);
|
||||
me->SetVisible(false);
|
||||
// Stop spawning adds
|
||||
EntryCheckPredicate pred(_nefarianRightTunnel);
|
||||
summons.DoAction(ACTION_SPAWNER_STOP, pred);
|
||||
EntryCheckPredicate pred2(_nefarianLeftTunnel);
|
||||
summons.DoAction(ACTION_SPAWNER_STOP, pred2);
|
||||
bones->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_NEFARIAN, DONE);
|
||||
instance->SaveToDB();
|
||||
}
|
||||
|
||||
void BeginEvent()
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
Talk(SAY_GAMESBEGIN_2);
|
||||
|
||||
DoCast(me, SPELL_NEFARIANS_BARRIER);
|
||||
me->SetCombatMovement(false);
|
||||
me->SetImmuneToPC(false);
|
||||
AttackStart(SelectTarget(SelectTargetMethod::Random, 0, 200.f, true));
|
||||
events.ScheduleEvent(EVENT_SHADOWBLINK, 500ms);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 3s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 13s, 15s);
|
||||
events.ScheduleEvent(EVENT_FEAR, 10s, 20s);
|
||||
events.ScheduleEvent(EVENT_SILENCE, 20s, 25s);
|
||||
events.ScheduleEvent(EVENT_MIND_CONTROL, 30s, 35s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_ADDS, 10s);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == 1 && data == 1)
|
||||
else
|
||||
{
|
||||
me->StopMoving();
|
||||
events.ScheduleEvent(EVENT_PATH_2, 9s);
|
||||
_Reset();
|
||||
}
|
||||
|
||||
if (type == 1 && data == 2)
|
||||
events.ScheduleEvent(EVENT_SUCCESS_1, 5s);
|
||||
me->SetVisible(true);
|
||||
me->SetPhaseMask(1, true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetStandState(UNIT_STAND_STATE_SIT_HIGH_CHAIR);
|
||||
me->RemoveAura(SPELL_NEFARIANS_BARRIER);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() != NPC_NEFARIAN)
|
||||
BossAI::JustSummoned(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_NEFARIAN)
|
||||
{
|
||||
summons.DespawnEntry(_nefarianLeftTunnel);
|
||||
summons.DespawnEntry(_nefarianRightTunnel);
|
||||
me->KillSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_RESET)
|
||||
{
|
||||
me->RemoveAura(SPELL_ROOT_SELF);
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
if (action == ACTION_ADD_KILLED)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
events.Update(diff);
|
||||
_killedAdds++;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
if (_killedAdds == MAX_DRAKONID_KILLED)
|
||||
{
|
||||
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_PATH_2:
|
||||
me->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_2, false);
|
||||
events.ScheduleEvent(EVENT_CHAOS_1, 7s);
|
||||
break;
|
||||
case EVENT_CHAOS_1:
|
||||
if (Creature* gyth = me->FindNearestCreature(NPC_GYTH, 75.0f, true))
|
||||
{
|
||||
me->SetFacingToObject(gyth);
|
||||
Talk(SAY_CHAOS_SPELL);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHAOS_2, 2s);
|
||||
break;
|
||||
case EVENT_CHAOS_2:
|
||||
DoCast(SPELL_CHROMATIC_CHAOS);
|
||||
me->SetFacingTo(1.570796f);
|
||||
break;
|
||||
case EVENT_SUCCESS_1:
|
||||
if (Unit* player = me->SelectNearestPlayer(60.0f))
|
||||
{
|
||||
me->SetFacingToObject(player);
|
||||
Talk(SAY_SUCCESS);
|
||||
if (GameObject* portcullis1 = me->FindNearestGameObject(GO_PORTCULLIS_ACTIVE, 65.0f))
|
||||
portcullis1->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* portcullis2 = me->FindNearestGameObject(GO_PORTCULLIS_TOBOSSROOMS, 80.0f))
|
||||
portcullis2->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUCCESS_2, 4s);
|
||||
break;
|
||||
case EVENT_SUCCESS_2:
|
||||
DoCast(me, SPELL_VAELASTRASZZ_SPAWN);
|
||||
me->DespawnOrUnsummon(1s);
|
||||
break;
|
||||
case EVENT_PATH_3:
|
||||
me->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_3, false);
|
||||
break;
|
||||
case EVENT_START_EVENT:
|
||||
BeginEvent();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nefarian->setActive(true);
|
||||
nefarian->SetCanFly(true);
|
||||
nefarian->SetDisableGravity(true);
|
||||
nefarian->GetMotionMaster()->MoveWaypoint(NEFARIAN_PATH, false);
|
||||
}
|
||||
|
||||
events.Reset();
|
||||
DoCastSelf(SPELL_ROOT_SELF, true);
|
||||
me->SetVisible(false);
|
||||
// Stop spawning adds
|
||||
EntryCheckPredicate pred(_nefarianRightTunnel);
|
||||
summons.DoAction(ACTION_SPAWNER_STOP, pred);
|
||||
EntryCheckPredicate pred2(_nefarianLeftTunnel);
|
||||
summons.DoAction(ACTION_SPAWNER_STOP, pred2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetBossState(DATA_NEFARIAN, DONE);
|
||||
instance->SaveToDB();
|
||||
}
|
||||
|
||||
void BeginEvent()
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
Talk(SAY_GAMESBEGIN_2);
|
||||
|
||||
DoCast(me, SPELL_NEFARIANS_BARRIER);
|
||||
me->SetCombatMovement(false);
|
||||
me->SetImmuneToPC(false);
|
||||
AttackStart(SelectTarget(SelectTargetMethod::Random, 0, 200.f, true));
|
||||
events.ScheduleEvent(EVENT_SHADOWBLINK, 500ms);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 3s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 13s, 15s);
|
||||
events.ScheduleEvent(EVENT_FEAR, 10s, 20s);
|
||||
events.ScheduleEvent(EVENT_SILENCE, 20s, 25s);
|
||||
events.ScheduleEvent(EVENT_MIND_CONTROL, 30s, 35s);
|
||||
events.ScheduleEvent(EVENT_SPAWN_ADDS, 10s);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == 1 && data == 1)
|
||||
{
|
||||
me->StopMoving();
|
||||
events.ScheduleEvent(EVENT_PATH_2, 9s);
|
||||
}
|
||||
|
||||
if (type == 1 && data == 2)
|
||||
events.ScheduleEvent(EVENT_SUCCESS_1, 5s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_PATH_2:
|
||||
me->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_2, false);
|
||||
events.ScheduleEvent(EVENT_CHAOS_1, 7s);
|
||||
break;
|
||||
case EVENT_CHAOS_1:
|
||||
if (Creature* gyth = me->FindNearestCreature(NPC_GYTH, 75.0f, true))
|
||||
{
|
||||
me->SetFacingToObject(gyth);
|
||||
Talk(SAY_CHAOS_SPELL);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHAOS_2, 2s);
|
||||
break;
|
||||
case EVENT_CHAOS_2:
|
||||
DoCast(SPELL_CHROMATIC_CHAOS);
|
||||
me->SetFacingTo(1.570796f);
|
||||
break;
|
||||
case EVENT_SUCCESS_1:
|
||||
if (Unit* player = me->SelectNearestPlayer(60.0f))
|
||||
{
|
||||
me->SetFacingToObject(player);
|
||||
Talk(SAY_SUCCESS);
|
||||
if (GameObject* portcullis1 = me->FindNearestGameObject(GO_PORTCULLIS_ACTIVE, 65.0f))
|
||||
portcullis1->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* portcullis2 = me->FindNearestGameObject(GO_PORTCULLIS_TOBOSSROOMS, 80.0f))
|
||||
portcullis2->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUCCESS_2, 4s);
|
||||
break;
|
||||
case EVENT_SUCCESS_2:
|
||||
DoCast(me, SPELL_VAELASTRASZZ_SPAWN);
|
||||
me->DespawnOrUnsummon(1s);
|
||||
break;
|
||||
case EVENT_PATH_3:
|
||||
me->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_3, false);
|
||||
break;
|
||||
case EVENT_START_EVENT:
|
||||
BeginEvent();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Only do this if we haven't spawned nefarian yet
|
||||
if (UpdateVictim() && _killedAdds <= MAX_DRAKONID_KILLED)
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
// Only do this if we haven't spawned nefarian yet
|
||||
if (UpdateVictim() && KilledAdds <= MAX_DRAKONID_KILLED)
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
events.Update(diff);
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOW_BOLT:
|
||||
DoCastRandomTarget(SPELL_SHADOWBOLT, 0, 150.f);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2s, 4s);
|
||||
break;
|
||||
case EVENT_SHADOW_BOLT_VOLLEY:
|
||||
DoCastAOE(SPELL_SHADOWBOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 19s, 25s);
|
||||
break;
|
||||
case EVENT_FEAR:
|
||||
DoCastRandomTarget(SPELL_FEAR, 0, 40.0f);
|
||||
events.ScheduleEvent(EVENT_FEAR, 10s, 20s);
|
||||
break;
|
||||
case EVENT_SILENCE:
|
||||
DoCastRandomTarget(SPELL_SILENCE, 0, 150.f);
|
||||
events.ScheduleEvent(EVENT_SILENCE, 14s,23s);
|
||||
break;
|
||||
case EVENT_MIND_CONTROL:
|
||||
DoCastRandomTarget(SPELL_SHADOW_COMMAND, 0, 40.0f);
|
||||
events.ScheduleEvent(EVENT_MIND_CONTROL, 24s, 30s);
|
||||
break;
|
||||
case EVENT_SHADOWBLINK:
|
||||
DoCastSelf(SPELL_SHADOWBLINK);
|
||||
events.ScheduleEvent(EVENT_SHADOWBLINK, 30s, 40s);
|
||||
break;
|
||||
case EVENT_SPAWN_ADDS:
|
||||
// Spawn the spawners.
|
||||
me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]);
|
||||
me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOW_BOLT:
|
||||
DoCastRandomTarget(SPELL_SHADOWBOLT, 0, 150.f);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2s, 4s);
|
||||
break;
|
||||
case EVENT_SHADOW_BOLT_VOLLEY:
|
||||
DoCastAOE(SPELL_SHADOWBOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 19s, 25s);
|
||||
break;
|
||||
case EVENT_FEAR:
|
||||
DoCastRandomTarget(SPELL_FEAR, 0, 40.0f);
|
||||
events.ScheduleEvent(EVENT_FEAR, 10s, 20s);
|
||||
break;
|
||||
case EVENT_SILENCE:
|
||||
DoCastRandomTarget(SPELL_SILENCE, 0, 150.f);
|
||||
events.ScheduleEvent(EVENT_SILENCE, 14s,23s);
|
||||
break;
|
||||
case EVENT_MIND_CONTROL:
|
||||
DoCastRandomTarget(SPELL_SHADOW_COMMAND, 0, 40.0f);
|
||||
events.ScheduleEvent(EVENT_MIND_CONTROL, 24s, 30s);
|
||||
break;
|
||||
case EVENT_SHADOWBLINK:
|
||||
DoCastSelf(SPELL_SHADOWBLINK);
|
||||
events.ScheduleEvent(EVENT_SHADOWBLINK, 30s, 40s);
|
||||
break;
|
||||
case EVENT_SPAWN_ADDS:
|
||||
// Spawn the spawners.
|
||||
me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]);
|
||||
me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
|
||||
{
|
||||
if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID)
|
||||
{
|
||||
// pussywizard:
|
||||
InstanceScript* instance = player->GetInstanceScript();
|
||||
if (!instance || instance->GetBossState(DATA_NEFARIAN) == DONE)
|
||||
return;
|
||||
|
||||
CloseGossipMenuFor(player);
|
||||
Talk(SAY_GAMESBEGIN_1);
|
||||
events.ScheduleEvent(EVENT_START_EVENT, 4s);
|
||||
me->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 KilledAdds;
|
||||
uint32 _nefarianRightTunnel;
|
||||
uint32 _nefarianLeftTunnel;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_victor_nefariusAI>(creature);
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
|
||||
{
|
||||
if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID)
|
||||
{
|
||||
// pussywizard:
|
||||
InstanceScript* instance = player->GetInstanceScript();
|
||||
if (!instance || instance->GetBossState(DATA_NEFARIAN) == DONE)
|
||||
return;
|
||||
|
||||
CloseGossipMenuFor(player);
|
||||
Talk(SAY_GAMESBEGIN_1);
|
||||
events.ScheduleEvent(EVENT_START_EVENT, 4s);
|
||||
me->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _killedAdds;
|
||||
uint32 _nefarianRightTunnel;
|
||||
uint32 _nefarianLeftTunnel;
|
||||
};
|
||||
|
||||
struct boss_nefarian : public BossAI
|
||||
|
|
@ -545,12 +528,8 @@ struct boss_nefarian : public BossAI
|
|||
{
|
||||
_Reset();
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_VICTOR_NEFARIUS, 200.f, true))
|
||||
{
|
||||
if (victor->AI())
|
||||
{
|
||||
victor->AI()->DoAction(ACTION_RESET);
|
||||
}
|
||||
}
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
|
|
@ -578,9 +557,7 @@ struct boss_nefarian : public BossAI
|
|||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (rand32() % 5)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(SAY_SLAY, victim);
|
||||
}
|
||||
|
|
@ -588,14 +565,10 @@ struct boss_nefarian : public BossAI
|
|||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != WAYPOINT_MOTION_TYPE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == 4)
|
||||
{
|
||||
Talk(SAY_INTRO);
|
||||
}
|
||||
|
||||
if (id == 6)
|
||||
{
|
||||
|
|
@ -617,9 +590,7 @@ struct boss_nefarian : public BossAI
|
|||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoZoneInCombat();
|
||||
if (me->GetVictim())
|
||||
{
|
||||
AttackStart(me->GetVictim());
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 12s);
|
||||
events.ScheduleEvent(EVENT_FEAR, 25s, 35s);
|
||||
|
|
@ -633,16 +604,12 @@ struct boss_nefarian : public BossAI
|
|||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
|
|
@ -671,16 +638,10 @@ struct boss_nefarian : public BossAI
|
|||
break;
|
||||
case EVENT_CLASSCALL:
|
||||
if (classesPresent.empty())
|
||||
{
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
if (Unit* victim = ref->GetVictim())
|
||||
{
|
||||
if (victim->IsPlayer())
|
||||
classesPresent.insert(victim->getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 targetClass = Acore::Containers::SelectRandomContainerElement(classesPresent);
|
||||
|
||||
|
|
@ -731,9 +692,7 @@ struct boss_nefarian : public BossAI
|
|||
me->GetMap()->DoForAllPlayers([&](Player* p)
|
||||
{
|
||||
if (!p->IsGameMaster())
|
||||
{
|
||||
me->CastSpell(p, SPELL_DEATH_KNIGHT, true);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
|
|
@ -745,9 +704,7 @@ struct boss_nefarian : public BossAI
|
|||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
|
|
@ -783,9 +740,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||
{
|
||||
me->AddUnitState(UNIT_STATE_ROOT);
|
||||
if (!me->HasAura(SPELL_ROOT_SELF))
|
||||
{
|
||||
me->AddAura(SPELL_ROOT_SELF, me);
|
||||
}
|
||||
|
||||
me->AddAura(AURA_AVOIDANCE, me);
|
||||
scheduler.CancelAll();
|
||||
|
|
@ -809,9 +764,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||
}
|
||||
|
||||
if (!spellId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint32> mobsEntries =
|
||||
{
|
||||
|
|
@ -835,25 +788,19 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||
tmpMobList.pop_front();
|
||||
|
||||
if (!curr->IsAlive())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (apply && me->IsAlive())
|
||||
{
|
||||
if (me->IsWithinDistInMap(curr, 40.f))
|
||||
{
|
||||
if (!curr->HasAura(spellId))
|
||||
{
|
||||
curr->AddAura(spellId, curr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curr->HasAura(spellId))
|
||||
{
|
||||
curr->RemoveAurasDueToSpell(spellId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -899,9 +846,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (me->GetEntry() != NPC_TOTEM_C_FIRE_NOVA)
|
||||
{
|
||||
SetAura(false);
|
||||
}
|
||||
|
||||
scheduler.CancelAll();
|
||||
}
|
||||
|
|
@ -909,9 +854,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
|
@ -952,9 +895,7 @@ struct npc_drakonid_spawner : public ScriptedAI
|
|||
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
|
||||
{
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _owner))
|
||||
{
|
||||
victor->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
|
||||
}
|
||||
|
||||
ObjectGuid summonGuid = summon->GetGUID();
|
||||
|
||||
|
|
@ -1002,15 +943,11 @@ class spell_class_call_handler : public SpellScript
|
|||
{
|
||||
Player const* player = target->ToPlayer();
|
||||
if (!player || player->IsClass(CLASS_DEATH_KNIGHT)) // ignore all death knights from whatever spell, for some reason the condition below is not working x.x
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto it = classCallSpells.find(spellInfo->Id);
|
||||
if (it != classCallSpells.end()) // should never happen but only to be sure.
|
||||
{
|
||||
return target->ToPlayer()->getClass() != it->second;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
|
@ -1022,9 +959,7 @@ class spell_class_call_handler : public SpellScript
|
|||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
if (!caster || !target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Position tp = caster->GetFirstCollisionPosition(5.f, 0.f);
|
||||
target->NearTeleportTo(tp.GetPositionX(), tp.GetPositionY(), tp.GetPositionZ(), tp.GetOrientation());
|
||||
|
|
@ -1033,9 +968,7 @@ class spell_class_call_handler : public SpellScript
|
|||
void HandleOnHitWarlock()
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
target->CastSpell(target, SPELL_SUMMON_INFERNALS, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -1065,9 +998,7 @@ class aura_class_call_wild_magic : public AuraScript
|
|||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (!GetTarget())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_POLYMORPH, true);
|
||||
}
|
||||
|
|
@ -1092,12 +1023,8 @@ class aura_class_call_siphon_blessing : public AuraScript
|
|||
PreventDefaultAction();
|
||||
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
if (Unit* nefarian = target->FindNearestCreature(NPC_NEFARIAN, 100.f))
|
||||
{
|
||||
target->CastSpell(nefarian, SPELL_BLESSING_PROTECTION, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -1154,9 +1081,7 @@ class spell_corrupted_totems : public SpellScript
|
|||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
if (!GetCaster())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<uint32> spellList = { SPELL_CORRUPTED_FIRE_NOVA_TOTEM, SPELL_CORRUPTED_HEALING_TOTEM, SPELL_CORRUPTED_STONESKIN_TOTEM, SPELL_CORRUPTED_WINDFURY_TOTEM };
|
||||
uint32 spellId = Acore::Containers::SelectRandomContainerElement(spellList);
|
||||
|
|
@ -1207,15 +1132,11 @@ class spell_shadowblink : public SpellScript
|
|||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster || !caster->ToCreature() || !caster->ToCreature()->AI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = caster->ToCreature()->AI()->SelectTarget(SelectTargetMethod::Random, 0, 200.f, true);
|
||||
if (!target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& itr : spellPos)
|
||||
{
|
||||
|
|
@ -1252,9 +1173,7 @@ class spell_spawn_drakonid : public SpellScript
|
|||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
caster->CastSpell(caster, spawnerSpells[caster->GetEntry()], true);
|
||||
}
|
||||
|
|
@ -1267,7 +1186,7 @@ class spell_spawn_drakonid : public SpellScript
|
|||
|
||||
void AddSC_boss_nefarian()
|
||||
{
|
||||
new boss_victor_nefarius();
|
||||
RegisterBlackwingLairCreatureAI(boss_victor_nefarius);
|
||||
RegisterCreatureAI(boss_nefarian);
|
||||
RegisterCreatureAI(npc_corrupted_totem);
|
||||
RegisterCreatureAI(npc_drakonid_spawner);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
|
||||
#include "CreatureScript.h"
|
||||
#include "GameObject.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "GameObjectScript.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
|
@ -70,214 +72,190 @@ enum EVENTS
|
|||
EVENT_CONFLAGRATION = 4
|
||||
};
|
||||
|
||||
class boss_razorgore : public CreatureScript
|
||||
struct boss_razorgore : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_razorgore() : CreatureScript("boss_razorgore") { }
|
||||
boss_razorgore(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { }
|
||||
|
||||
struct boss_razorgoreAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_razorgoreAI(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_charmerGUID.Clear();
|
||||
secondPhase = false;
|
||||
summons.DespawnAll();
|
||||
instance->SetData(DATA_EGG_EVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (secondPhase)
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Respawn shorty in case of failure during phase 1.
|
||||
me->SetCorpseRemoveTime(25);
|
||||
me->SetRespawnTime(30);
|
||||
me->SaveRespawnTime();
|
||||
|
||||
// Might not be required, safe measure.
|
||||
me->SetLootRecipient(nullptr);
|
||||
|
||||
instance->SetData(DATA_EGG_EVENT, FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
return !(target->IsCreature() && !secondPhase);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 15s);
|
||||
events.ScheduleEvent(EVENT_STOMP, 35s);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 7s);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 12s);
|
||||
|
||||
instance->SetData(DATA_EGG_EVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void DoChangePhase()
|
||||
{
|
||||
secondPhase = true;
|
||||
_charmerGUID.Clear();
|
||||
me->RemoveAllAuras();
|
||||
|
||||
DoCastSelf(SPELL_WARMING_FLAMES, true);
|
||||
|
||||
if (Creature* troops = instance->GetCreature(DATA_NEFARIAN_TROOPS))
|
||||
{
|
||||
troops->AI()->Talk(EMOTE_TROOPS_RETREAT);
|
||||
}
|
||||
|
||||
for (ObjectGuid const& guid : _summonGUIDS)
|
||||
{
|
||||
if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
|
||||
{
|
||||
if (creature->IsAlive())
|
||||
{
|
||||
creature->CombatStop(true);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
creature->GetMotionMaster()->MovePoint(0, Position(-7560.568848f, -1028.553345f, 408.491211f, 0.523858f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 /*id*/) override
|
||||
{
|
||||
_charmerGUID = guid;
|
||||
}
|
||||
|
||||
void OnCharmed(bool apply) override
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
|
||||
{
|
||||
charmer->CastSpell(charmer, SPELL_MIND_EXHAUSTION, true);
|
||||
charmer->CastSpell(me, SPELL_MINDCONTROL_VISUAL, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
|
||||
{
|
||||
charmer->RemoveAurasDueToSpell(SPELL_MINDCONTROL_VISUAL);
|
||||
me->EngageWithTarget(charmer);
|
||||
me->AddThreat(charmer, 100.0f);
|
||||
me->AI()->AttackStart(charmer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_PHASE_TWO)
|
||||
{
|
||||
DoChangePhase();
|
||||
}
|
||||
|
||||
if (action == TALK_EGG_BROKEN_RAND)
|
||||
{
|
||||
Talk(urand(SAY_EGGS_BROKEN1, SAY_EGGS_BROKEN3));
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
_summonGUIDS.push_back(summon->GetGUID());
|
||||
summon->SetOwnerGUID(me->GetGUID());
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonMovementInform(Creature* summon, uint32 movementType, uint32 /*pathId*/) override
|
||||
{
|
||||
if (movementType == POINT_MOTION_TYPE)
|
||||
{
|
||||
summon->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!secondPhase && damage >= me->GetHealth())
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
DoCastAOE(SPELL_EXPLODE_ORB);
|
||||
DoCastAOE(SPELL_EXPLOSION);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!me->IsCharmed())
|
||||
{
|
||||
events.Update(diff);
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 7s, 10s);
|
||||
break;
|
||||
case EVENT_STOMP:
|
||||
DoCastVictim(SPELL_WARSTOMP);
|
||||
events.ScheduleEvent(EVENT_STOMP, 15s, 25s);
|
||||
break;
|
||||
case EVENT_FIREBALL:
|
||||
DoCastVictim(SPELL_FIREBALLVOLLEY);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 12s, 15s);
|
||||
break;
|
||||
case EVENT_CONFLAGRATION:
|
||||
DoCastVictim(SPELL_CONFLAGRATION);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 30s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool secondPhase;
|
||||
ObjectGuid _charmerGUID;
|
||||
GuidVector _summonGUIDS;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_razorgoreAI>(creature);
|
||||
_Reset();
|
||||
_charmerGUID.Clear();
|
||||
secondPhase = false;
|
||||
summons.DespawnAll();
|
||||
instance->SetData(DATA_EGG_EVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (secondPhase)
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Respawn shorty in case of failure during phase 1.
|
||||
me->SetCorpseRemoveTime(25);
|
||||
me->SetRespawnTime(30);
|
||||
me->SaveRespawnTime();
|
||||
|
||||
// Might not be required, safe measure.
|
||||
me->SetLootRecipient(nullptr);
|
||||
|
||||
instance->SetData(DATA_EGG_EVENT, FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
return !(target->IsCreature() && !secondPhase);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 15s);
|
||||
events.ScheduleEvent(EVENT_STOMP, 35s);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 7s);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 12s);
|
||||
|
||||
instance->SetData(DATA_EGG_EVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void DoChangePhase()
|
||||
{
|
||||
secondPhase = true;
|
||||
_charmerGUID.Clear();
|
||||
me->RemoveAllAuras();
|
||||
|
||||
DoCastSelf(SPELL_WARMING_FLAMES, true);
|
||||
|
||||
if (Creature* troops = instance->GetCreature(DATA_NEFARIAN_TROOPS))
|
||||
troops->AI()->Talk(EMOTE_TROOPS_RETREAT);
|
||||
|
||||
for (ObjectGuid const& guid : _summonGUIDS)
|
||||
{
|
||||
if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
|
||||
if (creature->IsAlive())
|
||||
{
|
||||
creature->CombatStop(true);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
creature->GetMotionMaster()->MovePoint(0, Position(-7560.568848f, -1028.553345f, 408.491211f, 0.523858f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 /*id*/) override
|
||||
{
|
||||
_charmerGUID = guid;
|
||||
}
|
||||
|
||||
void OnCharmed(bool apply) override
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
|
||||
{
|
||||
charmer->CastSpell(charmer, SPELL_MIND_EXHAUSTION, true);
|
||||
charmer->CastSpell(me, SPELL_MINDCONTROL_VISUAL, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
|
||||
{
|
||||
charmer->RemoveAurasDueToSpell(SPELL_MINDCONTROL_VISUAL);
|
||||
me->EngageWithTarget(charmer);
|
||||
me->AddThreat(charmer, 100.0f);
|
||||
me->AI()->AttackStart(charmer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_PHASE_TWO)
|
||||
DoChangePhase();
|
||||
|
||||
if (action == TALK_EGG_BROKEN_RAND)
|
||||
Talk(urand(SAY_EGGS_BROKEN1, SAY_EGGS_BROKEN3));
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
_summonGUIDS.push_back(summon->GetGUID());
|
||||
summon->SetOwnerGUID(me->GetGUID());
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonMovementInform(Creature* summon, uint32 movementType, uint32 /*pathId*/) override
|
||||
{
|
||||
if (movementType == POINT_MOTION_TYPE)
|
||||
summon->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!secondPhase && damage >= me->GetHealth())
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
DoCastAOE(SPELL_EXPLODE_ORB);
|
||||
DoCastAOE(SPELL_EXPLOSION);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!me->IsCharmed())
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 7s, 10s);
|
||||
break;
|
||||
case EVENT_STOMP:
|
||||
DoCastVictim(SPELL_WARSTOMP);
|
||||
events.ScheduleEvent(EVENT_STOMP, 15s, 25s);
|
||||
break;
|
||||
case EVENT_FIREBALL:
|
||||
DoCastVictim(SPELL_FIREBALLVOLLEY);
|
||||
events.ScheduleEvent(EVENT_FIREBALL, 12s, 15s);
|
||||
break;
|
||||
case EVENT_CONFLAGRATION:
|
||||
DoCastVictim(SPELL_CONFLAGRATION);
|
||||
events.ScheduleEvent(EVENT_CONFLAGRATION, 30s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool secondPhase;
|
||||
ObjectGuid _charmerGUID;
|
||||
GuidVector _summonGUIDS;
|
||||
};
|
||||
|
||||
class go_orb_of_domination : public GameObjectScript
|
||||
struct go_orb_of_domination : public GameObjectAI
|
||||
{
|
||||
public:
|
||||
go_orb_of_domination() : GameObjectScript("go_orb_of_domination") { }
|
||||
go_orb_of_domination(GameObject* go) : GameObjectAI(go) { }
|
||||
|
||||
bool OnGossipHello(Player* player, GameObject* go) override
|
||||
bool GossipHello(Player* player, bool /*reportUse*/) override
|
||||
{
|
||||
if (InstanceScript* instance = go->GetInstanceScript())
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (instance->GetData(DATA_EGG_EVENT) != DONE && !player->HasAura(SPELL_MIND_EXHAUSTION) && !player->GetPet())
|
||||
if (Creature* razor = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_RAZORGORE_THE_UNTAMED)))
|
||||
if (Creature* razor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORGORE_THE_UNTAMED)))
|
||||
{
|
||||
razor->AI()->SetGUID(player->GetGUID());
|
||||
razor->Attack(player, true);
|
||||
|
|
@ -294,12 +272,9 @@ class spell_egg_event : public SpellScript
|
|||
void HandleOnHit()
|
||||
{
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
{
|
||||
instance->SetData(DATA_EGG_EVENT, SPECIAL);
|
||||
}
|
||||
|
||||
if (Creature* razorgore = GetCaster()->ToCreature())
|
||||
{
|
||||
if (GameObject* egg = GetHitGObj())
|
||||
{
|
||||
razorgore->AI()->DoAction(TALK_EGG_BROKEN_RAND);
|
||||
|
|
@ -307,7 +282,6 @@ class spell_egg_event : public SpellScript
|
|||
egg->UseDoorOrButton(10000);
|
||||
egg->SetRespawnTime(WEEK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -318,7 +292,7 @@ class spell_egg_event : public SpellScript
|
|||
|
||||
void AddSC_boss_razorgore()
|
||||
{
|
||||
new boss_razorgore();
|
||||
new go_orb_of_domination();
|
||||
RegisterBlackwingLairCreatureAI(boss_razorgore);
|
||||
RegisterBlackwingLairGameObjectAI(go_orb_of_domination);
|
||||
RegisterSpellScript(spell_egg_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,227 +72,214 @@ enum Events
|
|||
EVENT_BURNING_ADRENALINE = 12,
|
||||
};
|
||||
|
||||
class boss_vaelastrasz : public CreatureScript
|
||||
struct boss_vaelastrasz : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_vaelastrasz() : CreatureScript("boss_vaelastrasz") { }
|
||||
|
||||
struct boss_vaelAI : public BossAI
|
||||
boss_vaelastrasz(Creature* creature) : BossAI(creature, DATA_VAELASTRAZ_THE_CORRUPT)
|
||||
{
|
||||
boss_vaelAI(Creature* creature) : BossAI(creature, DATA_VAELASTRAZ_THE_CORRUPT)
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
PlayerGUID.Clear();
|
||||
HasYelled = false;
|
||||
_introDone = false;
|
||||
_burningAdrenalineCast = 0;
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
me->SetHealth(me->CountPctFromMaxHealth(30));
|
||||
|
||||
if (!_introDone)
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_DEAD);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
Initialize();
|
||||
_eventsIntro.Reset();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
else
|
||||
{
|
||||
PlayerGUID.Clear();
|
||||
HasYelled = false;
|
||||
_introDone = false;
|
||||
_burningAdrenalineCast = 0;
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
DoCastAOE(SPELL_ESSENCE_OF_THE_RED);
|
||||
// now drop damage requirement to be able to take loot
|
||||
me->ResetPlayerDamageReq();
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 10s);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 15s);
|
||||
events.ScheduleEvent(EVENT_FIRE_NOVA, 5s);
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 11s);
|
||||
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15s);
|
||||
}
|
||||
|
||||
void BeginSpeech(Unit* target)
|
||||
{
|
||||
PlayerGUID = target->GetGUID();
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_1, 1s);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (rand32() % 5)
|
||||
return;
|
||||
|
||||
Talk(SAY_KILLTARGET, victim);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
_eventsIntro.Update(diff);
|
||||
|
||||
// Speech
|
||||
if (!_introDone)
|
||||
{
|
||||
_Reset();
|
||||
me->SetHealth(me->CountPctFromMaxHealth(30));
|
||||
|
||||
if (!_introDone)
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_DEAD);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
Initialize();
|
||||
_eventsIntro.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
HasYelled = false;
|
||||
_burningAdrenalineCast = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
DoCastAOE(SPELL_ESSENCE_OF_THE_RED);
|
||||
// now drop damage requirement to be able to take loot
|
||||
me->ResetPlayerDamageReq();
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 10s);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 15s);
|
||||
events.ScheduleEvent(EVENT_FIRE_NOVA, 5s);
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 11s);
|
||||
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15s);
|
||||
}
|
||||
|
||||
void BeginSpeech(Unit* target)
|
||||
{
|
||||
PlayerGUID = target->GetGUID();
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_1, 1s);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (rand32() % 5)
|
||||
return;
|
||||
|
||||
Talk(SAY_KILLTARGET, victim);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
_eventsIntro.Update(diff);
|
||||
|
||||
// Speech
|
||||
if (!_introDone)
|
||||
{
|
||||
while (uint32 eventId = _eventsIntro.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SPEECH_1:
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SummonCreature(NPC_VICTOR_NEFARIUS, aNefariusSpawnLoc[0], aNefariusSpawnLoc[1], aNefariusSpawnLoc[2], aNefariusSpawnLoc[3], TEMPSUMMON_TIMED_DESPAWN, 26000);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_2, 1s);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
case EVENT_SPEECH_2:
|
||||
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
|
||||
{
|
||||
nefarius->CastSpell(me, SPELL_NEFARIUS_CORRUPTION, TRIGGERED_CAST_DIRECTLY);
|
||||
nefarius->Yell(SAY_NEFARIAN_VAEL_INTRO);
|
||||
nefarius->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
}
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_3, 18s);
|
||||
break;
|
||||
case EVENT_SPEECH_3:
|
||||
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
|
||||
nefarius->CastSpell(me, SPELL_RED_LIGHTNING, TRIGGERED_NONE);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_4, 2s);
|
||||
break;
|
||||
case EVENT_SPEECH_4:
|
||||
Talk(SAY_LINE1);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_5, 12s);
|
||||
break;
|
||||
case EVENT_SPEECH_5:
|
||||
Talk(SAY_LINE2);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_6, 12s);
|
||||
break;
|
||||
case EVENT_SPEECH_6:
|
||||
Talk(SAY_LINE3);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_7, 17s);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
case EVENT_SPEECH_7:
|
||||
me->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
|
||||
if (PlayerGUID && ObjectAccessor::GetUnit(*me, PlayerGUID))
|
||||
AttackStart(ObjectAccessor::GetUnit(*me, PlayerGUID));
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
_introDone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
while (uint32 eventId = _eventsIntro.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CLEAVE:
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 15s);
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
case EVENT_SPEECH_1:
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SummonCreature(NPC_VICTOR_NEFARIUS, aNefariusSpawnLoc[0], aNefariusSpawnLoc[1], aNefariusSpawnLoc[2], aNefariusSpawnLoc[3], TEMPSUMMON_TIMED_DESPAWN, 26000);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_2, 1s);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCastVictim(SPELL_FLAME_BREATH);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 8s, 14s);
|
||||
break;
|
||||
case EVENT_FIRE_NOVA:
|
||||
DoCastVictim(SPELL_FIRE_NOVA);
|
||||
events.ScheduleEvent(EVENT_FIRE_NOVA, 3s, 5s);
|
||||
break;
|
||||
case EVENT_TAIL_SWEEP:
|
||||
DoCastAOE(SPELL_TAIL_SWEEP);
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 15s);
|
||||
break;
|
||||
case EVENT_BURNING_ADRENALINE:
|
||||
{
|
||||
if (_burningAdrenalineCast < 2) // It's better to use TaskScheduler for this, but zzz
|
||||
case EVENT_SPEECH_2:
|
||||
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
|
||||
{
|
||||
//selects a random target that isn't the current victim and is a mana user (selects mana users) but not pets
|
||||
//it also ignores targets who have the aura. We don't want to place the debuff on the same target twice.
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [&](Unit* u) { return u && !u->IsPet() && u->getPowerType() == POWER_MANA && !u->HasAura(SPELL_BURNING_ADRENALINE) && u != me->GetVictim(); }))
|
||||
{
|
||||
me->CastSpell(target, SPELL_BURNING_ADRENALINE, true);
|
||||
}
|
||||
|
||||
_burningAdrenalineCast++;
|
||||
nefarius->CastSpell(me, SPELL_NEFARIUS_CORRUPTION, TRIGGERED_CAST_DIRECTLY);
|
||||
nefarius->Yell(SAY_NEFARIAN_VAEL_INTRO);
|
||||
nefarius->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_BURNING_ADRENALINE, true);
|
||||
_burningAdrenalineCast = 0;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15s);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_3, 18s);
|
||||
break;
|
||||
case EVENT_SPEECH_3:
|
||||
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
|
||||
nefarius->CastSpell(me, SPELL_RED_LIGHTNING, TRIGGERED_NONE);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_4, 2s);
|
||||
break;
|
||||
case EVENT_SPEECH_4:
|
||||
Talk(SAY_LINE1);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_5, 12s);
|
||||
break;
|
||||
case EVENT_SPEECH_5:
|
||||
Talk(SAY_LINE2);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_6, 12s);
|
||||
break;
|
||||
case EVENT_SPEECH_6:
|
||||
Talk(SAY_LINE3);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
_eventsIntro.ScheduleEvent(EVENT_SPEECH_7, 17s);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
case EVENT_SPEECH_7:
|
||||
me->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
|
||||
if (PlayerGUID && ObjectAccessor::GetUnit(*me, PlayerGUID))
|
||||
AttackStart(ObjectAccessor::GetUnit(*me, PlayerGUID));
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
_introDone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Yell if hp lower than 15%
|
||||
if (HealthBelowPct(15) && !HasYelled)
|
||||
{
|
||||
Talk(SAY_HALFLIFE);
|
||||
HasYelled = true;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
if (summoned->GetEntry() == NPC_VICTOR_NEFARIUS)
|
||||
switch (eventId)
|
||||
{
|
||||
// Set not selectable, so players won't interact with it
|
||||
summoned->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
m_nefariusGuid = summoned->GetGUID();
|
||||
case EVENT_CLEAVE:
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 15s);
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCastVictim(SPELL_FLAME_BREATH);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 8s, 14s);
|
||||
break;
|
||||
case EVENT_FIRE_NOVA:
|
||||
DoCastVictim(SPELL_FIRE_NOVA);
|
||||
events.ScheduleEvent(EVENT_FIRE_NOVA, 3s, 5s);
|
||||
break;
|
||||
case EVENT_TAIL_SWEEP:
|
||||
DoCastAOE(SPELL_TAIL_SWEEP);
|
||||
events.ScheduleEvent(EVENT_TAIL_SWEEP, 15s);
|
||||
break;
|
||||
case EVENT_BURNING_ADRENALINE:
|
||||
{
|
||||
if (_burningAdrenalineCast < 2) // It's better to use TaskScheduler for this, but zzz
|
||||
{
|
||||
//selects a random target that isn't the current victim and is a mana user (selects mana users) but not pets
|
||||
//it also ignores targets who have the aura. We don't want to place the debuff on the same target twice.
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [&](Unit* u) { return u && !u->IsPet() && u->getPowerType() == POWER_MANA && !u->HasAura(SPELL_BURNING_ADRENALINE) && u != me->GetVictim(); }))
|
||||
me->CastSpell(target, SPELL_BURNING_ADRENALINE, true);
|
||||
|
||||
_burningAdrenalineCast++;
|
||||
}
|
||||
else
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_BURNING_ADRENALINE, true);
|
||||
_burningAdrenalineCast = 0;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
|
||||
// Yell if hp lower than 15%
|
||||
if (HealthBelowPct(15) && !HasYelled)
|
||||
{
|
||||
if (sender == GOSSIP_ID && action == 0)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
BeginSpeech(player);
|
||||
}
|
||||
Talk(SAY_HALFLIFE);
|
||||
HasYelled = true;
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid PlayerGUID;
|
||||
ObjectGuid m_nefariusGuid;
|
||||
bool HasYelled;
|
||||
bool _introDone;
|
||||
EventMap _eventsIntro;
|
||||
uint8 _burningAdrenalineCast;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackwingLairAI<boss_vaelAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
if (summoned->GetEntry() == NPC_VICTOR_NEFARIUS)
|
||||
{
|
||||
// Set not selectable, so players won't interact with it
|
||||
summoned->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
m_nefariusGuid = summoned->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
|
||||
{
|
||||
if (sender == GOSSIP_ID && action == 0)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
BeginSpeech(player);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid PlayerGUID;
|
||||
ObjectGuid m_nefariusGuid;
|
||||
bool HasYelled;
|
||||
bool _introDone;
|
||||
EventMap _eventsIntro;
|
||||
uint8 _burningAdrenalineCast;
|
||||
};
|
||||
|
||||
// 18173 - Burning Adrenaline
|
||||
|
|
@ -308,9 +295,7 @@ class spell_vael_burning_adrenaline : public AuraScript
|
|||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (!GetTarget())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Do the explosion, then kill the target.
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_BURNING_ADRENALINE_EXPLOSION, true);
|
||||
|
|
@ -325,6 +310,6 @@ class spell_vael_burning_adrenaline : public AuraScript
|
|||
|
||||
void AddSC_boss_vaelastrasz()
|
||||
{
|
||||
new boss_vaelastrasz();
|
||||
RegisterBlackwingLairCreatureAI(boss_vaelastrasz);
|
||||
RegisterSpellScript(spell_vael_burning_adrenaline);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,404 +72,355 @@ Position const SummonPosition[8] =
|
|||
|
||||
uint32 const Entry[3] = { 12422, 12416, 12420 };
|
||||
|
||||
class instance_blackwing_lair : public InstanceMapScript
|
||||
struct instance_blackwing_lair : public InstanceScript
|
||||
{
|
||||
public:
|
||||
instance_blackwing_lair() : InstanceMapScript(BWLScriptName, MAP_BLACKWING_LAIR) { }
|
||||
|
||||
struct instance_blackwing_lair_InstanceMapScript : public InstanceScript
|
||||
instance_blackwing_lair(Map* map) : InstanceScript(map)
|
||||
{
|
||||
instance_blackwing_lair_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadDoorData(doorData);
|
||||
LoadObjectData(creatureData, objectData);
|
||||
}
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
// Razorgore
|
||||
EggCount = 0;
|
||||
EggEvent = 0;
|
||||
NefarianLeftTunnel = 0;
|
||||
NefarianRightTunnel = 0;
|
||||
addsCount.fill(0);
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
// This is required because the tempspawn at Vael overwrites his GUID.
|
||||
if (creature->GetEntry() == NPC_VICTOR_NEFARIUS && creature->ToTempSummon())
|
||||
return;
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadDoorData(doorData);
|
||||
LoadObjectData(creatureData, objectData);
|
||||
case NPC_RAZORGORE:
|
||||
razorgoreGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_BLACKWING_DRAGON:
|
||||
++addsCount[0];
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
if (CreatureAI* razorAI = razor->AI())
|
||||
razorAI->JustSummoned(creature);
|
||||
break;
|
||||
case NPC_BLACKWING_LEGIONAIRE:
|
||||
case NPC_BLACKWING_MAGE:
|
||||
++addsCount[1];
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
if (CreatureAI* razorAI = razor->AI())
|
||||
razorAI->JustSummoned(creature);
|
||||
break;
|
||||
case NPC_BLACKWING_GUARDSMAN:
|
||||
guardList.push_back(creature->GetGUID());
|
||||
break;
|
||||
case NPC_NEFARIAN:
|
||||
nefarianGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_BLACK_DRAKONID:
|
||||
case NPC_BLUE_DRAKONID:
|
||||
case NPC_BRONZE_DRAKONID:
|
||||
case NPC_CHROMATIC_DRAKONID:
|
||||
case NPC_GREEN_DRAKONID:
|
||||
case NPC_RED_DRAKONID:
|
||||
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
|
||||
if (CreatureAI* nefariusAI = nefarius->AI())
|
||||
nefariusAI->JustSummoned(creature);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
InstanceScript::OnGameObjectCreate(go);
|
||||
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_BLACK_DRAGON_EGG:
|
||||
if (GetBossState(DATA_FIREMAW) == DONE)
|
||||
go->SetPhaseMask(2, true);
|
||||
else
|
||||
EggList.push_back(go->GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectRemove(GameObject* go) override
|
||||
{
|
||||
InstanceScript::OnGameObjectRemove(go);
|
||||
|
||||
if (go->GetEntry() == GO_BLACK_DRAGON_EGG)
|
||||
EggList.remove(go->GetGUID());
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const override
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case DATA_NEFARIAN_LEFT_TUNNEL:
|
||||
return NefarianLeftTunnel;
|
||||
case DATA_NEFARIAN_RIGHT_TUNNEL:
|
||||
return NefarianRightTunnel;
|
||||
case DATA_EGG_EVENT:
|
||||
return EggEvent;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
void Initialize() override
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override
|
||||
{
|
||||
switch (bossId)
|
||||
{
|
||||
// Razorgore
|
||||
EggCount = 0;
|
||||
EggEvent = 0;
|
||||
NefarianLeftTunnel = 0;
|
||||
NefarianRightTunnel = 0;
|
||||
addsCount.fill(0);
|
||||
case DATA_BROODLORD_LASHLAYER:
|
||||
if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// This is required because the tempspawn at Vael overwrites his GUID.
|
||||
if (creature->GetEntry() == NPC_VICTOR_NEFARIUS && creature->ToTempSummon())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_RAZORGORE:
|
||||
razorgoreGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_BLACKWING_DRAGON:
|
||||
++addsCount[0];
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
case DATA_RAZORGORE_THE_UNTAMED:
|
||||
if (state == DONE)
|
||||
{
|
||||
for (ObjectGuid const& guid : EggList)
|
||||
{
|
||||
if (CreatureAI* razorAI = razor->AI())
|
||||
{
|
||||
razorAI->JustSummoned(creature);
|
||||
}
|
||||
// Eggs should be destroyed instead
|
||||
/// @todo: after dynamic spawns
|
||||
if (GameObject* egg = instance->GetGameObject(guid))
|
||||
egg->SetPhaseMask(2, true);
|
||||
}
|
||||
break;
|
||||
case NPC_BLACKWING_LEGIONAIRE:
|
||||
case NPC_BLACKWING_MAGE:
|
||||
++addsCount[1];
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
{
|
||||
if (CreatureAI* razorAI = razor->AI())
|
||||
{
|
||||
razorAI->JustSummoned(creature);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_BLACKWING_GUARDSMAN:
|
||||
guardList.push_back(creature->GetGUID());
|
||||
break;
|
||||
case NPC_NEFARIAN:
|
||||
nefarianGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_BLACK_DRAKONID:
|
||||
case NPC_BLUE_DRAKONID:
|
||||
case NPC_BRONZE_DRAKONID:
|
||||
case NPC_CHROMATIC_DRAKONID:
|
||||
case NPC_GREEN_DRAKONID:
|
||||
case NPC_RED_DRAKONID:
|
||||
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
|
||||
{
|
||||
if (CreatureAI* nefariusAI = nefarius->AI())
|
||||
{
|
||||
nefariusAI->JustSummoned(creature);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATA_NEFARIAN:
|
||||
switch (state)
|
||||
{
|
||||
case FAIL:
|
||||
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15min);
|
||||
[[fallthrough]];
|
||||
case NOT_STARTED:
|
||||
if (Creature* nefarian = instance->GetCreature(nefarianGUID))
|
||||
nefarian->DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
InstanceScript::OnGameObjectCreate(go);
|
||||
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_BLACK_DRAGON_EGG:
|
||||
if (GetBossState(DATA_FIREMAW) == DONE)
|
||||
{
|
||||
go->SetPhaseMask(2, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EggList.push_back(go->GetGUID());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectRemove(GameObject* go) override
|
||||
{
|
||||
InstanceScript::OnGameObjectRemove(go);
|
||||
|
||||
if (go->GetEntry() == GO_BLACK_DRAGON_EGG)
|
||||
EggList.remove(go->GetGUID());
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const override
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == DATA_EGG_EVENT)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case DATA_NEFARIAN_LEFT_TUNNEL:
|
||||
return NefarianLeftTunnel;
|
||||
case DATA_NEFARIAN_RIGHT_TUNNEL:
|
||||
return NefarianRightTunnel;
|
||||
case DATA_EGG_EVENT:
|
||||
return EggEvent;
|
||||
default:
|
||||
case DONE:
|
||||
EggEvent = data;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override
|
||||
{
|
||||
switch (bossId)
|
||||
{
|
||||
case DATA_BROODLORD_LASHLAYER:
|
||||
if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE)
|
||||
return false;
|
||||
case FAIL:
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
break;
|
||||
default:
|
||||
case IN_PROGRESS:
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45s);
|
||||
EggEvent = data;
|
||||
EggCount = 0;
|
||||
addsCount.fill(0);
|
||||
break;
|
||||
}
|
||||
case NOT_STARTED:
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
EggEvent = data;
|
||||
EggCount = 0;
|
||||
addsCount.fill(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
for (ObjectGuid const& guid : EggList)
|
||||
DoRespawnGameObject(guid, 0);
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
DoRespawnCreature(DATA_GRETHOK);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_RAZORGORE_THE_UNTAMED:
|
||||
if (state == DONE)
|
||||
for (ObjectGuid const& guid : guardList)
|
||||
DoRespawnCreature(guid);
|
||||
|
||||
break;
|
||||
case SPECIAL:
|
||||
if (EggEvent == NOT_STARTED)
|
||||
SetData(DATA_EGG_EVENT, IN_PROGRESS);
|
||||
if (++EggCount >= EggList.size())
|
||||
{
|
||||
for (ObjectGuid const& guid : EggList)
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
{
|
||||
// Eggs should be destroyed instead
|
||||
/// @todo: after dynamic spawns
|
||||
if (GameObject* egg = instance->GetGameObject(guid))
|
||||
{
|
||||
egg->SetPhaseMask(2, true);
|
||||
}
|
||||
SetData(DATA_EGG_EVENT, DONE);
|
||||
razor->RemoveAurasDueToSpell(19832); // MindControl
|
||||
DoRemoveAurasDueToSpellOnPlayers(19832);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATA_NEFARIAN:
|
||||
switch (state)
|
||||
{
|
||||
case FAIL:
|
||||
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15min);
|
||||
[[fallthrough]];
|
||||
case NOT_STARTED:
|
||||
if (Creature* nefarian = instance->GetCreature(nefarianGUID))
|
||||
{
|
||||
nefarian->DespawnOrUnsummon();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == DATA_EGG_EVENT)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case DONE:
|
||||
EggEvent = data;
|
||||
break;
|
||||
case FAIL:
|
||||
_events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, 1s);
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45s);
|
||||
EggEvent = data;
|
||||
EggCount = 0;
|
||||
addsCount.fill(0);
|
||||
break;
|
||||
case NOT_STARTED:
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
EggEvent = data;
|
||||
EggCount = 0;
|
||||
addsCount.fill(0);
|
||||
|
||||
for (ObjectGuid const& guid : EggList)
|
||||
{
|
||||
DoRespawnGameObject(guid, 0);
|
||||
}
|
||||
|
||||
DoRespawnCreature(DATA_GRETHOK);
|
||||
|
||||
for (ObjectGuid const& guid : guardList)
|
||||
{
|
||||
DoRespawnCreature(guid);
|
||||
}
|
||||
|
||||
break;
|
||||
case SPECIAL:
|
||||
if (EggEvent == NOT_STARTED)
|
||||
SetData(DATA_EGG_EVENT, IN_PROGRESS);
|
||||
if (++EggCount >= EggList.size())
|
||||
{
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
{
|
||||
SetData(DATA_EGG_EVENT, DONE);
|
||||
razor->RemoveAurasDueToSpell(19832); // MindControl
|
||||
DoRemoveAurasDueToSpellOnPlayers(19832);
|
||||
}
|
||||
_events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, 1s);
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == DATA_NEFARIAN_LEFT_TUNNEL)
|
||||
{
|
||||
NefarianLeftTunnel = data;
|
||||
}
|
||||
|
||||
if (type == DATA_NEFARIAN_RIGHT_TUNNEL)
|
||||
{
|
||||
NefarianRightTunnel = data;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_RAZORGORE_THE_UNTAMED:
|
||||
return razorgoreGUID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
void OnUnitDeath(Unit* unit) override
|
||||
{
|
||||
switch (unit->GetEntry())
|
||||
{
|
||||
case NPC_BLACKWING_DRAGON:
|
||||
--addsCount[0];
|
||||
if (EggEvent != DONE && !_events.HasTimeUntilEvent(EVENT_RAZOR_SPAWN))
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 1s);
|
||||
}
|
||||
break;
|
||||
case NPC_BLACKWING_LEGIONAIRE:
|
||||
case NPC_BLACKWING_MAGE:
|
||||
--addsCount[1];
|
||||
if (EggEvent != DONE && !_events.HasTimeUntilEvent(EVENT_RAZOR_SPAWN))
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 1s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(uint32 diff) override
|
||||
if (type == DATA_NEFARIAN_LEFT_TUNNEL)
|
||||
NefarianLeftTunnel = data;
|
||||
|
||||
if (type == DATA_NEFARIAN_RIGHT_TUNNEL)
|
||||
NefarianRightTunnel = data;
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
if (_events.Empty())
|
||||
return;
|
||||
case DATA_RAZORGORE_THE_UNTAMED:
|
||||
return razorgoreGUID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_events.Update(diff);
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
void OnUnitDeath(Unit* unit) override
|
||||
{
|
||||
switch (unit->GetEntry())
|
||||
{
|
||||
case NPC_BLACKWING_DRAGON:
|
||||
--addsCount[0];
|
||||
if (EggEvent != DONE && !_events.HasTimeUntilEvent(EVENT_RAZOR_SPAWN))
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 1s);
|
||||
break;
|
||||
case NPC_BLACKWING_LEGIONAIRE:
|
||||
case NPC_BLACKWING_MAGE:
|
||||
--addsCount[1];
|
||||
if (EggEvent != DONE && !_events.HasTimeUntilEvent(EVENT_RAZOR_SPAWN))
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 1s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(uint32 diff) override
|
||||
{
|
||||
if (_events.Empty())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RAZOR_SPAWN:
|
||||
if (EggEvent == IN_PROGRESS)
|
||||
case EVENT_RAZOR_SPAWN:
|
||||
if (EggEvent == IN_PROGRESS)
|
||||
{
|
||||
bool spawnMoreAdds = true;
|
||||
for (uint8 i = urand(2, 5); i > 0; --i)
|
||||
{
|
||||
bool spawnMoreAdds = true;
|
||||
for (uint8 i = urand(2, 5); i > 0; --i)
|
||||
{
|
||||
uint32 mobEntry = Entry[urand(0, 2)];
|
||||
uint32 dragonkinsCount = addsCount[0];
|
||||
uint32 orcsCount = addsCount[1];
|
||||
uint32 mobEntry = Entry[urand(0, 2)];
|
||||
uint32 dragonkinsCount = addsCount[0];
|
||||
uint32 orcsCount = addsCount[1];
|
||||
|
||||
// If more than 12 dragonkins...
|
||||
if (dragonkinsCount >= 12)
|
||||
// If more than 12 dragonkins...
|
||||
if (dragonkinsCount >= 12)
|
||||
{
|
||||
//... and more than 40 orcs - stop spawning more adds.
|
||||
if (orcsCount >= 40)
|
||||
{
|
||||
//... and more than 40 orcs - stop spawning more adds.
|
||||
if (orcsCount >= 40)
|
||||
{
|
||||
spawnMoreAdds = false;
|
||||
break;
|
||||
}
|
||||
//... - stop spawning them.
|
||||
else if (mobEntry == NPC_BLACKWING_DRAGON)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
spawnMoreAdds = false;
|
||||
break;
|
||||
}
|
||||
// If more than 40 orcs - stop spawning them.
|
||||
else if (orcsCount >= 40 && mobEntry != NPC_BLACKWING_DRAGON)
|
||||
//... - stop spawning them.
|
||||
else if (mobEntry == NPC_BLACKWING_DRAGON)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Creature* summon = instance->SummonCreature(mobEntry, SummonPosition[urand(0, 7)]))
|
||||
{
|
||||
summon->AI()->DoZoneInCombat();
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnMoreAdds)
|
||||
// If more than 40 orcs - stop spawning them.
|
||||
else if (orcsCount >= 40 && mobEntry != NPC_BLACKWING_DRAGON)
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 15s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Creature* summon = instance->SummonCreature(mobEntry, SummonPosition[urand(0, 7)]))
|
||||
summon->AI()->DoZoneInCombat();
|
||||
}
|
||||
break;
|
||||
case EVENT_RAZOR_PHASE_TWO:
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
razor->AI()->DoAction(ACTION_PHASE_TWO);
|
||||
break;
|
||||
case EVENT_RESPAWN_NEFARIUS:
|
||||
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
|
||||
{
|
||||
nefarius->SetPhaseMask(1, true);
|
||||
nefarius->setActive(true);
|
||||
nefarius->Respawn();
|
||||
nefarius->GetMotionMaster()->MoveTargetedHome();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (spawnMoreAdds)
|
||||
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 15s);
|
||||
}
|
||||
break;
|
||||
case EVENT_RAZOR_PHASE_TWO:
|
||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||
razor->AI()->DoAction(ACTION_PHASE_TWO);
|
||||
break;
|
||||
case EVENT_RESPAWN_NEFARIUS:
|
||||
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
|
||||
{
|
||||
nefarius->SetPhaseMask(1, true);
|
||||
nefarius->setActive(true);
|
||||
nefarius->Respawn();
|
||||
nefarius->GetMotionMaster()->MoveTargetedHome();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
data >> NefarianLeftTunnel;
|
||||
data >> NefarianRightTunnel;
|
||||
}
|
||||
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
{
|
||||
data << NefarianLeftTunnel << ' ' << NefarianRightTunnel;
|
||||
}
|
||||
|
||||
protected:
|
||||
ObjectGuid razorgoreGUID;
|
||||
ObjectGuid nefarianGUID;
|
||||
ObjectGuid nefarianDoorGUID;
|
||||
|
||||
// Razorgore
|
||||
uint8 EggCount;
|
||||
uint32 EggEvent;
|
||||
GuidList EggList;
|
||||
GuidList guardList;
|
||||
std::array<uint32, 2> addsCount;
|
||||
|
||||
// Nefarian
|
||||
uint32 NefarianLeftTunnel;
|
||||
uint32 NefarianRightTunnel;
|
||||
|
||||
// Misc
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_blackwing_lair_InstanceMapScript(map);
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
data >> NefarianLeftTunnel;
|
||||
data >> NefarianRightTunnel;
|
||||
}
|
||||
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
{
|
||||
data << NefarianLeftTunnel << ' ' << NefarianRightTunnel;
|
||||
}
|
||||
|
||||
protected:
|
||||
ObjectGuid razorgoreGUID;
|
||||
ObjectGuid nefarianGUID;
|
||||
ObjectGuid nefarianDoorGUID;
|
||||
|
||||
// Razorgore
|
||||
uint8 EggCount;
|
||||
uint32 EggEvent;
|
||||
GuidList EggList;
|
||||
GuidList guardList;
|
||||
std::array<uint32, 2> addsCount;
|
||||
|
||||
// Nefarian
|
||||
uint32 NefarianLeftTunnel;
|
||||
uint32 NefarianRightTunnel;
|
||||
|
||||
// Misc
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
enum ShadowFlame
|
||||
|
|
@ -527,7 +478,7 @@ public:
|
|||
|
||||
void AddSC_instance_blackwing_lair()
|
||||
{
|
||||
new instance_blackwing_lair();
|
||||
RegisterInstanceScript(instance_blackwing_lair, MAP_BLACKWING_LAIR);
|
||||
RegisterSpellScript(spell_bwl_shadowflame);
|
||||
new at_orb_of_command();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,88 +43,73 @@ enum Events
|
|||
EVENT_LIVING_BOMB,
|
||||
};
|
||||
|
||||
class boss_baron_geddon : public CreatureScript
|
||||
struct boss_baron_geddon : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_baron_geddon() : CreatureScript("boss_baron_geddon") { }
|
||||
|
||||
struct boss_baron_geddonAI : public BossAI
|
||||
boss_baron_geddon(Creature* creature) : BossAI(creature, DATA_GEDDON),
|
||||
armageddonCasted(false)
|
||||
{
|
||||
boss_baron_geddonAI(Creature* creature) : BossAI(creature, DATA_GEDDON),
|
||||
armageddonCasted(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
armageddonCasted = false;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_INFERNO, 13s, 15s);
|
||||
events.ScheduleEvent(EVENT_IGNITE_MANA, 7s, 19s);
|
||||
events.ScheduleEvent(EVENT_LIVING_BOMB, 11s, 16s);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
// If boss is below 2% hp - cast Armageddon
|
||||
if (!armageddonCasted && damage < me->GetHealth() && me->HealthBelowPctDamaged(2, damage))
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_INFERNO);
|
||||
me->StopMoving();
|
||||
if (me->CastSpell(me, SPELL_ARMAGEDDON, TRIGGERED_FULL_MASK) == SPELL_CAST_OK)
|
||||
{
|
||||
Talk(EMOTE_SERVICE);
|
||||
armageddonCasted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_INFERNO:
|
||||
{
|
||||
DoCastAOE(SPELL_INFERNO);
|
||||
events.Repeat(21s, 26s);
|
||||
break;
|
||||
}
|
||||
case EVENT_IGNITE_MANA:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_IGNITE_MANA))
|
||||
{
|
||||
DoCast(target, SPELL_IGNITE_MANA);
|
||||
}
|
||||
|
||||
events.Repeat(27s, 32s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LIVING_BOMB:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_LIVING_BOMB);
|
||||
}
|
||||
|
||||
events.Repeat(11s, 16s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool armageddonCasted;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_baron_geddonAI>(creature);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
armageddonCasted = false;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_INFERNO, 13s, 15s);
|
||||
events.ScheduleEvent(EVENT_IGNITE_MANA, 7s, 19s);
|
||||
events.ScheduleEvent(EVENT_LIVING_BOMB, 11s, 16s);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
// If boss is below 2% hp - cast Armageddon
|
||||
if (!armageddonCasted && damage < me->GetHealth() && me->HealthBelowPctDamaged(2, damage))
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_INFERNO);
|
||||
me->StopMoving();
|
||||
if (me->CastSpell(me, SPELL_ARMAGEDDON, TRIGGERED_FULL_MASK) == SPELL_CAST_OK)
|
||||
{
|
||||
Talk(EMOTE_SERVICE);
|
||||
armageddonCasted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_INFERNO:
|
||||
{
|
||||
DoCastAOE(SPELL_INFERNO);
|
||||
events.Repeat(21s, 26s);
|
||||
break;
|
||||
}
|
||||
case EVENT_IGNITE_MANA:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_IGNITE_MANA))
|
||||
DoCast(target, SPELL_IGNITE_MANA);
|
||||
|
||||
events.Repeat(27s, 32s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LIVING_BOMB:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
DoCast(target, SPELL_LIVING_BOMB);
|
||||
|
||||
events.Repeat(11s, 16s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool armageddonCasted;
|
||||
};
|
||||
|
||||
// 19695 Inferno
|
||||
|
|
@ -149,9 +134,7 @@ class spell_geddon_inferno_aura : public AuraScript
|
|||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Creature* pCreatureTarget = GetTarget()->ToCreature())
|
||||
{
|
||||
pCreatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void PeriodicTick(AuraEffect const* aurEff)
|
||||
|
|
@ -209,9 +192,7 @@ class spell_geddon_armageddon_aura : public AuraScript
|
|||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Creature* pCreatureTarget = GetTarget()->ToCreature())
|
||||
{
|
||||
pCreatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -223,7 +204,7 @@ class spell_geddon_armageddon_aura : public AuraScript
|
|||
|
||||
void AddSC_boss_baron_geddon()
|
||||
{
|
||||
new boss_baron_geddon();
|
||||
RegisterMoltenCoreCreatureAI(boss_baron_geddon);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_geddon_inferno_aura);
|
||||
|
|
|
|||
|
|
@ -51,123 +51,93 @@ enum Events
|
|||
EVENT_MAGMA_SHACKLES,
|
||||
};
|
||||
|
||||
class boss_garr : public CreatureScript
|
||||
struct boss_garr : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_garr() : CreatureScript("boss_garr") {}
|
||||
|
||||
struct boss_garrAI : public BossAI
|
||||
boss_garr(Creature* creature) : BossAI(creature, DATA_GARR),
|
||||
massEruptionTimer(600000) // 10 mins
|
||||
{
|
||||
boss_garrAI(Creature* creature) : BossAI(creature, DATA_GARR),
|
||||
massEruptionTimer(600000) // 10 mins
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
massEruptionTimer = 600000;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
DoCastSelf(SPELL_SEPARATION_ANXIETY, true);
|
||||
events.ScheduleEvent(EVENT_ANTIMAGIC_PULSE, 15s);
|
||||
events.ScheduleEvent(EVENT_MAGMA_SHACKLES, 10s);
|
||||
massEruptionTimer = 600000; // 10 mins
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// This should always process
|
||||
if (massEruptionTimer <= diff)
|
||||
{
|
||||
Talk(EMOTE_MASS_ERRUPTION, me);
|
||||
DoCastAOE(SPELL_ERUPTION_TRIGGER, true);
|
||||
massEruptionTimer = 20000;
|
||||
}
|
||||
else
|
||||
{
|
||||
massEruptionTimer -= diff;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
_Reset();
|
||||
massEruptionTimer = 600000;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
DoCastSelf(SPELL_SEPARATION_ANXIETY, true);
|
||||
events.ScheduleEvent(EVENT_ANTIMAGIC_PULSE, 15s);
|
||||
events.ScheduleEvent(EVENT_MAGMA_SHACKLES, 10s);
|
||||
massEruptionTimer = 600000; // 10 mins
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
case EVENT_ANTIMAGIC_PULSE:
|
||||
{
|
||||
DoCastSelf(SPELL_ANTIMAGIC_PULSE);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_SHACKLES:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGMA_SHACKLES);
|
||||
events.Repeat(15s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This should always process
|
||||
if (massEruptionTimer <= diff)
|
||||
{
|
||||
Talk(EMOTE_MASS_ERRUPTION, me);
|
||||
DoCastAOE(SPELL_ERUPTION_TRIGGER, true);
|
||||
massEruptionTimer = 20000;
|
||||
}
|
||||
else
|
||||
{
|
||||
massEruptionTimer -= diff;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_ANTIMAGIC_PULSE:
|
||||
{
|
||||
DoCastSelf(SPELL_ANTIMAGIC_PULSE);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_SHACKLES:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGMA_SHACKLES);
|
||||
events.Repeat(15s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 massEruptionTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_garrAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 massEruptionTimer;
|
||||
};
|
||||
|
||||
class npc_garr_firesworn : public CreatureScript
|
||||
struct npc_garr_firesworn : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_garr_firesworn() : CreatureScript("npc_garr_firesworn") {}
|
||||
npc_garr_firesworn(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
struct npc_garr_fireswornAI : public ScriptedAI
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) override
|
||||
{
|
||||
npc_garr_fireswornAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) override
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
// Prevent double damage because Firesworn can kill himself with Massive Erruption
|
||||
if (me != attacker)
|
||||
{
|
||||
DoCastSelf(SPELL_ERUPTION, true);
|
||||
}
|
||||
// Prevent double damage because Firesworn can kill himself with Massive Eruption
|
||||
if (me != attacker)
|
||||
DoCastSelf(SPELL_ERUPTION, true);
|
||||
|
||||
DoCastAOE(SPELL_ENRAGE_TRIGGER);
|
||||
}
|
||||
DoCastAOE(SPELL_ENRAGE_TRIGGER);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_garr_fireswornAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -210,9 +180,7 @@ class spell_garr_frenzy : public SpellScript
|
|||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
target->CastSpell(target, SPELL_FRENZY);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -223,8 +191,8 @@ class spell_garr_frenzy : public SpellScript
|
|||
|
||||
void AddSC_boss_garr()
|
||||
{
|
||||
new boss_garr();
|
||||
new npc_garr_firesworn();
|
||||
RegisterMoltenCoreCreatureAI(boss_garr);
|
||||
RegisterMoltenCoreCreatureAI(npc_garr_firesworn);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_garr_separation_anxiety_aura);
|
||||
|
|
|
|||
|
|
@ -34,74 +34,57 @@ enum Events
|
|||
EVENT_SHADOW_BOLT,
|
||||
};
|
||||
|
||||
class boss_gehennas : public CreatureScript
|
||||
struct boss_gehennas : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_gehennas() : CreatureScript("boss_gehennas") { }
|
||||
boss_gehennas(Creature* creature) : BossAI(creature, DATA_GEHENNAS) {}
|
||||
|
||||
struct boss_gehennasAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
boss_gehennasAI(Creature* creature) : BossAI(creature, DATA_GEHENNAS) {}
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_GEHENNAS_CURSE, 6s, 9s);
|
||||
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 10s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 3s, 5s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_GEHENNAS_CURSE, 6s, 9s);
|
||||
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 10s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, 3s, 5s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_GEHENNAS_CURSE:
|
||||
{
|
||||
case EVENT_GEHENNAS_CURSE:
|
||||
DoCastVictim(SPELL_GEHENNAS_CURSE);
|
||||
events.Repeat(25s, 30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAIN_OF_FIRE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
DoCast(target, SPELL_RAIN_OF_FIRE, true);
|
||||
events.Repeat(6s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_BOLT:
|
||||
{
|
||||
if (urand(0, 1))
|
||||
{
|
||||
DoCastVictim(SPELL_GEHENNAS_CURSE);
|
||||
events.Repeat(25s, 30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAIN_OF_FIRE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_RAIN_OF_FIRE, true);
|
||||
}
|
||||
events.Repeat(6s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_BOLT:
|
||||
{
|
||||
if (urand(0, 1))
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false))
|
||||
{
|
||||
DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
||||
}
|
||||
}
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false))
|
||||
DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
||||
}
|
||||
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
||||
}
|
||||
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_gehennasAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_gehennas()
|
||||
{
|
||||
new boss_gehennas();
|
||||
RegisterMoltenCoreCreatureAI(boss_gehennas);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,191 +40,157 @@ enum Spells
|
|||
SPELL_FULL_HEAL = 17683,
|
||||
};
|
||||
|
||||
class boss_golemagg : public CreatureScript
|
||||
struct boss_golemagg : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_golemagg() : CreatureScript("boss_golemagg") { }
|
||||
boss_golemagg(Creature* creature) : BossAI(creature, DATA_GOLEMAGG),
|
||||
earthquakeTimer(0),
|
||||
pyroblastTimer(0),
|
||||
enraged(false)
|
||||
{}
|
||||
|
||||
struct boss_golemaggAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_golemaggAI(Creature* creature) : BossAI(creature, DATA_GOLEMAGG),
|
||||
earthquakeTimer(0),
|
||||
pyroblastTimer(0),
|
||||
enraged(false)
|
||||
{}
|
||||
_Reset();
|
||||
earthquakeTimer = 0;
|
||||
pyroblastTimer = urand(3000, 7000);
|
||||
enraged = false;
|
||||
DoCastSelf(SPELL_MAGMASPLASH);
|
||||
DoCastSelf(SPELL_GOLEMAGG_TRUST_AURA);
|
||||
DoCastSelf(SPELL_DOUBLE_ATTACK);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!enraged && me->HealthBelowPctDamaged(10, damage))
|
||||
{
|
||||
_Reset();
|
||||
earthquakeTimer = 0;
|
||||
pyroblastTimer = urand(3000, 7000);
|
||||
enraged = false;
|
||||
DoCastSelf(SPELL_MAGMASPLASH);
|
||||
DoCastSelf(SPELL_GOLEMAGG_TRUST_AURA);
|
||||
DoCastSelf(SPELL_DOUBLE_ATTACK);
|
||||
DoCastSelf(SPELL_ATTRACK_RAGER, true);
|
||||
DoCastAOE(SPELL_EARTHQUAKE, true);
|
||||
earthquakeTimer = 5000;
|
||||
enraged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// Should not get impact by cast state (cast should always happen)
|
||||
if (earthquakeTimer)
|
||||
{
|
||||
if (!enraged && me->HealthBelowPctDamaged(10, damage))
|
||||
if (earthquakeTimer <= diff)
|
||||
{
|
||||
DoCastSelf(SPELL_ATTRACK_RAGER, true);
|
||||
DoCastAOE(SPELL_EARTHQUAKE, true);
|
||||
DoCastSelf(SPELL_EARTHQUAKE, true);
|
||||
earthquakeTimer = 5000;
|
||||
enraged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Should not get impact by cast state (cast should always happen)
|
||||
if (earthquakeTimer)
|
||||
{
|
||||
if (earthquakeTimer <= diff)
|
||||
{
|
||||
DoCastSelf(SPELL_EARTHQUAKE, true);
|
||||
earthquakeTimer = 5000;
|
||||
}
|
||||
else
|
||||
{
|
||||
earthquakeTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pyroblastTimer <= diff)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_PYROBLAST);
|
||||
|
||||
pyroblastTimer = 7000;
|
||||
}
|
||||
else
|
||||
{
|
||||
pyroblastTimer -= diff;
|
||||
earthquakeTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 earthquakeTimer;
|
||||
uint32 pyroblastTimer;
|
||||
bool enraged;
|
||||
};
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_golemaggAI>(creature);
|
||||
if (pyroblastTimer <= diff)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_PYROBLAST);
|
||||
|
||||
pyroblastTimer = 7000;
|
||||
}
|
||||
else
|
||||
{
|
||||
pyroblastTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 earthquakeTimer;
|
||||
uint32 pyroblastTimer;
|
||||
bool enraged;
|
||||
};
|
||||
|
||||
class npc_core_rager : public CreatureScript
|
||||
struct npc_core_rager : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_core_rager() : CreatureScript("npc_core_rager") { }
|
||||
|
||||
struct npc_core_ragerAI : public ScriptedAI
|
||||
npc_core_rager(Creature* creature) : ScriptedAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
mangleTimer(7000),
|
||||
rangeCheckTimer(1000)
|
||||
{
|
||||
npc_core_ragerAI(Creature* creature) : ScriptedAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
mangleTimer(7000),
|
||||
rangeCheckTimer(1000)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
mangleTimer = 7000; // These times are probably wrong
|
||||
rangeCheckTimer = 1000;
|
||||
|
||||
if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
|
||||
{
|
||||
DoCastSelf(SPELL_CORE_RAGER_QUIET_SUICIDE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
// Just in case if something will go bad, let players to kill this creature
|
||||
if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HealthBelowPctDamaged(50, damage))
|
||||
{
|
||||
damage = 0;
|
||||
DoCastSelf(SPELL_FULL_HEAL, true);
|
||||
Talk(EMOTE_LOWHP);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Should have no impact from unit state
|
||||
if (rangeCheckTimer <= diff)
|
||||
{
|
||||
Creature const* golemagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GOLEMAGG));
|
||||
if (golemagg && me->GetDistance(golemagg) > 100.0f)
|
||||
{
|
||||
instance->DoAction(ACTION_RESET_GOLEMAGG_ENCOUNTER);
|
||||
return;
|
||||
}
|
||||
|
||||
rangeCheckTimer = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeCheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Mangle
|
||||
if (mangleTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_MANGLE);
|
||||
mangleTimer = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
mangleTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 mangleTimer;
|
||||
uint32 rangeCheckTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_core_ragerAI>(creature);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
mangleTimer = 7000; // These times are probably wrong
|
||||
rangeCheckTimer = 1000;
|
||||
|
||||
if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
|
||||
DoCastSelf(SPELL_CORE_RAGER_QUIET_SUICIDE, true);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
// Just in case if something will go bad, let players to kill this creature
|
||||
if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
|
||||
return;
|
||||
|
||||
if (me->HealthBelowPctDamaged(50, damage))
|
||||
{
|
||||
damage = 0;
|
||||
DoCastSelf(SPELL_FULL_HEAL, true);
|
||||
Talk(EMOTE_LOWHP);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// Should have no impact from unit state
|
||||
if (rangeCheckTimer <= diff)
|
||||
{
|
||||
Creature const* golemagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GOLEMAGG));
|
||||
if (golemagg && me->GetDistance(golemagg) > 100.0f)
|
||||
{
|
||||
instance->DoAction(ACTION_RESET_GOLEMAGG_ENCOUNTER);
|
||||
return;
|
||||
}
|
||||
|
||||
rangeCheckTimer = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeCheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
// Mangle
|
||||
if (mangleTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_MANGLE);
|
||||
mangleTimer = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
mangleTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 mangleTimer;
|
||||
uint32 rangeCheckTimer;
|
||||
};
|
||||
|
||||
void AddSC_boss_golemagg()
|
||||
{
|
||||
new boss_golemagg();
|
||||
new npc_core_rager();
|
||||
RegisterMoltenCoreCreatureAI(boss_golemagg);
|
||||
RegisterMoltenCoreCreatureAI(npc_core_rager);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,56 +33,45 @@ enum Events
|
|||
EVENT_SHADOW_SHOCK = 3,
|
||||
};
|
||||
|
||||
class boss_lucifron : public CreatureScript
|
||||
struct boss_lucifron : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_lucifron() : CreatureScript("boss_lucifron") { }
|
||||
boss_lucifron(Creature* creature) : BossAI(creature, DATA_LUCIFRON) {}
|
||||
|
||||
struct boss_lucifronAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_lucifronAI(Creature* creature) : BossAI(creature, DATA_LUCIFRON) {}
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_IMPENDING_DOOM, 6s, 11s);
|
||||
events.ScheduleEvent(EVENT_LUCIFRON_CURSE, 11s, 14s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_SHOCK, 5s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_IMPENDING_DOOM, 6s, 11s);
|
||||
events.ScheduleEvent(EVENT_LUCIFRON_CURSE, 11s, 14s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_SHOCK, 5s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_IMPENDING_DOOM:
|
||||
{
|
||||
case EVENT_IMPENDING_DOOM:
|
||||
{
|
||||
DoCastVictim(SPELL_IMPENDING_DOOM);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LUCIFRON_CURSE:
|
||||
{
|
||||
DoCastVictim(SPELL_LUCIFRON_CURSE);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_SHOCK:
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_SHOCK);
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
}
|
||||
DoCastVictim(SPELL_IMPENDING_DOOM);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LUCIFRON_CURSE:
|
||||
{
|
||||
DoCastVictim(SPELL_LUCIFRON_CURSE);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_SHOCK:
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_SHOCK);
|
||||
events.Repeat(5s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_lucifronAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_lucifron()
|
||||
{
|
||||
new boss_lucifron();
|
||||
RegisterMoltenCoreCreatureAI(boss_lucifron);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,73 +47,58 @@ enum Events
|
|||
|
||||
constexpr float MELEE_TARGET_LOOKUP_DIST = 10.0f;
|
||||
|
||||
class boss_magmadar : public CreatureScript
|
||||
struct boss_magmadar : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_magmadar() : CreatureScript("boss_magmadar") {}
|
||||
boss_magmadar(Creature* creature) : BossAI(creature, DATA_MAGMADAR) {}
|
||||
|
||||
struct boss_magmadarAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_magmadarAI(Creature* creature) : BossAI(creature, DATA_MAGMADAR) {}
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FRENZY, 8500ms);
|
||||
events.ScheduleEvent(EVENT_PANIC, 9500ms);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB, 12s);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB_RANGED, 15s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_FRENZY, 8500ms);
|
||||
events.ScheduleEvent(EVENT_PANIC, 9500ms);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB, 12s);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB_RANGED, 15s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_FRENZY:
|
||||
{
|
||||
case EVENT_FRENZY:
|
||||
{
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
events.Repeat(15s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_PANIC:
|
||||
{
|
||||
DoCastVictim(SPELL_PANIC);
|
||||
events.Repeat(31s, 38s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BOMB:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, MELEE_TARGET_LOOKUP_DIST, true))
|
||||
{
|
||||
DoCast(target, SPELL_LAVA_BOMB);
|
||||
}
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
events.Repeat(15s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_PANIC:
|
||||
{
|
||||
DoCastVictim(SPELL_PANIC);
|
||||
events.Repeat(31s, 38s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BOMB:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, MELEE_TARGET_LOOKUP_DIST, true))
|
||||
DoCast(target, SPELL_LAVA_BOMB);
|
||||
|
||||
events.Repeat(12s, 15s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BOMB_RANGED:
|
||||
events.Repeat(12s, 15s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BOMB_RANGED:
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, 1, SelectTargetMethod::Random, 1, [this](Unit* target)
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, 1, SelectTargetMethod::Random, 1, [this](Unit* target)
|
||||
{
|
||||
return target && target->IsPlayer() && target->GetDistance(me) > MELEE_TARGET_LOOKUP_DIST && target->GetDistance(me) < 100.0f;
|
||||
});
|
||||
return target && target->IsPlayer() && target->GetDistance(me) > MELEE_TARGET_LOOKUP_DIST && target->GetDistance(me) < 100.0f;
|
||||
});
|
||||
|
||||
if (!targets.empty())
|
||||
{
|
||||
DoCast(targets.front() , SPELL_LAVA_BOMB_RANGED);
|
||||
}
|
||||
events.Repeat(12s, 15s);
|
||||
break;
|
||||
}
|
||||
if (!targets.empty())
|
||||
DoCast(targets.front() , SPELL_LAVA_BOMB_RANGED);
|
||||
events.Repeat(12s, 15s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_magmadarAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -162,7 +147,7 @@ class spell_magmadar_lava_bomb : public SpellScript
|
|||
|
||||
void AddSC_boss_magmadar()
|
||||
{
|
||||
new boss_magmadar();
|
||||
RegisterMoltenCoreCreatureAI(boss_magmadar);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_magmadar_lava_bomb);
|
||||
|
|
|
|||
|
|
@ -131,412 +131,389 @@ struct MajordomoAddData
|
|||
MajordomoAddData(ObjectGuid _guid, uint32 _creatureEntry, Position _spawnPos) : guid(_guid), creatureEntry(_creatureEntry), spawnPos(_spawnPos) { }
|
||||
};
|
||||
|
||||
class boss_majordomo : public CreatureScript
|
||||
struct boss_majordomo : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_majordomo() : CreatureScript("boss_majordomo") {}
|
||||
boss_majordomo(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_EXECUTUS) {}
|
||||
|
||||
struct boss_majordomoAI : public BossAI
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
boss_majordomoAI(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_EXECUTUS) {}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
me->DespawnOrUnsummon(10s, 0s);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_RAGNAROS)
|
||||
{
|
||||
summon->CastSpell(summon, SPELL_RAGNAROS_FADE);
|
||||
summon->CastSpell(summon, SPELL_RAGNAROS_SUBMERGE_EFFECT, true);
|
||||
summon->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
summon->SetImmuneToAll(true);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
|
||||
std::list<TempSummon*> p_summons;
|
||||
me->SummonCreatureGroup(SUMMON_GROUP_ADDS, &p_summons);
|
||||
if (!p_summons.empty())
|
||||
{
|
||||
for (TempSummon const* summon : p_summons)
|
||||
{
|
||||
if (summon)
|
||||
{
|
||||
static_minionsGUIDS.insert(summon->GetGUID());
|
||||
majordomoSummonsData[summon->GetGUID().GetCounter()] = MajordomoAddData(summon->GetGUID(), summon->GetEntry(), summon->GetPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
events.SetPhase(PHASE_NONE);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->ResetLootMode();
|
||||
events.Reset();
|
||||
aliveMinionsGUIDS.clear();
|
||||
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, NOT_STARTED);
|
||||
|
||||
for (auto const& summon : majordomoSummonsData)
|
||||
{
|
||||
if (ObjectAccessor::GetCreature(*me, summon.second.guid))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Creature* spawn = me->SummonCreature(summon.second.creatureEntry, summon.second.spawnPos))
|
||||
{
|
||||
static_minionsGUIDS.erase(summon.second.guid); // Erase the guid from the previous, no longer existing, spawn.
|
||||
static_minionsGUIDS.insert(spawn->GetGUID());
|
||||
majordomoSummonsData.erase(summon.second.guid.GetCounter());
|
||||
majordomoSummonsData[spawn->GetGUID().GetCounter()] = MajordomoAddData(spawn->GetGUID(), spawn->GetEntry(), spawn->GetPosition());
|
||||
}
|
||||
}
|
||||
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_minionsGUIDS.clear();
|
||||
majordomoSummonsData.clear();
|
||||
summons.DespawnAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* /*target*/) const override
|
||||
{
|
||||
return instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (roll_chance_i(25) && victim->IsPlayer())
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
if (!events.IsInPhase(PHASE_COMBAT))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_JustEngagedWith();
|
||||
DoCastAOE(SPELL_SEPARATION_ANXIETY);
|
||||
Talk(SAY_AGGRO);
|
||||
DoCastSelf(SPELL_AEGIS_OF_RAGNAROS, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHIELD_REFLECTION, 30s, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_RANDOM, 25s, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_TARGET, 15s, PHASE_COMBAT, PHASE_COMBAT);
|
||||
|
||||
aliveMinionsGUIDS.clear();
|
||||
aliveMinionsGUIDS = static_minionsGUIDS;
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
aliveMinionsGUIDS.erase(summon->GetGUID());
|
||||
if (summon->GetEntry() == NPC_FLAMEWAKER_HEALER || summon->GetEntry() == NPC_FLAMEWAKER_ELITE)
|
||||
{
|
||||
uint32 const remainingAdds = std::count_if(aliveMinionsGUIDS.begin(), aliveMinionsGUIDS.end(), [](ObjectGuid const& summonGuid)
|
||||
{
|
||||
return summonGuid.GetEntry() == NPC_FLAMEWAKER_HEALER || summonGuid.GetEntry() == NPC_FLAMEWAKER_ELITE;
|
||||
});
|
||||
|
||||
// Last remaining add
|
||||
if (remainingAdds == 1)
|
||||
{
|
||||
Talk(SAY_LAST_ADD);
|
||||
DoCastAOE(SPELL_CHAMPION);
|
||||
}
|
||||
// 50% of adds
|
||||
else if (remainingAdds == 4)
|
||||
{
|
||||
DoCastAOE(SPELL_IMMUNE_POLY);
|
||||
}
|
||||
else if (!remainingAdds)
|
||||
{
|
||||
static_minionsGUIDS.clear();
|
||||
|
||||
instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, DONE);
|
||||
events.CancelEventGroup(PHASE_COMBAT);
|
||||
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
|
||||
EnterEvadeMode();
|
||||
Talk(SAY_DEFEAT);
|
||||
return;
|
||||
}
|
||||
DoCastAOE(SPELL_ENCOURAGEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
_JustReachedHome();
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) == DONE)
|
||||
{
|
||||
events.Reset();
|
||||
events.SetPhase(PHASE_DEFEAT_OUTRO);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_1, 7500ms, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_COMBAT) && me->GetHealth() <= damage)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
|
||||
switch (events.GetPhaseMask())
|
||||
{
|
||||
case (1 << (PHASE_COMBAT - 1)):
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHIELD_REFLECTION:
|
||||
{
|
||||
if (rand_chance() <= 50.f)
|
||||
{
|
||||
DoCastSelf(SPELL_MAGIC_REFLECTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastSelf(SPELL_DAMAGE_REFLECTION);
|
||||
}
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_TELEPORT_RANDOM:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false))
|
||||
{
|
||||
DoCastSelf(SPELL_HATE_TO_ZERO, true);
|
||||
DoCast(target, SPELL_TELEPORT_RANDOM);
|
||||
}
|
||||
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_TELEPORT_TARGET:
|
||||
{
|
||||
DoCastSelf(SPELL_HATE_TO_ZERO, true);
|
||||
DoCastAOE(SPELL_TELEPORT_TARGET);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
break;
|
||||
}
|
||||
case (1 << (PHASE_DEFEAT_OUTRO - 1)):
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DEFEAT_OUTRO_1:
|
||||
{
|
||||
Talk(SAY_DEFEAT_2);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_2, 8s, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEFEAT_OUTRO_2:
|
||||
{
|
||||
Talk(SAY_DEFEAT_3);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_3, 21500ms, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEFEAT_OUTRO_3:
|
||||
{
|
||||
DoCastSelf(SPELL_TELEPORT_SELF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (1 << (PHASE_RAGNAROS_SUMMONING - 1)):
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RAGNAROS_SUMMON_1:
|
||||
{
|
||||
if (GameObject* lavaSplash = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_SPLASH)))
|
||||
{
|
||||
lavaSplash->SetRespawnTime(900);
|
||||
lavaSplash->Refresh();
|
||||
}
|
||||
if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
|
||||
{
|
||||
lavaSteam->SetRespawnTime(900);
|
||||
lavaSteam->Refresh();
|
||||
}
|
||||
Talk(SAY_RAG_SUM_2);
|
||||
// Next event will get triggered in MovementInform
|
||||
me->SetWalk(true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_RAGNAROS_SUMMON, MajordomoMoveRagPos, FORCED_MOVEMENT_NONE, 0.f, true, false);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_2:
|
||||
{
|
||||
if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
|
||||
{
|
||||
me->SetFacingToObject(lavaSteam);
|
||||
}
|
||||
|
||||
Talk(SAY_SUMMON_MAJ);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_3, 16700ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_EMERGE, 15s, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_3:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->AI()->Talk(SAY_ARRIVAL1_RAG);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_4, 11700ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_4:
|
||||
{
|
||||
Talk(SAY_ARRIVAL2_MAJ);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_5, 8700ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_5:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->AI()->Talk(SAY_ARRIVAL3_RAG);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_6, 16500ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_6:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->CastSpell(me, SPELL_ELEMENTAL_FIRE, true);
|
||||
ragnaros->AI()->DoAction(ACTION_FINISH_RAGNAROS_INTRO);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Additional events
|
||||
case EVENT_RAGNAROS_EMERGE:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->RemoveAurasDueToSpell(SPELL_RAGNAROS_FADE);
|
||||
ragnaros->CastSpell(ragnaros, SPELL_RAGNA_EMERGE);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && pointId == POINT_RAGNAROS_SUMMON)
|
||||
{
|
||||
DoCastAOE(SPELL_SUMMON_RAGNAROS);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_2, 11500ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_DEFEAT_OUTRO) && spellInfo->Id == SPELL_TELEPORT_SELF)
|
||||
{
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetHomePosition(MajordomoRagnaros);
|
||||
me->NearTeleportTo(MajordomoRagnaros.GetPositionX(), MajordomoRagnaros.GetPositionY(), MajordomoRagnaros.GetPositionZ(), MajordomoRagnaros.GetOrientation());
|
||||
events.SetPhase(PHASE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_START_RAGNAROS_INTRO && !events.IsInPhase(PHASE_RAGNAROS_SUMMONING))
|
||||
{
|
||||
events.SetPhase(PHASE_RAGNAROS_SUMMONING);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_1, 5s, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
}
|
||||
}
|
||||
private:
|
||||
GuidSet static_minionsGUIDS; // contained data should be changed on encounter completion
|
||||
GuidSet aliveMinionsGUIDS; // used for calculations
|
||||
std::unordered_map<uint32, MajordomoAddData> majordomoSummonsData;
|
||||
};
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_1, creature->GetGUID());
|
||||
return true;
|
||||
Talk(SAY_DEATH);
|
||||
me->DespawnOrUnsummon(10s, 0s);
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_RAGNAROS)
|
||||
{
|
||||
summon->CastSpell(summon, SPELL_RAGNAROS_FADE);
|
||||
summon->CastSpell(summon, SPELL_RAGNAROS_SUBMERGE_EFFECT, true);
|
||||
summon->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
summon->SetImmuneToAll(true);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
|
||||
std::list<TempSummon*> p_summons;
|
||||
me->SummonCreatureGroup(SUMMON_GROUP_ADDS, &p_summons);
|
||||
if (!p_summons.empty())
|
||||
{
|
||||
for (TempSummon const* summon : p_summons)
|
||||
{
|
||||
if (summon)
|
||||
{
|
||||
static_minionsGUIDS.insert(summon->GetGUID());
|
||||
majordomoSummonsData[summon->GetGUID().GetCounter()] = MajordomoAddData(summon->GetGUID(), summon->GetEntry(), summon->GetPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
events.SetPhase(PHASE_NONE);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->ResetLootMode();
|
||||
events.Reset();
|
||||
aliveMinionsGUIDS.clear();
|
||||
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, NOT_STARTED);
|
||||
|
||||
for (auto const& summon : majordomoSummonsData)
|
||||
{
|
||||
if (ObjectAccessor::GetCreature(*me, summon.second.guid))
|
||||
continue;
|
||||
|
||||
if (Creature* spawn = me->SummonCreature(summon.second.creatureEntry, summon.second.spawnPos))
|
||||
{
|
||||
static_minionsGUIDS.erase(summon.second.guid); // Erase the guid from the previous, no longer existing, spawn.
|
||||
static_minionsGUIDS.insert(spawn->GetGUID());
|
||||
majordomoSummonsData.erase(summon.second.guid.GetCounter());
|
||||
majordomoSummonsData[spawn->GetGUID().GetCounter()] = MajordomoAddData(spawn->GetGUID(), spawn->GetEntry(), spawn->GetPosition());
|
||||
}
|
||||
}
|
||||
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_minionsGUIDS.clear();
|
||||
majordomoSummonsData.clear();
|
||||
summons.DespawnAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* /*target*/) const override
|
||||
{
|
||||
return instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (roll_chance_i(25) && victim->IsPlayer())
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*attacker*/) override
|
||||
{
|
||||
if (!events.IsInPhase(PHASE_COMBAT))
|
||||
return;
|
||||
|
||||
_JustEngagedWith();
|
||||
DoCastAOE(SPELL_SEPARATION_ANXIETY);
|
||||
Talk(SAY_AGGRO);
|
||||
DoCastSelf(SPELL_AEGIS_OF_RAGNAROS, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_SHIELD_REFLECTION, 30s, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_RANDOM, 25s, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_TARGET, 15s, PHASE_COMBAT, PHASE_COMBAT);
|
||||
|
||||
aliveMinionsGUIDS.clear();
|
||||
aliveMinionsGUIDS = static_minionsGUIDS;
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
aliveMinionsGUIDS.erase(summon->GetGUID());
|
||||
if (summon->GetEntry() == NPC_FLAMEWAKER_HEALER || summon->GetEntry() == NPC_FLAMEWAKER_ELITE)
|
||||
{
|
||||
uint32 const remainingAdds = std::count_if(aliveMinionsGUIDS.begin(), aliveMinionsGUIDS.end(), [](ObjectGuid const& summonGuid)
|
||||
{
|
||||
return summonGuid.GetEntry() == NPC_FLAMEWAKER_HEALER || summonGuid.GetEntry() == NPC_FLAMEWAKER_ELITE;
|
||||
});
|
||||
|
||||
// Last remaining add
|
||||
if (remainingAdds == 1)
|
||||
{
|
||||
Talk(SAY_LAST_ADD);
|
||||
DoCastAOE(SPELL_CHAMPION);
|
||||
}
|
||||
// 50% of adds
|
||||
else if (remainingAdds == 4)
|
||||
{
|
||||
DoCastAOE(SPELL_IMMUNE_POLY);
|
||||
}
|
||||
else if (!remainingAdds)
|
||||
{
|
||||
static_minionsGUIDS.clear();
|
||||
|
||||
instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, DONE);
|
||||
events.CancelEventGroup(PHASE_COMBAT);
|
||||
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
|
||||
EnterEvadeMode();
|
||||
Talk(SAY_DEFEAT);
|
||||
return;
|
||||
}
|
||||
DoCastAOE(SPELL_ENCOURAGEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
_JustReachedHome();
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) == DONE)
|
||||
{
|
||||
events.Reset();
|
||||
events.SetPhase(PHASE_DEFEAT_OUTRO);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_1, 7500ms, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_COMBAT) && me->GetHealth() <= damage)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
|
||||
switch (events.GetPhaseMask())
|
||||
{
|
||||
case (1 << (PHASE_COMBAT - 1)):
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHIELD_REFLECTION:
|
||||
{
|
||||
if (rand_chance() <= 50.f)
|
||||
{
|
||||
DoCastSelf(SPELL_MAGIC_REFLECTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastSelf(SPELL_DAMAGE_REFLECTION);
|
||||
}
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_TELEPORT_RANDOM:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false))
|
||||
{
|
||||
DoCastSelf(SPELL_HATE_TO_ZERO, true);
|
||||
DoCast(target, SPELL_TELEPORT_RANDOM);
|
||||
}
|
||||
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_TELEPORT_TARGET:
|
||||
{
|
||||
DoCastSelf(SPELL_HATE_TO_ZERO, true);
|
||||
DoCastAOE(SPELL_TELEPORT_TARGET);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
break;
|
||||
}
|
||||
case (1 << (PHASE_DEFEAT_OUTRO - 1)):
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DEFEAT_OUTRO_1:
|
||||
{
|
||||
Talk(SAY_DEFEAT_2);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_2, 8s, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEFEAT_OUTRO_2:
|
||||
{
|
||||
Talk(SAY_DEFEAT_3);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_3, 21500ms, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEFEAT_OUTRO_3:
|
||||
{
|
||||
DoCastSelf(SPELL_TELEPORT_SELF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (1 << (PHASE_RAGNAROS_SUMMONING - 1)):
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RAGNAROS_SUMMON_1:
|
||||
{
|
||||
if (GameObject* lavaSplash = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_SPLASH)))
|
||||
{
|
||||
lavaSplash->SetRespawnTime(900);
|
||||
lavaSplash->Refresh();
|
||||
}
|
||||
if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
|
||||
{
|
||||
lavaSteam->SetRespawnTime(900);
|
||||
lavaSteam->Refresh();
|
||||
}
|
||||
Talk(SAY_RAG_SUM_2);
|
||||
// Next event will get triggered in MovementInform
|
||||
me->SetWalk(true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_RAGNAROS_SUMMON, MajordomoMoveRagPos, FORCED_MOVEMENT_NONE, 0.f, true, false);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_2:
|
||||
{
|
||||
if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
|
||||
{
|
||||
me->SetFacingToObject(lavaSteam);
|
||||
}
|
||||
|
||||
Talk(SAY_SUMMON_MAJ);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_3, 16700ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_EMERGE, 15s, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_3:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->AI()->Talk(SAY_ARRIVAL1_RAG);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_4, 11700ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_4:
|
||||
{
|
||||
Talk(SAY_ARRIVAL2_MAJ);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_5, 8700ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_5:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->AI()->Talk(SAY_ARRIVAL3_RAG);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_6, 16500ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_6:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->CastSpell(me, SPELL_ELEMENTAL_FIRE, true);
|
||||
ragnaros->AI()->DoAction(ACTION_FINISH_RAGNAROS_INTRO);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Additional events
|
||||
case EVENT_RAGNAROS_EMERGE:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->RemoveAurasDueToSpell(SPELL_RAGNAROS_FADE);
|
||||
ragnaros->CastSpell(ragnaros, SPELL_RAGNA_EMERGE);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && pointId == POINT_RAGNAROS_SUMMON)
|
||||
{
|
||||
DoCastAOE(SPELL_SUMMON_RAGNAROS);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_2, 11500ms, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_DEFEAT_OUTRO) && spellInfo->Id == SPELL_TELEPORT_SELF)
|
||||
{
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetHomePosition(MajordomoRagnaros);
|
||||
me->NearTeleportTo(MajordomoRagnaros.GetPositionX(), MajordomoRagnaros.GetPositionY(), MajordomoRagnaros.GetPositionZ(), MajordomoRagnaros.GetOrientation());
|
||||
events.SetPhase(PHASE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_START_RAGNAROS_INTRO && !events.IsInPhase(PHASE_RAGNAROS_SUMMONING))
|
||||
{
|
||||
events.SetPhase(PHASE_RAGNAROS_SUMMONING);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_1, 5s, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
}
|
||||
}
|
||||
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_1, me->GetGUID());
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
|
|
@ -544,40 +521,39 @@ public:
|
|||
case GOSSIP_ACTION_INFO_DEF:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, creature->GetGUID());
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, me->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, creature->GetGUID());
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, me->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_3, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_3, creature->GetGUID());
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_3, me->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
creature->AI()->Talk(SAY_RAG_SUM_1, player);
|
||||
creature->AI()->DoAction(ACTION_START_RAGNAROS_INTRO);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
Talk(SAY_RAG_SUM_1, player);
|
||||
DoAction(ACTION_START_RAGNAROS_INTRO);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CloseGossipMenuFor(player);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_majordomoAI>(creature);
|
||||
}
|
||||
private:
|
||||
GuidSet static_minionsGUIDS; // contained data should be changed on encounter completion
|
||||
GuidSet aliveMinionsGUIDS; // used for calculations
|
||||
std::unordered_map<uint32, MajordomoAddData> majordomoSummonsData;
|
||||
};
|
||||
|
||||
// 20538 Hate to Zero (SERVERSIDE)
|
||||
|
|
@ -593,12 +569,8 @@ class spell_hate_to_zero : public SpellScript
|
|||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Creature* creatureCaster = caster->ToCreature())
|
||||
{
|
||||
creatureCaster->GetThreatMgr().ResetAllThreat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -641,9 +613,7 @@ class spell_summon_ragnaros : public SpellScript
|
|||
void HandleHit()
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
caster->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 2 * HOUR * IN_MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
@ -654,7 +624,7 @@ class spell_summon_ragnaros : public SpellScript
|
|||
|
||||
void AddSC_boss_majordomo()
|
||||
{
|
||||
new boss_majordomo();
|
||||
RegisterMoltenCoreCreatureAI(boss_majordomo);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_hate_to_zero);
|
||||
|
|
|
|||
|
|
@ -112,390 +112,353 @@ enum Misc
|
|||
|
||||
constexpr float DEATH_ORIENTATION = 4.0f;
|
||||
|
||||
class boss_ragnaros : public CreatureScript
|
||||
struct boss_ragnaros : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_ragnaros() : CreatureScript("boss_ragnaros") {}
|
||||
|
||||
struct boss_ragnarosAI : public BossAI
|
||||
boss_ragnaros(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
|
||||
_isIntroDone(false),
|
||||
_hasYelledMagmaBurst(false),
|
||||
_processingMagmaBurst(false),
|
||||
_hasSubmergedOnce(false),
|
||||
_isKnockbackEmoteAllowed(true)
|
||||
{
|
||||
boss_ragnarosAI(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
|
||||
_isIntroDone(false),
|
||||
_hasYelledMagmaBurst(false),
|
||||
_processingMagmaBurst(false),
|
||||
_hasSubmergedOnce(false),
|
||||
_isKnockbackEmoteAllowed(true)
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
// Never reset intro events!
|
||||
if (_isIntroDone && !(extraEvents.GetPhaseMask() & (1 << (PHASE_INTRO - 1))))
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
// Never reset intro events!
|
||||
if (_isIntroDone && !(extraEvents.GetPhaseMask() & (1 << (PHASE_INTRO - 1))))
|
||||
{
|
||||
extraEvents.Reset();
|
||||
extraEvents.SetPhase(PHASE_EMERGED);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
}
|
||||
|
||||
_hasYelledMagmaBurst = false;
|
||||
_processingMagmaBurst = false;
|
||||
_hasSubmergedOnce = false;
|
||||
_isKnockbackEmoteAllowed = true;
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
_lavaBurstGUIDS.clear();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_SUBMERGED) && damage >= me->GetHealth())
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_FINISH_RAGNAROS_INTRO)
|
||||
{
|
||||
extraEvents.SetPhase(PHASE_INTRO);
|
||||
extraEvents.ScheduleEvent(EVENT_INTRO_SAY, 5s, 0, PHASE_INTRO);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
if (summon->GetEntry() == NPC_FLAME_OF_RAGNAROS)
|
||||
{
|
||||
summon->CastSpell((Unit*)nullptr, SPELL_INTENSE_HEAT, true, nullptr, nullptr, me->GetGUID());
|
||||
}
|
||||
else if (summon->GetEntry() == NPC_SON_OF_FLAME)
|
||||
{
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 index) override
|
||||
{
|
||||
if (index == GO_LAVA_BURST)
|
||||
{
|
||||
if (_lavaBurstGUIDS.empty())
|
||||
{
|
||||
extraEvents.ScheduleEvent(EVENT_LAVA_BURST_TRIGGER, 1ms);
|
||||
}
|
||||
|
||||
_lavaBurstGUIDS.insert(guid);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (events.IsInPhase(PHASE_SUBMERGED) && !summons.HasEntry(NPC_SON_OF_FLAME))
|
||||
{
|
||||
HandleEmerge();
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.SetPhase(PHASE_EMERGED);
|
||||
ScheduleCombatEvents();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
extraEvents.Reset();
|
||||
me->SetFacingTo(DEATH_ORIENTATION);
|
||||
extraEvents.SetPhase(PHASE_EMERGED);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
_hasYelledMagmaBurst = false;
|
||||
_processingMagmaBurst = false;
|
||||
_hasSubmergedOnce = false;
|
||||
_isKnockbackEmoteAllowed = true;
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
_lavaBurstGUIDS.clear();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_SUBMERGED) && damage >= me->GetHealth())
|
||||
{
|
||||
if (roll_chance_i(25) && victim->IsPlayer())
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_FINISH_RAGNAROS_INTRO)
|
||||
{
|
||||
extraEvents.SetPhase(PHASE_INTRO);
|
||||
extraEvents.ScheduleEvent(EVENT_INTRO_SAY, 5s, 0, PHASE_INTRO);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
if (summon->GetEntry() == NPC_FLAME_OF_RAGNAROS)
|
||||
summon->CastSpell((Unit*)nullptr, SPELL_INTENSE_HEAT, true, nullptr, nullptr, me->GetGUID());
|
||||
else if (summon->GetEntry() == NPC_SON_OF_FLAME)
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 index) override
|
||||
{
|
||||
if (index == GO_LAVA_BURST)
|
||||
{
|
||||
if (_lavaBurstGUIDS.empty())
|
||||
extraEvents.ScheduleEvent(EVENT_LAVA_BURST_TRIGGER, 1ms);
|
||||
|
||||
_lavaBurstGUIDS.insert(guid);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (events.IsInPhase(PHASE_SUBMERGED) && !summons.HasEntry(NPC_SON_OF_FLAME))
|
||||
HandleEmerge();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.SetPhase(PHASE_EMERGED);
|
||||
ScheduleCombatEvents();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
extraEvents.Reset();
|
||||
me->SetFacingTo(DEATH_ORIENTATION);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (roll_chance_i(25) && victim->IsPlayer())
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* target) override
|
||||
{
|
||||
if (target && me->Attack(target, true))
|
||||
DoStartNoMovement(target);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (!me->GetThreatMgr().IsThreatListEmpty())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
// Boss try to evade, but still got some targets on threat list - it means that none of these targets are in melee range - cast magma blast
|
||||
_processingMagmaBurst = true;
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* target) override
|
||||
else
|
||||
{
|
||||
if (target && me->Attack(target, true))
|
||||
{
|
||||
DoStartNoMovement(target);
|
||||
}
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
// Used for Magma Blast handling to force EnterEvadeMode if there are no melee targets
|
||||
return me->IsWithinMeleeRange(victim);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!extraEvents.Empty())
|
||||
{
|
||||
if (!me->GetThreatMgr().IsThreatListEmpty())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
{
|
||||
// Boss try to evade, but still got some targets on threat list - it means that none of these targets are in melee range - cast magma blast
|
||||
_processingMagmaBurst = true;
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
}
|
||||
extraEvents.Update(diff);
|
||||
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
// Used for Magma Blast handling to force EnterEvadeMode if there are no melee targets
|
||||
return me->IsWithinMeleeRange(victim);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!extraEvents.Empty())
|
||||
{
|
||||
extraEvents.Update(diff);
|
||||
|
||||
while (uint32 const eventId = extraEvents.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
// Intro events
|
||||
case EVENT_INTRO_SAY:
|
||||
{
|
||||
Talk(SAY_ARRIVAL5_RAG);
|
||||
extraEvents.ScheduleEvent(EVENT_INTRO_MAKE_ATTACKABLE, 2500ms, 0, PHASE_INTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_INTRO_MAKE_ATTACKABLE:
|
||||
{
|
||||
_isIntroDone = true;
|
||||
extraEvents.SetPhase(PHASE_EMERGED);
|
||||
me->RemoveAurasDueToSpell(SPELL_RAGNAROS_SUBMERGE_EFFECT);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoZoneInCombat();
|
||||
break;
|
||||
}
|
||||
// Submerge events
|
||||
case EVENT_EMERGE:
|
||||
{
|
||||
HandleEmerge();
|
||||
break;
|
||||
}
|
||||
case EVENT_RESET_KNOCKBACK_EMOTE:
|
||||
{
|
||||
_isKnockbackEmoteAllowed = true;
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BURST_TRIGGER:
|
||||
{
|
||||
if (!_lavaBurstGUIDS.empty())
|
||||
{
|
||||
ObjectGuid lavaBurstGUID = Acore::Containers::SelectRandomContainerElement(_lavaBurstGUIDS);
|
||||
|
||||
if (GameObject* go = ObjectAccessor::GetGameObject(*me, lavaBurstGUID))
|
||||
{
|
||||
go->CastSpell(nullptr, SPELL_LAVA_BURST_TRAP);
|
||||
go->SendCustomAnim(0);
|
||||
}
|
||||
|
||||
_lavaBurstGUIDS.erase(lavaBurstGUID);
|
||||
extraEvents.Repeat(1s);
|
||||
}
|
||||
else
|
||||
{
|
||||
events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Base combat events - (mainly emerge phase)
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
while (uint32 const eventId = extraEvents.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_WRATH_OF_RAGNAROS:
|
||||
// Intro events
|
||||
case EVENT_INTRO_SAY:
|
||||
{
|
||||
DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
Talk(SAY_WRATH);
|
||||
}
|
||||
events.Repeat(25s);
|
||||
Talk(SAY_ARRIVAL5_RAG);
|
||||
extraEvents.ScheduleEvent(EVENT_INTRO_MAKE_ATTACKABLE, 2500ms, 0, PHASE_INTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_HAND_OF_RAGNAROS:
|
||||
case EVENT_INTRO_MAKE_ATTACKABLE:
|
||||
{
|
||||
DoCastSelf(SPELL_HAND_OF_RAGNAROS);
|
||||
if (_isKnockbackEmoteAllowed)
|
||||
_isIntroDone = true;
|
||||
extraEvents.SetPhase(PHASE_EMERGED);
|
||||
me->RemoveAurasDueToSpell(SPELL_RAGNAROS_SUBMERGE_EFFECT);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoZoneInCombat();
|
||||
break;
|
||||
}
|
||||
// Submerge events
|
||||
case EVENT_EMERGE:
|
||||
{
|
||||
HandleEmerge();
|
||||
break;
|
||||
}
|
||||
case EVENT_RESET_KNOCKBACK_EMOTE:
|
||||
{
|
||||
_isKnockbackEmoteAllowed = true;
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BURST_TRIGGER:
|
||||
{
|
||||
if (!_lavaBurstGUIDS.empty())
|
||||
{
|
||||
Talk(SAY_KNOCKBACK);
|
||||
ObjectGuid lavaBurstGUID = Acore::Containers::SelectRandomContainerElement(_lavaBurstGUIDS);
|
||||
|
||||
if (GameObject* go = ObjectAccessor::GetGameObject(*me, lavaBurstGUID))
|
||||
{
|
||||
go->CastSpell(nullptr, SPELL_LAVA_BURST_TRAP);
|
||||
go->SendCustomAnim(0);
|
||||
}
|
||||
|
||||
_lavaBurstGUIDS.erase(lavaBurstGUID);
|
||||
extraEvents.Repeat(1s);
|
||||
}
|
||||
else
|
||||
{
|
||||
events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (!_processingMagmaBurst)
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
// Base combat events - (mainly emerge phase)
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_WRATH_OF_RAGNAROS:
|
||||
{
|
||||
DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
|
||||
|
||||
if (urand(0, 1))
|
||||
Talk(SAY_WRATH);
|
||||
events.Repeat(25s);
|
||||
break;
|
||||
}
|
||||
case EVENT_HAND_OF_RAGNAROS:
|
||||
{
|
||||
DoCastSelf(SPELL_HAND_OF_RAGNAROS);
|
||||
if (_isKnockbackEmoteAllowed)
|
||||
{
|
||||
Talk(SAY_KNOCKBACK);
|
||||
_isKnockbackEmoteAllowed = false;
|
||||
extraEvents.RescheduleEvent(EVENT_RESET_KNOCKBACK_EMOTE, 5s);
|
||||
}
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BURST:
|
||||
{
|
||||
DoCastAOE(SPELL_LAVA_BURST);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_BLAST:
|
||||
{
|
||||
_processingMagmaBurst = false;
|
||||
|
||||
if (!IsVictimWithinMeleeRange())
|
||||
{
|
||||
DoCastRandomTarget(SPELL_MAGMA_BLAST);
|
||||
|
||||
if (!_hasYelledMagmaBurst)
|
||||
{
|
||||
Talk(SAY_MAGMABURST);
|
||||
_hasYelledMagmaBurst = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EVENT_MIGHT_OF_RAGNAROS:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [](Unit const* target)
|
||||
{
|
||||
return target->IsPlayer() && target->getPowerType() == POWER_MANA;
|
||||
}))
|
||||
{
|
||||
if (me->CastSpell(target, SPELL_MIGHT_OF_RAGNAROS) == SPELL_CAST_OK && _isKnockbackEmoteAllowed)
|
||||
{
|
||||
Talk(SAY_KNOCKBACK, me);
|
||||
_isKnockbackEmoteAllowed = false;
|
||||
extraEvents.RescheduleEvent(EVENT_RESET_KNOCKBACK_EMOTE, 5s);
|
||||
}
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BURST:
|
||||
{
|
||||
DoCastAOE(SPELL_LAVA_BURST);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_BLAST:
|
||||
{
|
||||
_processingMagmaBurst = false;
|
||||
|
||||
if (!IsVictimWithinMeleeRange())
|
||||
{
|
||||
DoCastRandomTarget(SPELL_MAGMA_BLAST);
|
||||
|
||||
if (!_hasYelledMagmaBurst)
|
||||
{
|
||||
Talk(SAY_MAGMABURST);
|
||||
_hasYelledMagmaBurst = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EVENT_MIGHT_OF_RAGNAROS:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [](Unit const* target)
|
||||
{
|
||||
return target->IsPlayer() && target->getPowerType() == POWER_MANA;
|
||||
}))
|
||||
{
|
||||
if (me->CastSpell(target, SPELL_MIGHT_OF_RAGNAROS) == SPELL_CAST_OK && _isKnockbackEmoteAllowed)
|
||||
{
|
||||
Talk(SAY_KNOCKBACK, me);
|
||||
_isKnockbackEmoteAllowed = false;
|
||||
extraEvents.RescheduleEvent(EVENT_RESET_KNOCKBACK_EMOTE, 5s);
|
||||
}
|
||||
}
|
||||
events.Repeat(11s, 30s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SUBMERGE:
|
||||
{
|
||||
events.CancelEventGroup(PHASE_EMERGED);
|
||||
events.SetPhase(PHASE_SUBMERGED);
|
||||
extraEvents.SetPhase(PHASE_SUBMERGED);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->AttackStop();
|
||||
DoResetThreatList();
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
|
||||
DoCastSelf(SPELL_RAGNA_SUBMERGE_VISUAL, true);
|
||||
//me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
|
||||
|
||||
Talk(_hasSubmergedOnce ? SAY_REINFORCEMENTS2 : SAY_REINFORCEMENTS1);
|
||||
|
||||
DoCastAOE(SPELL_SUMMON_SONS_FLAME);
|
||||
|
||||
if (!_hasSubmergedOnce)
|
||||
{
|
||||
_hasSubmergedOnce = true;
|
||||
}
|
||||
|
||||
extraEvents.ScheduleEvent(EVENT_EMERGE, 90s, PHASE_SUBMERGED, PHASE_SUBMERGED);
|
||||
break;
|
||||
}
|
||||
events.Repeat(11s, 30s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
case EVENT_SUBMERGE:
|
||||
{
|
||||
return;
|
||||
events.CancelEventGroup(PHASE_EMERGED);
|
||||
events.SetPhase(PHASE_SUBMERGED);
|
||||
extraEvents.SetPhase(PHASE_SUBMERGED);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->AttackStop();
|
||||
DoResetThreatList();
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
|
||||
DoCastSelf(SPELL_RAGNA_SUBMERGE_VISUAL, true);
|
||||
//me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
|
||||
|
||||
Talk(_hasSubmergedOnce ? SAY_REINFORCEMENTS2 : SAY_REINFORCEMENTS1);
|
||||
|
||||
DoCastAOE(SPELL_SUMMON_SONS_FLAME);
|
||||
|
||||
if (!_hasSubmergedOnce)
|
||||
_hasSubmergedOnce = true;
|
||||
|
||||
extraEvents.ScheduleEvent(EVENT_EMERGE, 90s, PHASE_SUBMERGED, PHASE_SUBMERGED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap extraEvents;
|
||||
bool _isIntroDone;
|
||||
bool _hasYelledMagmaBurst;
|
||||
bool _processingMagmaBurst;
|
||||
bool _hasSubmergedOnce;
|
||||
bool _isKnockbackEmoteAllowed; // Prevents possible text overlap
|
||||
|
||||
GuidSet _lavaBurstGUIDS;
|
||||
|
||||
void HandleEmerge()
|
||||
{
|
||||
if (events.IsInPhase(PHASE_EMERGED))
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
events.SetPhase(PHASE_EMERGED);
|
||||
ScheduleCombatEvents();
|
||||
extraEvents.CancelEventGroup(PHASE_SUBMERGED);
|
||||
extraEvents.SetPhase(PHASE_EMERGED);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_RAGNA_SUBMERGE_VISUAL);
|
||||
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
{
|
||||
AttackStart(target);
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleCombatEvents()
|
||||
{
|
||||
events.RescheduleEvent(EVENT_ERUPTION, 15s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_HAND_OF_RAGNAROS, 25s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_SUBMERGE, 180s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_MIGHT_OF_RAGNAROS, 11s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool IsVictimWithinMeleeRange() const
|
||||
{
|
||||
return me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim());
|
||||
}
|
||||
};
|
||||
private:
|
||||
EventMap extraEvents;
|
||||
bool _isIntroDone;
|
||||
bool _hasYelledMagmaBurst;
|
||||
bool _processingMagmaBurst;
|
||||
bool _hasSubmergedOnce;
|
||||
bool _isKnockbackEmoteAllowed; // Prevents possible text overlap
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
GuidSet _lavaBurstGUIDS;
|
||||
|
||||
void HandleEmerge()
|
||||
{
|
||||
return GetMoltenCoreAI<boss_ragnarosAI>(creature);
|
||||
if (events.IsInPhase(PHASE_EMERGED))
|
||||
return;
|
||||
|
||||
events.SetPhase(PHASE_EMERGED);
|
||||
ScheduleCombatEvents();
|
||||
extraEvents.CancelEventGroup(PHASE_SUBMERGED);
|
||||
extraEvents.SetPhase(PHASE_EMERGED);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_RAGNA_SUBMERGE_VISUAL);
|
||||
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
AttackStart(target);
|
||||
}
|
||||
|
||||
void ScheduleCombatEvents()
|
||||
{
|
||||
events.RescheduleEvent(EVENT_ERUPTION, 15s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_HAND_OF_RAGNAROS, 25s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_SUBMERGE, 180s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
events.RescheduleEvent(EVENT_MIGHT_OF_RAGNAROS, 11s, PHASE_EMERGED, PHASE_EMERGED);
|
||||
}
|
||||
|
||||
bool IsVictimWithinMeleeRange() const
|
||||
{
|
||||
return me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -547,9 +510,7 @@ class spell_ragnaros_summon_sons_of_flame : public SpellScript
|
|||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
for (uint32 spell : RagnarosSoFSpells)
|
||||
{
|
||||
caster->CastSpell(caster, spell, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -561,7 +522,7 @@ class spell_ragnaros_summon_sons_of_flame : public SpellScript
|
|||
|
||||
void AddSC_boss_ragnaros()
|
||||
{
|
||||
new boss_ragnaros();
|
||||
RegisterMoltenCoreCreatureAI(boss_ragnaros);
|
||||
RegisterSpellScript(spell_ragnaros_lava_burst_randomizer);
|
||||
RegisterSpellScript(spell_ragnaros_summon_sons_of_flame);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,70 +41,57 @@ enum Events
|
|||
EVENT_SHAZZRAH_GATE,
|
||||
};
|
||||
|
||||
class boss_shazzrah : public CreatureScript
|
||||
struct boss_shazzrah : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_shazzrah() : CreatureScript("boss_shazzrah") { }
|
||||
boss_shazzrah(Creature* creature) : BossAI(creature, DATA_SHAZZRAH) {}
|
||||
|
||||
struct boss_shazzrahAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*target*/) override
|
||||
{
|
||||
boss_shazzrahAI(Creature* creature) : BossAI(creature, DATA_SHAZZRAH) {}
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 2s, 4s);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, 7s,11s);
|
||||
events.ScheduleEvent(EVENT_MAGIC_GROUNDING, 14s, 19s);
|
||||
events.ScheduleEvent(EVENT_COUNTERSPELL, 9s, 10s);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 30s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*target*/) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 2s, 4s);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, 7s,11s);
|
||||
events.ScheduleEvent(EVENT_MAGIC_GROUNDING, 14s, 19s);
|
||||
events.ScheduleEvent(EVENT_COUNTERSPELL, 9s, 10s);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 30s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_ARCANE_EXPLOSION:
|
||||
{
|
||||
case EVENT_ARCANE_EXPLOSION:
|
||||
{
|
||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||
events.Repeat(4s, 5s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHAZZRAH_CURSE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_SHAZZRAH_CURSE))
|
||||
{
|
||||
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
||||
}
|
||||
events.Repeat(23s, 26s);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGIC_GROUNDING:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGIC_GROUNDING);
|
||||
events.Repeat(7s, 9s);
|
||||
break;
|
||||
}
|
||||
case EVENT_COUNTERSPELL:
|
||||
{
|
||||
DoCastAOE(SPELL_COUNTERSPELL);
|
||||
events.Repeat(15s, 18s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHAZZRAH_GATE:
|
||||
{
|
||||
DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
|
||||
events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, 3s, 6s);
|
||||
events.Repeat(45s);
|
||||
break;
|
||||
}
|
||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||
events.Repeat(4s, 5s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHAZZRAH_CURSE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_SHAZZRAH_CURSE))
|
||||
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
||||
events.Repeat(23s, 26s);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGIC_GROUNDING:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGIC_GROUNDING);
|
||||
events.Repeat(7s, 9s);
|
||||
break;
|
||||
}
|
||||
case EVENT_COUNTERSPELL:
|
||||
{
|
||||
DoCastAOE(SPELL_COUNTERSPELL);
|
||||
events.Repeat(15s, 18s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHAZZRAH_GATE:
|
||||
{
|
||||
DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
|
||||
events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, 3s, 6s);
|
||||
events.Repeat(45s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_shazzrahAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -128,30 +115,22 @@ class spell_shazzrah_gate_dummy : public SpellScript
|
|||
Player const* plrTarget = target->ToPlayer();
|
||||
// Should not target non player targets
|
||||
if (!plrTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should skip current victim
|
||||
if (caster->GetVictim() == plrTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should not target enemies within melee range
|
||||
if (plrTarget->IsWithinMeleeRange(caster))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (!targets.empty())
|
||||
{
|
||||
Acore::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
|
|
@ -182,7 +161,7 @@ class spell_shazzrah_gate_dummy : public SpellScript
|
|||
|
||||
void AddSC_boss_shazzrah()
|
||||
{
|
||||
new boss_shazzrah();
|
||||
RegisterMoltenCoreCreatureAI(boss_shazzrah);
|
||||
|
||||
// Spells
|
||||
RegisterSpellScript(spell_shazzrah_gate_dummy);
|
||||
|
|
|
|||
|
|
@ -47,172 +47,138 @@ enum Events
|
|||
EVENT_IMMOLATE,
|
||||
};
|
||||
|
||||
class boss_sulfuron : public CreatureScript
|
||||
struct boss_sulfuron : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_sulfuron() : CreatureScript("boss_sulfuron") {}
|
||||
boss_sulfuron(Creature* creature) : BossAI(creature, DATA_SULFURON) {}
|
||||
|
||||
struct boss_sulfuronAI : public BossAI
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
boss_sulfuronAI(Creature* creature) : BossAI(creature, DATA_SULFURON) {}
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 6s, 20s);
|
||||
events.ScheduleEvent(EVENT_INSPIRE, 7s, 10s);
|
||||
events.ScheduleEvent(EVENT_KNOCKDOWN, 6s);
|
||||
events.ScheduleEvent(EVENT_FLAMESPEAR, 2s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
_JustEngagedWith();
|
||||
events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 6s, 20s);
|
||||
events.ScheduleEvent(EVENT_INSPIRE, 7s, 10s);
|
||||
events.ScheduleEvent(EVENT_KNOCKDOWN, 6s);
|
||||
events.ScheduleEvent(EVENT_FLAMESPEAR, 2s);
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_DEMORALIZING_SHOUT:
|
||||
{
|
||||
case EVENT_DEMORALIZING_SHOUT:
|
||||
{
|
||||
DoCastVictim(SPELL_DEMORALIZING_SHOUT);
|
||||
events.Repeat(12s, 18s);
|
||||
break;
|
||||
}
|
||||
case EVENT_INSPIRE:
|
||||
{
|
||||
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
|
||||
if (!healers.empty())
|
||||
{
|
||||
DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
|
||||
}
|
||||
DoCastVictim(SPELL_DEMORALIZING_SHOUT);
|
||||
events.Repeat(12s, 18s);
|
||||
break;
|
||||
}
|
||||
case EVENT_INSPIRE:
|
||||
{
|
||||
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
|
||||
if (!healers.empty())
|
||||
DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
|
||||
|
||||
DoCastSelf(SPELL_INSPIRE);
|
||||
events.Repeat(13s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_KNOCKDOWN:
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKDOWN);
|
||||
events.Repeat(10s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_FLAMESPEAR:
|
||||
{
|
||||
DoCastRandomTarget(SPELL_FLAMESPEAR);
|
||||
events.Repeat(12s, 16s);
|
||||
break;
|
||||
}
|
||||
DoCastSelf(SPELL_INSPIRE);
|
||||
events.Repeat(13s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_KNOCKDOWN:
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKDOWN);
|
||||
events.Repeat(10s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_FLAMESPEAR:
|
||||
{
|
||||
DoCastRandomTarget(SPELL_FLAMESPEAR);
|
||||
events.Repeat(12s, 16s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<boss_sulfuronAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_flamewaker_priest : public CreatureScript
|
||||
struct npc_flamewaker_priest : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_flamewaker_priest() : CreatureScript("npc_flamewaker_priest") {}
|
||||
npc_flamewaker_priest(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
struct npc_flamewaker_priestAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
npc_flamewaker_priestAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_DARK_STRIKE, 4s, 7s);
|
||||
events.ScheduleEvent(EVENT_DARK_MENDING, 15s, 30s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2s, 4s);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 3500ms, 6s);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_DARK_STRIKE, 4s, 7s);
|
||||
events.ScheduleEvent(EVENT_DARK_MENDING, 15s, 30s);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2s, 4s);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 3500ms, 6s);
|
||||
}
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
case EVENT_DARK_STRIKE:
|
||||
{
|
||||
DoCastVictim(SPELL_DARK_STRIKE);
|
||||
events.Repeat(4s, 7s);
|
||||
break;
|
||||
}
|
||||
case EVENT_DARK_MENDING:
|
||||
{
|
||||
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 1))
|
||||
{
|
||||
if (target->GetGUID() != me->GetGUID())
|
||||
{
|
||||
DoCast(target, SPELL_DARK_MENDING);
|
||||
}
|
||||
}
|
||||
events.Repeat(15s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_WORD_PAIN:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_SHADOW_WORD_PAIN))
|
||||
DoCast(target, SPELL_SHADOW_WORD_PAIN);
|
||||
events.Repeat(2500ms, 5s);
|
||||
break;
|
||||
}
|
||||
case EVENT_IMMOLATE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_IMMOLATE))
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
events.Repeat(5s, 7s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DARK_STRIKE:
|
||||
{
|
||||
DoCastVictim(SPELL_DARK_STRIKE);
|
||||
events.Repeat(4s, 7s);
|
||||
break;
|
||||
}
|
||||
case EVENT_DARK_MENDING:
|
||||
{
|
||||
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 1))
|
||||
{
|
||||
if (target->GetGUID() != me->GetGUID())
|
||||
{
|
||||
DoCast(target, SPELL_DARK_MENDING);
|
||||
}
|
||||
}
|
||||
events.Repeat(15s, 20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_WORD_PAIN:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_SHADOW_WORD_PAIN))
|
||||
{
|
||||
DoCast(target, SPELL_SHADOW_WORD_PAIN);
|
||||
}
|
||||
events.Repeat(2500ms, 5s);
|
||||
break;
|
||||
}
|
||||
case EVENT_IMMOLATE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_IMMOLATE))
|
||||
{
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
}
|
||||
events.Repeat(5s, 7s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_flamewaker_priestAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
void AddSC_boss_sulfuron()
|
||||
{
|
||||
new boss_sulfuron();
|
||||
new npc_flamewaker_priest();
|
||||
RegisterMoltenCoreCreatureAI(boss_sulfuron);
|
||||
RegisterMoltenCoreCreatureAI(npc_flamewaker_priest);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,384 +53,331 @@ MCBossObject const linkedBossObjData[MAX_MC_LINKED_BOSS_OBJ]=
|
|||
|
||||
constexpr uint8 SAY_SPAWN = 1;
|
||||
|
||||
class instance_molten_core : public InstanceMapScript
|
||||
struct instance_molten_core : public InstanceScript
|
||||
{
|
||||
public:
|
||||
instance_molten_core() : InstanceMapScript(MCScriptName, MAP_MOLTEN_CORE) {}
|
||||
|
||||
struct instance_molten_core_InstanceMapScript : public InstanceScript
|
||||
instance_molten_core(Map* map) : InstanceScript(map)
|
||||
{
|
||||
instance_molten_core_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
LoadMinionData(minionData);
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* /*player*/) override
|
||||
{
|
||||
if (CheckMajordomoExecutus())
|
||||
{
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_GOLEMAGG_THE_INCINERATOR:
|
||||
{
|
||||
_golemaggGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_CORE_RAGER:
|
||||
{
|
||||
_golemaggMinionsGUIDS.insert(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
case NPC_MAJORDOMO_EXECUTUS:
|
||||
{
|
||||
_majordomoExecutusGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_GARR:
|
||||
{
|
||||
_garrGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_RAGNAROS:
|
||||
{
|
||||
_ragnarosGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_FIRESWORN:
|
||||
case NPC_FLAMEWALKER:
|
||||
case NPC_FLAMEWALKER_PROTECTOR:
|
||||
case NPC_FLAMEWALKER_PRIEST:
|
||||
case NPC_FLAMEWALKER_HEALER:
|
||||
case NPC_FLAMEWALKER_ELITE:
|
||||
{
|
||||
AddMinion(creature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureRemove(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_FIRESWORN:
|
||||
{
|
||||
RemoveMinion(creature);
|
||||
break;
|
||||
}
|
||||
case NPC_FLAMEWALKER:
|
||||
case NPC_FLAMEWALKER_PROTECTOR:
|
||||
case NPC_FLAMEWALKER_PRIEST:
|
||||
case NPC_FLAMEWALKER_HEALER:
|
||||
case NPC_FLAMEWALKER_ELITE:
|
||||
{
|
||||
RemoveMinion(creature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_CACHE_OF_THE_FIRELORD:
|
||||
{
|
||||
_cacheOfTheFirelordGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_CIRCLE_GEDDON:
|
||||
case GO_CIRCLE_GARR:
|
||||
case GO_CIRCLE_GEHENNAS:
|
||||
case GO_CIRCLE_GOLEMAGG:
|
||||
case GO_CIRCLE_MAGMADAR:
|
||||
case GO_CIRCLE_SHAZZRAH:
|
||||
case GO_CIRCLE_SULFURON:
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
|
||||
{
|
||||
if (linkedBossObjData[i].circleId != go->GetEntry())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
|
||||
{
|
||||
go->DespawnOrUnsummon(0ms, Seconds(WEEK));
|
||||
}
|
||||
else
|
||||
{
|
||||
_circlesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case GO_RUNE_KRESS:
|
||||
case GO_RUNE_MOHN:
|
||||
case GO_RUNE_BLAZ:
|
||||
case GO_RUNE_MAZJ:
|
||||
case GO_RUNE_ZETH:
|
||||
case GO_RUNE_THERI:
|
||||
case GO_RUNE_KORO:
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
|
||||
{
|
||||
if (linkedBossObjData[i].runeId != go->GetEntry())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
|
||||
{
|
||||
go->UseDoorOrButton(WEEK * IN_MILLISECONDS);
|
||||
}
|
||||
else
|
||||
{
|
||||
_runesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_STEAM:
|
||||
{
|
||||
_lavaSteamGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_SPLASH:
|
||||
{
|
||||
_lavaSplashGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_BURST:
|
||||
{
|
||||
if (Creature* ragnaros = instance->GetCreature(_ragnarosGUID))
|
||||
{
|
||||
ragnaros->AI()->SetGUID(go->GetGUID(), GO_LAVA_BURST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_GOLEMAGG:
|
||||
return _golemaggGUID;
|
||||
case DATA_MAJORDOMO_EXECUTUS:
|
||||
return _majordomoExecutusGUID;
|
||||
case DATA_GARR:
|
||||
return _garrGUID;
|
||||
case DATA_LAVA_STEAM:
|
||||
return _lavaSteamGUID;
|
||||
case DATA_LAVA_SPLASH:
|
||||
return _lavaSplashGUID;
|
||||
case DATA_RAGNAROS:
|
||||
return _ragnarosGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 bossId, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(bossId, state))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bossId == DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
if (GameObject* cache = instance->GetGameObject(_cacheOfTheFirelordGUID))
|
||||
{
|
||||
cache->SetRespawnTime(7 * DAY);
|
||||
cache->SetLootRecipient(instance);
|
||||
}
|
||||
}
|
||||
else if (bossId == DATA_GOLEMAGG)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case NOT_STARTED:
|
||||
case FAIL:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
Creature* minion = instance->GetCreature(minionGuid);
|
||||
if (minion && minion->isDead())
|
||||
{
|
||||
minion->Respawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IN_PROGRESS:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
{
|
||||
minion->AI()->DoZoneInCombat(nullptr, 150.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
{
|
||||
minion->CastSpell(minion, SPELL_CORE_RAGER_QUIET_SUICIDE, true);
|
||||
}
|
||||
}
|
||||
_golemaggMinionsGUIDS.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Perform needed checks for Majordomu
|
||||
if (bossId < DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
if (GameObject* circle = instance->GetGameObject(_circlesGUIDs[bossId]))
|
||||
{
|
||||
circle->DespawnOrUnsummon(0ms, Seconds(WEEK));
|
||||
_circlesGUIDs[bossId].Clear();
|
||||
}
|
||||
|
||||
if (GameObject* rune = instance->GetGameObject(_runesGUIDs[bossId]))
|
||||
{
|
||||
rune->UseDoorOrButton(WEEK * IN_MILLISECONDS);
|
||||
_runesGUIDs[bossId].Clear();
|
||||
}
|
||||
|
||||
if (CheckMajordomoExecutus())
|
||||
{
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_RESET_GOLEMAGG_ENCOUNTER)
|
||||
{
|
||||
if (Creature* golemagg = instance->GetCreature(_golemaggGUID))
|
||||
{
|
||||
golemagg->AI()->EnterEvadeMode();
|
||||
}
|
||||
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
{
|
||||
minion->AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonMajordomoExecutus()
|
||||
{
|
||||
if (instance->GetCreature(_majordomoExecutusGUID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
if (Creature* creature = instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, MajordomoSummonPos))
|
||||
{
|
||||
creature->AI()->Talk(SAY_SPAWN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, MajordomoRagnaros);
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckMajordomoExecutus() const
|
||||
{
|
||||
if (GetBossState(DATA_RAGNAROS) == DONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < DATA_MAJORDOMO_EXECUTUS; ++i)
|
||||
{
|
||||
if (i == DATA_LUCIFRON)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetBossState(i) != DONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent spawning if Ragnaros is present
|
||||
if (instance->GetCreature(_ragnarosGUID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32/*bossid*/, ObjectGuid/*circleGUID*/> _circlesGUIDs;
|
||||
std::unordered_map<uint32/*bossid*/, ObjectGuid/*runeGUID*/> _runesGUIDs;
|
||||
|
||||
// Golemagg encounter related
|
||||
ObjectGuid _golemaggGUID;
|
||||
GuidSet _golemaggMinionsGUIDS;
|
||||
|
||||
// Ragnaros encounter related
|
||||
ObjectGuid _ragnarosGUID;
|
||||
ObjectGuid _lavaSteamGUID;
|
||||
ObjectGuid _lavaSplashGUID;
|
||||
|
||||
ObjectGuid _majordomoExecutusGUID;
|
||||
ObjectGuid _cacheOfTheFirelordGUID;
|
||||
ObjectGuid _garrGUID;
|
||||
ObjectGuid _magmadarGUID;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_molten_core_InstanceMapScript(map);
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
LoadMinionData(minionData);
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* /*player*/) override
|
||||
{
|
||||
if (CheckMajordomoExecutus())
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_GOLEMAGG_THE_INCINERATOR:
|
||||
{
|
||||
_golemaggGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_CORE_RAGER:
|
||||
{
|
||||
_golemaggMinionsGUIDS.insert(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
case NPC_MAJORDOMO_EXECUTUS:
|
||||
{
|
||||
_majordomoExecutusGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_GARR:
|
||||
{
|
||||
_garrGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_RAGNAROS:
|
||||
{
|
||||
_ragnarosGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_FIRESWORN:
|
||||
case NPC_FLAMEWALKER:
|
||||
case NPC_FLAMEWALKER_PROTECTOR:
|
||||
case NPC_FLAMEWALKER_PRIEST:
|
||||
case NPC_FLAMEWALKER_HEALER:
|
||||
case NPC_FLAMEWALKER_ELITE:
|
||||
{
|
||||
AddMinion(creature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureRemove(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_FIRESWORN:
|
||||
{
|
||||
RemoveMinion(creature);
|
||||
break;
|
||||
}
|
||||
case NPC_FLAMEWALKER:
|
||||
case NPC_FLAMEWALKER_PROTECTOR:
|
||||
case NPC_FLAMEWALKER_PRIEST:
|
||||
case NPC_FLAMEWALKER_HEALER:
|
||||
case NPC_FLAMEWALKER_ELITE:
|
||||
{
|
||||
RemoveMinion(creature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_CACHE_OF_THE_FIRELORD:
|
||||
{
|
||||
_cacheOfTheFirelordGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_CIRCLE_GEDDON:
|
||||
case GO_CIRCLE_GARR:
|
||||
case GO_CIRCLE_GEHENNAS:
|
||||
case GO_CIRCLE_GOLEMAGG:
|
||||
case GO_CIRCLE_MAGMADAR:
|
||||
case GO_CIRCLE_SHAZZRAH:
|
||||
case GO_CIRCLE_SULFURON:
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
|
||||
{
|
||||
if (linkedBossObjData[i].circleId != go->GetEntry())
|
||||
continue;
|
||||
|
||||
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
|
||||
go->DespawnOrUnsummon(0ms, Seconds(WEEK));
|
||||
else
|
||||
_circlesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case GO_RUNE_KRESS:
|
||||
case GO_RUNE_MOHN:
|
||||
case GO_RUNE_BLAZ:
|
||||
case GO_RUNE_MAZJ:
|
||||
case GO_RUNE_ZETH:
|
||||
case GO_RUNE_THERI:
|
||||
case GO_RUNE_KORO:
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
|
||||
{
|
||||
if (linkedBossObjData[i].runeId != go->GetEntry())
|
||||
continue;
|
||||
|
||||
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
|
||||
go->UseDoorOrButton(WEEK * IN_MILLISECONDS);
|
||||
else
|
||||
_runesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_STEAM:
|
||||
{
|
||||
_lavaSteamGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_SPLASH:
|
||||
{
|
||||
_lavaSplashGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_BURST:
|
||||
{
|
||||
if (Creature* ragnaros = instance->GetCreature(_ragnarosGUID))
|
||||
ragnaros->AI()->SetGUID(go->GetGUID(), GO_LAVA_BURST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_GOLEMAGG:
|
||||
return _golemaggGUID;
|
||||
case DATA_MAJORDOMO_EXECUTUS:
|
||||
return _majordomoExecutusGUID;
|
||||
case DATA_GARR:
|
||||
return _garrGUID;
|
||||
case DATA_LAVA_STEAM:
|
||||
return _lavaSteamGUID;
|
||||
case DATA_LAVA_SPLASH:
|
||||
return _lavaSplashGUID;
|
||||
case DATA_RAGNAROS:
|
||||
return _ragnarosGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 bossId, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(bossId, state))
|
||||
return false;
|
||||
|
||||
if (bossId == DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
if (GameObject* cache = instance->GetGameObject(_cacheOfTheFirelordGUID))
|
||||
{
|
||||
cache->SetRespawnTime(7 * DAY);
|
||||
cache->SetLootRecipient(instance);
|
||||
}
|
||||
}
|
||||
else if (bossId == DATA_GOLEMAGG)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case NOT_STARTED:
|
||||
case FAIL:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
Creature* minion = instance->GetCreature(minionGuid);
|
||||
if (minion && minion->isDead())
|
||||
minion->Respawn();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IN_PROGRESS:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
minion->AI()->DoZoneInCombat(nullptr, 150.0f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
minion->CastSpell(minion, SPELL_CORE_RAGER_QUIET_SUICIDE, true);
|
||||
}
|
||||
_golemaggMinionsGUIDS.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Perform needed checks for Majordomu
|
||||
if (bossId < DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
if (GameObject* circle = instance->GetGameObject(_circlesGUIDs[bossId]))
|
||||
{
|
||||
circle->DespawnOrUnsummon(0ms, Seconds(WEEK));
|
||||
_circlesGUIDs[bossId].Clear();
|
||||
}
|
||||
|
||||
if (GameObject* rune = instance->GetGameObject(_runesGUIDs[bossId]))
|
||||
{
|
||||
rune->UseDoorOrButton(WEEK * IN_MILLISECONDS);
|
||||
_runesGUIDs[bossId].Clear();
|
||||
}
|
||||
|
||||
if (CheckMajordomoExecutus())
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_RESET_GOLEMAGG_ENCOUNTER)
|
||||
{
|
||||
if (Creature* golemagg = instance->GetCreature(_golemaggGUID))
|
||||
golemagg->AI()->EnterEvadeMode();
|
||||
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
minion->AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonMajordomoExecutus()
|
||||
{
|
||||
if (instance->GetCreature(_majordomoExecutusGUID))
|
||||
return;
|
||||
|
||||
if (GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
if (Creature* creature = instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, MajordomoSummonPos))
|
||||
creature->AI()->Talk(SAY_SPAWN);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, MajordomoRagnaros);
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckMajordomoExecutus() const
|
||||
{
|
||||
if (GetBossState(DATA_RAGNAROS) == DONE)
|
||||
return false;
|
||||
|
||||
for (uint8 i = 0; i < DATA_MAJORDOMO_EXECUTUS; ++i)
|
||||
{
|
||||
if (i == DATA_LUCIFRON)
|
||||
continue;
|
||||
|
||||
if (GetBossState(i) != DONE)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent spawning if Ragnaros is present
|
||||
if (instance->GetCreature(_ragnarosGUID))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32/*bossid*/, ObjectGuid/*circleGUID*/> _circlesGUIDs;
|
||||
std::unordered_map<uint32/*bossid*/, ObjectGuid/*runeGUID*/> _runesGUIDs;
|
||||
|
||||
// Golemagg encounter related
|
||||
ObjectGuid _golemaggGUID;
|
||||
GuidSet _golemaggMinionsGUIDS;
|
||||
|
||||
// Ragnaros encounter related
|
||||
ObjectGuid _ragnarosGUID;
|
||||
ObjectGuid _lavaSteamGUID;
|
||||
ObjectGuid _lavaSplashGUID;
|
||||
|
||||
ObjectGuid _majordomoExecutusGUID;
|
||||
ObjectGuid _cacheOfTheFirelordGUID;
|
||||
ObjectGuid _garrGUID;
|
||||
ObjectGuid _magmadarGUID;
|
||||
};
|
||||
|
||||
void AddSC_instance_molten_core()
|
||||
{
|
||||
new instance_molten_core();
|
||||
RegisterInstanceScript(instance_molten_core, MAP_MOLTEN_CORE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,75 +46,60 @@ enum Spells
|
|||
};
|
||||
|
||||
// Serrated Bites timer may be wrong
|
||||
class npc_mc_core_hound : public CreatureScript
|
||||
struct npc_mc_core_hound : public CreatureAI
|
||||
{
|
||||
public:
|
||||
npc_mc_core_hound() : CreatureScript("npc_mc_core_hound") {}
|
||||
|
||||
struct npc_mc_core_houndAI : public CreatureAI
|
||||
npc_mc_core_hound(Creature* creature) :
|
||||
CreatureAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
serratedBiteTimer(3000)
|
||||
{
|
||||
npc_mc_core_houndAI(Creature* creature) :
|
||||
CreatureAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
serratedBiteTimer(3000)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
serratedBiteTimer = 3000;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
// Prevent receiving any extra damage if Hound is playing dead
|
||||
if (me->HasAura(SPELL_PLAY_DEAD))
|
||||
{
|
||||
damage = 0;
|
||||
return;
|
||||
}
|
||||
else if (me->GetHealth() <= damage)
|
||||
{
|
||||
damage = 0;
|
||||
Talk(EMOTE_SMOLDERING);
|
||||
DoCastSelf(SPELL_PLAY_DEAD);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_PLAY_DEAD))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (serratedBiteTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SERRATED_BITE);
|
||||
serratedBiteTimer = urand(5000, 6000);
|
||||
}
|
||||
else
|
||||
{
|
||||
serratedBiteTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 serratedBiteTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_mc_core_houndAI>(creature);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
serratedBiteTimer = 3000;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
// Prevent receiving any extra damage if Hound is playing dead
|
||||
if (me->HasAura(SPELL_PLAY_DEAD))
|
||||
{
|
||||
damage = 0;
|
||||
return;
|
||||
}
|
||||
else if (me->GetHealth() <= damage)
|
||||
{
|
||||
damage = 0;
|
||||
Talk(EMOTE_SMOLDERING);
|
||||
DoCastSelf(SPELL_PLAY_DEAD);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_PLAY_DEAD))
|
||||
return;
|
||||
|
||||
if (serratedBiteTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SERRATED_BITE);
|
||||
serratedBiteTimer = urand(5000, 6000);
|
||||
}
|
||||
else
|
||||
{
|
||||
serratedBiteTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 serratedBiteTimer;
|
||||
};
|
||||
|
||||
// 19822 Play Dead
|
||||
|
|
@ -136,9 +121,7 @@ class spell_mc_play_dead_aura : public AuraScript
|
|||
{
|
||||
Creature* creatureTarget = GetTarget()->ToCreature();
|
||||
if (!creatureTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
creatureTarget->CastSpell(creatureTarget, SPELL_PLAY_DEAD_PACIFY, true);
|
||||
creatureTarget->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
|
||||
|
|
@ -154,9 +137,7 @@ class spell_mc_play_dead_aura : public AuraScript
|
|||
{
|
||||
Creature* creatureTarget = GetTarget()->ToCreature();
|
||||
if (!creatureTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
creatureTarget->RemoveAurasDueToSpell(SPELL_PLAY_DEAD_PACIFY);
|
||||
creatureTarget->RemoveDynamicFlag(UNIT_DYNFLAG_DEAD);
|
||||
|
|
@ -166,9 +147,7 @@ class spell_mc_play_dead_aura : public AuraScript
|
|||
creatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
if (!creatureTarget->IsInCombat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldDie = true;
|
||||
std::list<Creature*> hounds;
|
||||
|
|
@ -246,9 +225,7 @@ struct npc_lava_spawn : public ScriptedAI
|
|||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
|
|
@ -262,7 +239,7 @@ private:
|
|||
void AddSC_molten_core()
|
||||
{
|
||||
// Creatures
|
||||
new npc_mc_core_hound();
|
||||
RegisterMoltenCoreCreatureAI(npc_mc_core_hound);
|
||||
RegisterCreatureAI(npc_lava_spawn);
|
||||
|
||||
// Spells
|
||||
|
|
|
|||
|
|
@ -127,4 +127,7 @@ inline AI* GetMoltenCoreAI(T* obj)
|
|||
return GetInstanceAI<AI>(obj, MCScriptName);
|
||||
}
|
||||
|
||||
#define RegisterMoltenCoreCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetMoltenCoreAI)
|
||||
#define RegisterMoltenCoreGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetMoltenCoreAI)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue