mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 20:34:53 +08:00
fix(Scripts/Northrend): Azjol-Nerub Hadronox
Allow reset trick for 'Hadronox Denied' achievement
Fix web grab LoS issue
Update boss spawn
Update crusher packs handling, summoning, pathing
Update foe waypoints and smartAI
Update hadronox movement points
Refactor spelldifficulty_dbc
Refactor registry macros
[3.3.5] Azjol-Nerub rewrite
4b990eb7d7
Co-authored-by: Treeston <treeston.mmoc@gmail.com>
This commit is contained in:
parent
639ee028fd
commit
b33b932b66
@ -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_ANUBARAK = 29120,
|
||||
|
||||
NPC_WORLD_TRIGGER_LAOI = 23472,
|
||||
NPC_ANUB_AR_CHAMPION = 29062,
|
||||
NPC_ANUB_AR_NECROMANCER = 29063,
|
||||
NPC_ANUB_AR_CRYPTFIEND = 29064,
|
||||
|
||||
@ -75,7 +75,6 @@ enum Events
|
||||
|
||||
enum CreatureIds
|
||||
{
|
||||
NPC_WORLD_TRIGGER = 22515,
|
||||
NPC_ANUBAR_GUARDIAN = 29216,
|
||||
NPC_ANUBAR_VENOMANCER = 29217,
|
||||
};
|
||||
|
||||
@ -26,19 +26,39 @@
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// World Trigger
|
||||
SPELL_SUMMON_ANUBAR_CHAMPION = 53064,
|
||||
SPELL_SUMMON_ANUBAR_CRYPT_FIEND = 53065,
|
||||
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_SIDE_DOORS = 53185,
|
||||
SPELL_ACID_CLOUD = 53400,
|
||||
SPELL_LEECH_POISON = 53030,
|
||||
SPELL_LEECH_POISON_HEAL = 53800,
|
||||
SPELL_WEB_GRAB = 57731,
|
||||
SPELL_WEB_GRAB = 53406,
|
||||
SPELL_PIERCE_ARMOR = 53418,
|
||||
|
||||
// Anub'ar Crusher
|
||||
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
|
||||
@ -54,274 +74,533 @@ enum Events
|
||||
EVENT_HADRONOX_SUMMON = 9,
|
||||
|
||||
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
|
||||
{
|
||||
NPC_ANUB_AR_CRUSHER = 28922,
|
||||
|
||||
SAY_CRUSHER_AGGRO = 0,
|
||||
SAY_CRUSHER_EMOTE = 1,
|
||||
SAY_CRUSHER_AGGRO = 1,
|
||||
SAY_CRUSHER_EMOTE = 2,
|
||||
SAY_HADRONOX_EMOTE = 0,
|
||||
|
||||
ACTION_DESPAWN_ADDS = 1,
|
||||
ACTION_START_EVENT = 2
|
||||
ACTION_CRUSHER_ENGAGED = 1,
|
||||
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},
|
||||
{611.67f, 564.11f, 720.0f, 0.0f},
|
||||
{576.1f, 580.0f, 727.5f, 0.0f},
|
||||
{534.87f, 554.0f, 733.0f, 0.0f}
|
||||
explicit boss_hadronox(Creature* creature) : BossAI(creature, DATA_HADRONOX), _crushersLeft(0), _doorsWebbed(false), _lastPlayerCombatState(false) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
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:
|
||||
boss_hadronox() : CreatureScript("boss_hadronox") { }
|
||||
npc_hadronox_crusherPackAI(Creature* creature, Position const* positions) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _positions(positions), _myPack(SUMMON_GROUP_CRUSHER_NONE), _doFacing(false) { }
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
switch (_myPack)
|
||||
{
|
||||
instance->SetBossState(DATA_HADRONOX, IN_PROGRESS);
|
||||
me->setActive(true);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE1, 20s);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE2, 40s);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 60s);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE4, 80s);
|
||||
case SUMMON_GROUP_CRUSHER_1:
|
||||
case SUMMON_GROUP_CRUSHER_2:
|
||||
case SUMMON_GROUP_CRUSHER_3:
|
||||
me->GetMotionMaster()->MovePoint(ACTION_PACK_WALK, _positions[_myPack - SUMMON_GROUP_CRUSHER_1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 data) const 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
|
||||
void MovementInform(uint32 type, uint32 id) 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:
|
||||
npc_anub_ar_crusher() : CreatureScript("npc_anub_ar_crusher") { }
|
||||
{ 520.3911f, 548.7895f, 732.0118f, 5.0091f },
|
||||
{ },
|
||||
{ 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) {}
|
||||
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
|
||||
void Reset() override
|
||||
switch (eventId)
|
||||
{
|
||||
summons.DespawnAll();
|
||||
events.Reset();
|
||||
|
||||
if (me->ToTempSummon())
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
if (summoner->GetEntry() == me->GetEntry())
|
||||
{
|
||||
me->CastSpell(me, RAND(SPELL_SUMMON_ANUBAR_CHAMPION, SPELL_SUMMON_ANUBAR_CRYPT_FIEND, SPELL_SUMMON_ANUBAR_NECROMANCER), true);
|
||||
me->CastSpell(me, RAND(SPELL_SUMMON_ANUBAR_CHAMPION, SPELL_SUMMON_ANUBAR_CRYPT_FIEND, SPELL_SUMMON_ANUBAR_NECROMANCER), true);
|
||||
}
|
||||
case EVENT_CRUSHING_WEBS:
|
||||
DoCastVictim(SPELL_CRUSHING_WEBS);
|
||||
events.Repeat(12s, 16s);
|
||||
break;
|
||||
case EVENT_INFECTED_WOUND:
|
||||
DoCastVictim(SPELL_INFECTED_WOUND);
|
||||
events.Repeat(16s, 25s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) 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
|
||||
void DoEngagedWith() 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);
|
||||
|
||||
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
|
||||
{
|
||||
@ -342,7 +621,7 @@ public:
|
||||
PreventDefaultAction();
|
||||
Unit* owner = GetUnitOwner();
|
||||
if (InstanceScript* instance = owner->GetInstanceScript())
|
||||
if (!instance->IsBossDone(DATA_HADRONOX))
|
||||
if (!instance->IsBossDone(DATA_HADRONOX) != NOT_STARTED)
|
||||
{
|
||||
if (!owner->HasAura(SPELL_WEB_FRONT_DOORS))
|
||||
owner->CastSpell(owner, _spellEntry, true);
|
||||
@ -363,7 +642,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _delay;
|
||||
int32 _delay;
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -407,11 +703,15 @@ public:
|
||||
|
||||
void AddSC_boss_hadronox()
|
||||
{
|
||||
new boss_hadronox();
|
||||
new npc_anub_ar_crusher();
|
||||
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_champion_aura", 15000, SPELL_SUMMON_ANUBAR_CHAMPION);
|
||||
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_necromancer_aura", 10000, SPELL_SUMMON_ANUBAR_NECROMANCER);
|
||||
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_crypt_fiend_aura", 5000, SPELL_SUMMON_ANUBAR_CRYPT_FIEND);
|
||||
RegisterAzjolNerubCreatureAI(boss_hadronox);
|
||||
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher);
|
||||
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher_champion);
|
||||
RegisterAzjolNerubCreatureAI(npc_anub_ar_crusher_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_web_grab);
|
||||
new achievement_hadronox_denied();
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ ObjectData const summonData[] =
|
||||
{ NPC_ANUB_AR_CHAMPION, DATA_HADRONOX },
|
||||
{ NPC_ANUB_AR_NECROMANCER, DATA_HADRONOX },
|
||||
{ NPC_ANUB_AR_CRYPTFIEND, DATA_HADRONOX },
|
||||
{ NPC_WORLD_TRIGGER_LAOI, DATA_HADRONOX },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user