Scripts/VioletHold: rewrote the whole instance
thanks @MitchesD for help
This commit is contained in:
1 parent
68e6c95f16
commit
df21162fe4
33 files changed
+3262
-3276
No files matched your search
@@ -0,0 +1,157 @@
|
||||
DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=58694;
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN (
|
||||
'spell_cyanigosa_arcane_vacuum',
|
||||
'spell_ichoron_splatter',
|
||||
'spell_ichoron_protective_bubble',
|
||||
'spell_ichoron_drained',
|
||||
'spell_ichoron_merge',
|
||||
'spell_moragg_ray',
|
||||
'spell_moragg_ray_of_pain',
|
||||
'spell_moragg_ray_of_suffering',
|
||||
'spell_xevozz_summon_ethereal_sphere',
|
||||
'spell_violet_hold_destroy_door_seal',
|
||||
'spell_violet_hold_portal_periodic',
|
||||
'spell_violet_hold_teleport_player',
|
||||
'spell_crystal_activation'
|
||||
);
|
||||
INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) values
|
||||
(58694,'spell_cyanigosa_arcane_vacuum'),
|
||||
(54259,'spell_ichoron_splatter'),
|
||||
(54306,'spell_ichoron_protective_bubble'),
|
||||
(59820,'spell_ichoron_drained'),
|
||||
(54269,'spell_ichoron_merge'),
|
||||
(54438,'spell_moragg_ray'),
|
||||
(54442,'spell_moragg_ray'),
|
||||
(59523,'spell_moragg_ray'),
|
||||
(59524,'spell_moragg_ray'),
|
||||
(58040,'spell_violet_hold_destroy_door_seal'),
|
||||
(58008,'spell_violet_hold_portal_periodic'),
|
||||
(62138,'spell_violet_hold_teleport_player');
|
||||
|
||||
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 and `SourceEntry` IN (57912, 57930, 58152, 54258, 54264, 54265, 54266, 54267, 54269);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
|
||||
(13,1,57912,0,0,31,0,3,29425,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,57930,0,0,31,0,3,30857,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,0,31,0,3,30661,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,1,31,0,3,30662,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,2,31,0,3,30663,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,3,31,0,3,30664,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,4,31,0,3,30665,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,5,31,0,3,30666,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,6,31,0,3,30667,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,7,31,0,3,30668,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,8,31,0,3,30918,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,9,31,0,3,30961,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,10,31,0,3,30962,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,11,31,0,3,30963,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,12,31,0,3,31007,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,13,31,0,3,31008,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,14,31,0,3,31009,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,15,31,0,3,31010,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,16,31,0,3,31118,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,58152,0,17,31,0,3,32191,0,0,0,0,'','Defense System - Arcane Lightning'),
|
||||
(13,1,54258,0,0,31,0,3,29326,102906,0,0,0,'','Ichoron - Water Globule'),
|
||||
(13,1,54264,0,0,31,0,3,29326,102905,0,0,0,'','Ichoron - Water Globule'),
|
||||
(13,1,54265,0,0,31,0,3,29326,102904,0,0,0,'','Ichoron - Water Globule'),
|
||||
(13,1,54266,0,0,31,0,3,29326,102901,0,0,0,'','Ichoron - Water Globule'),
|
||||
(13,1,54267,0,0,31,0,3,29326,102902,0,0,0,'','Ichoron - Water Globule'),
|
||||
(13,1,54269,0,0,31,0,3,29313,0,0,0,0,'','Ichoron - Merge');
|
||||
|
||||
UPDATE `creature_template` SET `gossip_menu_id`=9997 WHERE `entry`=30658;
|
||||
|
||||
UPDATE `gossip_menu_option` SET `action_menu_id`=9998 WHERE `menu_id`=9997;
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_violet_hold_teleportation_portal' WHERE `entry`=30679;
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_violet_hold_teleportation_portal_elite' WHERE `entry`=32174;
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_violet_hold_teleportation_portal_intro' WHERE `entry`=31011;
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_violet_hold_defense_system' WHERE `entry`=30837;
|
||||
|
||||
UPDATE `creature_template` SET `unit_flags`=832 WHERE `entry` IN (31134, 31506); -- Cyanigosa
|
||||
|
||||
UPDATE `creature_template` SET `speed_walk`=2.22222/2.5, `speed_run`=8.0/7.0, `unit_flags`=768 WHERE `entry` IN (31079, 31492); -- Azure Saboteur
|
||||
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=12.0/7.0, `unit_flags`=832 WHERE `entry` IN (29266, 31511, 32231, 32552); -- Xevozz
|
||||
UPDATE `creature_template` SET `speed_walk`=3.0/2.5, `speed_run`=3.0/7.0 WHERE `entry` IN (29271, 31514, 32582, 32583); -- Ethereal Sphere
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=12.0/7.0, `unit_flags`=832 WHERE `entry` IN (29312, 31509, 32237, 32553); -- Lavanthor
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=12.0/7.0, `unit_flags`=832 WHERE `entry` IN (29313, 31508, 32234, 32554); -- Ichoron
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=4.0/7.0, `unit_flags`=33587200 WHERE `entry` IN (29321, 31515); -- Ichor Globule
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=12.0/7.0, `unit_flags`=832 WHERE `entry` IN (29314, 31512, 32230, 32555); -- Zuramat
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=10.0/7.0, `unit_flags`=33600 WHERE `entry` IN (29315, 31507, 32226, 32550); -- Erekem
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=10.0/7.0, `unit_flags`=33600 WHERE `entry` IN (29395, 31513, 32228, 32549); -- Erekem Guard
|
||||
UPDATE `creature_template` SET `speed_walk`=4.0/2.5, `speed_run`=12.0/7.0, `unit_flags`=33600 WHERE `entry` IN (29316, 31510, 32235, 32551); -- Moragg
|
||||
|
||||
UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `ScriptName`='boss_xevozz' WHERE `entry`=32231; -- Xevozz
|
||||
UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `ScriptName`='boss_lavanthor' WHERE `entry`=32237; -- Lavanthor
|
||||
UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `ScriptName`='boss_ichoron' WHERE `entry`=32234; -- Ichoron
|
||||
UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `ScriptName`='boss_zuramat' WHERE `entry`=32230; -- Zuramat
|
||||
UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `ScriptName`='boss_erekem' WHERE `entry`=32226; -- Erekem
|
||||
UPDATE `creature_template` SET `minlevel`=76, `maxlevel`=76, `ScriptName`='npc_erekem_guard' WHERE `entry`=32228; -- Erekem Guard
|
||||
UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `ScriptName`='boss_moragg' WHERE `entry`=32235; -- Moragg
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (29364, 29365); -- Void Sentry
|
||||
UPDATE `creature_template` SET `flags_extra`=0, `AIName`='', `ScriptName`='npc_void_sentry' WHERE `entry`=29364; -- Void Sentry
|
||||
UPDATE `creature_template` SET `AIName`='' WHERE `entry`=29365; -- Void Sentry
|
||||
UPDATE `creature_template` SET `unit_flags`=0, `unit_flags2`=0 WHERE `entry` IN (29364, 31518);
|
||||
UPDATE `creature_template` SET `unit_flags`=33554432, `unit_flags2`=2080 WHERE `entry` IN (29365, 31519); -- Void Sentry
|
||||
|
||||
UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x1 WHERE `entry` IN (32552, 32553, 32554, 32555, 32550, 32551);
|
||||
UPDATE `creature_template` SET `mechanic_immune_mask`=536941137 WHERE `entry` IN (32231, 32552, 32237, 32553, 32234, 32554, 32230, 32555, 32226, 32550, 32228, 32549, 32235, 32551);
|
||||
|
||||
UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128 WHERE `entry`=30837;
|
||||
UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (29326, 30896);
|
||||
UPDATE `creature` SET `modelid`=0, `spawndist`=0, `MovementType`=0 WHERE `id` IN (29326, 30896);
|
||||
|
||||
UPDATE `creature_template` SET `AIName`='' WHERE `entry` IN (32226,32228,32230,32231,32234,32235,32237);
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (32226,32228,32230,32231,32234,32235,32237);
|
||||
|
||||
DELETE FROM `creature_template_addon` WHERE `entry` IN (30837, 30896, 31079, 29364, 29365, 31518, 31519);
|
||||
INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES
|
||||
(30837, 0, 0x3000000, 0x1, '57886 57887'),
|
||||
(30896, 0, 0x3000000, 0x1, ''),
|
||||
(31079, 0, 0x0, 0x1, '31635'),
|
||||
(29364, 0, 0x0, 0x1, '54351 54341'),
|
||||
(29365, 0, 0x0, 0x1, '54351 54342'),
|
||||
(31518, 0, 0x0, 0x1, '54351 54341'),
|
||||
(31519, 0, 0x0, 0x1, '54351 59747');
|
||||
|
||||
DELETE FROM `creature_text` WHERE `entry` IN (30658, 32204, 29271);
|
||||
DELETE FROM `creature_text` WHERE `entry`=29313 AND `groupid`=7;
|
||||
INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(30658, 0, 0, 'Prison guards, we are leaving! These adventurers are taking over! Go go go!', 14, 0, 100, 5, 0, 0, 31474, 3, 'Lieutenant Sinclari - Intro 1'),
|
||||
(30658, 1, 0, 'I''m locking the door. Good luck, and thank you for doing this.', 12, 0, 100, 396, 0, 0, 31475, 3, 'Lieutenant Sinclari - Intro 2'),
|
||||
(30658, 2, 0, 'You did it! You held the Blue Dragonflight back and defeated their commander. Amazing work!', 12, 0, 100, 396, 0, 0, 31694, 3, 'Lieutenant Sinclari - Outro'),
|
||||
|
||||
(32204, 0, 0, 'An elite Blue Dragonflight squad appears from the portal!', 41, 0, 100, 0, 0, 0, 32994, 3, 'Lieutenant Sinclari - Blue Dragonflight squad'),
|
||||
(32204, 1, 0, 'A Portal Guardian defends the new portal!', 41, 0, 100, 0, 0, 0, 32995, 3, 'Lieutenant Sinclari - Portal Guardian'),
|
||||
(32204, 2, 0, 'A Portal Keeper emerges from the portal!', 41, 0, 100, 0, 0, 0, 32996, 3, 'Lieutenant Sinclari - Portal Keeper'),
|
||||
(32204, 3, 0, 'Adventurers, the door is beginning to weaken!', 14, 0, 100, 0, 0, 0, 32557, 3, 'Lieutenant Sinclari - Door weaken'),
|
||||
(32204, 4, 0, 'Only half of the door seal''s strength remains! You must fight on!', 14, 0, 100, 0, 0, 0, 32558, 3, 'Lieutenant Sinclari - Half Door Seal reains'),
|
||||
(32204, 5, 0, 'The door seal is about to collapse! All is lost if the Blue Dragonflight breaks through the door!', 14, 0, 100, 0, 0, 0, 32559, 3, 'Lieutenant Sinclari - Door Seal broken'),
|
||||
|
||||
(29313, 7, 0, '%s''s Protective Bubble shatters!', 41, 0, 100, 0, 0, 0, 30086, 0, 'Ichoron - Emote Shatter'),
|
||||
|
||||
(29271, 0, 0, '%s begins to summon!', 41, 0, 100, 0, 0, 0, 30087, 3, 'Ethereal Sphere');
|
||||
|
||||
UPDATE `creature_text` SET `sound`=14499 WHERE `entry`=29266 AND `groupid`=0;
|
||||
UPDATE `creature_text` SET `emote`=396 WHERE `entry`=29266 AND `groupid`=3;
|
||||
UPDATE `creature_text` SET `emote`=15 WHERE `entry`=29315 AND `groupid`=3;
|
||||
UPDATE `creature_text` SET `emote`=396 WHERE `entry`=31134 AND `groupid`=3;
|
||||
|
||||
DELETE FROM `spell_target_position` WHERE `ID` IN (54102, 54137, 54138, 61337, 61338, 61339, 62139);
|
||||
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `VerifiedBuild`) VALUES
|
||||
(54102, 0, 608, 1854.36, 802.65, 44.3, 12340),
|
||||
(54137, 0, 608, 1899.18, 824.7, 38.72333, 12340),
|
||||
(54138, 0, 608, 1891.42, 788.04, 38.64, 12340),
|
||||
(61337, 0, 608, 1854.36, 802.65, 44.3, 12340),
|
||||
(61338, 0, 608, 1899.18, 824.7, 38.72333, 12340),
|
||||
(61339, 0, 608, 1891.42, 788.04, 38.64, 12340),
|
||||
(62139, 0, 608, 1857.24, 803.877, 44.0085, 12340);
|
||||
|
||||
-- 3.3.5 only
|
||||
DELETE FROM `spelldifficulty_dbc` WHERE `spellid0` IN (54102, 54137, 54138, 54207, 54438, 54442);
|
||||
INSERT INTO `spelldifficulty_dbc` (`id`, `spellid0`, `spellid1`) VALUES
|
||||
(54207, 54207, 59476),
|
||||
(54438, 54438, 59523),
|
||||
(54442, 54442, 59524);
|
||||
@@ -457,7 +457,13 @@ BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
summons(creature),
|
||||
_boundary(instance ? instance->GetBossBoundary(bossId) : NULL),
|
||||
_bossId(bossId) { }
|
||||
_bossId(bossId)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void BossAI::_Reset()
|
||||
{
|
||||
@@ -467,6 +473,7 @@ void BossAI::_Reset()
|
||||
me->ResetLootMode();
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
scheduler.CancelAll();
|
||||
if (instance)
|
||||
instance->SetBossState(_bossId, NOT_STARTED);
|
||||
}
|
||||
@@ -475,14 +482,13 @@ void BossAI::_JustDied()
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
scheduler.CancelAll();
|
||||
if (instance)
|
||||
instance->SetBossState(_bossId, DONE);
|
||||
}
|
||||
|
||||
void BossAI::_EnterCombat()
|
||||
{
|
||||
me->setActive(true);
|
||||
DoZoneInCombat();
|
||||
if (instance)
|
||||
{
|
||||
// bosses do not respawn, check only on enter combat
|
||||
@@ -493,6 +499,10 @@ void BossAI::_EnterCombat()
|
||||
}
|
||||
instance->SetBossState(_bossId, IN_PROGRESS);
|
||||
}
|
||||
|
||||
me->setActive(true);
|
||||
DoZoneInCombat();
|
||||
ScheduleTasks();
|
||||
}
|
||||
|
||||
void BossAI::TeleportCheaters()
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
#define CAST_AI(a, b) (dynamic_cast<a*>(b))
|
||||
#define ENSURE_AI(a,b) (EnsureAI<a>(b))
|
||||
@@ -359,6 +360,8 @@ class BossAI : public ScriptedAI
|
||||
// is supposed to run more than once
|
||||
virtual void ExecuteEvent(uint32 /*eventId*/) { }
|
||||
|
||||
virtual void ScheduleTasks() { }
|
||||
|
||||
void Reset() override { _Reset(); }
|
||||
void EnterCombat(Unit* /*who*/) override { _EnterCombat(); }
|
||||
void JustDied(Unit* /*killer*/) override { _JustDied(); }
|
||||
@@ -384,6 +387,7 @@ class BossAI : public ScriptedAI
|
||||
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
TaskScheduler scheduler;
|
||||
|
||||
private:
|
||||
BossBoundaryMap const* const _boundary;
|
||||
|
||||
@@ -68,8 +68,8 @@ struct npc_escortAI : public ScriptedAI
|
||||
|
||||
void EnterEvadeMode() override;
|
||||
|
||||
void UpdateAI(uint32 diff) override; //the "internal" update, calls UpdateEscortAI()
|
||||
virtual void UpdateEscortAI(uint32 const diff); //used when it's needed to add code in update (abilities, scripted events, etc)
|
||||
void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI()
|
||||
virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc)
|
||||
|
||||
void MovementInform(uint32, uint32) override;
|
||||
|
||||
|
||||
@@ -9590,6 +9590,17 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
|
||||
data << uint32(4131) << uint32(0); // 10 WORLDSTATE_ALGALON_DESPAWN_TIMER
|
||||
}
|
||||
break;
|
||||
// Violet Hold
|
||||
case 4415:
|
||||
if (instance && mapid == 608)
|
||||
instance->FillInitialWorldStates(data);
|
||||
else
|
||||
{
|
||||
data << uint32(3816) << uint32(0); // 9 WORLD_STATE_VH_SHOW
|
||||
data << uint32(3815) << uint32(100); // 10 WORLD_STATE_VH_PRISON_STATE
|
||||
data << uint32(3810) << uint32(0); // 11 WORLD_STATE_VH_WAVE_COUNT
|
||||
}
|
||||
break;
|
||||
// Halls of Refection
|
||||
case 4820:
|
||||
if (instance && mapid == 668)
|
||||
|
||||
@@ -319,6 +319,11 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InstanceScript::_SkipCheckRequiredBosses(Player const* player /*= nullptr*/) const
|
||||
{
|
||||
return player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES);
|
||||
}
|
||||
|
||||
void InstanceScript::Load(char const* data)
|
||||
{
|
||||
if (!data)
|
||||
|
||||
@@ -273,6 +273,8 @@ class InstanceScript : public ZoneScript
|
||||
void WriteSaveDataBossStates(std::ostringstream& data);
|
||||
virtual void WriteSaveDataMore(std::ostringstream& /*data*/) { }
|
||||
|
||||
bool _SkipCheckRequiredBosses(Player const* player = nullptr) const;
|
||||
|
||||
private:
|
||||
static void LoadObjectData(ObjectData const* creatureData, ObjectInfoMap& objectInfo);
|
||||
|
||||
|
||||
@@ -423,6 +423,24 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void MotionMaster::MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk)
|
||||
{
|
||||
Movement::PointsArray path(pathPoints, pathPoints + pathSize);
|
||||
|
||||
Movement::MoveSplineInit init(_owner);
|
||||
init.MovebyPath(path);
|
||||
init.SetSmooth();
|
||||
init.SetWalk(walk);
|
||||
init.Launch();
|
||||
|
||||
// This code is not correct
|
||||
// EffectMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE
|
||||
// need to call PointMovementGenerator with various pointIds
|
||||
Mutate(new EffectMovementGenerator(pointId), MOTION_SLOT_ACTIVE);
|
||||
//Position pos(pathPoints[pathSize - 1].x, pathPoints[pathSize - 1].y, pathPoints[pathSize - 1].z);
|
||||
//MovePoint(EVENT_CHARGE_PREPATH, pos, false);
|
||||
}
|
||||
|
||||
void MotionMaster::MoveFall(uint32 id /*=0*/)
|
||||
{
|
||||
// use larger distance for vmap height search than in most other cases
|
||||
|
||||
@@ -185,6 +185,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
|
||||
{ MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); }
|
||||
void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP);
|
||||
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
|
||||
void MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk);
|
||||
void MoveFall(uint32 id = 0);
|
||||
|
||||
void MoveSeekAssistance(float x, float y, float z);
|
||||
|
||||
@@ -3355,6 +3355,19 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
//! HACK: This spell break quest complete for alliance and on retail not used °_O
|
||||
spellInfo->Effects[EFFECT_0].Effect = 0;
|
||||
break;
|
||||
// VIOLET HOLD SPELLS
|
||||
//
|
||||
case 54258: // Water Globule (Ichoron)
|
||||
case 54264: // Water Globule (Ichoron)
|
||||
case 54265: // Water Globule (Ichoron)
|
||||
case 54266: // Water Globule (Ichoron)
|
||||
case 54267: // Water Globule (Ichoron)
|
||||
// in 3.3.5 there is only one radius in dbc which is 0 yards in this case
|
||||
// use max radius from 4.3.4
|
||||
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS);
|
||||
break;
|
||||
// ENDOF VIOLET HOLD
|
||||
//
|
||||
// ULDUAR SPELLS
|
||||
//
|
||||
case 62374: // Pursued (Flame Leviathan)
|
||||
|
||||
@@ -365,7 +365,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 uiDiff) override
|
||||
void UpdateEscortAI(uint32 uiDiff) override
|
||||
{
|
||||
if (uiPhase)
|
||||
{
|
||||
|
||||
@@ -272,7 +272,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 diff) override
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
//Check if we have a current target
|
||||
if (!UpdateVictim())
|
||||
|
||||
@@ -612,7 +612,7 @@ public:
|
||||
summoned->AI()->AttackStart(me);
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 Diff) override
|
||||
void UpdateEscortAI(uint32 Diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
|
||||
@@ -568,7 +568,7 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 diff) override
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
DialogueUpdate(diff);
|
||||
|
||||
|
||||
+1
-1
@@ -263,7 +263,7 @@ class npc_onyx_flamecaller : public CreatureScript
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 const diff) override
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "InstanceScript.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "WorldSession.h"
|
||||
#include "gundrak.h"
|
||||
#include "EventMap.h"
|
||||
|
||||
@@ -191,7 +190,7 @@ class instance_gundrak : public InstanceMapScript
|
||||
|
||||
bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override
|
||||
{
|
||||
if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES))
|
||||
if (_SkipCheckRequiredBosses(player))
|
||||
return true;
|
||||
|
||||
switch (bossId)
|
||||
|
||||
@@ -1140,7 +1140,7 @@ class npc_crok_scourgebane : public CreatureScript
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 const diff) override
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (_wipeCheckTimer <= diff)
|
||||
_wipeCheckTimer = 0;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "AccountMgr.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Map.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "PoolMgr.h"
|
||||
@@ -26,7 +25,6 @@
|
||||
#include "Transport.h"
|
||||
#include "TransportMgr.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "icecrown_citadel.h"
|
||||
|
||||
enum EventIds
|
||||
@@ -1121,7 +1119,7 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
|
||||
bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override
|
||||
{
|
||||
if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES))
|
||||
if (_SkipCheckRequiredBosses(player))
|
||||
return true;
|
||||
|
||||
switch (bossId)
|
||||
|
||||
@@ -437,7 +437,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 uiDiff) override
|
||||
void UpdateEscortAI(uint32 uiDiff) override
|
||||
{
|
||||
if (uiPhaseTimer <= uiDiff)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "InstanceScript.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "WorldSession.h"
|
||||
#include "halls_of_stone.h"
|
||||
|
||||
DoorData const doorData[] =
|
||||
@@ -172,7 +171,7 @@ class instance_halls_of_stone : public InstanceMapScript
|
||||
|
||||
bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override
|
||||
{
|
||||
if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES))
|
||||
if (_SkipCheckRequiredBosses(player))
|
||||
return true;
|
||||
|
||||
switch (bossId)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SUMMON_PLAYER = 21150,
|
||||
SPELL_ARCANE_VACUUM = 58694,
|
||||
SPELL_BLIZZARD = 58693,
|
||||
SPELL_MANA_DESTRUCTION = 59374,
|
||||
@@ -42,119 +43,91 @@ enum Yells
|
||||
|
||||
class boss_cyanigosa : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
|
||||
public:
|
||||
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
|
||||
|
||||
struct boss_cyanigosaAI : public BossAI
|
||||
{
|
||||
boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA)
|
||||
struct boss_cyanigosaAI : public BossAI
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA) { }
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiArcaneVacuumTimer = 10000;
|
||||
uiBlizzardTimer = 15000;
|
||||
uiManaDestructionTimer = 30000;
|
||||
uiTailSweepTimer = 20000;
|
||||
uiUncontrollableEnergyTimer = 25000;
|
||||
}
|
||||
|
||||
uint32 uiArcaneVacuumTimer;
|
||||
uint32 uiBlizzardTimer;
|
||||
uint32 uiManaDestructionTimer;
|
||||
uint32 uiTailSweepTimer;
|
||||
uint32 uiUncontrollableEnergyTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (instance->GetData(DATA_REMOVE_NPC) == 1)
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
instance->SetData(DATA_REMOVE_NPC, 0);
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiArcaneVacuumTimer <= diff)
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
DoCastAOE(SPELL_ARCANE_VACUUM);
|
||||
uiArcaneVacuumTimer = 10000;
|
||||
} else uiArcaneVacuumTimer -= diff;
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
if (uiBlizzardTimer <= diff)
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_BLIZZARD);
|
||||
uiBlizzardTimer = 15000;
|
||||
} else uiBlizzardTimer -= diff;
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
if (uiTailSweepTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_TAIL_SWEEP);
|
||||
uiTailSweepTimer = 20000;
|
||||
} else uiTailSweepTimer -= diff;
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
if (uiUncontrollableEnergyTimer <= diff)
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY);
|
||||
uiUncontrollableEnergyTimer = 25000;
|
||||
} else uiUncontrollableEnergyTimer -= diff;
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (IsHeroic())
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
if (uiManaDestructionTimer <= diff)
|
||||
scheduler.Schedule(Seconds(10), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_MANA_DESTRUCTION);
|
||||
uiManaDestructionTimer = 30000;
|
||||
} else uiManaDestructionTimer -= diff;
|
||||
DoCastAOE(SPELL_ARCANE_VACUUM);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(15), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
|
||||
DoCast(target, SPELL_BLIZZARD);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(20), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_TAIL_SWEEP);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(25), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(Seconds(30), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
|
||||
DoCast(target, SPELL_MANA_DESTRUCTION);
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
return GetVioletHoldAI<boss_cyanigosaAI>(creature);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_cyanigosaAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_defenseless : public AchievementCriteriaScript
|
||||
{
|
||||
public:
|
||||
achievement_defenseless() : AchievementCriteriaScript("achievement_defenseless")
|
||||
{
|
||||
}
|
||||
achievement_defenseless() : AchievementCriteriaScript("achievement_defenseless") { }
|
||||
|
||||
bool OnCheck(Player* /*player*/, Unit* target) override
|
||||
{
|
||||
@@ -165,10 +138,40 @@ class achievement_defenseless : public AchievementCriteriaScript
|
||||
if (!instance)
|
||||
return false;
|
||||
|
||||
if (!instance->GetData(DATA_DEFENSELESS))
|
||||
return false;
|
||||
return instance->GetData(DATA_DEFENSELESS) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
return true;
|
||||
class spell_cyanigosa_arcane_vacuum : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_cyanigosa_arcane_vacuum() : SpellScriptLoader("spell_cyanigosa_arcane_vacuum") { }
|
||||
|
||||
class spell_cyanigosa_arcane_vacuum_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_cyanigosa_arcane_vacuum_SpellScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_PLAYER))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_PLAYER, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_cyanigosa_arcane_vacuum_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_cyanigosa_arcane_vacuum_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,4 +179,5 @@ void AddSC_boss_cyanigosa()
|
||||
{
|
||||
new boss_cyanigosa();
|
||||
new achievement_defenseless();
|
||||
new spell_cyanigosa_arcane_vacuum();
|
||||
}
|
||||
@@ -41,269 +41,207 @@ enum Yells
|
||||
SAY_BOTH_ADDS_KILLED = 5
|
||||
};
|
||||
|
||||
enum ErekemEvents
|
||||
{
|
||||
EVENT_EARTH_SHIELD = 1,
|
||||
EVENT_CHAIN_HEAL,
|
||||
EVENT_BLOODLUST,
|
||||
EVENT_LIGHTNING_BOLT,
|
||||
EVENT_EARTH_SHOCK,
|
||||
EVENT_WINDFURY,
|
||||
EVENT_STORMSTRIKE
|
||||
};
|
||||
|
||||
class boss_erekem : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_erekem() : CreatureScript("boss_erekem") { }
|
||||
public:
|
||||
boss_erekem() : CreatureScript("boss_erekem") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_erekemAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_erekemAI : public ScriptedAI
|
||||
{
|
||||
boss_erekemAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct boss_erekemAI : public BossAI
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
phase = 0;
|
||||
breakBondsCd = 0;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS)
|
||||
boss_erekemAI(Creature* creature) : BossAI(creature, DATA_EREKEM)
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
pGuard1->DespawnOrUnsummon();
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
pGuard2->DespawnOrUnsummon();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
if (!pGuard1->IsAlive())
|
||||
pGuard1->Respawn();
|
||||
}
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (!pGuard2->IsAlive())
|
||||
pGuard2->Respawn();
|
||||
}
|
||||
Initialize();
|
||||
}
|
||||
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
pGuard1->Respawn();
|
||||
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
pGuard2->Respawn();
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
void Initialize()
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
{
|
||||
pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (!pGuard1->GetVictim() && pGuard1->AI())
|
||||
pGuard1->AI()->AttackStart(who);
|
||||
}
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (!pGuard2->GetVictim() && pGuard2->AI())
|
||||
pGuard2->AI()->AttackStart(who);
|
||||
}
|
||||
_phase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
DoCast(me, SPELL_EARTH_SHIELD);
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
BossAI::Reset();
|
||||
me->SetCanDualWield(false);
|
||||
}
|
||||
|
||||
if (GameObject* door = instance->GetGameObject(DATA_EREKEM_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
DoCast(me, SPELL_EARTH_SHIELD);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type == EFFECT_MOTION_TYPE && pointId == POINT_INTRO)
|
||||
me->SetFacingTo(4.921828f);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
instance->SetData(DATA_HANDLE_CELLS, DATA_EREKEM);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
bool CheckGuardAuras(Creature* guard) const
|
||||
{
|
||||
static uint32 const MechanicImmunityList =
|
||||
(1 << MECHANIC_SNARE)
|
||||
| (1 << MECHANIC_ROOT)
|
||||
| (1 << MECHANIC_FEAR)
|
||||
| (1 << MECHANIC_STUN)
|
||||
| (1 << MECHANIC_SLEEP)
|
||||
| (1 << MECHANIC_CHARM)
|
||||
| (1 << MECHANIC_SAPPED)
|
||||
| (1 << MECHANIC_HORROR)
|
||||
| (1 << MECHANIC_POLYMORPH)
|
||||
| (1 << MECHANIC_DISORIENTED)
|
||||
| (1 << MECHANIC_FREEZE)
|
||||
| (1 << MECHANIC_TURN);
|
||||
|
||||
static std::list<AuraType> const AuraImmunityList =
|
||||
{
|
||||
EnterEvadeMode();
|
||||
SPELL_AURA_MOD_STUN,
|
||||
SPELL_AURA_MOD_DECREASE_SPEED,
|
||||
SPELL_AURA_MOD_ROOT,
|
||||
SPELL_AURA_MOD_CONFUSE,
|
||||
SPELL_AURA_MOD_FEAR
|
||||
};
|
||||
|
||||
if (guard->HasAuraWithMechanic(MechanicImmunityList))
|
||||
return true;
|
||||
|
||||
for (AuraType type : AuraImmunityList)
|
||||
if (guard->HasAuraType(type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckGuardAlive() const
|
||||
{
|
||||
for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i)
|
||||
{
|
||||
if (Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i)))
|
||||
if (guard->IsAlive())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Unit* GetChainHealTarget() const
|
||||
{
|
||||
if (HealthBelowPct(85))
|
||||
return me;
|
||||
|
||||
for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i)
|
||||
{
|
||||
if (Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i)))
|
||||
if (guard->IsAlive() && !guard->HealthAbovePct(75))
|
||||
return guard;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
|
||||
events.ScheduleEvent(EVENT_EARTH_SHIELD, 20000);
|
||||
events.ScheduleEvent(EVENT_BLOODLUST, 15000);
|
||||
events.ScheduleEvent(EVENT_CHAIN_HEAL, 10000);
|
||||
events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 2000);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (phase == 0)
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
if (_phase == 0 && !CheckGuardAlive())
|
||||
{
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (!pGuard1->IsAlive() && !pGuard2->IsAlive())
|
||||
{
|
||||
phase = 1;
|
||||
DoCastVictim(SPELL_STORMSTRIKE);
|
||||
DoCast(SPELL_WINDFURY);
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, urand(2000, 8000));
|
||||
events.ScheduleEvent(EVENT_WINDFURY, urand(1500, 2000));
|
||||
events.ScheduleEvent(EVENT_STORMSTRIKE, urand(1500, 2000));
|
||||
}
|
||||
}
|
||||
_phase = 1;
|
||||
me->SetCanDualWield(true);
|
||||
DoCast(me, SPELL_WINDFURY, true);
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (breakBondsCd <= 0)
|
||||
{
|
||||
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
|
||||
scheduler.Update(diff, [this]
|
||||
{
|
||||
if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)))
|
||||
{
|
||||
if (pGuard1->IsAlive())
|
||||
{
|
||||
if (pGuard1->HasAuraType(SPELL_AURA_MOD_STUN) || pGuard1->HasAuraType(SPELL_AURA_MOD_ROOT)
|
||||
|| pGuard1->HasAuraType(SPELL_AURA_MOD_CONFUSE) || pGuard1->HasAuraType(SPELL_AURA_MOD_PACIFY)
|
||||
|| pGuard1->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
|
||||
{
|
||||
DoCast(SPELL_BREAK_BONDS);
|
||||
breakBondsCd = 10000;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (pGuard2->IsAlive())
|
||||
{
|
||||
if (pGuard2->HasAuraType(SPELL_AURA_MOD_STUN) || pGuard2->HasAuraType(SPELL_AURA_MOD_ROOT)
|
||||
|| pGuard2->HasAuraType(SPELL_AURA_MOD_CONFUSE) || pGuard2->HasAuraType(SPELL_AURA_MOD_PACIFY)
|
||||
|| pGuard2->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
|
||||
{
|
||||
DoCast(SPELL_BREAK_BONDS);
|
||||
breakBondsCd = 10000;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_phase == 1)
|
||||
DoSpellAttackIfReady(SPELL_STORMSTRIKE);
|
||||
else
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
else
|
||||
breakBondsCd -= diff;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
case EVENT_EARTH_SHIELD:
|
||||
scheduler.Schedule(Seconds(20), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* ally = DoSelectLowestHpFriendly(30.0f))
|
||||
DoCast(ally, SPELL_EARTH_SHIELD);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHIELD, 20000);
|
||||
break;
|
||||
case EVENT_BLOODLUST:
|
||||
|
||||
task.Repeat(Seconds(20));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(2), [this](TaskContext task)
|
||||
{
|
||||
DoCast(SPELL_BLOODLUST);
|
||||
events.ScheduleEvent(EVENT_BLOODLUST, urand(35000, 45000));
|
||||
break;
|
||||
case EVENT_LIGHTNING_BOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
task.Repeat(Seconds(35), Seconds(45));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(2), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f))
|
||||
DoCast(target, SPELL_LIGHTNING_BOLT);
|
||||
events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 2500);
|
||||
break;
|
||||
case EVENT_CHAIN_HEAL:
|
||||
|
||||
task.Repeat(Milliseconds(2500));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(10), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* ally = DoSelectLowestHpFriendly(40.0f))
|
||||
DoCast(ally, SPELL_CHAIN_HEAL);
|
||||
{
|
||||
Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1));
|
||||
Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2));
|
||||
events.ScheduleEvent(EVENT_CHAIN_HEAL, ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()) ? 3000 : 8000 + rand() % 3000));
|
||||
}
|
||||
break;
|
||||
case EVENT_EARTH_SHOCK:
|
||||
|
||||
task.Repeat(!CheckGuardAlive() ? Seconds(3) : (Seconds(8), Seconds(11)));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(2), Seconds(8), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, urand(8000, 13000));
|
||||
break;
|
||||
case EVENT_WINDFURY:
|
||||
DoCast(SPELL_WINDFURY);
|
||||
events.ScheduleEvent(EVENT_WINDFURY, urand(1500, 2000));
|
||||
break;
|
||||
case EVENT_STORMSTRIKE:
|
||||
DoCastVictim(SPELL_STORMSTRIKE);
|
||||
events.ScheduleEvent(EVENT_STORMSTRIKE, urand(1500, 2000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
task.Repeat(Seconds(8), Seconds(13));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(0), [this](TaskContext task)
|
||||
{
|
||||
for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i)
|
||||
{
|
||||
Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i));
|
||||
|
||||
if (guard && guard->IsAlive() && CheckGuardAuras(guard))
|
||||
{
|
||||
DoCastAOE(SPELL_BREAK_BONDS);
|
||||
task.Repeat(Seconds(10));
|
||||
return;
|
||||
}
|
||||
}
|
||||
task.Repeat(Milliseconds(500));
|
||||
});
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
uint8 _phase;
|
||||
};
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
uint8 phase;
|
||||
int32 breakBondsCd;
|
||||
};
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVioletHoldAI<boss_erekemAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
enum GuardSpells
|
||||
@@ -315,85 +253,61 @@ enum GuardSpells
|
||||
|
||||
class npc_erekem_guard : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_erekem_guard() : CreatureScript("npc_erekem_guard") { }
|
||||
public:
|
||||
npc_erekem_guard() : CreatureScript("npc_erekem_guard") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_erekem_guardAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_erekem_guardAI : public ScriptedAI
|
||||
{
|
||||
npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct npc_erekem_guardAI : public ScriptedAI
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiStrikeTimer = urand(4000, 8000);
|
||||
uiHowlingScreechTimer = urand(8000, 13000);
|
||||
uiGushingWoundTimer = urand(1000, 3000);
|
||||
}
|
||||
|
||||
uint32 uiGushingWoundTimer;
|
||||
uint32 uiHowlingScreechTimer;
|
||||
uint32 uiStrikeTimer;
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
void Reset() override
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
scheduler.CancelAll();
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff,
|
||||
std::bind(&ScriptedAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
void ScheduledTasks()
|
||||
{
|
||||
scheduler.Schedule(Seconds(4), Seconds(8), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_STRIKE);
|
||||
task.Repeat(Seconds(4), Seconds(8));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(8), Seconds(13), [this](TaskContext task)
|
||||
{
|
||||
DoCastAOE(SPELL_HOWLING_SCREECH);
|
||||
task.Repeat(Seconds(8), Seconds(13));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(1), Seconds(3), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_GUSHING_WOUND);
|
||||
task.Repeat(Seconds(7), Seconds(12));
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler scheduler;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
|
||||
if (uiStrikeTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_STRIKE);
|
||||
uiStrikeTimer = urand(4000, 8000);
|
||||
} else uiStrikeTimer -= diff;
|
||||
|
||||
if (uiHowlingScreechTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_HOWLING_SCREECH);
|
||||
uiHowlingScreechTimer = urand(8000, 13000);
|
||||
} else uiHowlingScreechTimer -= diff;
|
||||
|
||||
if (uiGushingWoundTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_GUSHING_WOUND);
|
||||
uiGushingWoundTimer = urand(7000, 12000);
|
||||
} else uiGushingWoundTimer -= diff;
|
||||
return GetVioletHoldAI<npc_erekem_guardAI>(creature);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_erekem()
|
||||
|
||||
@@ -17,26 +17,32 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "violet_hold.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_DRAINED = 59820,
|
||||
SPELL_FRENZY = 54312,
|
||||
SPELL_PROTECTIVE_BUBBLE = 54306,
|
||||
SPELL_WATER_BLAST = 54237,
|
||||
SPELL_WATER_BOLT_VOLLEY = 54241,
|
||||
SPELL_SPLASH = 59516,
|
||||
SPELL_SPLATTER = 54259,
|
||||
SPELL_PROTECTIVE_BUBBLE = 54306,
|
||||
SPELL_FRENZY = 54312,
|
||||
SPELL_BURST = 54379,
|
||||
SPELL_WATER_GLOBULE = 54268,
|
||||
SPELL_MERGE = 54269,
|
||||
SPELL_WATER_GLOBULE_VISUAL = 54260
|
||||
};
|
||||
SPELL_DRAINED = 59820,
|
||||
SPELL_THREAT_PROC = 61732,
|
||||
SPELL_SHRINK = 54297,
|
||||
|
||||
enum IchoronCreatures
|
||||
{
|
||||
NPC_ICHOR_GLOBULE = 29321,
|
||||
NPC_ICHORON_SUMMON_TARGET = 29326
|
||||
SPELL_WATER_GLOBULE_SUMMON_1 = 54258,
|
||||
SPELL_WATER_GLOBULE_SUMMON_2 = 54264,
|
||||
SPELL_WATER_GLOBULE_SUMMON_3 = 54265,
|
||||
SPELL_WATER_GLOBULE_SUMMON_4 = 54266,
|
||||
SPELL_WATER_GLOBULE_SUMMON_5 = 54267,
|
||||
SPELL_WATER_GLOBULE_TRANSFORM = 54268,
|
||||
SPELL_WATER_GLOBULE_VISUAL = 54260,
|
||||
|
||||
SPELL_MERGE = 54269,
|
||||
SPELL_SPLASH = 59516
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -47,483 +53,412 @@ enum Yells
|
||||
SAY_SPAWN = 3,
|
||||
SAY_ENRAGE = 4,
|
||||
SAY_SHATTER = 5,
|
||||
SAY_BUBBLE = 6
|
||||
SAY_BUBBLE = 6,
|
||||
EMOTE_SHATTER = 7
|
||||
};
|
||||
|
||||
enum Actions
|
||||
{
|
||||
ACTION_WATER_ELEMENT_HIT = 1
|
||||
};
|
||||
|
||||
enum IchoronEvents
|
||||
{
|
||||
EVENT_WATER_BLAST = 1,
|
||||
EVENT_WATER_BOLT_VOLLEY
|
||||
};
|
||||
|
||||
enum GlobuleEvents
|
||||
{
|
||||
EVENT_GLOBULE_MOVE = 1
|
||||
ACTION_WATER_GLOBULE_HIT = 1,
|
||||
ACTION_PROTECTIVE_BUBBLE_SHATTERED = 2,
|
||||
ACTION_DRAINED = 3
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
DATA_GLOBULE_PATH = 0,
|
||||
DATA_DEHYDRATION = 1
|
||||
};
|
||||
|
||||
|
||||
#define MAX_GLOBULE_PATHS 10
|
||||
|
||||
Position const globulePaths[MAX_GLOBULE_PATHS] =
|
||||
{
|
||||
// first target
|
||||
{ 1861.357f, 804.039f, 44.008f, 6.268f },
|
||||
{ 1869.375f, 803.976f, 38.781f, 0.009f },
|
||||
// second target
|
||||
{ 1888.063f, 763.488f, 47.667f, 1.744f },
|
||||
{ 1882.865f, 776.385f, 38.824f, 1.882f },
|
||||
// third target
|
||||
{ 1935.140f, 817.752f, 52.181f, 1.885f },
|
||||
{ 1916.642f, 826.337f, 39.139f, 2.851f },
|
||||
// fourth target
|
||||
{ 1930.257f, 833.053f, 46.906f, 4.579f },
|
||||
{ 1916.642f, 826.337f, 39.139f, 2.851f },
|
||||
// fifth target
|
||||
{ 1878.248f, 841.883f, 43.334f, 4.717f },
|
||||
{ 1879.438f, 834.443f, 38.699f, 4.831f }
|
||||
};
|
||||
|
||||
class boss_ichoron : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_ichoron() : CreatureScript("boss_ichoron") { }
|
||||
public:
|
||||
boss_ichoron() : CreatureScript("boss_ichoron") { }
|
||||
|
||||
struct boss_ichoronAI : public ScriptedAI
|
||||
{
|
||||
boss_ichoronAI(Creature* creature) : ScriptedAI(creature), m_waterElements(creature)
|
||||
struct boss_ichoronAI : public BossAI
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
boss_ichoronAI(Creature* creature) : BossAI(creature, DATA_ICHORON)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
bIsExploded = false;
|
||||
bIsFrenzy = false;
|
||||
bIsDrained = false;
|
||||
dehydration = true;
|
||||
drainedTimer = 50;
|
||||
burstTimer = 15000;
|
||||
}
|
||||
/// for some reason ichoron can't walk back to it's water basin on evade
|
||||
me->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
void Initialize()
|
||||
{
|
||||
_isFrenzy = false;
|
||||
_dehydration = true;
|
||||
}
|
||||
|
||||
events.Reset();
|
||||
me->SetVisible(true);
|
||||
DespawnWaterElements();
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
BossAI::Reset();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
}
|
||||
DoCast(me, SPELL_THREAT_PROC, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
DoCast(me, SPELL_PROTECTIVE_BUBBLE);
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
instance->SetData(DATA_HANDLE_CELLS, DATA_ICHORON);
|
||||
}
|
||||
|
||||
if (GameObject* door = instance->GetGameObject(DATA_ICHORON_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
void DoAction(int32 actionId) override
|
||||
{
|
||||
switch (actionId)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
case ACTION_WATER_GLOBULE_HIT:
|
||||
if (!me->IsAlive())
|
||||
break;
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000));
|
||||
events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000));
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (!me->IsAlive())
|
||||
return;
|
||||
|
||||
switch (param)
|
||||
{
|
||||
case ACTION_WATER_ELEMENT_HIT:
|
||||
{
|
||||
if (bIsExploded)
|
||||
DoExplodeCompleted();
|
||||
|
||||
me->SetHealth(me->GetHealth() + me->CountPctFromMaxHealth(3));
|
||||
dehydration = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DespawnWaterElements()
|
||||
{
|
||||
m_waterElements.DespawnAll();
|
||||
}
|
||||
|
||||
// call when explode shall stop.
|
||||
// either when "hit" by a bubble, or when there is no bubble left.
|
||||
void DoExplodeCompleted()
|
||||
{
|
||||
bIsExploded = false;
|
||||
bIsDrained = false;
|
||||
|
||||
if (!HealthBelowPct(25))
|
||||
{
|
||||
Talk(SAY_BUBBLE);
|
||||
DoCast(me, SPELL_PROTECTIVE_BUBBLE, true);
|
||||
}
|
||||
|
||||
me->SetVisible(true);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_DEHYDRATION)
|
||||
return dehydration ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!who->ToCreature())
|
||||
return;
|
||||
|
||||
if (who->GetEntry() != NPC_ICHOR_GLOBULE)
|
||||
return;
|
||||
|
||||
if (!me->IsWithinDist(who, 4.0f, false))
|
||||
return;
|
||||
|
||||
if (who->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
|
||||
return;
|
||||
|
||||
who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
who->CastSpell(who, SPELL_MERGE);
|
||||
DoAction(ACTION_WATER_ELEMENT_HIT);
|
||||
who->ToCreature()->DespawnOrUnsummon(1000);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
if (bIsExploded)
|
||||
{
|
||||
bIsExploded = false;
|
||||
me->SetVisible(true);
|
||||
}
|
||||
|
||||
DespawnWaterElements();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
summoned->SetSpeed(MOVE_RUN, 0.3f);
|
||||
m_waterElements.Summon(summoned);
|
||||
|
||||
instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
m_waterElements.Despawn(summoned);
|
||||
|
||||
if (m_waterElements.empty() && bIsExploded)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
DoExplodeCompleted();
|
||||
}
|
||||
|
||||
instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID());
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded)
|
||||
{
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCast(me, SPELL_FRENZY, true);
|
||||
bIsFrenzy = true;
|
||||
}
|
||||
|
||||
if (!bIsFrenzy)
|
||||
{
|
||||
if (!bIsExploded)
|
||||
{
|
||||
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
|
||||
me->ModifyHealth(int32(me->CountPctFromMaxHealth(3)));
|
||||
_dehydration = false;
|
||||
break;
|
||||
case ACTION_PROTECTIVE_BUBBLE_SHATTERED:
|
||||
{
|
||||
bIsExploded = true;
|
||||
Talk(SAY_SHATTER);
|
||||
DoCast(SPELL_BURST);
|
||||
me->RemoveAllAuras();
|
||||
burstTimer = 15000;
|
||||
Talk(EMOTE_SHATTER);
|
||||
|
||||
std::list<Creature*> summonTargets;
|
||||
GetCreatureListWithEntryInGrid(summonTargets, me, NPC_ICHORON_SUMMON_TARGET, 200.0f);
|
||||
std::list<Creature*>::iterator itr = summonTargets.begin();
|
||||
DoCastAOE(SPELL_SPLATTER, true);
|
||||
DoCastAOE(SPELL_BURST, true);
|
||||
DoCast(me, SPELL_DRAINED, true);
|
||||
|
||||
for (uint8 i = 0; i < MAX_GLOBULE_PATHS; i++)
|
||||
{
|
||||
std::advance(itr, urand(0, summonTargets.size() - 1)); // I take a random minion in the list
|
||||
Position targetPos = (*itr)->GetRandomNearPosition(10.0f);
|
||||
itr = summonTargets.begin();
|
||||
TempSummon* globule = me->SummonCreature(NPC_ICHOR_GLOBULE, targetPos, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
DoCast(globule, SPELL_WATER_GLOBULE_VISUAL);
|
||||
|
||||
float minDistance = 1000.0f;
|
||||
uint8 nextPath = 0;
|
||||
// I move the globules to next position. the 10 positions are in couples, defined in globulePaths, so i have to increase by 2.
|
||||
for (uint8 gpath = 0; gpath < MAX_GLOBULE_PATHS; gpath += 2)
|
||||
{
|
||||
if (globule->GetDistance(globulePaths[gpath]) < minDistance)
|
||||
{
|
||||
minDistance = globule->GetDistance(globulePaths[gpath]);
|
||||
nextPath = gpath;
|
||||
}
|
||||
}
|
||||
|
||||
globule->GetAI()->SetData(DATA_GLOBULE_PATH, nextPath);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_WATER_BLAST:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_WATER_BLAST);
|
||||
events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000));
|
||||
break;
|
||||
case EVENT_WATER_BOLT_VOLLEY:
|
||||
DoCast(SPELL_WATER_BOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000));
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
else if (!bIsDrained)
|
||||
{
|
||||
if (drainedTimer <= 0)
|
||||
{
|
||||
bIsDrained = true;
|
||||
drainedTimer = 50;
|
||||
uint32 damage = me->CountPctFromMaxHealth(30);
|
||||
if (me->GetHealth() < damage)
|
||||
me->SetHealth(me->CountPctFromMaxHealth(1));
|
||||
else
|
||||
me->LowerPlayerDamageReq(damage);
|
||||
me->ModifyHealth(-std::min<int32>(damage, me->GetHealth() - 1));
|
||||
|
||||
scheduler.DelayAll(Seconds(15));
|
||||
break;
|
||||
}
|
||||
case ACTION_DRAINED:
|
||||
if (HealthAbovePct(30))
|
||||
{
|
||||
me->SetHealth(me->GetHealth() - damage);
|
||||
me->LowerPlayerDamageReq(damage);
|
||||
Talk(SAY_BUBBLE);
|
||||
DoCast(me, SPELL_PROTECTIVE_BUBBLE, true);
|
||||
}
|
||||
DoCast(SPELL_DRAINED);
|
||||
me->SetVisible(false);
|
||||
me->AttackStop();
|
||||
}
|
||||
else
|
||||
drainedTimer -= diff;
|
||||
}
|
||||
else if (bIsDrained)
|
||||
{
|
||||
if (burstTimer <= 0)
|
||||
{
|
||||
DoExplodeCompleted();
|
||||
}
|
||||
else
|
||||
burstTimer -= diff;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (type == DATA_DEHYDRATION)
|
||||
return _dehydration ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
|
||||
if (summon->GetEntry() == NPC_ICHOR_GLOBULE)
|
||||
DoCast(summon, SPELL_WATER_GLOBULE_VISUAL);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
BossAI::SummonedCreatureDespawn(summon);
|
||||
|
||||
if (summons.empty())
|
||||
me->RemoveAurasDueToSpell(SPELL_DRAINED, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
if (!_isFrenzy && HealthBelowPct(25) && !me->HasAura(SPELL_DRAINED))
|
||||
{
|
||||
case EVENT_WATER_BLAST:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_WATER_BLAST);
|
||||
events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000));
|
||||
break;
|
||||
case EVENT_WATER_BOLT_VOLLEY:
|
||||
DoCast(SPELL_WATER_BOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000));
|
||||
break;
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCast(me, SPELL_FRENZY, true);
|
||||
_isFrenzy = true;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
scheduler.Async([this]
|
||||
{
|
||||
DoCast(me, SPELL_SHRINK);
|
||||
DoCast(me, SPELL_PROTECTIVE_BUBBLE);
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(10), Seconds(15), [this](TaskContext task)
|
||||
{
|
||||
DoCastAOE(SPELL_WATER_BOLT_VOLLEY);
|
||||
task.Repeat(Seconds(10), Seconds(15));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(6), Seconds(9), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f))
|
||||
DoCast(target, SPELL_WATER_BLAST);
|
||||
task.Repeat(Seconds(6), Seconds(9));
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isFrenzy;
|
||||
bool _dehydration;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVioletHoldAI<boss_ichoronAI>(creature);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
SummonList m_waterElements;
|
||||
EventMap events;
|
||||
bool bIsExploded;
|
||||
bool bIsFrenzy;
|
||||
bool bIsDrained;
|
||||
bool dehydration;
|
||||
int32 drainedTimer;
|
||||
int32 burstTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_ichoronAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_ichor_globule : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_ichor_globule() : CreatureScript("npc_ichor_globule") { }
|
||||
public:
|
||||
npc_ichor_globule() : CreatureScript("npc_ichor_globule") { }
|
||||
|
||||
struct npc_ichor_globuleAI : public ScriptedAI
|
||||
{
|
||||
npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct npc_ichor_globuleAI : public ScriptedAI
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
pathId = 0;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
events.Reset();
|
||||
DoCast(SPELL_WATER_GLOBULE);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void SetData(uint32 id, uint32 data) override
|
||||
{
|
||||
if (id == DATA_GLOBULE_PATH)
|
||||
npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
pathId = data;
|
||||
me->GetMotionMaster()->MovePoint(0, globulePaths[pathId]);
|
||||
_instance = creature->GetInstanceScript();
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
switch (id)
|
||||
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
case 0:
|
||||
me->GetMotionMaster()->Clear();
|
||||
events.ScheduleEvent(EVENT_GLOBULE_MOVE, 500);
|
||||
break;
|
||||
case 1:
|
||||
me->GetMotionMaster()->Clear();
|
||||
if (Creature* ichoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON)))
|
||||
me->GetMotionMaster()->MoveFollow(ichoron, 0.0f, 0.0f);
|
||||
break;
|
||||
if (spellInfo->Id == SPELL_WATER_GLOBULE_VISUAL)
|
||||
{
|
||||
DoCast(me, SPELL_WATER_GLOBULE_TRANSFORM);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->GetMotionMaster()->MoveFollow(caster, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// on retail spell casted on a creature's death are not casted after death but keeping mob at 1 health, casting it and then letting the mob die.
|
||||
// this feature should be still implemented
|
||||
void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != FOLLOW_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (_instance->GetObjectGuid(DATA_ICHORON).GetCounter() != id)
|
||||
return;
|
||||
|
||||
me->CastSpell(me, SPELL_MERGE);
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
// on retail spell casted on a creature's death are not casted after death but keeping mob at 1 health, casting it and then letting the mob die.
|
||||
// this feature should be still implemented
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
DoCastAOE(SPELL_SPLASH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override { }
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
int32 actualHp = me->GetHealth();
|
||||
actualHp -= damage;
|
||||
|
||||
if (actualHp <= 0)
|
||||
DoCast(SPELL_SPLASH);
|
||||
return GetVioletHoldAI<npc_ichor_globuleAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
// 59820 - Drained
|
||||
class spell_ichoron_drained : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_ichoron_drained() : SpellScriptLoader("spell_ichoron_drained") { }
|
||||
|
||||
class spell_ichoron_drained_AuraScript : public AuraScript
|
||||
{
|
||||
events.Update(diff);
|
||||
PrepareAuraScript(spell_ichoron_drained_AuraScript);
|
||||
|
||||
if (events.ExecuteEvent() == EVENT_GLOBULE_MOVE)
|
||||
me->GetMotionMaster()->MovePoint(1, globulePaths[pathId + 1]);
|
||||
bool Load() override
|
||||
{
|
||||
return GetOwner()->GetEntry() == NPC_ICHORON || GetOwner()->GetEntry() == NPC_DUMMY_ICHORON;
|
||||
}
|
||||
|
||||
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_31);
|
||||
GetTarget()->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_31);
|
||||
GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
if (GetTarget()->IsAIEnabled)
|
||||
GetTarget()->GetAI()->DoAction(ACTION_DRAINED);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_ichoron_drained_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_drained_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_ichoron_drained_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
uint8 pathId;
|
||||
};
|
||||
// 54269 - Merge
|
||||
class spell_ichoron_merge : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_ichoron_merge() : SpellScriptLoader("spell_ichoron_merge") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_ichor_globuleAI>(creature);
|
||||
}
|
||||
class spell_ichoron_merge_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_ichoron_merge_SpellScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
if (!sSpellMgr->GetSpellInfo(SPELL_SHRINK))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Creature* target = GetHitCreature())
|
||||
{
|
||||
if (Aura* aura = target->GetAura(SPELL_SHRINK))
|
||||
aura->ModStackAmount(-1);
|
||||
|
||||
target->AI()->DoAction(ACTION_WATER_GLOBULE_HIT);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_ichoron_merge_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_ichoron_merge_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
// 54306 - Protective Bubble
|
||||
class spell_ichoron_protective_bubble : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_ichoron_protective_bubble() : SpellScriptLoader("spell_ichoron_protective_bubble") { }
|
||||
|
||||
class spell_ichoron_protective_bubble_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_ichoron_protective_bubble_AuraScript);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetOwner()->GetEntry() == NPC_ICHORON || GetOwner()->GetEntry() == NPC_DUMMY_ICHORON;
|
||||
}
|
||||
|
||||
void HandleShatter(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
//if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL)
|
||||
if (GetAura()->GetCharges() <= 1)
|
||||
if (GetTarget()->IsAIEnabled)
|
||||
GetTarget()->GetAI()->DoAction(ACTION_PROTECTIVE_BUBBLE_SHATTERED);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_protective_bubble_AuraScript::HandleShatter, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_ichoron_protective_bubble_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
// 54259 - Splatter
|
||||
class spell_ichoron_splatter : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_ichoron_splatter() : SpellScriptLoader("spell_ichoron_splatter") { }
|
||||
|
||||
class spell_ichoron_splatter_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_ichoron_splatter_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
if (!sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_1)
|
||||
|| !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_2)
|
||||
|| !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_3)
|
||||
|| !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_4)
|
||||
|| !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_5)
|
||||
|| !sSpellMgr->GetSpellInfo(SPELL_SHRINK))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PeriodicTick(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
GetTarget()->CastSpell(GetTarget(), RAND(SPELL_WATER_GLOBULE_SUMMON_1, SPELL_WATER_GLOBULE_SUMMON_2, SPELL_WATER_GLOBULE_SUMMON_3, SPELL_WATER_GLOBULE_SUMMON_4, SPELL_WATER_GLOBULE_SUMMON_5), true);
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
if (Aura* aura = GetTarget()->GetAura(SPELL_SHRINK))
|
||||
aura->ModStackAmount(10);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ichoron_splatter_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_splatter_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_ichoron_splatter_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_dehydration : public AchievementCriteriaScript
|
||||
{
|
||||
public:
|
||||
achievement_dehydration() : AchievementCriteriaScript("achievement_dehydration")
|
||||
{
|
||||
}
|
||||
achievement_dehydration() : AchievementCriteriaScript("achievement_dehydration") { }
|
||||
|
||||
bool OnCheck(Player* /*player*/, Unit* target) override
|
||||
{
|
||||
@@ -542,5 +477,9 @@ void AddSC_boss_ichoron()
|
||||
{
|
||||
new boss_ichoron();
|
||||
new npc_ichor_globule();
|
||||
new spell_ichoron_drained();
|
||||
new spell_ichoron_merge();
|
||||
new spell_ichoron_protective_bubble();
|
||||
new spell_ichoron_splatter();
|
||||
new achievement_dehydration();
|
||||
}
|
||||
@@ -27,130 +27,82 @@ enum Spells
|
||||
SPELL_LAVA_BURN = 54249
|
||||
};
|
||||
|
||||
enum LavanthorEvents
|
||||
{
|
||||
EVENT_CAUTERIZING_FLAMES = 1,
|
||||
EVENT_FIREBOLT,
|
||||
EVENT_FLAME_BREATH,
|
||||
EVENT_LAVA_BURN
|
||||
};
|
||||
|
||||
class boss_lavanthor : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_lavanthor() : CreatureScript("boss_lavanthor") { }
|
||||
public:
|
||||
boss_lavanthor() : CreatureScript("boss_lavanthor") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_lavanthorAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_lavanthorAI : public ScriptedAI
|
||||
{
|
||||
boss_lavanthorAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct boss_lavanthorAI : public BossAI
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
boss_lavanthorAI(Creature* creature) : BossAI(creature, DATA_LAVANTHOR) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
events.Reset();
|
||||
}
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (GameObject* door = instance->GetGameObject(DATA_LAVANTHOR_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
instance->SetData(DATA_HANDLE_CELLS, DATA_LAVANTHOR);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_FIREBOLT, 1000);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 5000);
|
||||
events.ScheduleEvent(EVENT_LAVA_BURN, 10000);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_CAUTERIZING_FLAMES, 3000);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
case EVENT_FIREBOLT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
scheduler.Schedule(Seconds(1), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
|
||||
DoCast(target, SPELL_FIREBOLT);
|
||||
events.ScheduleEvent(EVENT_FIREBOLT, urand(5000, 13000));
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCast(SPELL_FLAME_BREATH);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, urand(10000, 15000));
|
||||
break;
|
||||
case EVENT_LAVA_BURN:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
task.Repeat(Seconds(5), Seconds(13));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(5), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_FLAME_BREATH);
|
||||
task.Repeat(Seconds(10), Seconds(15));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(10), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f))
|
||||
DoCast(target, SPELL_LAVA_BURN);
|
||||
events.ScheduleEvent(EVENT_LAVA_BURN, urand(15000, 23000));
|
||||
break;
|
||||
case EVENT_CAUTERIZING_FLAMES:
|
||||
DoCast(SPELL_CAUTERIZING_FLAMES);
|
||||
events.ScheduleEvent(EVENT_CAUTERIZING_FLAMES, urand(10000, 16000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
task.Repeat(Seconds(15), Seconds(23));
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(Seconds(3), [this](TaskContext task)
|
||||
{
|
||||
DoCastAOE(SPELL_CAUTERIZING_FLAMES);
|
||||
task.Repeat(Seconds(10), Seconds(16));
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
return GetVioletHoldAI<boss_lavanthorAI>(creature);
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_lavanthor()
|
||||
|
||||
@@ -25,8 +25,8 @@ enum Spells
|
||||
{
|
||||
SPELL_CORROSIVE_SALIVA = 54527,
|
||||
SPELL_OPTIC_LINK = 54396,
|
||||
SPELL_RAY_OF_PAIN = 54438, // NYI missing spelldifficulty
|
||||
SPELL_RAY_OF_SUFFERING = 54442, // NYI missing spelldifficulty
|
||||
SPELL_RAY_OF_PAIN = 54438,
|
||||
SPELL_RAY_OF_SUFFERING = 54442,
|
||||
|
||||
// Visual
|
||||
SPELL_OPTIC_LINK_LEVEL_1 = 54393,
|
||||
@@ -34,191 +34,107 @@ enum Spells
|
||||
SPELL_OPTIC_LINK_LEVEL_3 = 54395
|
||||
};
|
||||
|
||||
enum MoraggEvents
|
||||
{
|
||||
EVENT_CORROSIVE_SALIVA = 1,
|
||||
EVENT_OPTIC_LINK
|
||||
};
|
||||
|
||||
class boss_moragg : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_moragg() : CreatureScript("boss_moragg") { }
|
||||
public:
|
||||
boss_moragg() : CreatureScript("boss_moragg") { }
|
||||
|
||||
struct boss_moraggAI : public ScriptedAI
|
||||
{
|
||||
boss_moraggAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct boss_moraggAI : public BossAI
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
boss_moraggAI(Creature* creature) : BossAI(creature, DATA_MORAGG) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
}
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (GameObject* door = instance->GetGameObject(DATA_MORAGG_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
instance->SetData(DATA_HANDLE_CELLS, DATA_MORAGG);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
me->SetInCombatWithZone();
|
||||
|
||||
DoCast(SPELL_RAY_OF_PAIN);
|
||||
DoCast(SPELL_RAY_OF_SUFFERING);
|
||||
events.ScheduleEvent(EVENT_OPTIC_LINK, 15000);
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_SALIVA, 5000);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
case EVENT_OPTIC_LINK:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
scheduler.Async([this]
|
||||
{
|
||||
DoCast(me, SPELL_RAY_OF_PAIN);
|
||||
DoCast(me, SPELL_RAY_OF_SUFFERING);
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(15), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
|
||||
DoCast(target, SPELL_OPTIC_LINK);
|
||||
events.ScheduleEvent(EVENT_OPTIC_LINK, 25000);
|
||||
break;
|
||||
case EVENT_CORROSIVE_SALIVA:
|
||||
task.Repeat(Seconds(25));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(5), [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_CORROSIVE_SALIVA);
|
||||
events.ScheduleEvent(EVENT_CORROSIVE_SALIVA, 10000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
task.Repeat(Seconds(10));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
return GetVioletHoldAI<boss_moraggAI>(creature);
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_moraggAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moragg_ray_of_suffering : public SpellScriptLoader
|
||||
class spell_moragg_ray : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_moragg_ray_of_suffering() : SpellScriptLoader("spell_moragg_ray_of_suffering") { }
|
||||
public:
|
||||
spell_moragg_ray() : SpellScriptLoader("spell_moragg_ray") { }
|
||||
|
||||
class spell_moragg_ray_of_suffering_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_moragg_ray_of_suffering_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
class spell_moragg_ray_AuraScript : public AuraScript
|
||||
{
|
||||
PreventDefaultAction();
|
||||
std::list<HostileReference*> players = GetTarget()->getThreatManager().getThreatList();
|
||||
if (!players.empty())
|
||||
PrepareAuraScript(spell_moragg_ray_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
std::list<HostileReference*>::iterator itr = players.begin();
|
||||
std::advance(itr, urand(0, players.size() - 1));
|
||||
PreventDefaultAction();
|
||||
|
||||
uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
|
||||
GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_MAX_TARGETS, 1, (*itr)->getTarget(), TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
if (!GetTarget()->IsAIEnabled)
|
||||
return;
|
||||
|
||||
if (Unit* target = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
|
||||
{
|
||||
uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
|
||||
GetTarget()->CastSpell(target, triggerSpell, TRIGGERED_FULL_MASK, nullptr, aurEff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_of_suffering_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_moragg_ray_of_suffering_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moragg_ray_of_pain : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_moragg_ray_of_pain() : SpellScriptLoader("spell_moragg_ray_of_pain") { }
|
||||
|
||||
class spell_moragg_ray_of_pain_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_moragg_ray_of_pain_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
std::list<HostileReference*> players = GetTarget()->getThreatManager().getThreatList();
|
||||
if (!players.empty())
|
||||
void Register() override
|
||||
{
|
||||
std::list<HostileReference*>::iterator itr = players.begin();
|
||||
std::advance(itr, urand(0, players.size() - 1));
|
||||
|
||||
uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
|
||||
GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_MAX_TARGETS, 1, (*itr)->getTarget(), TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Register() override
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_of_pain_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
return new spell_moragg_ray_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_moragg_ray_of_pain_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_moragg_optic_link : public SpellScriptLoader
|
||||
@@ -232,30 +148,15 @@ public:
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
switch (aurEff->GetTickNumber()) // Different visual based on tick
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_2, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_2, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_3, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (aurEff->GetTickNumber() >= 8)
|
||||
caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_3, TRIGGERED_FULL_MASK, nullptr, aurEff);
|
||||
|
||||
if (aurEff->GetTickNumber() >= 4)
|
||||
caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_2, TRIGGERED_FULL_MASK, nullptr, aurEff);
|
||||
|
||||
caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_1, TRIGGERED_FULL_MASK, nullptr, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +194,6 @@ public:
|
||||
void AddSC_boss_moragg()
|
||||
{
|
||||
new boss_moragg();
|
||||
new spell_moragg_ray_of_suffering();
|
||||
new spell_moragg_ray_of_pain();
|
||||
new spell_moragg_ray();
|
||||
new spell_moragg_optic_link();
|
||||
}
|
||||
@@ -22,25 +22,34 @@
|
||||
#include "Player.h"
|
||||
#include "violet_hold.h"
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Implement Ethereal Summon Target
|
||||
*/
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_ARCANE_BARRAGE_VOLLEY = 54202,
|
||||
SPELL_ARCANE_BUFFET = 54226,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_2 = 61337,
|
||||
SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138
|
||||
SPELL_SUMMON_TARGET_VISUAL = 54111
|
||||
};
|
||||
|
||||
static uint32 const EtherealSphereCount = 3;
|
||||
static uint32 const EtherealSphereSummonSpells[EtherealSphereCount] = { 54102, 54137, 54138 };
|
||||
static uint32 const EtherealSphereHeroicSummonSpells[EtherealSphereCount] = { 54102, 54137, 54138 };
|
||||
|
||||
enum NPCs
|
||||
{
|
||||
NPC_ETHEREAL_SPHERE = 29271,
|
||||
NPC_ETHEREAL_SPHERE2 = 32582
|
||||
NPC_ETHEREAL_SPHERE2 = 32582,
|
||||
NPC_ETHEREAL_SUMMON_TARGET = 29276
|
||||
};
|
||||
|
||||
enum CreatureSpells
|
||||
{
|
||||
SPELL_ARCANE_POWER = 54160,
|
||||
H_SPELL_ARCANE_POWER = 59474,
|
||||
SPELL_MAGIC_PULL = 50770,
|
||||
SPELL_SUMMON_PLAYERS = 54164,
|
||||
SPELL_POWER_BALL_VISUAL = 54141,
|
||||
SPELL_POWER_BALL_DAMAGE_TRIGGER = 54207
|
||||
@@ -48,24 +57,17 @@ enum CreatureSpells
|
||||
|
||||
enum Yells
|
||||
{
|
||||
// Xevozz
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_DEATH = 2,
|
||||
SAY_SPAWN = 3,
|
||||
SAY_CHARGED = 4,
|
||||
SAY_REPEAT_SUMMON = 5,
|
||||
SAY_SUMMON_ENERGY = 6
|
||||
};
|
||||
SAY_SUMMON_ENERGY = 6,
|
||||
|
||||
enum XevozzEvents
|
||||
{
|
||||
EVENT_ARCANE_BARRAGE = 1,
|
||||
EVENT_ARCANE_BUFFET,
|
||||
EVENT_SUMMON_SPHERE,
|
||||
EVENT_SUMMON_SPHERE_2,
|
||||
EVENT_RANGE_CHECK,
|
||||
EVENT_SUMMON_PLAYERS,
|
||||
EVENT_DESPAWN_SPHERE
|
||||
// Ethereal Sphere
|
||||
SAY_ETHEREAL_SPHERE_SUMMON = 0
|
||||
};
|
||||
|
||||
enum SphereActions
|
||||
@@ -75,319 +77,213 @@ enum SphereActions
|
||||
|
||||
class boss_xevozz : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_xevozz() : CreatureScript("boss_xevozz") { }
|
||||
public:
|
||||
boss_xevozz() : CreatureScript("boss_xevozz") { }
|
||||
|
||||
struct boss_xevozzAI : public ScriptedAI
|
||||
{
|
||||
boss_xevozzAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct boss_xevozzAI : public BossAI
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
boss_xevozzAI(Creature* creature) : BossAI(creature, DATA_XEVOZZ) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
DespawnSphere();
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void DespawnSphere()
|
||||
{
|
||||
std::list<Creature*> assistList;
|
||||
GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE, 150.0f);
|
||||
GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE2, 150.0f);
|
||||
|
||||
if (assistList.empty())
|
||||
return;
|
||||
|
||||
for (std::list<Creature*>::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter)
|
||||
void Reset() override
|
||||
{
|
||||
if (Creature* pSphere = *iter)
|
||||
pSphere->Kill(pSphere, false);
|
||||
BossAI::Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
summoned->SetSpeed(MOVE_RUN, 0.5f);
|
||||
summoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (GameObject* door = instance->GetGameObject(DATA_XEVOZZ_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
instance->SetData(DATA_HANDLE_CELLS, DATA_XEVOZZ);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
summon->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*who*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_ARCANE_POWER || spell->Id == H_SPELL_ARCANE_POWER)
|
||||
Talk(SAY_SUMMON_ENERGY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPHERE, 5000);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(8000, 10000));
|
||||
events.ScheduleEvent(EVENT_ARCANE_BUFFET, urand(10000, 11000));
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
DespawnSphere();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* who, const SpellInfo* spell) override
|
||||
{
|
||||
if (!who->ToCreature())
|
||||
return;
|
||||
|
||||
if ((spell->Id == SPELL_ARCANE_POWER) || (spell->Id == H_SPELL_ARCANE_POWER))
|
||||
Talk(SAY_SUMMON_ENERGY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ARCANE_BARRAGE:
|
||||
DoCast(SPELL_ARCANE_BARRAGE_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(8000, 10000));
|
||||
break;
|
||||
case EVENT_ARCANE_BUFFET:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_ARCANE_BUFFET);
|
||||
events.ScheduleEvent(EVENT_ARCANE_BUFFET, urand(15000, 20000));
|
||||
break;
|
||||
case EVENT_SUMMON_SPHERE:
|
||||
Talk(SAY_REPEAT_SUMMON);
|
||||
DoCast(SPELL_SUMMON_ETHEREAL_SPHERE_1);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPHERE_2, 2500);
|
||||
events.ScheduleEvent(EVENT_SUMMON_PLAYERS, urand(33000, 35000));
|
||||
events.ScheduleEvent(EVENT_SUMMON_SPHERE, urand(45000, 47000));
|
||||
break;
|
||||
case EVENT_SUMMON_SPHERE_2:
|
||||
Talk(SAY_REPEAT_SUMMON);
|
||||
DoCast(SPELL_SUMMON_ETHEREAL_SPHERE_2);
|
||||
break;
|
||||
case EVENT_SUMMON_PLAYERS:
|
||||
scheduler.Schedule(Seconds(8), Seconds(10), [this](TaskContext task)
|
||||
{
|
||||
Creature* sphere = me->FindNearestCreature(NPC_ETHEREAL_SPHERE, 150.0f);
|
||||
if (!sphere)
|
||||
sphere = me->FindNearestCreature(NPC_ETHEREAL_SPHERE2, 150.0f);
|
||||
if (sphere)
|
||||
sphere->GetAI()->DoAction(ACTION_SUMMON);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
DoCastAOE(SPELL_ARCANE_BARRAGE_VOLLEY);
|
||||
task.Repeat(Seconds(8), Seconds(10));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(10), Seconds(11), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
|
||||
DoCast(target, SPELL_ARCANE_BUFFET);
|
||||
task.Repeat(Seconds(15), Seconds(20));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(5), [this](TaskContext task)
|
||||
{
|
||||
Talk(SAY_REPEAT_SUMMON);
|
||||
|
||||
std::list<uint8> summonSpells = { 0, 1, 2 };
|
||||
|
||||
auto it = summonSpells.begin();
|
||||
std::advance(it, urand(0, summonSpells.size() - 1));
|
||||
DoCast(me, EtherealSphereSummonSpells[*it]);
|
||||
it = summonSpells.erase(it);
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
task.Schedule(Milliseconds(2500), [this, &it, &summonSpells](TaskContext /*task*/)
|
||||
{
|
||||
it = summonSpells.begin();
|
||||
std::advance(it, urand(0, summonSpells.size() - 1));
|
||||
DoCast(me, EtherealSphereHeroicSummonSpells[*it]);
|
||||
it = summonSpells.erase(it);
|
||||
});
|
||||
}
|
||||
|
||||
task.Schedule(Seconds(33), Seconds(35), [this](TaskContext /*task*/)
|
||||
{
|
||||
DummyEntryCheckPredicate pred;
|
||||
summons.DoAction(ACTION_SUMMON, pred);
|
||||
});
|
||||
|
||||
task.Repeat(Seconds(45), Seconds(47));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVioletHoldAI<boss_xevozzAI>(creature);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_xevozzAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_ethereal_sphere : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { }
|
||||
public:
|
||||
npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { }
|
||||
|
||||
struct npc_ethereal_sphereAI : public ScriptedAI
|
||||
{
|
||||
npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature)
|
||||
struct npc_ethereal_sphereAI : public ScriptedAI
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
arcanePower = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
events.Reset();
|
||||
DoCast(SPELL_POWER_BALL_VISUAL);
|
||||
DoCast(SPELL_POWER_BALL_DAMAGE_TRIGGER);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->setFaction(16);
|
||||
events.ScheduleEvent(EVENT_DESPAWN_SPHERE, 40000);
|
||||
events.ScheduleEvent(EVENT_RANGE_CHECK, 1000);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_SUMMON)
|
||||
DoCast(SPELL_SUMMON_PLAYERS);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
case EVENT_RANGE_CHECK:
|
||||
if (Creature* xevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ)))
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
scheduler.CancelAll();
|
||||
ScheduledTasks();
|
||||
|
||||
DoCast(me, SPELL_POWER_BALL_VISUAL);
|
||||
DoCast(me, SPELL_POWER_BALL_DAMAGE_TRIGGER);
|
||||
|
||||
me->DespawnOrUnsummon(40000);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_SUMMON)
|
||||
{
|
||||
Talk(SAY_ETHEREAL_SPHERE_SUMMON);
|
||||
DoCastAOE(SPELL_SUMMON_PLAYERS);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void ScheduledTasks()
|
||||
{
|
||||
scheduler.Schedule(Seconds(1), [this](TaskContext task)
|
||||
{
|
||||
if (Creature* xevozz = instance->GetCreature(DATA_XEVOZZ))
|
||||
{
|
||||
if (me->IsWithinDist(xevozz, 3.0f) && !arcanePower)
|
||||
if (me->IsWithinDist(xevozz, 3.0f))
|
||||
{
|
||||
DoCast(SPELL_ARCANE_POWER);
|
||||
arcanePower = true;
|
||||
events.ScheduleEvent(EVENT_DESPAWN_SPHERE, 8000);
|
||||
DoCastAOE(SPELL_ARCANE_POWER);
|
||||
me->DespawnOrUnsummon(8000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RANGE_CHECK, 1000);
|
||||
break;
|
||||
case EVENT_DESPAWN_SPHERE:
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
TaskScheduler scheduler;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVioletHoldAI<npc_ethereal_sphereAI>(creature);
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
bool arcanePower;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_ethereal_sphereAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_xevozz_summon_players : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_xevozz_summon_players() : SpellScriptLoader("spell_xevozz_summon_players") { }
|
||||
public:
|
||||
spell_xevozz_summon_players() : SpellScriptLoader("spell_xevozz_summon_players") { }
|
||||
|
||||
class spell_xevozz_summon_players_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_xevozz_summon_players_SpellScript);
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
class spell_xevozz_summon_players_SpellScript : public SpellScript
|
||||
{
|
||||
Unit* target = GetHitUnit();
|
||||
PrepareSpellScript(spell_xevozz_summon_players_SpellScript);
|
||||
|
||||
if (target)
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
Position pos = GetOriginalCaster()->GetPosition();
|
||||
|
||||
target->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_xevozz_summon_players_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_xevozz_summon_players_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_xevozz_summon_ethereal_sphere : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_xevozz_summon_ethereal_sphere() : SpellScriptLoader("spell_xevozz_summon_ethereal_sphere") { }
|
||||
|
||||
class spell_xevozz_summon_ethereal_sphere_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_xevozz_summon_ethereal_sphere_SpellScript);
|
||||
|
||||
void HandleScript(SpellDestination& target)
|
||||
{
|
||||
Unit* caster = GetOriginalCaster();
|
||||
Position pos;
|
||||
float distance = 0.0f;
|
||||
|
||||
while (distance < 20.0f)
|
||||
{
|
||||
pos = caster->GetRandomNearPosition(60.0f);
|
||||
distance = caster->GetDistance(pos);
|
||||
if (!sSpellMgr->GetSpellInfo(SPELL_MAGIC_PULL))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
target.Relocate(pos);
|
||||
}
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_MAGIC_PULL, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_xevozz_summon_players_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_xevozz_summon_ethereal_sphere_SpellScript::HandleScript, EFFECT_0, TARGET_DEST_DB);
|
||||
return new spell_xevozz_summon_players_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_xevozz_summon_ethereal_sphere_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_xevozz()
|
||||
@@ -395,5 +291,4 @@ void AddSC_boss_xevozz()
|
||||
new boss_xevozz();
|
||||
new npc_ethereal_sphere();
|
||||
new spell_xevozz_summon_players();
|
||||
new spell_xevozz_summon_ethereal_sphere();
|
||||
}
|
||||
@@ -25,6 +25,10 @@ enum Spells
|
||||
SPELL_SUMMON_VOID_SENTRY = 54369,
|
||||
SPELL_VOID_SHIFT = 54361,
|
||||
SPELL_VOID_SHIFTED = 54343,
|
||||
SPELL_ZURAMAT_ADD = 54341,
|
||||
SPELL_ZURAMAT_ADD_2 = 54342,
|
||||
SPELL_ZURAMAT_ADD_DUMMY = 54351,
|
||||
SPELL_SUMMON_VOID_SENTRY_BALL = 58650
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -39,188 +43,172 @@ enum Yells
|
||||
|
||||
enum Misc
|
||||
{
|
||||
ACTION_DESPAWN_VOID_SENTRY_BALL = 1,
|
||||
DATA_VOID_DANCE = 2153
|
||||
};
|
||||
|
||||
enum ZuramatEvents
|
||||
{
|
||||
EVENT_VOID_SHIFT = 1,
|
||||
EVENT_SUMMON_VOID,
|
||||
EVENT_SHROUD_OF_DARKNESS
|
||||
};
|
||||
|
||||
class boss_zuramat : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_zuramat() : CreatureScript("boss_zuramat") { }
|
||||
public:
|
||||
boss_zuramat() : CreatureScript("boss_zuramat") { }
|
||||
|
||||
struct boss_zuramatAI : public ScriptedAI
|
||||
{
|
||||
boss_zuramatAI(Creature* creature) : ScriptedAI(creature), sentries(me)
|
||||
struct boss_zuramatAI : public BossAI
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
voidDance = true;
|
||||
}
|
||||
|
||||
void DespawnSentries()
|
||||
{
|
||||
sentries.DespawnAll();
|
||||
std::list<Creature*> sentrylist;
|
||||
GetCreatureListWithEntryInGrid(sentrylist, me, NPC_VOID_SENTRY_BALL, 200.0f);
|
||||
if (!sentrylist.empty())
|
||||
for (std::list<Creature*>::const_iterator itr = sentrylist.begin(); itr != sentrylist.end(); ++itr)
|
||||
(*itr)->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
|
||||
|
||||
Initialize();
|
||||
events.Reset();
|
||||
DespawnSentries();
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
boss_zuramatAI(Creature* creature) : BossAI(creature, DATA_ZURAMAT)
|
||||
{
|
||||
me->AddThreat(who, 0.0f);
|
||||
me->SetInCombatWith(who);
|
||||
who->SetInCombatWith(me);
|
||||
DoStartMovement(who);
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
if (GameObject* door = instance->GetGameObject(DATA_ZURAMAT_CELL))
|
||||
if (door->GetGoState() == GO_STATE_READY)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
void Initialize()
|
||||
{
|
||||
_voidDance = true;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
instance->SetData(DATA_HANDLE_CELLS, DATA_ZURAMAT);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*who*/) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_VOID_SENTRY)
|
||||
_voidDance = false;
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_VOID_SENTRY)
|
||||
summon->AI()->DoAction(ACTION_DESPAWN_VOID_SENTRY_BALL);
|
||||
BossAI::SummonedCreatureDespawn(summon);
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_VOID_DANCE)
|
||||
return _voidDance ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
|
||||
|
||||
me->SetInCombatWithZone();
|
||||
events.ScheduleEvent(EVENT_SHROUD_OF_DARKNESS, urand(18000, 20000));
|
||||
events.ScheduleEvent(EVENT_VOID_SHIFT, 9000);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VOID, 4000);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
sentries.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summoned, Unit* /*who*/) override
|
||||
{
|
||||
if (summoned->GetEntry() == NPC_VOID_SENTRY)
|
||||
voidDance = false;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_VOID_DANCE)
|
||||
return voidDance ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetData(DATA_ZURAMAT, 1);
|
||||
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
DespawnSentries();
|
||||
|
||||
if (instance->GetData(DATA_WAVE_COUNT) == 6)
|
||||
{
|
||||
instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 7);
|
||||
}
|
||||
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
|
||||
{
|
||||
instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
|
||||
instance->SetData(DATA_WAVE_COUNT, 13);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SUMMON_VOID:
|
||||
DoCast(SPELL_SUMMON_VOID_SENTRY);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VOID, urand(7000, 10000));
|
||||
break;
|
||||
case EVENT_VOID_SHIFT:
|
||||
if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(unit, SPELL_VOID_SHIFT);
|
||||
events.ScheduleEvent(EVENT_VOID_SHIFT, 15000);
|
||||
break;
|
||||
case EVENT_SHROUD_OF_DARKNESS:
|
||||
DoCast(SPELL_SHROUD_OF_DARKNESS);
|
||||
events.ScheduleEvent(EVENT_SHROUD_OF_DARKNESS, urand(18000, 20000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
scheduler.Update(diff,
|
||||
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
void ScheduleTasks() override
|
||||
{
|
||||
scheduler.Schedule(Seconds(4), [this](TaskContext task)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_VOID_SENTRY);
|
||||
task.Repeat(Seconds(7), Seconds(10));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(9), [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true))
|
||||
DoCast(target, SPELL_VOID_SHIFT);
|
||||
task.Repeat(Seconds(15));
|
||||
});
|
||||
|
||||
scheduler.Schedule(Seconds(18), Seconds(20), [this](TaskContext task)
|
||||
{
|
||||
DoCast(me, SPELL_SHROUD_OF_DARKNESS);
|
||||
task.Repeat(Seconds(18), Seconds(20));
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
bool _voidDance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVioletHoldAI<boss_zuramatAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
SummonList sentries;
|
||||
bool voidDance;
|
||||
};
|
||||
class npc_void_sentry : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_void_sentry() : CreatureScript("npc_void_sentry") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<boss_zuramatAI>(creature);
|
||||
}
|
||||
struct npc_void_sentryAI : public ScriptedAI
|
||||
{
|
||||
npc_void_sentryAI(Creature* creature) : ScriptedAI(creature), _summons(creature)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void IsSummonedBy(Unit* /*summoner*/) override
|
||||
{
|
||||
me->CastSpell(me, SPELL_SUMMON_VOID_SENTRY_BALL, true);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
_summons.Summon(summon);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
_summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void DoAction(int32 actionId) override
|
||||
{
|
||||
if (actionId == ACTION_DESPAWN_VOID_SENTRY_BALL)
|
||||
_summons.DespawnAll();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
DoAction(ACTION_DESPAWN_VOID_SENTRY_BALL);
|
||||
}
|
||||
|
||||
private:
|
||||
SummonList _summons;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetVioletHoldAI<npc_void_sentryAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class achievement_void_dance : public AchievementCriteriaScript
|
||||
{
|
||||
public:
|
||||
achievement_void_dance() : AchievementCriteriaScript("achievement_void_dance")
|
||||
{
|
||||
}
|
||||
achievement_void_dance() : AchievementCriteriaScript("achievement_void_dance") { }
|
||||
|
||||
bool OnCheck(Player* /*player*/, Unit* target) override
|
||||
{
|
||||
@@ -238,5 +226,6 @@ class achievement_void_dance : public AchievementCriteriaScript
|
||||
void AddSC_boss_zuramat()
|
||||
{
|
||||
new boss_zuramat();
|
||||
new npc_void_sentry();
|
||||
new achievement_void_dance();
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -15,44 +15,56 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DEF_VIOLET_HOLD_H
|
||||
#define DEF_VIOLET_HOLD_H
|
||||
#ifndef VIOLET_HOLD_H_
|
||||
#define VIOLET_HOLD_H_
|
||||
|
||||
#define VioletHoldScriptName "instance_violet_hold"
|
||||
#define DataHeader "VH"
|
||||
|
||||
uint32 const EncounterCount = 3;
|
||||
uint32 const EncounterCount = 3 + 6;
|
||||
|
||||
// Defined in instance_violet_hold.cpp
|
||||
extern Position const DefenseSystemLocation;
|
||||
uint8 const PortalIntroCount = 3;
|
||||
extern Position const PortalIntroPositions[];
|
||||
|
||||
/*
|
||||
* Violet hold bosses:
|
||||
*
|
||||
* 1 - Moragg
|
||||
* 2 - Erekem
|
||||
* 3 - Ichoron
|
||||
* 4 - Lavanthor
|
||||
* 5 - Xevozz
|
||||
* 6 - Zuramat
|
||||
* 7 - Cyanigosa
|
||||
*/
|
||||
|
||||
enum Data
|
||||
{
|
||||
// Main encounters
|
||||
DATA_1ST_BOSS_EVENT,
|
||||
DATA_2ND_BOSS_EVENT,
|
||||
DATA_CYANIGOSA,
|
||||
DATA_1ST_BOSS = 0,
|
||||
DATA_2ND_BOSS = 1,
|
||||
DATA_CYANIGOSA = 2,
|
||||
// Bosses
|
||||
DATA_MORAGG = 3,
|
||||
DATA_EREKEM = 4,
|
||||
DATA_ICHORON = 5,
|
||||
DATA_LAVANTHOR = 6,
|
||||
DATA_XEVOZZ = 7,
|
||||
DATA_ZURAMAT = 8,
|
||||
|
||||
// Misc
|
||||
DATA_MAIN_EVENT_STATE,
|
||||
DATA_WAVE_COUNT,
|
||||
DATA_REMOVE_NPC,
|
||||
DATA_PORTAL_LOCATION,
|
||||
DATA_DOOR_INTEGRITY,
|
||||
DATA_NPC_PRESENCE_AT_DOOR,
|
||||
DATA_NPC_PRESENCE_AT_DOOR_ADD,
|
||||
DATA_NPC_PRESENCE_AT_DOOR_REMOVE,
|
||||
DATA_PORTAL_LOCATION,
|
||||
DATA_START_BOSS_ENCOUNTER,
|
||||
DATA_FIRST_BOSS,
|
||||
DATA_SECOND_BOSS,
|
||||
DATA_ACTIVATE_CRYSTAL,
|
||||
DATA_MAIN_EVENT_PHASE,
|
||||
DATA_DEFENSELESS,
|
||||
|
||||
// Bosses
|
||||
DATA_MORAGG,
|
||||
DATA_EREKEM,
|
||||
DATA_EREKEM_GUARD_1,
|
||||
DATA_EREKEM_GUARD_2,
|
||||
DATA_ICHORON,
|
||||
DATA_LAVANTHOR,
|
||||
DATA_XEVOZZ,
|
||||
DATA_ZURAMAT,
|
||||
|
||||
// Cells
|
||||
DATA_MORAGG_CELL,
|
||||
@@ -67,43 +79,43 @@ enum Data
|
||||
// Misc
|
||||
DATA_MAIN_DOOR,
|
||||
DATA_SINCLARI,
|
||||
DATA_TELEPORTATION_PORTAL,
|
||||
DATA_SABOTEUR_PORTAL,
|
||||
DATA_ADD_TRASH_MOB,
|
||||
DATA_DEL_TRASH_MOB
|
||||
};
|
||||
|
||||
enum Bosses
|
||||
{
|
||||
BOSS_NONE, // 0 used as marker for not yet randomized
|
||||
BOSS_MORAGG,
|
||||
BOSS_EREKEM,
|
||||
BOSS_ICHORON,
|
||||
BOSS_LAVANTHOR,
|
||||
BOSS_XEVOZZ,
|
||||
BOSS_ZURAMAT,
|
||||
BOSS_CYANIGOSA
|
||||
DATA_SINCLARI_TRIGGER,
|
||||
DATA_HANDLE_CELLS
|
||||
};
|
||||
|
||||
enum CreaturesIds
|
||||
{
|
||||
NPC_TELEPORTATION_PORTAL = 31011,
|
||||
NPC_TELEPORTATION_PORTAL = 30679,
|
||||
NPC_TELEPORTATION_PORTAL_ELITE = 32174,
|
||||
NPC_TELEPORTATION_PORTAL_INTRO = 31011,
|
||||
NPC_PORTAL_GUARDIAN = 30660,
|
||||
NPC_PORTAL_KEEPER = 30695,
|
||||
NPC_XEVOZZ = 29266,
|
||||
NPC_LAVANTHOR = 29312,
|
||||
NPC_ICHORON = 29313,
|
||||
NPC_ICHOR_GLOBULE = 29321,
|
||||
NPC_ICHORON_SUMMON_TARGET = 29326,
|
||||
NPC_ZURAMAT = 29314,
|
||||
NPC_VOID_SENTRY = 29364,
|
||||
NPC_VOID_SENTRY_BALL = 29365,
|
||||
NPC_EREKEM = 29315,
|
||||
NPC_EREKEM_GUARD = 29395,
|
||||
NPC_MORAGG = 29316,
|
||||
|
||||
NPC_DUMMY_XEVOZZ = 32231,
|
||||
NPC_DUMMY_LAVANTHOR = 32237,
|
||||
NPC_DUMMY_ICHORON = 32234,
|
||||
NPC_DUMMY_ZURAMAT = 32230,
|
||||
NPC_DUMMY_EREKEM = 32226,
|
||||
NPC_DUMMY_EREKEM_GUARD = 32228,
|
||||
NPC_DUMMY_MORAGG = 32235,
|
||||
|
||||
NPC_CYANIGOSA = 31134,
|
||||
NPC_SINCLARI = 30658,
|
||||
NPC_SINCLARI_TRIGGER = 32204,
|
||||
NPC_SABOTEOUR = 31079,
|
||||
NPC_VIOLET_HOLD_GUARD = 30659,
|
||||
NPC_DEFENSE_SYSTEM = 30837,
|
||||
NPC_VOID_SENTRY = 29364,
|
||||
NPC_VOID_SENTRY_BALL = 29365
|
||||
NPC_DEFENSE_SYSTEM = 30837
|
||||
};
|
||||
|
||||
enum GameObjectIds
|
||||
@@ -117,13 +129,13 @@ enum GameObjectIds
|
||||
GO_EREKEM_GUARD_1_DOOR = 191563,
|
||||
GO_EREKEM_GUARD_2_DOOR = 191562,
|
||||
GO_MORAGG_DOOR = 191606,
|
||||
GO_INTRO_ACTIVATION_CRYSTAL = 193615,
|
||||
GO_ACTIVATION_CRYSTAL = 193611
|
||||
GO_ACTIVATION_CRYSTAL = 193611,
|
||||
GO_INTRO_ACTIVATION_CRYSTAL = 193615
|
||||
};
|
||||
|
||||
enum WorldStateIds
|
||||
{
|
||||
WORLD_STATE_VH = 3816,
|
||||
WORLD_STATE_VH_SHOW = 3816,
|
||||
WORLD_STATE_VH_PRISON_STATE = 3815,
|
||||
WORLD_STATE_VH_WAVE_COUNT = 3810,
|
||||
};
|
||||
@@ -133,4 +145,16 @@ enum Events
|
||||
EVENT_ACTIVATE_CRYSTAL = 20001
|
||||
};
|
||||
|
||||
#endif
|
||||
enum InstanceMisc
|
||||
{
|
||||
ACTION_SINCLARI_OUTRO = 1,
|
||||
POINT_INTRO = 1
|
||||
};
|
||||
|
||||
template<class AI>
|
||||
inline AI* GetVioletHoldAI(Creature* creature)
|
||||
{
|
||||
return GetInstanceAI<AI>(creature, VioletHoldScriptName);
|
||||
}
|
||||
|
||||
#endif // VIOLET_HOLD_H_
|
||||
@@ -1819,7 +1819,7 @@ public:
|
||||
player->FailQuest(QUEST_GET_ME_OUTA_HERE);
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 /*diff*/) override
|
||||
void UpdateEscortAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (GetAttack() && UpdateVictim())
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
player->FailQuest(QUEST_TRAIL_OF_FIRE);
|
||||
}
|
||||
|
||||
void UpdateEscortAI(const uint32 diff) override
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (HealthBelowPct(75))
|
||||
{
|
||||
|
||||
@@ -136,7 +136,7 @@ class boss_ambassador_hellmaw : public CreatureScript
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 const diff) override
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user