local addonName = ... local SetGuard = CreateFrame("Frame") _G[addonName] = SetGuard local savedSetItems = {} local hookedFrames = {} local updateQueued = false local merchantOpen = false function SetGuard:RebuildSetSlots() wipe(savedSetItems) if not (C_EquipmentSet and C_EquipmentSet.GetEquipmentSetIDs and C_EquipmentSet.GetItemIDs) then return end local setIDs = C_EquipmentSet.GetEquipmentSetIDs() if not setIDs then return end for _, setID in ipairs(setIDs) do local itemIDs = C_EquipmentSet.GetItemIDs(setID) if itemIDs then for _, itemID in pairs(itemIDs) do if itemID and itemID > 0 then savedSetItems[itemID] = true end end end end end local function GetBagItemID(bag, slot) if C_Container and C_Container.GetContainerItemID then return C_Container.GetContainerItemID(bag, slot) end if C_Container and C_Container.GetContainerItemInfo then local info = C_Container.GetContainerItemInfo(bag, slot) return info and info.itemID end return nil end local function GetItemIcon(button) return button.icon or button.Icon or button.ItemIcon or button.IconTexture or button:GetNormalTexture() end local function GetItemTextures(button) local textures, seen = {}, {} local candidates = { button.icon, button.Icon, button.ItemIcon, button.IconTexture, button:GetNormalTexture(), } for _, texture in pairs(candidates) do if texture and texture.GetVertexColor and not seen[texture] then seen[texture] = true table.insert(textures, texture) end end return textures end local function SetButtonDesaturated(button, desaturated) if SetItemButtonDesaturated then SetItemButtonDesaturated(button, desaturated) return end local icon = GetItemIcon(button) if icon and icon.SetDesaturated then icon:SetDesaturated(desaturated) end end local function SetButtonBrightness(button, brightness) if not button.SetGuardVertexColors then button.SetGuardVertexColors = {} for _, texture in ipairs(GetItemTextures(button)) do local red, green, blue, alpha = texture:GetVertexColor() button.SetGuardVertexColors[texture] = { red, green, blue, alpha } end end for texture, color in pairs(button.SetGuardVertexColors) do texture:SetVertexColor(color[1] * brightness, color[2] * brightness, color[3] * brightness, color[4]) end end local function RestoreButtonBrightness(button) if not button.SetGuardVertexColors then return end for texture, color in pairs(button.SetGuardVertexColors) do texture:SetVertexColor(color[1], color[2], color[3], color[4]) end button.SetGuardVertexColors = nil end function SetGuard:UpdateBagButton(button) if not button or not button.GetBagID then return end local label = button.SetGuardLabel if not label then label = button:CreateFontString(nil, "OVERLAY", "GameFontNormal") label:SetPoint("TOPLEFT", button, "TOPLEFT", 2, -2) label:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") label:SetText("S") label:SetTextColor(0.1, 1, 0.1) button.SetGuardLabel = label end local bag, slot = button:GetBagID(), button:GetID() local itemID = bag and slot and GetBagItemID(bag, slot) local isSetItem = itemID and savedSetItems[itemID] label:SetShown(isSetItem == true) if isSetItem and merchantOpen then if not button.SetGuardDimmed then local icon = GetItemIcon(button) button.SetGuardWasDesaturated = icon and icon.GetDesaturated and icon:GetDesaturated() or false button.SetGuardDimmed = true end SetButtonDesaturated(button, true) SetButtonBrightness(button, 0.25) elseif button.SetGuardDimmed then SetButtonDesaturated(button, button.SetGuardWasDesaturated == true) RestoreButtonBrightness(button) button.SetGuardDimmed = nil button.SetGuardWasDesaturated = nil end end function SetGuard:UpdateContainerFrame(frame) if not frame then return end if frame.EnumerateValidItems then for _, button in frame:EnumerateValidItems() do self:UpdateBagButton(button) end elseif frame.Items then for _, button in ipairs(frame.Items) do self:UpdateBagButton(button) end end end function SetGuard:HookContainerFrame(frame) if not frame or hookedFrames[frame] or not frame.Update then return end hooksecurefunc(frame, "Update", function(updatedFrame) SetGuard:UpdateContainerFrame(updatedFrame) end) hookedFrames[frame] = true end function SetGuard:UpdateVisibleBags() local index = 1 local frame = _G["ContainerFrame" .. index] while frame do self:HookContainerFrame(frame) self:UpdateContainerFrame(frame) index = index + 1 frame = _G["ContainerFrame" .. index] end if ContainerFrameCombinedBags then self:HookContainerFrame(ContainerFrameCombinedBags) self:UpdateContainerFrame(ContainerFrameCombinedBags) end end function SetGuard:QueueUpdate(rebuildSets) if rebuildSets then self:RebuildSetSlots() end if updateQueued then return end updateQueued = true C_Timer.After(0.1, function() updateQueued = false SetGuard:UpdateVisibleBags() end) end function SetGuard:OnEvent(event) if event == "MERCHANT_SHOW" then merchantOpen = true elseif event == "MERCHANT_CLOSED" then merchantOpen = false end self:QueueUpdate(event == "PLAYER_LOGIN" or event == "EQUIPMENT_SETS_CHANGED") end SetGuard:RegisterEvent("PLAYER_LOGIN") SetGuard:RegisterEvent("EQUIPMENT_SETS_CHANGED") SetGuard:RegisterEvent("BAG_UPDATE_DELAYED") SetGuard:RegisterEvent("MERCHANT_SHOW") SetGuard:RegisterEvent("MERCHANT_CLOSED") SetGuard:RegisterEvent("ADDON_LOADED") SetGuard:SetScript("OnEvent", SetGuard.OnEvent)