fix(Scripts/AzjolNerub): Hadronox encounter door mob spawns (#27905)

Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Co-authored-by: Treeston <[email protected]>
Co-authored-by: sogladev <[email protected]>
This commit is contained in:
Stephen Schlie
2026-10-03 11:49:15 -03:00
committed by GitHub
co-authored by Claude Sonnet 5.5 Treeston sogladev
parent ff9edc9fe4
commit 5e45615d29
5 changed files with 100 additions and 20 deletions
@@ -0,0 +1,19 @@
-- Lower Hadronox door adds: attack Hadronox when out of combat and despawn on death, like their 29062-29064 counterparts
DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `entryorguid` IN (29096, 29097, 29098);
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
(29096,0,0,0,0,0,100,2,6000,9000,17000,32000,0,0,11,53317,32,0,0,0,0,5,0,0,0,53317,0,0,0,0,'Anub\'ar Champion - In Combat - Cast \'Rend\' (Phase 1) (No Repeat) (Dungeon)'),
(29096,0,1,0,0,0,100,4,4000,7000,15000,18000,0,0,11,59343,32,0,0,0,0,5,0,0,0,59343,0,0,0,0,'Anub\'ar Champion - In Combat - Cast \'Rend\' (Phase 1) (No Repeat) (Dungeon)'),
(29096,0,2,0,105,0,25,2,14000,17000,14000,17000,0,5,11,53394,1,0,0,0,0,7,0,0,0,0,0,0,0,0,'Anub\'ar Champion - Target Casting - Cast \'Pummel\' (Phase 1) (No Repeat) (Dungeon)'),
(29096,0,3,0,105,0,25,4,9000,12000,9000,12000,0,5,11,59344,1,0,0,0,0,7,0,0,0,0,0,0,0,0,'Anub\'ar Champion - Target Casting - Cast \'Pummel\' (Phase 1) (No Repeat) (Dungeon)'),
(29096,0,4,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'),
(29096,0,5,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'),
(29097,0,0,0,0,0,100,2,4000,7000,9000,12000,0,0,11,53330,32,0,0,0,0,5,0,0,0,53330,0,0,0,0,'Anub\'ar Crypt Fiend - In Combat - Cast \'Infected Wound\' (Phase 1) (No Repeat) (Dungeon)'),
(29097,0,1,0,0,0,100,4,4000,7000,9000,12000,0,0,11,59348,32,0,0,0,0,5,0,0,0,59348,0,0,0,0,'Anub\'ar Crypt Fiend - In Combat - Cast \'Infected Wound\' (Phase 1) (No Repeat) (Dungeon)'),
(29097,0,2,0,0,0,100,2,9000,12000,13000,17000,0,0,11,53322,1,0,0,0,0,5,0,0,0,0,0,0,0,0,'Anub\'ar Crypt Fiend - In Combat - Cast \'Crushing Webs\' (Phase 1) (No Repeat) (Dungeon)'),
(29097,0,3,0,0,0,100,4,9000,12000,10000,13000,0,0,11,59347,1,0,0,0,0,5,0,0,0,0,0,0,0,0,'Anub\'ar Crypt Fiend - In Combat - Cast \'Crushing Webs\' (Phase 1) (No Repeat) (Dungeon)'),
(29097,0,4,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'),
(29097,0,5,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'),
(29098,0,0,0,0,0,100,6,0,0,4000,6000,0,0,11,53333,64,0,0,0,0,2,0,0,0,0,0,0,0,0,'Anub\'ar Necromancer - Combat CMC - Cast \'Shadow Bolt\' (Dungeon)'),
(29098,0,1,0,0,0,100,6,14000,17000,23000,27000,0,0,11,53334,1,0,0,0,0,1,0,0,0,0,0,0,0,0,'Anub\'ar Necromancer - Combat - Cast \'Animate Bones\' (Dungeon)'),
(29098,0,2,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'),
(29098,0,3,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');
@@ -0,0 +1,2 @@
-- Hadronox adds no longer use these paths, they pathfind down the ramp
DELETE FROM `waypoint_data` WHERE `id` IN (3000012, 3000013, 3000014);
@@ -54,6 +54,10 @@ enum ANIds
NPC_ANUB_AR_CHAMPION = 29062,
NPC_ANUB_AR_NECROMANCER = 29063,
NPC_ANUB_AR_CRYPTFIEND = 29064,
// Summoned by the lower Hadronox door (53090-53092)
NPC_ANUB_AR_CHAMPION_LOWER = 29096,
NPC_ANUB_AR_CRYPT_FIEND_LOWER = 29097,
NPC_ANUB_AR_NECROMANCER_LOWER = 29098,
GO_KRIKTHIR_DOORS = 192395,
GO_ANUBARAK_DOORS1 = 192396,
@@ -17,6 +17,7 @@
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "PathGenerator.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellScriptLoader.h"
@@ -30,6 +31,9 @@ enum Spells
SPELL_SUMMON_ANUBAR_CHAMPION = 53064,
SPELL_SUMMON_ANUBAR_CRYPT_FIEND = 53065,
SPELL_SUMMON_ANUBAR_NECROMANCER = 53066,
SPELL_SUMMON_ANUBAR_CHAMPION_LOWER = 53090,
SPELL_SUMMON_ANUBAR_CRYPT_FIEND_LOWER = 53091,
SPELL_SUMMON_ANUBAR_NECROMANCER_LOWER = 53092,
SPELL_SUMMON_ANUBAR_CHAMPION_PERIODIC = 53035,
SPELL_SUMMON_ANUBAR_NECROMANCER_PERIODIC = 53036,
SPELL_SUMMON_ANUBAR_CRYPT_FIEND_PERIODIC = 53037,
@@ -123,6 +127,22 @@ enum Misc
ACTION_PACK_WALK = 3,
};
static Position const LowerDoorPosition = { 581.0f, 608.5f, 739.0f };
static Position const RampUpperLanding = { 571.498718f, 576.978333f, 727.582947f };
static Position const RampBottom = { 532.775f, 535.233f, 681.056f };
// Stops of the add path from each door. The first one is right outside the door's web wall and is reached in a
// straight line because the navmesh does not pass through the webbing; the others are reached down the ramp by
// pathfinding.
static std::array<std::vector<Position>, 3> const doorPaths =
{{
{ { 485.314606f, 611.418640f, 771.428406f }, { 513.574341f, 587.022156f, 736.229065f }, RampUpperLanding,
RampBottom },
{ { 575.760437f, 611.516418f, 771.427368f }, { 537.920410f, 580.436157f, 732.796692f }, RampUpperLanding,
RampBottom },
{ { 588.930725f, 598.233276f, 739.142151f }, { 601.289246f, 583.259644f, 725.443054f }, RampBottom },
}};
static const std::array<Position, 3> hadronoxSteps =
{{
{ 562.191f, 514.068f, 696.50710f },
@@ -202,19 +222,45 @@ struct boss_hadronox : public BossAI
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);
case NPC_ANUB_AR_CHAMPION_LOWER:
case NPC_ANUB_AR_CRYPT_FIEND_LOWER:
case NPC_ANUB_AR_NECROMANCER_LOWER:
MoveDownRamp(summon);
break;
default:
break;
}
}
void MoveDownRamp(Creature* summon)
{
auto const& doorPath = *std::min_element(doorPaths.begin(), doorPaths.end(),
[summon](std::vector<Position> const& a, std::vector<Position> const& b)
{
return summon->GetExactDistSq(a.front()) < summon->GetExactDistSq(b.front());
});
Movement::PointsArray path;
path.emplace_back(summon->GetPositionX(), summon->GetPositionY(), summon->GetPositionZ());
path.emplace_back(doorPath.front().GetPositionX(), doorPath.front().GetPositionY(),
doorPath.front().GetPositionZ());
PathGenerator pathGenerator(summon);
for (std::size_t i = 1; i < doorPath.size(); ++i)
{
Position const& from = doorPath[i - 1];
Position const& to = doorPath[i];
bool const found = pathGenerator.CalculatePath(from.GetPositionX(), from.GetPositionY(),
from.GetPositionZ(), to.GetPositionX(), to.GetPositionY(), to.GetPositionZ(), false);
if (found && (pathGenerator.GetPathType() & PATHFIND_NORMAL))
path.insert(path.end(), std::next(pathGenerator.GetPath().begin()), pathGenerator.GetPath().end());
else
path.emplace_back(to.GetPositionX(), to.GetPositionY(), to.GetPositionZ());
}
summon->GetMotionMaster()->MoveSplinePath(&path, FORCED_MOVEMENT_RUN);
}
void KilledUnit(Unit* victim) override
{
if (!me->IsAlive() || !victim->HasAura(SPELL_LEECH_POISON))
@@ -610,22 +656,28 @@ class spell_hadronox_summon_periodic_aura : public AuraScript
PrepareAuraScript(spell_hadronox_summon_periodic_aura);
public:
spell_hadronox_summon_periodic_aura(int32 delay, uint32 spellEntry) : _delay(delay), _spellEntry(spellEntry) { }
static constexpr int32 SUMMON_PERIOD = 15'000;
spell_hadronox_summon_periodic_aura(int32 delay, uint32 spellEntry, uint32 lowerDoorSpellEntry) : _delay(delay), _spellEntry(spellEntry), _lowerDoorSpellEntry(lowerDoorSpellEntry) { }
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_WEB_FRONT_DOORS });
return ValidateSpellInfo({ SPELL_WEB_FRONT_DOORS, _spellEntry, _lowerDoorSpellEntry });
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
void HandlePeriodic(AuraEffect const* aurEff)
{
PreventDefaultAction();
// The three auras start 5s apart (see OnApply) and each repeats every 15s, so a door spawns one add per 5s.
// The core re-arms the timer with the DBC amplitude before each tick, so pin the period here.
GetAura()->GetEffect(aurEff->GetEffIndex())->SetPeriodicTimer(SUMMON_PERIOD);
Unit* owner = GetUnitOwner();
if (InstanceScript* instance = owner->GetInstanceScript())
if (!instance->IsBossDone(DATA_HADRONOX) != NOT_STARTED)
{
if (!owner->HasAura(SPELL_WEB_FRONT_DOORS))
owner->CastSpell(owner, _spellEntry, true);
owner->CastSpell(owner, owner->GetDistance(LowerDoorPosition) < 5.0f ? _lowerDoorSpellEntry : _spellEntry, true);
else if (!instance->IsEncounterInProgress())
owner->RemoveAurasDueToSpell(SPELL_WEB_FRONT_DOORS);
}
@@ -645,6 +697,7 @@ public:
private:
int32 _delay;
uint32 _spellEntry;
uint32 _lowerDoorSpellEntry;
};
class spell_hadronox_leech_poison_aura : public AuraScript
@@ -709,9 +762,9 @@ void AddSC_boss_hadronox()
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);
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_champion_aura", 5'000, SPELL_SUMMON_ANUBAR_CHAMPION, SPELL_SUMMON_ANUBAR_CHAMPION_LOWER);
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_necromancer_aura", 10'000, SPELL_SUMMON_ANUBAR_NECROMANCER, SPELL_SUMMON_ANUBAR_NECROMANCER_LOWER);
RegisterSpellScriptWithArgs(spell_hadronox_summon_periodic_aura, "spell_hadronox_summon_periodic_crypt_fiend_aura", 15'000, SPELL_SUMMON_ANUBAR_CRYPT_FIEND, SPELL_SUMMON_ANUBAR_CRYPT_FIEND_LOWER);
RegisterSpellScript(spell_hadronox_leech_poison_aura);
RegisterSpellScript(spell_hadronox_web_grab);
new achievement_hadronox_denied();
@@ -46,12 +46,14 @@ ObjectData const creatureData[] =
ObjectData const summonData[] =
{
{ NPC_SKITTERING_SWARMER, DATA_KRIKTHIR },
{ NPC_SKITTERING_INFECTIOR, DATA_KRIKTHIR },
{ NPC_ANUB_AR_CHAMPION, DATA_HADRONOX },
{ NPC_ANUB_AR_NECROMANCER, DATA_HADRONOX },
{ NPC_ANUB_AR_CRYPTFIEND, DATA_HADRONOX },
{ NPC_WORLD_TRIGGER_LAOI, DATA_HADRONOX },
{ NPC_SKITTERING_SWARMER, DATA_KRIKTHIR },
{ NPC_SKITTERING_INFECTIOR, DATA_KRIKTHIR },
{ NPC_ANUB_AR_CHAMPION, DATA_HADRONOX },
{ NPC_ANUB_AR_NECROMANCER, DATA_HADRONOX },
{ NPC_ANUB_AR_CRYPTFIEND, DATA_HADRONOX },
{ NPC_ANUB_AR_CHAMPION_LOWER, DATA_HADRONOX },
{ NPC_ANUB_AR_CRYPT_FIEND_LOWER, DATA_HADRONOX },
{ NPC_ANUB_AR_NECROMANCER_LOWER, DATA_HADRONOX },
{ 0, 0 }
};