fix(Scripts/BlackTemple): Rewrite Shade of Akama (#18601)

* init

* akama

only generators left

* Update boss_shade_of_akama.cpp

* Update boss_shade_of_akama.cpp

* warnign

* OMFG

* akama generators

* more for generators

* done

* codestyle

* warnings

* illidan fix

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* Update rev_1711048056647652400.sql

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* a

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* Update instance_black_temple.cpp

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* Update rev_1711048056647652400.sql

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* avoid collecting trash

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* Update boss_illidan.cpp

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* Update boss_shade_of_akama.cpp

Co-Authored-By: 天鹿 <18535853+pklloveyou@users.noreply.github.com>

* crashfix?

* takes too long to despawn

* maybe

* clear lists

---------

Co-authored-by: 天鹿 <18535853+pklloveyou@users.noreply.github.com>
This commit is contained in:
Gultask
2024-04-02 17:08:51 -03:00
committed by GitHub
parent 6fbcaf7ab1
commit dc7753b2b6
6 changed files with 481 additions and 510 deletions

View File

@@ -40,17 +40,27 @@ enum DataTypes
DATA_RELIQUARY_OF_SOULS = 5,
DATA_MOTHER_SHAHRAZ = 6,
DATA_ILLIDARI_COUNCIL = 7,
DATA_AKAMA_FINISHED = 8,
DATA_AKAMA_ILLIDAN = 8,
DATA_ILLIDAN_STORMRAGE = 9,
MAX_ENCOUNTERS = 10
MAX_ENCOUNTERS = 10,
DATA_AKAMA_SHADE = 11,
DATA_GATHIOS_THE_SHATTERER = 12,
DATA_HIGH_NETHERMANCER_ZEREVOR = 13,
DATA_LADY_MALANDE = 14,
DATA_VERAS_DARKSHADOW = 15
};
enum CreatureIds
{
NPC_HIGH_WARLORD_NAJENTUS = 22887,
NPC_SUPREMUS = 22898,
NPC_SHADE_OF_AKAMA = 22841,
NPC_AKAMA_SHADE = 23191,
NPC_STORM_FURY = 22848,
NPC_ASHTONGUE_CHANNELER = 23421,
NPC_CREATURE_GENERATOR_AKAMA = 23210,
NPC_TERON_GOREFIEND = 22871,
NPC_GURTOGG_BLOODBOIL = 22948,
NPC_VENGEFUL_SPIRIT = 23109,
NPC_SHADOWY_CONSTRUCT = 23111,
NPC_ANGERED_SOUL_FRAGMENT = 23398,
@@ -58,17 +68,26 @@ enum CreatureIds
NPC_SUFFERING_SOUL_FRAGMENT = 23399,
NPC_RELIQUARY_OF_THE_LOST = 22856,
NPC_ENSLAVED_SOUL = 23469,
NPC_MOTHER_SHAHRAZ = 22947,
NPC_GATHIOS_THE_SHATTERER = 22949,
NPC_HIGH_NETHERMANCER_ZEREVOR = 22950,
NPC_LADY_MALANDE = 22951,
NPC_VERAS_DARKSHADOW = 22952,
NPC_ILLIDARI_COUNCIL = 23426,
NPC_AKAMA = 23089,
NPC_AKAMA_ILLIDAN = 23089,
NPC_ILLIDAN_STORMRAGE = 22917,
NPC_PARASITIC_SHADOWFIEND = 23498,
NPC_BLADE_OF_AZZINOTH = 22996,
NPC_FLAME_OF_AZZINOTH = 22997,
NPC_ASHTONGUE_BATTLELORD = 22844,
NPC_ASHTONGUE_MYSTIC = 22845,
NPC_ASHTONGUE_STORMCALLER = 22846,
NPC_ASHTONGUE_PRIMALIST = 22847,
NPC_ASHTONGUE_FERAL_SPIRIT = 22849,
NPC_ASHTONGUE_STALKER = 23374,
NPC_STORM_FURY = 22848,
NPC_DRAGON_TURTLE = 22885
};

View File

@@ -48,6 +48,8 @@ enum Says
SAY_AKAMA_ILLIDAN1 = 4,
SAY_AKAMA_ILLIDAN2 = 5,
SAY_AKAMA_ILLIDAN3 = 6,
SAY_AKAMA_COUNCIL_1 = 9,
SAY_AKAMA_COUNCIL_2 = 10,
SAY_MAIEV_SHADOWSONG_TAUNT = 0,
SAY_MAIEV_SHADOWSONG_ILLIDAN1 = 1,
@@ -117,6 +119,7 @@ enum Spells
enum Misc
{
ACTION_ILLIDARI_COUNCIL_DONE = 0,
ACTION_FIGHT_MINIONS = 1,
ACTION_RETURN_BLADE = 2,
ACTION_ILLIDAN_CAGED = 3,
@@ -133,7 +136,9 @@ enum Misc
NPC_ILLIDAN_DB_TARGET = 23070,
NPC_MAIEV_SHADOWSONG = 23197,
GO_CAGE_TRAP = 185916
GO_CAGE_TRAP = 185916,
PATH_AKAMA_ILLIDARI_COUNCIL_1 = 230891
};
enum Events
@@ -237,13 +242,13 @@ public:
{
BossAI::EnterEvadeMode(why);
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA)))
if (Creature* akama = instance->GetCreature(NPC_AKAMA_ILLIDAN))
akama->AI()->EnterEvadeMode(why);
}
bool CanAIAttack(Unit const* target) const override
{
return target->GetEntry() != NPC_AKAMA && target->GetEntry() != NPC_MAIEV_SHADOWSONG;
return target->GetEntry() != NPC_AKAMA_ILLIDAN && target->GetEntry() != NPC_MAIEV_SHADOWSONG;
}
void DoAction(int32 param) override
@@ -408,7 +413,7 @@ public:
switch (events2.ExecuteEvent())
{
case EVENT_SUMMON_MINIONS2:
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA)))
if (Creature* akama = instance->GetCreature(NPC_AKAMA_ILLIDAN))
akama->AI()->DoAction(ACTION_FIGHT_MINIONS);
break;
case EVENT_PHASE_2_EYE_BEAM_START:
@@ -445,7 +450,7 @@ public:
maiev->AI()->Talk(SAY_MAIEV_SHADOWSONG_ILLIDAN3);
}
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA)))
if (Creature* akama = instance->GetCreature(NPC_AKAMA_ILLIDAN))
{
akama->AI()->DoAction(ACTION_ILLIDAN_DEAD);
akama->SetTarget(me->GetGUID());
@@ -754,6 +759,8 @@ enum Akama
EVENT_AKAMA_HEALTH = 102
};
Position AkamaTeleport = { 609.772f, 308.456f, 271.826f, 6.1972566f };
class npc_akama_illidan : public CreatureScript
{
public:
@@ -764,7 +771,7 @@ public:
npc_akama_illidanAI(Creature* creature) : npc_escortAI(creature), summons(me)
{
instance = creature->GetInstanceScript();
if (instance->GetBossState(DATA_AKAMA_FINISHED) == DONE)
if (instance->GetBossState(DATA_AKAMA_ILLIDAN) == DONE)
{
me->GetMap()->LoadGrid(751.664f, 238.933f);
me->SetHomePosition(751.664f, 238.933f, 353.106f, 2.18f);
@@ -789,6 +796,12 @@ public:
summons.DespawnAll();
me->CombatStop(true);
}
else if (param == ACTION_ILLIDARI_COUNCIL_DONE)
{
me->NearTeleportTo(AkamaTeleport);
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->GetMotionMaster()->MovePath(PATH_AKAMA_ILLIDARI_COUNCIL_1, false);
}
}
void Reset() override
@@ -796,7 +809,6 @@ public:
me->SetReactState(REACT_AGGRESSIVE);
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->setActive(false);
me->SetVisible(instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE && instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != DONE);
events.Reset();
summons.DespawnAll();
}
@@ -807,7 +819,7 @@ public:
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE);
me->setActive(true);
if (instance->GetBossState(DATA_AKAMA_FINISHED) != DONE)
if (instance->GetBossState(DATA_AKAMA_ILLIDAN) != DONE)
{
me->SetReactState(REACT_PASSIVE);
Start(false, true);
@@ -830,6 +842,22 @@ public:
}
}
void PathEndReached(uint32 pathId) override
{
if (pathId == PATH_AKAMA_ILLIDARI_COUNCIL_1)
{
ScheduleUniqueTimedEvent(200ms, [&]
{
Talk(SAY_AKAMA_COUNCIL_1);
}, 1);
ScheduleUniqueTimedEvent(7800ms, [&]
{
Talk(SAY_AKAMA_COUNCIL_2);
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
}, 2);
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
@@ -878,6 +906,7 @@ public:
void UpdateEscortAI(uint32 diff) override
{
scheduler.Update(diff);
events.Update(diff);
switch (events.ExecuteEvent())
{
@@ -913,8 +942,8 @@ public:
udalo->CastSpell(udalo, SPELL_AKAMA_DOOR_OPEN, false);
break;
case EVENT_AKAMA_SCENE_9:
instance->SetBossState(DATA_AKAMA_FINISHED, NOT_STARTED);
instance->SetBossState(DATA_AKAMA_FINISHED, DONE);
instance->SetBossState(DATA_AKAMA_ILLIDAN, NOT_STARTED);
instance->SetBossState(DATA_AKAMA_ILLIDAN, DONE);
break;
case EVENT_AKAMA_SCENE_10:
Talk(SAY_AKAMA_BEWARE);
@@ -923,40 +952,40 @@ public:
SetEscortPaused(false);
break;
case EVENT_AKAMA_SCENE_20:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->SetStandState(UNIT_STAND_STATE_STAND);
break;
case EVENT_AKAMA_SCENE_21:
me->SetFacingTo(M_PI);
break;
case EVENT_AKAMA_SCENE_22:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->AI()->Talk(SAY_ILLIDAN_AKAMA1);
break;
case EVENT_AKAMA_SCENE_23:
Talk(SAY_AKAMA_ILLIDAN1);
break;
case EVENT_AKAMA_SCENE_24:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->AI()->Talk(SAY_ILLIDAN_AKAMA2);
break;
case EVENT_AKAMA_SCENE_25:
Talk(SAY_AKAMA_ILLIDAN2);
break;
case EVENT_AKAMA_SCENE_26:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->AI()->Talk(SAY_ILLIDAN_AKAMA3);
break;
case EVENT_AKAMA_SCENE_27:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->LoadEquipment(1, true);
break;
case EVENT_AKAMA_SCENE_28:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE);
break;
case EVENT_AKAMA_SCENE_29:
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDAN_STORMRAGE)))
if (Creature* illidan = instance->GetCreature(DATA_ILLIDAN_STORMRAGE))
{
illidan->SetImmuneToAll(false);
illidan->SetInCombatWithZone();

View File

@@ -25,30 +25,43 @@ enum Says
SAY_BROKEN_FREE_0 = 0,
SAY_BROKEN_FREE_1 = 1,
SAY_BROKEN_FREE_2 = 2,
SAY_LOW_HEALTH = 3,
SAY_DEATH = 4,
SAY_BROKEN_S1 = 0,
SAY_BROKEN_S2 = 1
};
enum Spells
{
// Akama
SPELL_STEALTH = 34189,
SPELL_AKAMA_SOUL_CHANNEL = 40447,
SPELL_SHADE_SOUL_CHANNEL = 40401,
SPELL_CHAIN_LIGHTNING = 39945,
SPELL_DESTRUCTIVE_POISON = 40874,
SPELL_SHADE_OF_AKAMA_TRIGGER = 40955,
SPELL_AKAMA_SOUL_RETRIEVE = 40902,
SPELL_CHAIN_LIGHTNING = 39945,
SPELL_AKAMA_SOUL_CHANNEL = 40447,
SPELL_FIXATE = 40607,
SPELL_AKAMA_SOUL_RETRIEVE = 40902, // epilogue
SPELL_AKAMA_SOUL_EXPEL_CHANNEL = 40927, // epilogue
SPELL_ASHTONGUE_WAVE_B = 42035,
SPELL_SUMMON_ASHTONGUE_SORCERER = 40476,
SPELL_SUMMON_ASHTONGUE_DEFENDER = 40474
// Shade & Channelers
SPELL_SHADE_SOUL_CHANNEL = 40401,
SPELL_THREAT = 41602,
SPELL_SHADE_OF_AKAMA_TRIGGER = 40955,
// Summons
SPELL_ASHTONGUE_WAVE_A = 42073, // unused
SPELL_ASHTONGUE_WAVE_B = 42035,
SPELL_SUMMON_ASHTONGUE_SORCERER = 40476,
SPELL_SUMMON_ASHTONGUE_DEFENDER = 40474
};
enum Creatures
{
NPC_ASHTONGUE_CHANNELER = 23421,
NPC_CREATURE_GENERATOR_AKAMA = 23210,
NPC_ASHTONGUE_SORCERER = 23215,
NPC_ASHTONGUE_DEFENDER = 23216,
NPC_ASHTONGUE_ELEMENTAL = 23523,
NPC_ASHTONGUE_ROGUE = 23318,
NPC_ASHTONGUE_SPIRITBIND = 23524,
NPC_ASHTONGUE_BROKEN = 23319
};
@@ -56,220 +69,137 @@ enum Misc
{
SUMMON_GROUP_BROKENS = 1,
POINT_START = 0,
POINT_CHANNEL_SOUL = 1,
POINT_ENGAGE = 0,
POINT_OUTRO = 1,
ACTION_AKAMA_DIED = 1,
ACTION_START_ENCOUNTER = 2,
ACTION_STOP_SPAWNING = 3,
ACTION_DESPAWN_ALL = 4,
ACTION_CHANNELERS_START_CHANNEL = 5,
ACTION_KILL_CHANNELERS = 6,
ACTION_NO_SORCERERS = 7,
ACTION_SHADE_DIED = 8,
ACTION_GENERATOR_START = 1,
ACTION_GENERATOR_STOP = 2,
ACTION_GENERATOR_DESPAWN_ALL = 3,
EVENT_AKAMA_START_ENCOUNTER = 1,
EVENT_AKAMA_START_CHANNEL = 2,
EVENT_SPELL_CHAIN_LIGHTNING = 4,
EVENT_SPELL_DESTRUCTIVE_POISON = 5,
COUNTER_SPAWNS_MAX = 20, // Max number of spawns for each generator, number chosen at random
EVENT_SHADE_CHECK_DISTANCE = 10,
EVENT_SHADE_RESET_ENCOUNTER = 11,
EVENT_SHADE_GATHER_NPCS = 12,
ACTION_AKAMA_START_OUTRO = 1,
EVENT_SUMMON_WAVE_B = 20,
EVENT_SUMMON_ASHTONGUE_SORCERER = 21,
EVENT_SUMMON_ASHTONGUE_DEFENDER = 22,
EVENT_AKAMA_SCENE0 = 29,
EVENT_AKAMA_SCENE1 = 30,
EVENT_AKAMA_SCENE2 = 31,
EVENT_AKAMA_SCENE3 = 32,
EVENT_AKAMA_SCENE4 = 33,
EVENT_AKAMA_SCENE5 = 34,
EVENT_AKAMA_SCENE6 = 35,
EVENT_AKAMA_SCENE7 = 36
FACTION_DEFAULT = 1820,
FACTION_ENGAGE = 1868
};
Position AkamaEngage = { 517.4877f, 400.79926f, 112.77704f };
Position AkamaOutro = { 469.0867f, 401.0793f, 118.52704f, 0.087266460061073303f };
Position ShadeEngage = { 512.48773f, 400.8283f, 112.77704f };
struct boss_shade_of_akama : public BossAI
{
boss_shade_of_akama(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA), summonsChanneler(me), summonsGenerator(me)
{
events2.ScheduleEvent(EVENT_SHADE_GATHER_NPCS, 1000);
}
boss_shade_of_akama(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA) { }
SummonList summonsChanneler;
SummonList summonsGenerator;
EventMap events2;
void ChannelersAction(int32 action)
{
for (SummonList::const_iterator i = summonsChanneler.begin(); i != summonsChanneler.end(); ++i)
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i))
{
if (action == ACTION_CHANNELERS_START_CHANNEL)
{
summon->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true);
summon->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
else if (action == ACTION_START_ENCOUNTER)
{
summon->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
else if (action == ACTION_KILL_CHANNELERS)
{
Unit::Kill(me, summon);
}
}
}
std::list<Creature*> channelers;
std::list<Creature*> generators;
void Reset() override
{
BossAI::Reset();
me->SetReactState(REACT_PASSIVE);
channelers.clear();
generators.clear();
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetImmuneToAll(true);
me->SetWalk(true);
me->SetReactState(REACT_DEFENSIVE);
BossAI::Reset();
}
void EnterEvadeMode(EvadeReason why) override
{
for (Creature* generator : generators)
generator->AI()->DoAction(ACTION_GENERATOR_DESPAWN_ALL);
for (Creature* channeler : channelers)
channeler->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
BossAI::EnterEvadeMode(why);
summonsGenerator.DoAction(ACTION_DESPAWN_ALL);
events2.ScheduleEvent(EVENT_SHADE_RESET_ENCOUNTER, 20000);
me->SetVisible(false);
ChannelersAction(ACTION_KILL_CHANNELERS);
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
summonsGenerator.DoAction(ACTION_DESPAWN_ALL);
summonsChanneler.DespawnAll();
me->CastSpell(me, SPELL_SHADE_OF_AKAMA_TRIGGER, true);
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE)))
for (Creature* generator : generators)
generator->AI()->DoAction(ACTION_GENERATOR_DESPAWN_ALL);
if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
akama->AI()->DoAction(ACTION_AKAMA_START_OUTRO);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_AKAMA_SOUL_CHANNEL)
{
akama->SetHomePosition(*akama);
akama->AI()->DoAction(ACTION_SHADE_DIED);
instance->SetBossState(DATA_SHADE_OF_AKAMA, IN_PROGRESS);
me->GetCreatureListWithEntryInGrid(channelers, NPC_ASHTONGUE_CHANNELER, 40.0f);
me->GetCreatureListWithEntryInGrid(generators, NPC_CREATURE_GENERATOR_AKAMA, 100.0f);
for (Creature* channeler : channelers)
channeler->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
for (Creature* generator : generators)
generator->AI()->DoAction(ACTION_GENERATOR_START);
ScheduleTimedEvent(1200ms, [&]
{
if (me->GetSpeed(MOVE_WALK) > 0.01f)
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(POINT_ENGAGE, ShadeEngage);
}
}, 1200ms);
}
}
void DoAction(int32 param) override
void MovementInform(uint32 type, uint32 point) override
{
if (param == ACTION_START_ENCOUNTER)
if (type == POINT_MOTION_TYPE && point == POINT_ENGAGE)
{
summonsGenerator.DoAction(ACTION_START_ENCOUNTER);
ChannelersAction(ACTION_START_ENCOUNTER);
events.ScheduleEvent(EVENT_SHADE_CHECK_DISTANCE, 1000);
}
else if (param == ACTION_AKAMA_DIED)
{
EnterEvadeMode(EVADE_REASON_OTHER);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL);
scheduler.CancelAll();
for (Creature* generator : generators)
generator->AI()->DoAction(ACTION_GENERATOR_STOP);
if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
{
akama->SetReactState(REACT_AGGRESSIVE);
akama->InterruptSpell(CURRENT_CHANNELED_SPELL);
DoCast(akama, SPELL_THREAT, true);
me->AddThreat(akama, 900000.0f);
akama->AI()->DoCast(me, SPELL_FIXATE, true);
AttackStart(akama);
}
ScheduleTimedEvent(3500ms, [&]
{
if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
me->AddThreat(akama, 900000.0f);
}, 3500ms);
}
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
switch (events2.ExecuteEvent())
{
case EVENT_SHADE_GATHER_NPCS:
{
std::list<Creature*> ChannelerList;
me->GetCreaturesWithEntryInRange(ChannelerList, 100.0f, NPC_ASHTONGUE_CHANNELER);
for (std::list<Creature*>::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr)
summonsChanneler.Summon(*itr);
std::list<Creature*> SpawnerList;
me->GetCreaturesWithEntryInRange(SpawnerList, 100.0f, NPC_CREATURE_GENERATOR_AKAMA);
for (std::list<Creature*>::const_iterator itr = SpawnerList.begin(); itr != SpawnerList.end(); ++itr)
summonsGenerator.Summon(*itr);
summonsChanneler.Respawn();
summonsGenerator.Respawn();
ChannelersAction(ACTION_CHANNELERS_START_CHANNEL);
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE)))
akama->Respawn(true);
break;
}
case EVENT_SHADE_RESET_ENCOUNTER:
me->SetVisible(true);
summonsGenerator.Respawn();
summonsChanneler.Respawn();
ChannelersAction(ACTION_CHANNELERS_START_CHANNEL);
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE)))
akama->Respawn(true);
break;
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SHADE_CHECK_DISTANCE:
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE)
{
int32 slow = me->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED);
if (slow > -100)
{
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_START, 510.0f, 400.7993f, 112.7837f);
}
}
else
{
int32 slow = me->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED);
if (slow < -100)
me->GetMotionMaster()->Clear();
else if (slow == 0)
{
summonsGenerator.DoAction(ACTION_NO_SORCERERS);
me->SetWalk(false);
}
}
if (me->IsWithinMeleeRange(me->GetVictim()))
{
me->SetReactState(REACT_AGGRESSIVE);
DoResetThreatList();
me->GetVictim()->InterruptNonMeleeSpells(false);
me->AddThreat(me->GetVictim(), 1000000.0f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetImmuneToAll(false);
summonsGenerator.DoAction(ACTION_STOP_SPAWNING);
break;
}
events.ScheduleEvent(EVENT_SHADE_CHECK_DISTANCE, 1000);
break;
}
scheduler.Update(diff);
DoMeleeAttackIfReady();
}
bool CheckEvadeIfOutOfCombatArea() const override
{
return !SelectTargetFromPlayerList(120.0f);
}
};
struct npc_akama_shade : public ScriptedAI
{
npc_akama_shade(Creature* creature) : ScriptedAI(creature), summons(me)
npc_akama_shade(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
EventMap events;
EventMap events2;
SummonList summons;
void Reset() override
{
@@ -279,244 +209,262 @@ struct npc_akama_shade : public ScriptedAI
return;
}
me->SetFaction(FACTION_DEFAULT);
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->CastSpell(me, SPELL_STEALTH, true);
events.Reset();
events2.Reset();
DoCastSelf(SPELL_STEALTH, true);
me->SetWalk(true);
scheduler.CancelAll();
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != POINT_MOTION_TYPE || point != POINT_CHANNEL_SOUL)
return;
if (type == POINT_MOTION_TYPE)
{
switch (point)
{
case POINT_ENGAGE:
me->SetHomePosition(me->GetPosition());
me->SetFaction(FACTION_ENGAGE);
DoCast(me, SPELL_AKAMA_SOUL_CHANNEL, true);
break;
case POINT_OUTRO:
DoCastSelf(SPELL_AKAMA_SOUL_RETRIEVE, true);
ScheduleUniqueTimedEvent(15600ms, [&]
{
Talk(SAY_BROKEN_FREE_0);
me->SummonCreatureGroup(SUMMON_GROUP_BROKENS);
}, 1);
ScheduleUniqueTimedEvent(26550ms, [&]
{
Talk(SAY_BROKEN_FREE_1);
}, 2);
ScheduleUniqueTimedEvent(37500ms, [&]
{
Talk(SAY_BROKEN_FREE_2);
}, 3);
ScheduleUniqueTimedEvent(52000ms, [&]
{
std::list<Creature*> brokens;
me->GetCreatureListWithEntryInGrid(brokens, NPC_ASHTONGUE_BROKEN, 40.0f);
if (Creature* broken = GetClosestCreatureWithEntry(me, NPC_ASHTONGUE_BROKEN, 40.0f))
broken->AI()->Talk(SAY_BROKEN_S1);
me->SetFacingTo(0.0f);
events2.ScheduleEvent(EVENT_AKAMA_SCENE1, 1000);
events2.ScheduleEvent(EVENT_AKAMA_SCENE2, 16500);
events2.ScheduleEvent(EVENT_AKAMA_SCENE3, 17500);
events2.ScheduleEvent(EVENT_AKAMA_SCENE4, 27000);
events2.ScheduleEvent(EVENT_AKAMA_SCENE5, 37000);
events2.ScheduleEvent(EVENT_AKAMA_SCENE6, 51000);
events2.ScheduleEvent(EVENT_AKAMA_SCENE7, 56000);
for (Creature* broken : brokens)
{
broken->SetStandState(UNIT_STAND_STATE_KNEEL);
broken->SetFaction(FACTION_DEFAULT);
broken->AI()->Talk(SAY_BROKEN_S2, 4800ms);
}
}, 4);
break;
}
}
}
void DoAction(int32 param) override
{
if (param == ACTION_SHADE_DIED)
events2.ScheduleEvent(EVENT_AKAMA_SCENE0, 1000);
if (param == ACTION_AKAMA_START_OUTRO)
{
me->SetWalk(false);
me->GetMotionMaster()->MovePoint(POINT_OUTRO, AkamaOutro);
}
}
void JustSummoned(Creature* summon) override
{
// In Retail they seem to me like they should move in formations of 3 to set points, this is simpler for now
ScriptedAI::JustSummoned(summon);
float x, y, z;
me->GetNearPoint(summon, x, y, z, 25.f, 0, me->GetAngle(summon));
summon->SetWalk(true);
summon->GetMotionMaster()->MovePoint(POINT_OUTRO, x, y, z);
}
void EnterEvadeMode(EvadeReason /*why*/) override { }
void JustDied(Unit* /*killer*/) override
{
if (Creature* shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_SHADE_OF_AKAMA)))
shade->AI()->DoAction(ACTION_AKAMA_DIED);
if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
shade->SetHomePosition(shade->GetHomePosition());
shade->AI()->EnterEvadeMode();
}
me->DespawnOrUnsummon();
}
void JustEngagedWith(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 2000);
events.ScheduleEvent(EVENT_SPELL_DESTRUCTIVE_POISON, 5000);
ScheduleTimedEvent(2s, [&]
{
DoCastVictim(SPELL_CHAIN_LIGHTNING);
}, 10s, 15s);
ScheduleTimedEvent(5s, [&]
{
DoCastVictim(SPELL_DESTRUCTIVE_POISON);
}, 4s, 15s);
}
void JustSummoned(Creature* summon) override
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override
{
float dist = frand(30.0f, 32.0f);
summon->SetWalk(true);
summon->GetMotionMaster()->MovePoint(POINT_START, summon->GetPositionX() + dist * cos(summon->GetOrientation()), summon->GetPositionY() + dist * std::sin(summon->GetOrientation()), summon->GetPositionZ(), false);
summons.Summon(summon);
CloseGossipMenuFor(player);
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->RemoveAurasDueToSpell(SPELL_STEALTH);
me->GetMotionMaster()->MovePoint(POINT_ENGAGE, AkamaEngage);
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
switch (events2.ExecuteEvent())
{
case EVENT_AKAMA_START_ENCOUNTER:
me->RemoveAura(SPELL_STEALTH);
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_START, 517.4877f, 400.7993f, 112.7837f, false);
events2.ScheduleEvent(EVENT_AKAMA_START_CHANNEL, 11000);
break;
case EVENT_AKAMA_START_CHANNEL:
me->CastSpell(me, SPELL_AKAMA_SOUL_CHANNEL, false);
if (Creature* shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_SHADE_OF_AKAMA)))
{
shade->AI()->AttackStart(me);
shade->GetMotionMaster()->Clear();
shade->AI()->DoAction(ACTION_START_ENCOUNTER);
}
break;
case EVENT_AKAMA_SCENE0:
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_CHANNEL_SOUL, 467.0f, 400.7993f, 118.537f);
break;
case EVENT_AKAMA_SCENE1:
me->CastSpell(me, SPELL_AKAMA_SOUL_RETRIEVE, true);
break;
case EVENT_AKAMA_SCENE2:
Talk(SAY_BROKEN_FREE_0);
break;
case EVENT_AKAMA_SCENE3:
me->SummonCreatureGroup(SUMMON_GROUP_BROKENS);
break;
case EVENT_AKAMA_SCENE4:
Talk(SAY_BROKEN_FREE_1);
break;
case EVENT_AKAMA_SCENE5:
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* broken = ObjectAccessor::GetCreature(*me, *itr))
broken->SetStandState(UNIT_STAND_STATE_KNEEL);
Talk(SAY_BROKEN_FREE_2);
break;
case EVENT_AKAMA_SCENE6:
if (Creature* broken = summons.GetCreatureWithEntry(NPC_ASHTONGUE_BROKEN))
broken->AI()->Talk(SAY_BROKEN_S1);
break;
case EVENT_AKAMA_SCENE7:
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* broken = ObjectAccessor::GetCreature(*me, *itr))
broken->AI()->Talk(SAY_BROKEN_S2);
break;
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_CHAIN_LIGHTNING:
me->CastSpell(me->GetVictim(), SPELL_CHAIN_LIGHTNING, false);
events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, urand(10000, 15000));
break;
case EVENT_SPELL_DESTRUCTIVE_POISON:
me->CastSpell(me, SPELL_DESTRUCTIVE_POISON, false);
events.ScheduleEvent(EVENT_SPELL_DESTRUCTIVE_POISON, urand(4000, 5000));
break;
}
scheduler.Update(diff);
DoMeleeAttackIfReady();
}
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
{
if (action == 0)
{
CloseGossipMenuFor(player);
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
events2.ScheduleEvent(EVENT_AKAMA_START_ENCOUNTER, 0);
}
}
};
struct npc_creature_generator_akama : public NullCreatureAI
struct npc_creature_generator_akama : public ScriptedAI
{
npc_creature_generator_akama(Creature* creature) : NullCreatureAI(creature), summons(me)
npc_creature_generator_akama(Creature* creature) : ScriptedAI(creature), summons(me)
{
instance = creature->GetInstanceScript();
}
uint8 spawnCounter = 0;
void Reset() override
{
events.Reset();
summons.DespawnAll();
scheduler.CancelAll();
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() == NPC_ASHTONGUE_SORCERER)
spawnCounter++;
ScriptedAI::JustSummoned(summon);
switch (summon->GetEntry())
{
std::list<Creature*> channelerList;
me->GetCreaturesWithEntryInRange(channelerList, 120.0f, NPC_ASHTONGUE_CHANNELER);
for (std::list<Creature*>::const_iterator itr = channelerList.begin(); itr != channelerList.end(); ++itr)
case NPC_ASHTONGUE_SORCERER:
if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA))
{
if ((*itr)->IsAlive() || (*itr)->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
continue;
summon->SetInCombatWithZone();
summon->SetReactState(REACT_PASSIVE);
summon->GetMotionMaster()->MovePoint(POINT_START, **itr);
(*itr)->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
return;
float x, y, z;
shade->GetNearPoint(shade, x, y, z, 20.f, 0, shade->GetAngle(summon));
summon->GetMotionMaster()->MovePoint(POINT_ENGAGE, x, y, z);
}
}
summon->SetInCombatWithZone();
if (Unit* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE)))
{
summon->AddThreat(akama, 500.0f);
summon->AI()->AttackStart(akama);
break;
default:
summon->SetInCombatWithZone();
if (Creature* akama = instance->GetCreature(DATA_AKAMA_SHADE))
summon->AI()->AttackStart(akama);
break;
}
}
void SummonedCreatureDies(Creature* summon, Unit*) override
{
spawnCounter--;
summon->DespawnOrUnsummon(10000);
summons.Despawn(summon);
}
void DoAction(int32 param) override
{
if (param == ACTION_STOP_SPAWNING || param == ACTION_DESPAWN_ALL)
switch (param)
{
events.Reset();
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
case ACTION_GENERATOR_STOP:
scheduler.CancelAll();
break;
case ACTION_GENERATOR_START:
if (me->GetPositionY() > 400.0f) // Right Side
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
ScheduleTimedEvent(10s, [&]
{
if (summon->GetEntry() != NPC_ASHTONGUE_SORCERER)
continue;
summon->InterruptNonMeleeSpells(false);
summon->GetMotionMaster()->Clear();
summon->SetInCombatWithZone();
}
if (spawnCounter <= COUNTER_SPAWNS_MAX)
DoCastSelf(SPELL_ASHTONGUE_WAVE_B);
}, 50s, 60s);
ScheduleTimedEvent(2s, 5s, [&]
{
if (spawnCounter <= COUNTER_SPAWNS_MAX)
DoCastSelf(SPELL_SUMMON_ASHTONGUE_DEFENDER);
}, 30s, 40s);
}
}
if (param == ACTION_DESPAWN_ALL)
if (me->GetPositionY() < 400.0f) // Left Side
{
ScheduleTimedEvent(3s, [&]
{
if (spawnCounter <= COUNTER_SPAWNS_MAX)
DoCastSelf(SPELL_ASHTONGUE_WAVE_B);
}, 50s, 60s);
ScheduleTimedEvent(2s, 5s, [&]
{
if (spawnCounter <= COUNTER_SPAWNS_MAX)
DoCastSelf(SPELL_SUMMON_ASHTONGUE_SORCERER);
}, 30s, 35s);
}
break;
case ACTION_GENERATOR_DESPAWN_ALL:
summons.DespawnAll();
else if (param == ACTION_NO_SORCERERS)
events.CancelEvent(EVENT_SUMMON_ASHTONGUE_SORCERER);
else if (param == ACTION_START_ENCOUNTER)
{
events.ScheduleEvent(EVENT_SUMMON_WAVE_B, 5000);
events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, 20000);
events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, 35000);
scheduler.CancelAll();
break;
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_SUMMON_WAVE_B:
me->CastSpell(me, SPELL_ASHTONGUE_WAVE_B, true);
events.ScheduleEvent(EVENT_SUMMON_WAVE_B, 45000);
break;
case EVENT_SUMMON_ASHTONGUE_SORCERER: // left
me->CastSpell(me, SPELL_SUMMON_ASHTONGUE_SORCERER, true);
events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, 45000);
break;
case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right
me->CastSpell(me, SPELL_SUMMON_ASHTONGUE_DEFENDER, true);
events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, 45000);
break;
default:
break;
}
scheduler.Update(diff);
}
private:
EventMap events;
SummonList summons;
InstanceScript* instance;
};
struct npc_ashtongue_sorcerer : public NullCreatureAI
{
npc_ashtongue_sorcerer(Creature* creature) : NullCreatureAI(creature)
{
instance = creature->GetInstanceScript();
}
void MovementInform(uint32 type, uint32 point) override
{
if (type == POINT_MOTION_TYPE && point == POINT_ENGAGE)
me->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true);
}
private:
InstanceScript* instance;
};
struct npc_ashtongue_channeler : public NullCreatureAI
{
npc_ashtongue_channeler(Creature* creature) : NullCreatureAI(creature)
{
instance = creature->GetInstanceScript();
}
void Reset() override
{
scheduler.Schedule(3600ms, [this](TaskContext context)
{
if (!me->HasUnitState(UNIT_STATE_CASTING))
me->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true);
context.Repeat();
});
}
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
}
private:
InstanceScript* instance;
TaskScheduler scheduler;
};
class spell_shade_of_akama_shade_soul_channel : public AuraScript
{
PrepareAuraScript(spell_shade_of_akama_shade_soul_channel);
@@ -562,6 +510,8 @@ void AddSC_boss_shade_of_akama()
RegisterBlackTempleCreatureAI(boss_shade_of_akama);
RegisterBlackTempleCreatureAI(npc_akama_shade);
RegisterBlackTempleCreatureAI(npc_creature_generator_akama);
RegisterBlackTempleCreatureAI(npc_ashtongue_channeler);
RegisterBlackTempleCreatureAI(npc_ashtongue_sorcerer);
RegisterSpellScript(spell_shade_of_akama_shade_soul_channel);
RegisterSpellScript(spell_shade_of_akama_akama_soul_expel);
}

View File

@@ -152,15 +152,13 @@ public:
{
}
ObjectGuid councilGUIDs[4];
void Reset() override
void EnterEvadeMode(EvadeReason why)
{
BossAI::Reset();
Creature* member = nullptr;
for (uint8 i = 0; i < 4; ++i)
if ((member = ObjectAccessor::GetCreature(*me, councilGUIDs[i])))
for (uint8 i = DATA_GATHIOS_THE_SHATTERER; i <= DATA_VERAS_DARKSHADOW; ++i)
if (Creature* member = instance->GetCreature(i))
member->AI()->EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void AttackStart(Unit*) override { }
@@ -171,15 +169,11 @@ public:
if (!me->isActiveObject() && param == ACTION_START_ENCOUNTER)
{
me->setActive(true);
councilGUIDs[0] = instance->GetGuidData(NPC_GATHIOS_THE_SHATTERER);
councilGUIDs[1] = instance->GetGuidData(NPC_HIGH_NETHERMANCER_ZEREVOR);
councilGUIDs[2] = instance->GetGuidData(NPC_LADY_MALANDE);
councilGUIDs[3] = instance->GetGuidData(NPC_VERAS_DARKSHADOW);
bool spoken = false;
for (uint8 i = 0; i < 4; ++i)
for (uint8 i = DATA_GATHIOS_THE_SHATTERER; i <= DATA_VERAS_DARKSHADOW; ++i)
{
if (Creature* member = ObjectAccessor::GetCreature(*me, councilGUIDs[i]))
if (Creature* member = instance->GetCreature(i))
{
if (!spoken && (roll_chance_i(33) || i == 3))
{
@@ -193,17 +187,15 @@ public:
}
else if (param == ACTION_ENRAGE)
{
Creature* member = nullptr;
for (uint8 i = 0; i < 4; ++i)
if ((member = ObjectAccessor::GetCreature(*me, councilGUIDs[i])))
for (uint8 i = DATA_GATHIOS_THE_SHATTERER; i <= DATA_VERAS_DARKSHADOW; ++i)
if (Creature* member = instance->GetCreature(i))
member->AI()->DoAction(ACTION_ENRAGE);
}
else if (param == ACTION_END_ENCOUNTER)
{
me->setActive(false);
Creature* member = nullptr;
for (uint8 i = 0; i < 4; ++i)
if ((member = ObjectAccessor::GetCreature(*me, councilGUIDs[i])))
for (uint8 i = DATA_GATHIOS_THE_SHATTERER; i <= DATA_VERAS_DARKSHADOW; ++i)
if (Creature* member = instance->GetCreature(i))
if (member->IsAlive())
Unit::Kill(me, member);
me->KillSelf();
@@ -217,7 +209,7 @@ public:
if (!SelectTargetFromPlayerList(115.0f))
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
return;
}
@@ -268,13 +260,13 @@ struct boss_illidari_council_memberAI : public ScriptedAI
void JustDied(Unit*) override
{
Talk(SAY_COUNCIL_DEATH);
if (Creature* council = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDARI_COUNCIL)))
if (Creature* council = instance->GetCreature(DATA_ILLIDARI_COUNCIL))
council->GetAI()->DoAction(ACTION_END_ENCOUNTER);
}
void JustEngagedWith(Unit* /*who*/) override
{
if (Creature* council = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDARI_COUNCIL)))
if (Creature* council = instance->GetCreature(DATA_ILLIDARI_COUNCIL))
council->GetAI()->DoAction(ACTION_START_ENCOUNTER);
}
};
@@ -296,14 +288,14 @@ public:
Creature* SelectCouncilMember()
{
if (roll_chance_i(50))
return ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_LADY_MALANDE));
return instance->GetCreature(DATA_LADY_MALANDE);
if (roll_chance_i(20))
if (Creature* veras = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_VERAS_DARKSHADOW)))
if (Creature* veras = instance->GetCreature(DATA_VERAS_DARKSHADOW))
if (!veras->HasAura(SPELL_VANISH))
return veras;
return ObjectAccessor::GetCreature(*me, instance->GetGuidData(RAND(NPC_GATHIOS_THE_SHATTERER, NPC_HIGH_NETHERMANCER_ZEREVOR)));
return instance->GetCreature(RAND(DATA_GATHIOS_THE_SHATTERER, DATA_HIGH_NETHERMANCER_ZEREVOR));
}
void JustEngagedWith(Unit* who) override
@@ -555,7 +547,7 @@ public:
break;
case EVENT_SPELL_ENRAGE:
DoResetThreatList();
if (Creature* council = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDARI_COUNCIL)))
if (Creature* council = instance->GetCreature(DATA_ILLIDARI_COUNCIL))
council->GetAI()->DoAction(ACTION_ENRAGE);
break;
}

View File

@@ -36,12 +36,37 @@ DoorData const doorData[] =
{ GO_MOTHER_SHAHRAZ_DOOR, DATA_MOTHER_SHAHRAZ, DOOR_TYPE_PASSAGE },
{ GO_COUNCIL_DOOR_1, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM },
{ GO_COUNCIL_DOOR_2, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM },
{ GO_ILLIDAN_GATE, DATA_AKAMA_FINISHED, DOOR_TYPE_PASSAGE },
{ GO_ILLIDAN_GATE, DATA_AKAMA_ILLIDAN, DOOR_TYPE_PASSAGE },
{ GO_ILLIDAN_DOOR_L, DATA_ILLIDAN_STORMRAGE, DOOR_TYPE_ROOM },
{ GO_ILLIDAN_DOOR_R, DATA_ILLIDAN_STORMRAGE, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM }
};
ObjectData const creatureData[] =
{
{ NPC_HIGH_WARLORD_NAJENTUS, DATA_HIGH_WARLORD_NAJENTUS },
{ NPC_SUPREMUS, DATA_SUPREMUS },
{ NPC_SHADE_OF_AKAMA, DATA_SHADE_OF_AKAMA },
{ NPC_AKAMA_SHADE, DATA_AKAMA_SHADE },
{ NPC_TERON_GOREFIEND, DATA_TERON_GOREFIEND },
{ NPC_GURTOGG_BLOODBOIL, DATA_GURTOGG_BLOODBOIL },
{ NPC_RELIQUARY_OF_THE_LOST, DATA_RELIQUARY_OF_SOULS },
{ NPC_MOTHER_SHAHRAZ, DATA_MOTHER_SHAHRAZ },
{ NPC_ILLIDARI_COUNCIL, DATA_ILLIDARI_COUNCIL },
{ NPC_GATHIOS_THE_SHATTERER, DATA_GATHIOS_THE_SHATTERER },
{ NPC_HIGH_NETHERMANCER_ZEREVOR, DATA_HIGH_NETHERMANCER_ZEREVOR },
{ NPC_LADY_MALANDE, DATA_LADY_MALANDE },
{ NPC_VERAS_DARKSHADOW, DATA_VERAS_DARKSHADOW },
{ NPC_AKAMA_ILLIDAN, DATA_AKAMA_ILLIDAN },
{ NPC_ILLIDAN_STORMRAGE, DATA_ILLIDAN_STORMRAGE },
{ 0, 0 }
};
ObjectData const objectData[] =
{
{ 0, 0 }
};
BossBoundaryData const boundaries =
{
{ DATA_HIGH_WARLORD_NAJENTUS, new RectangleBoundary(394.0f, 479.4f, 707.8f, 859.1f) },
@@ -70,6 +95,7 @@ public:
SetBossNumber(MAX_ENCOUNTERS);
LoadDoorData(doorData);
LoadBossBoundaries(boundaries);
LoadObjectData(creatureData, objectData);
ashtongueGUIDs.clear();
}
@@ -78,52 +104,19 @@ public:
{
switch (creature->GetEntry())
{
case NPC_SHADE_OF_AKAMA:
ShadeOfAkamaGUID = creature->GetGUID();
break;
case NPC_AKAMA_SHADE:
AkamaShadeGUID = creature->GetGUID();
break;
case NPC_TERON_GOREFIEND:
TeronGorefiendGUID = creature->GetGUID();
break;
case NPC_RELIQUARY_OF_THE_LOST:
ReliquaryGUID = creature->GetGUID();
break;
case NPC_GATHIOS_THE_SHATTERER:
GathiosTheShattererGUID = creature->GetGUID();
break;
case NPC_HIGH_NETHERMANCER_ZEREVOR:
HighNethermancerZerevorGUID = creature->GetGUID();
break;
case NPC_LADY_MALANDE:
LadyMalandeGUID = creature->GetGUID();
break;
case NPC_VERAS_DARKSHADOW:
VerasDarkshadowGUID = creature->GetGUID();
break;
case NPC_ILLIDARI_COUNCIL:
IllidariCouncilGUID = creature->GetGUID();
break;
case NPC_AKAMA:
AkamaGUID = creature->GetGUID();
break;
case NPC_ILLIDAN_STORMRAGE:
IllidanStormrageGUID = creature->GetGUID();
break;
case NPC_VENGEFUL_SPIRIT:
case NPC_SHADOWY_CONSTRUCT:
if (Creature* teron = instance->GetCreature(TeronGorefiendGUID))
if (Creature* teron = GetCreature(DATA_TERON_GOREFIEND))
teron->AI()->JustSummoned(creature);
break;
case NPC_ENSLAVED_SOUL:
if (Creature* reliquary = instance->GetCreature(ReliquaryGUID))
if (Creature* reliquary = GetCreature(DATA_RELIQUARY_OF_SOULS))
reliquary->AI()->JustSummoned(creature);
break;
case NPC_PARASITIC_SHADOWFIEND:
case NPC_BLADE_OF_AZZINOTH:
case NPC_FLAME_OF_AZZINOTH:
if (Creature* illidan = instance->GetCreature(IllidanStormrageGUID))
if (Creature* illidan = GetCreature(DATA_ILLIDAN_STORMRAGE))
illidan->AI()->JustSummoned(creature);
break;
case NPC_ANGERED_SOUL_FRAGMENT:
@@ -131,85 +124,38 @@ public:
case NPC_SUFFERING_SOUL_FRAGMENT:
creature->SetCorpseDelay(5);
break;
case NPC_ASHTONGUE_BATTLELORD:
case NPC_ASHTONGUE_MYSTIC:
case NPC_ASHTONGUE_STORMCALLER:
case NPC_ASHTONGUE_PRIMALIST:
case NPC_ASHTONGUE_FERAL_SPIRIT:
case NPC_ASHTONGUE_STALKER:
case NPC_STORM_FURY:
if (GetBossState(DATA_SHADE_OF_AKAMA) == DONE)
creature->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
else
ashtongueGUIDs.insert(creature->GetGUID());
break;
default:
break;
}
if (creature->GetName().find("Ashtongue") != std::string::npos || creature->GetEntry() == NPC_STORM_FURY)
{
ashtongueGUIDs.push_back(creature->GetGUID());
if (GetBossState(DATA_SHADE_OF_AKAMA) == DONE)
creature->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
}
InstanceScript::OnCreatureCreate(creature);
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
// If created after Illidari Council is done, then skip Akama's event. Used for crashes/reset
if (go->GetEntry() == GO_ILLIDAN_GATE)
{
case GO_NAJENTUS_GATE:
case GO_SUPREMUS_GATE:
case GO_SHADE_OF_AKAMA_DOOR:
case GO_TERON_DOOR_1:
case GO_TERON_DOOR_2:
case GO_GURTOGG_DOOR:
case GO_TEMPLE_DOOR:
case GO_MOTHER_SHAHRAZ_DOOR:
case GO_COUNCIL_DOOR_1:
case GO_COUNCIL_DOOR_2:
case GO_ILLIDAN_GATE:
case GO_ILLIDAN_DOOR_R:
case GO_ILLIDAN_DOOR_L:
AddDoor(go);
break;
}
}
void OnGameObjectRemove(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_NAJENTUS_GATE:
case GO_SUPREMUS_GATE:
case GO_SHADE_OF_AKAMA_DOOR:
case GO_TERON_DOOR_1:
case GO_TERON_DOOR_2:
case GO_GURTOGG_DOOR:
case GO_TEMPLE_DOOR:
case GO_MOTHER_SHAHRAZ_DOOR:
case GO_COUNCIL_DOOR_1:
case GO_COUNCIL_DOOR_2:
case GO_ILLIDAN_GATE:
case GO_ILLIDAN_DOOR_R:
case GO_ILLIDAN_DOOR_L:
RemoveDoor(go);
break;
}
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case NPC_SHADE_OF_AKAMA:
return ShadeOfAkamaGUID;
case NPC_AKAMA_SHADE:
return AkamaShadeGUID;
case NPC_GATHIOS_THE_SHATTERER:
return GathiosTheShattererGUID;
case NPC_HIGH_NETHERMANCER_ZEREVOR:
return HighNethermancerZerevorGUID;
case NPC_LADY_MALANDE:
return LadyMalandeGUID;
case NPC_VERAS_DARKSHADOW:
return VerasDarkshadowGUID;
case NPC_ILLIDARI_COUNCIL:
return IllidariCouncilGUID;
case NPC_AKAMA:
return AkamaGUID;
case NPC_ILLIDAN_STORMRAGE:
return IllidanStormrageGUID;
if (GetBossState(DATA_ILLIDARI_COUNCIL) == DONE)
{
SetBossState(DATA_AKAMA_ILLIDAN, DONE);
HandleGameObject(ObjectGuid::Empty, true, go);
}
}
return ObjectGuid::Empty;
InstanceScript::OnGameObjectCreate(go);
}
bool SetBossState(uint32 type, EncounterState state) override
@@ -225,26 +171,15 @@ public:
}
else if (type == DATA_ILLIDARI_COUNCIL && state == DONE)
{
if (Creature* akama = instance->GetCreature(AkamaGUID))
akama->SetVisible(true);
if (Creature* akama = GetCreature(DATA_AKAMA_ILLIDAN))
akama->AI()->DoAction(0);
}
return true;
}
protected:
ObjectGuid ShadeOfAkamaGUID;
ObjectGuid AkamaShadeGUID;
ObjectGuid TeronGorefiendGUID;
ObjectGuid ReliquaryGUID;
GuidList ashtongueGUIDs;
ObjectGuid GathiosTheShattererGUID;
ObjectGuid HighNethermancerZerevorGUID;
ObjectGuid LadyMalandeGUID;
ObjectGuid VerasDarkshadowGUID;
ObjectGuid IllidariCouncilGUID;
ObjectGuid AkamaGUID;
ObjectGuid IllidanStormrageGUID;
GuidSet ashtongueGUIDs;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override