retarget conditional, fix defer frame to use polling approach

This commit is contained in:
Jrc13245
2026-03-06 20:36:24 -05:00
parent 720246e473
commit aca7b2af3b
2 changed files with 92 additions and 10 deletions
+91 -10
View File
@@ -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