mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 15:58:04 +00:00
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:
@@ -18,6 +18,7 @@
|
|||||||
#include "blackrock_depths.h"
|
#include "blackrock_depths.h"
|
||||||
#include "AreaTriggerScript.h"
|
#include "AreaTriggerScript.h"
|
||||||
#include "CreatureScript.h"
|
#include "CreatureScript.h"
|
||||||
|
#include "GameObjectAI.h"
|
||||||
#include "GameObjectScript.h"
|
#include "GameObjectScript.h"
|
||||||
#include "GameTime.h"
|
#include "GameTime.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
@@ -34,93 +35,76 @@ enum IronhandData
|
|||||||
constexpr Milliseconds IRONHAND_FLAMES_TIMER = 16s;
|
constexpr Milliseconds IRONHAND_FLAMES_TIMER = 16s;
|
||||||
constexpr Milliseconds IRONHAND_FLAMES_TIMER_RAND = 3s;
|
constexpr Milliseconds IRONHAND_FLAMES_TIMER_RAND = 3s;
|
||||||
|
|
||||||
class go_shadowforge_brazier : public GameObjectScript
|
struct go_shadowforge_brazier : public GameObjectAI
|
||||||
{
|
{
|
||||||
public:
|
go_shadowforge_brazier(GameObject* go) : GameObjectAI(go) {}
|
||||||
go_shadowforge_brazier() : GameObjectScript("go_shadowforge_brazier") {}
|
|
||||||
|
|
||||||
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* northBrazier = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SF_BRAZIER_N));
|
||||||
GameObject* southBrazier = ObjectAccessor::GetGameObject(*go, instance->GetGuidData(DATA_SF_BRAZIER_S));
|
GameObject* southBrazier = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SF_BRAZIER_S));
|
||||||
|
|
||||||
if (!northBrazier || !southBrazier)
|
if (!northBrazier || !southBrazier)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// should only happen on first brazier
|
// should only happen on first brazier
|
||||||
if (instance->GetData(TYPE_LYCEUM) == NOT_STARTED)
|
if (instance->GetData(TYPE_LYCEUM) == NOT_STARTED)
|
||||||
{
|
|
||||||
instance->SetData(TYPE_LYCEUM, IN_PROGRESS);
|
instance->SetData(TYPE_LYCEUM, IN_PROGRESS);
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the opposite brazier is lit - if it is, open the gates.
|
// 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);
|
instance->SetData(TYPE_LYCEUM, DONE);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ironhand_guardian : public CreatureScript
|
struct brd_ironhand_guardian : public CreatureAI
|
||||||
{
|
{
|
||||||
public:
|
brd_ironhand_guardian(Creature* creature) : CreatureAI(creature) {}
|
||||||
ironhand_guardian() : CreatureScript("brd_ironhand_guardian") {}
|
|
||||||
|
|
||||||
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) {}
|
events.Update(diff);
|
||||||
bool flames_enabled = false;
|
|
||||||
|
|
||||||
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);
|
case SPELL_GOUT_OF_FLAMES:
|
||||||
events.ScheduleEvent(SPELL_GOUT_OF_FLAMES, urand(1, IRONHAND_N_GROUPS) * IRONHAND_FLAMES_TIMER / IRONHAND_N_GROUPS);
|
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
|
private:
|
||||||
{
|
bool _flamesEnabled = false;
|
||||||
events.Update(diff);
|
EventMap events;
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WaveCreature
|
struct WaveCreature
|
||||||
@@ -159,13 +143,10 @@ public:
|
|||||||
{
|
{
|
||||||
time_t now = GameTime::GetGameTime().count();
|
time_t now = GameTime::GetGameTime().count();
|
||||||
if (instance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || instance->GetData(TYPE_RING_OF_LAW) == DONE)
|
if (instance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || instance->GetData(TYPE_RING_OF_LAW) == DONE)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
if (now - instance->GetData(DATA_TIME_RING_FAIL) < 2 * 60) // in case of wipe, so people can rez.
|
if (now - instance->GetData(DATA_TIME_RING_FAIL) < 2 * 60) // in case of wipe, so people can rez.
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
instance->SetData(TYPE_RING_OF_LAW, IN_PROGRESS);
|
instance->SetData(TYPE_RING_OF_LAW, IN_PROGRESS);
|
||||||
return true;
|
return true;
|
||||||
@@ -185,249 +166,232 @@ enum GrimstoneTexts
|
|||||||
SAY_TEXT6 = 5
|
SAY_TEXT6 = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_grimstone : public CreatureScript
|
struct npc_grimstone : public npc_escortAI
|
||||||
{
|
{
|
||||||
public:
|
npc_grimstone(Creature* creature) : npc_escortAI(creature), summons(me)
|
||||||
npc_grimstone() : CreatureScript("npc_grimstone") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
{
|
||||||
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;
|
resetTimer = 0;
|
||||||
theldrenEvent = false;
|
eventTimer = 5000;
|
||||||
summons.DespawnAll();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstanceScript* instance;
|
void WaypointReached(uint32 waypointId) override
|
||||||
SummonList summons;
|
{
|
||||||
|
switch (waypointId)
|
||||||
uint8 eventPhase;
|
|
||||||
uint32 eventTimer;
|
|
||||||
uint32 resetTimer;
|
|
||||||
uint8 MobSpawnId;
|
|
||||||
uint8 BossSpawnId;
|
|
||||||
bool theldrenEvent;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
case 0:
|
||||||
}
|
Talk(SAY_TEXT1);
|
||||||
|
SetEscortPaused(true);
|
||||||
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;
|
|
||||||
eventTimer = 5000;
|
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:
|
if (Creature* creature = ObjectAccessor::GetCreature(*me, sum))
|
||||||
Talk(SAY_TEXT1);
|
{
|
||||||
SetEscortPaused(true);
|
if (creature->IsAlive() && creature->GetVictim())
|
||||||
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);
|
resetTimer = 30000;
|
||||||
instance->SetData(TYPE_RING_OF_LAW, DONE);
|
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);
|
if (eventTimer <= diff)
|
||||||
}
|
|
||||||
|
|
||||||
void SummonBoss()
|
|
||||||
{
|
|
||||||
if (me->FindNearestGameObject(GO_BANNER_OF_PROVOCATION, 100.0f))
|
|
||||||
{
|
{
|
||||||
theldrenEvent = true;
|
switch (eventPhase)
|
||||||
me->SummonCreature(NPC_THELDREN, 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
{
|
||||||
uint8 rand = urand(0, 4);
|
case 0:
|
||||||
for (uint8 i = rand; i < rand + 4; ++i)
|
Talk(SAY_TEXT5);
|
||||||
me->SummonCreature(theldrenTeam[i], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
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
|
else
|
||||||
me->SummonCreature(RingBoss[BossSpawnId], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
eventTimer -= diff;
|
||||||
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)
|
|
||||||
{
|
|
||||||
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
|
// npc_phalanx
|
||||||
@@ -438,67 +402,53 @@ enum PhalanxSpells
|
|||||||
SPELL_MIGHTYBLOW = 14099
|
SPELL_MIGHTYBLOW = 14099
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_phalanx : public CreatureScript
|
struct npc_phalanx : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_phalanx(Creature* creature) : ScriptedAI(creature) { }
|
||||||
npc_phalanx() : CreatureScript("npc_phalanx") { }
|
|
||||||
|
|
||||||
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;
|
if (_thunderClapTimer <= diff)
|
||||||
uint32 FireballVolley_Timer;
|
|
||||||
uint32 MightyBlow_Timer;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
ThunderClap_Timer = 12000;
|
DoCastVictim(SPELL_THUNDERCLAP);
|
||||||
FireballVolley_Timer = 0;
|
_thunderClapTimer = 10000;
|
||||||
MightyBlow_Timer = 15000;
|
}
|
||||||
|
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
|
DoCastVictim(SPELL_MIGHTYBLOW);
|
||||||
if (!UpdateVictim())
|
_mightyBlowTimer = 10000;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
};
|
else _mightyBlowTimer -= diff;
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 _thunderClapTimer;
|
||||||
|
uint32 _fireballVolleyTimer;
|
||||||
|
uint32 _mightyBlowTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// npc_lokhtos_darkbargainer
|
// npc_lokhtos_darkbargainer
|
||||||
@@ -518,12 +468,11 @@ enum LokhtosSpells
|
|||||||
SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059
|
SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_lokhtos_darkbargainer : public CreatureScript
|
struct npc_lokhtos_darkbargainer : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_lokhtos_darkbargainer(Creature* creature) : ScriptedAI(creature) { }
|
||||||
npc_lokhtos_darkbargainer() : CreatureScript("npc_lokhtos_darkbargainer") { }
|
|
||||||
|
|
||||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||||
{
|
{
|
||||||
ClearGossipMenuFor(player);
|
ClearGossipMenuFor(player);
|
||||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||||
@@ -532,32 +481,26 @@ public:
|
|||||||
player->CastSpell(player, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false);
|
player->CastSpell(player, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false);
|
||||||
}
|
}
|
||||||
if (action == GOSSIP_ACTION_TRADE)
|
if (action == GOSSIP_ACTION_TRADE)
|
||||||
player->GetSession()->SendListInventory(creature->GetGUID());
|
player->GetSession()->SendListInventory(me->GetGUID());
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnGossipHello(Player* player, Creature* creature) override
|
void sGossipHello(Player* player) override
|
||||||
{
|
{
|
||||||
if (creature->IsQuestGiver())
|
if (me->IsQuestGiver())
|
||||||
player->PrepareQuestMenu(creature->GetGUID());
|
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);
|
AddGossipItemFor(player, 4781, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||||
|
|
||||||
if (player->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 &&
|
if (player->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 &&
|
||||||
!player->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) &&
|
!player->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) &&
|
||||||
player->HasItemCount(ITEM_SULFURON_INGOT))
|
player->HasItemCount(ITEM_SULFURON_INGOT))
|
||||||
{
|
|
||||||
AddGossipItemFor(player, 4781, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
AddGossipItemFor(player, 4781, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||||
}
|
|
||||||
|
|
||||||
if (player->GetReputationRank(59) < REP_FRIENDLY)
|
if (player->GetReputationRank(59) < REP_FRIENDLY)
|
||||||
SendGossipMenuFor(player, 3673, creature->GetGUID());
|
SendGossipMenuFor(player, 3673, me->GetGUID());
|
||||||
else
|
else
|
||||||
SendGossipMenuFor(player, 3677, creature->GetGUID());
|
SendGossipMenuFor(player, 3677, me->GetGUID());
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -577,19 +520,29 @@ enum RocknotQuests
|
|||||||
QUEST_ALE = 4295
|
QUEST_ALE = 4295
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_rocknot : public CreatureScript
|
struct npc_rocknot : public npc_escortAI
|
||||||
{
|
{
|
||||||
public:
|
npc_rocknot(Creature* creature) : npc_escortAI(creature)
|
||||||
npc_rocknot() : CreatureScript("npc_rocknot") { }
|
{
|
||||||
|
instance = creature->GetInstanceScript();
|
||||||
bool OnQuestReward(Player* /*player*/, Creature* creature, Quest const* quest, uint32 /*item*/) override
|
}
|
||||||
|
|
||||||
|
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)
|
if (!instance)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
if (instance->GetData(TYPE_BAR) == DONE || instance->GetData(TYPE_BAR) == SPECIAL)
|
if (instance->GetData(TYPE_BAR) == DONE || instance->GetData(TYPE_BAR) == SPECIAL)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
if (quest->GetQuestId() == QUEST_ALE)
|
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
|
//keep track of amount in instance script, returns SPECIAL if amount ok and event in progress
|
||||||
if (instance->GetData(TYPE_BAR) == SPECIAL)
|
if (instance->GetData(TYPE_BAR) == SPECIAL)
|
||||||
{
|
{
|
||||||
creature->AI()->Talk(SAY_GOT_BEER);
|
Talk(SAY_GOT_BEER);
|
||||||
creature->CastSpell(creature, SPELL_DRUNKEN_RAGE, false);
|
me->CastSpell(me, SPELL_DRUNKEN_RAGE, false);
|
||||||
|
me->SetWalk(true);
|
||||||
if (npc_escortAI* escortAI = CAST_AI(npc_rocknot::npc_rocknotAI, creature->AI()))
|
Start(false);
|
||||||
{
|
|
||||||
creature->SetWalk(true);
|
|
||||||
escortAI->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;
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
uint32 BreakKeg_Timer;
|
if (_breakKegTimer)
|
||||||
uint32 BreakDoor_Timer;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
if (HasEscortState(STATE_ESCORT_ESCORTING))
|
if (_breakKegTimer <= diff)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
case 1:
|
DoGo(DATA_GO_BAR_KEG, 0);
|
||||||
me->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
|
_breakKegTimer = 0;
|
||||||
break;
|
_breakDoorTimer = 1000;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
else _breakKegTimer -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
if (_breakDoorTimer)
|
||||||
{
|
{
|
||||||
if (BreakKeg_Timer)
|
if (_breakDoorTimer <= diff)
|
||||||
{
|
{
|
||||||
if (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
|
||||||
DoGo(DATA_GO_BAR_KEG, 0);
|
//spell by trap has effect61, this indicate the bar go hostile
|
||||||
BreakKeg_Timer = 0;
|
|
||||||
BreakDoor_Timer = 1000;
|
if (Unit* tmp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PHALANX)))
|
||||||
}
|
tmp->SetFaction(FACTION_MONSTER);
|
||||||
else BreakKeg_Timer -= diff;
|
|
||||||
|
//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;
|
||||||
}
|
}
|
||||||
|
else _breakDoorTimer -= diff;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
npc_escortAI::UpdateAI(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
InstanceScript* instance;
|
||||||
|
uint32 _breakKegTimer;
|
||||||
|
uint32 _breakDoorTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_blackrock_depths()
|
void AddSC_blackrock_depths()
|
||||||
{
|
{
|
||||||
new go_shadowforge_brazier();
|
RegisterBlackrockDepthsGameObjectAI(go_shadowforge_brazier);
|
||||||
new at_ring_of_law();
|
new at_ring_of_law();
|
||||||
new npc_grimstone();
|
RegisterBlackrockDepthsCreatureAI(npc_grimstone);
|
||||||
new npc_phalanx();
|
RegisterBlackrockDepthsCreatureAI(npc_phalanx);
|
||||||
new npc_lokhtos_darkbargainer();
|
RegisterBlackrockDepthsCreatureAI(npc_lokhtos_darkbargainer);
|
||||||
new npc_rocknot();
|
RegisterBlackrockDepthsCreatureAI(npc_rocknot);
|
||||||
new ironhand_guardian();
|
RegisterBlackrockDepthsCreatureAI(brd_ironhand_guardian);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,4 +151,7 @@ inline AI* GetBlackrockDepthsAI(T* obj)
|
|||||||
return GetInstanceAI<AI>(obj, BRDScriptName);
|
return GetInstanceAI<AI>(obj, BRDScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RegisterBlackrockDepthsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackrockDepthsAI)
|
||||||
|
#define RegisterBlackrockDepthsGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetBlackrockDepthsAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -50,219 +50,184 @@ const Position SummonPositions[7] =
|
|||||||
|
|
||||||
std::vector<int> gobjectDwarfRunesEntry { 170578, 170579, 170580, 170581, 170582, 170583, 170584 };
|
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(Creature* creature) : BossAI(creature, BOSS_AMBASSADOR_FLAMELASH) { }
|
||||||
boss_ambassador_flamelash() : CreatureScript("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
|
for (int RuneEntry : gobjectDwarfRunesEntry)
|
||||||
SummonList summons;
|
if (GameObject* dwarfRune = me->FindNearestGameObject(RuneEntry, 200.0f))
|
||||||
|
dwarfRune->SetGoState(state);
|
||||||
|
}
|
||||||
|
|
||||||
// This will allow to find a valid position to spawn them
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
std::vector<int> validPosition;
|
{
|
||||||
bool foundValidPosition = false;
|
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:
|
// Check every position inside the vector
|
||||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 12s, 14s);
|
for (int pos : _validPosition)
|
||||||
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
|
// If the random is different, we found a temporary true,
|
||||||
for (int pos : validPosition)
|
// 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,
|
_foundValidPosition = false;
|
||||||
// until we find one that is equal, which means it has been used.
|
break;
|
||||||
if (pos != randomPosition)
|
|
||||||
foundValidPosition = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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
|
case EVENT_SPELL_FIREBLAST:
|
||||||
me->SummonCreature(NPC_FIRE_SPIRIT, SummonPositions[getValidRandomPosition()], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60 * IN_MILLISECONDS);
|
DoCastVictim(SPELL_FIREBLAST);
|
||||||
_events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 12s, 14s);
|
events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 7s);
|
||||||
|
break;
|
||||||
|
case EVENT_SUMMON_SPIRITS:
|
||||||
|
SummonSpirits();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
DoMeleeAttackIfReady();
|
||||||
{
|
}
|
||||||
//Return since we have no target
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
_events.Update(diff);
|
private:
|
||||||
|
// This will allow to find a valid position to spawn them
|
||||||
switch (_events.ExecuteEvent())
|
std::vector<int> _validPosition;
|
||||||
{
|
bool _foundValidPosition = false;
|
||||||
case EVENT_SPELL_FIREBLAST:
|
|
||||||
DoCastVictim(SPELL_FIREBLAST);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_FIREBLAST, 7s);
|
|
||||||
break;
|
|
||||||
case EVENT_SUMMON_SPIRITS:
|
|
||||||
SummonSpirits();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_burning_spirit : public CreatureScript
|
struct npc_burning_spirit : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_burning_spirit(Creature* creature) : ScriptedAI(creature) {}
|
||||||
npc_burning_spirit() : CreatureScript("npc_burning_spirit") { }
|
|
||||||
|
|
||||||
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
|
_flamelasherGUID = summoner->GetGUID();
|
||||||
{
|
me->GetMotionMaster()->MoveFollow(summoner->ToCreature(), 0.f, 0.f);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void AddSC_boss_ambassador_flamelash()
|
||||||
{
|
{
|
||||||
new boss_ambassador_flamelash();
|
RegisterBlackrockDepthsCreatureAI(boss_ambassador_flamelash);
|
||||||
new npc_burning_spirit();
|
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_DEMON_ARMOR = 3s; //virtually only cast once
|
||||||
constexpr Milliseconds TIMER_ENVELOPING_WEB = 16s;
|
constexpr Milliseconds TIMER_ENVELOPING_WEB = 16s;
|
||||||
|
|
||||||
class boss_anubshiah : public CreatureScript
|
struct boss_anubshiah : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_anubshiah(Creature* creature) : BossAI(creature, DATA_ANUBSHIAH) { }
|
||||||
boss_anubshiah() : CreatureScript("boss_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();
|
switch (eventId)
|
||||||
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT / 5);
|
{
|
||||||
events.ScheduleEvent(SPELL_CURSE_TONGUES, TIMER_CURSE_TONGUES / 5);
|
case SPELL_SHADOWBOLT:
|
||||||
events.ScheduleEvent(SPELL_CURSE_WEAKNESS, TIMER_CURSE_WEAKNESS / 5);
|
DoCastVictim(SPELL_SHADOWBOLT);
|
||||||
events.ScheduleEvent(SPELL_DEMON_ARMOR, TIMER_DEMON_ARMOR / 5);
|
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT - 2s, TIMER_SHADOWBOLT + 2s);
|
||||||
events.ScheduleEvent(SPELL_ENVELOPING_WEB, TIMER_ENVELOPING_WEB / 5);
|
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();
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_anubshiah()
|
void AddSC_boss_anubshiah()
|
||||||
{
|
{
|
||||||
new boss_anubshiah();
|
RegisterBlackrockDepthsCreatureAI(boss_anubshiah);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,106 +34,87 @@ enum Spells
|
|||||||
|
|
||||||
#define DATA_PERCENT_DEAD_SENATORS 0
|
#define DATA_PERCENT_DEAD_SENATORS 0
|
||||||
|
|
||||||
class boss_emperor_dagran_thaurissan : public CreatureScript
|
struct boss_emperor_dagran_thaurissan : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
uint32 hasYelled = 0;
|
||||||
boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") { }
|
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;
|
Talk(SAY_SLAY);
|
||||||
uint32 SenatorYells[5] = {3, 4, 5, 6, 7}; // IDs in creature_text database
|
}
|
||||||
|
|
||||||
boss_draganthaurissanAI(Creature* creature) : BossAI(creature, DATA_EMPEROR){}
|
void SetData(uint32 type, uint32 data) override
|
||||||
|
{
|
||||||
void JustEngagedWith(Unit* /*who*/) 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);
|
if (hasYelled < 5)
|
||||||
}
|
if (me->IsAlive())
|
||||||
else
|
Talk(SenatorYells[hasYelled]);
|
||||||
{
|
hasYelled++;
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
case SPELL_HANDOFTHAURISSAN:
|
||||||
Moira->AI()->Talk(0);
|
DoCast(SelectTarget(SelectTargetMethod::Random), SPELL_HANDOFTHAURISSAN);
|
||||||
Moira->SetFaction(FACTION_FRIENDLY);
|
//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();
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_draganthaurissan()
|
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_REND = 20s;
|
||||||
constexpr Milliseconds TIMER_SHIELD = 12s;
|
constexpr Milliseconds TIMER_SHIELD = 12s;
|
||||||
|
|
||||||
class boss_eviscerator : public CreatureScript
|
struct boss_eviscerator : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_eviscerator(Creature* creature) : BossAI(creature, DATA_EVISCERATOR) {}
|
||||||
boss_eviscerator() : CreatureScript("boss_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) {}
|
if ((damageSchoolMask & SPELL_SCHOOL_MASK_MAGIC) && SpellShieldReady)
|
||||||
|
|
||||||
bool SpellShieldReady = false;
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
|
||||||
{
|
{
|
||||||
_JustEngagedWith();
|
DoCast(SPELL_SHIELD);
|
||||||
events.ScheduleEvent(SPELL_SHADOWBOLT_VOLLEY, TIMER_SHADOWBOLT_VOLLEY / 5);
|
SpellShieldReady = false;
|
||||||
events.ScheduleEvent(SPELL_REND, TIMER_REND / 5);
|
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD);
|
||||||
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD / 5);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
case SPELL_SHADOWBOLT_VOLLEY:
|
||||||
SpellShieldReady = false;
|
DoCastVictim(SPELL_SHADOWBOLT_VOLLEY);
|
||||||
events.ScheduleEvent(SPELL_SHIELD, TIMER_SHIELD);
|
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();
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_eviscerator()
|
void AddSC_boss_eviscerator()
|
||||||
{
|
{
|
||||||
new boss_eviscerator();
|
RegisterBlackrockDepthsCreatureAI(boss_eviscerator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,108 +26,94 @@ enum Spells
|
|||||||
SPELL_CLEAVE = 20691
|
SPELL_CLEAVE = 20691
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_general_angerforge : public CreatureScript
|
struct boss_general_angerforge : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_general_angerforge(Creature* creature) : ScriptedAI(creature) { }
|
||||||
boss_general_angerforge() : CreatureScript("boss_general_angerforge") { }
|
|
||||||
|
|
||||||
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;
|
void SummonMedics(Unit* victim)
|
||||||
uint32 HamString_Timer;
|
{
|
||||||
uint32 Cleave_Timer;
|
if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
|
||||||
uint32 Adds_Timer;
|
SummonedMedic->AI()->AttackStart(victim);
|
||||||
bool Medics;
|
}
|
||||||
|
|
||||||
void Reset() override
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
//Return since we have no target
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_mightyBlowTimer <= diff)
|
||||||
{
|
{
|
||||||
MightyBlow_Timer = 8000;
|
DoCastVictim(SPELL_MIGHTYBLOW);
|
||||||
HamString_Timer = 12000;
|
_mightyBlowTimer = 18000;
|
||||||
Cleave_Timer = 16000;
|
}
|
||||||
Adds_Timer = 0;
|
else _mightyBlowTimer -= diff;
|
||||||
Medics = false;
|
|
||||||
|
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 { }
|
//Summon Medics
|
||||||
|
if (!_medics && HealthBelowPct(21))
|
||||||
void SummonAdds(Unit* victim)
|
|
||||||
{
|
{
|
||||||
if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
|
SummonMedics(me->GetVictim());
|
||||||
SummonedAdd->AI()->AttackStart(victim);
|
SummonMedics(me->GetVictim());
|
||||||
|
_medics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SummonMedics(Unit* victim)
|
DoMeleeAttackIfReady();
|
||||||
{
|
}
|
||||||
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 UpdateAI(uint32 diff) override
|
private:
|
||||||
{
|
uint32 _mightyBlowTimer;
|
||||||
//Return since we have no target
|
uint32 _hamStringTimer;
|
||||||
if (!UpdateVictim())
|
uint32 _cleaveTimer;
|
||||||
return;
|
uint32 _addsTimer;
|
||||||
|
bool _medics;
|
||||||
//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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_general_angerforge()
|
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_MORTAL = 22s;
|
||||||
constexpr Milliseconds TIMER_BLOODLUST = 30s;
|
constexpr Milliseconds TIMER_BLOODLUST = 30s;
|
||||||
|
|
||||||
class boss_gorosh_the_dervish : public CreatureScript
|
struct boss_gorosh_the_dervish : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_gorosh_the_dervish(Creature* creature) : BossAI(creature, DATA_GOROSH) { }
|
||||||
boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { }
|
|
||||||
|
|
||||||
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();
|
switch (eventId)
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
return;
|
case SPELL_WHIRLWIND:
|
||||||
}
|
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
{
|
||||||
case SPELL_WHIRLWIND:
|
DoCastVictim(SPELL_WHIRLWIND);
|
||||||
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
nextWhirlwindTime = randtime(TIMER_WHIRLWIND - 2s, TIMER_WHIRLWIND + 2s);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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()
|
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_GROUNDTREMOR = 10s;
|
||||||
constexpr Milliseconds TIMER_FRENZY = 15s;
|
constexpr Milliseconds TIMER_FRENZY = 15s;
|
||||||
|
|
||||||
class boss_grizzle : public CreatureScript
|
struct boss_grizzle : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_grizzle(Creature* creature) : BossAI(creature, DATA_GRIZZLE) {}
|
||||||
boss_grizzle() : CreatureScript("boss_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();
|
switch (eventId)
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
return;
|
case SPELL_GROUNDTREMOR:
|
||||||
}
|
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
{
|
||||||
case SPELL_GROUNDTREMOR:
|
DoCastVictim(SPELL_GROUNDTREMOR);
|
||||||
if (me->GetDistance2d(me->GetVictim()) < 10.0f)
|
nextTremorTime = randtime(TIMER_GROUNDTREMOR - 2s, TIMER_GROUNDTREMOR + 2s);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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()
|
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_BANEFUL = 24s;
|
||||||
constexpr Milliseconds TIMER_WEB_EXPLOSION = 20s;
|
constexpr Milliseconds TIMER_WEB_EXPLOSION = 20s;
|
||||||
|
|
||||||
class boss_hedrum : public CreatureScript
|
struct boss_hedrum : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_hedrum(Creature* creature) : BossAI(creature, DATA_HEDRUM) {}
|
||||||
boss_hedrum() : CreatureScript("boss_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();
|
switch (eventId)
|
||||||
events.ScheduleEvent(SPELL_PARALYZING, TIMER_PARALYZING / 5);
|
{
|
||||||
events.ScheduleEvent(SPELL_BANEFUL, TIMER_BANEFUL / 5);
|
case SPELL_PARALYZING:
|
||||||
events.ScheduleEvent(SPELL_WEB_EXPLOSION, TIMER_WEB_EXPLOSION / 5);
|
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();
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_hedrum()
|
void AddSC_boss_hedrum()
|
||||||
{
|
{
|
||||||
new boss_hedrum();
|
RegisterBlackrockDepthsCreatureAI(boss_hedrum);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,81 +27,67 @@ enum Spells
|
|||||||
SPELL_SHADOWSHIELD = 22417
|
SPELL_SHADOWSHIELD = 22417
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_high_interrogator_gerstahn : public CreatureScript
|
struct boss_high_interrogator_gerstahn : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_high_interrogator_gerstahn(Creature* creature) : ScriptedAI(creature) { }
|
||||||
boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") { }
|
|
||||||
|
|
||||||
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;
|
if (_shadowWordPainTimer <= diff)
|
||||||
uint32 ManaBurn_Timer;
|
|
||||||
uint32 PsychicScream_Timer;
|
|
||||||
uint32 ShadowShield_Timer;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
ShadowWordPain_Timer = 4000;
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||||
ManaBurn_Timer = 14000;
|
DoCast(target, SPELL_SHADOWWORDPAIN);
|
||||||
PsychicScream_Timer = 32000;
|
_shadowWordPainTimer = 7000;
|
||||||
ShadowShield_Timer = 8000;
|
|
||||||
}
|
}
|
||||||
|
else _shadowWordPainTimer -= diff;
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override { }
|
if (_manaBurnTimer <= diff)
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
{
|
||||||
//Return since we have no target
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||||
if (!UpdateVictim())
|
DoCast(target, SPELL_MANABURN);
|
||||||
return;
|
_manaBurnTimer = 10000;
|
||||||
|
|
||||||
//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();
|
|
||||||
}
|
}
|
||||||
};
|
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()
|
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
|
SPELL_WARSTOMP = 24375
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_magmus : public CreatureScript
|
struct boss_magmus : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_magmus(Creature* creature) : BossAI(creature, TYPE_IRON_HALL) {}
|
||||||
boss_magmus() : CreatureScript("boss_magmus") { }
|
|
||||||
|
|
||||||
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
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
_Reset();
|
//Return since we have no target
|
||||||
instance->SetData(TYPE_IRON_HALL, NOT_STARTED);
|
if (!UpdateVictim())
|
||||||
}
|
return;
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
events.Update(diff);
|
||||||
{
|
|
||||||
instance->SetData(TYPE_IRON_HALL, IN_PROGRESS);
|
|
||||||
_JustEngagedWith();
|
|
||||||
events.ScheduleEvent(SPELL_WARSTOMP, 8s, 12s);
|
|
||||||
events.ScheduleEvent(SPELL_FIERYBURST, 4s, 8s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
//Return since we have no target
|
switch (eventId)
|
||||||
if (!UpdateVictim())
|
|
||||||
{
|
{
|
||||||
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()
|
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_SHADOWBOLT = 16s;
|
||||||
constexpr Milliseconds TIMER_WORDPAIN = 12s;
|
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
|
// 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
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
{
|
{
|
||||||
_JustEngagedWith();
|
_JustEngagedWith();
|
||||||
@@ -49,15 +49,13 @@ struct boss_moira_bronzebeardAI : public BossAI
|
|||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
@@ -83,22 +81,18 @@ struct boss_moira_bronzebeardAI : public BossAI
|
|||||||
{
|
{
|
||||||
Creature* emperor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EMPEROR));
|
Creature* emperor = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EMPEROR));
|
||||||
if (emperor && emperor->HealthBelowPct(90))
|
if (emperor && emperor->HealthBelowPct(90))
|
||||||
{
|
|
||||||
DoCast(emperor, spell);
|
DoCast(emperor, spell);
|
||||||
}
|
|
||||||
else if (HealthBelowPct(90))
|
else if (HealthBelowPct(90))
|
||||||
{
|
|
||||||
DoCastSelf(spell);
|
DoCastSelf(spell);
|
||||||
}
|
|
||||||
events.ScheduleEvent(spell, timer - 2s, timer + 2s);
|
events.ScheduleEvent(spell, timer - 2s, timer + 2s);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// high priestess should be fairly identical to Moira.
|
// high priestess should be fairly identical to Moira.
|
||||||
// Running away when emperor dies is handled through GUID from emperor, therefore not relevant here.
|
// 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
|
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);
|
events.ScheduleEvent(SPELL_SHADOWBOLT, TIMER_SHADOWBOLT / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
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()
|
void AddSC_boss_moira_bronzebeard()
|
||||||
{
|
{
|
||||||
new boss_moira_bronzebeard();
|
RegisterBlackrockDepthsCreatureAI(boss_moira_bronzebeard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddSC_boss_high_priestess_thaurissan()
|
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_POLYMORPH = 12s;
|
||||||
constexpr Milliseconds TIMER_SLOW = 15s;
|
constexpr Milliseconds TIMER_SLOW = 15s;
|
||||||
|
|
||||||
class boss_okthor : public CreatureScript
|
struct boss_okthor : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_okthor(Creature* creature) : BossAI(creature, DATA_OKTHOR) {}
|
||||||
boss_okthor() : CreatureScript("boss_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();
|
switch (eventId)
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
return;
|
case SPELL_ARCANE_BOLT:
|
||||||
}
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||||
events.Update(diff);
|
DoCast(target, SPELL_ARCANE_BOLT);
|
||||||
|
events.ScheduleEvent(SPELL_ARCANE_BOLT, TIMER_ARCANE_BOLT - 2s, TIMER_ARCANE_BOLT + 2s);
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
break;
|
||||||
{
|
case SPELL_ARCANE_EXPLOSION:
|
||||||
return;
|
if (me->GetDistance2d(me->GetVictim()) < 50.0f)
|
||||||
}
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
switch (eventId)
|
|
||||||
{
|
{
|
||||||
case SPELL_ARCANE_BOLT:
|
DoCast(SPELL_ARCANE_EXPLOSION);
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
_nextArcaneExplosionTime = randtime(TIMER_ARCANE_EXPLOSION - 2s, TIMER_ARCANE_EXPLOSION + 2s);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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()
|
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...
|
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(Creature* creature) : ScriptedAI(creature) { }
|
||||||
boss_gloomrel() : CreatureScript("boss_gloomrel") { }
|
|
||||||
|
|
||||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||||
{
|
{
|
||||||
ClearGossipMenuFor(player);
|
ClearGossipMenuFor(player);
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case GOSSIP_ACTION_INFO_DEF+1:
|
case GOSSIP_ACTION_INFO_DEF+1:
|
||||||
AddGossipItemFor(player, GOSSIP_TEXT_CONTINUE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
|
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;
|
break;
|
||||||
case GOSSIP_ACTION_INFO_DEF+11:
|
case GOSSIP_ACTION_INFO_DEF+11:
|
||||||
CloseGossipMenuFor(player);
|
CloseGossipMenuFor(player);
|
||||||
@@ -73,33 +72,29 @@ public:
|
|||||||
break;
|
break;
|
||||||
case GOSSIP_ACTION_INFO_DEF+2:
|
case GOSSIP_ACTION_INFO_DEF+2:
|
||||||
AddGossipItemFor(player, GOSSIP_TEXT_CONTINUE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
|
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;
|
break;
|
||||||
case GOSSIP_ACTION_INFO_DEF+22:
|
case GOSSIP_ACTION_INFO_DEF+22:
|
||||||
CloseGossipMenuFor(player);
|
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
|
//are 5 minutes expected? go template may have data to despawn when used at quest
|
||||||
instance->DoRespawnGameObject(instance->GetGuidData(DATA_GO_CHALICE), MINUTE * 5);
|
instance->DoRespawnGameObject(instance->GetGuidData(DATA_GO_CHALICE), MINUTE * 5);
|
||||||
}
|
|
||||||
break;
|
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))
|
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);
|
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)
|
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);
|
AddGossipItemFor(player, GOSSIP_GROOMREL, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||||
|
|
||||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,145 +115,124 @@ enum DoomrelEvents
|
|||||||
EVENT_SPELL_SUMMON_VOIDWALKERS = 5,
|
EVENT_SPELL_SUMMON_VOIDWALKERS = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_doomrel : public CreatureScript
|
struct boss_doomrel : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
boss_doomrel(Creature* creature) : ScriptedAI(creature)
|
||||||
boss_doomrel() : CreatureScript("boss_doomrel") { }
|
{
|
||||||
|
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);
|
ClearGossipMenuFor(player);
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case GOSSIP_ACTION_INFO_DEF+1:
|
case GOSSIP_ACTION_INFO_DEF+1:
|
||||||
AddGossipItemFor(player, GOSSIP_TEXT_CONTINUE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
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;
|
break;
|
||||||
case GOSSIP_ACTION_INFO_DEF+2:
|
case GOSSIP_ACTION_INFO_DEF+2:
|
||||||
CloseGossipMenuFor(player);
|
CloseGossipMenuFor(player);
|
||||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||||
// Start encounter
|
// Start encounter
|
||||||
InstanceScript* instance = creature->GetInstanceScript();
|
|
||||||
if (instance)
|
if (instance)
|
||||||
{
|
|
||||||
instance->SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS);
|
instance->SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS);
|
||||||
}
|
Talk(SAY_START_FIGHT);
|
||||||
creature->AI()->Talk(SAY_START_FIGHT);
|
|
||||||
break;
|
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);
|
AddGossipItemFor(player, GOSSIP_DOOMREL_START_COMBAT, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||||
SendGossipMenuFor(player, SAY_DOOMREL_HELLO, creature->GetGUID());
|
SendGossipMenuFor(player, SAY_DOOMREL_HELLO, me->GetGUID());
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
DoMeleeAttackIfReady();
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_tomb_of_seven()
|
void AddSC_boss_tomb_of_seven()
|
||||||
{
|
{
|
||||||
new boss_gloomrel();
|
RegisterBlackrockDepthsCreatureAI(boss_gloomrel);
|
||||||
new boss_doomrel();
|
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 RegisterBlackrockSpireCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackrockSpireAI)
|
||||||
|
#define RegisterBlackrockSpireGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetBlackrockSpireAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,98 +40,85 @@ enum Events
|
|||||||
EVENT_CHECK_CONFLAGRATION_TARGET
|
EVENT_CHECK_CONFLAGRATION_TARGET
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_drakkisath : public CreatureScript
|
struct boss_drakkisath : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_drakkisath(Creature* creature) : BossAI(creature, DATA_GENERAL_DRAKKISATH)
|
||||||
boss_drakkisath() : CreatureScript("boss_drakkisath") { }
|
|
||||||
|
|
||||||
struct boss_drakkisathAI : public BossAI
|
|
||||||
{
|
{
|
||||||
boss_drakkisathAI(Creature* creature) : BossAI(creature, DATA_GENERAL_DRAKKISATH)
|
_conflagrateThreat = 0.0f;
|
||||||
{
|
|
||||||
_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void AddSC_boss_drakkisath()
|
||||||
{
|
{
|
||||||
new boss_drakkisath();
|
RegisterBlackrockSpireCreatureAI(boss_drakkisath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,125 +51,114 @@ enum Events
|
|||||||
EVENT_SUMMONED_2 = 6
|
EVENT_SUMMONED_2 = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_gyth : public CreatureScript
|
struct boss_gyth : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_gyth(Creature* creature) : BossAI(creature, DATA_GYTH) { }
|
||||||
boss_gyth() : CreatureScript("boss_gyth") { }
|
|
||||||
|
|
||||||
struct boss_gythAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_gythAI(Creature* creature) : BossAI(creature, DATA_GYTH) { }
|
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
instance->SetBossState(DATA_GYTH, NOT_STARTED);
|
||||||
{
|
summons.DespawnAll();
|
||||||
instance->SetBossState(DATA_GYTH, NOT_STARTED);
|
me->DespawnOrUnsummon();
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
events.Update(diff);
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_CORROSIVE_ACID:
|
case EVENT_SUMMONED_1:
|
||||||
DoCast(me, SPELL_CORROSIVE_ACID);
|
me->AddAura(SPELL_REND_MOUNTS, me);
|
||||||
events.ScheduleEvent(EVENT_CORROSIVE_ACID, 10s, 16s);
|
if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 40.0f))
|
||||||
|
portcullis->UseDoorOrButton();
|
||||||
|
events.ScheduleEvent(EVENT_SUMMONED_2, 2s);
|
||||||
break;
|
break;
|
||||||
case EVENT_FREEZE:
|
case EVENT_SUMMONED_2:
|
||||||
DoCast(me, SPELL_FREEZE);
|
me->GetMotionMaster()->MoveWaypoint(GYTH_PATH_1, false);
|
||||||
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DoMeleeAttackIfReady();
|
return;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
events.Update(diff);
|
||||||
{
|
|
||||||
return GetBlackrockSpireAI<boss_gythAI>(creature);
|
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()
|
void AddSC_boss_gyth()
|
||||||
{
|
{
|
||||||
new boss_gyth();
|
RegisterBlackrockSpireCreatureAI(boss_gyth);
|
||||||
RegisterSpellScript(spell_gyth_chromatic_protection);
|
RegisterSpellScript(spell_gyth_chromatic_protection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,70 +38,59 @@ enum Events
|
|||||||
|
|
||||||
const Position SummonLocation = { -167.9561f, -411.7844f, 76.23057f, 1.53589f };
|
const Position SummonLocation = { -167.9561f, -411.7844f, 76.23057f, 1.53589f };
|
||||||
|
|
||||||
class boss_halycon : public CreatureScript
|
struct boss_halycon : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_halycon(Creature* creature) : BossAI(creature, DATA_HALYCON) { }
|
||||||
boss_halycon() : CreatureScript("boss_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();
|
switch (eventId)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
case EVENT_REND:
|
||||||
{
|
DoCastVictim(SPELL_REND);
|
||||||
case EVENT_REND:
|
events.ScheduleEvent(EVENT_REND, 8s, 10s);
|
||||||
DoCastVictim(SPELL_REND);
|
break;
|
||||||
events.ScheduleEvent(EVENT_REND, 8s, 10s);
|
case EVENT_THRASH:
|
||||||
break;
|
DoCast(me, SPELL_THRASH);
|
||||||
case EVENT_THRASH:
|
break;
|
||||||
DoCast(me, SPELL_THRASH);
|
default:
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
};
|
DoMeleeAttackIfReady();
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetBlackrockSpireAI<boss_halyconAI>(creature);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_halycon()
|
void AddSC_boss_halycon()
|
||||||
{
|
{
|
||||||
new boss_halycon();
|
RegisterBlackrockSpireCreatureAI(boss_halycon);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,69 +31,58 @@ enum Events
|
|||||||
EVENT_KNOCK_AWAY = 2
|
EVENT_KNOCK_AWAY = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_highlord_omokk : public CreatureScript
|
struct boss_highlord_omokk : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_highlord_omokk(Creature* creature) : BossAI(creature, DATA_HIGHLORD_OMOKK) { }
|
||||||
boss_highlord_omokk() : CreatureScript("boss_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();
|
switch (eventId)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
case EVENT_FRENZY:
|
||||||
{
|
DoCastVictim(SPELL_FRENZY);
|
||||||
case EVENT_FRENZY:
|
events.ScheduleEvent(EVENT_FRENZY, 60s);
|
||||||
DoCastVictim(SPELL_FRENZY);
|
break;
|
||||||
events.ScheduleEvent(EVENT_FRENZY, 60s);
|
case EVENT_KNOCK_AWAY:
|
||||||
break;
|
DoCastVictim(SPELL_KNOCK_AWAY);
|
||||||
case EVENT_KNOCK_AWAY:
|
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s);
|
||||||
DoCastVictim(SPELL_KNOCK_AWAY);
|
break;
|
||||||
events.ScheduleEvent(EVENT_KNOCK_AWAY, 12s);
|
default:
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
};
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_highlordomokk()
|
void AddSC_boss_highlordomokk()
|
||||||
{
|
{
|
||||||
new boss_highlord_omokk();
|
RegisterBlackrockSpireCreatureAI(boss_highlord_omokk);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,145 +49,130 @@ enum EventPhase
|
|||||||
EVENT_PHASE_FIGHT = 2
|
EVENT_PHASE_FIGHT = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_lord_valthalak : public CreatureScript
|
struct boss_lord_valthalak : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_lord_valthalak(Creature* creature) : BossAI(creature, DATA_LORD_VALTHALAK) { }
|
||||||
boss_lord_valthalak() : CreatureScript("boss_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
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
{
|
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||||
BossAI::Reset();
|
|
||||||
|
|
||||||
me->SetReactState(REACT_AGGRESSIVE);
|
_frenzy40 = false;
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
_frenzy15 = false;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
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:
|
case PHASE_HUMAN:
|
||||||
spell = Acore::Containers::SelectRandomContainerElement(humanSpells);
|
spell = Acore::Containers::SelectRandomContainerElement(humanSpells);
|
||||||
if (spell == SPELL_REJUVENATION || spell == SPELL_HEALING_TOUCH)
|
if (spell == SPELL_REJUVENATION || spell == SPELL_HEALING_TOUCH)
|
||||||
{
|
|
||||||
DoCastSelf(spell);
|
DoCastSelf(spell);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
DoCastAOE(spell);
|
DoCastAOE(spell);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case PHASE_BEAR:
|
case PHASE_BEAR:
|
||||||
spell = Acore::Containers::SelectRandomContainerElement(bearSpells);
|
spell = Acore::Containers::SelectRandomContainerElement(bearSpells);
|
||||||
@@ -155,9 +151,7 @@ struct boss_mor_grayhoof : public BossAI
|
|||||||
{
|
{
|
||||||
CastRandomSpell(PHASE_BEAR);
|
CastRandomSpell(PHASE_BEAR);
|
||||||
if (context.GetRepeatCounter() <= 3)
|
if (context.GetRepeatCounter() <= 3)
|
||||||
{
|
|
||||||
context.Repeat();
|
context.Repeat();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (_phase == PHASE_BEAR && me->HealthBelowPct(50.f))
|
else if (_phase == PHASE_BEAR && me->HealthBelowPct(50.f))
|
||||||
@@ -170,9 +164,7 @@ struct boss_mor_grayhoof : public BossAI
|
|||||||
{
|
{
|
||||||
CastRandomSpell(PHASE_CAT);
|
CastRandomSpell(PHASE_CAT);
|
||||||
if (context.GetRepeatCounter() <= 3)
|
if (context.GetRepeatCounter() <= 3)
|
||||||
{
|
|
||||||
context.Repeat();
|
context.Repeat();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (_phase == PHASE_CAT && me->HealthBelowPct(25.f))
|
else if (_phase == PHASE_CAT && me->HealthBelowPct(25.f))
|
||||||
@@ -203,9 +195,7 @@ struct boss_mor_grayhoof : public BossAI
|
|||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
_scheduler.Update(diff, [this]
|
_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 SummonLocation1 = {-49.43f, -455.82f, 77.82f, 4.61f};
|
||||||
const Position SummonLocation2 = {-58.48f, -456.29f, 77.82f, 4.613f};
|
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(Creature* creature) : BossAI(creature, DATA_OVERLORD_WYRMTHALAK) { }
|
||||||
boss_overlord_wyrmthalak() : CreatureScript("boss_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();
|
Talk(CALL_HELP);
|
||||||
Summoned = false;
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||||
}
|
|
||||||
|
|
||||||
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 (Creature* warlord = me->SummonCreature(NPC_SPIRESTONE_WARLORD, SummonLocation1, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
warlord->AI()->AttackStart(target);
|
||||||
{
|
if (Creature* berserker = me->SummonCreature(NPC_SMOLDERTHORN_BERSERKER, SummonLocation2, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
||||||
if (Creature* warlord = me->SummonCreature(NPC_SPIRESTONE_WARLORD, SummonLocation1, TEMPSUMMON_TIMED_DESPAWN, 300 * IN_MILLISECONDS))
|
berserker->AI()->AttackStart(target);
|
||||||
warlord->AI()->AttackStart(target);
|
_summoned = true;
|
||||||
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()
|
void AddSC_boss_overlordwyrmthalak()
|
||||||
{
|
{
|
||||||
new boss_overlord_wyrmthalak();
|
RegisterBlackrockSpireCreatureAI(boss_overlord_wyrmthalak);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,241 +68,226 @@ enum Events
|
|||||||
EVENT_ENTER_COMBAT = 10
|
EVENT_ENTER_COMBAT = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_pyroguard_emberseer : public CreatureScript
|
struct boss_pyroguard_emberseer : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_pyroguard_emberseer(Creature* creature) : BossAI(creature, DATA_PYROGAURD_EMBERSEER) { }
|
||||||
boss_pyroguard_emberseer() : CreatureScript("boss_pyroguard_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);
|
case 1:
|
||||||
me->SetImmuneToPC(true);
|
events.ScheduleEvent(EVENT_PRE_FIGHT_1, 2s);
|
||||||
events.Reset();
|
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS);
|
||||||
// Apply auras on spawn and reset
|
break;
|
||||||
// DoCast(me, SPELL_FIRE_SHIELD_TRIGGER); // Need to find this in old DBC if possible
|
case 2:
|
||||||
me->RemoveAura(SPELL_EMBERSEER_FULL_STRENGTH);
|
// Close these two doors on Blackhand Incarcerators aggro
|
||||||
me->RemoveAura(SPELL_EMBERSEER_GROWING);
|
if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_EMBERSEER_IN)))
|
||||||
me->RemoveAura(SPELL_EMBERSEER_GROWING_TRIGGER);
|
if (door1->GetGoState() == GO_STATE_ACTIVE)
|
||||||
events.ScheduleEvent(EVENT_RESPAWN, 5s);
|
door1->SetGoState(GO_STATE_READY);
|
||||||
// Hack for missing trigger spell
|
if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetGuidData(GO_DOORS)))
|
||||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
if (door2->GetGoState() == GO_STATE_ACTIVE)
|
||||||
|
door2->SetGoState(GO_STATE_READY);
|
||||||
// Open doors on reset
|
break;
|
||||||
if (instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS)
|
case 3:
|
||||||
OpenDoors(false); // Opens 2 entrance doors
|
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.CancelEvent(EVENT_FIRE_SHIELD); // temporarily cancel fire shield to keep it from interrupting combat start
|
||||||
events.ScheduleEvent(EVENT_PRE_FIGHT_1, 2s);
|
|
||||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS);
|
// Schedule out the pre-combat scene
|
||||||
break;
|
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_1, 0s);
|
||||||
case 2:
|
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_2, 2s);
|
||||||
// Close these two doors on Blackhand Incarcerators aggro
|
events.ScheduleEvent(EVENT_ENTER_COMBAT, 5s);
|
||||||
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 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);
|
events.Update(diff);
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
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:
|
case EVENT_FIRE_SHIELD:
|
||||||
|
// #### Spell isn't doing any damage ??? ####
|
||||||
DoCast(me, SPELL_FIRE_SHIELD);
|
DoCast(me, SPELL_FIRE_SHIELD);
|
||||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||||
break;
|
break;
|
||||||
case EVENT_FIRENOVA:
|
case EVENT_PRE_ENTER_COMBAT_1:
|
||||||
DoCast(me, SPELL_FIRENOVA);
|
me->RemoveAura(SPELL_ENCAGED_EMBERSEER);
|
||||||
events.ScheduleEvent(EVENT_FIRENOVA, 6s);
|
me->RemoveAura(SPELL_FREEZE_ANIM);
|
||||||
|
me->CastSpell(me, SPELL_EMBERSEER_FULL_STRENGTH);
|
||||||
|
Talk(EMOTE_FREE_OF_BONDS);
|
||||||
break;
|
break;
|
||||||
case EVENT_FLAMEBUFFET:
|
case EVENT_PRE_ENTER_COMBAT_2:
|
||||||
DoCast(me, SPELL_FLAMEBUFFET);
|
Talk(YELL_FREE_OF_BONDS);
|
||||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 14s);
|
|
||||||
break;
|
break;
|
||||||
case EVENT_PYROBLAST:
|
case EVENT_ENTER_COMBAT:
|
||||||
DoCastRandomTarget(SPELL_PYROBLAST, 0, 100.0f);
|
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
events.ScheduleEvent(EVENT_PYROBLAST, 15s);
|
me->SetImmuneToPC(false);
|
||||||
|
DoZoneInCombat();
|
||||||
|
// re-enable fire shield
|
||||||
|
events.ScheduleEvent(EVENT_FIRE_SHIELD, 0s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DoMeleeAttackIfReady();
|
return;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
events.Update(diff);
|
||||||
{
|
|
||||||
return GetBlackrockSpireAI<boss_pyroguard_emberseerAI>(creature);
|
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
|
EMOTE_FLEE = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_blackhand_incarcerator : public CreatureScript
|
struct npc_blackhand_incarcerator : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_blackhand_incarcerator(Creature* creature) : ScriptedAI(creature)
|
||||||
npc_blackhand_incarcerator() : CreatureScript("npc_blackhand_incarcerator") { }
|
|
||||||
|
|
||||||
struct npc_blackhand_incarceratorAI : public ScriptedAI
|
|
||||||
{
|
{
|
||||||
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);
|
_events.Update(diff);
|
||||||
|
|
||||||
while (uint32 eventId = _events.ExecuteEvent())
|
while (uint32 eventId = _events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_STRIKE:
|
case EVENT_ENCAGED_EMBERSEER:
|
||||||
DoCastVictim(SPELL_STRIKE, true);
|
{
|
||||||
_events.ScheduleEvent(EVENT_STRIKE, 14s, 23s);
|
if (me->GetPositionX() == me->GetHomePosition().GetPositionX())
|
||||||
break;
|
if (!me->HasAura(SPELL_ENCAGE_EMBERSEER))
|
||||||
case EVENT_ENCAGE:
|
if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true))
|
||||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 100, true), EVENT_ENCAGE, true);
|
DoCast(Emberseer, SPELL_ENCAGE_EMBERSEER);
|
||||||
_events.ScheduleEvent(EVENT_ENCAGE, 6s, 12s);
|
break;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
_events.Update(diff);
|
||||||
EventMap _events;
|
|
||||||
bool _fleedForAssistance;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
while (uint32 eventId = _events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
return GetBlackrockSpireAI<npc_blackhand_incarceratorAI>(creature);
|
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()
|
void AddSC_boss_pyroguard_emberseer()
|
||||||
{
|
{
|
||||||
new boss_pyroguard_emberseer();
|
RegisterBlackrockSpireCreatureAI(boss_pyroguard_emberseer);
|
||||||
new npc_blackhand_incarcerator();
|
RegisterBlackrockSpireCreatureAI(npc_blackhand_incarcerator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,16 +87,12 @@ struct boss_quartermaster_zigris : public BossAI
|
|||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
@@ -135,9 +131,7 @@ struct boss_quartermaster_zigris : public BossAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
|
|||||||
@@ -99,346 +99,327 @@ enum Events
|
|||||||
EVENT_MORTAL_STRIKE = 32,
|
EVENT_MORTAL_STRIKE = 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_rend_blackhand : public CreatureScript
|
struct boss_rend_blackhand : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_rend_blackhand(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND) { }
|
||||||
boss_rend_blackhand() : CreatureScript("boss_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();
|
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PREPARATION);
|
||||||
|
me->SetImmuneToAll(false);
|
||||||
if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS)
|
return;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
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);
|
if (!_gythEvent)
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
_gythEvent = true;
|
||||||
}
|
|
||||||
|
|
||||||
BossAI::SummonedCreatureDespawn(creature);
|
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f))
|
||||||
}
|
|
||||||
|
|
||||||
void SetData(uint32 type, uint32 data) override
|
|
||||||
{
|
|
||||||
if (type == AREATRIGGER && data == AREATRIGGER_BLACKROCK_STADIUM)
|
|
||||||
{
|
|
||||||
if (!gythEvent)
|
|
||||||
{
|
{
|
||||||
gythEvent = true;
|
if (!victor->IsAlive())
|
||||||
|
victor->Respawn(true);
|
||||||
|
|
||||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f))
|
_victorGUID = victor->GetGUID();
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
case 6:
|
break;
|
||||||
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);
|
events.Update(diff);
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_WHIRLWIND:
|
case EVENT_START_1:
|
||||||
DoCast(SPELL_WHIRLWIND);
|
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, IN_PROGRESS);
|
||||||
events.ScheduleEvent(EVENT_WHIRLWIND, 13s, 18s);
|
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;
|
break;
|
||||||
case EVENT_CLEAVE:
|
case EVENT_START_2:
|
||||||
DoCastVictim(SPELL_CLEAVE);
|
events.ScheduleEvent(EVENT_TURN_TO_PLAYER, 0ms);
|
||||||
events.ScheduleEvent(EVENT_CLEAVE, 10s, 14s);
|
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||||
|
victor->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
|
||||||
|
events.ScheduleEvent(EVENT_START_3, 4s);
|
||||||
break;
|
break;
|
||||||
case EVENT_MORTAL_STRIKE:
|
case EVENT_START_3:
|
||||||
DoCastVictim(SPELL_MORTAL_STRIKE);
|
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 14s, 18s);
|
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;
|
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);
|
switch (eventId)
|
||||||
|
|
||||||
if (GameObject* waveDoor = me->GetMap()->GetGameObject(waveDoorGUID))
|
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
private:
|
|
||||||
bool gythEvent;
|
|
||||||
uint8 _currentWave;
|
|
||||||
ObjectGuid victorGUID;
|
|
||||||
ObjectGuid waveDoorGUID;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetBlackrockSpireAI<boss_rend_blackhandAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void AddSC_boss_rend_blackhand()
|
||||||
{
|
{
|
||||||
new boss_rend_blackhand();
|
RegisterBlackrockSpireCreatureAI(boss_rend_blackhand);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,211 +38,178 @@ enum Says
|
|||||||
SAY_SUMMON = 0,
|
SAY_SUMMON = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_rookery_hatcher : public CreatureScript
|
struct npc_rookery_hatcher : public CreatureAI
|
||||||
{
|
{
|
||||||
public:
|
npc_rookery_hatcher(Creature* creature) : CreatureAI(creature) {}
|
||||||
npc_rookery_hatcher() : CreatureScript("npc_rookery_hatcher") {}
|
|
||||||
|
|
||||||
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;
|
std::list<GameObject*> nearbyEggs;
|
||||||
GameObject* targetEgg;
|
float tempDist = 20;
|
||||||
Position targetPosition;
|
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();
|
if (!whelp->IsInCombat())
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
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
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
return;
|
||||||
BossAI::InitializeAI();
|
events.Update(diff);
|
||||||
Talk(SAY_SUMMON);
|
|
||||||
DoZoneInCombat(nullptr, 100.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
|
||||||
_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)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case SPELL_WAR_STOMP:
|
case SPELL_HATCH_EGG:
|
||||||
DoCastVictim(SPELL_WAR_STOMP);
|
if (!targetEgg) // no target, try to find one
|
||||||
events.ScheduleEvent(SPELL_WAR_STOMP, 17s, 20s);
|
{
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
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())
|
me->StopMovingOnCurrentPos();
|
||||||
{
|
me->SetFacingToObject(targetEgg);
|
||||||
resetTimer -= diff;
|
targetPosition = me->GetPosition();
|
||||||
if (resetTimer < diff)
|
DoCast(SPELL_HATCH_EGG);
|
||||||
{
|
targetEgg = nullptr;
|
||||||
instance->SetData(DATA_SOLAKAR_FLAMEWREATH, FAIL);
|
events.ScheduleEvent(SPELL_HATCH_EGG, 6s, 8s);
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resetTimer = 10000;
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
ExecuteEvent(eventId);
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
};
|
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()
|
void AddSC_boss_solakar_flamewreath()
|
||||||
{
|
{
|
||||||
new boss_solakar_flamewreath();
|
RegisterBlackrockSpireCreatureAI(boss_solakar_flamewreath);
|
||||||
new npc_rookery_hatcher();
|
RegisterBlackrockSpireCreatureAI(npc_rookery_hatcher);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,185 +90,152 @@ private:
|
|||||||
// Used to make Hodir disengage whenever he leaves his room
|
// Used to make Hodir disengage whenever he leaves his room
|
||||||
constexpr static float FirewalPositionY = -505.f;
|
constexpr static float FirewalPositionY = -505.f;
|
||||||
|
|
||||||
class boss_the_beast : public CreatureScript
|
struct boss_the_beast : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_the_beast(Creature* creature) : BossAI(creature, DATA_THE_BEAST), _beastReached(false), _orcYelled(false) {}
|
||||||
boss_the_beast() : CreatureScript("boss_the_beast") { }
|
|
||||||
|
|
||||||
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();
|
case DATA_BEAST_ROOM:
|
||||||
|
|
||||||
if (_beastReached)
|
|
||||||
{
|
{
|
||||||
me->GetMotionMaster()->MoveWaypoint(BEAST_MOVEMENT_ID, true);
|
if (!_orcYelled)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (_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();
|
if (!yelled)
|
||||||
}
|
|
||||||
|
|
||||||
//! 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)
|
yelled = true;
|
||||||
{
|
orc->AI()->Talk(SAY_BLACKHAND_DOOMED);
|
||||||
yelled = true;
|
|
||||||
orc->AI()->Talk(SAY_BLACKHAND_DOOMED);
|
|
||||||
}
|
|
||||||
|
|
||||||
orc->m_Events.AddEventAtOffset(new OrcMoveEvent(orc), 3s);
|
|
||||||
orc->m_Events.AddEventAtOffset(new OrcDeathEvent(orc), 9s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
// There is a chance player logged in between areatriggers (realm crash or restart)
|
||||||
// executing part of script which happens when player enters boss room
|
// 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)
|
// otherwise we will see weird behaviour when someone steps on the previous areatrigger (dead mob yelling/moving)
|
||||||
SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (me->GetPositionY() > FirewalPositionY)
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
EnterEvadeMode();
|
||||||
{
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (me->GetPositionY() > FirewalPositionY)
|
events.Update(diff);
|
||||||
{
|
|
||||||
EnterEvadeMode();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
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()
|
DoMeleeAttackIfReady();
|
||||||
{
|
}
|
||||||
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:
|
void FindNearbyOrcs()
|
||||||
bool _beastReached;
|
{
|
||||||
bool _orcYelled;
|
std::list<Creature*> temp;
|
||||||
GuidVector _nearbyOrcsGUIDs;
|
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)
|
//! 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
|
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
||||||
{
|
{
|
||||||
if (player->IsGameMaster())
|
if (player->IsGameMaster())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (InstanceScript* instance = player->GetInstanceScript())
|
if (InstanceScript* instance = player->GetInstanceScript())
|
||||||
{
|
{
|
||||||
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
|
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
|
||||||
{
|
|
||||||
beast->AI()->SetData(DATA_BEAST_REACHED, DATA_BEAST_REACHED);
|
beast->AI()->SetData(DATA_BEAST_REACHED, DATA_BEAST_REACHED);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -306,16 +269,12 @@ public:
|
|||||||
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
||||||
{
|
{
|
||||||
if (player->IsGameMaster())
|
if (player->IsGameMaster())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (InstanceScript* instance = player->GetInstanceScript())
|
if (InstanceScript* instance = player->GetInstanceScript())
|
||||||
{
|
{
|
||||||
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
|
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
|
||||||
{
|
|
||||||
beast->AI()->SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
beast->AI()->SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -326,7 +285,7 @@ public:
|
|||||||
|
|
||||||
void AddSC_boss_thebeast()
|
void AddSC_boss_thebeast()
|
||||||
{
|
{
|
||||||
new boss_the_beast();
|
RegisterBlackrockSpireCreatureAI(boss_the_beast);
|
||||||
new at_trigger_the_beast_movement();
|
new at_trigger_the_beast_movement();
|
||||||
new at_the_beast_room();
|
new at_the_beast_room();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,82 +40,67 @@ enum Events
|
|||||||
EVENT_INTIMIDATING_ROAR = 3
|
EVENT_INTIMIDATING_ROAR = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_urok_doomhowl : public CreatureScript
|
struct boss_urok_doomhowl : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_urok_doomhowl(Creature* creature) : BossAI(creature, DATA_UROK_DOOMHOWL) {}
|
||||||
boss_urok_doomhowl() : CreatureScript("boss_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
|
if (GameObject* challenge = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_CHALLENGE)))
|
||||||
{
|
challenge->Delete();
|
||||||
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)))
|
if (GameObject* pile = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_PILE)))
|
||||||
{
|
pile->DespawnOrUnsummon(0ms, Seconds(MONTH));
|
||||||
challenge->Delete();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (GameObject* pile = instance->instance->GetGameObject(instance->GetGuidData(GO_UROK_PILE)))
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
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()
|
void AddSC_boss_urok_doomhowl()
|
||||||
{
|
{
|
||||||
new boss_urok_doomhowl();
|
RegisterBlackrockSpireCreatureAI(boss_urok_doomhowl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,86 +55,75 @@ enum EventGroups
|
|||||||
GROUP_WARMASTER
|
GROUP_WARMASTER
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_warmaster_voone : public CreatureScript
|
struct boss_warmaster_voone : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_warmaster_voone(Creature* creature) : BossAI(creature, DATA_WARMASTER_VOONE) { }
|
||||||
boss_warmaster_voone() : CreatureScript("boss_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
|
events.SetPhase(PHASE_BRAWLER);
|
||||||
{
|
events.ScheduleEvent(EVENT_THRASH, 3s, GROUP_BRAWLER, PHASE_BRAWLER);
|
||||||
_JustEngagedWith();
|
events.ScheduleEvent(EVENT_THROW_AXE, 1s, GROUP_BRAWLER, PHASE_BRAWLER);
|
||||||
|
}
|
||||||
|
|
||||||
events.SetPhase(PHASE_BRAWLER);
|
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||||
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
|
|
||||||
{
|
{
|
||||||
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()
|
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 RegisterBlackwingLairCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackwingLairAI)
|
||||||
|
#define RegisterBlackwingLairGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetBlackwingLairAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -58,196 +58,157 @@ enum Actions
|
|||||||
ACTION_DISARMED = 1
|
ACTION_DISARMED = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_broodlord : public CreatureScript
|
struct boss_broodlord : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_broodlord(Creature* creature) : BossAI(creature, DATA_BROODLORD_LASHLAYER) { }
|
||||||
boss_broodlord() : CreatureScript("boss_broodlord") { }
|
|
||||||
|
|
||||||
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
|
events.ScheduleEvent(EVENT_CLEAVE, 8s);
|
||||||
{
|
events.ScheduleEvent(EVENT_BLASTWAVE, 12s);
|
||||||
BossAI::JustEngagedWith(who);
|
events.ScheduleEvent(EVENT_MORTALSTRIKE, 20s);
|
||||||
Talk(SAY_AGGRO);
|
events.ScheduleEvent(EVENT_KNOCKBACK, 30s);
|
||||||
|
events.ScheduleEvent(EVENT_CHECK, 1s);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class go_suppression_device : public GameObjectScript
|
void JustDied(Unit* /*killer*/) override
|
||||||
{
|
{
|
||||||
public:
|
_JustDied();
|
||||||
go_suppression_device() : GameObjectScript("go_suppression_device") { }
|
|
||||||
|
|
||||||
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
|
case EVENT_CLEAVE:
|
||||||
go->SetLootState(GO_READY);
|
DoCastVictim(SPELL_CLEAVE);
|
||||||
[[fallthrough]];
|
events.ScheduleEvent(EVENT_CLEAVE, 7s);
|
||||||
case GO_ACTIVATED:
|
break;
|
||||||
go->AI()->DoAction(ACTION_DISARMED);
|
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;
|
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) { }
|
Deactivate();
|
||||||
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_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
|
class spell_suppression_aura : public SpellScript
|
||||||
@@ -271,7 +232,7 @@ class spell_suppression_aura : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_broodlord()
|
void AddSC_boss_broodlord()
|
||||||
{
|
{
|
||||||
new boss_broodlord();
|
RegisterBlackwingLairCreatureAI(boss_broodlord);
|
||||||
new go_suppression_device();
|
RegisterBlackwingLairGameObjectAI(go_suppression_device);
|
||||||
RegisterSpellScript(spell_suppression_aura);
|
RegisterSpellScript(spell_suppression_aura);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,203 +70,171 @@ enum Misc
|
|||||||
|
|
||||||
Position const homePos = { -7491.1587f, -1069.718f, 476.59094, 476.59094f };
|
Position const homePos = { -7491.1587f, -1069.718f, 476.59094, 476.59094f };
|
||||||
|
|
||||||
class boss_chromaggus : public CreatureScript
|
struct boss_chromaggus : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_chromaggus(Creature* creature) : BossAI(creature, DATA_CHROMAGGUS)
|
||||||
boss_chromaggus() : CreatureScript("boss_chromaggus") { }
|
|
||||||
|
|
||||||
struct boss_chromaggusAI : public BossAI
|
|
||||||
{
|
{
|
||||||
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();
|
_playerGUID = guid;
|
||||||
|
|
||||||
// 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.
|
// 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;
|
switch (eventId)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
_playerGUID = guid;
|
case EVENT_SHIMMER:
|
||||||
// Hack fix: This is here to prevent him from being pulled from the floor underneath, remove it once maps are fixed.
|
{
|
||||||
me->SetImmuneToAll(false);
|
// 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))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
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:
|
// Enrage if not already enraged and below 20%
|
||||||
std::list<uint32> _breathSpells;
|
if (!Enraged && HealthBelowPct(20))
|
||||||
bool Enraged;
|
{
|
||||||
ObjectGuid _playerGUID;
|
DoCast(me, SPELL_ENRAGE);
|
||||||
};
|
Enraged = true;
|
||||||
|
}
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
DoMeleeAttackIfReady();
|
||||||
{
|
|
||||||
return GetBlackwingLairAI<boss_chromaggusAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
|
||||||
go_chromaggus_lever() : GameObjectScript("go_chromaggus_lever") { }
|
|
||||||
|
|
||||||
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()) { }
|
if (_instance->GetBossState(DATA_CHROMAGGUS) != DONE && _instance->GetBossState(DATA_CHROMAGGUS) != IN_PROGRESS)
|
||||||
|
|
||||||
bool GossipHello(Player* player, bool reportUse) override
|
|
||||||
{
|
{
|
||||||
if (reportUse)
|
if (Creature* creature = _instance->GetCreature(DATA_CHROMAGGUS))
|
||||||
{
|
{
|
||||||
if (_instance->GetBossState(DATA_CHROMAGGUS) != DONE && _instance->GetBossState(DATA_CHROMAGGUS) != IN_PROGRESS)
|
creature->SetHomePosition(homePos);
|
||||||
{
|
creature->GetMotionMaster()->MoveWaypoint(creature->GetEntry() * 10, false);
|
||||||
if (Creature* creature = _instance->GetCreature(DATA_CHROMAGGUS))
|
creature->AI()->SetGUID(player->GetGUID(), GUID_LEVER_USER);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (GameObject* go = _instance->GetGameObject(DATA_GO_CHROMAGGUS_DOOR))
|
||||||
|
_instance->HandleGameObject(ObjectGuid::Empty, true, go);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
me->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE | GO_FLAG_IN_USE);
|
||||||
InstanceScript* _instance;
|
me->SetGoState(GO_STATE_ACTIVE);
|
||||||
};
|
|
||||||
|
|
||||||
GameObjectAI* GetAI(GameObject* go) const override
|
|
||||||
{
|
|
||||||
return GetBlackwingLairAI<go_chromaggus_leverAI>(go);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
InstanceScript* _instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ElementalShieldSpells
|
enum ElementalShieldSpells
|
||||||
@@ -306,9 +274,7 @@ class spell_gen_elemental_shield : public SpellScript
|
|||||||
if (Unit* caster = GetCaster())
|
if (Unit* caster = GetCaster())
|
||||||
{
|
{
|
||||||
for (uint32 spell = SPELL_FIRE_ELEMENTAL_SHIELD; spell <= SPELL_ARCANE_ELEMENTAL_SHIELD; ++spell)
|
for (uint32 spell = SPELL_FIRE_ELEMENTAL_SHIELD; spell <= SPELL_ARCANE_ELEMENTAL_SHIELD; ++spell)
|
||||||
{
|
|
||||||
caster->RemoveAurasDueToSpell(spell);
|
caster->RemoveAurasDueToSpell(spell);
|
||||||
}
|
|
||||||
|
|
||||||
caster->CastSpell(caster, SPELL_FIRE_ELEMENTAL_SHIELD + urand(0, 4), true);
|
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())
|
if (Unit* caster = GetCaster())
|
||||||
{
|
{
|
||||||
for (uint32 spell = SPELL_RED_BROOD_POWER; spell <= SPELL_GREEN_BROOD_POWER; ++spell)
|
for (uint32 spell = SPELL_RED_BROOD_POWER; spell <= SPELL_GREEN_BROOD_POWER; ++spell)
|
||||||
{
|
|
||||||
caster->RemoveAurasDueToSpell(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);
|
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()
|
void AddSC_boss_chromaggus()
|
||||||
{
|
{
|
||||||
new boss_chromaggus();
|
RegisterBlackwingLairCreatureAI(boss_chromaggus);
|
||||||
new go_chromaggus_lever();
|
RegisterBlackwingLairGameObjectAI(go_chromaggus_lever);
|
||||||
RegisterSpellScript(spell_gen_elemental_shield);
|
RegisterSpellScript(spell_gen_elemental_shield);
|
||||||
RegisterSpellScript(spell_gen_brood_power);
|
RegisterSpellScript(spell_gen_brood_power);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,82 +33,69 @@ enum Events
|
|||||||
EVENT_SHADOWOFEBONROC = 3
|
EVENT_SHADOWOFEBONROC = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_ebonroc : public CreatureScript
|
struct boss_ebonroc : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_ebonroc(Creature* creature) : BossAI(creature, DATA_EBONROC) { }
|
||||||
boss_ebonroc() : CreatureScript("boss_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))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
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
|
DoMeleeAttackIfReady();
|
||||||
{
|
|
||||||
return GetBlackwingLairAI<boss_ebonrocAI>(creature);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_ebonroc()
|
void AddSC_boss_ebonroc()
|
||||||
{
|
{
|
||||||
new boss_ebonroc();
|
RegisterBlackwingLairCreatureAI(boss_ebonroc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,69 +33,58 @@ enum Events
|
|||||||
EVENT_FLAMEBUFFET = 3
|
EVENT_FLAMEBUFFET = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_firemaw : public CreatureScript
|
struct boss_firemaw : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_firemaw(Creature* creature) : BossAI(creature, DATA_FIREMAW) { }
|
||||||
boss_firemaw() : CreatureScript("boss_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);
|
switch (eventId)
|
||||||
|
{
|
||||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
case EVENT_SHADOWFLAME:
|
||||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
DoCastVictim(SPELL_SHADOWFLAME);
|
||||||
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5s);
|
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||||
}
|
break;
|
||||||
|
case EVENT_WINGBUFFET:
|
||||||
void UpdateAI(uint32 diff) override
|
DoCastVictim(SPELL_WINGBUFFET);
|
||||||
{
|
if (DoGetThreat(me->GetVictim()))
|
||||||
if (!UpdateVictim())
|
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||||
return;
|
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||||
|
break;
|
||||||
events.Update(diff);
|
case EVENT_FLAMEBUFFET:
|
||||||
|
DoCastVictim(SPELL_FLAMEBUFFET);
|
||||||
|
events.ScheduleEvent(EVENT_FLAMEBUFFET, 5s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
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
|
DoMeleeAttackIfReady();
|
||||||
{
|
|
||||||
return GetBlackwingLairAI<boss_firemawAI>(creature);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_firemaw()
|
void AddSC_boss_firemaw()
|
||||||
{
|
{
|
||||||
new boss_firemaw();
|
RegisterBlackwingLairCreatureAI(boss_firemaw);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,70 +38,59 @@ enum Events
|
|||||||
EVENT_FRENZY = 3
|
EVENT_FRENZY = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_flamegor : public CreatureScript
|
struct boss_flamegor : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_flamegor(Creature* creature) : BossAI(creature, DATA_FLAMEGOR) { }
|
||||||
boss_flamegor() : CreatureScript("boss_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);
|
switch (eventId)
|
||||||
|
{
|
||||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 18s);
|
case EVENT_SHADOWFLAME:
|
||||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
DoCastVictim(SPELL_SHADOWFLAME);
|
||||||
events.ScheduleEvent(EVENT_FRENZY, 10s);
|
events.ScheduleEvent(EVENT_SHADOWFLAME, 15s, 25s);
|
||||||
}
|
break;
|
||||||
|
case EVENT_WINGBUFFET:
|
||||||
void UpdateAI(uint32 diff) override
|
DoCastVictim(SPELL_WINGBUFFET);
|
||||||
{
|
if (DoGetThreat(me->GetVictim()))
|
||||||
if (!UpdateVictim())
|
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||||
return;
|
events.ScheduleEvent(EVENT_WINGBUFFET, 30s);
|
||||||
|
break;
|
||||||
events.Update(diff);
|
case EVENT_FRENZY:
|
||||||
|
Talk(EMOTE_FRENZY);
|
||||||
|
DoCast(me, SPELL_FRENZY);
|
||||||
|
events.ScheduleEvent(EVENT_FRENZY, 8s, 10s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
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
|
DoMeleeAttackIfReady();
|
||||||
{
|
|
||||||
return GetBlackwingLairAI<boss_flamegorAI>(creature);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_flamegor()
|
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
|
bool operator()(Unit const* target) const
|
||||||
{
|
{
|
||||||
if (!_me || !target || !target->IsPlayer())
|
if (!_me || !target || !target->IsPlayer())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (target->getClass() != _targetClass)
|
if (target->getClass() != _targetClass)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -231,304 +227,291 @@ private:
|
|||||||
uint8 _targetClass;
|
uint8 _targetClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_victor_nefarius : public CreatureScript
|
struct boss_victor_nefarius : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_victor_nefarius(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
|
||||||
boss_victor_nefarius() : CreatureScript("boss_victor_nefarius") { }
|
|
||||||
|
|
||||||
struct boss_victor_nefariusAI : public BossAI
|
|
||||||
{
|
{
|
||||||
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 = nefarianDrakonidSpawners[0];
|
||||||
_nefarianRightTunnel = instance->GetData(DATA_NEFARIAN_RIGHT_TUNNEL);
|
_nefarianLeftTunnel = nefarianDrakonidSpawners[1];
|
||||||
|
|
||||||
if (!_nefarianLeftTunnel || !_nefarianRightTunnel)
|
// save it to instance
|
||||||
{
|
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
|
||||||
// Victor Nefarius weekly mechanic drakonid spawn
|
instance->SetData(DATA_NEFARIAN_RIGHT_TUNNEL, _nefarianRightTunnel);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Initialize()
|
void Initialize()
|
||||||
|
{
|
||||||
|
_killedAdds = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
|
||||||
|
if (me->GetMapId() == MAP_BLACKWING_LAIR)
|
||||||
{
|
{
|
||||||
KilledAdds = 0;
|
if (Creature* nefarian = me->FindNearestCreature(NPC_NEFARIAN, 1000.0f, true))
|
||||||
}
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
Initialize();
|
|
||||||
|
|
||||||
if (me->GetMapId() == MAP_BLACKWING_LAIR)
|
|
||||||
{
|
{
|
||||||
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.
|
nefarian->DespawnOrUnsummon();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
std::list<GameObject*> drakonidBones;
|
||||||
|
me->GetGameObjectListWithEntryInGrid(drakonidBones, GO_DRAKONID_BONES, DEFAULT_VISIBILITY_INSTANCE);
|
||||||
|
for (auto const& bones : drakonidBones)
|
||||||
{
|
{
|
||||||
_Reset();
|
bones->DespawnOrUnsummon();
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
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();
|
_Reset();
|
||||||
events.ScheduleEvent(EVENT_PATH_2, 9s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 1 && data == 2)
|
me->SetVisible(true);
|
||||||
events.ScheduleEvent(EVENT_SUCCESS_1, 5s);
|
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())
|
_killedAdds++;
|
||||||
{
|
|
||||||
events.Update(diff);
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
if (_killedAdds == MAX_DRAKONID_KILLED)
|
||||||
|
{
|
||||||
|
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
|
||||||
{
|
{
|
||||||
switch (eventId)
|
nefarian->setActive(true);
|
||||||
{
|
nefarian->SetCanFly(true);
|
||||||
case EVENT_PATH_2:
|
nefarian->SetDisableGravity(true);
|
||||||
me->GetMotionMaster()->MoveWaypoint(NEFARIUS_PATH_2, false);
|
nefarian->GetMotionMaster()->MoveWaypoint(NEFARIAN_PATH, 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Only do this if we haven't spawned nefarian yet
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
if (UpdateVictim() && KilledAdds <= MAX_DRAKONID_KILLED)
|
|
||||||
{
|
{
|
||||||
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))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
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
|
struct boss_nefarian : public BossAI
|
||||||
@@ -545,12 +528,8 @@ struct boss_nefarian : public BossAI
|
|||||||
{
|
{
|
||||||
_Reset();
|
_Reset();
|
||||||
if (Creature* victor = me->FindNearestCreature(NPC_VICTOR_NEFARIUS, 200.f, true))
|
if (Creature* victor = me->FindNearestCreature(NPC_VICTOR_NEFARIUS, 200.f, true))
|
||||||
{
|
|
||||||
if (victor->AI())
|
if (victor->AI())
|
||||||
{
|
|
||||||
victor->AI()->DoAction(ACTION_RESET);
|
victor->AI()->DoAction(ACTION_RESET);
|
||||||
}
|
|
||||||
}
|
|
||||||
me->DespawnOrUnsummon();
|
me->DespawnOrUnsummon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,9 +557,7 @@ struct boss_nefarian : public BossAI
|
|||||||
void KilledUnit(Unit* victim) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
if (rand32() % 5)
|
if (rand32() % 5)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Talk(SAY_SLAY, victim);
|
Talk(SAY_SLAY, victim);
|
||||||
}
|
}
|
||||||
@@ -588,14 +565,10 @@ struct boss_nefarian : public BossAI
|
|||||||
void MovementInform(uint32 type, uint32 id) override
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
{
|
{
|
||||||
if (type != WAYPOINT_MOTION_TYPE)
|
if (type != WAYPOINT_MOTION_TYPE)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 4)
|
if (id == 4)
|
||||||
{
|
|
||||||
Talk(SAY_INTRO);
|
Talk(SAY_INTRO);
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 6)
|
if (id == 6)
|
||||||
{
|
{
|
||||||
@@ -617,9 +590,7 @@ struct boss_nefarian : public BossAI
|
|||||||
me->SetReactState(REACT_AGGRESSIVE);
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
DoZoneInCombat();
|
DoZoneInCombat();
|
||||||
if (me->GetVictim())
|
if (me->GetVictim())
|
||||||
{
|
|
||||||
AttackStart(me->GetVictim());
|
AttackStart(me->GetVictim());
|
||||||
}
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_SHADOWFLAME, 12s);
|
events.ScheduleEvent(EVENT_SHADOWFLAME, 12s);
|
||||||
events.ScheduleEvent(EVENT_FEAR, 25s, 35s);
|
events.ScheduleEvent(EVENT_FEAR, 25s, 35s);
|
||||||
@@ -633,16 +604,12 @@ struct boss_nefarian : public BossAI
|
|||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
@@ -671,16 +638,10 @@ struct boss_nefarian : public BossAI
|
|||||||
break;
|
break;
|
||||||
case EVENT_CLASSCALL:
|
case EVENT_CLASSCALL:
|
||||||
if (classesPresent.empty())
|
if (classesPresent.empty())
|
||||||
{
|
|
||||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||||
{
|
|
||||||
if (Unit* victim = ref->GetVictim())
|
if (Unit* victim = ref->GetVictim())
|
||||||
{
|
|
||||||
if (victim->IsPlayer())
|
if (victim->IsPlayer())
|
||||||
classesPresent.insert(victim->getClass());
|
classesPresent.insert(victim->getClass());
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 targetClass = Acore::Containers::SelectRandomContainerElement(classesPresent);
|
uint8 targetClass = Acore::Containers::SelectRandomContainerElement(classesPresent);
|
||||||
|
|
||||||
@@ -731,9 +692,7 @@ struct boss_nefarian : public BossAI
|
|||||||
me->GetMap()->DoForAllPlayers([&](Player* p)
|
me->GetMap()->DoForAllPlayers([&](Player* p)
|
||||||
{
|
{
|
||||||
if (!p->IsGameMaster())
|
if (!p->IsGameMaster())
|
||||||
{
|
|
||||||
me->CastSpell(p, SPELL_DEATH_KNIGHT, true);
|
me->CastSpell(p, SPELL_DEATH_KNIGHT, true);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -745,9 +704,7 @@ struct boss_nefarian : public BossAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
@@ -783,9 +740,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||||||
{
|
{
|
||||||
me->AddUnitState(UNIT_STATE_ROOT);
|
me->AddUnitState(UNIT_STATE_ROOT);
|
||||||
if (!me->HasAura(SPELL_ROOT_SELF))
|
if (!me->HasAura(SPELL_ROOT_SELF))
|
||||||
{
|
|
||||||
me->AddAura(SPELL_ROOT_SELF, me);
|
me->AddAura(SPELL_ROOT_SELF, me);
|
||||||
}
|
|
||||||
|
|
||||||
me->AddAura(AURA_AVOIDANCE, me);
|
me->AddAura(AURA_AVOIDANCE, me);
|
||||||
scheduler.CancelAll();
|
scheduler.CancelAll();
|
||||||
@@ -809,9 +764,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!spellId)
|
if (!spellId)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint32> mobsEntries =
|
std::vector<uint32> mobsEntries =
|
||||||
{
|
{
|
||||||
@@ -835,25 +788,19 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||||||
tmpMobList.pop_front();
|
tmpMobList.pop_front();
|
||||||
|
|
||||||
if (!curr->IsAlive())
|
if (!curr->IsAlive())
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (apply && me->IsAlive())
|
if (apply && me->IsAlive())
|
||||||
{
|
{
|
||||||
if (me->IsWithinDistInMap(curr, 40.f))
|
if (me->IsWithinDistInMap(curr, 40.f))
|
||||||
{
|
{
|
||||||
if (!curr->HasAura(spellId))
|
if (!curr->HasAura(spellId))
|
||||||
{
|
|
||||||
curr->AddAura(spellId, curr);
|
curr->AddAura(spellId, curr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (curr->HasAura(spellId))
|
if (curr->HasAura(spellId))
|
||||||
{
|
|
||||||
curr->RemoveAurasDueToSpell(spellId);
|
curr->RemoveAurasDueToSpell(spellId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -899,9 +846,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||||||
void JustDied(Unit* /*killer*/) override
|
void JustDied(Unit* /*killer*/) override
|
||||||
{
|
{
|
||||||
if (me->GetEntry() != NPC_TOTEM_C_FIRE_NOVA)
|
if (me->GetEntry() != NPC_TOTEM_C_FIRE_NOVA)
|
||||||
{
|
|
||||||
SetAura(false);
|
SetAura(false);
|
||||||
}
|
|
||||||
|
|
||||||
scheduler.CancelAll();
|
scheduler.CancelAll();
|
||||||
}
|
}
|
||||||
@@ -909,9 +854,7 @@ struct npc_corrupted_totem : public ScriptedAI
|
|||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
scheduler.Update(diff);
|
scheduler.Update(diff);
|
||||||
}
|
}
|
||||||
@@ -952,9 +895,7 @@ struct npc_drakonid_spawner : public ScriptedAI
|
|||||||
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
|
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
|
||||||
{
|
{
|
||||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _owner))
|
if (Creature* victor = ObjectAccessor::GetCreature(*me, _owner))
|
||||||
{
|
|
||||||
victor->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
|
victor->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
|
||||||
}
|
|
||||||
|
|
||||||
ObjectGuid summonGuid = summon->GetGUID();
|
ObjectGuid summonGuid = summon->GetGUID();
|
||||||
|
|
||||||
@@ -1002,15 +943,11 @@ class spell_class_call_handler : public SpellScript
|
|||||||
{
|
{
|
||||||
Player const* player = target->ToPlayer();
|
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
|
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;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
auto it = classCallSpells.find(spellInfo->Id);
|
auto it = classCallSpells.find(spellInfo->Id);
|
||||||
if (it != classCallSpells.end()) // should never happen but only to be sure.
|
if (it != classCallSpells.end()) // should never happen but only to be sure.
|
||||||
{
|
|
||||||
return target->ToPlayer()->getClass() != it->second;
|
return target->ToPlayer()->getClass() != it->second;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@@ -1022,9 +959,7 @@ class spell_class_call_handler : public SpellScript
|
|||||||
Unit* caster = GetCaster();
|
Unit* caster = GetCaster();
|
||||||
Unit* target = GetHitUnit();
|
Unit* target = GetHitUnit();
|
||||||
if (!caster || !target)
|
if (!caster || !target)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Position tp = caster->GetFirstCollisionPosition(5.f, 0.f);
|
Position tp = caster->GetFirstCollisionPosition(5.f, 0.f);
|
||||||
target->NearTeleportTo(tp.GetPositionX(), tp.GetPositionY(), tp.GetPositionZ(), tp.GetOrientation());
|
target->NearTeleportTo(tp.GetPositionX(), tp.GetPositionY(), tp.GetPositionZ(), tp.GetOrientation());
|
||||||
@@ -1033,9 +968,7 @@ class spell_class_call_handler : public SpellScript
|
|||||||
void HandleOnHitWarlock()
|
void HandleOnHitWarlock()
|
||||||
{
|
{
|
||||||
if (Unit* target = GetHitUnit())
|
if (Unit* target = GetHitUnit())
|
||||||
{
|
|
||||||
target->CastSpell(target, SPELL_SUMMON_INFERNALS, true);
|
target->CastSpell(target, SPELL_SUMMON_INFERNALS, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -1065,9 +998,7 @@ class aura_class_call_wild_magic : public AuraScript
|
|||||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||||
{
|
{
|
||||||
if (!GetTarget())
|
if (!GetTarget())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
GetTarget()->CastSpell(GetTarget(), SPELL_POLYMORPH, true);
|
GetTarget()->CastSpell(GetTarget(), SPELL_POLYMORPH, true);
|
||||||
}
|
}
|
||||||
@@ -1092,12 +1023,8 @@ class aura_class_call_siphon_blessing : public AuraScript
|
|||||||
PreventDefaultAction();
|
PreventDefaultAction();
|
||||||
|
|
||||||
if (Unit* target = GetTarget())
|
if (Unit* target = GetTarget())
|
||||||
{
|
|
||||||
if (Unit* nefarian = target->FindNearestCreature(NPC_NEFARIAN, 100.f))
|
if (Unit* nefarian = target->FindNearestCreature(NPC_NEFARIAN, 100.f))
|
||||||
{
|
|
||||||
target->CastSpell(nefarian, SPELL_BLESSING_PROTECTION, true);
|
target->CastSpell(nefarian, SPELL_BLESSING_PROTECTION, true);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -1154,9 +1081,7 @@ class spell_corrupted_totems : public SpellScript
|
|||||||
{
|
{
|
||||||
PreventHitDefaultEffect(effIndex);
|
PreventHitDefaultEffect(effIndex);
|
||||||
if (!GetCaster())
|
if (!GetCaster())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
std::list<uint32> spellList = { SPELL_CORRUPTED_FIRE_NOVA_TOTEM, SPELL_CORRUPTED_HEALING_TOTEM, SPELL_CORRUPTED_STONESKIN_TOTEM, SPELL_CORRUPTED_WINDFURY_TOTEM };
|
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);
|
uint32 spellId = Acore::Containers::SelectRandomContainerElement(spellList);
|
||||||
@@ -1207,15 +1132,11 @@ class spell_shadowblink : public SpellScript
|
|||||||
{
|
{
|
||||||
Unit* caster = GetCaster();
|
Unit* caster = GetCaster();
|
||||||
if (!caster || !caster->ToCreature() || !caster->ToCreature()->AI())
|
if (!caster || !caster->ToCreature() || !caster->ToCreature()->AI())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Unit* target = caster->ToCreature()->AI()->SelectTarget(SelectTargetMethod::Random, 0, 200.f, true);
|
Unit* target = caster->ToCreature()->AI()->SelectTarget(SelectTargetMethod::Random, 0, 200.f, true);
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& itr : spellPos)
|
for (auto& itr : spellPos)
|
||||||
{
|
{
|
||||||
@@ -1252,9 +1173,7 @@ class spell_spawn_drakonid : public SpellScript
|
|||||||
{
|
{
|
||||||
Unit* caster = GetCaster();
|
Unit* caster = GetCaster();
|
||||||
if (!caster)
|
if (!caster)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
caster->CastSpell(caster, spawnerSpells[caster->GetEntry()], true);
|
caster->CastSpell(caster, spawnerSpells[caster->GetEntry()], true);
|
||||||
}
|
}
|
||||||
@@ -1267,7 +1186,7 @@ class spell_spawn_drakonid : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_nefarian()
|
void AddSC_boss_nefarian()
|
||||||
{
|
{
|
||||||
new boss_victor_nefarius();
|
RegisterBlackwingLairCreatureAI(boss_victor_nefarius);
|
||||||
RegisterCreatureAI(boss_nefarian);
|
RegisterCreatureAI(boss_nefarian);
|
||||||
RegisterCreatureAI(npc_corrupted_totem);
|
RegisterCreatureAI(npc_corrupted_totem);
|
||||||
RegisterCreatureAI(npc_drakonid_spawner);
|
RegisterCreatureAI(npc_drakonid_spawner);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CreatureScript.h"
|
#include "CreatureScript.h"
|
||||||
|
#include "GameObject.h"
|
||||||
|
#include "GameObjectAI.h"
|
||||||
#include "GameObjectScript.h"
|
#include "GameObjectScript.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "ScriptedCreature.h"
|
#include "ScriptedCreature.h"
|
||||||
@@ -70,214 +72,190 @@ enum EVENTS
|
|||||||
EVENT_CONFLAGRATION = 4
|
EVENT_CONFLAGRATION = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_razorgore : public CreatureScript
|
struct boss_razorgore : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_razorgore(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { }
|
||||||
boss_razorgore() : CreatureScript("boss_razorgore") { }
|
|
||||||
|
|
||||||
struct boss_razorgoreAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_razorgoreAI(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { }
|
_Reset();
|
||||||
|
_charmerGUID.Clear();
|
||||||
void Reset() override
|
secondPhase = false;
|
||||||
{
|
summons.DespawnAll();
|
||||||
_Reset();
|
instance->SetData(DATA_EGG_EVENT, NOT_STARTED);
|
||||||
_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(GameObject* go) : GameObjectAI(go) { }
|
||||||
go_orb_of_domination() : GameObjectScript("go_orb_of_domination") { }
|
|
||||||
|
|
||||||
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 (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->AI()->SetGUID(player->GetGUID());
|
||||||
razor->Attack(player, true);
|
razor->Attack(player, true);
|
||||||
@@ -294,12 +272,9 @@ class spell_egg_event : public SpellScript
|
|||||||
void HandleOnHit()
|
void HandleOnHit()
|
||||||
{
|
{
|
||||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||||
{
|
|
||||||
instance->SetData(DATA_EGG_EVENT, SPECIAL);
|
instance->SetData(DATA_EGG_EVENT, SPECIAL);
|
||||||
}
|
|
||||||
|
|
||||||
if (Creature* razorgore = GetCaster()->ToCreature())
|
if (Creature* razorgore = GetCaster()->ToCreature())
|
||||||
{
|
|
||||||
if (GameObject* egg = GetHitGObj())
|
if (GameObject* egg = GetHitGObj())
|
||||||
{
|
{
|
||||||
razorgore->AI()->DoAction(TALK_EGG_BROKEN_RAND);
|
razorgore->AI()->DoAction(TALK_EGG_BROKEN_RAND);
|
||||||
@@ -307,7 +282,6 @@ class spell_egg_event : public SpellScript
|
|||||||
egg->UseDoorOrButton(10000);
|
egg->UseDoorOrButton(10000);
|
||||||
egg->SetRespawnTime(WEEK);
|
egg->SetRespawnTime(WEEK);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -318,7 +292,7 @@ class spell_egg_event : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_razorgore()
|
void AddSC_boss_razorgore()
|
||||||
{
|
{
|
||||||
new boss_razorgore();
|
RegisterBlackwingLairCreatureAI(boss_razorgore);
|
||||||
new go_orb_of_domination();
|
RegisterBlackwingLairGameObjectAI(go_orb_of_domination);
|
||||||
RegisterSpellScript(spell_egg_event);
|
RegisterSpellScript(spell_egg_event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,227 +72,214 @@ enum Events
|
|||||||
EVENT_BURNING_ADRENALINE = 12,
|
EVENT_BURNING_ADRENALINE = 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_vaelastrasz : public CreatureScript
|
struct boss_vaelastrasz : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_vaelastrasz(Creature* creature) : BossAI(creature, DATA_VAELASTRAZ_THE_CORRUPT)
|
||||||
boss_vaelastrasz() : CreatureScript("boss_vaelastrasz") { }
|
|
||||||
|
|
||||||
struct boss_vaelAI : public BossAI
|
|
||||||
{
|
{
|
||||||
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();
|
Initialize();
|
||||||
|
_eventsIntro.Reset();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
void Initialize()
|
|
||||||
{
|
{
|
||||||
PlayerGUID.Clear();
|
|
||||||
HasYelled = false;
|
HasYelled = false;
|
||||||
_introDone = false;
|
|
||||||
_burningAdrenalineCast = 0;
|
_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();
|
while (uint32 eventId = _eventsIntro.ExecuteEvent())
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_CLEAVE:
|
case EVENT_SPEECH_1:
|
||||||
events.ScheduleEvent(EVENT_CLEAVE, 15s);
|
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
DoCastVictim(SPELL_CLEAVE);
|
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;
|
break;
|
||||||
case EVENT_FLAME_BREATH:
|
case EVENT_SPEECH_2:
|
||||||
DoCastVictim(SPELL_FLAME_BREATH);
|
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
|
||||||
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
|
nefarius->CastSpell(me, SPELL_NEFARIUS_CORRUPTION, TRIGGERED_CAST_DIRECTLY);
|
||||||
//it also ignores targets who have the aura. We don't want to place the debuff on the same target twice.
|
nefarius->Yell(SAY_NEFARIAN_VAEL_INTRO);
|
||||||
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(); }))
|
nefarius->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
{
|
|
||||||
me->CastSpell(target, SPELL_BURNING_ADRENALINE, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
_burningAdrenalineCast++;
|
|
||||||
}
|
}
|
||||||
else
|
_eventsIntro.ScheduleEvent(EVENT_SPEECH_3, 18s);
|
||||||
{
|
break;
|
||||||
me->CastSpell(me->GetVictim(), SPELL_BURNING_ADRENALINE, true);
|
case EVENT_SPEECH_3:
|
||||||
_burningAdrenalineCast = 0;
|
if (Creature* nefarius = me->GetMap()->GetCreature(m_nefariusGuid))
|
||||||
}
|
nefarius->CastSpell(me, SPELL_RED_LIGHTNING, TRIGGERED_NONE);
|
||||||
events.ScheduleEvent(EVENT_BURNING_ADRENALINE, 15s);
|
_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;
|
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
|
case EVENT_CLEAVE:
|
||||||
summoned->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
events.ScheduleEvent(EVENT_CLEAVE, 15s);
|
||||||
m_nefariusGuid = summoned->GetGUID();
|
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)
|
Talk(SAY_HALFLIFE);
|
||||||
{
|
HasYelled = true;
|
||||||
CloseGossipMenuFor(player);
|
|
||||||
BeginSpeech(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
DoMeleeAttackIfReady();
|
||||||
ObjectGuid PlayerGUID;
|
|
||||||
ObjectGuid m_nefariusGuid;
|
|
||||||
bool HasYelled;
|
|
||||||
bool _introDone;
|
|
||||||
EventMap _eventsIntro;
|
|
||||||
uint8 _burningAdrenalineCast;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetBlackwingLairAI<boss_vaelAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 18173 - Burning Adrenaline
|
||||||
@@ -308,9 +295,7 @@ class spell_vael_burning_adrenaline : public AuraScript
|
|||||||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||||
{
|
{
|
||||||
if (!GetTarget())
|
if (!GetTarget())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Do the explosion, then kill the target.
|
// Do the explosion, then kill the target.
|
||||||
GetTarget()->CastSpell(GetTarget(), SPELL_BURNING_ADRENALINE_EXPLOSION, true);
|
GetTarget()->CastSpell(GetTarget(), SPELL_BURNING_ADRENALINE_EXPLOSION, true);
|
||||||
@@ -325,6 +310,6 @@ class spell_vael_burning_adrenaline : public AuraScript
|
|||||||
|
|
||||||
void AddSC_boss_vaelastrasz()
|
void AddSC_boss_vaelastrasz()
|
||||||
{
|
{
|
||||||
new boss_vaelastrasz();
|
RegisterBlackwingLairCreatureAI(boss_vaelastrasz);
|
||||||
RegisterSpellScript(spell_vael_burning_adrenaline);
|
RegisterSpellScript(spell_vael_burning_adrenaline);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,404 +72,355 @@ Position const SummonPosition[8] =
|
|||||||
|
|
||||||
uint32 const Entry[3] = { 12422, 12416, 12420 };
|
uint32 const Entry[3] = { 12422, 12416, 12420 };
|
||||||
|
|
||||||
class instance_blackwing_lair : public InstanceMapScript
|
struct instance_blackwing_lair : public InstanceScript
|
||||||
{
|
{
|
||||||
public:
|
instance_blackwing_lair(Map* map) : InstanceScript(map)
|
||||||
instance_blackwing_lair() : InstanceMapScript(BWLScriptName, MAP_BLACKWING_LAIR) { }
|
|
||||||
|
|
||||||
struct instance_blackwing_lair_InstanceMapScript : public InstanceScript
|
|
||||||
{
|
{
|
||||||
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);
|
case NPC_RAZORGORE:
|
||||||
SetBossNumber(EncounterCount);
|
razorgoreGUID = creature->GetGUID();
|
||||||
LoadDoorData(doorData);
|
break;
|
||||||
LoadObjectData(creatureData, objectData);
|
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
|
case DATA_BROODLORD_LASHLAYER:
|
||||||
EggCount = 0;
|
if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE)
|
||||||
EggEvent = 0;
|
return false;
|
||||||
NefarianLeftTunnel = 0;
|
break;
|
||||||
NefarianRightTunnel = 0;
|
default:
|
||||||
addsCount.fill(0);
|
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.
|
case DATA_RAZORGORE_THE_UNTAMED:
|
||||||
if (creature->GetEntry() == NPC_VICTOR_NEFARIUS && creature->ToTempSummon())
|
if (state == DONE)
|
||||||
{
|
{
|
||||||
return;
|
for (ObjectGuid const& guid : EggList)
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
if (CreatureAI* razorAI = razor->AI())
|
// Eggs should be destroyed instead
|
||||||
{
|
/// @todo: after dynamic spawns
|
||||||
razorAI->JustSummoned(creature);
|
if (GameObject* egg = instance->GetGameObject(guid))
|
||||||
}
|
egg->SetPhaseMask(2, true);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case NPC_BLACKWING_LEGIONAIRE:
|
break;
|
||||||
case NPC_BLACKWING_MAGE:
|
case DATA_NEFARIAN:
|
||||||
++addsCount[1];
|
switch (state)
|
||||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
{
|
||||||
{
|
case FAIL:
|
||||||
if (CreatureAI* razorAI = razor->AI())
|
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15min);
|
||||||
{
|
[[fallthrough]];
|
||||||
razorAI->JustSummoned(creature);
|
case NOT_STARTED:
|
||||||
}
|
if (Creature* nefarian = instance->GetCreature(nefarianGUID))
|
||||||
}
|
nefarian->DespawnOrUnsummon();
|
||||||
break;
|
break;
|
||||||
case NPC_BLACKWING_GUARDSMAN:
|
default:
|
||||||
guardList.push_back(creature->GetGUID());
|
break;
|
||||||
break;
|
}
|
||||||
case NPC_NEFARIAN:
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void OnGameObjectCreate(GameObject* go) override
|
void SetData(uint32 type, uint32 data) override
|
||||||
{
|
{
|
||||||
InstanceScript::OnGameObjectCreate(go);
|
if (type == DATA_EGG_EVENT)
|
||||||
|
|
||||||
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)
|
switch (data)
|
||||||
{
|
{
|
||||||
case DATA_NEFARIAN_LEFT_TUNNEL:
|
case DONE:
|
||||||
return NefarianLeftTunnel;
|
EggEvent = data;
|
||||||
case DATA_NEFARIAN_RIGHT_TUNNEL:
|
|
||||||
return NefarianRightTunnel;
|
|
||||||
case DATA_EGG_EVENT:
|
|
||||||
return EggEvent;
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
case FAIL:
|
||||||
|
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
default:
|
case IN_PROGRESS:
|
||||||
|
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45s);
|
||||||
|
EggEvent = data;
|
||||||
|
EggCount = 0;
|
||||||
|
addsCount.fill(0);
|
||||||
break;
|
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
|
DoRespawnCreature(DATA_GRETHOK);
|
||||||
{
|
|
||||||
if (!InstanceScript::SetBossState(type, state))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (type)
|
for (ObjectGuid const& guid : guardList)
|
||||||
{
|
DoRespawnCreature(guid);
|
||||||
case DATA_RAZORGORE_THE_UNTAMED:
|
|
||||||
if (state == DONE)
|
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
|
SetData(DATA_EGG_EVENT, DONE);
|
||||||
/// @todo: after dynamic spawns
|
razor->RemoveAurasDueToSpell(19832); // MindControl
|
||||||
if (GameObject* egg = instance->GetGameObject(guid))
|
DoRemoveAurasDueToSpellOnPlayers(19832);
|
||||||
{
|
|
||||||
egg->SetPhaseMask(2, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
_events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, 1s);
|
||||||
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.CancelEvent(EVENT_RAZOR_SPAWN);
|
_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;
|
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())
|
case DATA_RAZORGORE_THE_UNTAMED:
|
||||||
return;
|
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;
|
uint32 mobEntry = Entry[urand(0, 2)];
|
||||||
for (uint8 i = urand(2, 5); i > 0; --i)
|
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 more than 12 dragonkins...
|
||||||
if (dragonkinsCount >= 12)
|
if (dragonkinsCount >= 12)
|
||||||
|
{
|
||||||
|
//... and more than 40 orcs - stop spawning more adds.
|
||||||
|
if (orcsCount >= 40)
|
||||||
{
|
{
|
||||||
//... and more than 40 orcs - stop spawning more adds.
|
spawnMoreAdds = false;
|
||||||
if (orcsCount >= 40)
|
break;
|
||||||
{
|
|
||||||
spawnMoreAdds = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//... - stop spawning them.
|
|
||||||
else if (mobEntry == NPC_BLACKWING_DRAGON)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// If more than 40 orcs - stop spawning them.
|
//... - stop spawning them.
|
||||||
else if (orcsCount >= 40 && mobEntry != NPC_BLACKWING_DRAGON)
|
else if (mobEntry == NPC_BLACKWING_DRAGON)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Creature* summon = instance->SummonCreature(mobEntry, SummonPosition[urand(0, 7)]))
|
|
||||||
{
|
|
||||||
summon->AI()->DoZoneInCombat();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// If more than 40 orcs - stop spawning them.
|
||||||
if (spawnMoreAdds)
|
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:
|
if (spawnMoreAdds)
|
||||||
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 15s);
|
||||||
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
}
|
||||||
razor->AI()->DoAction(ACTION_PHASE_TWO);
|
break;
|
||||||
break;
|
case EVENT_RAZOR_PHASE_TWO:
|
||||||
case EVENT_RESPAWN_NEFARIUS:
|
_events.CancelEvent(EVENT_RAZOR_SPAWN);
|
||||||
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
|
if (Creature* razor = instance->GetCreature(razorgoreGUID))
|
||||||
{
|
razor->AI()->DoAction(ACTION_PHASE_TWO);
|
||||||
nefarius->SetPhaseMask(1, true);
|
break;
|
||||||
nefarius->setActive(true);
|
case EVENT_RESPAWN_NEFARIUS:
|
||||||
nefarius->Respawn();
|
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
|
||||||
nefarius->GetMotionMaster()->MoveTargetedHome();
|
{
|
||||||
}
|
nefarius->SetPhaseMask(1, true);
|
||||||
break;
|
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
|
enum ShadowFlame
|
||||||
@@ -527,7 +478,7 @@ public:
|
|||||||
|
|
||||||
void AddSC_instance_blackwing_lair()
|
void AddSC_instance_blackwing_lair()
|
||||||
{
|
{
|
||||||
new instance_blackwing_lair();
|
RegisterInstanceScript(instance_blackwing_lair, MAP_BLACKWING_LAIR);
|
||||||
RegisterSpellScript(spell_bwl_shadowflame);
|
RegisterSpellScript(spell_bwl_shadowflame);
|
||||||
new at_orb_of_command();
|
new at_orb_of_command();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,88 +43,73 @@ enum Events
|
|||||||
EVENT_LIVING_BOMB,
|
EVENT_LIVING_BOMB,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_baron_geddon : public CreatureScript
|
struct boss_baron_geddon : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_baron_geddon(Creature* creature) : BossAI(creature, DATA_GEDDON),
|
||||||
boss_baron_geddon() : CreatureScript("boss_baron_geddon") { }
|
armageddonCasted(false)
|
||||||
|
|
||||||
struct boss_baron_geddonAI : public BossAI
|
|
||||||
{
|
{
|
||||||
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
|
// 19695 Inferno
|
||||||
@@ -149,9 +134,7 @@ class spell_geddon_inferno_aura : public AuraScript
|
|||||||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||||
{
|
{
|
||||||
if (Creature* pCreatureTarget = GetTarget()->ToCreature())
|
if (Creature* pCreatureTarget = GetTarget()->ToCreature())
|
||||||
{
|
|
||||||
pCreatureTarget->SetReactState(REACT_AGGRESSIVE);
|
pCreatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicTick(AuraEffect const* aurEff)
|
void PeriodicTick(AuraEffect const* aurEff)
|
||||||
@@ -209,9 +192,7 @@ class spell_geddon_armageddon_aura : public AuraScript
|
|||||||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||||
{
|
{
|
||||||
if (Creature* pCreatureTarget = GetTarget()->ToCreature())
|
if (Creature* pCreatureTarget = GetTarget()->ToCreature())
|
||||||
{
|
|
||||||
pCreatureTarget->SetReactState(REACT_AGGRESSIVE);
|
pCreatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -223,7 +204,7 @@ class spell_geddon_armageddon_aura : public AuraScript
|
|||||||
|
|
||||||
void AddSC_boss_baron_geddon()
|
void AddSC_boss_baron_geddon()
|
||||||
{
|
{
|
||||||
new boss_baron_geddon();
|
RegisterMoltenCoreCreatureAI(boss_baron_geddon);
|
||||||
|
|
||||||
// Spells
|
// Spells
|
||||||
RegisterSpellScript(spell_geddon_inferno_aura);
|
RegisterSpellScript(spell_geddon_inferno_aura);
|
||||||
|
|||||||
@@ -51,123 +51,93 @@ enum Events
|
|||||||
EVENT_MAGMA_SHACKLES,
|
EVENT_MAGMA_SHACKLES,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_garr : public CreatureScript
|
struct boss_garr : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_garr(Creature* creature) : BossAI(creature, DATA_GARR),
|
||||||
boss_garr() : CreatureScript("boss_garr") {}
|
massEruptionTimer(600000) // 10 mins
|
||||||
|
|
||||||
struct boss_garrAI : public BossAI
|
|
||||||
{
|
{
|
||||||
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();
|
switch (eventId)
|
||||||
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;
|
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))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
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:
|
DoMeleeAttackIfReady();
|
||||||
uint32 massEruptionTimer;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetMoltenCoreAI<boss_garrAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 massEruptionTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_garr_firesworn : public CreatureScript
|
struct npc_garr_firesworn : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_garr_firesworn(Creature* creature) : ScriptedAI(creature) {}
|
||||||
npc_garr_firesworn() : CreatureScript("npc_garr_firesworn") {}
|
|
||||||
|
|
||||||
struct npc_garr_fireswornAI : public ScriptedAI
|
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) override
|
||||||
{
|
{
|
||||||
npc_garr_fireswornAI(Creature* creature) : ScriptedAI(creature) {}
|
if (damage >= me->GetHealth())
|
||||||
|
|
||||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) override
|
|
||||||
{
|
{
|
||||||
if (damage >= me->GetHealth())
|
// Prevent double damage because Firesworn can kill himself with Massive Eruption
|
||||||
{
|
if (me != attacker)
|
||||||
// Prevent double damage because Firesworn can kill himself with Massive Erruption
|
DoCastSelf(SPELL_ERUPTION, true);
|
||||||
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*/)
|
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||||
{
|
{
|
||||||
if (Unit* target = GetHitUnit())
|
if (Unit* target = GetHitUnit())
|
||||||
{
|
|
||||||
target->CastSpell(target, SPELL_FRENZY);
|
target->CastSpell(target, SPELL_FRENZY);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -223,8 +191,8 @@ class spell_garr_frenzy : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_garr()
|
void AddSC_boss_garr()
|
||||||
{
|
{
|
||||||
new boss_garr();
|
RegisterMoltenCoreCreatureAI(boss_garr);
|
||||||
new npc_garr_firesworn();
|
RegisterMoltenCoreCreatureAI(npc_garr_firesworn);
|
||||||
|
|
||||||
// Spells
|
// Spells
|
||||||
RegisterSpellScript(spell_garr_separation_anxiety_aura);
|
RegisterSpellScript(spell_garr_separation_anxiety_aura);
|
||||||
|
|||||||
@@ -34,74 +34,57 @@ enum Events
|
|||||||
EVENT_SHADOW_BOLT,
|
EVENT_SHADOW_BOLT,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_gehennas : public CreatureScript
|
struct boss_gehennas : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_gehennas(Creature* creature) : BossAI(creature, DATA_GEHENNAS) {}
|
||||||
boss_gehennas() : CreatureScript("boss_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();
|
case EVENT_GEHENNAS_CURSE:
|
||||||
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:
|
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);
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false))
|
||||||
events.Repeat(25s, 30s);
|
DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
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()
|
void AddSC_boss_gehennas()
|
||||||
{
|
{
|
||||||
new boss_gehennas();
|
RegisterMoltenCoreCreatureAI(boss_gehennas);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,191 +40,157 @@ enum Spells
|
|||||||
SPELL_FULL_HEAL = 17683,
|
SPELL_FULL_HEAL = 17683,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_golemagg : public CreatureScript
|
struct boss_golemagg : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_golemagg(Creature* creature) : BossAI(creature, DATA_GOLEMAGG),
|
||||||
boss_golemagg() : CreatureScript("boss_golemagg") { }
|
earthquakeTimer(0),
|
||||||
|
pyroblastTimer(0),
|
||||||
|
enraged(false)
|
||||||
|
{}
|
||||||
|
|
||||||
struct boss_golemaggAI : public BossAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
boss_golemaggAI(Creature* creature) : BossAI(creature, DATA_GOLEMAGG),
|
_Reset();
|
||||||
earthquakeTimer(0),
|
earthquakeTimer = 0;
|
||||||
pyroblastTimer(0),
|
pyroblastTimer = urand(3000, 7000);
|
||||||
enraged(false)
|
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();
|
DoCastSelf(SPELL_ATTRACK_RAGER, true);
|
||||||
earthquakeTimer = 0;
|
DoCastAOE(SPELL_EARTHQUAKE, true);
|
||||||
pyroblastTimer = urand(3000, 7000);
|
earthquakeTimer = 5000;
|
||||||
enraged = false;
|
enraged = true;
|
||||||
DoCastSelf(SPELL_MAGMASPLASH);
|
|
||||||
DoCastSelf(SPELL_GOLEMAGG_TRUST_AURA);
|
|
||||||
DoCastSelf(SPELL_DOUBLE_ATTACK);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
DoCastSelf(SPELL_EARTHQUAKE, true);
|
||||||
DoCastAOE(SPELL_EARTHQUAKE, true);
|
|
||||||
earthquakeTimer = 5000;
|
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
|
else
|
||||||
{
|
{
|
||||||
pyroblastTimer -= diff;
|
earthquakeTimer -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
uint32 earthquakeTimer;
|
return;
|
||||||
uint32 pyroblastTimer;
|
|
||||||
bool enraged;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
if (pyroblastTimer <= diff)
|
||||||
{
|
{
|
||||||
return GetMoltenCoreAI<boss_golemaggAI>(creature);
|
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(Creature* creature) : ScriptedAI(creature),
|
||||||
npc_core_rager() : CreatureScript("npc_core_rager") { }
|
instance(creature->GetInstanceScript()),
|
||||||
|
mangleTimer(7000),
|
||||||
struct npc_core_ragerAI : public ScriptedAI
|
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()
|
void AddSC_boss_golemagg()
|
||||||
{
|
{
|
||||||
new boss_golemagg();
|
RegisterMoltenCoreCreatureAI(boss_golemagg);
|
||||||
new npc_core_rager();
|
RegisterMoltenCoreCreatureAI(npc_core_rager);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,56 +33,45 @@ enum Events
|
|||||||
EVENT_SHADOW_SHOCK = 3,
|
EVENT_SHADOW_SHOCK = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_lucifron : public CreatureScript
|
struct boss_lucifron : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_lucifron(Creature* creature) : BossAI(creature, DATA_LUCIFRON) {}
|
||||||
boss_lucifron() : CreatureScript("boss_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();
|
case EVENT_IMPENDING_DOOM:
|
||||||
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:
|
DoCastVictim(SPELL_IMPENDING_DOOM);
|
||||||
{
|
events.Repeat(20s);
|
||||||
DoCastVictim(SPELL_IMPENDING_DOOM);
|
break;
|
||||||
events.Repeat(20s);
|
}
|
||||||
break;
|
case EVENT_LUCIFRON_CURSE:
|
||||||
}
|
{
|
||||||
case EVENT_LUCIFRON_CURSE:
|
DoCastVictim(SPELL_LUCIFRON_CURSE);
|
||||||
{
|
events.Repeat(20s);
|
||||||
DoCastVictim(SPELL_LUCIFRON_CURSE);
|
break;
|
||||||
events.Repeat(20s);
|
}
|
||||||
break;
|
case EVENT_SHADOW_SHOCK:
|
||||||
}
|
{
|
||||||
case EVENT_SHADOW_SHOCK:
|
DoCastVictim(SPELL_SHADOW_SHOCK);
|
||||||
{
|
events.Repeat(5s);
|
||||||
DoCastVictim(SPELL_SHADOW_SHOCK);
|
break;
|
||||||
events.Repeat(5s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetMoltenCoreAI<boss_lucifronAI>(creature);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_lucifron()
|
void AddSC_boss_lucifron()
|
||||||
{
|
{
|
||||||
new boss_lucifron();
|
RegisterMoltenCoreCreatureAI(boss_lucifron);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,73 +47,58 @@ enum Events
|
|||||||
|
|
||||||
constexpr float MELEE_TARGET_LOOKUP_DIST = 10.0f;
|
constexpr float MELEE_TARGET_LOOKUP_DIST = 10.0f;
|
||||||
|
|
||||||
class boss_magmadar : public CreatureScript
|
struct boss_magmadar : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_magmadar(Creature* creature) : BossAI(creature, DATA_MAGMADAR) {}
|
||||||
boss_magmadar() : CreatureScript("boss_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();
|
case EVENT_FRENZY:
|
||||||
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:
|
Talk(EMOTE_FRENZY);
|
||||||
{
|
DoCastSelf(SPELL_FRENZY);
|
||||||
Talk(EMOTE_FRENZY);
|
events.Repeat(15s, 20s);
|
||||||
DoCastSelf(SPELL_FRENZY);
|
break;
|
||||||
events.Repeat(15s, 20s);
|
}
|
||||||
break;
|
case EVENT_PANIC:
|
||||||
}
|
{
|
||||||
case EVENT_PANIC:
|
DoCastVictim(SPELL_PANIC);
|
||||||
{
|
events.Repeat(31s, 38s);
|
||||||
DoCastVictim(SPELL_PANIC);
|
break;
|
||||||
events.Repeat(31s, 38s);
|
}
|
||||||
break;
|
case EVENT_LAVA_BOMB:
|
||||||
}
|
{
|
||||||
case EVENT_LAVA_BOMB:
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, MELEE_TARGET_LOOKUP_DIST, true))
|
||||||
{
|
DoCast(target, SPELL_LAVA_BOMB);
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, MELEE_TARGET_LOOKUP_DIST, true))
|
|
||||||
{
|
|
||||||
DoCast(target, SPELL_LAVA_BOMB);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.Repeat(12s, 15s);
|
events.Repeat(12s, 15s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_LAVA_BOMB_RANGED:
|
case EVENT_LAVA_BOMB_RANGED:
|
||||||
|
{
|
||||||
|
std::list<Unit*> targets;
|
||||||
|
SelectTargetList(targets, 1, SelectTargetMethod::Random, 1, [this](Unit* target)
|
||||||
{
|
{
|
||||||
std::list<Unit*> targets;
|
return target && target->IsPlayer() && target->GetDistance(me) > MELEE_TARGET_LOOKUP_DIST && target->GetDistance(me) < 100.0f;
|
||||||
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;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!targets.empty())
|
if (!targets.empty())
|
||||||
{
|
DoCast(targets.front() , SPELL_LAVA_BOMB_RANGED);
|
||||||
DoCast(targets.front() , SPELL_LAVA_BOMB_RANGED);
|
events.Repeat(12s, 15s);
|
||||||
}
|
break;
|
||||||
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()
|
void AddSC_boss_magmadar()
|
||||||
{
|
{
|
||||||
new boss_magmadar();
|
RegisterMoltenCoreCreatureAI(boss_magmadar);
|
||||||
|
|
||||||
// Spells
|
// Spells
|
||||||
RegisterSpellScript(spell_magmadar_lava_bomb);
|
RegisterSpellScript(spell_magmadar_lava_bomb);
|
||||||
|
|||||||
@@ -131,412 +131,389 @@ struct MajordomoAddData
|
|||||||
MajordomoAddData(ObjectGuid _guid, uint32 _creatureEntry, Position _spawnPos) : guid(_guid), creatureEntry(_creatureEntry), spawnPos(_spawnPos) { }
|
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(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_EXECUTUS) {}
|
||||||
boss_majordomo() : CreatureScript("boss_majordomo") {}
|
|
||||||
|
|
||||||
struct boss_majordomoAI : public BossAI
|
void JustDied(Unit* /*killer*/) override
|
||||||
{
|
{
|
||||||
boss_majordomoAI(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_EXECUTUS) {}
|
Talk(SAY_DEATH);
|
||||||
|
me->DespawnOrUnsummon(10s, 0s);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
ClearGossipMenuFor(player);
|
||||||
switch (action)
|
switch (action)
|
||||||
@@ -544,40 +521,39 @@ public:
|
|||||||
case GOSSIP_ACTION_INFO_DEF:
|
case GOSSIP_ACTION_INFO_DEF:
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GOSSIP_ACTION_INFO_DEF+1:
|
case GOSSIP_ACTION_INFO_DEF+1:
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GOSSIP_ACTION_INFO_DEF+2:
|
case GOSSIP_ACTION_INFO_DEF+2:
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_3, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GOSSIP_ACTION_INFO_DEF+3:
|
case GOSSIP_ACTION_INFO_DEF+3:
|
||||||
{
|
{
|
||||||
CloseGossipMenuFor(player);
|
CloseGossipMenuFor(player);
|
||||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||||
creature->AI()->Talk(SAY_RAG_SUM_1, player);
|
Talk(SAY_RAG_SUM_1, player);
|
||||||
creature->AI()->DoAction(ACTION_START_RAGNAROS_INTRO);
|
DoAction(ACTION_START_RAGNAROS_INTRO);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
CloseGossipMenuFor(player);
|
CloseGossipMenuFor(player);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
private:
|
||||||
{
|
GuidSet static_minionsGUIDS; // contained data should be changed on encounter completion
|
||||||
return GetMoltenCoreAI<boss_majordomoAI>(creature);
|
GuidSet aliveMinionsGUIDS; // used for calculations
|
||||||
}
|
std::unordered_map<uint32, MajordomoAddData> majordomoSummonsData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 20538 Hate to Zero (SERVERSIDE)
|
// 20538 Hate to Zero (SERVERSIDE)
|
||||||
@@ -593,12 +569,8 @@ class spell_hate_to_zero : public SpellScript
|
|||||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||||
{
|
{
|
||||||
if (Unit* caster = GetCaster())
|
if (Unit* caster = GetCaster())
|
||||||
{
|
|
||||||
if (Creature* creatureCaster = caster->ToCreature())
|
if (Creature* creatureCaster = caster->ToCreature())
|
||||||
{
|
|
||||||
creatureCaster->GetThreatMgr().ResetAllThreat();
|
creatureCaster->GetThreatMgr().ResetAllThreat();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -641,9 +613,7 @@ class spell_summon_ragnaros : public SpellScript
|
|||||||
void HandleHit()
|
void HandleHit()
|
||||||
{
|
{
|
||||||
if (Unit* caster = GetCaster())
|
if (Unit* caster = GetCaster())
|
||||||
{
|
|
||||||
caster->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 2 * HOUR * IN_MILLISECONDS);
|
caster->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 2 * HOUR * IN_MILLISECONDS);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
void Register() override
|
||||||
@@ -654,7 +624,7 @@ class spell_summon_ragnaros : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_majordomo()
|
void AddSC_boss_majordomo()
|
||||||
{
|
{
|
||||||
new boss_majordomo();
|
RegisterMoltenCoreCreatureAI(boss_majordomo);
|
||||||
|
|
||||||
// Spells
|
// Spells
|
||||||
RegisterSpellScript(spell_hate_to_zero);
|
RegisterSpellScript(spell_hate_to_zero);
|
||||||
|
|||||||
@@ -112,390 +112,353 @@ enum Misc
|
|||||||
|
|
||||||
constexpr float DEATH_ORIENTATION = 4.0f;
|
constexpr float DEATH_ORIENTATION = 4.0f;
|
||||||
|
|
||||||
class boss_ragnaros : public CreatureScript
|
struct boss_ragnaros : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_ragnaros(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
|
||||||
boss_ragnaros() : CreatureScript("boss_ragnaros") {}
|
_isIntroDone(false),
|
||||||
|
_hasYelledMagmaBurst(false),
|
||||||
struct boss_ragnarosAI : public BossAI
|
_processingMagmaBurst(false),
|
||||||
|
_hasSubmergedOnce(false),
|
||||||
|
_isKnockbackEmoteAllowed(true)
|
||||||
{
|
{
|
||||||
boss_ragnarosAI(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
|
}
|
||||||
_isIntroDone(false),
|
|
||||||
_hasYelledMagmaBurst(false),
|
void Reset() override
|
||||||
_processingMagmaBurst(false),
|
{
|
||||||
_hasSubmergedOnce(false),
|
_Reset();
|
||||||
_isKnockbackEmoteAllowed(true)
|
|
||||||
|
// 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();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
void AttackStart(Unit* target) override
|
|
||||||
{
|
{
|
||||||
if (target && me->Attack(target, true))
|
BossAI::EnterEvadeMode(why);
|
||||||
{
|
|
||||||
DoStartNoMovement(target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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())
|
extraEvents.Update(diff);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CanAIAttack(Unit const* victim) const override
|
while (uint32 const eventId = extraEvents.ExecuteEvent())
|
||||||
{
|
|
||||||
// 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())
|
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_WRATH_OF_RAGNAROS:
|
// Intro events
|
||||||
|
case EVENT_INTRO_SAY:
|
||||||
{
|
{
|
||||||
DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
|
Talk(SAY_ARRIVAL5_RAG);
|
||||||
|
extraEvents.ScheduleEvent(EVENT_INTRO_MAKE_ATTACKABLE, 2500ms, 0, PHASE_INTRO);
|
||||||
if (urand(0, 1))
|
|
||||||
{
|
|
||||||
Talk(SAY_WRATH);
|
|
||||||
}
|
|
||||||
events.Repeat(25s);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_HAND_OF_RAGNAROS:
|
case EVENT_INTRO_MAKE_ATTACKABLE:
|
||||||
{
|
{
|
||||||
DoCastSelf(SPELL_HAND_OF_RAGNAROS);
|
_isIntroDone = true;
|
||||||
if (_isKnockbackEmoteAllowed)
|
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;
|
_isKnockbackEmoteAllowed = false;
|
||||||
extraEvents.RescheduleEvent(EVENT_RESET_KNOCKBACK_EMOTE, 5s);
|
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;
|
||||||
}
|
}
|
||||||
|
case EVENT_SUBMERGE:
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
{
|
||||||
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();
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
return;
|
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()
|
DoMeleeAttackIfReady();
|
||||||
{
|
}
|
||||||
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
|
private:
|
||||||
{
|
EventMap extraEvents;
|
||||||
return me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim());
|
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())
|
if (Unit* caster = GetCaster())
|
||||||
{
|
{
|
||||||
for (uint32 spell : RagnarosSoFSpells)
|
for (uint32 spell : RagnarosSoFSpells)
|
||||||
{
|
|
||||||
caster->CastSpell(caster, spell, true);
|
caster->CastSpell(caster, spell, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +522,7 @@ class spell_ragnaros_summon_sons_of_flame : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_ragnaros()
|
void AddSC_boss_ragnaros()
|
||||||
{
|
{
|
||||||
new boss_ragnaros();
|
RegisterMoltenCoreCreatureAI(boss_ragnaros);
|
||||||
RegisterSpellScript(spell_ragnaros_lava_burst_randomizer);
|
RegisterSpellScript(spell_ragnaros_lava_burst_randomizer);
|
||||||
RegisterSpellScript(spell_ragnaros_summon_sons_of_flame);
|
RegisterSpellScript(spell_ragnaros_summon_sons_of_flame);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,70 +41,57 @@ enum Events
|
|||||||
EVENT_SHAZZRAH_GATE,
|
EVENT_SHAZZRAH_GATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_shazzrah : public CreatureScript
|
struct boss_shazzrah : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_shazzrah(Creature* creature) : BossAI(creature, DATA_SHAZZRAH) {}
|
||||||
boss_shazzrah() : CreatureScript("boss_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();
|
case EVENT_ARCANE_EXPLOSION:
|
||||||
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:
|
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||||
{
|
events.Repeat(4s, 5s);
|
||||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
break;
|
||||||
events.Repeat(4s, 5s);
|
}
|
||||||
break;
|
case EVENT_SHAZZRAH_CURSE:
|
||||||
}
|
{
|
||||||
case EVENT_SHAZZRAH_CURSE:
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_SHAZZRAH_CURSE))
|
||||||
{
|
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_SHAZZRAH_CURSE))
|
events.Repeat(23s, 26s);
|
||||||
{
|
break;
|
||||||
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
}
|
||||||
}
|
case EVENT_MAGIC_GROUNDING:
|
||||||
events.Repeat(23s, 26s);
|
{
|
||||||
break;
|
DoCastSelf(SPELL_MAGIC_GROUNDING);
|
||||||
}
|
events.Repeat(7s, 9s);
|
||||||
case EVENT_MAGIC_GROUNDING:
|
break;
|
||||||
{
|
}
|
||||||
DoCastSelf(SPELL_MAGIC_GROUNDING);
|
case EVENT_COUNTERSPELL:
|
||||||
events.Repeat(7s, 9s);
|
{
|
||||||
break;
|
DoCastAOE(SPELL_COUNTERSPELL);
|
||||||
}
|
events.Repeat(15s, 18s);
|
||||||
case EVENT_COUNTERSPELL:
|
break;
|
||||||
{
|
}
|
||||||
DoCastAOE(SPELL_COUNTERSPELL);
|
case EVENT_SHAZZRAH_GATE:
|
||||||
events.Repeat(15s, 18s);
|
{
|
||||||
break;
|
DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
|
||||||
}
|
events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, 3s, 6s);
|
||||||
case EVENT_SHAZZRAH_GATE:
|
events.Repeat(45s);
|
||||||
{
|
break;
|
||||||
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();
|
Player const* plrTarget = target->ToPlayer();
|
||||||
// Should not target non player targets
|
// Should not target non player targets
|
||||||
if (!plrTarget)
|
if (!plrTarget)
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
// Should skip current victim
|
// Should skip current victim
|
||||||
if (caster->GetVictim() == plrTarget)
|
if (caster->GetVictim() == plrTarget)
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
// Should not target enemies within melee range
|
// Should not target enemies within melee range
|
||||||
if (plrTarget->IsWithinMeleeRange(caster))
|
if (plrTarget->IsWithinMeleeRange(caster))
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targets.empty())
|
if (!targets.empty())
|
||||||
{
|
|
||||||
Acore::Containers::RandomResize(targets, 1);
|
Acore::Containers::RandomResize(targets, 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||||
@@ -182,7 +161,7 @@ class spell_shazzrah_gate_dummy : public SpellScript
|
|||||||
|
|
||||||
void AddSC_boss_shazzrah()
|
void AddSC_boss_shazzrah()
|
||||||
{
|
{
|
||||||
new boss_shazzrah();
|
RegisterMoltenCoreCreatureAI(boss_shazzrah);
|
||||||
|
|
||||||
// Spells
|
// Spells
|
||||||
RegisterSpellScript(spell_shazzrah_gate_dummy);
|
RegisterSpellScript(spell_shazzrah_gate_dummy);
|
||||||
|
|||||||
@@ -47,172 +47,138 @@ enum Events
|
|||||||
EVENT_IMMOLATE,
|
EVENT_IMMOLATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_sulfuron : public CreatureScript
|
struct boss_sulfuron : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
boss_sulfuron(Creature* creature) : BossAI(creature, DATA_SULFURON) {}
|
||||||
boss_sulfuron() : CreatureScript("boss_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();
|
case EVENT_DEMORALIZING_SHOUT:
|
||||||
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:
|
DoCastVictim(SPELL_DEMORALIZING_SHOUT);
|
||||||
{
|
events.Repeat(12s, 18s);
|
||||||
DoCastVictim(SPELL_DEMORALIZING_SHOUT);
|
break;
|
||||||
events.Repeat(12s, 18s);
|
}
|
||||||
break;
|
case EVENT_INSPIRE:
|
||||||
}
|
{
|
||||||
case EVENT_INSPIRE:
|
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
|
||||||
{
|
if (!healers.empty())
|
||||||
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
|
DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
|
||||||
if (!healers.empty())
|
|
||||||
{
|
|
||||||
DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
DoCastSelf(SPELL_INSPIRE);
|
DoCastSelf(SPELL_INSPIRE);
|
||||||
events.Repeat(13s, 20s);
|
events.Repeat(13s, 20s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_KNOCKDOWN:
|
case EVENT_KNOCKDOWN:
|
||||||
{
|
{
|
||||||
DoCastVictim(SPELL_KNOCKDOWN);
|
DoCastVictim(SPELL_KNOCKDOWN);
|
||||||
events.Repeat(10s, 20s);
|
events.Repeat(10s, 20s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_FLAMESPEAR:
|
case EVENT_FLAMESPEAR:
|
||||||
{
|
{
|
||||||
DoCastRandomTarget(SPELL_FLAMESPEAR);
|
DoCastRandomTarget(SPELL_FLAMESPEAR);
|
||||||
events.Repeat(12s, 16s);
|
events.Repeat(12s, 16s);
|
||||||
break;
|
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(Creature* creature) : ScriptedAI(creature) {}
|
||||||
npc_flamewaker_priest() : CreatureScript("npc_flamewaker_priest") {}
|
|
||||||
|
|
||||||
struct npc_flamewaker_priestAI : public ScriptedAI
|
void Reset() override
|
||||||
{
|
{
|
||||||
npc_flamewaker_priestAI(Creature* creature) : ScriptedAI(creature) {}
|
events.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
void Reset() override
|
void JustDied(Unit* /*killer*/) override
|
||||||
{
|
{
|
||||||
events.Reset();
|
events.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
{
|
{
|
||||||
events.Reset();
|
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
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
events.ScheduleEvent(EVENT_DARK_STRIKE, 4s, 7s);
|
if (!UpdateVictim())
|
||||||
events.ScheduleEvent(EVENT_DARK_MENDING, 15s, 30s);
|
return;
|
||||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2s, 4s);
|
|
||||||
events.ScheduleEvent(EVENT_IMMOLATE, 3500ms, 6s);
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
{
|
|
||||||
return;
|
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:
|
DoMeleeAttackIfReady();
|
||||||
EventMap events;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetMoltenCoreAI<npc_flamewaker_priestAI>(creature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap events;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_sulfuron()
|
void AddSC_boss_sulfuron()
|
||||||
{
|
{
|
||||||
new boss_sulfuron();
|
RegisterMoltenCoreCreatureAI(boss_sulfuron);
|
||||||
new npc_flamewaker_priest();
|
RegisterMoltenCoreCreatureAI(npc_flamewaker_priest);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,384 +53,331 @@ MCBossObject const linkedBossObjData[MAX_MC_LINKED_BOSS_OBJ]=
|
|||||||
|
|
||||||
constexpr uint8 SAY_SPAWN = 1;
|
constexpr uint8 SAY_SPAWN = 1;
|
||||||
|
|
||||||
class instance_molten_core : public InstanceMapScript
|
struct instance_molten_core : public InstanceScript
|
||||||
{
|
{
|
||||||
public:
|
instance_molten_core(Map* map) : InstanceScript(map)
|
||||||
instance_molten_core() : InstanceMapScript(MCScriptName, MAP_MOLTEN_CORE) {}
|
|
||||||
|
|
||||||
struct instance_molten_core_InstanceMapScript : public InstanceScript
|
|
||||||
{
|
{
|
||||||
instance_molten_core_InstanceMapScript(Map* map) : InstanceScript(map)
|
SetHeaders(DataHeader);
|
||||||
{
|
SetBossNumber(MAX_ENCOUNTER);
|
||||||
SetHeaders(DataHeader);
|
LoadMinionData(minionData);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
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
|
// 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(Creature* creature) :
|
||||||
npc_mc_core_hound() : CreatureScript("npc_mc_core_hound") {}
|
CreatureAI(creature),
|
||||||
|
instance(creature->GetInstanceScript()),
|
||||||
struct npc_mc_core_houndAI : public CreatureAI
|
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
|
// 19822 Play Dead
|
||||||
@@ -136,9 +121,7 @@ class spell_mc_play_dead_aura : public AuraScript
|
|||||||
{
|
{
|
||||||
Creature* creatureTarget = GetTarget()->ToCreature();
|
Creature* creatureTarget = GetTarget()->ToCreature();
|
||||||
if (!creatureTarget)
|
if (!creatureTarget)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
creatureTarget->CastSpell(creatureTarget, SPELL_PLAY_DEAD_PACIFY, true);
|
creatureTarget->CastSpell(creatureTarget, SPELL_PLAY_DEAD_PACIFY, true);
|
||||||
creatureTarget->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
|
creatureTarget->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
|
||||||
@@ -154,9 +137,7 @@ class spell_mc_play_dead_aura : public AuraScript
|
|||||||
{
|
{
|
||||||
Creature* creatureTarget = GetTarget()->ToCreature();
|
Creature* creatureTarget = GetTarget()->ToCreature();
|
||||||
if (!creatureTarget)
|
if (!creatureTarget)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
creatureTarget->RemoveAurasDueToSpell(SPELL_PLAY_DEAD_PACIFY);
|
creatureTarget->RemoveAurasDueToSpell(SPELL_PLAY_DEAD_PACIFY);
|
||||||
creatureTarget->RemoveDynamicFlag(UNIT_DYNFLAG_DEAD);
|
creatureTarget->RemoveDynamicFlag(UNIT_DYNFLAG_DEAD);
|
||||||
@@ -166,9 +147,7 @@ class spell_mc_play_dead_aura : public AuraScript
|
|||||||
creatureTarget->SetReactState(REACT_AGGRESSIVE);
|
creatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
|
||||||
if (!creatureTarget->IsInCombat())
|
if (!creatureTarget->IsInCombat())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
bool shouldDie = true;
|
bool shouldDie = true;
|
||||||
std::list<Creature*> hounds;
|
std::list<Creature*> hounds;
|
||||||
@@ -246,9 +225,7 @@ struct npc_lava_spawn : public ScriptedAI
|
|||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
_scheduler.Update(diff);
|
_scheduler.Update(diff);
|
||||||
|
|
||||||
@@ -262,7 +239,7 @@ private:
|
|||||||
void AddSC_molten_core()
|
void AddSC_molten_core()
|
||||||
{
|
{
|
||||||
// Creatures
|
// Creatures
|
||||||
new npc_mc_core_hound();
|
RegisterMoltenCoreCreatureAI(npc_mc_core_hound);
|
||||||
RegisterCreatureAI(npc_lava_spawn);
|
RegisterCreatureAI(npc_lava_spawn);
|
||||||
|
|
||||||
// Spells
|
// Spells
|
||||||
|
|||||||
@@ -127,4 +127,7 @@ inline AI* GetMoltenCoreAI(T* obj)
|
|||||||
return GetInstanceAI<AI>(obj, MCScriptName);
|
return GetInstanceAI<AI>(obj, MCScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RegisterMoltenCoreCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetMoltenCoreAI)
|
||||||
|
#define RegisterMoltenCoreGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetMoltenCoreAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user