mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
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:
@@ -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');
|
||||||
@@ -16,9 +16,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AchievementCriteriaScript.h"
|
#include "AchievementCriteriaScript.h"
|
||||||
|
#include "Containers.h"
|
||||||
#include "CreatureScript.h"
|
#include "CreatureScript.h"
|
||||||
#include "GameObjectScript.h"
|
#include "GameObjectScript.h"
|
||||||
#include "GameTime.h"
|
#include "GameTime.h"
|
||||||
|
#include "GridNotifiers.h"
|
||||||
#include "MapMgr.h"
|
#include "MapMgr.h"
|
||||||
#include "PassiveAI.h"
|
#include "PassiveAI.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
@@ -54,6 +56,10 @@ enum SpellData
|
|||||||
SPELL_HEAT_WAVE = 64533,
|
SPELL_HEAT_WAVE = 64533,
|
||||||
|
|
||||||
SPELL_ROCKET_STRIKE_AURA = 64064,
|
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_VISUAL = 34050,
|
||||||
NPC_ROCKET_STRIKE_N = 34047,
|
NPC_ROCKET_STRIKE_N = 34047,
|
||||||
|
|
||||||
@@ -1342,38 +1348,19 @@ struct npc_ulduar_vx001 : public ScriptedAI
|
|||||||
_events.Repeat(10s);
|
_events.Repeat(10s);
|
||||||
break;
|
break;
|
||||||
case EVENT_SPELL_ROCKET_STRIKE:
|
case EVENT_SPELL_ROCKET_STRIKE:
|
||||||
if (Vehicle* vk = me->GetVehicleKit())
|
me->CastSpell(me, _phase == 2 ? SPELL_ROCKET_STRIKE_SINGLE : SPELL_ROCKET_STRIKE_BOTH, true);
|
||||||
{
|
_events.Repeat(20s);
|
||||||
for( int i = 0; i < (_phase / 2); ++i )
|
_events.ScheduleEvent(EVENT_REINSTALL_ROCKETS, 10s);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case EVENT_REINSTALL_ROCKETS:
|
case EVENT_REINSTALL_ROCKETS:
|
||||||
if (Vehicle* vk = me->GetVehicleKit())
|
if (Vehicle* vk = me->GetVehicleKit())
|
||||||
{
|
{
|
||||||
for (uint8 i = 5; i <= 6; ++i)
|
for (uint8 i = 5; i <= 6; ++i)
|
||||||
if (!vk->GetPassenger(i))
|
if (Unit* rocket = vk->GetPassenger(i))
|
||||||
if (TempSummon* accessory = me->SummonCreature(NPC_ROCKET_VISUAL, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 4.0f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN))
|
rocket->SetDisplayId(rocket->GetNativeDisplayId()); // restore the fired rocket's visual
|
||||||
if (!me->HandleSpellClick(accessory, i))
|
else if (TempSummon* accessory = me->SummonCreature(NPC_ROCKET_VISUAL, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 4.0f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN))
|
||||||
accessory->UnSummon();
|
if (!me->HandleSpellClick(accessory, i))
|
||||||
|
accessory->UnSummon();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_SPELL_RAPID_BURST:
|
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
|
struct npc_ulduar_mimiron_rocket : public NullCreatureAI
|
||||||
{
|
{
|
||||||
npc_ulduar_mimiron_rocket(Creature* creature) : NullCreatureAI(creature) {}
|
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) {}
|
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
|
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||||
{
|
{
|
||||||
if (!target || !spell)
|
if (!target || !spell)
|
||||||
@@ -2340,6 +2402,8 @@ void AddSC_boss_mimiron()
|
|||||||
RegisterSpellScript(spell_mimiron_rapid_burst_aura);
|
RegisterSpellScript(spell_mimiron_rapid_burst_aura);
|
||||||
RegisterSpellScript(spell_mimiron_p3wx2_laser_barrage_aura);
|
RegisterSpellScript(spell_mimiron_p3wx2_laser_barrage_aura);
|
||||||
RegisterSpellScript(spell_ulduar_mimiron_mine_explosion);
|
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();
|
new go_ulduar_do_not_push_this_button();
|
||||||
RegisterUlduarCreatureAI(npc_ulduar_flames_initial);
|
RegisterUlduarCreatureAI(npc_ulduar_flames_initial);
|
||||||
RegisterUlduarCreatureAI(npc_ulduar_flames_spread);
|
RegisterUlduarCreatureAI(npc_ulduar_flames_spread);
|
||||||
|
|||||||
Reference in New Issue
Block a user