Scripts/BoT: updated and modernized Halfus Wyrmbreaker encounter
* moved several mechanics from instance script into the boss script itself * changed the unresponsive dragon selection from two saved variables into a single generated flag * corrected timer layout for the Proto-Behemoth and handled a missing mechanic of the Time-Dilation debuff * moved all encounter spawns into spawngroups * simplified and cleaned up the dragon ads script
This commit is contained in:
1 parent
d8ef0352e1
commit
abfddaa915
4 files changed
+437
-413
No files matched your search
@@ -63,11 +63,12 @@ enum BoTDataTypes
|
||||
|
||||
// Encounter Related
|
||||
/*Halfus Wyrmbreaker*/
|
||||
DATA_UNRESPONSIVE_DRAGON_FIRST,
|
||||
DATA_UNRESPONSIVE_DRAGON_SECOND,
|
||||
DATA_CAST_DRAGON_BUFFS,
|
||||
DATA_DRAGON_CAGE_ENABLED,
|
||||
DATA_OPEN_ORPHANED_EMERALD_WHELP_CAGE,
|
||||
DATA_ACTIVE_DRAGON_FLAGS,
|
||||
DATA_SLATE_DRAGON,
|
||||
DATA_NETHER_SCION,
|
||||
DATA_STORM_RIDER,
|
||||
DATA_TIME_WARDEN,
|
||||
DATA_WHELP_CAGE,
|
||||
|
||||
/*Theralion and Valiona*/
|
||||
DATA_RANDOM_VALIONA_DUMMY,
|
||||
@@ -78,12 +79,6 @@ enum BoTDataTypes
|
||||
DATA_FULL_HEROIC_ID
|
||||
};
|
||||
|
||||
enum BoTDataStates
|
||||
{
|
||||
DRAGON_BUFFS_HALFUS_WYRMBREAKER = 0,
|
||||
DRAGON_BUFFS_PROTO_BEHEMOTH,
|
||||
};
|
||||
|
||||
enum BoTCreatures
|
||||
{
|
||||
// Bosses
|
||||
@@ -160,13 +155,7 @@ enum BoTGameObjects
|
||||
enum BoTActions
|
||||
{
|
||||
// Halfus Wyrmbreaker
|
||||
ACTION_ENABLE_MALEVOLENT_STRIKES = 1,
|
||||
ACTION_ENABLE_FRENZIED_ASSAULT = 2,
|
||||
ACTION_ENABLE_SHADOW_NOVA = 3,
|
||||
ACTION_ENABLE_FIREBALL_BARRAGE = 1,
|
||||
ACTION_ENABLE_SCORCHING_BREATH = 2,
|
||||
ACTION_CAST_DRAGONS_VENGEANCE = 3,
|
||||
ACTION_MOVE_OUT_OF_CAGE = 4,
|
||||
ACTION_DRAGON_FREED = 0,
|
||||
|
||||
// Theralion and Valiona
|
||||
ACTION_START_ARGUMENT_INTRO = 1,
|
||||
@@ -208,6 +197,17 @@ enum BoTWorldStates
|
||||
WORLD_STATE_ID_THE_ABYSS_WILL_GAZE_BACK_INTO_YOU = 5659
|
||||
};
|
||||
|
||||
enum BoTHalfusDragonFlags : uint8
|
||||
{
|
||||
DRAGON_FLAG_NETHER_SCION = 0x01,
|
||||
DRAGON_FLAG_SLATE_DRAGON = 0x02,
|
||||
DRAGON_FLAG_STORM_RIDER = 0x04,
|
||||
DRAGON_FLAG_TIME_WARDEN = 0x08,
|
||||
DRAGON_FLAG_EMERALD_WHELPS = 0x10,
|
||||
|
||||
DRAGON_FLAG_ALL_ACTIVE = DRAGON_FLAG_NETHER_SCION | DRAGON_FLAG_SLATE_DRAGON | DRAGON_FLAG_STORM_RIDER | DRAGON_FLAG_TIME_WARDEN | DRAGON_FLAG_EMERALD_WHELPS
|
||||
};
|
||||
|
||||
template<class AI>
|
||||
AI* GetBastionOfTwilightAI(Creature* creature)
|
||||
{
|
||||
|
||||
+228
-212
@@ -48,6 +48,7 @@ enum Spells
|
||||
SPELL_DANCING_FLAMES = 84106,
|
||||
SPELL_SUPERHEATED_BREATH = 83956,
|
||||
SPELL_FIREBALL = 86058,
|
||||
SPELL_FIREBALL_SLOW = 83862,
|
||||
SPELL_FIREBALL_BARRAGE = 83706,
|
||||
SPELL_FIREBALL_BARRAGE_FAST = 83720,
|
||||
SPELL_FIREBALL_BARRAGE_SLOW = 83733,
|
||||
@@ -69,7 +70,7 @@ enum Events
|
||||
// Halfus Wyrmbreaker
|
||||
EVENT_SHADOW_NOVA = 1,
|
||||
EVENT_FURIOUS_ROAR,
|
||||
EVENT_RESET_ACHIEVEMT,
|
||||
EVENT_RESET_ACHIEVEMENT,
|
||||
EVENT_BERSERK,
|
||||
|
||||
// Proto-Behemoth
|
||||
@@ -81,7 +82,13 @@ enum Events
|
||||
EVENT_LIFTOFF,
|
||||
EVENT_CAST_DEBUFF,
|
||||
EVENT_BIND_TO_HALFUS_WILL,
|
||||
EVENT_MOVE_OUT_OF_CAGE
|
||||
EVENT_MOVE_OUT_OF_CAGE,
|
||||
EVENT_ENGAGE_WITH_PLAYERS
|
||||
};
|
||||
|
||||
enum Actions
|
||||
{
|
||||
ACTION_ORPHANED_EMERALD_WHELP_KILLED = 0,
|
||||
};
|
||||
|
||||
enum Texts
|
||||
@@ -93,47 +100,26 @@ enum Texts
|
||||
SAY_ANNOUNCE_FURIOUS_ROAR = 3
|
||||
};
|
||||
|
||||
Position const SpikePositions[] =
|
||||
enum SpawnGroups
|
||||
{
|
||||
{ -348.538f, -700.247f, 888.19f, 5.53269f },
|
||||
{ -353.764f, -706.361f, 888.19f, 2.30383f },
|
||||
{ -352.804f, -695.064f, 888.19f, 5.35816f },
|
||||
{ -358.964f, -702.148f, 888.19f, 2.30383f },
|
||||
{ -320.158f, -727.995f, 888.191f, 3.24631f },
|
||||
{ -274.891f, -656.835f, 888.189f, 4.95674f },
|
||||
{ -284.868f, -661.151f, 888.19f, 1.71042f },
|
||||
{ -277.955f, -687.788f, 888.192f, 3.15905f },
|
||||
{ -314.986f, -717.396f, 888.19f, 0.261799f },
|
||||
{ -280.724f, -674.46f, 888.19f, 0.0872665f },
|
||||
{ -273.922f, -675.948f, 888.189f, 6.19592f },
|
||||
{ -283.142f, -685.325f, 888.191f, 3.15905f },
|
||||
{ -321.974f, -718.424f, 888.191f, 0.383972f },
|
||||
{ -273.01f, -684.694f, 888.191f, 3.15905f }
|
||||
SPAWN_GROUP_ID_ENCOUNTER_SETUP = 462
|
||||
};
|
||||
|
||||
Position const OrphanedEmeraldWhelpPositions[] =
|
||||
struct EncounterDragonData
|
||||
{
|
||||
{ -342.002f, -726.528f, 891.764f, 1.16937f },
|
||||
{ -340.75f, -722.476f, 891.764f, 1.16937f },
|
||||
{ -350.564f, -721.663f, 891.763f, 1.01229f },
|
||||
{ -347.08f, -728.128f, 891.764f, 1.11701f },
|
||||
{ -346.434f, -724.049f, 891.764f, 1.09956f },
|
||||
{ -347.578f, -717.302f, 891.763f, 1.0472f },
|
||||
{ -350.571f, -725.417f, 891.763f, 1.06465f },
|
||||
{ -344.839f, -720.163f, 891.764f, 1.0821f }
|
||||
uint32 DataType = 0;
|
||||
uint32 EncounterCreatureId = 0;
|
||||
};
|
||||
|
||||
Position const NetherScionPos = { -280.118f, -659.385f, 888.188f, 1.67552f };
|
||||
Position const SlateDragonPos = { -279.111f, -680.594f, 888.191f, 3.10669f };
|
||||
Position const StormRiderPos = { -318.705f, -722.688f, 888.191f, 3.19395f };
|
||||
Position const TimeWardenPos = { -353.179f, -700.667f, 888.19f, 5.53269f };
|
||||
Position const ProtoBehemothPos = { -265.891f, -740.023f, 907.363f, 2.33874f };
|
||||
static constexpr std::array<EncounterDragonData, 4> const DragonData =
|
||||
{
|
||||
EncounterDragonData(DATA_SLATE_DRAGON, NPC_SLATE_DRAGON_ENCOUNTER),
|
||||
EncounterDragonData(DATA_NETHER_SCION, NPC_NETHER_SCION_ENCOUNTER),
|
||||
EncounterDragonData(DATA_STORM_RIDER, NPC_STORM_RIDER_ENCOUNTER),
|
||||
EncounterDragonData(DATA_TIME_WARDEN, NPC_TIME_WARDEN_ENCOUNTER)
|
||||
};
|
||||
|
||||
Position const WhelpCageBasePos = { -346.672f, -723.26f, 888.106f, 5.53269f };
|
||||
QuaternionData const WhelpCageBaseRot = QuaternionData(0.0f, 0.0f, -0.366501f, 0.930418f);
|
||||
|
||||
Position const WhelpCagePos = { -346.672f, -723.26f, 888.106f, 5.53269f };
|
||||
QuaternionData const WhelpCageRot = QuaternionData(0.0f, 0.0f, -0.366501f, 0.930418f);
|
||||
static constexpr uint8 OrphanedEmeraldWhelpPackSize = 8;
|
||||
|
||||
struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
{
|
||||
@@ -142,29 +128,17 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
instance->SetData(DATA_CAST_DRAGON_BUFFS, DRAGON_BUFFS_HALFUS_WYRMBREAKER);
|
||||
uint8 activeDragonFlags = static_cast<uint8>(instance->GetData(DATA_ACTIVE_DRAGON_FLAGS));
|
||||
if ((activeDragonFlags & DRAGON_FLAG_SLATE_DRAGON) != 0)
|
||||
DoCastSelf(SPELL_MALEVOLENT_STRIKES);
|
||||
|
||||
if (GameObject* cageBase = me->SummonGameObject(GO_WHELP_CAGE_BASE, WhelpCageBasePos, WhelpCageBaseRot, WEEK, GO_SUMMON_TIMED_DESPAWN))
|
||||
_cageBaseGUID = cageBase->GetGUID();
|
||||
if ((activeDragonFlags & DRAGON_FLAG_NETHER_SCION) != 0)
|
||||
DoCastSelf(SPELL_FRENZIED_ASSAULT);
|
||||
|
||||
if (GameObject* cage = me->SummonGameObject(GO_WHELP_CAGE, WhelpCagePos, WhelpCageRot, WEEK, GO_SUMMON_TIMED_DESPAWN))
|
||||
_cageGUID = cage->GetGUID();
|
||||
if ((activeDragonFlags & DRAGON_FLAG_STORM_RIDER) != 0)
|
||||
DoCastSelf(SPELL_SHADOW_WRAPPED);
|
||||
|
||||
if (Map* map = me->GetMap())
|
||||
{
|
||||
map->SummonCreature(NPC_NETHER_SCION, NetherScionPos);
|
||||
map->SummonCreature(NPC_SLATE_DRAGON, SlateDragonPos);
|
||||
map->SummonCreature(NPC_STORM_RIDER, StormRiderPos);
|
||||
map->SummonCreature(NPC_TIME_WARDEN, TimeWardenPos);
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < 8; i++)
|
||||
DoSummon(NPC_ORPHANED_EMERALD_WELP, OrphanedEmeraldWhelpPositions[i]);
|
||||
|
||||
for (uint8 i = 0; i < 14; i++)
|
||||
DoSummon(NPC_SPIKE, SpikePositions[i]);
|
||||
|
||||
DoSummon(NPC_PROTO_BEHEMOTH, ProtoBehemothPos);
|
||||
instance->instance->SpawnGroupSpawn(SPAWN_GROUP_ID_ENCOUNTER_SETUP, true);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
@@ -176,19 +150,24 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
events.ScheduleEvent(EVENT_BERSERK, 10min);
|
||||
|
||||
if (Creature* protoBehemoth = instance->GetCreature(DATA_PROTO_BEHEMOTH))
|
||||
protoBehemoth->AI()->DoZoneInCombat();
|
||||
DoZoneInCombat(protoBehemoth);
|
||||
|
||||
if (instance->GetData(DATA_DRAGON_CAGE_ENABLED))
|
||||
if (GameObject* cage = ObjectAccessor::GetGameObject(*me, _cageGUID))
|
||||
for (EncounterDragonData const& dragonData : DragonData)
|
||||
if (Creature* dragon = instance->GetCreature(dragonData.DataType))
|
||||
if (dragon->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
|
||||
dragon->UpdateEntry(dragonData.EncounterCreatureId);
|
||||
|
||||
if ((static_cast<uint8>(instance->GetData(DATA_ACTIVE_DRAGON_FLAGS) & DRAGON_FLAG_EMERALD_WHELPS) != 0))
|
||||
if (GameObject* cage = instance->GetGameObject(DATA_WHELP_CAGE))
|
||||
cage->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
|
||||
if (me->HasAura(SPELL_SHADOW_WRAPPED))
|
||||
events.ScheduleEvent(EVENT_SHADOW_NOVA, Seconds(7));
|
||||
events.ScheduleEvent(EVENT_SHADOW_NOVA, 7s);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
if (victim->IsPlayer())
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
@@ -196,12 +175,7 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
{
|
||||
_JustDied();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
if (GameObject* cage = ObjectAccessor::GetGameObject(*me, _cageGUID))
|
||||
cage->DespawnOrUnsummon();
|
||||
|
||||
if (GameObject* cageBase = ObjectAccessor::GetGameObject(*me, _cageBaseGUID))
|
||||
cageBase->DespawnOrUnsummon();
|
||||
instance->instance->SpawnGroupDespawn(SPAWN_GROUP_ID_ENCOUNTER_SETUP);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
@@ -209,13 +183,7 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
_EnterEvadeMode();
|
||||
summons.DespawnAll();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
|
||||
if (GameObject* cage = ObjectAccessor::GetGameObject(*me, _cageGUID))
|
||||
cage->DespawnOrUnsummon();
|
||||
|
||||
if (GameObject* cageBase = ObjectAccessor::GetGameObject(*me, _cageBaseGUID))
|
||||
cageBase->DespawnOrUnsummon();
|
||||
|
||||
instance->instance->SpawnGroupDespawn(SPAWN_GROUP_ID_ENCOUNTER_SETUP);
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
@@ -240,13 +208,13 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
{
|
||||
_theOnlyEscapeAchievementState = IN_PROGRESS;
|
||||
instance->DoUpdateWorldState(WORLD_STATE_ID_THE_ONLY_ESCAPE, 1);
|
||||
events.ScheduleEvent(EVENT_RESET_ACHIEVEMT, Seconds(10));
|
||||
events.ScheduleEvent(EVENT_RESET_ACHIEVEMENT, 10s);
|
||||
}
|
||||
else if (_theOnlyEscapeAchievementState == IN_PROGRESS)
|
||||
{
|
||||
_theOnlyEscapeAchievementState = DONE;
|
||||
instance->DoUpdateWorldState(WORLD_STATE_ID_THE_ONLY_ESCAPE, 2);
|
||||
events.CancelEvent(EVENT_RESET_ACHIEVEMT);
|
||||
events.CancelEvent(EVENT_RESET_ACHIEVEMENT);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -263,24 +231,6 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_ENABLE_MALEVOLENT_STRIKES:
|
||||
me->AddAura(SPELL_MALEVOLENT_STRIKES, me);
|
||||
break;
|
||||
case ACTION_ENABLE_FRENZIED_ASSAULT:
|
||||
me->AddAura(SPELL_FRENZIED_ASSAULT, me);
|
||||
break;
|
||||
case ACTION_ENABLE_SHADOW_NOVA:
|
||||
me->AddAura(SPELL_SHADOW_WRAPPED, me);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
@@ -316,7 +266,7 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
_furiousRoarCount = 0;
|
||||
}
|
||||
break;
|
||||
case EVENT_RESET_ACHIEVEMT:
|
||||
case EVENT_RESET_ACHIEVEMENT:
|
||||
_theOnlyEscapeAchievementState = NOT_STARTED;
|
||||
break;
|
||||
case EVENT_BERSERK:
|
||||
@@ -331,8 +281,6 @@ struct boss_halfus_wyrmbreaker final : public BossAI
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _cageGUID;
|
||||
ObjectGuid _cageBaseGUID;
|
||||
bool _announcedOrphanedEmeraldWhelpBinding;
|
||||
bool _furiousRoarEnabled;
|
||||
uint8 _theOnlyEscapeAchievementState;
|
||||
@@ -341,36 +289,45 @@ private:
|
||||
|
||||
struct npc_halfus_proto_behemoth final : public PassiveAI
|
||||
{
|
||||
npc_halfus_proto_behemoth(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) {}
|
||||
npc_halfus_proto_behemoth(Creature* creature) : PassiveAI(creature), _instance(nullptr), _killedEmeraldWhelps(0) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
_instance = me->GetInstanceScript();
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
uint8 activeDragonFlags = static_cast<uint8>(_instance->GetData(DATA_ACTIVE_DRAGON_FLAGS));
|
||||
if ((activeDragonFlags & DRAGON_FLAG_EMERALD_WHELPS) != 0)
|
||||
DoCastSelf(SPELL_SUPERHEATED_BREATH);
|
||||
|
||||
if ((activeDragonFlags & DRAGON_FLAG_TIME_WARDEN) != 0)
|
||||
DoCastSelf(SPELL_DANCING_FLAMES);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_FIREBALL, 1s);
|
||||
|
||||
if (me->HasAura(SPELL_DANCING_FLAMES))
|
||||
{
|
||||
_events.ScheduleEvent(EVENT_FIREBALL_BARRAGE, 13s);
|
||||
|
||||
if (me->HasAura(SPELL_SUPERHEATED_BREATH))
|
||||
_events.ScheduleEvent(EVENT_SCORCHING_BREATH, 24s);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
_instance->SetData(DATA_CAST_DRAGON_BUFFS, DRAGON_BUFFS_PROTO_BEHEMOTH);
|
||||
if (me->HasAura(SPELL_SUPERHEATED_BREATH))
|
||||
_events.ScheduleEvent(EVENT_SCORCHING_BREATH, 24s);
|
||||
}
|
||||
else if (me->HasAura(SPELL_SUPERHEATED_BREATH))
|
||||
_events.ScheduleEvent(EVENT_SCORCHING_BREATH, 13s);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_CAST_DRAGONS_VENGEANCE:
|
||||
DoCastSelf(SPELL_DRAGONS_VENGEANCE, true);
|
||||
break;
|
||||
case ACTION_ENABLE_SCORCHING_BREATH:
|
||||
me->AddAura(SPELL_SUPERHEATED_BREATH, me);
|
||||
break;
|
||||
case ACTION_ENABLE_FIREBALL_BARRAGE:
|
||||
me->AddAura(SPELL_DANCING_FLAMES, me);
|
||||
case ACTION_ORPHANED_EMERALD_WHELP_KILLED:
|
||||
++_killedEmeraldWhelps;
|
||||
if (_killedEmeraldWhelps == OrphanedEmeraldWhelpPackSize)
|
||||
DoCastAOE(SPELL_DRAGONS_VENGEANCE, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -389,16 +346,26 @@ struct npc_halfus_proto_behemoth final : public PassiveAI
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FIREBALL:
|
||||
DoCastAOE(SPELL_FIREBALL);
|
||||
_events.Repeat(2s + 500ms);
|
||||
if (!me->HasAura(SPELL_TIME_DILATION))
|
||||
{
|
||||
DoCastAOE(SPELL_FIREBALL, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_MAX_TARGETS, 1));
|
||||
_events.Repeat(2s + 500ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastAOE(SPELL_FIREBALL_SLOW, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_MAX_TARGETS, 1));
|
||||
_events.Repeat(3s + 500ms);
|
||||
}
|
||||
break;
|
||||
case EVENT_FIREBALL_BARRAGE:
|
||||
DoCastSelf(SPELL_FIREBALL_BARRAGE);
|
||||
_events.Repeat(31s);
|
||||
_events.RescheduleEvent(EVENT_FIREBALL, 11s);
|
||||
break;
|
||||
case EVENT_SCORCHING_BREATH:
|
||||
DoCastSelf(SPELL_SCORCHING_BREATH);
|
||||
_events.Repeat(31s);
|
||||
_events.RescheduleEvent(EVENT_FIREBALL, 11s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -409,25 +376,19 @@ struct npc_halfus_proto_behemoth final : public PassiveAI
|
||||
private:
|
||||
EventMap _events;
|
||||
InstanceScript* _instance;
|
||||
uint8 _killedEmeraldWhelps;
|
||||
};
|
||||
|
||||
struct npc_halfus_enslaved_dragon final : public ScriptedAI
|
||||
{
|
||||
npc_halfus_enslaved_dragon(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) {}
|
||||
npc_halfus_enslaved_dragon(Creature* creature) : ScriptedAI(creature), _instance(nullptr) { }
|
||||
|
||||
void Reset() override
|
||||
void InitializeAI() override
|
||||
{
|
||||
_events.Reset();
|
||||
|
||||
if (_instance->GetData(DATA_UNRESPONSIVE_DRAGON_FIRST) == me->GetEntry()
|
||||
|| _instance->GetData(DATA_UNRESPONSIVE_DRAGON_SECOND) == me->GetEntry())
|
||||
{
|
||||
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
if (me->GetEntry() == NPC_ORPHANED_EMERALD_WELP)
|
||||
DoCastSelf(SPELL_UNRESPONSIVE_WHELP, true);
|
||||
else
|
||||
DoCastSelf(SPELL_UNRESPONSIVE_DRAGON, true);
|
||||
}
|
||||
_instance = me->GetInstanceScript();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
if (isUnresponsive())
|
||||
DoCastSelf(me->GetEntry() != NPC_ORPHANED_EMERALD_WELP ? SPELL_UNRESPONSIVE_DRAGON : SPELL_UNRESPONSIVE_WHELP);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -436,28 +397,35 @@ struct npc_halfus_enslaved_dragon final : public ScriptedAI
|
||||
me->SendSetPlayHoverAnim(false);
|
||||
me->DespawnOrUnsummon(6s);
|
||||
|
||||
if (me->GetEntry() != NPC_ORPHANED_EMERALD_WELP)
|
||||
if (Creature* protoBehemoth = _instance->GetCreature(DATA_PROTO_BEHEMOTH))
|
||||
protoBehemoth->AI()->DoAction(ACTION_CAST_DRAGONS_VENGEANCE);
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->HasEffect(SPELL_EFFECT_SEND_EVENT))
|
||||
if (Creature* protoBehemoth = _instance->GetCreature(DATA_PROTO_BEHEMOTH))
|
||||
{
|
||||
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
me->RemoveAllAuras();
|
||||
_events.ScheduleEvent(EVENT_LIFTOFF, 1ms);
|
||||
if (me->GetOriginalEntry() != NPC_ORPHANED_EMERALD_WELP)
|
||||
protoBehemoth->CastSpell(nullptr, SPELL_DRAGONS_VENGEANCE, true);
|
||||
else if (CreatureAI* ai = protoBehemoth->AI())
|
||||
ai->DoAction(ACTION_ORPHANED_EMERALD_WHELP_KILLED);
|
||||
}
|
||||
else if (spell->Id == SPELL_BIND_WILL_TRIGGERED)
|
||||
if (Player* player = me->SelectNearestPlayer(100.0f))
|
||||
me->AI()->AttackStart(player);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_MOVE_OUT_OF_CAGE)
|
||||
_events.ScheduleEvent(EVENT_MOVE_OUT_OF_CAGE, 250ms);
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_DRAGON_FREED:
|
||||
if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
|
||||
{
|
||||
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
me->RemoveAllAuras();
|
||||
_events.ScheduleEvent(EVENT_LIFTOFF, 1ms);
|
||||
}
|
||||
else if (me->GetEntry() == NPC_ORPHANED_EMERALD_WELP && me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
|
||||
{
|
||||
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
_events.ScheduleEvent(EVENT_MOVE_OUT_OF_CAGE, 1ms);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -475,20 +443,21 @@ struct npc_halfus_enslaved_dragon final : public ScriptedAI
|
||||
{
|
||||
case EVENT_LIFTOFF:
|
||||
{
|
||||
Position pos = me->GetPosition();
|
||||
pos.m_positionZ += 5.5f;
|
||||
me->GetMotionMaster()->MoveTakeoff(0, pos);
|
||||
_events.ScheduleEvent(EVENT_CAST_DEBUFF, 1s + 800ms);
|
||||
Position const pos = Position(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 5.5f, me->GetOrientation());
|
||||
me->GetMotionMaster()->MoveTakeoff(0, pos, 4.f);
|
||||
me->SetDisableGravity(true);
|
||||
me->SetHover(true);
|
||||
_events.ScheduleEvent(EVENT_CAST_DEBUFF, 2s + 500ms);
|
||||
break;
|
||||
}
|
||||
case EVENT_MOVE_OUT_OF_CAGE:
|
||||
{
|
||||
float angle = me->GetOrientation();
|
||||
float x = me->GetPositionX() + cos(angle) * 20.0f;
|
||||
float y = me->GetPositionY() + sin(angle) * 20.0f;
|
||||
float x = me->GetPositionX() + std::cos(angle) * 20.f;
|
||||
float y = me->GetPositionY() + std::sin(angle) * 20.f;
|
||||
float z = 888.1f;
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z, true);
|
||||
_events.ScheduleEvent(EVENT_CAST_DEBUFF, 2s + 600ms);
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z);
|
||||
_events.ScheduleEvent(EVENT_CAST_DEBUFF, 2s + 500ms);
|
||||
break;
|
||||
}
|
||||
case EVENT_CAST_DEBUFF:
|
||||
@@ -499,43 +468,43 @@ struct npc_halfus_enslaved_dragon final : public ScriptedAI
|
||||
if (!halfus || !protoBehemoth)
|
||||
break;
|
||||
|
||||
if (me->GetEntry() != NPC_ORPHANED_EMERALD_WELP)
|
||||
{
|
||||
me->SetDisableGravity(true);
|
||||
me->SetHover(true);
|
||||
}
|
||||
|
||||
switch (me->GetEntry())
|
||||
{
|
||||
case NPC_NETHER_SCION_ENCOUNTER:
|
||||
me->SetFacingToObject(halfus);
|
||||
DoCastSelf(SPELL_NETHER_BLINDNESS, true);
|
||||
DoCastSelf(SPELL_NETHER_BLINDNESS);
|
||||
break;
|
||||
case NPC_SLATE_DRAGON_ENCOUNTER:
|
||||
me->SetFacingToObject(halfus);
|
||||
DoCastSelf(SPELL_STONE_TOUCH, true);
|
||||
DoCastSelf(SPELL_STONE_TOUCH);
|
||||
break;
|
||||
case NPC_STORM_RIDER_ENCOUNTER:
|
||||
me->SetFacingToObject(halfus);
|
||||
DoCastSelf(SPELL_CYCLONE_WINDS, true);
|
||||
DoCastSelf(SPELL_CYCLONE_WINDS);
|
||||
break;
|
||||
case NPC_TIME_WARDEN_ENCOUNTER:
|
||||
me->SetFacingToObject(protoBehemoth);
|
||||
DoCastSelf(SPELL_TIME_DILATION, true);
|
||||
DoCastSelf(SPELL_TIME_DILATION);
|
||||
break;
|
||||
case NPC_ORPHANED_EMERALD_WELP:
|
||||
me->SetFacingToObject(protoBehemoth);
|
||||
DoCastSelf(SPELL_ATROPHIC_POISON, true);
|
||||
DoCastSelf(SPELL_ATROPHIC_POISON);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_events.ScheduleEvent(EVENT_BIND_TO_HALFUS_WILL, 1s + 850ms);
|
||||
_events.ScheduleEvent(EVENT_BIND_TO_HALFUS_WILL, 2s);
|
||||
break;
|
||||
}
|
||||
case EVENT_BIND_TO_HALFUS_WILL:
|
||||
if (_instance->GetCreature(DATA_HALFUS_WYRMBREAKER))
|
||||
DoCastSelf(SPELL_BIND_WILL, true);
|
||||
DoCastSelf(SPELL_BIND_WILL);
|
||||
_events.ScheduleEvent(EVENT_ENGAGE_WITH_PLAYERS, 1s);
|
||||
break;
|
||||
case EVENT_ENGAGE_WITH_PLAYERS:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
if (!me->IsEngaged())
|
||||
if (Unit* target = me->SelectNearestTarget(100.f))
|
||||
me->EngageWithTarget(target);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -547,6 +516,27 @@ struct npc_halfus_enslaved_dragon final : public ScriptedAI
|
||||
private:
|
||||
EventMap _events;
|
||||
InstanceScript* _instance;
|
||||
|
||||
bool isUnresponsive()
|
||||
{
|
||||
uint8 activeDragonFlags = static_cast<uint8>(_instance->GetData(DATA_ACTIVE_DRAGON_FLAGS));
|
||||
if (me->GetEntry() == NPC_SLATE_DRAGON && (activeDragonFlags & DRAGON_FLAG_SLATE_DRAGON) == 0)
|
||||
return true;
|
||||
|
||||
if (me->GetEntry() == NPC_NETHER_SCION && (activeDragonFlags & DRAGON_FLAG_NETHER_SCION) == 0)
|
||||
return true;
|
||||
|
||||
if (me->GetEntry() == NPC_STORM_RIDER && (activeDragonFlags & DRAGON_FLAG_STORM_RIDER) == 0)
|
||||
return true;
|
||||
|
||||
if (me->GetEntry() == NPC_TIME_WARDEN && (activeDragonFlags & DRAGON_FLAG_TIME_WARDEN) == 0)
|
||||
return true;
|
||||
|
||||
if (me->GetEntry() == NPC_ORPHANED_EMERALD_WELP && (activeDragonFlags & DRAGON_FLAG_EMERALD_WHELPS) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct go_halfus_whelp_cage final : public GameObjectAI
|
||||
@@ -555,8 +545,18 @@ struct go_halfus_whelp_cage final : public GameObjectAI
|
||||
|
||||
bool OnReportUse(Player* /*player*/) override
|
||||
{
|
||||
if (me->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE))
|
||||
return true;
|
||||
|
||||
me->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
_instance->SetData(DATA_OPEN_ORPHANED_EMERALD_WHELP_CAGE, DONE);
|
||||
|
||||
// There is no event linked to releasing the whelps so we have to resort to grid searching.
|
||||
std::vector<Creature*> whelpVector;
|
||||
me->GetCreatureListWithEntryInGrid(whelpVector, NPC_ORPHANED_EMERALD_WELP, 20.f);
|
||||
for (Creature* whelp : whelpVector)
|
||||
if (CreatureAI* ai = whelp->AI())
|
||||
ai->DoAction(ACTION_DRAGON_FREED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -584,35 +584,51 @@ class spell_halfus_fireball final : public SpellScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_FIREBALL_BARRAGE_FAST,
|
||||
SPELL_FIREBALL_BARRAGE_SLOW
|
||||
});
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
Trinity::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (!caster->HasAura(SPELL_TIME_DILATION))
|
||||
caster->CastSpell(GetHitUnit(), SPELL_FIREBALL_BARRAGE_FAST, true);
|
||||
else
|
||||
caster->CastSpell(GetHitUnit(), SPELL_FIREBALL_BARRAGE_SLOW, true);
|
||||
}
|
||||
SPELL_FIREBALL_SLOW,
|
||||
SPELL_FIREBALL_BARRAGE_FAST,
|
||||
SPELL_FIREBALL_BARRAGE_SLOW
|
||||
});
|
||||
}
|
||||
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), GetSpellInfo()->Id == SPELL_FIREBALL_SLOW ? SPELL_FIREBALL_BARRAGE_SLOW : SPELL_FIREBALL_BARRAGE_FAST, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect.Register(&spell_halfus_fireball::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
OnEffectHitTarget.Register(&spell_halfus_fireball::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnEffectHitTarget.Register(&spell_halfus_fireball::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_halfus_fireball_barrage final : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
SPELL_FIREBALL_BARRAGE_FAST,
|
||||
SPELL_FIREBALL_BARRAGE_SLOW,
|
||||
SPELL_TIME_DILATION
|
||||
});
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.size() > 1)
|
||||
Trinity::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
|
||||
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), GetCaster()->HasAura(SPELL_TIME_DILATION) ? SPELL_FIREBALL_BARRAGE_SLOW : SPELL_FIREBALL_BARRAGE_FAST, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect.Register(&spell_halfus_fireball_barrage::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
OnEffectHitTarget.Register(&spell_halfus_fireball_barrage::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -657,33 +673,17 @@ class spell_halfus_cyclone_winds final : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class DancingFlamesDistanceCheck
|
||||
{
|
||||
public:
|
||||
DancingFlamesDistanceCheck(Unit* caster) : _caster(caster) { }
|
||||
|
||||
bool operator()(WorldObject* object)
|
||||
{
|
||||
return (object->GetDistance2d(_caster) <= 40.0f || object->GetDistance2d(_caster) >= 100.0f);
|
||||
}
|
||||
private:
|
||||
Unit* _caster;
|
||||
};
|
||||
|
||||
class spell_halfus_dancing_flames final : public SpellScript
|
||||
{
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
if (targets.size() < 1)
|
||||
return;
|
||||
|
||||
if (Unit* caster = GetCaster())
|
||||
targets.remove_if(DancingFlamesDistanceCheck(caster));
|
||||
targets.remove_if([caster = GetCaster()](WorldObject const* target) { return (target->GetDistance2d(caster) <= 40.0f || target->GetDistance2d(caster) >= 100.0f); });
|
||||
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
Trinity::Containers::RandomResize(targets, 1);
|
||||
if (targets.size() > 1)
|
||||
Trinity::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
@@ -691,6 +691,20 @@ class spell_halfus_dancing_flames final : public SpellScript
|
||||
OnObjectAreaTargetSelect.Register(&spell_halfus_dancing_flames::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_halfus_unresponsive final : public SpellScript
|
||||
{
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetHitUnit()->IsCreature())
|
||||
GetHitUnit()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget.Register(&spell_halfus_unresponsive::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_boss_halfus_wyrmbreaker()
|
||||
@@ -703,7 +717,9 @@ void AddSC_boss_halfus_wyrmbreaker()
|
||||
RegisterGameObjectAI(go_halfus_whelp_cage);
|
||||
RegisterSpellScript(spell_halfus_bind_will);
|
||||
RegisterSpellScript(spell_halfus_fireball);
|
||||
RegisterSpellScript(spell_halfus_fireball_barrage);
|
||||
RegisterSpellScript(spell_halfus_stone_touch);
|
||||
RegisterSpellScript(spell_halfus_cyclone_winds);
|
||||
RegisterSpellScript(spell_halfus_dancing_flames);
|
||||
RegisterSpellScript(spell_halfus_unresponsive);
|
||||
}
|
||||
+73
-183
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "Containers.h"
|
||||
#include "bastion_of_twilight.h"
|
||||
#include "GameObject.h"
|
||||
#include "InstanceScript.h"
|
||||
@@ -39,6 +40,10 @@ ObjectData const creatureData[] =
|
||||
{ BOSS_CHOGALL, DATA_CHOGALL },
|
||||
{ BOSS_SINESTRA, DATA_SINESTRA },
|
||||
{ NPC_PROTO_BEHEMOTH, DATA_PROTO_BEHEMOTH },
|
||||
{ NPC_SLATE_DRAGON, DATA_SLATE_DRAGON },
|
||||
{ NPC_NETHER_SCION, DATA_NETHER_SCION },
|
||||
{ NPC_STORM_RIDER, DATA_STORM_RIDER },
|
||||
{ NPC_TIME_WARDEN, DATA_TIME_WARDEN },
|
||||
{ NPC_ASCENDANT_COUNCIL_CONTROLLER, DATA_ASCENDANT_COUNCIL_CONTROLLER },
|
||||
{ NPC_CORRUPTION, DATA_CORRUPTION },
|
||||
{ NPC_CHOGALL, DATA_CHOGALL_EVENT },
|
||||
@@ -48,6 +53,7 @@ ObjectData const creatureData[] =
|
||||
ObjectData const gameobjectData[] =
|
||||
{
|
||||
{ GO_GRIM_BATOL_RAID_TRAP_DOOR, DATA_GRIM_BATOL_RAID_TRAP_DOOR },
|
||||
{ GO_WHELP_CAGE, DATA_WHELP_CAGE },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
@@ -63,13 +69,12 @@ DoorData const doorData[] =
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
};
|
||||
|
||||
uint32 HalfusDragonEntries[] =
|
||||
enum MapEvents
|
||||
{
|
||||
NPC_NETHER_SCION,
|
||||
NPC_SLATE_DRAGON,
|
||||
NPC_STORM_RIDER,
|
||||
NPC_TIME_WARDEN,
|
||||
NPC_ORPHANED_EMERALD_WELP
|
||||
EVENT_ID_NETHER_SCION_FREED = 26077,
|
||||
EVENT_ID_SLATE_DRAGON_FREED = 26078,
|
||||
EVENT_ID_STORM_RIDER_FREED = 26079,
|
||||
EVENT_ID_TIME_WARDEN_FREED = 26064
|
||||
};
|
||||
|
||||
Position const BreathFlightTargetStalkerSortPos = { -740.677f, -592.328f, 859.455f };
|
||||
@@ -87,30 +92,19 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
SetBossNumber(!map->IsHeroic() ? EncounterCountNormal : EncounterCountHeroic); // Sinestra only in heroic mode
|
||||
LoadDoorData(doorData);
|
||||
LoadObjectData(creatureData, gameobjectData);
|
||||
_unresponsiveDragonEntryFirst = 0;
|
||||
_unresponsiveDragonEntrySecond = 0;
|
||||
_deadOrphanedEmeraldWhelps = 0;
|
||||
_fullHeroicId = instance->IsHeroic();
|
||||
GenerateHalfusDragonData();
|
||||
}
|
||||
_activeDragonFlags = DRAGON_FLAG_ALL_ACTIVE;
|
||||
|
||||
void GenerateHalfusDragonData()
|
||||
{
|
||||
for (uint8 i = 0; i < 5; i++)
|
||||
_activeDragonEntries.insert(HalfusDragonEntries[i]);
|
||||
|
||||
if (!instance->IsHeroic())
|
||||
if (!map->IsHeroic())
|
||||
{
|
||||
for (uint8 i = 0; i < 2; i++)
|
||||
{
|
||||
uint32 entry = Trinity::Containers::SelectRandomContainerElement(_activeDragonEntries);
|
||||
_activeDragonEntries.erase(entry);
|
||||
if (i == 0)
|
||||
_unresponsiveDragonEntryFirst = entry;
|
||||
else
|
||||
_unresponsiveDragonEntrySecond = entry;
|
||||
}
|
||||
_activeDragonFlags = 0;
|
||||
std::vector<BoTHalfusDragonFlags> activeDragons = { DRAGON_FLAG_NETHER_SCION, DRAGON_FLAG_SLATE_DRAGON, DRAGON_FLAG_STORM_RIDER, DRAGON_FLAG_TIME_WARDEN, DRAGON_FLAG_EMERALD_WHELPS };
|
||||
Trinity::Containers::RandomResize(activeDragons, 3);
|
||||
for (BoTHalfusDragonFlags flag : activeDragons)
|
||||
_activeDragonFlags |= flag;
|
||||
}
|
||||
|
||||
if ((_activeDragonFlags & DRAGON_FLAG_TIME_WARDEN) != 0)
|
||||
events.ScheduleEvent(EVENT_CAST_DANCING_FLAMES, 1s);
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
@@ -119,20 +113,8 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_NETHER_SCION:
|
||||
case NPC_SLATE_DRAGON:
|
||||
case NPC_STORM_RIDER:
|
||||
case NPC_TIME_WARDEN:
|
||||
if (Creature* halfus = GetCreature(DATA_HALFUS_WYRMBREAKER))
|
||||
halfus->AI()->JustSummoned(creature);
|
||||
[[fallthrough]];
|
||||
case NPC_ORPHANED_EMERALD_WELP:
|
||||
case NPC_SPIKE:
|
||||
_halfusEncounterGUIDs.insert(creature->GetGUID());
|
||||
break;
|
||||
case NPC_INVISIBLE_STALKER:
|
||||
if (creature->GetPositionZ() < 850.0f)
|
||||
_dancingFlamesInvisibleStalkerGUIDs.insert(creature->GetGUID());
|
||||
_dancingFlamesInvisibleStalkerGUIDs.insert(creature->GetGUID());
|
||||
break;
|
||||
case NPC_COLLAPSING_TWILIGHT_PORTAL:
|
||||
if (Creature* valiona = GetCreature(DATA_VALIONA))
|
||||
@@ -175,12 +157,16 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureRemove(Creature* creature) override
|
||||
{
|
||||
InstanceScript::OnCreatureRemove(creature);
|
||||
if (creature->GetEntry() == NPC_INVISIBLE_STALKER)
|
||||
_dancingFlamesInvisibleStalkerGUIDs.erase(creature->GetGUID());
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
InstanceScript::OnGameObjectCreate(go);
|
||||
|
||||
if (go->GetEntry() == GO_GRIM_BATOL_RAID_TRAP_DOOR && instance->IsHeroic() && _fullHeroicId && GetBossState(DATA_CHOGALL) == DONE)
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
@@ -191,51 +177,8 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
switch (type)
|
||||
{
|
||||
case DATA_HALFUS_WYRMBREAKER:
|
||||
if (state == IN_PROGRESS)
|
||||
if (state == DONE)
|
||||
{
|
||||
for (ObjectGuid guid : _halfusEncounterGUIDs)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
{
|
||||
if (creature->GetEntry() != NPC_SPIKE
|
||||
&& creature->GetEntry() != _unresponsiveDragonEntryFirst
|
||||
&& creature->GetEntry() != _unresponsiveDragonEntrySecond)
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_NETHER_SCION:
|
||||
creature->UpdateEntry(NPC_NETHER_SCION_ENCOUNTER);
|
||||
break;
|
||||
case NPC_SLATE_DRAGON:
|
||||
creature->UpdateEntry(NPC_SLATE_DRAGON_ENCOUNTER);
|
||||
break;
|
||||
case NPC_STORM_RIDER:
|
||||
creature->UpdateEntry(NPC_STORM_RIDER_ENCOUNTER);
|
||||
break;
|
||||
case NPC_TIME_WARDEN:
|
||||
creature->UpdateEntry(NPC_TIME_WARDEN_ENCOUNTER);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
if (creature->GetEntry() != NPC_ORPHANED_EMERALD_WELP)
|
||||
creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state == FAIL)
|
||||
{
|
||||
_halfusEncounterGUIDs.clear();
|
||||
_deadOrphanedEmeraldWhelps = 0;
|
||||
events.CancelEvent(EVENT_CAST_DANCING_FLAMES);
|
||||
}
|
||||
else if (state == DONE)
|
||||
{
|
||||
events.CancelEvent(EVENT_CAST_DANCING_FLAMES);
|
||||
if (Creature* chogall = GetCreature(DATA_CHOGALL_EVENT))
|
||||
chogall->AI()->DoAction(ACTION_TALK_HALFUS_WYRMBREAKER_DEAD);
|
||||
}
|
||||
@@ -270,66 +213,13 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == DONE && !instance->IsHeroic())
|
||||
_fullHeroicId = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnUnitDeath(Unit* unit) override
|
||||
{
|
||||
if (unit->GetEntry() == NPC_ORPHANED_EMERALD_WELP)
|
||||
{
|
||||
_deadOrphanedEmeraldWhelps++;
|
||||
if (_deadOrphanedEmeraldWhelps == 8)
|
||||
if (Creature* protoBehemoth = GetCreature(DATA_PROTO_BEHEMOTH))
|
||||
protoBehemoth->AI()->DoAction(ACTION_CAST_DRAGONS_VENGEANCE);
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
void SetData(uint32 type, uint32 /*data*/) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_CAST_DRAGON_BUFFS:
|
||||
if (data == DRAGON_BUFFS_HALFUS_WYRMBREAKER)
|
||||
{
|
||||
if (Creature* halfus = GetCreature(DATA_HALFUS_WYRMBREAKER))
|
||||
{
|
||||
for (uint32 entry : _activeDragonEntries)
|
||||
{
|
||||
if (entry == NPC_SLATE_DRAGON)
|
||||
halfus->AI()->DoAction(ACTION_ENABLE_MALEVOLENT_STRIKES);
|
||||
if (entry == NPC_NETHER_SCION)
|
||||
halfus->AI()->DoAction(ACTION_ENABLE_FRENZIED_ASSAULT);
|
||||
if (entry == NPC_STORM_RIDER)
|
||||
halfus->AI()->DoAction(ACTION_ENABLE_SHADOW_NOVA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data == DRAGON_BUFFS_PROTO_BEHEMOTH)
|
||||
{
|
||||
if (Creature* protoBehemoth = GetCreature(DATA_PROTO_BEHEMOTH))
|
||||
{
|
||||
for (uint32 entry : _activeDragonEntries)
|
||||
{
|
||||
if (entry == NPC_ORPHANED_EMERALD_WELP)
|
||||
protoBehemoth->AI()->DoAction(ACTION_ENABLE_SCORCHING_BREATH);
|
||||
if (entry == NPC_TIME_WARDEN)
|
||||
{
|
||||
protoBehemoth->AI()->DoAction(ACTION_ENABLE_FIREBALL_BARRAGE);
|
||||
events.RescheduleEvent(EVENT_CAST_DANCING_FLAMES, 500ms, 1s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATA_OPEN_ORPHANED_EMERALD_WHELP_CAGE:
|
||||
for (ObjectGuid guid : _halfusEncounterGUIDs)
|
||||
if (Creature* orphanedEmeraldWhelp = instance->GetCreature(guid))
|
||||
if (orphanedEmeraldWhelp->GetEntry() == NPC_ORPHANED_EMERALD_WELP)
|
||||
orphanedEmeraldWhelp->AI()->DoAction(ACTION_MOVE_OUT_OF_CAGE);
|
||||
break;
|
||||
case DATA_AT_HALFUS_WYRMBREAKER_INTRO:
|
||||
if (GetBossState(DATA_HALFUS_WYRMBREAKER) != DONE)
|
||||
if (Creature* chogall = GetCreature(DATA_CHOGALL_EVENT))
|
||||
@@ -392,12 +282,6 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_UNRESPONSIVE_DRAGON_FIRST:
|
||||
return _unresponsiveDragonEntryFirst;
|
||||
case DATA_UNRESPONSIVE_DRAGON_SECOND:
|
||||
return _unresponsiveDragonEntrySecond;
|
||||
case DATA_DRAGON_CAGE_ENABLED:
|
||||
return uint8((instance->IsHeroic() || HasActiveOrphanedEmeraldWhelps()));
|
||||
case DATA_COLLAPSING_TWILIGHT_PORTAL_COUNT:
|
||||
{
|
||||
uint8 portalCount = 0;
|
||||
@@ -407,7 +291,9 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
return portalCount;
|
||||
}
|
||||
case DATA_FULL_HEROIC_ID:
|
||||
return _fullHeroicId;
|
||||
return false;
|
||||
case DATA_ACTIVE_DRAGON_FLAGS:
|
||||
return _activeDragonFlags;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -423,12 +309,33 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CAST_DANCING_FLAMES:
|
||||
if (ObjectGuid guid = Trinity::Containers::SelectRandomContainerElement(_dancingFlamesInvisibleStalkerGUIDs))
|
||||
if (Creature* cataclysmStalker = instance->GetCreature(guid))
|
||||
cataclysmStalker->CastSpell(cataclysmStalker, SPELL_DANCING_FLAMES_VISUAL, true);
|
||||
{
|
||||
if (_dancingFlamesInvisibleStalkerGUIDs.size() < 1)
|
||||
{
|
||||
events.Repeat(1s);
|
||||
break;
|
||||
}
|
||||
|
||||
// Between one and three stalkers cast the dancing flames at the same time. We now have to select a range within the guidset
|
||||
uint32 castingStalkerNum = std::min<uint32>(urand(1, 3), (_dancingFlamesInvisibleStalkerGUIDs.size() - 1));
|
||||
GuidSet::const_iterator startIterator = _dancingFlamesInvisibleStalkerGUIDs.begin();
|
||||
GuidSet::const_iterator endIterator = _dancingFlamesInvisibleStalkerGUIDs.begin();
|
||||
std::advance(endIterator, castingStalkerNum);
|
||||
|
||||
if (_dancingFlamesInvisibleStalkerGUIDs.size() > (castingStalkerNum))
|
||||
{
|
||||
uint32 offset = urand(0, _dancingFlamesInvisibleStalkerGUIDs.size() - castingStalkerNum);
|
||||
std::advance(startIterator, offset);
|
||||
std::advance(endIterator, offset);
|
||||
}
|
||||
|
||||
for (GuidSet::const_iterator itr = startIterator; itr != endIterator; ++itr)
|
||||
if (Creature* cataclysmStalker = instance->GetCreature(*itr))
|
||||
cataclysmStalker->CastSpell(cataclysmStalker, SPELL_DANCING_FLAMES_VISUAL);
|
||||
|
||||
events.Repeat(500ms, 1s);
|
||||
break;
|
||||
}
|
||||
case EVENT_CHOGALL_TALK_THERALION_AND_VALIONA_DEAD:
|
||||
if (Creature* chogall = GetCreature(DATA_CHOGALL))
|
||||
chogall->AI()->DoAction(ACTION_TALK_THERALION_AND_VALIONA_DEAD);
|
||||
@@ -439,50 +346,33 @@ class instance_bastion_of_twilight final : public InstanceMapScript
|
||||
}
|
||||
}
|
||||
|
||||
void WriteSaveDataMore(std::ostringstream& data) override
|
||||
void ProcessEvent(WorldObject* objTarget, uint32 eventId, WorldObject* /*invoker*/) override
|
||||
{
|
||||
data << _unresponsiveDragonEntryFirst << ' '
|
||||
<< _unresponsiveDragonEntrySecond << ' '
|
||||
<< _fullHeroicId;
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(std::istringstream& data) override
|
||||
{
|
||||
data >> _unresponsiveDragonEntryFirst;
|
||||
data >> _unresponsiveDragonEntrySecond;
|
||||
data >> _fullHeroicId;
|
||||
|
||||
if (_unresponsiveDragonEntryFirst && _unresponsiveDragonEntrySecond)
|
||||
switch (eventId)
|
||||
{
|
||||
// Clear default generated unresponsive dragon selection and replace it with our saved data
|
||||
_activeDragonEntries.clear();
|
||||
for (uint8 i = 0; i < 5; i++)
|
||||
_activeDragonEntries.insert(HalfusDragonEntries[i]);
|
||||
|
||||
_activeDragonEntries.erase(_unresponsiveDragonEntryFirst);
|
||||
_activeDragonEntries.erase(_unresponsiveDragonEntrySecond);
|
||||
// These events are sent by the Free Dragon spells in Halfus Wyrmbreaker's encounter. Though it makes zero sense to use them in this context, we will just
|
||||
// do so to follow Blizzard's intention. Probably some intern's doing or so.
|
||||
case EVENT_ID_SLATE_DRAGON_FREED:
|
||||
case EVENT_ID_NETHER_SCION_FREED:
|
||||
case EVENT_ID_STORM_RIDER_FREED:
|
||||
case EVENT_ID_TIME_WARDEN_FREED:
|
||||
if (objTarget->IsCreature())
|
||||
if (CreatureAI* ai = objTarget->ToCreature()->AI())
|
||||
ai->DoAction(ACTION_DRAGON_FREED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasActiveOrphanedEmeraldWhelps() const
|
||||
{
|
||||
return (_unresponsiveDragonEntryFirst != NPC_ORPHANED_EMERALD_WELP
|
||||
&& _unresponsiveDragonEntrySecond != NPC_ORPHANED_EMERALD_WELP);
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
GuidSet _halfusEncounterGUIDs;
|
||||
GuidSet _dancingFlamesInvisibleStalkerGUIDs;
|
||||
GuidSet _valionaDummyGUIDs;
|
||||
GuidSet _unstableTwilightGUIDs;
|
||||
GuidSet _collapsingTwilightPortalGUIDs;
|
||||
ObjectGuid _valionaAuraDummyGUID;
|
||||
std::set<uint32> _activeDragonEntries;
|
||||
uint32 _unresponsiveDragonEntryFirst;
|
||||
uint32 _unresponsiveDragonEntrySecond;
|
||||
uint8 _deadOrphanedEmeraldWhelps;
|
||||
uint8 _fullHeroicId;
|
||||
uint8 _activeDragonFlags;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
|
||||
Reference in new issue
Block a user