fix: auto-sell manually assigned Junk items
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
-- Auto-sell items explicitly assigned by the user to the built-in Junk category.
|
||||
-- Upstream Guda's vendor pass only sells poor-quality (gray) links, so a white,
|
||||
-- green, etc. item manually moved to Junk is displayed as junk but never sold.
|
||||
-- This module handles only those manual non-gray overrides; the original gray
|
||||
-- junk seller remains unchanged.
|
||||
|
||||
local addon = Guda
|
||||
|
||||
local runner = CreateFrame("Frame")
|
||||
runner:Hide()
|
||||
runner.items = nil
|
||||
runner.index = 0
|
||||
runner.waitElapsed = 0
|
||||
runner.pollElapsed = 0
|
||||
runner.soldCount = 0
|
||||
|
||||
local function IsMerchantOpen()
|
||||
return MerchantFrame and MerchantFrame:IsShown()
|
||||
end
|
||||
|
||||
local function GetItemID(link)
|
||||
if not link then return nil end
|
||||
local Utils = addon.Modules and addon.Modules.Utils
|
||||
if Utils and Utils.ExtractItemID then
|
||||
return Utils:ExtractItemID(link)
|
||||
end
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
return id and tonumber(id) or nil
|
||||
end
|
||||
|
||||
local function IsProtected(itemID)
|
||||
local DB = addon.Modules and addon.Modules.DB
|
||||
return DB and DB.IsItemProtected and DB:IsItemProtected(itemID)
|
||||
end
|
||||
|
||||
local function IsManualJunk(itemID)
|
||||
if not itemID then return false end
|
||||
local CategoryManager = addon.Modules and addon.Modules.CategoryManager
|
||||
if not CategoryManager or not CategoryManager.GetCategories then return false end
|
||||
local cats = CategoryManager:GetCategories()
|
||||
return cats and cats.itemOverrides and cats.itemOverrides[itemID] == "Junk"
|
||||
end
|
||||
|
||||
local function IsGrayLink(link)
|
||||
return link and string.find(link, "|cff9d9d9d") ~= nil
|
||||
end
|
||||
|
||||
-- Wait for Guda's existing gray-junk seller to finish before starting this
|
||||
-- pass, avoiding two vendor loops calling UseContainerItem in the same frame.
|
||||
local function HasUnprotectedGrayJunk()
|
||||
for bag = 0, 4 do
|
||||
local numSlots = GetContainerNumSlots(bag) or 0
|
||||
for slot = 1, numSlots do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if IsGrayLink(link) then
|
||||
local itemID = GetItemID(link)
|
||||
if itemID and not IsProtected(itemID) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function StopRunner()
|
||||
runner:Hide()
|
||||
runner.items = nil
|
||||
runner.index = 0
|
||||
runner.waitElapsed = 0
|
||||
runner.pollElapsed = 0
|
||||
runner.soldCount = 0
|
||||
end
|
||||
|
||||
local function StartManualJunkSale()
|
||||
local DB = addon.Modules and addon.Modules.DB
|
||||
if not DB then return end
|
||||
|
||||
local autoVendor = DB:GetSetting("autoVendorJunk")
|
||||
if autoVendor == nil then autoVendor = true end
|
||||
if not autoVendor then return end
|
||||
|
||||
local items = {}
|
||||
for bag = 0, 4 do
|
||||
local numSlots = GetContainerNumSlots(bag) or 0
|
||||
for slot = 1, numSlots do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
-- Gray items are already handled by Guda's original vendor pass.
|
||||
if link and not IsGrayLink(link) then
|
||||
local itemID = GetItemID(link)
|
||||
if itemID and IsManualJunk(itemID) and not IsProtected(itemID) then
|
||||
local _, _, locked = GetContainerItemInfo(bag, slot)
|
||||
if not locked then
|
||||
table.insert(items, { bag = bag, slot = slot, itemID = itemID })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if table.getn(items) == 0 then return end
|
||||
|
||||
runner.items = items
|
||||
runner.index = 0
|
||||
runner.waitElapsed = 0
|
||||
runner.pollElapsed = 0
|
||||
runner.soldCount = 0
|
||||
runner:Show()
|
||||
end
|
||||
|
||||
runner:SetScript("OnUpdate", function()
|
||||
if not IsMerchantOpen() then
|
||||
StopRunner()
|
||||
return
|
||||
end
|
||||
|
||||
-- Poll at 10 Hz while the original gray-item seller is active. A hard
|
||||
-- two-second ceiling prevents a stuck/locked gray item from blocking the
|
||||
-- manual-junk pass forever.
|
||||
if this.waitElapsed < 2.0 then
|
||||
this.waitElapsed = this.waitElapsed + arg1
|
||||
this.pollElapsed = this.pollElapsed + arg1
|
||||
if this.pollElapsed < 0.10 then return end
|
||||
this.pollElapsed = 0
|
||||
if HasUnprotectedGrayJunk() then return end
|
||||
this.waitElapsed = 2.0
|
||||
end
|
||||
|
||||
this.index = this.index + 1
|
||||
local item = this.items and this.items[this.index]
|
||||
if not item then
|
||||
if this.soldCount > 0 then
|
||||
addon:Debug("Sold %d manually assigned junk item(s)", this.soldCount)
|
||||
end
|
||||
StopRunner()
|
||||
return
|
||||
end
|
||||
|
||||
-- Revalidate the slot immediately before selling. This protects against
|
||||
-- inventory changes while the merchant window is open.
|
||||
local link = GetContainerItemLink(item.bag, item.slot)
|
||||
local itemID = GetItemID(link)
|
||||
if link and itemID == item.itemID and not IsGrayLink(link)
|
||||
and IsManualJunk(itemID) and not IsProtected(itemID) then
|
||||
local _, _, locked = GetContainerItemInfo(item.bag, item.slot)
|
||||
if not locked then
|
||||
UseContainerItem(item.bag, item.slot)
|
||||
this.soldCount = this.soldCount + 1
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local eventFrame = CreateFrame("Frame")
|
||||
eventFrame:RegisterEvent("MERCHANT_SHOW")
|
||||
eventFrame:RegisterEvent("MERCHANT_CLOSED")
|
||||
eventFrame:SetScript("OnEvent", function()
|
||||
if event == "MERCHANT_SHOW" then
|
||||
StartManualJunkSale()
|
||||
elseif event == "MERCHANT_CLOSED" then
|
||||
StopRunner()
|
||||
end
|
||||
end)
|
||||
|
||||
addon:Debug("Manual Junk auto-sell compatibility fix loaded")
|
||||
Reference in New Issue
Block a user