From 92562ab1a47a681c0fe9250a4920b755223d255f Mon Sep 17 00:00:00 2001 From: Jrc13245 Date: Thu, 13 Nov 2025 15:46:00 -0500 Subject: [PATCH] Fix macro icons with syntax not using conditionals and fix imbue conditionals --- Conditionals.lua | 122 ++++++++++++++++++++++++++++++++++++++++------- Core.lua | 51 +++++++++++++++++++- 2 files changed, 154 insertions(+), 19 deletions(-) diff --git a/Conditionals.lua b/Conditionals.lua index f8f1554..8475a1c 100644 --- a/Conditionals.lua +++ b/Conditionals.lua @@ -821,15 +821,38 @@ function CleveRoids.ValidatePlayerDebuff(args) end function CleveRoids.ValidateWeaponImbue(slot, imbueName) - -- Check if weapon has enchant + -- Check if weapon has enchant via API local hasMainEnchant, mainExpiration, mainCharges, hasOffEnchant, offExpiration, offCharges = GetWeaponEnchantInfo() + + local hasEnchant, expiration, charges + if slot == "mh" then + hasEnchant = hasMainEnchant + expiration = mainExpiration + charges = mainCharges + else + hasEnchant = hasOffEnchant + expiration = offExpiration + charges = offCharges + end + + -- Only consider temporary enchants (with time or charges) + -- This filters out permanent enchants like Crusader, Lifestealing, etc. + local hasTemporaryEnchant = hasEnchant and (expiration and expiration > 0 or charges and charges > 0) - local hasEnchant = (slot == "mh" and hasMainEnchant) or (slot == "oh" and hasOffEnchant) - if not hasEnchant then return false end - - -- If no specific imbue requested, just return enchant exists - if not imbueName or imbueName == "" then return true end + -- If no specific imbue requested, return temporary enchant status + if not imbueName or imbueName == "" then + return hasTemporaryEnchant + end + + -- If no temporary enchant, don't bother scanning + if not hasTemporaryEnchant then + return false + end + -- For specific imbue names, scan tooltip to match the name + -- BUT only check lines that have time markers (temporary enchants) + -- This prevents matching weapon stats like "Equip: ... critical strike ..." + -- Create tooltip scanner if needed if not CleveRoidsTooltip then CreateFrame("GameTooltip", "CleveRoidsTooltip", nil, "GameTooltipTemplate") @@ -840,22 +863,33 @@ function CleveRoids.ValidateWeaponImbue(slot, imbueName) CleveRoidsTooltip:ClearLines() CleveRoidsTooltip:SetInventoryItem("player", slot == "mh" and 16 or 17) - -- Look for green text (temporary enchant) + -- Normalize search term once + local searchTerm = string.lower(string.gsub(imbueName, "_", " ")) + + -- Look for green text with time markers - check ALL green lines with time for i = 1, CleveRoidsTooltip:NumLines() do local text = _G["CleveRoidsTooltipTextLeft"..i] if text then local line = text:GetText() - local r, g, b = text:GetTextColor() - -- Green text indicates temporary enchant - if line and g > 0.8 and r < 0.2 and b < 0.2 then - -- Normalize and compare - line = string.lower(line) - imbueName = string.lower(string.gsub(imbueName, "_", " ")) - return string.find(line, imbueName, 1, true) ~= nil + if line then + local r, g, b = text:GetTextColor() + -- Green text indicates enchant + if g > 0.8 and r < 0.2 and b < 0.2 then + local lowerLine = string.lower(line) + -- Only check lines with time markers (temporary enchants) + -- This skips permanent weapon stats like "Equip: ... critical strike ..." + if string.find(lowerLine, "%(") and (string.find(lowerLine, " min%)") or string.find(lowerLine, " sec%)") or string.find(lowerLine, " charge")) then + -- This is a temporary enchant line, check if it matches + if string.find(lowerLine, searchTerm, 1, true) then + return true -- Found it! + end + end + end end end end + -- Checked all lines, didn't find it return false end @@ -2020,18 +2054,70 @@ CleveRoids.Keywords = { end, mhimbue = function(conditionals) - return CleveRoids.ValidateWeaponImbue("mh", conditionals.value) + local imbueName = nil + + -- Case 1: conditionals.mhimbue is a string (e.g., [mhimbue]Frostbrand) + if type(conditionals.mhimbue) == "string" then + imbueName = conditionals.mhimbue + -- Case 2: conditionals.mhimbue is a table (e.g., [mhimbue:Frostbrand]) + elseif type(conditionals.mhimbue) == "table" and table.getn(conditionals.mhimbue) > 0 then + imbueName = conditionals.mhimbue[1] -- Use first value + -- Case 3: Boolean true means check for any imbue + elseif conditionals.mhimbue == true then + imbueName = nil -- Check for existence only + end + + return CleveRoids.ValidateWeaponImbue("mh", imbueName) end, nomhimbue = function(conditionals) - return not CleveRoids.ValidateWeaponImbue("mh", conditionals.value) + local imbueName = nil + + -- Case 1: conditionals.nomhimbue is a string + if type(conditionals.nomhimbue) == "string" then + imbueName = conditionals.nomhimbue + -- Case 2: conditionals.nomhimbue is a table + elseif type(conditionals.nomhimbue) == "table" and table.getn(conditionals.nomhimbue) > 0 then + imbueName = conditionals.nomhimbue[1] + -- Case 3: Boolean true + elseif conditionals.nomhimbue == true then + imbueName = nil + end + + return not CleveRoids.ValidateWeaponImbue("mh", imbueName) end, ohimbue = function(conditionals) - return CleveRoids.ValidateWeaponImbue("oh", conditionals.value) + local imbueName = nil + + -- Case 1: conditionals.ohimbue is a string + if type(conditionals.ohimbue) == "string" then + imbueName = conditionals.ohimbue + -- Case 2: conditionals.ohimbue is a table + elseif type(conditionals.ohimbue) == "table" and table.getn(conditionals.ohimbue) > 0 then + imbueName = conditionals.ohimbue[1] + -- Case 3: Boolean true + elseif conditionals.ohimbue == true then + imbueName = nil + end + + return CleveRoids.ValidateWeaponImbue("oh", imbueName) end, noohimbue = function(conditionals) - return not CleveRoids.ValidateWeaponImbue("oh", conditionals.value) + local imbueName = nil + + -- Case 1: conditionals.noohimbue is a string + if type(conditionals.noohimbue) == "string" then + imbueName = conditionals.noohimbue + -- Case 2: conditionals.noohimbue is a table + elseif type(conditionals.noohimbue) == "table" and table.getn(conditionals.noohimbue) > 0 then + imbueName = conditionals.noohimbue[1] + -- Case 3: Boolean true + elseif conditionals.noohimbue == true then + imbueName = nil + end + + return not CleveRoids.ValidateWeaponImbue("oh", imbueName) end } diff --git a/Core.lua b/Core.lua index 2d61106..968962e 100644 --- a/Core.lua +++ b/Core.lua @@ -459,6 +459,7 @@ function CleveRoids.TestForActiveAction(actions) local hasActive = false local newActiveAction = nil local newSequence = nil + local firstUnconditional = nil if actions.tooltip and table.getn(actions.list) == 0 then if CleveRoids.TestAction(actions.cmd or "", actions.args or "") then @@ -467,9 +468,20 @@ function CleveRoids.TestForActiveAction(actions) actions.active = actions.tooltip end else + -- First pass: find first action with conditionals that passes for _, action in ipairs(actions.list) do + local result = CleveRoids.TestAction(action.cmd, action.args) + + -- Check if action has conditionals + local _, conditionals = CleveRoids.GetParsedMsg(action.args) + + if not conditionals and not firstUnconditional then + -- Track first unconditional action as fallback + firstUnconditional = action + end + -- break on first action that passes tests - if CleveRoids.TestAction(action.cmd, action.args) then + if result then hasActive = true if action.sequence then newSequence = action.sequence @@ -481,6 +493,12 @@ function CleveRoids.TestForActiveAction(actions) if hasActive then break end end end + + -- If no conditional action passed, use first unconditional action + if not hasActive and firstUnconditional then + hasActive = true + newActiveAction = firstUnconditional + end end local changed = false @@ -1021,6 +1039,7 @@ function CleveRoids.ParseMacro(name) -- #showtooltip and item/spell/macro specified, only use this tooltip if st and tt ~= "" then + showTooltipHasArg = true for _, arg in ipairs(CleveRoids.splitStringIgnoringQuotes(tt)) do macro.actions.tooltip = CleveRoids.CreateActionInfo(arg) local action = CleveRoids.CreateActionInfo(CleveRoids.GetParsedMsg(arg)) @@ -1052,6 +1071,14 @@ function CleveRoids.ParseMacro(name) end end + -- If #showtooltip was present but had no argument, use the first action as the tooltip + if hasShowTooltip and not showTooltipHasArg and table.getn(macro.actions.list) > 0 then + macro.actions.tooltip = macro.actions.list[1] + end + + -- Store whether #showtooltip had an explicit argument (for icon fallback logic) + macro.actions.explicitTooltip = showTooltipHasArg + CleveRoids.Macros[name] = macro return macro end @@ -1152,6 +1179,10 @@ function CleveRoids.ParseMsg(msg) noresting = true, isplayer = true, isnpc = true, + mhimbue = true, + nomhimbue = true, + ohimbue = true, + noohimbue = true, } if booleanConditionals[condition] then @@ -2386,6 +2417,24 @@ function GetActionTexture(slot) local actions = CleveRoids.GetAction(slot) if actions and (actions.active or actions.tooltip) then + -- If #showtooltip had NO argument and all conditionals failed, show macro icon + -- (Get the macro's default texture instead of tooltip or unknown) + if not actions.active and not actions.explicitTooltip and actions.list and table.getn(actions.list) > 0 then + -- Return the macro's default icon + local macroName = GetActionText(slot) + if macroName then + local macroID = GetMacroIndexByName(macroName) + if macroID and macroID > 0 then + local _, macroTexture = GetMacroInfo(macroID) + if macroTexture then + return macroTexture + end + end + end + -- Fallback to unknown if we can't get macro texture + return CleveRoids.unknownTexture + end + -- Prioritize active action, fall back to tooltip local a = actions.active or actions.tooltip