From ceaf7c2c43fc5ca594779433e00cd5d6f55d73ed Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Mon, 22 Jun 2026 12:58:59 -0500 Subject: [PATCH] Refresh [moving] macro icons on movement via ClassicAPI Register PLAYER_STARTED_MOVING (ClassicAPI, edge-detected off the WASD/ autorun key state) and queue an action update so [moving]/[nomoving] macro icons repaint when movement starts. PLAYER_STOPPED_MOVING is deliberately NOT used -- it's key-release based and misses real stops (running into geometry, click-to-move, roots, knockback). Instead, STARTED kicks off a 0.1s C_Timer.NewTicker that watches IsPlayerMoving() (the same speed>0/falling signal [moving] evaluates) and, on the actual stop, refreshes once and cancels itself. No timer exists while stopped, so there's no idle cost; guarded on isShuttingDown and event-driven mode (realtime==0). --- Core.lua | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Core.lua b/Core.lua index 43f22b8..4c2bdec 100644 --- a/Core.lua +++ b/Core.lua @@ -5088,6 +5088,15 @@ CleveRoids.Frame:RegisterEvent("PLAYER_REGEN_DISABLED") -- Entered actual combat CleveRoids.Frame:RegisterEvent("PLAYER_REGEN_ENABLED") -- Left actual combat (no threat) CleveRoids.Frame:RegisterEvent("UPDATE_SHAPESHIFT_FORM") CleveRoids.Frame:RegisterEvent("SPELL_UPDATE_COOLDOWN") +-- ClassicAPI fires PLAYER_STARTED_MOVING (edge-detected off the WASD/autorun +-- key state). We DON'T trust PLAYER_STOPPED_MOVING -- it's key-release based and +-- misses real stops (geometry, click-to-move, roots, knockback) -- and instead +-- poll for the actual stop after STARTED (see the handler below). pcall-guarded: +-- older ClassicAPI builds may not have reserved the event name, and +-- RegisterEvent errors on an unknown event in 1.12. +pcall(function() + CleveRoids.Frame:RegisterEvent("PLAYER_STARTED_MOVING") +end) -- Use GUID events when available (v2.39+), fall back to standard per-token events if CleveRoids.NampowerAPI.features.hasUnitGuidEvents then CleveRoids.Frame:RegisterEvent("UNIT_AURA_GUID") @@ -5804,6 +5813,48 @@ function CleveRoids.Frame:PLAYER_REGEN_ENABLED() end end +-- Movement -> [moving]/[nomoving] icon refresh. +-- PLAYER_STARTED_MOVING is reliable; PLAYER_STOPPED_MOVING is not (key-release +-- based, misses geometry/click-to-move/root/knockback stops). So STARTED flips +-- the icon to "moving" and starts a bounded poll; the poll detects the real +-- stop from IsPlayerMoving() (the signal [moving] uses), refreshes once, and +-- shuts itself off. Only runs while actually moving, so no idle cost. +local MOVE_POLL_INTERVAL = 0.1 +local moveTicker = nil + +local function StopMovePoll() + if moveTicker then + moveTicker:Cancel() + moveTicker = nil + end +end + +local function StartMovePoll() + if moveTicker then return end -- already polling this movement + moveTicker = C_Timer.NewTicker(MOVE_POLL_INTERVAL, function() + if CleveRoids.isShuttingDown then + StopMovePoll() + return + end + if not CleveRoids.IsPlayerMoving() then + -- Movement actually ended -- repaint [moving]/[nomoving] icons, stop polling. + StopMovePoll() + if CleveRoidMacros.realtime == 0 then + CleveRoids.QueueActionUpdate() + end + end + end) +end + +function CleveRoids.Frame:PLAYER_STARTED_MOVING() + -- Started moving: flip to the [moving] icon now... + if CleveRoidMacros.realtime == 0 then + CleveRoids.QueueActionUpdate() + end + -- ...and watch for the (unreliable-event) stop ourselves. + StartMovePoll() +end + function CleveRoids.Frame:PLAYER_TARGET_CHANGED() CleveRoids.CurrentSpell.autoAttack = false CleveRoids.CurrentSpell.autoAttackLock = false