fix(Scripts/Ulduar): Mimiron Rocket Strike prefers ranged players (#26685)

Co-authored-by: Unholychick <lucas__jensen@hotmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-07-19 08:37:12 -03:00
committed by GitHub
parent f839009e9a
commit 37ac84e71b
2 changed files with 97 additions and 27 deletions

View File

@@ -0,0 +1,6 @@
-- Mimiron Rocket Strike: spell-driven target selection (prefers ranged players)
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_mimiron_rocket_strike', 'spell_mimiron_rocket_strike_target_select');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(64402, 'spell_mimiron_rocket_strike'),
(65034, 'spell_mimiron_rocket_strike'),
(63681, 'spell_mimiron_rocket_strike_target_select');

View File

@@ -16,9 +16,11 @@
*/
#include "AchievementCriteriaScript.h"
#include "Containers.h"
#include "CreatureScript.h"
#include "GameObjectScript.h"
#include "GameTime.h"
#include "GridNotifiers.h"
#include "MapMgr.h"
#include "PassiveAI.h"
#include "Player.h"
@@ -54,6 +56,10 @@ enum SpellData
SPELL_HEAT_WAVE = 64533,
SPELL_ROCKET_STRIKE_AURA = 64064,
SPELL_ROCKET_STRIKE_SINGLE = 64402, // VX-001 fires one of the two mounted rockets
SPELL_ROCKET_STRIKE_BOTH = 65034, // VX-001 fires both mounted rockets
SPELL_ROCKET_STRIKE_TARGET = 63681, // Cast by a fired rocket; picks the impact target (prefers ranged)
SPELL_SUMMON_ROCKET_STRIKE = 63036, // Summons the ground strike at the chosen target
NPC_ROCKET_VISUAL = 34050,
NPC_ROCKET_STRIKE_N = 34047,
@@ -1342,38 +1348,19 @@ struct npc_ulduar_vx001 : public ScriptedAI
_events.Repeat(10s);
break;
case EVENT_SPELL_ROCKET_STRIKE:
if (Vehicle* vk = me->GetVehicleKit())
{
for( int i = 0; i < (_phase / 2); ++i )
{
uint8 index = (_phase == 2 ? rand() % 2 : i);
if (Unit* r = vk->GetPassenger(5 + index))
if (Player* temp = SelectTargetFromPlayerList(100.0f))
{
if (Creature* trigger = me->SummonCreature(NPC_ROCKET_STRIKE_N, temp->GetPositionX(), temp->GetPositionY(), temp->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 6000))
trigger->CastSpell(trigger, SPELL_ROCKET_STRIKE_AURA, true);
Position exitPos = r->GetPosition();
exitPos.m_positionX += cos(me->GetOrientation()) * 2.35f;
exitPos.m_positionY += std::sin(me->GetOrientation()) * 2.35f;
exitPos.m_positionZ += 2.0f * _phase;
r->_ExitVehicle(&exitPos);
me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, r->GetGUID());
if (r->IsCreature())
r->ToCreature()->AI()->SetData(0, 0);
}
}
_events.Repeat(20s);
_events.ScheduleEvent(EVENT_REINSTALL_ROCKETS, 10s);
}
me->CastSpell(me, _phase == 2 ? SPELL_ROCKET_STRIKE_SINGLE : SPELL_ROCKET_STRIKE_BOTH, true);
_events.Repeat(20s);
_events.ScheduleEvent(EVENT_REINSTALL_ROCKETS, 10s);
break;
case EVENT_REINSTALL_ROCKETS:
if (Vehicle* vk = me->GetVehicleKit())
{
for (uint8 i = 5; i <= 6; ++i)
if (!vk->GetPassenger(i))
if (TempSummon* accessory = me->SummonCreature(NPC_ROCKET_VISUAL, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 4.0f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN))
if (!me->HandleSpellClick(accessory, i))
accessory->UnSummon();
if (Unit* rocket = vk->GetPassenger(i))
rocket->SetDisplayId(rocket->GetNativeDisplayId()); // restore the fired rocket's visual
else if (TempSummon* accessory = me->SummonCreature(NPC_ROCKET_VISUAL, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 4.0f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN))
if (!me->HandleSpellClick(accessory, i))
accessory->UnSummon();
}
break;
case EVENT_SPELL_RAPID_BURST:
@@ -1822,6 +1809,75 @@ class spell_ulduar_mimiron_mine_explosion : public SpellScript
}
};
// 64402, 65034 - Rocket Strike
class spell_mimiron_rocket_strike : public SpellScript
{
PrepareSpellScript(spell_mimiron_rocket_strike);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
// The single-rocket cast picks just one of the two mounted rockets; the "both" cast keeps both.
if (GetSpellInfo()->Id == SPELL_ROCKET_STRIKE_SINGLE && GetCaster()->IsVehicle())
if (Unit* rocket = GetCaster()->GetVehicleKit()->GetPassenger(urand(5, 6)))
{
targets.clear();
targets.push_back(rocket);
}
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
// The fired rocket resolves its own impact target, keeping VX-001 as the original caster for credit.
GetHitUnit()->CastSpell((Unit*)nullptr, SPELL_ROCKET_STRIKE_TARGET, TRIGGERED_FULL_MASK, nullptr, nullptr, GetCaster()->GetGUID());
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_rocket_strike::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 63681 - Rocket Strike
class spell_mimiron_rocket_strike_target_select : public SpellScript
{
PrepareSpellScript(spell_mimiron_rocket_strike_target_select);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if([](WorldObject* target) { return !target->IsPlayer(); });
if (targets.empty())
return;
WorldObject* target = Acore::Containers::SelectRandomContainerElement(targets);
// Prefer players out of melee range; only strike someone within 15y if nobody is further out (patch 3.1.3).
targets.remove_if(Acore::AllWorldObjectsInRange(GetCaster(), 15.0f));
if (!targets.empty())
target = Acore::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
ObjectGuid originalCaster = GetOriginalCaster() ? GetOriginalCaster()->GetGUID() : GetCaster()->GetGUID();
GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ROCKET_STRIKE, TRIGGERED_FULL_MASK, nullptr, nullptr, originalCaster);
GetCaster()->SetDisplayId(11686); // hide the spent rocket until it is reloaded
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_rocket_strike_target_select::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_target_select::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
struct npc_ulduar_mimiron_rocket : public NullCreatureAI
{
npc_ulduar_mimiron_rocket(Creature* creature) : NullCreatureAI(creature) {}
@@ -2265,6 +2321,12 @@ struct npc_ulduar_rocket_strike_trigger : public NullCreatureAI
{
npc_ulduar_rocket_strike_trigger(Creature* creature) : NullCreatureAI(creature) {}
void InitializeAI() override
{
me->CastSpell(me, SPELL_ROCKET_STRIKE_AURA, true);
me->DespawnOrUnsummon(6s);
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
if (!target || !spell)
@@ -2340,6 +2402,8 @@ void AddSC_boss_mimiron()
RegisterSpellScript(spell_mimiron_rapid_burst_aura);
RegisterSpellScript(spell_mimiron_p3wx2_laser_barrage_aura);
RegisterSpellScript(spell_ulduar_mimiron_mine_explosion);
RegisterSpellScript(spell_mimiron_rocket_strike);
RegisterSpellScript(spell_mimiron_rocket_strike_target_select);
new go_ulduar_do_not_push_this_button();
RegisterUlduarCreatureAI(npc_ulduar_flames_initial);
RegisterUlduarCreatureAI(npc_ulduar_flames_spread);