From a67cf7e3b800db40b5e7b5540db686b1f905ec83 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Thu, 5 Mar 2026 06:28:31 -0300 Subject: [PATCH] fix(Scripts/Ulduar): port TC Mimiron Magnetic Core handling (#24998) Co-authored-by: Unholychick Co-authored-by: sirikfoll Co-authored-by: Claude Sonnet 4.6 --- .../rev_1772582872453213100.sql | 17 ++ src/server/game/Maps/Map.h | 1 + .../game/Spells/SpellInfoCorrections.cpp | 3 +- .../Northrend/Ulduar/Ulduar/boss_mimiron.cpp | 226 ++++++++---------- 4 files changed, 123 insertions(+), 124 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1772582872453213100.sql diff --git a/data/sql/updates/pending_db_world/rev_1772582872453213100.sql b/data/sql/updates/pending_db_world/rev_1772582872453213100.sql new file mode 100644 index 000000000..6d90da488 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1772582872453213100.sql @@ -0,0 +1,17 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN (64436, 64444); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(64436, 'spell_mimiron_magnetic_core_aura'), +(64444, 'spell_mimiron_magnetic_core_summon'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` = 64436; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 2, 64436, 0, 0, 31, 0, 3, 33670, 0, 0, 0, 0, '', 'Mimiron - Magnetic Core hits Aerial Command Unit only'); + +UPDATE `creature_template` SET `unit_flags` = `unit_flags`&~4 WHERE `entry` IN (33670, 34109); + +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 34068; + +DELETE FROM `smart_scripts` WHERE `entryorguid` = 34068 AND `source_type` = 0; +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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(34068, 0, 0, 1, 25, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mimiron - Magnetic Core - On Reset - Set React State Passive'), +(34068, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 64436, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mimiron - Magnetic Core - Linked - Cast Magnetic Core Triggered'); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 29857eadf..035ba0dce 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -239,6 +239,7 @@ public: // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height [[nodiscard]] float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + [[nodiscard]] float GetHeight(Position const& pos, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), checkVMap, maxSearchDist); } [[nodiscard]] float GetGridHeight(float x, float y) const; [[nodiscard]] float GetMinHeight(float x, float y) const; Transport* GetTransportForPos(uint32 phase, float x, float y, float z, WorldObject* worldobject = nullptr); diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 8553143a5..db178cd07 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -1885,9 +1885,8 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_1].Effect = 0; }); - // Ulduar, Mimiron, Magnetic Core (summon) // Meeting Stone Summon - ApplySpellFix({ 64444, 23598 }, [](SpellInfo* spellInfo) + ApplySpellFix({ 23598 }, [](SpellInfo* spellInfo) { spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_CASTER); }); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index e4c1367f9..8958c9af8 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -62,10 +62,12 @@ enum SpellData SPELL_SPINNING_UP = 63414, // PHASE 3: - SPELL_PLASMA_BALL = 63689, + SPELL_PLASMA_BALL_P1 = 63689, + SPELL_PLASMA_BALL_P2 = 65647, SPELL_MAGNETIC_CORE = 64436, - SPELL_SPINNING = 64438, + SPELL_MAGNETIC_CORE_VISUAL = 64438, + SPELL_MAGNETIC_CORE_SUMMON = 64444, SPELL_SUMMON_BOMB_BOT = 63811, SPELL_BB_EXPLODE = 63801, @@ -194,9 +196,6 @@ enum EVENTS EVENT_BOMB_BOT_RELOCATE = 30, EVENT_SUMMON_ASSAULT_BOT = 40, EVENT_SUMMON_JUNK_BOT = 41, - EVENT_MAGNETIC_CORE_PULL_DOWN = 42, - EVENT_MAGNETIC_CORE_FREE = 43, - EVENT_MAGNETIC_CORE_REMOVE_IMMOBILIZE = 44, // Hard mode: EVENT_COMPUTER_SAY_INITIATED = 60, @@ -212,6 +211,12 @@ enum EVENTS EVENT_EMERGENCY_BOT_ATTACK = 70, }; +enum Actions +{ + DO_DISABLE_AERIAL = 1, + DO_ENABLE_AERIAL, +}; + enum Texts { // Mimiron @@ -255,6 +260,8 @@ enum Texts #define GetVX001() instance->GetCreature(DATA_MIMIRON_VX001) #define GetACU() instance->GetCreature(DATA_MIMIRON_ACU) +Position const ACUSummonPos = { 2742.6265f, 2568.0571f, 377.22076f, 0.0f }; /// @todo: replace with sniffed position + struct boss_mimiron : public BossAI { boss_mimiron(Creature* pCreature) : BossAI(pCreature, BOSS_MIMIRON) @@ -563,12 +570,9 @@ struct boss_mimiron : public BossAI break; case EVENT_GET_OUT_VX001: if (Creature* VX001 = GetVX001()) - if (Creature* ACU = me->SummonCreature(NPC_AERIAL_COMMAND_UNIT, 2743.91f, 2568.78f, 391.34f, M_PI, TEMPSUMMON_MANUAL_DESPAWN)) + if (me->SummonCreature(NPC_AERIAL_COMMAND_UNIT, ACUSummonPos, TEMPSUMMON_MANUAL_DESPAWN)) { me->EnterVehicle(VX001, 4); - float speed = ACU->GetDistance(2737.75f, 2574.22f, 381.34f) / 2.0f; - ACU->GetMotionMaster()->MovePoint(0, 2737.75f, 2574.22f, 381.34f, FORCED_MOVEMENT_NONE, speed); - ACU->SetPosition(2737.75f, 2574.22f, 381.34f, M_PI); events.ScheduleEvent(EVENT_SAY_VX001_DEAD, 2s); break; } @@ -1499,7 +1503,6 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI { instance = me->GetInstanceScript(); bIsEvading = false; - immobilized = false; me->SetDisableGravity(true); } @@ -1508,19 +1511,13 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI SummonList summons; bool bIsEvading; uint8 Phase; - bool immobilized; void Reset() override { Phase = 0; events.Reset(); summons.DespawnAll(); - } - - void AttackStart(Unit* who) override - { - if (who) - me->Attack(who, true); // skip following + me->SetCombatMovement(false); /// @todo: research ACU behaviour } void SetData(uint32 id, uint32 value) override @@ -1532,16 +1529,12 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI case 0: Phase = 0; events.Reset(); - immobilized = false; break; case 3: Phase = 3; me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - if (Unit* target = SelectTargetFromPlayerList(75.0f)) - AttackStart(target); DoZoneInCombat(); events.Reset(); - events.ScheduleEvent(EVENT_SPELL_PLASMA_BALL, 0ms); events.ScheduleEvent(EVENT_SUMMON_BOMB_BOT, 15s); events.ScheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 1s); events.ScheduleEvent(EVENT_SUMMON_JUNK_BOT, 10s); @@ -1561,17 +1554,31 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI events.ScheduleEvent(EVENT_SPELL_PLASMA_BALL, 0ms); } } - else if (id == 2 && !immobilized && Phase == 3) // magnetic core - { - immobilized = true; - events.ScheduleEvent(EVENT_MAGNETIC_CORE_PULL_DOWN, 2s); - } } void DoAction(int32 param) override { - if (param == 1337) - summons.DespawnAll(); + switch (param) + { + case DO_DISABLE_AERIAL: + me->CastStop(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetDisableGravity(false); + me->GetMotionMaster()->MoveFall(); + events.DelayEvents(25s); + break; + case DO_ENABLE_AERIAL: + me->SetDisableGravity(true); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f); + me->m_Events.AddEventAtOffset([&] { + me->SetReactState(REACT_AGGRESSIVE); + }, 2s); + break; + case 1337: + summons.DespawnAll(); + break; + } } void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override @@ -1624,42 +1631,11 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) || me->HasAura(SPELL_MAGNETIC_CORE)) return; - // following :D - if (Phase == 3 && !immobilized) - if (Unit* victim = me->GetVictim()) - if (me->GetExactDist2d(victim) > 25.0f ) - { - float angle = victim->GetAngle(me->GetPositionX(), me->GetPositionY()); - me->SetOrientation( me->GetAngle(victim->GetPositionX(), victim->GetPositionY())); - float x = victim->GetPositionX() + 15.0f * cos(angle); - float y = victim->GetPositionY() + 15.0f * std::sin(angle); - - // check if there's magnetic core in line of movement - Creature* mc = nullptr; - std::list cl; - me->GetCreaturesWithEntryInRange(cl, me->GetExactDist2d(victim), NPC_MAGNETIC_CORE); - for( std::list::iterator itr = cl.begin(); itr != cl.end(); ++itr ) - { - if ((*itr)->IsInBetween(me, victim, 4.0f) && (*itr)->GetExactDist2d(victim) >= 10.0f) // don't come very close just because there's a magnetic core - { - x = (*itr)->GetPositionX(); - y = (*itr)->GetPositionY(); - mc = (*itr); - break; - } - } - - float speed = me->GetExactDist(x, y, 381.34f); - me->GetMotionMaster()->MovePoint(0, x, y, 381.34f, FORCED_MOVEMENT_NONE, speed); - if (mc) - { - mc->AI()->SetData(0, 0); - SetData(2, 1); - } - } + if (!UpdateVictim()) + return; events.Update(diff); @@ -1670,14 +1646,8 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI { case 0: break; - case EVENT_SPELL_PLASMA_BALL: - if (!immobilized) - DoCastVictim(SPELL_PLASMA_BALL); - events.Repeat(3s); - break; case EVENT_SUMMON_BOMB_BOT: - if (!immobilized) - me->CastSpell(me, SPELL_SUMMON_BOMB_BOT, false); + me->CastSpell(me, SPELL_SUMMON_BOMB_BOT, false); events.Repeat(15s); break; case EVENT_SUMMON_ASSAULT_BOT: @@ -1702,21 +1672,9 @@ struct npc_ulduar_aerial_command_unit : public ScriptedAI events.Repeat(45s); } break; - case EVENT_MAGNETIC_CORE_PULL_DOWN: - me->CastSpell(me, SPELL_MAGNETIC_CORE, true); - me->CastSpell(me, SPELL_SPINNING, true); - me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), 365.34f, FORCED_MOVEMENT_NONE, me->GetExactDist(me->GetPositionX(), me->GetPositionY(), 365.34f)); - events.ScheduleEvent(EVENT_MAGNETIC_CORE_FREE, 20s); - break; - case EVENT_MAGNETIC_CORE_FREE: - me->RemoveAura(SPELL_SPINNING); - me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), 381.34f, FORCED_MOVEMENT_NONE, me->GetDistance(me->GetPositionX(), me->GetPositionY(), 381.34f)); - events.ScheduleEvent(EVENT_MAGNETIC_CORE_REMOVE_IMMOBILIZE, 1s); - break; - case EVENT_MAGNETIC_CORE_REMOVE_IMMOBILIZE: - immobilized = false; - break; } + + DoSpellAttackIfReady(Phase == 3 ? SPELL_PLASMA_BALL_P1 : SPELL_PLASMA_BALL_P2); } void MoveInLineOfSight(Unit* /*mover*/) override {} @@ -1871,44 +1829,6 @@ struct npc_ulduar_mimiron_rocket : public NullCreatureAI } }; -struct npc_ulduar_magnetic_core : public NullCreatureAI -{ - npc_ulduar_magnetic_core(Creature* pCreature) : NullCreatureAI(pCreature) - { - instance = me->GetInstanceScript(); - if (Creature* c = GetACU()) - if (c->GetExactDist2d(me) <= 10.0f) - { - me->SendMonsterMove(c->GetPositionX(), c->GetPositionY(), 364.313f, 1); - me->UpdatePosition(c->GetPositionX(), c->GetPositionY(), 364.313f, me->GetOrientation(), true); - me->StopMovingOnCurrentPos(); - c->AI()->SetData(2, 1); - despawnTimer = 20000; - return; - } - despawnTimer = 60000; - } - - InstanceScript* instance; - uint16 despawnTimer; - - void SetData(uint32 /*id*/, uint32 /*value*/) override - { - despawnTimer = 20000; - } - - void UpdateAI(uint32 diff) override - { - if (despawnTimer <= diff) - { - despawnTimer = 60000; - me->DespawnOrUnsummon(1ms); - } - else - despawnTimer -= diff; - } -}; - struct npc_ulduar_bot_summon_trigger : public NullCreatureAI { npc_ulduar_bot_summon_trigger(Creature* pCreature) : NullCreatureAI(pCreature) { } @@ -1965,6 +1885,67 @@ struct npc_ulduar_bot_summon_trigger : public NullCreatureAI } }; +// 64444 - Magnetic Core Summon +class spell_mimiron_magnetic_core_summon : public SpellScript +{ + PrepareSpellScript(spell_mimiron_magnetic_core_summon); + + void ModDest(SpellDestination& dest) + { + Unit* caster = GetCaster(); + Position pos = caster->GetPosition(); + pos.m_positionZ = caster->GetMap()->GetHeight(pos); + dest.Relocate(pos); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_mimiron_magnetic_core_summon::ModDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + } +}; + +// 64436 - Magnetic Core (aura) +class spell_mimiron_magnetic_core_aura : public AuraScript +{ + PrepareAuraScript(spell_mimiron_magnetic_core_aura); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_MAGNETIC_CORE_VISUAL }); + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + { + target->AI()->DoAction(DO_DISABLE_AERIAL); + target->CastSpell(target, SPELL_MAGNETIC_CORE_VISUAL, true); + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + { + target->AI()->DoAction(DO_ENABLE_AERIAL); + target->RemoveAurasDueToSpell(SPELL_MAGNETIC_CORE_VISUAL); + } + } + + void OnRemoveSelf(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (TempSummon* summ = GetTarget()->ToTempSummon()) + summ->DespawnOrUnsummon(); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_mimiron_magnetic_core_aura::OnApply, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_mimiron_magnetic_core_aura::OnRemove, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_mimiron_magnetic_core_aura::OnRemoveSelf, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + class spell_mimiron_rapid_burst_aura : public AuraScript { PrepareAuraScript(spell_mimiron_rapid_burst_aura); @@ -2325,8 +2306,9 @@ void AddSC_boss_mimiron() RegisterUlduarCreatureAI(npc_ulduar_proximity_mine); RegisterUlduarCreatureAI(npc_ulduar_mimiron_rocket); - RegisterUlduarCreatureAI(npc_ulduar_magnetic_core); RegisterUlduarCreatureAI(npc_ulduar_bot_summon_trigger); + RegisterSpellScript(spell_mimiron_magnetic_core_summon); + RegisterSpellScript(spell_mimiron_magnetic_core_aura); RegisterSpellScript(spell_mimiron_rapid_burst_aura); RegisterSpellScript(spell_mimiron_p3wx2_laser_barrage_aura); RegisterSpellScript(spell_ulduar_mimiron_mine_explosion);