mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 20:54:15 +08:00
Merge b33b932b664fe2e2944d7e94608ad857290eae5e into 5bef92d5eaca3e2ecc317f9d599312bc23eb71aa
This commit is contained in:
commit
2b3520ffcc
@ -0,0 +1,74 @@
|
|||||||
|
--
|
||||||
|
-- HARD_RESET
|
||||||
|
UPDATE `creature_template` SET `flags_extra` = `flags_extra` | 2147483648 WHERE (`entry` IN (28921, 31611));
|
||||||
|
|
||||||
|
DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (53406, 53317, 53394, 53330, 53322);
|
||||||
|
INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`, `DifficultySpellID_3`, `DifficultySpellID_4`) VALUES
|
||||||
|
(53406, 53406, 59420, 0, 0),
|
||||||
|
(53317, 53317, 59343, 0, 0),
|
||||||
|
(53394, 53394, 59344, 0, 0),
|
||||||
|
(53330, 53330, 59348, 0, 0),
|
||||||
|
(53322, 53322, 59347, 0, 0);
|
||||||
|
|
||||||
|
DELETE FROM `spell_script_names` WHERE `spell_id` IN (53406, 59420) AND `ScriptName` = 'spell_hadronox_web_grab';
|
||||||
|
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||||
|
(53406, 'spell_hadronox_web_grab'),
|
||||||
|
(59420, 'spell_hadronox_web_grab');
|
||||||
|
|
||||||
|
DELETE FROM `creature_summon_groups` WHERE `summonerId` = 28921;
|
||||||
|
INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`, `Comment`) VALUES
|
||||||
|
(28921, 0, 1, 28922, 529.691, 547.126, 731.916, 4.79965, 6, 45000, 'Hadronox - Group 1 - Anub''ar Crusher'),
|
||||||
|
(28921, 0, 1, 29117, 539.208, 549.754, 732.867, 4.55531, 6, 30000, 'Hadronox - Group 1 - Anub''ar Champion'),
|
||||||
|
(28921, 0, 1, 29118, 520.391, 548.789, 732.012, 5.0091, 6, 30000, 'Hadronox - Group 1 - Anub''ar Crypt Fiend'),
|
||||||
|
(28921, 0, 2, 28922, 493.477, 603.344, 760.563, 5.44024, 6, 45000, 'Hadronox - Group 2 - Anub''ar Crusher'),
|
||||||
|
(28921, 0, 2, 29117, 490.442, 604.335, 763.182, 5.6256, 6, 30000, 'Hadronox - Group 2 - Anub''ar Champion'),
|
||||||
|
(28921, 0, 2, 29119, 488.825, 609.282, 767.588, 5.59029, 6, 30000, 'Hadronox - Group 2 - Anub''ar Necromancer'),
|
||||||
|
(28921, 0, 3, 28922, 566.979, 602.571, 759.642, 3.88597, 6, 45000, 'Hadronox - Group 3 - Anub''ar Crusher'),
|
||||||
|
(28921, 0, 3, 29118, 569.348, 604.999, 763.214, 4.17983, 6, 30000, 'Hadronox - Group 3 - Anub''ar Crypt Fiend'),
|
||||||
|
(28921, 0, 3, 29119, 572.474, 607.411, 767.178, 3.94417, 6, 30000, 'Hadronox - Group 3 - Anub''ar Necromancer'),
|
||||||
|
(28921, 0, 4, 23472, 581.448, 608.841, 739.405, 1.72788, 6, 3600000, 'Hadronox - Group 4 - World Trigger'),
|
||||||
|
(28921, 0, 4, 23472, 477.016, 618.4, 771.515, 2.35619, 6, 3600000, 'Hadronox - Group 4 - World Trigger'),
|
||||||
|
(28921, 0, 4, 23472, 583.091, 617.371, 771.551, 0.645772, 6, 3600000, 'Hadronox - Group 4 - World Trigger');
|
||||||
|
|
||||||
|
DELETE FROM `creature` WHERE (`id1` = 23472) AND (`guid` IN (127376, 127377, 127378));
|
||||||
|
DELETE FROM `creature_addon` WHERE (`guid` IN (127376, 127377, 127378));
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 0) AND (`entryorguid` IN (29117, 29118, 29119));
|
||||||
|
UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_anub_ar_crusher_champion' WHERE (`entry` = 29117);
|
||||||
|
UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_anub_ar_crusher_crypt_fiend' WHERE (`entry` = 29118);
|
||||||
|
UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_anub_ar_crusher_necromancer' WHERE (`entry` = 29119);
|
||||||
|
|
||||||
|
SET @SPAWN_X := 522.53107;
|
||||||
|
SET @SPAWN_Y := 544.91125;
|
||||||
|
SET @SPAWN_Z := 674.6791;
|
||||||
|
SET @SPAWN_O := 5.633617;
|
||||||
|
DELETE FROM `creature` WHERE (`id1` = 28921) AND (`guid` = 127401);
|
||||||
|
INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `Comment`, `VerifiedBuild`) VALUES
|
||||||
|
(127401, 28921, 0, 0, 601, 0, 0, 3, 1, 0, @SPAWN_X, @SPAWN_Y, @SPAWN_Z, @SPAWN_O, 86400, 0, 0, 154230, 0, 0, 0, 0, 0, '', NULL, 0);
|
||||||
|
|
||||||
|
DELETE FROM `waypoint_data` WHERE `id` IN (3000012, 3000013) AND `point` IN (13, 14);
|
||||||
|
DELETE FROM `waypoint_data` WHERE `id` = 3000014 AND `point` IN (9, 10);
|
||||||
|
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||||
|
(3000012, 13, 538.0253, 529.9829, 686.0557, 0, 1, 0, 100, 0),
|
||||||
|
(3000012, 14, 532.7753, 535.2329, 681.0557, 0, 1, 0, 100, 0),
|
||||||
|
(3000013, 13, 538.0253, 529.9829, 686.0557, 0, 1, 0, 100, 0),
|
||||||
|
(3000013, 14, 532.7753, 535.2329, 681.0557, 0, 1, 0, 100, 0),
|
||||||
|
(3000014, 9, 538.0253, 529.9829, 686.0557, 0, 1, 0, 100, 0),
|
||||||
|
(3000014, 10, 532.7753, 535.2329, 681.0557, 0, 1, 0, 100, 0);
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` IN (29062, 29063, 29064));
|
||||||
|
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||||
|
(29062, 0, 0, 0, 0, 0, 100, 0, 4000, 7000, 12000, 18000, 0, 0, 11, 53317, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Champion - In Combat - Cast \'Rend\''),
|
||||||
|
(29062, 0, 1, 0, 105, 0, 100, 0, 9000, 13000, 9000, 13000, 0, 5, 11, 53394, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Champion - On Hostile Casting in Range - Cast \'Pummel\''),
|
||||||
|
(29062, 0, 2, 0, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Champion - On Just Died - Despawn In 10000 ms'),
|
||||||
|
(29062, 0, 3, 0, 1, 0, 100, 0, 10000, 10000, 1000, 1000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 11, 28921, 50, 1, 0, 0, 0, 0, 0, 'Anub\'ar Champion Out of Combat - Start Attacking'),
|
||||||
|
(29062, 0, 4, 0, 0, 0, 100, 0, 15000, 50000, 15000, 50000, 0, 0, 11, 53798, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Champion - In Combat - Cast \'Taunt\''),
|
||||||
|
(29063, 0, 0, 0, 0, 0, 100, 0, 4000, 7000, 9000, 12000, 0, 0, 11, 53330, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Crypt Fiend - In Combat - Cast \'Infected Wound\''),
|
||||||
|
(29063, 0, 1, 0, 0, 0, 100, 0, 9000, 12000, 13000, 17000, 0, 0, 11, 53322, 0, 0, 0, 0, 0, 5, 30, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Crypt Fiend - In Combat - Cast \'Crushing Webs\''),
|
||||||
|
(29063, 0, 2, 0, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Crypt Fiend - On Just Died - Despawn In 10000 ms'),
|
||||||
|
(29063, 0, 3, 0, 1, 0, 100, 0, 10000, 10000, 1000, 1000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 11, 28921, 50, 1, 0, 0, 0, 0, 0, 'Anub\'ar Crypt Fiend - Out of Combat - Start Attacking'),
|
||||||
|
(29063, 0, 4, 0, 0, 0, 100, 0, 15000, 50000, 15000, 50000, 0, 0, 11, 53798, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Crypt Fiend - In Combat - Cast \'Taunt\''),
|
||||||
|
(29064, 0, 0, 0, 1, 0, 100, 0, 0, 1000, 2000, 3000, 0, 0, 11, 53333, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Necromancer - Out of Combat - Cast \'Shadow Bolt\''),
|
||||||
|
(29064, 0, 2, 0, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Necromancer - On Just Died - Despawn In 10000 ms'),
|
||||||
|
(29064, 0, 3, 0, 1, 0, 100, 0, 10000, 10000, 1000, 1000, 0, 0, 49, 0, 0, 0, 0, 0, 0, 11, 28921, 50, 1, 0, 0, 0, 0, 0, 'Anub\'ar Necromancer Out of Combat - Start Attacking'),
|
||||||
|
(29064, 0, 4, 0, 0, 0, 100, 0, 15000, 50000, 15000, 50000, 0, 0, 11, 53798, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Necromancer - In Combat - Cast \'Taunt\'');
|
||||||
@ -43,6 +43,7 @@ enum ANIds
|
|||||||
NPC_HADRONOX = 28921,
|
NPC_HADRONOX = 28921,
|
||||||
NPC_ANUBARAK = 29120,
|
NPC_ANUBARAK = 29120,
|
||||||
|
|
||||||
|
NPC_WORLD_TRIGGER_LAOI = 23472,
|
||||||
NPC_ANUB_AR_CHAMPION = 29062,
|
NPC_ANUB_AR_CHAMPION = 29062,
|
||||||
NPC_ANUB_AR_NECROMANCER = 29063,
|
NPC_ANUB_AR_NECROMANCER = 29063,
|
||||||
NPC_ANUB_AR_CRYPTFIEND = 29064,
|
NPC_ANUB_AR_CRYPTFIEND = 29064,
|
||||||
|
|||||||
@ -75,7 +75,6 @@ enum Events
|
|||||||
|
|
||||||
enum CreatureIds
|
enum CreatureIds
|
||||||
{
|
{
|
||||||
NPC_WORLD_TRIGGER = 22515,
|
|
||||||
NPC_ANUBAR_GUARDIAN = 29216,
|
NPC_ANUBAR_GUARDIAN = 29216,
|
||||||
NPC_ANUBAR_VENOMANCER = 29217,
|
NPC_ANUBAR_VENOMANCER = 29217,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,19 +26,39 @@
|
|||||||
|
|
||||||
enum Spells
|
enum Spells
|
||||||
{
|
{
|
||||||
|
// World Trigger
|
||||||
SPELL_SUMMON_ANUBAR_CHAMPION = 53064,
|
SPELL_SUMMON_ANUBAR_CHAMPION = 53064,
|
||||||
SPELL_SUMMON_ANUBAR_CRYPT_FIEND = 53065,
|
SPELL_SUMMON_ANUBAR_CRYPT_FIEND = 53065,
|
||||||
SPELL_SUMMON_ANUBAR_NECROMANCER = 53066,
|
SPELL_SUMMON_ANUBAR_NECROMANCER = 53066,
|
||||||
|
SPELL_SUMMON_ANUBAR_CHAMPION_PERIODIC = 53035,
|
||||||
|
SPELL_SUMMON_ANUBAR_NECROMANCER_PERIODIC = 53036,
|
||||||
|
SPELL_SUMMON_ANUBAR_CRYPT_FIEND_PERIODIC = 53037,
|
||||||
|
|
||||||
|
// Hadronox
|
||||||
SPELL_WEB_FRONT_DOORS = 53177,
|
SPELL_WEB_FRONT_DOORS = 53177,
|
||||||
SPELL_WEB_SIDE_DOORS = 53185,
|
SPELL_WEB_SIDE_DOORS = 53185,
|
||||||
SPELL_ACID_CLOUD = 53400,
|
SPELL_ACID_CLOUD = 53400,
|
||||||
SPELL_LEECH_POISON = 53030,
|
SPELL_LEECH_POISON = 53030,
|
||||||
SPELL_LEECH_POISON_HEAL = 53800,
|
SPELL_LEECH_POISON_HEAL = 53800,
|
||||||
SPELL_WEB_GRAB = 57731,
|
SPELL_WEB_GRAB = 53406,
|
||||||
SPELL_PIERCE_ARMOR = 53418,
|
SPELL_PIERCE_ARMOR = 53418,
|
||||||
|
|
||||||
|
// Anub'ar Crusher
|
||||||
SPELL_SMASH = 53318,
|
SPELL_SMASH = 53318,
|
||||||
SPELL_FRENZY = 53801
|
SPELL_FRENZY = 53801,
|
||||||
|
|
||||||
|
// Anub'ar Champion
|
||||||
|
SPELL_REND = 59343,
|
||||||
|
SPELL_PUMMEL = 59344,
|
||||||
|
|
||||||
|
// Anub'ar Crypt Guard
|
||||||
|
SPELL_CRUSHING_WEBS = 59347,
|
||||||
|
SPELL_INFECTED_WOUND = 59348,
|
||||||
|
|
||||||
|
// Anub'ar Necromancer
|
||||||
|
SPELL_SHADOW_BOLT = 53333,
|
||||||
|
SPELL_ANIMATE_BONES_1 = 53334,
|
||||||
|
SPELL_ANIMATE_BONES_2 = 53336,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Events
|
enum Events
|
||||||
@ -54,274 +74,533 @@ enum Events
|
|||||||
EVENT_HADRONOX_SUMMON = 9,
|
EVENT_HADRONOX_SUMMON = 9,
|
||||||
|
|
||||||
EVENT_CRUSHER_SMASH = 20,
|
EVENT_CRUSHER_SMASH = 20,
|
||||||
EVENT_CHECK_HEALTH = 21
|
EVENT_CHECK_HEALTH = 21,
|
||||||
|
EVENT_CHECK_EVADE = 22,
|
||||||
|
|
||||||
|
// Anub'ar Champion
|
||||||
|
EVENT_REND,
|
||||||
|
EVENT_PUMMEL,
|
||||||
|
|
||||||
|
// Anub'ar Crypt Guard
|
||||||
|
EVENT_CRUSHING_WEBS,
|
||||||
|
EVENT_INFECTED_WOUND,
|
||||||
|
|
||||||
|
// Anub'ar Necromancer
|
||||||
|
EVENT_SHADOW_BOLT,
|
||||||
|
EVENT_ANIMATE_BONES
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NPCs
|
||||||
|
{
|
||||||
|
NPC_ANUB_AR_CRUSHER = 28922,
|
||||||
|
NPC_ANUB_AR_CHAMPION_PACK = 29117,
|
||||||
|
NPC_ANUB_AR_CRYPT_FIEND_PACK = 29118,
|
||||||
|
NPC_ANUB_AR_NECROMANCER_PACK = 29119,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SummonGroups : uint32
|
||||||
|
{
|
||||||
|
SUMMON_GROUP_CRUSHER_NONE = 0,
|
||||||
|
SUMMON_GROUP_CRUSHER_1 = 1,
|
||||||
|
SUMMON_GROUP_CRUSHER_2 = 2,
|
||||||
|
SUMMON_GROUP_CRUSHER_3 = 3,
|
||||||
|
SUMMON_GROUP_WORLD_TRIGGERS = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Data
|
||||||
|
{
|
||||||
|
DATA_CRUSHER_PACK_ID = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Misc
|
enum Misc
|
||||||
{
|
{
|
||||||
NPC_ANUB_AR_CRUSHER = 28922,
|
SAY_CRUSHER_AGGRO = 1,
|
||||||
|
SAY_CRUSHER_EMOTE = 2,
|
||||||
SAY_CRUSHER_AGGRO = 0,
|
|
||||||
SAY_CRUSHER_EMOTE = 1,
|
|
||||||
SAY_HADRONOX_EMOTE = 0,
|
SAY_HADRONOX_EMOTE = 0,
|
||||||
|
|
||||||
ACTION_DESPAWN_ADDS = 1,
|
ACTION_CRUSHER_ENGAGED = 1,
|
||||||
ACTION_START_EVENT = 2
|
ACTION_CRUSHER_DIED = 2,
|
||||||
|
ACTION_PACK_WALK = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Position hadronoxSteps[4] =
|
static const std::array<Position, 3> hadronoxSteps =
|
||||||
|
{{
|
||||||
|
{ 562.191f, 514.068f, 696.50710f },
|
||||||
|
{ 615.802f, 517.418f, 695.68066f },
|
||||||
|
{ 530.420f, 560.003f, 733.22473f },
|
||||||
|
}};
|
||||||
|
|
||||||
|
struct boss_hadronox : public BossAI
|
||||||
{
|
{
|
||||||
{607.9f, 512.8f, 695.3f, 0.0f},
|
explicit boss_hadronox(Creature* creature) : BossAI(creature, DATA_HADRONOX), _crushersLeft(0), _doorsWebbed(false), _lastPlayerCombatState(false) { }
|
||||||
{611.67f, 564.11f, 720.0f, 0.0f},
|
|
||||||
{576.1f, 580.0f, 727.5f, 0.0f},
|
void Reset() override
|
||||||
{534.87f, 554.0f, 733.0f, 0.0f}
|
{
|
||||||
|
BossAI::Reset();
|
||||||
|
SummonCrusherPack(SUMMON_GROUP_CRUSHER_1);
|
||||||
|
me->SummonCreatureGroup(SUMMON_GROUP_WORLD_TRIGGERS);
|
||||||
|
_doorsWebbed = false;
|
||||||
|
_lastPlayerCombatState = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SummonedCreatureEvade(Creature* summon) override
|
||||||
|
{
|
||||||
|
switch (summon->GetEntry())
|
||||||
|
{
|
||||||
|
case NPC_ANUB_AR_CRUSHER:
|
||||||
|
case NPC_ANUB_AR_CHAMPION_PACK:
|
||||||
|
case NPC_ANUB_AR_CRYPT_FIEND_PACK:
|
||||||
|
case NPC_ANUB_AR_NECROMANCER_PACK:
|
||||||
|
EnterEvadeMode(EVADE_REASON_OTHER);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoAction(int32 param) override
|
||||||
|
{
|
||||||
|
if (param == ACTION_CRUSHER_DIED)
|
||||||
|
--_crushersLeft;
|
||||||
|
else if (param == ACTION_CRUSHER_ENGAGED)
|
||||||
|
{
|
||||||
|
if (instance->GetBossState(DATA_HADRONOX) == IN_PROGRESS)
|
||||||
|
return;
|
||||||
|
instance->SetBossState(DATA_HADRONOX, IN_PROGRESS);
|
||||||
|
events.ScheduleEvent(EVENT_CHECK_EVADE, 5s);
|
||||||
|
SummonCrusherPack(SUMMON_GROUP_CRUSHER_2);
|
||||||
|
SummonCrusherPack(SUMMON_GROUP_CRUSHER_3);
|
||||||
|
events.ScheduleEvent(EVENT_HADRONOX_MOVE1, 0s);
|
||||||
|
events.ScheduleEvent(EVENT_HADRONOX_MOVE2, 45s);
|
||||||
|
events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 90s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SummonCrusherPack(const SummonGroups group)
|
||||||
|
{
|
||||||
|
std::list<TempSummon*> summoned;
|
||||||
|
me->SummonCreatureGroup(group, &summoned);
|
||||||
|
_crushersLeft = summoned.size();
|
||||||
|
for (TempSummon* summon : summoned)
|
||||||
|
{
|
||||||
|
summon->AI()->SetData(DATA_CRUSHER_PACK_ID, group);
|
||||||
|
summon->AI()->DoAction(ACTION_PACK_WALK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* summon) override
|
||||||
|
{
|
||||||
|
summons.Summon(summon);
|
||||||
|
|
||||||
|
switch (summon->GetEntry())
|
||||||
|
{
|
||||||
|
case NPC_WORLD_TRIGGER_LAOI:
|
||||||
|
summon->AddAura(SPELL_SUMMON_ANUBAR_CHAMPION_PERIODIC, summon);
|
||||||
|
summon->AddAura(SPELL_SUMMON_ANUBAR_NECROMANCER_PERIODIC, summon);
|
||||||
|
summon->AddAura(SPELL_SUMMON_ANUBAR_CRYPT_FIEND_PERIODIC, summon);
|
||||||
|
break;
|
||||||
|
case NPC_ANUB_AR_CHAMPION:
|
||||||
|
case NPC_ANUB_AR_NECROMANCER:
|
||||||
|
case NPC_ANUB_AR_CRYPTFIEND:
|
||||||
|
// Xinef: cannot use pathfinding...
|
||||||
|
if (summon->GetDistance(477.0f, 618.0f, 771.0f) < 5.0f)
|
||||||
|
summon->GetMotionMaster()->MoveWaypoint(3000012, false);
|
||||||
|
else if (summon->GetDistance(583.0f, 617.0f, 771.0f) < 5.0f)
|
||||||
|
summon->GetMotionMaster()->MoveWaypoint(3000013, false);
|
||||||
|
else if (summon->GetDistance(581.0f, 608.5f, 739.0f) < 5.0f)
|
||||||
|
summon->GetMotionMaster()->MoveWaypoint(3000014, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KilledUnit(Unit* victim) override
|
||||||
|
{
|
||||||
|
if (!me->IsAlive() || !victim->HasAura(SPELL_LEECH_POISON))
|
||||||
|
return;
|
||||||
|
|
||||||
|
me->ModifyHealth(static_cast<int32>(me->CountPctFromMaxHealth(10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
me->setActive(true);
|
||||||
|
events.RescheduleEvent(EVENT_HADRONOX_ACID, 10s);
|
||||||
|
events.RescheduleEvent(EVENT_HADRONOX_LEECH, 4s);
|
||||||
|
events.RescheduleEvent(EVENT_HADRONOX_PIERCE, 1s);
|
||||||
|
events.RescheduleEvent(EVENT_HADRONOX_GRAB, 15s);
|
||||||
|
events.RescheduleEvent(EVENT_CHECK_EVADE, 1s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsInCombatWithPlayer() const
|
||||||
|
{
|
||||||
|
return std::ranges::any_of(me->GetThreatMgr().GetThreatList(), [](auto const& ref) {
|
||||||
|
return ref->getTarget()->IsControlledByPlayer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* who, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
|
{
|
||||||
|
if ((!who || !who->IsControlledByPlayer()) && me->HealthBelowPct(70))
|
||||||
|
{
|
||||||
|
if (me->HealthBelowPctDamaged(5, damage))
|
||||||
|
damage = 0;
|
||||||
|
else
|
||||||
|
damage *= (me->GetHealthPct() - 5.0f) / 65.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
events.Update(diff);
|
||||||
|
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (uint32 eventId = events.ExecuteEvent())
|
||||||
|
{
|
||||||
|
case EVENT_HADRONOX_PIERCE:
|
||||||
|
DoCastVictim(SPELL_PIERCE_ARMOR);
|
||||||
|
events.Repeat(8s);
|
||||||
|
break;
|
||||||
|
case EVENT_HADRONOX_ACID:
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, false))
|
||||||
|
DoCast(target, SPELL_ACID_CLOUD);
|
||||||
|
events.Repeat(25s);
|
||||||
|
break;
|
||||||
|
case EVENT_HADRONOX_LEECH:
|
||||||
|
DoCastSelf(SPELL_LEECH_POISON);
|
||||||
|
events.Repeat(12s);
|
||||||
|
break;
|
||||||
|
case EVENT_HADRONOX_GRAB:
|
||||||
|
DoCastSelf(SPELL_WEB_GRAB);
|
||||||
|
events.Repeat(25s);
|
||||||
|
break;
|
||||||
|
case EVENT_HADRONOX_MOVE3:
|
||||||
|
if (_crushersLeft > 0)
|
||||||
|
{
|
||||||
|
events.Repeat(2s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
case EVENT_HADRONOX_MOVE1:
|
||||||
|
case EVENT_HADRONOX_MOVE2:
|
||||||
|
Talk(SAY_HADRONOX_EMOTE);
|
||||||
|
me->SetReactState(REACT_PASSIVE);
|
||||||
|
me->GetMotionMaster()->Clear();
|
||||||
|
me->AttackStop();
|
||||||
|
me->GetMotionMaster()->MovePoint(eventId, hadronoxSteps[eventId - 1]);
|
||||||
|
break;
|
||||||
|
case EVENT_CHECK_EVADE:
|
||||||
|
if (IsInCombatWithPlayer() != _lastPlayerCombatState)
|
||||||
|
{
|
||||||
|
_lastPlayerCombatState = !_lastPlayerCombatState;
|
||||||
|
if (_lastPlayerCombatState)
|
||||||
|
{
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
|
||||||
|
me->GetMotionMaster()->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
|
||||||
|
}
|
||||||
|
events.Repeat(1s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementInform(uint32 movementType, uint32 pointId) override
|
||||||
|
{
|
||||||
|
if (movementType != POINT_MOTION_TYPE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
|
||||||
|
if (pointId == EVENT_HADRONOX_MOVE3)
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_WEB_FRONT_DOORS, true);
|
||||||
|
_doorsWebbed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetData(uint32 data) const override
|
||||||
|
{
|
||||||
|
if (data == me->GetEntry()) // 'Hadronox Denied' achievement
|
||||||
|
return _doorsWebbed ? 0 : 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 _crushersLeft;
|
||||||
|
bool _doorsWebbed;
|
||||||
|
bool _lastPlayerCombatState;
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_hadronox : public CreatureScript
|
struct npc_hadronox_crusherPackAI : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_hadronox_crusherPackAI(Creature* creature, Position const* positions) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _positions(positions), _myPack(SUMMON_GROUP_CRUSHER_NONE), _doFacing(false) { }
|
||||||
boss_hadronox() : CreatureScript("boss_hadronox") { }
|
|
||||||
|
|
||||||
struct boss_hadronoxAI : public BossAI
|
virtual void DoEngagedWith() = 0;
|
||||||
|
virtual void DoEvent(uint32 /*eventId*/) = 0;
|
||||||
|
|
||||||
|
void DoAction(int32 action) override
|
||||||
{
|
{
|
||||||
boss_hadronoxAI(Creature* creature) : BossAI(creature, DATA_HADRONOX)
|
if (action == ACTION_PACK_WALK)
|
||||||
{
|
{
|
||||||
}
|
switch (_myPack)
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
summons.DoAction(ACTION_DESPAWN_ADDS);
|
|
||||||
BossAI::Reset();
|
|
||||||
me->SummonCreature(NPC_ANUB_AR_CRUSHER, 542.9f, 519.5f, 741.24f, 2.14f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoAction(int32 param) override
|
|
||||||
{
|
|
||||||
if (param == ACTION_START_EVENT)
|
|
||||||
{
|
{
|
||||||
instance->SetBossState(DATA_HADRONOX, IN_PROGRESS);
|
case SUMMON_GROUP_CRUSHER_1:
|
||||||
me->setActive(true);
|
case SUMMON_GROUP_CRUSHER_2:
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE1, 20s);
|
case SUMMON_GROUP_CRUSHER_3:
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE2, 40s);
|
me->GetMotionMaster()->MovePoint(ACTION_PACK_WALK, _positions[_myPack - SUMMON_GROUP_CRUSHER_1]);
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 60s);
|
break;
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE4, 80s);
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 GetData(uint32 data) const override
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
{
|
|
||||||
if (data == me->GetEntry())
|
|
||||||
return !me->isActiveObject() || events.HasTimeUntilEvent(EVENT_HADRONOX_MOVE4) ? 1 : 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
|
||||||
{
|
|
||||||
summons.Summon(summon);
|
|
||||||
|
|
||||||
// Xinef: cannot use pathfinding...
|
|
||||||
if (summon->GetDistance(477.0f, 618.0f, 771.0f) < 5.0f)
|
|
||||||
summon->GetMotionMaster()->MoveWaypoint(3000012, false);
|
|
||||||
else if (summon->GetDistance(583.0f, 617.0f, 771.0f) < 5.0f)
|
|
||||||
summon->GetMotionMaster()->MoveWaypoint(3000013, false);
|
|
||||||
else if (summon->GetDistance(581.0f, 608.5f, 739.0f) < 5.0f)
|
|
||||||
summon->GetMotionMaster()->MoveWaypoint(3000014, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
|
||||||
{
|
|
||||||
if (!me->IsAlive() || !victim->HasAura(SPELL_LEECH_POISON))
|
|
||||||
return;
|
|
||||||
|
|
||||||
me->ModifyHealth(int32(me->CountPctFromMaxHealth(10)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* killer) override
|
|
||||||
{
|
|
||||||
BossAI::JustDied(killer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit*) override
|
|
||||||
{
|
|
||||||
events.RescheduleEvent(EVENT_HADRONOX_ACID, 10s);
|
|
||||||
events.RescheduleEvent(EVENT_HADRONOX_LEECH, 4s);
|
|
||||||
events.RescheduleEvent(EVENT_HADRONOX_PIERCE, 1s);
|
|
||||||
events.RescheduleEvent(EVENT_HADRONOX_GRAB, 15s);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnyPlayerValid() const
|
|
||||||
{
|
|
||||||
Map::PlayerList const& playerList = me->GetMap()->GetPlayers();
|
|
||||||
for(Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
|
|
||||||
if (me->GetDistance(itr->GetSource()) < 130.0f && itr->GetSource()->IsAlive() && !itr->GetSource()->IsGameMaster() && me->CanCreatureAttack(itr->GetSource()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DamageTaken(Unit* who, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
|
|
||||||
{
|
|
||||||
if ((!who || !who->IsControlledByPlayer()) && me->HealthBelowPct(70))
|
|
||||||
{
|
|
||||||
if (me->HealthBelowPctDamaged(5, damage))
|
|
||||||
{
|
|
||||||
damage = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
damage *= (me->GetHealthPct() - 5.0f) / 65.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (uint32 eventId = events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case EVENT_HADRONOX_PIERCE:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_PIERCE_ARMOR, false);
|
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_PIERCE, 8s);
|
|
||||||
break;
|
|
||||||
case EVENT_HADRONOX_ACID:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, false))
|
|
||||||
me->CastSpell(target, SPELL_ACID_CLOUD, false);
|
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_ACID, 25s);
|
|
||||||
break;
|
|
||||||
case EVENT_HADRONOX_LEECH:
|
|
||||||
me->CastSpell(me, SPELL_LEECH_POISON, false);
|
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_LEECH, 12s);
|
|
||||||
break;
|
|
||||||
case EVENT_HADRONOX_GRAB:
|
|
||||||
me->CastSpell(me, SPELL_WEB_GRAB, false);
|
|
||||||
events.ScheduleEvent(EVENT_HADRONOX_GRAB, 25s);
|
|
||||||
break;
|
|
||||||
case EVENT_HADRONOX_MOVE4:
|
|
||||||
me->CastSpell(me, SPELL_WEB_FRONT_DOORS, true);
|
|
||||||
[[fallthrough]]; /// @todo: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
|
|
||||||
case EVENT_HADRONOX_MOVE1:
|
|
||||||
case EVENT_HADRONOX_MOVE2:
|
|
||||||
case EVENT_HADRONOX_MOVE3:
|
|
||||||
Talk(SAY_HADRONOX_EMOTE);
|
|
||||||
me->GetMotionMaster()->MoveCharge(hadronoxSteps[eventId - 1].GetPositionX(), hadronoxSteps[eventId - 1].GetPositionY(), hadronoxSteps[eventId - 1].GetPositionZ(), 10.0f, 0, nullptr, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckEvadeIfOutOfCombatArea() const override
|
|
||||||
{
|
|
||||||
return me->isActiveObject() && !AnyPlayerValid();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
{
|
||||||
return GetAzjolNerubAI<boss_hadronoxAI>(creature);
|
if (type == POINT_MOTION_TYPE && id == ACTION_PACK_WALK)
|
||||||
|
_doFacing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetData(uint32 data) const override
|
||||||
|
{
|
||||||
|
if (data == DATA_CRUSHER_PACK_ID)
|
||||||
|
return _myPack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetData(uint32 data, uint32 value) override
|
||||||
|
{
|
||||||
|
if (data == DATA_CRUSHER_PACK_ID)
|
||||||
|
{
|
||||||
|
_myPack = SummonGroups(value);
|
||||||
|
me->SetReactState(_myPack ? REACT_PASSIVE : REACT_AGGRESSIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* who) override
|
||||||
|
{
|
||||||
|
if (me->HasReactState(REACT_PASSIVE))
|
||||||
|
{
|
||||||
|
std::list<Creature*> creatures;
|
||||||
|
|
||||||
|
me->GetCreatureListWithEntryInGrid(creatures, { NPC_ANUB_AR_CRUSHER, NPC_ANUB_AR_CHAMPION_PACK, NPC_ANUB_AR_NECROMANCER_PACK, NPC_ANUB_AR_CRYPT_FIEND_PACK }, 40.0f);
|
||||||
|
for (Creature* creature : creatures)
|
||||||
|
if (creature->AI()->GetData(DATA_CRUSHER_PACK_ID) == _myPack)
|
||||||
|
{
|
||||||
|
creature->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
creature->AI()->AttackStart(who);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DoEngagedWith();
|
||||||
|
ScriptedAI::JustEngagedWith(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveInLineOfSight(Unit* who) override
|
||||||
|
{
|
||||||
|
if (!me->HasReactState(REACT_PASSIVE))
|
||||||
|
{
|
||||||
|
ScriptedAI::MoveInLineOfSight(who);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->CanStartAttack(who) && me->IsWithinDistInMap(who, me->GetAttackDistance(who) + me->m_CombatDistance))
|
||||||
|
JustEngagedWith(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (_doFacing)
|
||||||
|
{
|
||||||
|
_doFacing = false;
|
||||||
|
me->SetFacingTo(_positions[_myPack - SUMMON_GROUP_CRUSHER_1].GetOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
events.Update(diff);
|
||||||
|
|
||||||
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
|
DoEvent(eventId);
|
||||||
|
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
InstanceScript* const _instance;
|
||||||
|
Position const* const _positions;
|
||||||
|
SummonGroups _myPack;
|
||||||
|
bool _doFacing;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Position crusherWaypoints[] =
|
||||||
|
{
|
||||||
|
{ 529.6913f, 547.1257f, 731.9155f, 4.799650f },
|
||||||
|
{ 517.51f , 561.439f , 734.0306f, 4.520403f },
|
||||||
|
{ 543.414f , 551.728f , 732.0522f, 3.996804f }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct npc_anub_ar_crusher : public npc_hadronox_crusherPackAI
|
||||||
|
{
|
||||||
|
explicit npc_anub_ar_crusher(Creature* creature) : npc_hadronox_crusherPackAI(creature, crusherWaypoints), _hadFrenzy(false) { }
|
||||||
|
|
||||||
|
void DoEngagedWith() override
|
||||||
|
{
|
||||||
|
events.ScheduleEvent(EVENT_CRUSHER_SMASH, 8s, 12s);
|
||||||
|
|
||||||
|
if (_myPack != SUMMON_GROUP_CRUSHER_1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_instance->GetBossState(DATA_HADRONOX) == IN_PROGRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Creature* hadronox = _instance->GetCreature(DATA_HADRONOX))
|
||||||
|
hadronox->AI()->DoAction(ACTION_CRUSHER_ENGAGED);
|
||||||
|
|
||||||
|
Talk(SAY_CRUSHER_AGGRO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
|
{
|
||||||
|
if (_hadFrenzy || !me->HealthBelowPctDamaged(25, damage))
|
||||||
|
return;
|
||||||
|
_hadFrenzy = true;
|
||||||
|
Talk(SAY_CRUSHER_EMOTE);
|
||||||
|
DoCastSelf(SPELL_FRENZY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoEvent(uint32 eventId) override
|
||||||
|
{
|
||||||
|
if (eventId == EVENT_CRUSHER_SMASH)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_SMASH);
|
||||||
|
events.Repeat(13s, 21s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* killer) override
|
||||||
|
{
|
||||||
|
if (Creature* hadronox = _instance->GetCreature(DATA_HADRONOX))
|
||||||
|
hadronox->AI()->DoAction(ACTION_CRUSHER_DIED);
|
||||||
|
ScriptedAI::JustDied(killer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _hadFrenzy;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Position championWaypoints[] =
|
||||||
|
{
|
||||||
|
{ 539.2076f, 549.7539f, 732.8668f, 4.55531f },
|
||||||
|
{ 527.3098f, 559.5197f, 732.9407f, 4.742493f },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
struct npc_anub_ar_crusher_champion : public npc_hadronox_crusherPackAI
|
||||||
|
{
|
||||||
|
explicit npc_anub_ar_crusher_champion(Creature* creature) : npc_hadronox_crusherPackAI(creature, championWaypoints) { }
|
||||||
|
|
||||||
|
void DoEvent(uint32 eventId) override
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_REND:
|
||||||
|
DoCastVictim(SPELL_REND);
|
||||||
|
events.Repeat(12s, 16s);
|
||||||
|
break;
|
||||||
|
case EVENT_PUMMEL:
|
||||||
|
DoCastVictim(SPELL_PUMMEL);
|
||||||
|
events.Repeat(12s, 17s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoEngagedWith() override
|
||||||
|
{
|
||||||
|
events.ScheduleEvent(EVENT_REND, 4s, 8s);
|
||||||
|
events.ScheduleEvent(EVENT_PUMMEL, 15s, 19s);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_anub_ar_crusher : public CreatureScript
|
static const Position cryptFiendWaypoints[] =
|
||||||
{
|
{
|
||||||
public:
|
{ 520.3911f, 548.7895f, 732.0118f, 5.0091f },
|
||||||
npc_anub_ar_crusher() : CreatureScript("npc_anub_ar_crusher") { }
|
{ },
|
||||||
|
{ 550.9611f, 545.1674f, 731.9031f, 3.996804f }
|
||||||
|
};
|
||||||
|
struct npc_anub_ar_crusher_crypt_fiend : public npc_hadronox_crusherPackAI
|
||||||
|
{
|
||||||
|
explicit npc_anub_ar_crusher_crypt_fiend(Creature* creature) : npc_hadronox_crusherPackAI(creature, cryptFiendWaypoints) { }
|
||||||
|
|
||||||
struct npc_anub_ar_crusherAI : public ScriptedAI
|
void DoEvent(uint32 eventId) override
|
||||||
{
|
{
|
||||||
npc_anub_ar_crusherAI(Creature* c) : ScriptedAI(c), summons(me) {}
|
switch (eventId)
|
||||||
|
|
||||||
EventMap events;
|
|
||||||
SummonList summons;
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
{
|
||||||
summons.DespawnAll();
|
case EVENT_CRUSHING_WEBS:
|
||||||
events.Reset();
|
DoCastVictim(SPELL_CRUSHING_WEBS);
|
||||||
|
events.Repeat(12s, 16s);
|
||||||
if (me->ToTempSummon())
|
break;
|
||||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
case EVENT_INFECTED_WOUND:
|
||||||
if (summoner->GetEntry() == me->GetEntry())
|
DoCastVictim(SPELL_INFECTED_WOUND);
|
||||||
{
|
events.Repeat(16s, 25s);
|
||||||
me->CastSpell(me, RAND(SPELL_SUMMON_ANUBAR_CHAMPION, SPELL_SUMMON_ANUBAR_CRYPT_FIEND, SPELL_SUMMON_ANUBAR_NECROMANCER), true);
|
break;
|
||||||
me->CastSpell(me, RAND(SPELL_SUMMON_ANUBAR_CHAMPION, SPELL_SUMMON_ANUBAR_CRYPT_FIEND, SPELL_SUMMON_ANUBAR_NECROMANCER), true);
|
default:
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
void DoEngagedWith() override
|
||||||
{
|
|
||||||
if (summon->GetEntry() != me->GetEntry())
|
|
||||||
{
|
|
||||||
summon->GetMotionMaster()->MovePoint(0, *me, FORCED_MOVEMENT_NONE, 0.f, false);
|
|
||||||
summon->GetMotionMaster()->MoveFollow(me, 0.1f, 0.0f + M_PI * 0.3f * summons.size());
|
|
||||||
}
|
|
||||||
summons.Summon(summon);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoAction(int32 param) override
|
|
||||||
{
|
|
||||||
if (param == ACTION_DESPAWN_ADDS)
|
|
||||||
{
|
|
||||||
summons.DoAction(ACTION_DESPAWN_ADDS);
|
|
||||||
summons.DespawnAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit*) override
|
|
||||||
{
|
|
||||||
if (me->ToTempSummon())
|
|
||||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
|
||||||
if (summoner->GetEntry() != me->GetEntry())
|
|
||||||
{
|
|
||||||
summoner->GetAI()->DoAction(ACTION_START_EVENT);
|
|
||||||
me->SummonCreature(NPC_ANUB_AR_CRUSHER, 519.58f, 573.73f, 734.30f, 4.50f);
|
|
||||||
me->SummonCreature(NPC_ANUB_AR_CRUSHER, 539.38f, 573.25f, 732.20f, 4.738f);
|
|
||||||
Talk(SAY_CRUSHER_AGGRO);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_CRUSHER_SMASH, 8s, 0, 0);
|
|
||||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
|
||||||
case EVENT_CRUSHER_SMASH:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_SMASH, false);
|
|
||||||
events.ScheduleEvent(EVENT_CRUSHER_SMASH, 15s);
|
|
||||||
break;
|
|
||||||
case EVENT_CHECK_HEALTH:
|
|
||||||
if (me->HealthBelowPct(30))
|
|
||||||
{
|
|
||||||
Talk(SAY_CRUSHER_EMOTE);
|
|
||||||
me->CastSpell(me, SPELL_FRENZY, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
{
|
||||||
return GetAzjolNerubAI<npc_anub_ar_crusherAI>(creature);
|
events.ScheduleEvent(EVENT_CRUSHING_WEBS, 4s, 8s);
|
||||||
|
events.ScheduleEvent(EVENT_INFECTED_WOUND, 15s, 19s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Position necromancerWaypoints[] =
|
||||||
|
{
|
||||||
|
{ },
|
||||||
|
{ 507.6937f, 563.3471f, 734.8986f, 4.520403f },
|
||||||
|
{ 535.1049f, 552.8961f, 732.8441f, 3.996804f },
|
||||||
|
};
|
||||||
|
struct npc_anub_ar_crusher_necromancer : public npc_hadronox_crusherPackAI
|
||||||
|
{
|
||||||
|
explicit npc_anub_ar_crusher_necromancer(Creature* creature) : npc_hadronox_crusherPackAI(creature, necromancerWaypoints) { }
|
||||||
|
|
||||||
|
void DoEvent(uint32 eventId) override
|
||||||
|
{
|
||||||
|
switch (eventId)
|
||||||
|
{
|
||||||
|
case EVENT_SHADOW_BOLT:
|
||||||
|
DoCastVictim(SPELL_SHADOW_BOLT);
|
||||||
|
events.Repeat(2s, 5s);
|
||||||
|
break;
|
||||||
|
case EVENT_ANIMATE_BONES:
|
||||||
|
DoCastVictim(RAND(SPELL_ANIMATE_BONES_2, SPELL_ANIMATE_BONES_1));
|
||||||
|
events.Repeat(35s, 50s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoEngagedWith() override
|
||||||
|
{
|
||||||
|
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2s, 4s);
|
||||||
|
events.ScheduleEvent(EVENT_ANIMATE_BONES, 37s, 45s);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -330,7 +609,7 @@ class spell_hadronox_summon_periodic_aura : public AuraScript
|
|||||||
PrepareAuraScript(spell_hadronox_summon_periodic_aura);
|
PrepareAuraScript(spell_hadronox_summon_periodic_aura);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
spell_hadronox_summon_periodic_aura(uint32 delay, uint32 spellEntry) : _delay(delay), _spellEntry(spellEntry) { }
|
spell_hadronox_summon_periodic_aura(int32 delay, uint32 spellEntry) : _delay(delay), _spellEntry(spellEntry) { }
|
||||||
|
|
||||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||||
{
|
{
|
||||||
@ -342,7 +621,7 @@ public:
|
|||||||
PreventDefaultAction();
|
PreventDefaultAction();
|
||||||
Unit* owner = GetUnitOwner();
|
Unit* owner = GetUnitOwner();
|
||||||
if (InstanceScript* instance = owner->GetInstanceScript())
|
if (InstanceScript* instance = owner->GetInstanceScript())
|
||||||
if (!instance->IsBossDone(DATA_HADRONOX))
|
if (!instance->IsBossDone(DATA_HADRONOX) != NOT_STARTED)
|
||||||
{
|
{
|
||||||
if (!owner->HasAura(SPELL_WEB_FRONT_DOORS))
|
if (!owner->HasAura(SPELL_WEB_FRONT_DOORS))
|
||||||
owner->CastSpell(owner, _spellEntry, true);
|
owner->CastSpell(owner, _spellEntry, true);
|
||||||
@ -363,7 +642,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 _delay;
|
int32 _delay;
|
||||||
uint32 _spellEntry;
|
uint32 _spellEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -389,12 +668,29 @@ class spell_hadronox_leech_poison_aura : public AuraScript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class spell_hadronox_web_grab : public SpellScript
|
||||||
|
{
|
||||||
|
PrepareSpellScript(spell_hadronox_web_grab);
|
||||||
|
|
||||||
|
// hack to avoid pulling Anub'ar Crusher through the floor and causing Hadronox to evade
|
||||||
|
void FilterTargets(std::list<WorldObject*>& targets)
|
||||||
|
{
|
||||||
|
targets.remove_if([&](WorldObject* target) -> bool
|
||||||
|
{
|
||||||
|
return target->GetEntry() == NPC_ANUB_AR_CRUSHER;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register() override
|
||||||
|
{
|
||||||
|
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_hadronox_web_grab::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class achievement_hadronox_denied : public AchievementCriteriaScript
|
class achievement_hadronox_denied : public AchievementCriteriaScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
achievement_hadronox_denied() : AchievementCriteriaScript("achievement_hadronox_denied")
|
achievement_hadronox_denied() : AchievementCriteriaScript("achievement_hadronox_denied") { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
|
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
|
||||||
{
|
{
|
||||||
@ -407,11 +703,15 @@ public:
|
|||||||
|
|
||||||
void AddSC_boss_hadronox()
|
void AddSC_boss_hadronox()
|
||||||
{
|
{
|
||||||
new boss_hadronox();
|
RegisterAzjolNerubCreatureAI(boss_hadronox);
|
||||||
new npc_anub_ar_crusher();
|
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher);
|
||||||
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_champion_aura", 15000, SPELL_SUMMON_ANUBAR_CHAMPION);
|
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher_champion);
|
||||||
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_necromancer_aura", 10000, SPELL_SUMMON_ANUBAR_NECROMANCER);
|
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher_crypt_fiend);
|
||||||
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_crypt_fiend_aura", 5000, SPELL_SUMMON_ANUBAR_CRYPT_FIEND);
|
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher_necromancer);
|
||||||
|
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_champion_aura", 15'000, SPELL_SUMMON_ANUBAR_CHAMPION);
|
||||||
|
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_necromancer_aura", 10'000, SPELL_SUMMON_ANUBAR_NECROMANCER);
|
||||||
|
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_crypt_fiend_aura", 5'000, SPELL_SUMMON_ANUBAR_CRYPT_FIEND);
|
||||||
RegisterSpellScript(spell_hadronox_leech_poison_aura);
|
RegisterSpellScript(spell_hadronox_leech_poison_aura);
|
||||||
|
RegisterSpellScript(spell_hadronox_web_grab);
|
||||||
new achievement_hadronox_denied();
|
new achievement_hadronox_denied();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ ObjectData const summonData[] =
|
|||||||
{ NPC_ANUB_AR_CHAMPION, DATA_HADRONOX },
|
{ NPC_ANUB_AR_CHAMPION, DATA_HADRONOX },
|
||||||
{ NPC_ANUB_AR_NECROMANCER, DATA_HADRONOX },
|
{ NPC_ANUB_AR_NECROMANCER, DATA_HADRONOX },
|
||||||
{ NPC_ANUB_AR_CRYPTFIEND, DATA_HADRONOX },
|
{ NPC_ANUB_AR_CRYPTFIEND, DATA_HADRONOX },
|
||||||
|
{ NPC_WORLD_TRIGGER_LAOI, DATA_HADRONOX },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user