fix(Scripts/MoltenCore): Ragnaros melee retarget on knockback (#25390)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-04-10 04:16:08 -03:00
committed by GitHub
parent d6b292221e
commit dbae4648ba
@@ -80,6 +80,7 @@ enum Events
EVENT_MIGHT_OF_RAGNAROS, EVENT_MIGHT_OF_RAGNAROS,
EVENT_LAVA_BURST, EVENT_LAVA_BURST,
EVENT_MAGMA_BLAST, EVENT_MAGMA_BLAST,
EVENT_MELEE_SCAN,
EVENT_SUBMERGE, EVENT_SUBMERGE,
EVENT_LAVA_BURST_TRIGGER, EVENT_LAVA_BURST_TRIGGER,
@@ -218,29 +219,6 @@ struct boss_ragnaros : public BossAI
DoStartNoMovement(target); DoStartNoMovement(target);
} }
void EnterEvadeMode(EvadeReason why) override
{
if (!me->GetThreatMgr().IsThreatListEmpty())
{
if (!_processingMagmaBurst)
{
// Boss try to evade, but still got some targets on threat list - it means that none of these targets are in melee range - cast magma blast
_processingMagmaBurst = true;
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
}
}
else
{
BossAI::EnterEvadeMode(why);
}
}
bool CanAIAttack(Unit const* victim) const override
{
// Used for Magma Blast handling to force EnterEvadeMode if there are no melee targets
return me->IsWithinMeleeRange(victim);
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!extraEvents.Empty()) if (!extraEvents.Empty())
@@ -307,10 +285,7 @@ struct boss_ragnaros : public BossAI
} }
if (!UpdateVictim()) if (!UpdateVictim())
{
if (!_processingMagmaBurst)
return; return;
}
events.Update(diff); events.Update(diff);
@@ -348,19 +323,47 @@ struct boss_ragnaros : public BossAI
DoCastAOE(SPELL_LAVA_BURST); DoCastAOE(SPELL_LAVA_BURST);
break; break;
} }
case EVENT_MELEE_SCAN:
{
// ReselectVictim() in the threat system already prefers
// in-melee-range targets, so if the current victim is out
// of melee range it means *nobody* is in range. Use that
// as the trigger for the Magma Blast fallback.
if (!IsVictimWithinMeleeRange())
{
if (!_processingMagmaBurst)
{
_processingMagmaBurst = true;
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
}
}
else if (_processingMagmaBurst)
{
events.CancelEvent(EVENT_MAGMA_BLAST);
_processingMagmaBurst = false;
}
events.Repeat(500ms);
break;
}
case EVENT_MAGMA_BLAST: case EVENT_MAGMA_BLAST:
{ {
_processingMagmaBurst = false; _processingMagmaBurst = false;
if (!IsVictimWithinMeleeRange()) if (IsVictimWithinMeleeRange())
break;
if (Unit* victim = me->GetVictim())
{ {
DoCastRandomTarget(SPELL_MAGMA_BLAST); DoCast(victim, SPELL_MAGMA_BLAST);
if (!_hasYelledMagmaBurst) if (!_hasYelledMagmaBurst)
{ {
Talk(SAY_MAGMABURST); Talk(SAY_MAGMABURST);
_hasYelledMagmaBurst = true; _hasYelledMagmaBurst = true;
} }
_processingMagmaBurst = true;
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4s, PHASE_EMERGED, PHASE_EMERGED);
} }
break; break;
@@ -454,12 +457,14 @@ private:
events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED); events.RescheduleEvent(EVENT_LAVA_BURST, 10s, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_SUBMERGE, 180s, PHASE_EMERGED, PHASE_EMERGED); events.RescheduleEvent(EVENT_SUBMERGE, 180s, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_MIGHT_OF_RAGNAROS, 11s, PHASE_EMERGED, PHASE_EMERGED); events.RescheduleEvent(EVENT_MIGHT_OF_RAGNAROS, 11s, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_MELEE_SCAN, 500ms, PHASE_EMERGED, PHASE_EMERGED);
} }
bool IsVictimWithinMeleeRange() const bool IsVictimWithinMeleeRange() const
{ {
return me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim()); return me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim());
} }
}; };
constexpr std::array<uint32, 8> RagnarosLavaBurstSpells = { SPELL_LAVA_BURST_A, SPELL_LAVA_BURST_B, SPELL_LAVA_BURST_C, SPELL_LAVA_BURST_D, SPELL_LAVA_BURST_E, SPELL_LAVA_BURST_F, SPELL_LAVA_BURST_G, SPELL_LAVA_BURST_H }; constexpr std::array<uint32, 8> RagnarosLavaBurstSpells = { SPELL_LAVA_BURST_A, SPELL_LAVA_BURST_B, SPELL_LAVA_BURST_C, SPELL_LAVA_BURST_D, SPELL_LAVA_BURST_E, SPELL_LAVA_BURST_F, SPELL_LAVA_BURST_G, SPELL_LAVA_BURST_H };