mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
retarget conditional, fix defer frame to use polling approach
This commit is contained in:
@@ -69,30 +69,91 @@ local string_gsub = string.gsub
|
||||
local table_insert = table.insert
|
||||
local table_getn = table.getn
|
||||
|
||||
-- Deferred stop-attack/clear-target frame
|
||||
-- Deferred stop-attack/clear-target/retarget frame
|
||||
-- CastSpellByName starts autoattack as a C++ side-effect that doesn't settle
|
||||
-- in the same Lua frame. Deferring to the next OnUpdate ensures AttackTarget()
|
||||
-- toggle catches the active attack state (same approach as CheapShot addon).
|
||||
-- Multiple frames are used to verify auto-attack is actually stopped.
|
||||
local _DeferStopFrame = CreateFrame("Frame")
|
||||
_DeferStopFrame:Hide()
|
||||
local _deferStopAttack = false
|
||||
local _deferClearTarget = false
|
||||
local _deferRetarget = false
|
||||
local _deferStartTime = 0
|
||||
local _deferPhase = 0 -- 0=stop+clear, 1=retarget, 2=verify
|
||||
local DEFER_TIMEOUT = 0.5
|
||||
|
||||
_DeferStopFrame:SetScript("OnUpdate", function()
|
||||
_DeferStopFrame:Hide()
|
||||
if _deferStopAttack then
|
||||
_deferStopAttack = false
|
||||
if _deferPhase == 0 then
|
||||
-- Phase 0 (first frame): Toggle off auto-attack + clear target
|
||||
if _deferStopAttack and UnitExists("target") then
|
||||
AttackTarget() -- Toggle off while target still exists
|
||||
end
|
||||
-- ClearTarget immediately prevents any in-flight melee swing from landing
|
||||
ClearTarget()
|
||||
|
||||
-- If only cleartarget (no stopattack, no retarget), we're done
|
||||
if not _deferStopAttack and not _deferRetarget then
|
||||
_deferClearTarget = false
|
||||
_deferPhase = 0
|
||||
_DeferStopFrame:Hide()
|
||||
return
|
||||
end
|
||||
_deferPhase = 1
|
||||
return
|
||||
end
|
||||
|
||||
if _deferPhase == 1 then
|
||||
-- Phase 1: Retarget after ClearTarget + AttackTarget have had a frame to settle
|
||||
if _deferRetarget then
|
||||
TargetNearestEnemy()
|
||||
elseif not _deferClearTarget then
|
||||
-- stopattack alone: retarget back to same target
|
||||
TargetLastTarget()
|
||||
end
|
||||
-- cleartarget without retarget: leave cleared (no action needed)
|
||||
|
||||
-- If no stopattack, we're done after retarget
|
||||
if not _deferStopAttack then
|
||||
_deferClearTarget = false
|
||||
_deferRetarget = false
|
||||
_deferPhase = 0
|
||||
_DeferStopFrame:Hide()
|
||||
return
|
||||
end
|
||||
_deferPhase = 2
|
||||
return
|
||||
end
|
||||
|
||||
-- Phase 2: Verify auto-attack is stopped (poll until confirmed or timeout)
|
||||
local slot = CleveRoids.GetProxyActionSlot(CleveRoids.Localized.Attack)
|
||||
local stillAttacking = slot and CleveRoids.Hooks.IsCurrentAction(slot)
|
||||
|
||||
if stillAttacking then
|
||||
-- Auto-attack still active — toggle off and clear target as safety
|
||||
AttackTarget()
|
||||
CleveRoids.CurrentSpell.autoAttack = false
|
||||
if UnitExists("target") then
|
||||
AttackTarget()
|
||||
if not _deferClearTarget then
|
||||
ClearTarget()
|
||||
ClearTarget()
|
||||
-- Will re-retarget on completion
|
||||
end
|
||||
end
|
||||
|
||||
-- Done when confirmed stopped or timeout reached
|
||||
if not stillAttacking or (GetTime() - _deferStartTime) >= DEFER_TIMEOUT then
|
||||
-- Final retarget if we had to re-clear during verification
|
||||
if not UnitExists("target") then
|
||||
if _deferRetarget then
|
||||
TargetNearestEnemy()
|
||||
elseif not _deferClearTarget then
|
||||
TargetLastTarget()
|
||||
end
|
||||
end
|
||||
end
|
||||
if _deferClearTarget then
|
||||
_deferStopAttack = false
|
||||
_deferClearTarget = false
|
||||
ClearTarget()
|
||||
_deferRetarget = false
|
||||
_deferPhase = 0
|
||||
_DeferStopFrame:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -100,11 +161,24 @@ function CleveRoids.DeferStopAttack()
|
||||
CleveRoids.CurrentSpell.autoAttack = false
|
||||
CleveRoids.CurrentSpell.autoAttackLock = false
|
||||
_deferStopAttack = true
|
||||
_deferPhase = 0
|
||||
_deferStartTime = GetTime()
|
||||
_DeferStopFrame:Show()
|
||||
end
|
||||
|
||||
function CleveRoids.DeferClearTarget()
|
||||
_deferClearTarget = true
|
||||
if _deferPhase == 0 then
|
||||
_deferStartTime = GetTime()
|
||||
end
|
||||
_DeferStopFrame:Show()
|
||||
end
|
||||
|
||||
function CleveRoids.DeferRetarget()
|
||||
_deferRetarget = true
|
||||
if _deferPhase == 0 then
|
||||
_deferStartTime = GetTime()
|
||||
end
|
||||
_DeferStopFrame:Show()
|
||||
end
|
||||
|
||||
@@ -139,6 +213,7 @@ local BOOLEAN_CONDITIONALS = {
|
||||
nomoving = true,
|
||||
stopattack = true,
|
||||
cleartarget = true,
|
||||
retarget = true,
|
||||
}
|
||||
|
||||
local requirementCheckFrame = CreateFrame("Frame")
|
||||
@@ -2628,6 +2703,12 @@ function CleveRoids.DoWithConditionals(msg, hook, fixEmptyTargetFunc, targetBefo
|
||||
CleveRoids.DeferClearTarget()
|
||||
end
|
||||
|
||||
-- [retarget] modifier: clear target and target nearest enemy after cast
|
||||
-- Deferred to next frame alongside stopattack/cleartarget.
|
||||
if conditionals.retarget then
|
||||
CleveRoids.DeferRetarget()
|
||||
end
|
||||
|
||||
conditionals.target = origTarget
|
||||
return result
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user