Files
Guda-ClassicAPI/Core/ManualJunkAutoSell.lua

165 lines
5.3 KiB
Lua

-- 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")