From 19824a09a5ec84960bb3f878bb252f8447181d06 Mon Sep 17 00:00:00 2001 From: Dusk-92 Date: Mon, 24 Aug 2026 14:37:56 +0200 Subject: [PATCH] Make Equip Compare event-driven with ClassicAPI --- mods/equip-compare.lua | 185 +++++++++++++++++++++++++++-------------- 1 file changed, 124 insertions(+), 61 deletions(-) diff --git a/mods/equip-compare.lua b/mods/equip-compare.lua index f58a39c..da8fa8e 100644 --- a/mods/equip-compare.lua +++ b/mods/equip-compare.lua @@ -1,5 +1,6 @@ local _G = ShaguTweaks.GetGlobalEnv() local T = ShaguTweaks.T +local API = ShaguTweaks.API local module = ShaguTweaks:register({ title = T["Equip Compare"], @@ -102,10 +103,11 @@ module.enable = function(self) ["INVTYPE_CROSSBOW"] = "弩", ["INVTYPE_PROJECTILE"] = "弹药", } - } + } - -- set globals for all inventory types - for key, value in pairs(itemtypes[GetLocale()]) do setglobal(key, value) end + -- Vanilla misses a few inventory type labels in some locales. + local localeTypes = itemtypes[GetLocale()] or {} + for key, value in pairs(localeTypes) do setglobal(key, value) end INVTYPE_WEAPON_OTHER = INVTYPE_WEAPON.."_other" INVTYPE_FINGER_OTHER = INVTYPE_FINGER.."_other" INVTYPE_TRINKET_OTHER = INVTYPE_TRINKET.."_other" @@ -147,72 +149,133 @@ module.enable = function(self) ShoppingTooltip1:SetClampedToScreen(true) ShoppingTooltip2:SetClampedToScreen(true) - local function ShowCompare(tooltip) - -- abort if shift is not pressed - if not IsShiftKeyDown() then - ShoppingTooltip1:Hide() - ShoppingTooltip2:Hide() - return + local function GetSlotType(tooltip) + -- Prefer ClassicAPI's cache-backed inventory type. This avoids depending on + -- localized tooltip text and works for Turtle WoW custom items when the + -- tooltip exposes its item link. + if API and tooltip.GetItem and API.GetItemIDFromLink + and API.GetItemInventoryTypeByID and API.GetItemInventorySlotKey then + local _, link = tooltip:GetItem() + local itemID = API.GetItemIDFromLink(link) + local inventoryType = itemID and API.GetItemInventoryTypeByID(itemID) + local slotKey = inventoryType and API.GetItemInventorySlotKey(inventoryType) + local slotType = slotKey and _G[slotKey] + if slotType and slots[slotType] then + return slotType + end end + -- 1.12 fallback: find the localized inventory type in the tooltip text. + local tooltipName = tooltip:GetName() for i=1,tooltip:NumLines() do - local tmpText = _G[tooltip:GetName() .. "TextLeft"..i] - - for slotType, slotName in pairs(slots) do - if tmpText:GetText() == slotType then - local slotID = GetInventorySlotInfo(slotName) - - -- determine screen part - local x = GetCursorPosition() / UIParent:GetEffectiveScale() - local anchor = x < GetScreenWidth() / 2 and "TOPLEFT" or "TOPRIGHT" - local relative = x < GetScreenWidth() / 2 and "TOPRIGHT" or "TOPLEFT" - - -- overwrite position for tooltips without owner - local pos, parent = tooltip:GetPoint() - if parent and parent == UIParent and pos == "TOPRIGHT" then - anchor = "TOPRIGHT" - relative = "TOPLEFT" - end - - -- first tooltip - ShoppingTooltip1:SetOwner(tooltip, "ANCHOR_NONE") - ShoppingTooltip1:ClearAllPoints() - ShoppingTooltip1:SetPoint(anchor, tooltip, relative, 0, 0) - ShoppingTooltip1:SetInventoryItem("player", slotID) - ShoppingTooltip1:Show() - AddHeader(ShoppingTooltip1) - - -- second tooltip - if slots[slotType .. "_other"] then - local slotID_other = GetInventorySlotInfo(slots[slotType .. "_other"]) - ShoppingTooltip2:SetOwner(tooltip, "ANCHOR_NONE") - ShoppingTooltip2:ClearAllPoints() - if ShoppingTooltip1:IsShown() then - ShoppingTooltip2:SetPoint(anchor, ShoppingTooltip1, relative, 0, 0) - else - ShoppingTooltip2:SetPoint(anchor, tooltip, relative, 0, 0) - end - ShoppingTooltip2:SetInventoryItem("player", slotID_other) - ShoppingTooltip2:Show() - AddHeader(ShoppingTooltip2) - end - end + local tmpText = _G[tooltipName .. "TextLeft"..i] + local text = tmpText and tmpText:GetText() + if text and slots[text] then + return text end end end - -- show item compare on default tooltips - local default = CreateFrame("Frame", nil, GameTooltip) - default:SetScript("OnUpdate", function() - ShowCompare(GameTooltip) - end) + local function ShowCompare(tooltip) + if not tooltip then return end - -- show compare on atlas tooltips - ShaguTweaks.HookAddonOrVariable("AtlasLoot", function() - local atlas = CreateFrame("Frame", nil, AtlasLootTooltip) - atlas:SetScript("OnUpdate", function() - ShowCompare(AtlasLootTooltip) - ShowCompare(AtlasLootTooltip2) + -- Always clear previous comparisons first so switching from a ring/trinket + -- to a single-slot item cannot leave ShoppingTooltip2 behind. + ShoppingTooltip1:Hide() + ShoppingTooltip2:Hide() + + if not IsShiftKeyDown() then return end + + local slotType = GetSlotType(tooltip) + local slotName = slotType and slots[slotType] + if not slotName then return end + + local slotID = GetInventorySlotInfo(slotName) + + -- determine screen part + local x = GetCursorPosition() / UIParent:GetEffectiveScale() + local anchor = x < GetScreenWidth() / 2 and "TOPLEFT" or "TOPRIGHT" + local relative = x < GetScreenWidth() / 2 and "TOPRIGHT" or "TOPLEFT" + + -- overwrite position for tooltips without owner + local pos, parent = tooltip:GetPoint() + if parent and parent == UIParent and pos == "TOPRIGHT" then + anchor = "TOPRIGHT" + relative = "TOPLEFT" + end + + -- first tooltip + ShoppingTooltip1:SetOwner(tooltip, "ANCHOR_NONE") + ShoppingTooltip1:ClearAllPoints() + ShoppingTooltip1:SetPoint(anchor, tooltip, relative, 0, 0) + ShoppingTooltip1:SetInventoryItem("player", slotID) + ShoppingTooltip1:Show() + AddHeader(ShoppingTooltip1) + + -- second tooltip for rings, trinkets and one-hand weapons + if slots[slotType .. "_other"] then + local slotID_other = GetInventorySlotInfo(slots[slotType .. "_other"]) + ShoppingTooltip2:SetOwner(tooltip, "ANCHOR_NONE") + ShoppingTooltip2:ClearAllPoints() + if ShoppingTooltip1:IsShown() then + ShoppingTooltip2:SetPoint(anchor, ShoppingTooltip1, relative, 0, 0) + else + ShoppingTooltip2:SetPoint(anchor, tooltip, relative, 0, 0) + end + ShoppingTooltip2:SetInventoryItem("player", slotID_other) + ShoppingTooltip2:Show() + AddHeader(ShoppingTooltip2) + end + end + + -- Recalculate only when a tooltip is actually shown/updated. The original + -- module scanned every tooltip line on every rendered frame. + local trackedTooltips = {} + local function TrackTooltip(tooltip) + if not tooltip or trackedTooltips[tooltip] then return end + trackedTooltips[tooltip] = true + + ShaguTweaks.hooksecurefunc(tooltip, "Show", function() + ShowCompare(tooltip) end) + end + + TrackTooltip(GameTooltip) + + -- ClassicAPI exposes modifier transitions, so pressing/releasing Shift can + -- refresh an already visible tooltip without an always-running OnUpdate. + local modifier = CreateFrame("Frame") + if API and API.modifierstate then + modifier:RegisterEvent("MODIFIER_STATE_CHANGED") + modifier:SetScript("OnEvent", function() + if arg1 == "LSHIFT" or arg1 == "RSHIFT" then + for tooltip in pairs(trackedTooltips) do + if tooltip:IsShown() then + ShowCompare(tooltip) + end + end + end + end) + else + -- Compatibility fallback for an older ClassicAPI build: poll only the + -- Shift boolean, not all tooltip lines every frame. + local previousShift = IsShiftKeyDown() + modifier:SetScript("OnUpdate", function() + local currentShift = IsShiftKeyDown() + if currentShift ~= previousShift then + previousShift = currentShift + for tooltip in pairs(trackedTooltips) do + if tooltip:IsShown() then + ShowCompare(tooltip) + end + end + end + end) + end + + -- AtlasLoot uses its own tooltip frames; hook their Show calls the same way. + ShaguTweaks.HookAddonOrVariable("AtlasLoot", function() + TrackTooltip(AtlasLootTooltip) + TrackTooltip(AtlasLootTooltip2) end) end