make supermacro compatibility work with new slashcommands

This commit is contained in:
Jrc13245
2026-01-22 17:46:03 -05:00
parent 36f79938cf
commit cbbc4cc5a7
18 changed files with 136 additions and 12 deletions
+26 -5
View File
@@ -63,14 +63,35 @@ do
CRM.Hooks.RunLine = CRM.Hooks.RunLine or orig_RunLine
_G.RunLine = function(...)
-- Check macro stop flags before processing any line
if CRM.stopMacroFlag or CRM.skipMacroFlag then
return true -- Skip this line, tell SM we handled it
end
-- SuperMacro calls RunLine(line) one line at a time; handle first arg.
local text = arg and arg[1]
-- IMPORTANT: Check for /nofirstaction BEFORE the stop flag check
-- This allows /nofirstaction to clear the stopMacroFlag set by /firstaction
if type(text) == "string" then
local _, _, nofirstactionArgs = string.find(text, "^%s*/nofirstaction%s*(.*)")
if nofirstactionArgs then
-- Capture stopOnCastFlag BEFORE DoNoFirstAction clears it
local wasFirstActionActive = CRM.stopOnCastFlag
if type(CleveRoids.DoNoFirstAction) == "function" then
pcall(CleveRoids.DoNoFirstAction, nofirstactionArgs or "")
end
-- Also clear stopMacroFlag if it was set by firstaction mechanism
if wasFirstActionActive and CRM.stopMacroFlag then
CRM.stopMacroFlag = false
end
return true -- We handled it
end
end
-- Check macro stop flags before processing any line
-- (but /nofirstaction was already handled above)
if CRM.stopMacroFlag or CRM.skipMacroFlag then
-- If stopOnCastFlag is true, this is firstaction mode - skip but continue
-- If stopOnCastFlag is false, this is /stopmacro - skip the line
return true -- Skip this line, tell SM we handled it
end
if type(text) == "string" then
-- 1) special-case /castsequence → call CRM directly and RETURN TRUE
local b, e, rest = string.find(text, "^%s*/castsequence%s*(.*)")
+35 -3
View File
@@ -1471,15 +1471,47 @@ function CleveRoids.CheckChanneled(channeledSpell)
-- Special cases for auto-attacks
if channeled == CleveRoids.Localized.Attack then
return not CleveRoids.CurrentSpell.autoAttack
-- Check event-based tracking first
if CleveRoids.CurrentSpell.autoAttack then
return false
end
-- Fallback: check action bar state for more reliable detection
local slot = CleveRoids.GetProxyActionSlot(CleveRoids.Localized.Attack)
if slot and IsCurrentAction(slot) then
CleveRoids.CurrentSpell.autoAttack = true
return false
end
return true
end
if channeled == CleveRoids.Localized.AutoShot then
return not CleveRoids.CurrentSpell.autoShot
-- Check event-based tracking first (most common)
if CleveRoids.CurrentSpell.autoShot then
return false
end
-- Fallback: check action bar state via IsAutoRepeatAction for more reliable detection
-- This catches cases where the event hasn't fired yet due to timing
local slot = CleveRoids.GetProxyActionSlot(CleveRoids.Localized.AutoShot)
if slot and IsAutoRepeatAction(slot) then
-- Sync the event-based flag for consistency
CleveRoids.CurrentSpell.autoShot = true
return false
end
return true
end
if channeled == CleveRoids.Localized.Shoot then
return not CleveRoids.CurrentSpell.wand
-- Check event-based tracking first
if CleveRoids.CurrentSpell.wand then
return false
end
-- Fallback: check action bar state for more reliable detection
local slot = CleveRoids.GetProxyActionSlot(CleveRoids.Localized.Shoot)
if slot and IsAutoRepeatAction(slot) then
CleveRoids.CurrentSpell.wand = true
return false
end
return true
end
-- If none of the special cases matched, allow the cast (not channeling the specified spell)
+11 -1
View File
@@ -86,7 +86,17 @@ end
-- This ensures we have a fallback for non-conditional use.
local StartAttack = function(msg)
if not UnitExists("target") or UnitIsDead("target") then TargetNearestEnemy() end
if not CleveRoids.CurrentSpell.autoAttack and not CleveRoids.CurrentSpell.autoAttackLock and UnitExists("target") and UnitCanAttack("player","target") then
-- Check both event-based flag AND action bar state for reliable detection
local isAttacking = CleveRoids.CurrentSpell.autoAttack
if not isAttacking then
-- Fallback: check action bar state via IsCurrentAction
local slot = CleveRoids.GetProxyActionSlot(CleveRoids.Localized.Attack)
if slot and IsCurrentAction(slot) then
CleveRoids.CurrentSpell.autoAttack = true
isAttacking = true
end
end
if not isAttacking and not CleveRoids.CurrentSpell.autoAttackLock and UnitExists("target") and UnitCanAttack("player","target") then
CleveRoids.CurrentSpell.autoAttackLock = true
CleveRoids.autoAttackLockElapsed = GetTime()
AttackTarget()
+17 -3
View File
@@ -2384,8 +2384,12 @@ function CleveRoids.DoWithConditionals(msg, hook, fixEmptyTargetFunc, targetBefo
end
end
if action == CastSpellByName then
-- Let Nampower DLL handle queuing natively via its CastSpellByName hook
if CleveRoids.hasSuperwow and conditionals.target then
-- Special case: !Attack should use AttackTarget() which doesn't toggle
-- This is more reliable than CastSpellByName("Attack") which toggles on/off
if msg == CleveRoids.Localized.Attack and conditionals.checkchanneled then
AttackTarget()
elseif CleveRoids.hasSuperwow and conditionals.target then
-- Let Nampower DLL handle queuing natively via its CastSpellByName hook
CastSpellByName(castMsg, conditionals.target)
else
CastSpellByName(castMsg)
@@ -2668,7 +2672,17 @@ end
-- PERFORMANCE: Module-level action to avoid closure allocation per call
local function _startAttackAction()
if not UnitExists("target") or UnitIsDead("target") then TargetNearestEnemy() end
if not CleveRoids.CurrentSpell.autoAttack and not CleveRoids.CurrentSpell.autoAttackLock and UnitExists("target") and UnitCanAttack("player", "target") then
-- Check both event-based flag AND action bar state for reliable detection
local isAttacking = CleveRoids.CurrentSpell.autoAttack
if not isAttacking then
-- Fallback: check action bar state via IsCurrentAction
local slot = CleveRoids.GetProxyActionSlot(CleveRoids.Localized.Attack)
if slot and IsCurrentAction(slot) then
CleveRoids.CurrentSpell.autoAttack = true
isAttacking = true
end
end
if not isAttacking and not CleveRoids.CurrentSpell.autoAttackLock and UnitExists("target") and UnitCanAttack("player", "target") then
CleveRoids.CurrentSpell.autoAttackLock = true
CleveRoids.autoAttackLockElapsed = GetTime()
AttackTarget()
+4
View File
@@ -24,6 +24,10 @@ function Extension.RegisterMouseoverForFrame(frame, unit)
frame:SetScript("OnLeave", function()
CleveRoids.ClearMouseoverFrom("blizz")
-- Also clear "native" source to prevent sticky highlights.
-- When SetMouseoverUnit("") is called, UPDATE_MOUSEOVER_UNIT fires but
-- selfTriggered causes it to skip, leaving "native" stale.
CleveRoids.ClearMouseoverFrom("native")
if onleave then
onleave()
end
+1
View File
@@ -45,6 +45,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("ctra")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.OnLoad()
+1
View File
@@ -20,6 +20,7 @@ function Extension.SetHook(widget)
widget:SetScript("OnLeave", function()
hookedOnLeave()
CleveRoids.ClearMouseoverFrom("ctuf")
CleveRoids.ClearMouseoverFrom("native")
end)
end
@@ -14,6 +14,7 @@ end
function Extension.OnLeaveFrame()
CleveRoids.ClearMouseoverFrom("duf")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.OnEnterElement()
@@ -22,6 +23,7 @@ end
function Extension.OnLeaveElement()
CleveRoids.ClearMouseoverFrom("duf")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.OnLoad()
+1
View File
@@ -33,6 +33,7 @@ function Extension.HookFrame(frame)
frame:SetScript("OnLeave", function()
CleveRoids.ClearMouseoverFrom("df3")
CleveRoids.ClearMouseoverFrom("native")
if origOnLeave then origOnLeave() end
end)
+1
View File
@@ -20,6 +20,7 @@ function Extension.RegisterMouseoverForFrame(frame)
frame:SetScript("OnLeave", function()
CleveRoids.ClearMouseoverFrom("focus")
CleveRoids.ClearMouseoverFrom("native")
if onleave then
onleave()
end
+27
View File
@@ -15,6 +15,9 @@ end
function Extension.OnClose()
CleveRoids.ClearMouseoverFrom("tooltip")
-- Also clear native source when tooltip closes to prevent sticky highlights
-- The native source may have been set from hovering units in the 3D world
CleveRoids.ClearMouseoverFrom("native")
end
-- Native UPDATE_MOUSEOVER_UNIT handler (priority 2)
@@ -46,6 +49,11 @@ function Extension.OnNonUnitTooltip()
-- Clear the tooltip source (lowest priority fallback)
CleveRoids.ClearMouseoverFrom("tooltip")
-- Also clear the "native" source since we're explicitly clearing mouseover.
-- Without this, a stale "native" source (from hovering units in 3D world)
-- would persist and cause sticky highlights/tooltips.
CleveRoids.ClearMouseoverFrom("native")
-- Also explicitly clear the game's mouseover to ensure UnitIsPlayer returns false.
-- This is defensive - the main fix is in Utility.lua:apply() using "" instead of nil.
if CleveRoids.hasSuperwow and _G.SetMouseoverUnit then
@@ -73,6 +81,25 @@ function Extension.OnLoad()
Extension.HookMethod(_G["GameTooltip"], "SetTradeSkillItem", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetTrainerService", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetHyperlink", "OnNonUnitTooltip")
-- Additional tooltip methods that can cause sticky mouseover state
-- Pet action bar, stance bar, buffs/debuffs, and other UI elements
Extension.HookMethod(_G["GameTooltip"], "SetPetAction", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetShapeshift", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetUnitBuff", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetUnitDebuff", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetPlayerBuff", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetUnitAura", "OnNonUnitTooltip")
-- Auction, mail, guild bank, and other UI tooltips
Extension.HookMethod(_G["GameTooltip"], "SetAuctionItem", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetAuctionSellItem", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetGuildBankItem", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetInboxItem", "OnNonUnitTooltip")
Extension.HookMethod(_G["GameTooltip"], "SetSendMailItem", "OnNonUnitTooltip")
-- Note: SetOwner and SetText are NOT hooked because they're used for ALL tooltips
-- including unit tooltips. Hooking them would incorrectly clear mouseover for units.
end
_G["CleveRoids"] = CleveRoids
+1
View File
@@ -16,6 +16,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("grid")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.OnLoad()
+1
View File
@@ -16,6 +16,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("ngrid")
CleveRoids.ClearMouseoverFrom("native")
end
function CleveRoids:NotGrid_CreateFrames()
+1
View File
@@ -16,6 +16,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("praid")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.OnLoad()
+1
View File
@@ -25,6 +25,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("xperl")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.DelayedInit()
+1
View File
@@ -12,6 +12,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("aguf")
CleveRoids.ClearMouseoverFrom("native")
end
-- Because AddOns are loaded in alphabetical order, this callback will never see the aUF loaded message, had to do a workaround...
+4
View File
@@ -88,6 +88,10 @@ local function PfClear(frame)
if frame and frame.__cr_src then
CleveRoids.ClearMouseoverFrom(frame.__cr_src)
frame.__cr_src = nil
-- Also clear "native" source to prevent sticky highlights.
-- When SetMouseoverUnit("") is called, UPDATE_MOUSEOVER_UNIT fires but
-- selfTriggered causes it to skip, leaving "native" stale.
CleveRoids.ClearMouseoverFrom("native")
end
end
+1
View File
@@ -14,6 +14,7 @@ end
function Extension.OnLeave()
CleveRoids.ClearMouseoverFrom("sraid")
CleveRoids.ClearMouseoverFrom("native")
end
function Extension.OnLoad()