Compare commits
4
Commits
f4afc16458
...
d9fa1aa73a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9fa1aa73a | ||
|
|
6f93adbb2e | ||
|
|
3f5e997afd | ||
|
|
f19ee3937b |
@@ -942,12 +942,12 @@ void Map::Update(uint32 t_diff)
|
|||||||
if (!m_mapRefManager.empty() || !m_activeNonPlayers.empty())
|
if (!m_mapRefManager.empty() || !m_activeNonPlayers.empty())
|
||||||
ProcessRelocationNotifies(t_diff);
|
ProcessRelocationNotifies(t_diff);
|
||||||
|
|
||||||
|
sScriptMgr->OnMapUpdate(this, t_diff);
|
||||||
|
|
||||||
//WowCommunity
|
//WowCommunity
|
||||||
UpdateWorldScenarios(t_diff);
|
UpdateWorldScenarios(t_diff);
|
||||||
//WowCommunity
|
//WowCommunity
|
||||||
|
|
||||||
sScriptMgr->OnMapUpdate(this, t_diff);
|
|
||||||
|
|
||||||
TC_METRIC_VALUE("map_creatures", uint64(GetObjectsStore().Size<Creature>()),
|
TC_METRIC_VALUE("map_creatures", uint64(GetObjectsStore().Size<Creature>()),
|
||||||
TC_METRIC_TAG("map_id", std::to_string(GetId())),
|
TC_METRIC_TAG("map_id", std::to_string(GetId())),
|
||||||
TC_METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
|
TC_METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
|
||||||
|
|||||||
@@ -105,13 +105,6 @@ namespace WorldPackets::Garrison
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sniff-verified for 12.0.1.66102 ? observed in the 8316-byte SMSG_GET_GARRISON_INFO_RESULT
|
|
||||||
// body (SNIFF_AUDIT_12.0.1.66102.md -5.3). int32 ItemFileDataID is always present
|
|
||||||
// (sometimes zero, sometimes a real DBD ID like 1599042); the trailing OptionalInit bit
|
|
||||||
// gates an optional ItemInstance blob.
|
|
||||||
// The brief's Deserialize_JamGarrisonMissionReward @ 0x7FF75C1754C0 (Byte-gated VarUInt32)
|
|
||||||
// decodes the JAM-mirror code path, NOT this dedicated SMSG. Both formats coexist for
|
|
||||||
// different sub-collection sync paths.
|
|
||||||
ByteBuffer& operator<<(ByteBuffer& data, GarrisonMissionReward const& missionRewardItem)
|
ByteBuffer& operator<<(ByteBuffer& data, GarrisonMissionReward const& missionRewardItem)
|
||||||
{
|
{
|
||||||
data << int32(missionRewardItem.ItemID);
|
data << int32(missionRewardItem.ItemID);
|
||||||
@@ -121,9 +114,7 @@ namespace WorldPackets::Garrison
|
|||||||
data << uint32(missionRewardItem.FollowerXP);
|
data << uint32(missionRewardItem.FollowerXP);
|
||||||
data << uint32(missionRewardItem.GarrMssnBonusAbilityID);
|
data << uint32(missionRewardItem.GarrMssnBonusAbilityID);
|
||||||
data << int32(missionRewardItem.ItemFileDataID);
|
data << int32(missionRewardItem.ItemFileDataID);
|
||||||
// itemInstance = OptionalInit bit + FlushBits. This is the SNIFF-CONFIRMED encoding (ADD_MISSION_RESULT
|
|
||||||
// decoded byte-exact / 0 trailing bytes). The talent socketData is the SAME reflection kind and must match
|
|
||||||
// this (bit), NOT a uint32 count - see operator<<(GarrisonTalent).
|
|
||||||
data << OptionalInit(missionRewardItem.ItemInstance);
|
data << OptionalInit(missionRewardItem.ItemInstance);
|
||||||
data.FlushBits();
|
data.FlushBits();
|
||||||
|
|
||||||
@@ -133,13 +124,6 @@ namespace WorldPackets::Garrison
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sniff-verified for 12.0.1.66102 (SNIFF_AUDIT_12.0.1.66102.md -3.15, embedded in
|
|
||||||
// the 188-byte SMSG_GET_GARRISON_INFO_RESULT). MissionScalar(float) sits between
|
|
||||||
// Flags and ContentTuningID followed by 3 size fields. Note: SMSG_GARRISON_START_MISSION_RESULT
|
|
||||||
// embeds a Mission whose exact byte layout has a residual ~2-byte misalignment vs this
|
|
||||||
// writer (audit -4.1) ? needs IDA pseudocode of Build_GarrisonStartMissionResult to fully
|
|
||||||
// resolve. The brief's Deserialize_JamGarrisonMission @ 0x7FF75C1755E0 with Currency/
|
|
||||||
// BonusActions/AutoMissionData tail is the JAM-mirror path, NOT this dedicated SMSG.
|
|
||||||
ByteBuffer& operator<<(ByteBuffer& data, GarrisonMission const& mission)
|
ByteBuffer& operator<<(ByteBuffer& data, GarrisonMission const& mission)
|
||||||
{
|
{
|
||||||
data << uint64(mission.DbID);
|
data << uint64(mission.DbID);
|
||||||
@@ -188,43 +172,16 @@ namespace WorldPackets::Garrison
|
|||||||
|
|
||||||
ByteBuffer& operator<<(ByteBuffer& data, GarrisonTalent const& talent)
|
ByteBuffer& operator<<(ByteBuffer& data, GarrisonTalent const& talent)
|
||||||
{
|
{
|
||||||
// Wire order (client JamGarrisonTalent, Ghidra-confirmed via ctor @client 0x729093890): garrTalentID(i32),
|
|
||||||
// garrTalentRank(i32), researchStartTime(i64), flags(i32), socketData(OptionalInit bit + FlushBits).
|
|
||||||
//
|
|
||||||
// The client reads the wire `flags` field with its OWN semantics, which differ from TC's internal
|
|
||||||
// Garrison::Talent::Flags. Bits were pinned by live client testing (the builder that computes these is
|
|
||||||
// control-flow-flattened, so it isn't offline-decompilable):
|
|
||||||
// client bit 0x4 = "this talent is being researched" ? gates whether the Order Advancement UI reads
|
|
||||||
// researchStartTime and renders the research timer. Verified live: flags=0 kept the client's startTime in
|
|
||||||
// memory (proven by a server-side diag log + a sentinel injection) but drew the talent idle; setting 0x4
|
|
||||||
// makes C_Garrison.GetTalentInfo(id).isBeingResearched=true with the real DB2 researchDuration.
|
|
||||||
// client bit 0x2 = a duration override that forces researchDuration to a fixed 24h; MUST NEVER be set.
|
|
||||||
// client bit 0x1 = "researched / talent taken". Recovered by static RE of the 12.0.7 client, which also
|
|
||||||
// proves it is PURELY server-supplied: the complete set of writers to the client-side talent record's
|
|
||||||
// flags word (+0x40) is three sites - RVA 0x22992A5 and 0x2299395, both verbatim copies of the wire
|
|
||||||
// struct inside Garrison::SetTalent (RVA 0x2298FF0), and RVA 0x2299448 in Garrison::RemoveTalent,
|
|
||||||
// which only zeroes it. There is no or/bts against that field anywhere in the image and no
|
|
||||||
// research-timer expiry that recomputes it, so the client can never derive "researched" on its own.
|
|
||||||
// Readers gated on the bit: ModifierTree 201/202/317 (evaluator RVA 0x20664B0 - the covenant/taxi
|
|
||||||
// PlayerCondition path), C_Garrison.GetTalentInfo's `researched` (builder RVA 0x22B95F0 via
|
|
||||||
// 0x228E2F0), GetTalentAvailability (RVA 0x2171390, bit set => availability 2) and
|
|
||||||
// CanResearchAtThisTier (RVA 0x2298DF0, which early-outs "already taken" only when the bit is set).
|
|
||||||
// Leaving it clear is why a fully researched sanctum/order-hall talent rendered as un-researched and
|
|
||||||
// why talent-gated unlocks (e.g. the covenant transport-network taxi nodes) never opened.
|
|
||||||
// TC's internal flags (only GARRISON_TALENT_FLAG_TEMPORARY=0x1 today, an unrelated meaning) are not
|
|
||||||
// wire-compatible, so derive the wire value purely from research state.
|
|
||||||
int32 wireFlags = 0;
|
int32 wireFlags = 0;
|
||||||
if (talent.Rank >= 1)
|
if (talent.Rank >= 1)
|
||||||
wireFlags |= 0x1; // client "researched / taken" bit; every client test pairs it with a rank check
|
wireFlags |= 0x1;
|
||||||
if (talent.ResearchStartTime != 0)
|
if (talent.ResearchStartTime != 0)
|
||||||
wireFlags |= 0x4; // client "being researched" bit (never 0x2 = duration override)
|
wireFlags |= 0x4;
|
||||||
data << int32(talent.GarrTalentID);
|
data << int32(talent.GarrTalentID);
|
||||||
data << int32(talent.Rank);
|
data << int32(talent.Rank);
|
||||||
data << talent.ResearchStartTime;
|
data << talent.ResearchStartTime;
|
||||||
data << int32(wireFlags);
|
data << int32(wireFlags);
|
||||||
// socketData is the SAME reflection kind (0x80003) as the reward itemInstance, which is sniff-confirmed as
|
|
||||||
// an OptionalInit bit (NOT a uint32 count). The prior uint32 "fix" made each talent 3 bytes too long,
|
|
||||||
// shifting the mission-reward data written right after the Talents block (rewards showed value x 2^16).
|
|
||||||
data << OptionalInit(talent.Socket);
|
data << OptionalInit(talent.Socket);
|
||||||
data.FlushBits();
|
data.FlushBits();
|
||||||
if (talent.Socket)
|
if (talent.Socket)
|
||||||
@@ -420,10 +377,7 @@ namespace WorldPackets::Garrison
|
|||||||
{
|
{
|
||||||
_worldPacket >> GarrTalentID;
|
_worldPacket >> GarrTalentID;
|
||||||
uint32 count = _worldPacket.read<uint32>();
|
uint32 count = _worldPacket.read<uint32>();
|
||||||
// Sanity cap the client-supplied socket count before resize(): a soulbind/conduit tree has at most a few dozen
|
|
||||||
// sockets, so this is well above any legitimate value while stopping a crafted count (e.g. 0xFFFFFFFF) from
|
|
||||||
// requesting a multi-gigabyte allocation. resize() throws std::bad_alloc, which the opcode dispatcher does not
|
|
||||||
// catch (only ByteBufferException), so an unbounded count would crash the world thread instead of disconnecting.
|
|
||||||
count = std::min<uint32>(count, 64);
|
count = std::min<uint32>(count, 64);
|
||||||
Sockets.resize(count);
|
Sockets.resize(count);
|
||||||
for (GarrisonTalentSocketData& socket : Sockets)
|
for (GarrisonTalentSocketData& socket : Sockets)
|
||||||
@@ -559,7 +513,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conservative shape: u32 Result, u32 GarrSpecID, u32 GarrPlotInstanceID.
|
|
||||||
WorldPacket const* GarrisonLearnSpecializationResult::Write()
|
WorldPacket const* GarrisonLearnSpecializationResult::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << uint32(Result);
|
_worldPacket << uint32(Result);
|
||||||
@@ -568,7 +521,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conservative shape: u32 Result, u32 GarrPlotInstanceID, u32 GarrSpecID.
|
|
||||||
WorldPacket const* GarrisonBuildingSetActiveSpecializationResult::Write()
|
WorldPacket const* GarrisonBuildingSetActiveSpecializationResult::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << uint32(Result);
|
_worldPacket << uint32(Result);
|
||||||
@@ -579,8 +531,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// u32 GarrPlotInstanceID, u64 TimeBuilt, u32 Result - see the header for the disassembly that inverts the
|
|
||||||
// order the old comment claimed. Result LAST is the field the client's `cmp [rcx+0x30], 0` gate reads.
|
|
||||||
WorldPacket const* GarrisonCompleteBuildingConstructionResult::Write()
|
WorldPacket const* GarrisonCompleteBuildingConstructionResult::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << uint32(GarrPlotInstanceID);
|
_worldPacket << uint32(GarrPlotInstanceID);
|
||||||
@@ -590,7 +540,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDA case 4980791 (-8.45): PackedGuid + sub-call + varU32 size + varU32[size].
|
|
||||||
WorldPacket const* GarrisonOpenCrafter::Write()
|
WorldPacket const* GarrisonOpenCrafter::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << NpcGUID;
|
_worldPacket << NpcGUID;
|
||||||
@@ -602,8 +551,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDA case 4980817 (-8.51): generic byte-block helper. Conservative: u32 NewMinLevel.
|
|
||||||
// 8 bytes, not 4 - the client's handler (0x22A0BA0) reads two u32s out of the opaque tail. See the header.
|
|
||||||
WorldPacket const* GarrisonAutoTroopMinLevelUpdateResult::Write()
|
WorldPacket const* GarrisonAutoTroopMinLevelUpdateResult::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << uint32(UnkLookupKey);
|
_worldPacket << uint32(UnkLookupKey);
|
||||||
@@ -612,8 +559,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDA case 4980772 (-8.30): u8 GarrTypeID + GarrisonSmallStruct.
|
|
||||||
// Conservative inner shape: {u32 MissionRecID, u32 BonusAbilityID}.
|
|
||||||
WorldPacket const* GarrisonActivateMissionBonusAbility::Write()
|
WorldPacket const* GarrisonActivateMissionBonusAbility::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << uint8(GarrTypeID);
|
_worldPacket << uint8(GarrTypeID);
|
||||||
@@ -667,7 +612,7 @@ namespace WorldPackets::Garrison
|
|||||||
|
|
||||||
void GarrisonGetMissionReward::Read()
|
void GarrisonGetMissionReward::Read()
|
||||||
{
|
{
|
||||||
_worldPacket >> DbID; // RAW uint64, not a PackedGuid ? see GarrisonPackets.h
|
_worldPacket >> DbID;
|
||||||
_worldPacket >> MissionRecID;
|
_worldPacket >> MissionRecID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,8 +692,6 @@ namespace WorldPackets::Garrison
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDA-confirmed (12.0.5.67186) layout ? see SNIFF_AUDIT -10.2. 3 CONFIRMED + 2 HIGH
|
|
||||||
// fields. FollowerInfo struct shape matches COMPLETE_MISSION_RESULT (-10.1.3).
|
|
||||||
WorldPacket const* GarrisonMissionBonusRollResult::Write()
|
WorldPacket const* GarrisonMissionBonusRollResult::Write()
|
||||||
{
|
{
|
||||||
_worldPacket << Mission;
|
_worldPacket << Mission;
|
||||||
|
|||||||
@@ -31,6 +31,26 @@ enum HOINFUSIONCreatureIds
|
|||||||
BOSS_GULPING_GOLIATH = 189722,
|
BOSS_GULPING_GOLIATH = 189722,
|
||||||
BOSS_KHAJIN_THE_UNYIELDING = 189727,
|
BOSS_KHAJIN_THE_UNYIELDING = 189727,
|
||||||
BOSS_PRIMAL_TSUNAMI = 189729,
|
BOSS_PRIMAL_TSUNAMI = 189729,
|
||||||
|
|
||||||
|
NPC_CONTAINMENT_APPARATUS = 190342,
|
||||||
|
NPC_PRIMALIST_GEOMANCER = 190345,
|
||||||
|
NPC_PRIMALIST_RAVAGER = 190348,
|
||||||
|
NPC_SKULKING_ZEALOT = 190359,
|
||||||
|
NPC_DAZZLING_DRAGONFLY = 190362,
|
||||||
|
NPC_CURIOUS_SWOGLET = 190366,
|
||||||
|
NPC_FLAMECALLER_AYMI = 190368,
|
||||||
|
NPC_SQUALLBRINGER_CYRAZ = 190370,
|
||||||
|
NPC_PRIMALIST_EARTHSHAKER = 190371,
|
||||||
|
NPC_PRIMALIST_GALESINGER = 190373,
|
||||||
|
NPC_PRIMALIST_ICECALLER = 190377,
|
||||||
|
NPC_GLACIAL_PROTO_DRAGON = 190403,
|
||||||
|
NPC_INFUSER_SARIYA = 190405,
|
||||||
|
NPC_AQUA_RAGER = 190407,
|
||||||
|
NPC_REFTI_DEFENDER = 190340,
|
||||||
|
NPC_CURIOUS_SWOGLET_ALT = 195399,
|
||||||
|
NPC_PRIMALIST_INFUSER = 196043,
|
||||||
|
NPC_PRIMALIST_SHOCKTROOPER = 199037,
|
||||||
|
NPC_INFUSED_GLOBULE = 196008,
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class AI, class T>
|
template <class AI, class T>
|
||||||
|
|||||||
@@ -5,23 +5,535 @@
|
|||||||
* and read our Terms
|
* and read our Terms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AreaTrigger.h"
|
|
||||||
#include "AreaTriggerAI.h"
|
|
||||||
#include "InstanceScript.h"
|
|
||||||
#include "Map.h"
|
|
||||||
#include "SpellAuras.h"
|
|
||||||
#include "SpellScript.h"
|
|
||||||
#include "ScriptMgr.h"
|
|
||||||
#include "Unit.h"
|
|
||||||
#include "HallsOfInfusion.h"
|
#include "HallsOfInfusion.h"
|
||||||
|
#include "InstanceScript.h"
|
||||||
|
#include "ScriptMgr.h"
|
||||||
|
#include "ScriptedCreature.h"
|
||||||
|
#include "SpellScript.h"
|
||||||
|
#include "SpellAuraEffects.h"
|
||||||
|
#include "SpellAuras.h"
|
||||||
|
#include "SpellHistory.h"
|
||||||
|
#include "Spell.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "MotionMaster.h"
|
||||||
|
#include "TemporarySummon.h"
|
||||||
|
|
||||||
//here to script trash and gobs
|
// Halls of Infusion trash (retail 12.1 sniff 69814)
|
||||||
|
|
||||||
enum NpcsSpells
|
enum TrashSpells
|
||||||
{
|
{
|
||||||
|
//Refti Defender 190340
|
||||||
|
SPELL_DEMORALIZING_SHOUT = 374339,
|
||||||
|
SPELL_SPEAR_FLURRY = 393432,
|
||||||
|
SPELL_GUSHING_WOUND = 393444,
|
||||||
|
//Primalist Geomancer 190345
|
||||||
|
SPELL_SEISMIC_SLAM = 374073,
|
||||||
|
SPELL_TAILWIND_GEOMANCER = 374154,
|
||||||
|
//Primalist Ravager 190348
|
||||||
|
SPELL_TAILWIND_RAVAGER = 374149,
|
||||||
|
//Skulking Zealot 190359
|
||||||
|
SPELL_STEALTH = 374612,
|
||||||
|
SPELL_CHEAP_SHOT = 374614,
|
||||||
|
SPELL_RISING_SQUALL = 374616,
|
||||||
|
//Dazzling Dragonfly 190362
|
||||||
|
SPELL_DAZZLE = 374563,
|
||||||
|
SPELL_EVASIVE_FLUTTER = 374578,
|
||||||
|
//Flamecaller Aymi 190368
|
||||||
|
SPELL_CAUTERIZE = 374699,
|
||||||
|
SPELL_PYRETIC_BURST = 374706,
|
||||||
|
SPELL_MOLTEN_SUBDUCTION = 374718,
|
||||||
|
SPELL_MAGMA_CRUSH = 374735,
|
||||||
|
//Squallbringer Cyraz 190370
|
||||||
|
SPELL_ZEPHYRS_CALL = 374823,
|
||||||
|
SPELL_GALE_FORCE_CHARGE = 374863,
|
||||||
|
SPELL_WHIRLING_FURY = 375079,
|
||||||
|
//Primalist Earthshaker 190371
|
||||||
|
SPELL_RUMBLING_EARTH = 375384,
|
||||||
|
//Primalist Galesinger 190373
|
||||||
|
SPELL_THUNDERSTRIKE = 437717,
|
||||||
|
//Primalist Icecaller 190377
|
||||||
|
SPELL_ICE_SHARD = 375950,
|
||||||
|
SPELL_REFRESHING_TIDES = 376171,
|
||||||
|
//Glacial Proto-Dragon 190403
|
||||||
|
SPELL_OCEANIC_BREATH = 375351,
|
||||||
|
SPELL_DEEP_CHILL = 391634,
|
||||||
|
//Infuser Sariya 190405
|
||||||
|
SPELL_AQUEOUS_BARRIER = 377402,
|
||||||
|
SPELL_INUNDATE = 388882,
|
||||||
|
SPELL_FLASH_FLOOD = 390290,
|
||||||
|
SPELL_WATER_MISSILE = 396783,
|
||||||
|
//Aqua Rager 190407
|
||||||
|
SPELL_TIDAL_DIVERGENCE = 377341,
|
||||||
|
SPELL_BOILING_RAGE = 377384,
|
||||||
|
//Primalist Infuser 196043
|
||||||
|
SPELL_INFUSE = 387618,
|
||||||
|
//Primalist Shocktrooper 199037
|
||||||
|
SPELL_LIGHTNING_BLAST = 395690,
|
||||||
|
SPELL_INFUSED_LIGHTNING = 395691,
|
||||||
|
SPELL_ELEMENTAL_FOCUS = 395694,
|
||||||
|
//Containment Apparatus 190342
|
||||||
|
SPELL_INVIS_DETECT = 18950,
|
||||||
|
SPELL_CONTAINMENT_BEAM = 374020,
|
||||||
|
SPELL_EXPULSE = 374045,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TrashEvents
|
||||||
|
{
|
||||||
|
EVENT_TH_A = 1,
|
||||||
|
EVENT_TH_B,
|
||||||
|
EVENT_TH_C,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------- generic two-spell caster trash ----------
|
||||||
|
|
||||||
|
template<uint32 SpellA, uint32 CooldownA, uint32 SpellB, uint32 CooldownB>
|
||||||
|
struct npc_hoi_two_caster : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_two_caster(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 2s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 6s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastVictim(SpellA);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, Milliseconds(CooldownA));
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
DoCastVictim(SpellB);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, Milliseconds(CooldownB));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------- generic single-spell trash ----------
|
||||||
|
|
||||||
|
template<uint32 SpellA, uint32 CooldownA>
|
||||||
|
struct npc_hoi_one_spell : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_one_spell(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 2s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
_events.Update(diff);
|
||||||
|
|
||||||
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (uint32 eventId = _events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
if (eventId == EVENT_TH_A)
|
||||||
|
{
|
||||||
|
DoCastVictim(SpellA);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, Milliseconds(CooldownA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------- named trash AI ----------
|
||||||
|
|
||||||
|
//Refti Defender 190340
|
||||||
|
struct npc_hoi_refti_defender : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_refti_defender(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 4s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 8s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 5s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastAOE(SPELL_DEMORALIZING_SHOUT);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 15s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
DoCastAOE(SPELL_SPEAR_FLURRY);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 12s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_C:
|
||||||
|
DoCastVictim(SPELL_GUSHING_WOUND);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 6s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Skulking Zealot 190359 - stealth opener
|
||||||
|
struct npc_hoi_skulking_zealot : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_skulking_zealot(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_STEALTH);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 5s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 12s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastVictim(SPELL_CHEAP_SHOT);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 8s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
DoCastAOE(SPELL_RISING_SQUALL);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 15s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Flamecaller Aymi 190368
|
||||||
|
struct npc_hoi_flamecaller_aymi : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_flamecaller_aymi(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 5s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 10s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 8s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastAOE(SPELL_PYRETIC_BURST);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 12s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
DoCastAOE(SPELL_MOLTEN_SUBDUCTION);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 18s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_C:
|
||||||
|
if (HealthBelowPct(70))
|
||||||
|
DoCastSelf(SPELL_CAUTERIZE);
|
||||||
|
else
|
||||||
|
DoCastVictim(SPELL_MAGMA_CRUSH);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 14s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Squallbringer Cyraz 190370
|
||||||
|
struct npc_hoi_squallbringer_cyraz : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_squallbringer_cyraz(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 6s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 12s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 20s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastAOE(SPELL_ZEPHYRS_CALL);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 15s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||||
|
DoCast(target, SPELL_GALE_FORCE_CHARGE);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 20s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_C:
|
||||||
|
DoCastSelf(SPELL_WHIRLING_FURY);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 25s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Infuser Sariya 190405
|
||||||
|
struct npc_hoi_infuser_sariya : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_infuser_sariya(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_AQUEOUS_BARRIER);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 3s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 12s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 25s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastVictim(SPELL_WATER_MISSILE);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 4s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
DoCastAOE(SPELL_INUNDATE);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 15s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_C:
|
||||||
|
DoCastAOE(SPELL_FLASH_FLOOD);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_C, 30s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Containment Apparatus 190342
|
||||||
|
struct npc_hoi_containment_apparatus : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_containment_apparatus(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 5s);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 20s);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_TH_A:
|
||||||
|
DoCastAOE(SPELL_CONTAINMENT_BEAM);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 8s);
|
||||||
|
break;
|
||||||
|
case EVENT_TH_B:
|
||||||
|
DoCastSelf(SPELL_EXPULSE);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_B, 20s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Primalist Infuser 196043 - buffs nearby allies
|
||||||
|
struct npc_hoi_primalist_infuser : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_hoi_primalist_infuser(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 4s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
_events.Update(diff);
|
||||||
|
|
||||||
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (uint32 eventId = _events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
if (eventId == EVENT_TH_A)
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_INFUSE);
|
||||||
|
_events.ScheduleEvent(EVENT_TH_A, 15s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventMap _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------- bindings (AI name = ScriptName) ----------
|
||||||
|
|
||||||
|
typedef npc_hoi_one_spell<SPELL_TAILWIND_RAVAGER, 8000> npc_hoi_primalist_ravager;
|
||||||
|
typedef npc_hoi_one_spell<SPELL_ICE_SHARD, 4000> npc_hoi_primalist_icecaller;
|
||||||
|
typedef npc_hoi_one_spell<SPELL_THUNDERSTRIKE, 6000> npc_hoi_primalist_galesinger;
|
||||||
|
typedef npc_hoi_one_spell<SPELL_RUMBLING_EARTH, 9000> npc_hoi_primalist_earthshaker;
|
||||||
|
|
||||||
|
typedef npc_hoi_two_caster<SPELL_SEISMIC_SLAM, 10000, SPELL_TAILWIND_GEOMANCER, 15000> npc_hoi_primalist_geomancer;
|
||||||
|
typedef npc_hoi_two_caster<SPELL_DAZZLE, 8000, SPELL_EVASIVE_FLUTTER, 20000> npc_hoi_dazzling_dragonfly;
|
||||||
|
typedef npc_hoi_two_caster<SPELL_OCEANIC_BREATH, 12000, SPELL_DEEP_CHILL, 8000> npc_hoi_glacial_proto_dragon;
|
||||||
|
typedef npc_hoi_two_caster<SPELL_BOILING_RAGE, 8000, SPELL_TIDAL_DIVERGENCE, 12000> npc_hoi_aqua_rager;
|
||||||
|
typedef npc_hoi_two_caster<SPELL_LIGHTNING_BLAST, 6000, SPELL_INFUSED_LIGHTNING, 9000> npc_hoi_primalist_shocktrooper;
|
||||||
|
|
||||||
void AddSC_HallsOfInfusion()
|
void AddSC_HallsOfInfusion()
|
||||||
{
|
{
|
||||||
|
RegisterCreatureAI(npc_hoi_refti_defender);
|
||||||
|
RegisterCreatureAI(npc_hoi_skulking_zealot);
|
||||||
|
RegisterCreatureAI(npc_hoi_flamecaller_aymi);
|
||||||
|
RegisterCreatureAI(npc_hoi_squallbringer_cyraz);
|
||||||
|
RegisterCreatureAI(npc_hoi_infuser_sariya);
|
||||||
|
RegisterCreatureAI(npc_hoi_containment_apparatus);
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_infuser);
|
||||||
|
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_ravager);
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_icecaller);
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_galesinger);
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_earthshaker);
|
||||||
|
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_geomancer);
|
||||||
|
RegisterCreatureAI(npc_hoi_dazzling_dragonfly);
|
||||||
|
RegisterCreatureAI(npc_hoi_glacial_proto_dragon);
|
||||||
|
RegisterCreatureAI(npc_hoi_aqua_rager);
|
||||||
|
RegisterCreatureAI(npc_hoi_primalist_shocktrooper);
|
||||||
}
|
}
|
||||||
@@ -24,9 +24,8 @@
|
|||||||
enum GulpinggoliathSpells
|
enum GulpinggoliathSpells
|
||||||
{
|
{
|
||||||
SPELL_BELLY_SLAM = 385531,
|
SPELL_BELLY_SLAM = 385531,
|
||||||
SPELL_GULP = 385551, //385555,
|
SPELL_BELLY_SLAM_FOLLOWUP = 385691,
|
||||||
SPELL_GULP_SWOG_TOXIN = 374389,
|
SPELL_GULP = 385551,
|
||||||
SPELL_HANGRY = 385743,
|
|
||||||
SPELL_OVERPOWERING_CROAK = 385181,
|
SPELL_OVERPOWERING_CROAK = 385181,
|
||||||
SPELL_TOXIC_EFFLUVIA = 385442,
|
SPELL_TOXIC_EFFLUVIA = 385442,
|
||||||
SPELL_PERIODIC_ENERGY_GAIN = 299956,
|
SPELL_PERIODIC_ENERGY_GAIN = 299956,
|
||||||
@@ -35,9 +34,8 @@ enum GulpinggoliathSpells
|
|||||||
enum Gulpinggoliathevents
|
enum Gulpinggoliathevents
|
||||||
{
|
{
|
||||||
EVENT_BELLY_SLAM = 1,
|
EVENT_BELLY_SLAM = 1,
|
||||||
|
EVENT_BELLY_SLAM_FOLLOWUP,
|
||||||
EVENT_GULP,
|
EVENT_GULP,
|
||||||
EVENT_GULP_SWOG_TOXIN,
|
|
||||||
EVENT_HANGRY,
|
|
||||||
EVENT_OVERPOWERING_CROAK,
|
EVENT_OVERPOWERING_CROAK,
|
||||||
EVENT_TOXIC_EFFLUVIA,
|
EVENT_TOXIC_EFFLUVIA,
|
||||||
};
|
};
|
||||||
@@ -62,12 +60,10 @@ public:
|
|||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||||
DoCast(SPELL_PERIODIC_ENERGY_GAIN);
|
DoCast(SPELL_PERIODIC_ENERGY_GAIN);
|
||||||
events.ScheduleEvent(EVENT_BELLY_SLAM, 24s);
|
events.ScheduleEvent(EVENT_OVERPOWERING_CROAK, 4s);
|
||||||
events.ScheduleEvent(EVENT_GULP, 8s);
|
events.ScheduleEvent(EVENT_GULP, 10s);
|
||||||
events.ScheduleEvent(EVENT_GULP_SWOG_TOXIN, 12s);
|
events.ScheduleEvent(EVENT_TOXIC_EFFLUVIA, 22s);
|
||||||
events.ScheduleEvent(EVENT_HANGRY, 14s);
|
events.ScheduleEvent(EVENT_BELLY_SLAM, 30s);
|
||||||
events.ScheduleEvent(EVENT_OVERPOWERING_CROAK, 5s);
|
|
||||||
events.ScheduleEvent(EVENT_TOXIC_EFFLUVIA, 19s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||||
@@ -108,19 +104,15 @@ public:
|
|||||||
{
|
{
|
||||||
case EVENT_BELLY_SLAM:
|
case EVENT_BELLY_SLAM:
|
||||||
DoCastVictim(SPELL_BELLY_SLAM);
|
DoCastVictim(SPELL_BELLY_SLAM);
|
||||||
events.ScheduleEvent(EVENT_BELLY_SLAM, 20s);
|
events.ScheduleEvent(EVENT_BELLY_SLAM_FOLLOWUP, 4s);
|
||||||
|
events.ScheduleEvent(EVENT_BELLY_SLAM, 30s);
|
||||||
|
break;
|
||||||
|
case EVENT_BELLY_SLAM_FOLLOWUP:
|
||||||
|
DoCastSelf(SPELL_BELLY_SLAM_FOLLOWUP);
|
||||||
break;
|
break;
|
||||||
case EVENT_GULP:
|
case EVENT_GULP:
|
||||||
DoCast(SPELL_GULP);
|
DoCast(SPELL_GULP);
|
||||||
events.ScheduleEvent(EVENT_GULP, 15s);
|
events.ScheduleEvent(EVENT_GULP, 47s);
|
||||||
break;
|
|
||||||
case EVENT_GULP_SWOG_TOXIN:
|
|
||||||
DoCastVictim(SPELL_GULP_SWOG_TOXIN);
|
|
||||||
events.ScheduleEvent(EVENT_GULP_SWOG_TOXIN, 25s);
|
|
||||||
break;
|
|
||||||
case EVENT_HANGRY:
|
|
||||||
DoCastSelf(SPELL_HANGRY);
|
|
||||||
events.ScheduleEvent(EVENT_HANGRY, 33s);
|
|
||||||
break;
|
break;
|
||||||
case EVENT_OVERPOWERING_CROAK:
|
case EVENT_OVERPOWERING_CROAK:
|
||||||
DoCastSelf(SPELL_OVERPOWERING_CROAK);
|
DoCastSelf(SPELL_OVERPOWERING_CROAK);
|
||||||
|
|||||||
@@ -23,19 +23,19 @@
|
|||||||
|
|
||||||
enum KhajintheunyieldingSpells
|
enum KhajintheunyieldingSpells
|
||||||
{
|
{
|
||||||
SPELL_FROST_CYCLONE = 390111,
|
|
||||||
SPELL_FROST_SHOCK = 385963,
|
SPELL_FROST_SHOCK = 385963,
|
||||||
SPELL_GLACIAL_SURGE = 386559,
|
SPELL_GLACIAL_SURGE = 386559,
|
||||||
|
SPELL_GLACIAL_SURGE_FOLLOW = 386562,
|
||||||
SPELL_HAILSTORM = 386757,
|
SPELL_HAILSTORM = 386757,
|
||||||
SPELL_POLAR_WINDS = 386743,
|
SPELL_POLAR_WINDS = 386741,
|
||||||
SPELL_PERIODIC_ENERGY_GAIN = 299956,
|
SPELL_POLAR_WINDS_FOLLOW = 386743,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Khajintheunyieldingevents
|
enum Khajintheunyieldingevents
|
||||||
{
|
{
|
||||||
EVENT_FROST_CYCLONE = 1,
|
EVENT_FROST_SHOCK = 1,
|
||||||
EVENT_FROST_SHOCK,
|
|
||||||
EVENT_GLACIAL_SURGE,
|
EVENT_GLACIAL_SURGE,
|
||||||
|
EVENT_GLACIAL_SURGE_FOLLOW,
|
||||||
EVENT_HAILSTORM,
|
EVENT_HAILSTORM,
|
||||||
EVENT_POLAR_WINDS,
|
EVENT_POLAR_WINDS,
|
||||||
};
|
};
|
||||||
@@ -49,9 +49,6 @@ public:
|
|||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
me->RemoveAura(SPELL_PERIODIC_ENERGY_GAIN);
|
|
||||||
me->SetPowerType(POWER_ENERGY);
|
|
||||||
me->SetPower(POWER_ENERGY, 0);
|
|
||||||
me->RemoveAllAreaTriggers();
|
me->RemoveAllAreaTriggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,12 +56,11 @@ public:
|
|||||||
{
|
{
|
||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||||
DoCast(SPELL_PERIODIC_ENERGY_GAIN);
|
DoCastSelf(SPELL_POLAR_WINDS);
|
||||||
events.ScheduleEvent(EVENT_FROST_CYCLONE, 24s);
|
events.ScheduleEvent(EVENT_POLAR_WINDS, 500ms);
|
||||||
events.ScheduleEvent(EVENT_FROST_SHOCK, 8s);
|
events.ScheduleEvent(EVENT_FROST_SHOCK, 6s);
|
||||||
events.ScheduleEvent(EVENT_GLACIAL_SURGE, 12s);
|
events.ScheduleEvent(EVENT_HAILSTORM, 10s);
|
||||||
events.ScheduleEvent(EVENT_HAILSTORM, 14s);
|
events.ScheduleEvent(EVENT_GLACIAL_SURGE, 22s);
|
||||||
events.ScheduleEvent(EVENT_POLAR_WINDS, 17s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||||
@@ -91,37 +87,30 @@ public:
|
|||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (me->GetPowerPct(POWER_ENERGY) == 100)
|
|
||||||
{
|
|
||||||
me->ModifyPower(POWER_ENERGY, -100);
|
|
||||||
events.ScheduleEvent(EVENT_POLAR_WINDS, 2s);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_FROST_CYCLONE:
|
case EVENT_POLAR_WINDS:
|
||||||
DoCast(SPELL_FROST_CYCLONE);
|
DoCastSelf(SPELL_POLAR_WINDS_FOLLOW);
|
||||||
events.ScheduleEvent(EVENT_FROST_CYCLONE, 20s);
|
|
||||||
break;
|
break;
|
||||||
case EVENT_FROST_SHOCK:
|
case EVENT_FROST_SHOCK:
|
||||||
DoCastVictim(SPELL_FROST_SHOCK);
|
DoCastVictim(SPELL_FROST_SHOCK);
|
||||||
events.ScheduleEvent(EVENT_FROST_SHOCK, 15s);
|
events.ScheduleEvent(EVENT_FROST_SHOCK, 12s);
|
||||||
break;
|
break;
|
||||||
case EVENT_GLACIAL_SURGE:
|
case EVENT_GLACIAL_SURGE:
|
||||||
DoCast(SPELL_GLACIAL_SURGE);
|
DoCastSelf(SPELL_GLACIAL_SURGE);
|
||||||
events.ScheduleEvent(EVENT_GLACIAL_SURGE, 12s);
|
events.ScheduleEvent(EVENT_GLACIAL_SURGE_FOLLOW, 4s);
|
||||||
|
events.ScheduleEvent(EVENT_GLACIAL_SURGE, 22s);
|
||||||
|
break;
|
||||||
|
case EVENT_GLACIAL_SURGE_FOLLOW:
|
||||||
|
DoCast(SPELL_GLACIAL_SURGE_FOLLOW);
|
||||||
break;
|
break;
|
||||||
case EVENT_HAILSTORM:
|
case EVENT_HAILSTORM:
|
||||||
DoCast(SPELL_HAILSTORM);
|
DoCast(SPELL_HAILSTORM);
|
||||||
events.ScheduleEvent(EVENT_HAILSTORM, 33s);
|
events.ScheduleEvent(EVENT_HAILSTORM, 28s);
|
||||||
break;
|
|
||||||
case EVENT_POLAR_WINDS:
|
|
||||||
DoCast(SPELL_POLAR_WINDS);
|
|
||||||
events.ScheduleEvent(EVENT_POLAR_WINDS, 37s);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -23,58 +23,56 @@
|
|||||||
|
|
||||||
enum PrimaltsunamiSpells
|
enum PrimaltsunamiSpells
|
||||||
{
|
{
|
||||||
SPELL_FOCUSED_DELUGE = 387571,
|
|
||||||
SPELL_INFUSE = 387619,
|
|
||||||
SPELL_INFUSED_GLOBULES = 387559,
|
SPELL_INFUSED_GLOBULES = 387559,
|
||||||
SPELL_ROGUE_WAVES = 388760,
|
SPELL_ROGUE_WAVES = 388788,
|
||||||
SPELL_SQUALL_BUFFET = 387504,
|
SPELL_SQUALL_BUFFET = 387504,
|
||||||
SPELL_SUBMERGE = 387585,
|
SPELL_SUBMERGE = 387585,
|
||||||
SPELL_TEMPESTS_FURY = 388424,
|
SPELL_TEMPESTS_FURY = 388424,
|
||||||
SPELL_UNDERTOW = 389872,
|
SPELL_UNDERTOW = 389872,
|
||||||
SPELL_UNDERTOW_DAMAGE = 389875,
|
SPELL_CRASHING_TSUNAMI = 388712,
|
||||||
SPELL_PERIODIC_ENERGY_GAIN = 299956,
|
SPELL_TELEPORT_CORPSES = 396893,
|
||||||
|
SPELL_PASSIVE_ENERGY_GAIN = 387593,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Primaltsunamievents
|
enum Primaltsunamievents
|
||||||
{
|
{
|
||||||
EVENT_FOCUSED_DELUGE = 1,
|
EVENT_INFUSED_GLOBULES = 1,
|
||||||
EVENT_INFUSE,
|
|
||||||
EVENT_INFUSED_GLOBULES,
|
|
||||||
EVENT_ROGUE_WAVES,
|
EVENT_ROGUE_WAVES,
|
||||||
EVENT_SQUALL_BUFFET,
|
EVENT_SQUALL_BUFFET,
|
||||||
EVENT_SUBMERGE,
|
EVENT_SUBMERGE,
|
||||||
EVENT_TEMPESTS_FURY,
|
EVENT_TEMPESTS_FURY,
|
||||||
EVENT_UNDERTOW,
|
EVENT_UNDERTOW,
|
||||||
|
EVENT_CRASHING_TSUNAMI,
|
||||||
|
EVENT_RE_EMERGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
//189729 Primal Tsunami
|
//189729 Primal Tsunami
|
||||||
class boss_primal_tsunami : public BossAI
|
class boss_primal_tsunami : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
boss_primal_tsunami(Creature* creature) : BossAI(creature, DATA_PRIMAL_TSUNAMI) {}
|
boss_primal_tsunami(Creature* creature) : BossAI(creature, DATA_PRIMAL_TSUNAMI), _submerged(false) {}
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
me->RemoveAura(SPELL_PERIODIC_ENERGY_GAIN);
|
me->RemoveAura(SPELL_PASSIVE_ENERGY_GAIN);
|
||||||
me->SetPowerType(POWER_ENERGY);
|
me->SetPowerType(POWER_ENERGY);
|
||||||
me->SetPower(POWER_ENERGY, 0);
|
me->SetPower(POWER_ENERGY, 0);
|
||||||
me->RemoveAllAreaTriggers();
|
me->RemoveAllAreaTriggers();
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
_submerged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* who) override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||||
DoCast(SPELL_PERIODIC_ENERGY_GAIN);
|
DoCastSelf(SPELL_PASSIVE_ENERGY_GAIN);
|
||||||
events.ScheduleEvent(EVENT_FOCUSED_DELUGE, 24s);
|
DoCastSelf(SPELL_UNDERTOW);
|
||||||
events.ScheduleEvent(EVENT_INFUSE, 8s);
|
events.ScheduleEvent(EVENT_ROGUE_WAVES, 1s);
|
||||||
events.ScheduleEvent(EVENT_INFUSED_GLOBULES, 12s);
|
|
||||||
events.ScheduleEvent(EVENT_ROGUE_WAVES, 14s);
|
|
||||||
events.ScheduleEvent(EVENT_SQUALL_BUFFET, 22s);
|
|
||||||
events.ScheduleEvent(EVENT_SUBMERGE, 17s);
|
|
||||||
events.ScheduleEvent(EVENT_TEMPESTS_FURY, 5s);
|
events.ScheduleEvent(EVENT_TEMPESTS_FURY, 5s);
|
||||||
events.ScheduleEvent(EVENT_UNDERTOW, 29s);
|
events.ScheduleEvent(EVENT_INFUSED_GLOBULES, 9s);
|
||||||
|
events.ScheduleEvent(EVENT_SQUALL_BUFFET, 17s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||||
@@ -98,10 +96,7 @@ public:
|
|||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (!_submerged && me->GetPowerPct(POWER_ENERGY) == 100)
|
||||||
return;
|
|
||||||
|
|
||||||
if (me->GetPowerPct(POWER_ENERGY) == 100)
|
|
||||||
{
|
{
|
||||||
me->ModifyPower(POWER_ENERGY, -100);
|
me->ModifyPower(POWER_ENERGY, -100);
|
||||||
events.ScheduleEvent(EVENT_SUBMERGE, 2s);
|
events.ScheduleEvent(EVENT_SUBMERGE, 2s);
|
||||||
@@ -113,37 +108,47 @@ public:
|
|||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_FOCUSED_DELUGE:
|
|
||||||
DoCastVictim(SPELL_FOCUSED_DELUGE);
|
|
||||||
events.ScheduleEvent(EVENT_FOCUSED_DELUGE, 20s);
|
|
||||||
break;
|
|
||||||
case EVENT_INFUSE:
|
|
||||||
DoCastSelf(SPELL_INFUSE);
|
|
||||||
me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
|
|
||||||
events.ScheduleEvent(EVENT_INFUSE, 15s);
|
|
||||||
break;
|
|
||||||
case EVENT_INFUSED_GLOBULES:
|
|
||||||
DoCast(SPELL_INFUSED_GLOBULES);
|
|
||||||
events.ScheduleEvent(EVENT_INFUSED_GLOBULES, 12s);
|
|
||||||
break;
|
|
||||||
case EVENT_ROGUE_WAVES:
|
|
||||||
DoCast(SPELL_ROGUE_WAVES);
|
|
||||||
events.ScheduleEvent(EVENT_ROGUE_WAVES, 91s);
|
|
||||||
break;
|
|
||||||
case EVENT_SQUALL_BUFFET:
|
|
||||||
DoCastVictim(SPELL_SQUALL_BUFFET);
|
|
||||||
events.ScheduleEvent(EVENT_SQUALL_BUFFET, 37s);
|
|
||||||
break;
|
|
||||||
case EVENT_SUBMERGE:
|
case EVENT_SUBMERGE:
|
||||||
DoCastSelf(SPELL_SUBMERGE);
|
DoCastSelf(SPELL_SUBMERGE);
|
||||||
|
me->SetReactState(REACT_PASSIVE);
|
||||||
|
me->AttackStop();
|
||||||
|
_submerged = true;
|
||||||
|
events.ScheduleEvent(EVENT_CRASHING_TSUNAMI, 3s);
|
||||||
|
events.ScheduleEvent(EVENT_RE_EMERGE, 30s);
|
||||||
|
break;
|
||||||
|
case EVENT_CRASHING_TSUNAMI:
|
||||||
|
DoCastSelf(SPELL_CRASHING_TSUNAMI);
|
||||||
|
if (_submerged)
|
||||||
|
events.ScheduleEvent(EVENT_CRASHING_TSUNAMI, 7s);
|
||||||
|
break;
|
||||||
|
case EVENT_RE_EMERGE:
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
DoCastSelf(SPELL_TELEPORT_CORPSES);
|
||||||
|
_submerged = false;
|
||||||
|
me->SetPower(POWER_ENERGY, 0);
|
||||||
|
events.ScheduleEvent(EVENT_TEMPESTS_FURY, 5s);
|
||||||
|
events.ScheduleEvent(EVENT_INFUSED_GLOBULES, 9s);
|
||||||
|
events.ScheduleEvent(EVENT_SQUALL_BUFFET, 17s);
|
||||||
|
events.ScheduleEvent(EVENT_ROGUE_WAVES, 25s);
|
||||||
|
break;
|
||||||
|
case EVENT_INFUSED_GLOBULES:
|
||||||
|
DoCastSelf(SPELL_INFUSED_GLOBULES);
|
||||||
|
events.ScheduleEvent(EVENT_INFUSED_GLOBULES, 17s);
|
||||||
|
break;
|
||||||
|
case EVENT_ROGUE_WAVES:
|
||||||
|
DoCastSelf(SPELL_ROGUE_WAVES);
|
||||||
|
events.ScheduleEvent(EVENT_ROGUE_WAVES, 20s);
|
||||||
|
break;
|
||||||
|
case EVENT_SQUALL_BUFFET:
|
||||||
|
DoCast(SPELL_SQUALL_BUFFET);
|
||||||
|
events.ScheduleEvent(EVENT_SQUALL_BUFFET, 37s);
|
||||||
break;
|
break;
|
||||||
case EVENT_TEMPESTS_FURY:
|
case EVENT_TEMPESTS_FURY:
|
||||||
DoCast(SPELL_TEMPESTS_FURY);
|
DoCastSelf(SPELL_TEMPESTS_FURY);
|
||||||
events.ScheduleEvent(EVENT_TEMPESTS_FURY, 44s);
|
events.ScheduleEvent(EVENT_TEMPESTS_FURY, 44s);
|
||||||
break;
|
break;
|
||||||
case EVENT_UNDERTOW:
|
case EVENT_UNDERTOW:
|
||||||
DoCast(SPELL_UNDERTOW);
|
DoCastSelf(SPELL_UNDERTOW);
|
||||||
DoCast(SPELL_UNDERTOW_DAMAGE);
|
|
||||||
events.ScheduleEvent(EVENT_UNDERTOW, 25s);
|
events.ScheduleEvent(EVENT_UNDERTOW, 25s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -151,7 +156,15 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_submerged && me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_submerged && me->GetVictim())
|
||||||
|
me->DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _submerged;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_primal_tsunami()
|
void AddSC_boss_primal_tsunami()
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ enum watcherirideusSpells
|
|||||||
SPELL_ABLATIVE_BARRIER = 383840,
|
SPELL_ABLATIVE_BARRIER = 383840,
|
||||||
SPELL_POWER_FIELD = 389181,
|
SPELL_POWER_FIELD = 389181,
|
||||||
SPELL_POWER_OVERLOAD = 389179,
|
SPELL_POWER_OVERLOAD = 389179,
|
||||||
SPELL_SIPHON_POWER = 389056, //389486,
|
SPELL_SIPHON_POWER = 389056,
|
||||||
SPELL_SPARK_VOLLEY = 383935, //384351,
|
SPELL_SPARK_VOLLEY = 384351,
|
||||||
SPELL_STATIC_SURGE = 384014,
|
SPELL_STATIC_SURGE = 384014,
|
||||||
SPELL_TITANIC_FIST = 384524,
|
SPELL_TITANIC_FIST = 384524,
|
||||||
SPELL_PERIODIC_ENERGY_GAIN = 299956,
|
SPELL_PERIODIC_ENERGY_GAIN = 299956,
|
||||||
@@ -65,13 +65,11 @@ public:
|
|||||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||||
Talk(0);
|
Talk(0);
|
||||||
DoCast(SPELL_PERIODIC_ENERGY_GAIN);
|
DoCast(SPELL_PERIODIC_ENERGY_GAIN);
|
||||||
events.ScheduleEvent(EVENT_ABLATIVE_BARRIER, 24s);
|
|
||||||
events.ScheduleEvent(EVENT_POWER_FIELD, 8s);
|
|
||||||
events.ScheduleEvent(EVENT_POWER_OVERLOAD, 12s);
|
|
||||||
events.ScheduleEvent(EVENT_SIPHON_POWER, 14s);
|
|
||||||
events.ScheduleEvent(EVENT_SPARK_VOLLEY, 3s);
|
|
||||||
events.ScheduleEvent(EVENT_STATIC_SURGE, 17s);
|
|
||||||
events.ScheduleEvent(EVENT_TITANIC_FIST, 5s);
|
events.ScheduleEvent(EVENT_TITANIC_FIST, 5s);
|
||||||
|
events.ScheduleEvent(EVENT_STATIC_SURGE, 10s);
|
||||||
|
events.ScheduleEvent(EVENT_POWER_OVERLOAD, 22s);
|
||||||
|
events.ScheduleEvent(EVENT_POWER_FIELD, 24s);
|
||||||
|
events.ScheduleEvent(EVENT_SPARK_VOLLEY, 26s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||||
@@ -113,10 +111,11 @@ public:
|
|||||||
{
|
{
|
||||||
case EVENT_ABLATIVE_BARRIER:
|
case EVENT_ABLATIVE_BARRIER:
|
||||||
DoCastSelf(SPELL_ABLATIVE_BARRIER);
|
DoCastSelf(SPELL_ABLATIVE_BARRIER);
|
||||||
|
events.ScheduleEvent(EVENT_SIPHON_POWER, 2s);
|
||||||
break;
|
break;
|
||||||
case EVENT_POWER_FIELD:
|
case EVENT_POWER_FIELD:
|
||||||
DoCastVictim(SPELL_POWER_FIELD);
|
DoCast(SPELL_POWER_FIELD);
|
||||||
events.ScheduleEvent(EVENT_POWER_FIELD, 20s);
|
events.ScheduleEvent(EVENT_POWER_FIELD, 25s);
|
||||||
break;
|
break;
|
||||||
case EVENT_POWER_OVERLOAD:
|
case EVENT_POWER_OVERLOAD:
|
||||||
DoCastSelf(SPELL_POWER_OVERLOAD);
|
DoCastSelf(SPELL_POWER_OVERLOAD);
|
||||||
@@ -124,19 +123,18 @@ public:
|
|||||||
break;
|
break;
|
||||||
case EVENT_SIPHON_POWER:
|
case EVENT_SIPHON_POWER:
|
||||||
DoCastSelf(SPELL_SIPHON_POWER);
|
DoCastSelf(SPELL_SIPHON_POWER);
|
||||||
events.ScheduleEvent(EVENT_SIPHON_POWER, 12s);
|
|
||||||
break;
|
break;
|
||||||
case EVENT_SPARK_VOLLEY:
|
case EVENT_SPARK_VOLLEY:
|
||||||
DoCastVictim(SPELL_SPARK_VOLLEY);
|
DoCastSelf(SPELL_SPARK_VOLLEY);
|
||||||
events.ScheduleEvent(EVENT_SPARK_VOLLEY, 39s);
|
events.ScheduleEvent(EVENT_SPARK_VOLLEY, 30s);
|
||||||
break;
|
break;
|
||||||
case EVENT_STATIC_SURGE:
|
case EVENT_STATIC_SURGE:
|
||||||
DoCastSelf(SPELL_STATIC_SURGE);
|
DoCastSelf(SPELL_STATIC_SURGE);
|
||||||
events.ScheduleEvent(EVENT_STATIC_SURGE, 15s);
|
events.ScheduleEvent(EVENT_STATIC_SURGE, 15s);
|
||||||
break;
|
break;
|
||||||
case EVENT_TITANIC_FIST:
|
case EVENT_TITANIC_FIST:
|
||||||
DoCast(SPELL_TITANIC_FIST);
|
DoCastSelf(SPELL_TITANIC_FIST);
|
||||||
events.ScheduleEvent(EVENT_TITANIC_FIST, 34s);
|
events.ScheduleEvent(EVENT_TITANIC_FIST, 30s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -52,12 +52,15 @@ public:
|
|||||||
if (!player->GetGroup() || !player->GetGroup()->GetLeaderGUID())
|
if (!player->GetGroup() || !player->GetGroup()->GetLeaderGUID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
player->GetGroup()->AddFollowerModeBots(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPlayerExit(Player* player)
|
void OnPlayerExit(Player* player)
|
||||||
{
|
{
|
||||||
if (!player->GetGroup())
|
if (!player->GetGroup())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
player->GetGroup()->DespawnFollowerModeBots(player);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user