init
This commit is contained in:
@@ -0,0 +1,511 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Cancel = TSM:NewModule("Cancel", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
|
||||
local cancelQueue, currentItem, tempIndexList = {}, {}, {}
|
||||
local totalToCancel, totalCanceled, count = 0, 0, 0
|
||||
local isScanning, GUI, isCancelAll, specialOptions
|
||||
local itemsCancelled, itemsMissed = {}, {}
|
||||
|
||||
|
||||
function Cancel:ValidateOperation(itemString, operation)
|
||||
local _, itemLink = TSMAPI:GetSafeItemInfo(itemString)
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString)
|
||||
|
||||
-- don't cancel this item if their settings are invalid
|
||||
if not prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your minimum price (%s) is invalid. Check your settings."], itemLink or itemString, operation.minPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
elseif not prices.maxPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your maximum price (%s) is invalid. Check your settings."], itemLink or itemString, operation.maxPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
elseif not prices.normalPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your normal price (%s) is invalid. Check your settings."], itemLink or itemString, operation.normalPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
elseif operation.cancelRepost and not prices.cancelRepostThreshold then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your cancel to repost threshold (%s) is invalid. Check your settings."], itemLink or itemString, operation.cancelRepostThreshold)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
elseif not prices.undercut then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your undercut (%s) is invalid. Check your settings."], itemLink or itemString, operation.undercut)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
elseif prices.maxPrice < prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your maximum price (%s) is lower than your minimum price (%s). Check your settings."], itemLink or itemString, operation.maxPrice, operation.minPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
elseif prices.normalPrice < prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not cancel %s because your normal price (%s) is lower than your minimum price (%s). Check your settings."], itemLink or itemString, operation.normalPrice, operation.minPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "invalid")
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function Cancel:GetScanListAndSetup(GUIRef, options)
|
||||
-- setup stuff
|
||||
GUI = GUIRef
|
||||
options = options or {}
|
||||
isScanning = true
|
||||
options.noScan = options.specialMode
|
||||
isCancelAll = options.specialMode
|
||||
wipe(cancelQueue)
|
||||
wipe(currentItem)
|
||||
wipe(itemsCancelled)
|
||||
wipe(itemsMissed)
|
||||
wipe(TSM.operationLookup)
|
||||
totalToCancel, totalCanceled, count = 0, 0, 0
|
||||
|
||||
local tempList, scanList, groupTemp = {}, {}, {}
|
||||
|
||||
specialOptions = specialOptions or {}
|
||||
wipe(specialOptions)
|
||||
if type(options.specialMode) == "string" then
|
||||
if strsub(options.specialMode, 1, 1) == "<" then
|
||||
specialOptions.specialPriceMax = TSMAPI:UnformatTextMoney(strsub(options.specialMode, 2))
|
||||
isCancelAll = "price"
|
||||
elseif strsub(options.specialMode, 1, 1) == ">" then
|
||||
specialOptions.specialPriceMin = TSMAPI:UnformatTextMoney(strsub(options.specialMode, 2))
|
||||
isCancelAll = "price"
|
||||
end
|
||||
end
|
||||
|
||||
for i=GetNumAuctionItems("owner"), 1, -1 do
|
||||
-- ignore sold auctions
|
||||
if select(13, GetAuctionItemInfo("owner", i)) == 0 then
|
||||
local itemString = TSMAPI:GetBaseItemString(GetAuctionItemLink("owner", i), true)
|
||||
if not TSM.db.global.cancelWithBid and select(10, GetAuctionItemInfo("owner", i)) > 0 then
|
||||
-- we aren't canceling auctions with bids
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", "bid")
|
||||
else
|
||||
if specialOptions.specialPriceMin then
|
||||
-- cancel auctions above some min price
|
||||
local buyout = select(9, GetAuctionItemInfo("owner", i))
|
||||
if buyout > 0 and buyout > specialOptions.specialPriceMin then
|
||||
tempList[itemString] = true
|
||||
end
|
||||
elseif specialOptions.specialPriceMax then
|
||||
-- cancel auctions below some max price
|
||||
local buyout = select(9, GetAuctionItemInfo("owner", i))
|
||||
if buyout > 0 and buyout < specialOptions.specialPriceMax then
|
||||
tempList[itemString] = true
|
||||
end
|
||||
elseif options.specialMode == "CancelAll" then
|
||||
-- cancel all auctions
|
||||
tempList[itemString] = true
|
||||
elseif type(options.specialMode) == "number" then
|
||||
-- cancel low duration auctions
|
||||
local timeLeft = GetAuctionItemTimeLeft("owner", i)
|
||||
if timeLeft <= options.specialMode then
|
||||
tempList[itemString] = true
|
||||
end
|
||||
elseif options.specialMode then
|
||||
-- cancel all items matching filter
|
||||
local itemName = GetAuctionItemInfo("owner", i)
|
||||
if strfind(strlower(itemName), strlower(options.specialMode)) then
|
||||
tempList[itemString] = true
|
||||
end
|
||||
elseif options.itemOperations[itemString] then
|
||||
-- normal cancel scan
|
||||
local operations = {}
|
||||
for _, operation in pairs(options.itemOperations[itemString]) do
|
||||
if operation.cancelUndercut or operation.cancelRepost then
|
||||
tinsert(operations, operation)
|
||||
end
|
||||
end
|
||||
tempList[itemString] = operations
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if options.specialMode then
|
||||
for itemString in pairs(tempList) do
|
||||
tinsert(scanList, itemString)
|
||||
end
|
||||
else
|
||||
for itemString, operations in pairs(tempList) do
|
||||
TSM.operationLookup[itemString] = operations
|
||||
local isValid
|
||||
for _, operation in pairs(operations) do
|
||||
if operation.cancelUndercut or operation.cancelRepost then
|
||||
isValid = true
|
||||
if not Cancel:ValidateOperation(itemString, operation) then
|
||||
isValid = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if isValid then
|
||||
tinsert(scanList, itemString)
|
||||
end
|
||||
end
|
||||
TSMAPI:FireEvent("AUCTIONING:CANCEL:START", {num=#scanList})
|
||||
end
|
||||
|
||||
return scanList
|
||||
end
|
||||
|
||||
function Cancel:ProcessItem(itemString, noLog)
|
||||
if isCancelAll then
|
||||
return Cancel:SpecialScanProcessItem(itemString, noLog)
|
||||
end
|
||||
|
||||
local operations = TSM.operationLookup[itemString]
|
||||
if not operations then return end
|
||||
for _, operation in pairs(operations) do
|
||||
local toCancel, reasonToCancel, reasonNotToCancel, buyout
|
||||
local cancelAuctions = {}
|
||||
for i=GetNumAuctionItems("owner"), 1, -1 do
|
||||
if select(13, GetAuctionItemInfo("owner", i)) == 0 and itemString == TSMAPI:GetBaseItemString(GetAuctionItemLink("owner", i), true) then
|
||||
local shouldCancel, reason = Cancel:ShouldCancel(i, operation)
|
||||
if shouldCancel then
|
||||
shouldCancel.reason = reason
|
||||
tinsert(cancelAuctions, shouldCancel)
|
||||
buyout = select(9, GetAuctionItemInfo("owner", i))
|
||||
else
|
||||
reasonNotToCancel = reasonNotToCancel or reason
|
||||
buyout = buyout or select(9, GetAuctionItemInfo("owner", i))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local numKept = 0
|
||||
sort(cancelAuctions, function(a, b) return a.buyout < b.buyout end) --keepPosted
|
||||
for i=#cancelAuctions, 1, -1 do
|
||||
local auction = cancelAuctions[i]
|
||||
if (auction.reason == "whitelistUndercut" or auction.reason == "undercut" or auction.reason == "notLowest") and numKept < operation.keepPosted then
|
||||
numKept = numKept + 1
|
||||
reasonNotToCancel = "keepPosted"
|
||||
else
|
||||
toCancel = true
|
||||
reasonToCancel = auction.reason
|
||||
totalToCancel = totalToCancel + 1
|
||||
tinsert(cancelQueue, auction)
|
||||
end
|
||||
end
|
||||
if totalToCancel > 0 then
|
||||
TSM.Manage:UpdateStatus("manage", totalCanceled, totalToCancel)
|
||||
end
|
||||
|
||||
if not noLog then
|
||||
if toCancel then
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Cancel", reasonToCancel, operation, buyout)
|
||||
elseif reasonNotToCancel then
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", reasonNotToCancel, operation, buyout)
|
||||
end
|
||||
end
|
||||
|
||||
if #cancelQueue > 0 and not currentItem.buyout then
|
||||
Cancel:SetupForAction()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Cancel:SpecialScanProcessItem(itemString, noLog)
|
||||
local toCancel, reasonToCancel, reasonNotToCancel
|
||||
local cancelAuctions = {}
|
||||
for i=GetNumAuctionItems("owner"), 1, -1 do
|
||||
if select(13, GetAuctionItemInfo("owner", i)) == 0 and itemString == TSMAPI:GetBaseItemString(GetAuctionItemLink("owner", i), true) then
|
||||
local _, _, quantity, _, _, _, bid, _, buyout, activeBid, _, _, wasSold = GetAuctionItemInfo("owner", i)
|
||||
local cancelData = {itemString=itemString, stackSize=quantity, buyout=buyout, bid=bid, index=i, numStacks=1}
|
||||
if specialOptions.specialPriceMin then
|
||||
if buyout > specialOptions.specialPriceMin then
|
||||
cancelData.reason = "cancelAll"
|
||||
tinsert(cancelAuctions, cancelData)
|
||||
else
|
||||
reasonNotToCancel = reasonNotToCancel or "cancelAll"
|
||||
end
|
||||
elseif specialOptions.specialPriceMax then
|
||||
if buyout < specialOptions.specialPriceMax then
|
||||
cancelData.reason = "cancelAll"
|
||||
tinsert(cancelAuctions, cancelData)
|
||||
else
|
||||
reasonNotToCancel = reasonNotToCancel or "cancelAll"
|
||||
end
|
||||
elseif type(isCancelAll) ~= "number" or GetAuctionItemTimeLeft("owner", i) <= isCancelAll then
|
||||
cancelData.reason = "cancelAll"
|
||||
tinsert(cancelAuctions, cancelData)
|
||||
else
|
||||
reasonNotToCancel = reasonNotToCancel or "cancelAll"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local numKept = 0
|
||||
sort(cancelAuctions, function(a, b) return a.buyout < b.buyout end) --keepPosted
|
||||
for i=#cancelAuctions, 1, -1 do
|
||||
local auction = cancelAuctions[i]
|
||||
toCancel = true
|
||||
reasonToCancel = auction.reason
|
||||
totalToCancel = totalToCancel + 1
|
||||
tinsert(cancelQueue, auction)
|
||||
end
|
||||
if totalToCancel > 0 then
|
||||
TSM.Manage:UpdateStatus("manage", totalCanceled, totalToCancel)
|
||||
end
|
||||
|
||||
if not noLog then
|
||||
if toCancel then
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Cancel", reasonToCancel)
|
||||
elseif reasonNotToCancel then
|
||||
TSM.Log:AddLogRecord(itemString, "cancel", "Skip", reasonNotToCancel)
|
||||
end
|
||||
end
|
||||
|
||||
if #cancelQueue > 0 and not currentItem.buyout then
|
||||
Cancel:SetupForAction()
|
||||
end
|
||||
end
|
||||
|
||||
function Cancel:ShouldCancel(index, operation)
|
||||
local _, _, quantity, _, _, _, bid, _, buyout, activeBid, _, _, wasSold = GetAuctionItemInfo("owner", index)
|
||||
local buyoutPerItem = floor(buyout / quantity)
|
||||
local bidPerItem = floor(bid / quantity)
|
||||
if operation.matchStackSize and quantity ~= operation.stackSize then return end
|
||||
|
||||
local itemString = TSMAPI:GetBaseItemString(GetAuctionItemLink("owner", index), true)
|
||||
local cancelData = {itemString=itemString, stackSize=quantity, buyout=buyout, bid=bid, index=index, numStacks=1, operation=operation}
|
||||
|
||||
local auctionItem = TSM.Scan.auctionData[itemString]
|
||||
local lowestBuyout, lowestBid, lowestOwner, isWhitelist, isPlayer, isInvalidSeller = TSM.Scan:GetLowestAuction(itemString, operation)
|
||||
local secondLowest = TSM.Scan:GetSecondLowest(itemString, lowestBuyout, operation) or 0
|
||||
|
||||
if wasSold == 1 or not lowestOwner then
|
||||
-- if this auction was sold or we don't have any data on it then this request is invalid
|
||||
return
|
||||
elseif isInvalidSeller or not lowestBuyout then
|
||||
if isInvalidSeller then
|
||||
TSM:Printf(L["Seller name of lowest auction for item %s was not returned from server. Skipping this item."], GetAuctionItemLink("owner", index))
|
||||
else
|
||||
TSM:Printf(L["Invalid scan data for item %s. Skipping this item."], GetAuctionItemLink("owner", index))
|
||||
end
|
||||
return false, "invalidSeller"
|
||||
end
|
||||
|
||||
if not TSM.db.global.cancelWithBid and activeBid > 0 then
|
||||
-- Don't cancel an auction if it has a bid and we're set to not cancel those
|
||||
return false, "bid"
|
||||
end
|
||||
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString)
|
||||
if buyoutPerItem < prices.minPrice then
|
||||
-- this auction is below min price
|
||||
if operation.cancelRepost and prices.resetPrice and buyoutPerItem < (prices.resetPrice - prices.cancelRepostThreshold) then
|
||||
-- canceling to post at reset price
|
||||
return cancelData, "reset"
|
||||
end
|
||||
return false, "belowMinPrice"
|
||||
elseif lowestBuyout < prices.minPrice then
|
||||
-- lowest buyout is below min price, so do nothing
|
||||
return false, "belowMinPrice"
|
||||
else
|
||||
-- lowest buyout is above the min price
|
||||
if operation.cancelUndercut and (buyoutPerItem - prices.undercut) > (TSM.Scan:GetPlayerLowestBuyout(auctionItem, operation) or math.huge) then
|
||||
-- this is not our lowest auction
|
||||
return cancelData, "notLowest"
|
||||
elseif auctionItem:IsPlayerOnly() then
|
||||
-- we are posted at the aboveMax price with no competition under our max price
|
||||
-- check if we can repost higher
|
||||
if operation.cancelRepost and prices.normalPrice - buyoutPerItem > prices.cancelRepostThreshold then
|
||||
-- we can repost higher
|
||||
return cancelData, "repost"
|
||||
end
|
||||
return false, "atNormal"
|
||||
elseif isPlayer and (secondLowest > prices.maxPrice) then
|
||||
-- we are posted at the aboveMax price with no competition under our max price
|
||||
-- check if we can repost higher
|
||||
if operation.cancelRepost and prices.aboveMax - buyoutPerItem > prices.cancelRepostThreshold then
|
||||
-- we can repost higher
|
||||
return cancelData, "repost"
|
||||
end
|
||||
return false, "atAboveMax"
|
||||
elseif isPlayer then
|
||||
-- we are the loewst auction
|
||||
-- check if we can repost higher
|
||||
if operation.cancelRepost and ((secondLowest - prices.undercut) - lowestBuyout) > prices.cancelRepostThreshold then
|
||||
-- we can repost higher
|
||||
return cancelData, "repost"
|
||||
end
|
||||
return false, "notUndercut"
|
||||
elseif not operation.cancelUndercut then
|
||||
return -- we're undercut but not canceling undercut auctions
|
||||
elseif isWhitelist and buyoutPerItem == lowestBuyout then
|
||||
-- at whitelisted player price
|
||||
return false, "atWhitelist"
|
||||
elseif not isWhitelist then
|
||||
-- we've been undercut by somebody not on our whitelist
|
||||
return cancelData, "undercut"
|
||||
elseif buyoutPerItem ~= lowestBuyout or bidPerItem ~= lowestBid then
|
||||
-- somebody on our whitelist undercut us (or their bid is lower)
|
||||
return cancelData, "whitelistUndercut"
|
||||
end
|
||||
end
|
||||
|
||||
error("unexpectedly reached end", buyoutPerItem, lowestBuyout, isWhitelist, isPlayer, prices.minPrice)
|
||||
end
|
||||
|
||||
-- register events and queue up the first item to cancel
|
||||
function Cancel:SetupForAction()
|
||||
Cancel:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||
Cancel:RegisterEvent("UI_ERROR_MESSAGE")
|
||||
TSM.Manage:UpdateStatus("manage", totalCanceled, totalToCancel)
|
||||
wipe(currentItem)
|
||||
currentItem = cancelQueue[1]
|
||||
TSM.Manage:SetCurrentItem(currentItem)
|
||||
GUI.buttons:Enable()
|
||||
end
|
||||
|
||||
-- Check if an auction was canceled and move on if so
|
||||
function Cancel:CHAT_MSG_SYSTEM(_, msg)
|
||||
if msg == ERR_AUCTION_REMOVED then
|
||||
count = count + 1
|
||||
TSM.Manage:UpdateStatus("confirm", count, totalToCancel)
|
||||
end
|
||||
end
|
||||
|
||||
-- "Item Not Found" error
|
||||
function Cancel:UI_ERROR_MESSAGE(event, msg)
|
||||
if msg == ERR_ITEM_NOT_FOUND then
|
||||
count = count + 1
|
||||
TSM.Manage:UpdateStatus("confirm", count, totalToCancel)
|
||||
tinsert(itemsMissed, itemsCancelled[count])
|
||||
end
|
||||
end
|
||||
|
||||
local function CountFrame()
|
||||
if count == totalToCancel then
|
||||
TSMAPI:CancelFrame("cancelCountFrame")
|
||||
Cancel:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
local function DelayFrame()
|
||||
if not isScanning and #(cancelQueue) == 0 then
|
||||
TSMAPI:CreateFunctionRepeat("cancelCountFrame", CountFrame)
|
||||
TSMAPI:CancelFrame("cancelDelayFrame")
|
||||
elseif #(cancelQueue) > 0 then
|
||||
Cancel:UpdateItem()
|
||||
TSMAPI:CancelFrame("cancelDelayFrame")
|
||||
end
|
||||
end
|
||||
|
||||
-- updates the current item to the first one in the list
|
||||
function Cancel:UpdateItem()
|
||||
if #(cancelQueue) == 0 then
|
||||
GUI.buttons:Disable()
|
||||
if isScanning then
|
||||
TSMAPI:CreateFunctionRepeat("cancelDelayFrame", DelayFrame)
|
||||
else
|
||||
TSMAPI:CreateFunctionRepeat("cancelCountFrame", CountFrame)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
sort(cancelQueue, function(a, b) return (a.index or 0)>(b.index or 0) end)
|
||||
|
||||
totalCanceled = totalCanceled + 1
|
||||
TSM.Manage:UpdateStatus("manage", totalCanceled, totalToCancel)
|
||||
wipe(currentItem)
|
||||
currentItem = cancelQueue[1]
|
||||
TSM.Manage:SetCurrentItem(currentItem)
|
||||
GUI.buttons:Enable()
|
||||
end
|
||||
|
||||
-- cancel the current item (gets called when the button is pressed
|
||||
function Cancel:DoAction()
|
||||
local index, backupIndex
|
||||
-- make sure the currentItem is accurate
|
||||
if cancelQueue[1].itemString ~= currentItem.itemString then
|
||||
Cancel:UpdateItem()
|
||||
end
|
||||
|
||||
-- figure out which index the item goes to
|
||||
for i=GetNumAuctionItems("owner"), 1, -1 do
|
||||
local _, _, quantity, _, _, _, bid, _, buyout, activeBid = GetAuctionItemInfo("owner", i)
|
||||
local itemString = TSMAPI:GetBaseItemString(GetAuctionItemLink("owner", i), true)
|
||||
if itemString == currentItem.itemString and abs((buyout or 0) - (currentItem.buyout or 0)) < quantity and abs((bid or 0) - (currentItem.bid or 0)) < quantity and (not TSM.db.global.cancelWithBid and activeBid == 0 or TSM.db.global.cancelWithBid) then
|
||||
if not tempIndexList[itemString..buyout..bid..i] then
|
||||
tempIndexList[itemString..buyout..bid..i] = true
|
||||
index = i
|
||||
break
|
||||
else
|
||||
backupIndex = i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if we found an index then cancel the item
|
||||
if index then
|
||||
CancelAuction(index)
|
||||
elseif backupIndex then
|
||||
CancelAuction(backupIndex)
|
||||
end
|
||||
|
||||
-- disable the button and move onto the next item
|
||||
GUI.buttons:Disable()
|
||||
tinsert(itemsCancelled, CopyTable(cancelQueue[1]))
|
||||
tremove(cancelQueue, 1)
|
||||
Cancel:UpdateItem()
|
||||
end
|
||||
|
||||
-- gets called when the "Skip Item" button is pressed
|
||||
function Cancel:SkipItem()
|
||||
tremove(cancelQueue, 1)
|
||||
count = count + 1
|
||||
TSM.Manage:UpdateStatus("confirm", count, totalToCancel)
|
||||
Cancel:UpdateItem()
|
||||
end
|
||||
|
||||
-- we are done canceling (maybe)
|
||||
function Cancel:Stop(interrupted)
|
||||
wipe(tempIndexList)
|
||||
if #itemsMissed == 0 or interrupted then
|
||||
-- didn't get "item not found" for any cancels or we were interrupted so we are done
|
||||
TSMAPI:CancelFrame("cancelCountFrame")
|
||||
TSMAPI:CancelFrame("cancelDelayFrame")
|
||||
TSMAPI:CancelFrame("updateCancelStatus")
|
||||
GUI:Stopped()
|
||||
|
||||
Cancel:UnregisterAllEvents()
|
||||
wipe(currentItem)
|
||||
totalToCancel, totalCanceled = 0, 0
|
||||
isScanning = false
|
||||
else -- got an "item not found" so requeue ones that we missed
|
||||
count = totalToCancel
|
||||
for _, info in ipairs(itemsMissed) do
|
||||
Cancel:ProcessItem(info.itemString, true)
|
||||
end
|
||||
wipe(itemsMissed)
|
||||
isScanning = false
|
||||
Cancel:UpdateItem()
|
||||
end
|
||||
end
|
||||
|
||||
function Cancel:DoneScanning()
|
||||
isScanning = false
|
||||
return totalToCancel
|
||||
end
|
||||
|
||||
function Cancel:GetCurrentItem()
|
||||
return currentItem
|
||||
end
|
||||
@@ -0,0 +1,957 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
local GUI = TSM:NewModule("GUI", "AceEvent-3.0", "AceHook-3.0")
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
local private = {}
|
||||
|
||||
function private:CreateButtons(parent)
|
||||
local height = 24
|
||||
local frame = CreateFrame("Frame", nil, parent)
|
||||
frame:SetHeight(height)
|
||||
frame:SetWidth(210)
|
||||
frame:SetPoint("BOTTOMRIGHT", -92, 5)
|
||||
|
||||
frame.Enable = function(self)
|
||||
if private.mode == "Post" then
|
||||
self.post:Enable()
|
||||
elseif private.mode == "Cancel" then
|
||||
self.cancel:Enable()
|
||||
end
|
||||
self.skip:Enable()
|
||||
self.stop:Enable()
|
||||
end
|
||||
|
||||
frame.Disable = function(self)
|
||||
if private.mode == "Post" then
|
||||
self.post:Disable()
|
||||
elseif private.mode == "Cancel" then
|
||||
self.cancel:Disable()
|
||||
end
|
||||
self.skip:Disable()
|
||||
end
|
||||
|
||||
frame.UpdateMode = function(self)
|
||||
if private.mode == "Post" then
|
||||
self.post:Show()
|
||||
self.cancel:Hide()
|
||||
self.cancel:Disable()
|
||||
elseif private.mode == "Cancel" then
|
||||
self.post:Hide()
|
||||
self.post:Disable()
|
||||
self.cancel:Show()
|
||||
end
|
||||
self.stop:Enable()
|
||||
end
|
||||
|
||||
local function OnClick(self)
|
||||
if self.which == "stop" and self.isDone then
|
||||
GUI:HideSelectionFrame()
|
||||
private.selectionFrame:Show()
|
||||
elseif frame:IsVisible() and private.OnAction then
|
||||
private:OnAction(self.which)
|
||||
end
|
||||
end
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 22, "TSMAuctioningPostButton")
|
||||
button:SetPoint("TOPLEFT")
|
||||
button:SetWidth(80)
|
||||
button:SetHeight(height)
|
||||
button:SetText(L["Post"])
|
||||
button.which = "action"
|
||||
button:SetScript("OnClick", OnClick)
|
||||
frame.post = button
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 22, "TSMAuctioningCancelButton")
|
||||
button:SetPoint("TOPLEFT")
|
||||
button:SetWidth(80)
|
||||
button:SetHeight(height)
|
||||
button:SetText(L["Cancel"])
|
||||
button.which = "action"
|
||||
button:SetScript("OnClick", OnClick)
|
||||
frame.cancel = button
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 18)
|
||||
button:SetPoint("TOPLEFT", frame.post, "TOPRIGHT", 5, 0)
|
||||
button:SetWidth(60)
|
||||
button:SetHeight(height)
|
||||
button:SetText(L["Skip"])
|
||||
button.which = "skip"
|
||||
button:SetScript("OnClick", OnClick)
|
||||
frame.skip = button
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 18)
|
||||
button:SetPoint("TOPLEFT", frame.skip, "TOPRIGHT", 5, 0)
|
||||
button:SetWidth(70)
|
||||
button:SetHeight(height)
|
||||
button:SetText(L["Stop"])
|
||||
button.which = "stop"
|
||||
button:SetScript("OnClick", OnClick)
|
||||
frame.stop = button
|
||||
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function private:CreateContentButtons(parent)
|
||||
local frame = CreateFrame("Frame", nil, parent)
|
||||
frame:SetAllPoints(parent)
|
||||
|
||||
frame.UpdateMode = function(self)
|
||||
if private.mode == "Post" then
|
||||
self.currAuctionsButton:Show()
|
||||
self.editPriceButton:Show()
|
||||
self.editPriceButton:Disable()
|
||||
elseif private.mode == "Cancel" then
|
||||
self.currAuctionsButton:Show()
|
||||
self.editPriceButton:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
frame.UnlockHighlight = function(self)
|
||||
self.auctionsButton:UnlockHighlight()
|
||||
self.logButton:UnlockHighlight()
|
||||
self.currAuctionsButton:UnlockHighlight()
|
||||
self.editPriceButton:UnlockHighlight()
|
||||
end
|
||||
|
||||
local function OnClick(self)
|
||||
frame:UnlockHighlight()
|
||||
self:LockHighlight()
|
||||
frame.editPriceFrame:Hide()
|
||||
|
||||
if self.which == "log" then
|
||||
private.auctionsST:Hide()
|
||||
private.logST:Show()
|
||||
private:UpdateLogSTData()
|
||||
elseif self.which == "auctions" then
|
||||
private.logST:Hide()
|
||||
private.auctionsST:Show()
|
||||
private.auctionsST.isCurrentItem = nil
|
||||
private:UpdateAuctionsSTData()
|
||||
elseif self.which == "currAuctions" then
|
||||
private.logST:Hide()
|
||||
private.auctionsST:Show()
|
||||
private.auctionsST.isCurrentItem = true
|
||||
private:UpdateAuctionsSTData()
|
||||
elseif self.which == "editPrice" then
|
||||
frame.editPriceFrame:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local auctionsButton = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
auctionsButton:SetPoint("TOPRIGHT", -10, -20)
|
||||
auctionsButton:SetHeight(17)
|
||||
auctionsButton:SetWidth(150)
|
||||
auctionsButton.which = "auctions"
|
||||
auctionsButton:SetScript("OnClick", OnClick)
|
||||
auctionsButton:SetText(L["Show All Auctions"])
|
||||
frame.auctionsButton = auctionsButton
|
||||
|
||||
local currAuctionsButton = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
currAuctionsButton:SetPoint("TOPRIGHT", -170, -20)
|
||||
currAuctionsButton:SetHeight(17)
|
||||
currAuctionsButton:SetWidth(150)
|
||||
currAuctionsButton.which = "currAuctions"
|
||||
currAuctionsButton:SetScript("OnClick", OnClick)
|
||||
currAuctionsButton:SetText(L["Show Item Auctions"])
|
||||
frame.currAuctionsButton = currAuctionsButton
|
||||
|
||||
local logButton = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
logButton:SetPoint("TOPRIGHT", -10, -45)
|
||||
logButton:SetHeight(17)
|
||||
logButton:SetWidth(150)
|
||||
logButton.which = "log"
|
||||
logButton:SetScript("OnClick", OnClick)
|
||||
logButton:SetText(L["Show Log"])
|
||||
frame.logButton = logButton
|
||||
|
||||
local editPriceButton = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
editPriceButton:SetPoint("TOPRIGHT", -170, -45)
|
||||
editPriceButton:SetHeight(17)
|
||||
editPriceButton:SetWidth(150)
|
||||
editPriceButton.which = "editPrice"
|
||||
editPriceButton:SetScript("OnClick", OnClick)
|
||||
editPriceButton:SetText(L["Edit Post Price"])
|
||||
frame.editPriceButton = editPriceButton
|
||||
|
||||
local editPriceFrame = CreateFrame("Frame", nil, frame)
|
||||
TSMAPI.Design:SetFrameBackdropColor(editPriceFrame)
|
||||
editPriceFrame:SetPoint("CENTER")
|
||||
editPriceFrame:SetFrameStrata("DIALOG")
|
||||
editPriceFrame:SetWidth(300)
|
||||
editPriceFrame:SetHeight(150)
|
||||
editPriceFrame:EnableMouse(true)
|
||||
editPriceFrame:SetScript("OnShow", function(self)
|
||||
editPriceFrame:SetFrameStrata("DIALOG")
|
||||
MoneyInputFrame_SetCopper(TSMPostPriceChangeBox, self.info.buyout)
|
||||
self.linkLabel:SetText(self.info.link)
|
||||
end)
|
||||
editPriceFrame:SetScript("OnUpdate", function()
|
||||
if not TSMAPI:AHTabIsVisible("Auctioning") then
|
||||
editPriceFrame:Hide()
|
||||
end
|
||||
end)
|
||||
frame.editPriceFrame = editPriceFrame
|
||||
|
||||
local linkLabel = TSMAPI.GUI:CreateLabel(editPriceFrame)
|
||||
linkLabel:SetPoint("TOP", 0, -14)
|
||||
linkLabel:SetJustifyH("CENTER")
|
||||
linkLabel:SetText("")
|
||||
editPriceFrame.linkLabel = linkLabel
|
||||
|
||||
local bg = editPriceFrame:CreateTexture(nil, "BACKGROUND")
|
||||
bg:SetPoint("TOPLEFT", linkLabel, -2, 2)
|
||||
bg:SetPoint("BOTTOMRIGHT", linkLabel, 2, -2)
|
||||
TSMAPI.Design:SetContentColor(bg)
|
||||
linkLabel.bg = bg
|
||||
|
||||
local priceBoxLabel = TSMAPI.GUI:CreateLabel(editPriceFrame)
|
||||
priceBoxLabel:SetPoint("TOPLEFT", 14, -40)
|
||||
priceBoxLabel:SetText(L["Auction Buyout (Stack Price):"])
|
||||
editPriceFrame.priceBoxLabel = priceBoxLabel
|
||||
|
||||
local priceBox = CreateFrame("Frame", "TSMPostPriceChangeBox", editPriceFrame, "MoneyInputFrameTemplate")
|
||||
priceBox:SetPoint("TOPLEFT", 20, -60)
|
||||
priceBox:SetHeight(20)
|
||||
priceBox:SetWidth(120)
|
||||
editPriceFrame.priceBox = priceBox
|
||||
|
||||
local saveButton = TSMAPI.GUI:CreateButton(editPriceFrame, 16)
|
||||
saveButton:SetPoint("BOTTOMLEFT", 10, 10)
|
||||
saveButton:SetPoint("BOTTOMRIGHT", editPriceFrame, "BOTTOM", -2, 10)
|
||||
saveButton:SetHeight(20)
|
||||
saveButton:SetScript("OnClick", function()
|
||||
TSM.Post:EditPostPrice(editPriceFrame.info.itemString, MoneyInputFrame_GetCopper(TSMPostPriceChangeBox), editPriceFrame.info.operation)
|
||||
editPriceFrame:Hide()
|
||||
end)
|
||||
saveButton:SetText(L["Save New Price"])
|
||||
editPriceFrame.saveButton = saveButton
|
||||
|
||||
local cancelButton = TSMAPI.GUI:CreateButton(editPriceFrame, 16)
|
||||
cancelButton:SetPoint("BOTTOMLEFT", editPriceFrame, "BOTTOM", 2, 10)
|
||||
cancelButton:SetPoint("BOTTOMRIGHT", -10, 10)
|
||||
cancelButton:SetHeight(20)
|
||||
cancelButton:SetScript("OnClick", function()
|
||||
editPriceFrame:Hide()
|
||||
end)
|
||||
cancelButton:SetText(L["Cancel"])
|
||||
editPriceFrame.cancelButton = cancelButton
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function private:CreateInfoText(parent)
|
||||
local frame = CreateFrame("Frame", nil, parent)
|
||||
frame:SetAllPoints()
|
||||
|
||||
frame.SetInfo = function(self, info)
|
||||
private:UpdateLogSTHighlight()
|
||||
if type(info) == "string" then
|
||||
self.icon:Hide()
|
||||
self.linkText:Hide()
|
||||
self.linkText.bg:Hide()
|
||||
self.stackText:Hide()
|
||||
self.bidText:Hide()
|
||||
self.buyoutText:Hide()
|
||||
self.quantityText:Hide()
|
||||
self.statusText:Show()
|
||||
|
||||
local status, _, gold, gold2 = ("\n"):split(info)
|
||||
if gold then
|
||||
self.goldText:Show()
|
||||
self.goldText2:Show()
|
||||
self.goldText:SetText(gold)
|
||||
self.goldText2:SetText(gold2)
|
||||
else
|
||||
self.goldText:Hide()
|
||||
self.goldText2:Hide()
|
||||
end
|
||||
self.statusText:SetText(status)
|
||||
elseif info.isReset then
|
||||
self.icon:Show()
|
||||
self.linkText:Show()
|
||||
self.linkText.bg:Show()
|
||||
self.stackText:Show()
|
||||
self.bidText:Show()
|
||||
self.buyoutText:Show()
|
||||
self.statusText:Hide()
|
||||
self.goldText:Hide()
|
||||
self.goldText2:Hide()
|
||||
|
||||
local itemID = TSMAPI:GetItemID(info.itemString)
|
||||
local total = TSM.Reset:GetTotalQuantity(info.itemString)
|
||||
self.quantityText:Show()
|
||||
self.quantityText:SetText(TSMAPI.Design:GetInlineColor("link")..L["Currently Owned:"].."|r "..total)
|
||||
|
||||
local _,link,_,_,_,_,_,_,_,texture = TSMAPI:GetSafeItemInfo(info.itemString)
|
||||
self.linkText:SetText(link)
|
||||
if self.linkText:GetStringWidth() > 200 then
|
||||
self.linkText:SetWidth(200)
|
||||
else
|
||||
self.linkText:SetWidth(self.linkText:GetStringWidth())
|
||||
end
|
||||
self.icon.link = link
|
||||
self.icon:GetNormalTexture():SetTexture(texture)
|
||||
self.stackText:SetText(format(L["%s item(s) to buy/cancel"], info.num..TSMAPI.Design:GetInlineColor("link")))
|
||||
self.bidText:SetText(TSMAPI.Design:GetInlineColor("link")..L["Target Price:"].."|r "..TSMAPI:FormatTextMoneyIcon(info.targetPrice))
|
||||
self.buyoutText:SetText(TSMAPI.Design:GetInlineColor("link")..L["Profit:"].."|r "..TSMAPI:FormatTextMoneyIcon(info.profit))
|
||||
else
|
||||
self.icon:Show()
|
||||
self.linkText:Show()
|
||||
self.linkText.bg:Show()
|
||||
self.stackText:Show()
|
||||
self.bidText:Show()
|
||||
self.buyoutText:Show()
|
||||
self.statusText:Hide()
|
||||
self.quantityText:Hide()
|
||||
self.goldText:Hide()
|
||||
self.goldText2:Hide()
|
||||
|
||||
local _,link,_,_,_,_,_,_,_,texture = TSMAPI:GetSafeItemInfo(info.itemString)
|
||||
self.linkText:SetText(link)
|
||||
if self.linkText:GetStringWidth() > 200 then
|
||||
self.linkText:SetWidth(200)
|
||||
else
|
||||
self.linkText:SetWidth(self.linkText:GetStringWidth())
|
||||
end
|
||||
self.icon.link = link
|
||||
self.icon:GetNormalTexture():SetTexture(texture)
|
||||
|
||||
local sText = format("%s "..TSMAPI.Design:GetInlineColor("link")..L["auctions of|r %s"], info.numStacks, info.stackSize)
|
||||
self.stackText:SetText(sText)
|
||||
|
||||
self.bidText:SetText(TSMAPI.Design:GetInlineColor("link")..BID..":|r "..TSMAPI:FormatTextMoneyIcon(info.bid))
|
||||
self.buyoutText:SetText(TSMAPI.Design:GetInlineColor("link")..BUYOUT..":|r "..TSMAPI:FormatTextMoneyIcon(info.buyout))
|
||||
|
||||
private.contentButtons.editPriceButton:Enable()
|
||||
private.contentButtons.editPriceFrame.itemString = info.itemString
|
||||
private.contentButtons.editPriceFrame.info = {itemString=info.itemString, link=link, buyout=info.buyout, operation=info.operation}
|
||||
|
||||
TSMAPI:CreateTimeDelay("AuctioningLogHLDelay", 0.01, function() private:UpdateLogSTHighlight(info) end)
|
||||
end
|
||||
end
|
||||
|
||||
frame.UpdateMode = function(self) end
|
||||
|
||||
local icon = CreateFrame("Button", nil, frame)
|
||||
icon:SetPoint("TOPLEFT", 85, -20)
|
||||
icon:SetWidth(50)
|
||||
icon:SetHeight(50)
|
||||
local tex = icon:CreateTexture()
|
||||
tex:SetAllPoints(icon)
|
||||
icon:SetNormalTexture(tex)
|
||||
icon:SetScript("OnEnter", function(self)
|
||||
if self.link and self.link ~= "" then
|
||||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||||
TSMAPI:SafeTooltipLink(self.link)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end)
|
||||
icon:SetScript("OnLeave", function()
|
||||
--BattlePetTooltip:Hide()
|
||||
GameTooltip:ClearLines()
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
frame.icon = icon
|
||||
|
||||
local linkText = TSMAPI.GUI:CreateLabel(frame)
|
||||
linkText:SetPoint("LEFT", icon, "RIGHT", 4, 0)
|
||||
linkText:SetJustifyH("LEFT")
|
||||
linkText:SetJustifyV("CENTER")
|
||||
frame.linkText = linkText
|
||||
|
||||
local bg = frame:CreateTexture(nil, "BACKGROUND")
|
||||
bg:SetPoint("TOPLEFT", linkText, -2, 2)
|
||||
bg:SetPoint("BOTTOMRIGHT", linkText, 2, -2)
|
||||
TSMAPI.Design:SetContentColor(bg)
|
||||
linkText.bg = bg
|
||||
|
||||
local stackText = TSMAPI.GUI:CreateLabel(frame)
|
||||
stackText:SetPoint("TOPLEFT", 350, -18)
|
||||
stackText:SetWidth(175)
|
||||
stackText:SetHeight(18)
|
||||
stackText:SetJustifyH("LEFT")
|
||||
stackText:SetJustifyV("CENTER")
|
||||
frame.stackText = stackText
|
||||
|
||||
local bidText = TSMAPI.GUI:CreateLabel(frame)
|
||||
bidText:SetPoint("TOPLEFT", 350, -38)
|
||||
bidText:SetWidth(175)
|
||||
bidText:SetHeight(18)
|
||||
bidText:SetJustifyH("LEFT")
|
||||
bidText:SetJustifyV("CENTER")
|
||||
frame.bidText = bidText
|
||||
|
||||
local buyoutText = TSMAPI.GUI:CreateLabel(frame)
|
||||
buyoutText:SetPoint("TOPLEFT", 350, -58)
|
||||
buyoutText:SetWidth(175)
|
||||
buyoutText:SetHeight(18)
|
||||
buyoutText:SetJustifyH("LEFT")
|
||||
buyoutText:SetJustifyV("CENTER")
|
||||
frame.buyoutText = buyoutText
|
||||
|
||||
local statusText = TSMAPI.GUI:CreateLabel(frame)
|
||||
statusText:SetPoint("TOP", frame, "TOPLEFT", 300, -15)
|
||||
statusText:SetJustifyH("CENTER")
|
||||
statusText:SetJustifyV("CENTER")
|
||||
frame.statusText = statusText
|
||||
|
||||
local goldText = TSMAPI.GUI:CreateLabel(frame)
|
||||
goldText:SetPoint("TOP", statusText, "BOTTOM", 0, -15)
|
||||
goldText:SetJustifyH("CENTER")
|
||||
goldText:SetJustifyV("CENTER")
|
||||
frame.goldText = goldText
|
||||
|
||||
local goldText2 = TSMAPI.GUI:CreateLabel(frame)
|
||||
goldText2:SetPoint("TOP", goldText, "BOTTOM")
|
||||
goldText2:SetJustifyH("CENTER")
|
||||
goldText2:SetJustifyV("CENTER")
|
||||
frame.goldText2 = goldText2
|
||||
|
||||
local quantityText = TSMAPI.GUI:CreateLabel(frame)
|
||||
quantityText:SetPoint("TOPLEFT", 535, -58)
|
||||
quantityText:SetWidth(175)
|
||||
quantityText:SetHeight(18)
|
||||
quantityText:SetJustifyH("LEFT")
|
||||
quantityText:SetJustifyV("CENTER")
|
||||
frame.quantityText = quantityText
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function private:CreateAuctionsST(parent)
|
||||
local frame = CreateFrame("Frame", nil, parent)
|
||||
frame:SetAllPoints()
|
||||
|
||||
local handlers = {
|
||||
OnClick = function(_, data, self, button)
|
||||
end,
|
||||
}
|
||||
|
||||
local rt = TSMAPI:CreateAuctionResultsTable(frame, handlers)
|
||||
rt:SetData({})
|
||||
rt:SetSort(7, true)
|
||||
rt:Hide()
|
||||
|
||||
return rt
|
||||
end
|
||||
|
||||
function private:CreateLogST(parent)
|
||||
local function GetPriceColumnText()
|
||||
if TSM.db.global.priceColumn == 1 then
|
||||
return L["Your Buyout"]
|
||||
elseif TSM.db.global.priceColumn == 2 then
|
||||
return L["Lowest Buyout"]
|
||||
end
|
||||
end
|
||||
|
||||
local stCols = {
|
||||
{
|
||||
name = L["Item"],
|
||||
width = 0.31,
|
||||
},
|
||||
{
|
||||
name = L["Operation"],
|
||||
width = 0.17,
|
||||
align = "Center"
|
||||
},
|
||||
{
|
||||
name = GetPriceColumnText(),
|
||||
width = 0.12,
|
||||
align = "RIGHT",
|
||||
},
|
||||
{
|
||||
name = L["Seller"],
|
||||
width = 0.11,
|
||||
align = "CENTER",
|
||||
},
|
||||
{
|
||||
name = L["Info"],
|
||||
width = 0.28,
|
||||
align = "LEFT",
|
||||
},
|
||||
{
|
||||
name = "",
|
||||
width = 0,
|
||||
},
|
||||
}
|
||||
|
||||
local handlers = {
|
||||
OnEnter = function(_, data, self)
|
||||
if not data.operation then return end
|
||||
local prices = TSM.Util:GetItemPrices(data.operation, data.itemString)
|
||||
GameTooltip:SetOwner(self, "ANCHOR_NONE")
|
||||
GameTooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT")
|
||||
GameTooltip:AddLine(data.link)
|
||||
GameTooltip:AddLine("Crafting Cost:".." "..(TSMAPI:FormatTextMoney(prices.cost, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Minimum Price:"].." "..(TSMAPI:FormatTextMoney(prices.minPrice, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Maximum Price:"].." "..(TSMAPI:FormatTextMoney(prices.maxPrice, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Normal Price:"].." "..(TSMAPI:FormatTextMoney(prices.normalPrice, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Lowest Buyout:"].." |r"..(TSMAPI:FormatTextMoney(data.lowestBuyout, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Log Info:"].." "..data.info)
|
||||
GameTooltip:AddLine("\n"..TSMAPI.Design:GetInlineColor("link2")..L["Click to show auctions for this item."].."|r".." ") -- the blank space is to fix formating.
|
||||
GameTooltip:AddLine(TSMAPI.Design:GetInlineColor("link2")..format(L["Right-Click to add %s to your friends list."], "|r"..(data.seller or "---")..TSMAPI.Design:GetInlineColor("link2")).."|r")
|
||||
GameTooltip:AddLine(TSMAPI.Design:GetInlineColor("link2")..L["Shift-Right-Click to show the options for this operation.".."|r"])
|
||||
GameTooltip:Show()
|
||||
end,
|
||||
OnLeave = function()
|
||||
GameTooltip:Hide()
|
||||
end,
|
||||
OnClick = function(_, data, _, button)
|
||||
if button == "LeftButton" then
|
||||
private.contentButtons:UnlockHighlight()
|
||||
private.logST:Hide()
|
||||
private.auctionsST:Show()
|
||||
private.auctionsST.isCurrentItem = data.itemString
|
||||
private:UpdateAuctionsSTData()
|
||||
elseif button == "RightButton" then
|
||||
if IsShiftKeyDown() then
|
||||
TSMAPI:ShowOperationOptions("Auctioning", TSM.operationNameLookup[data.operation])
|
||||
else
|
||||
if data.seller then
|
||||
AddFriend(data.seller)
|
||||
else
|
||||
TSM:Print(L["This item does not have any seller data."])
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
OnColumnClick = function(self, button)
|
||||
if self.colNum == 3 and button == "RightButton" then
|
||||
TSM.db.global.priceColumn = TSM.db.global.priceColumn + 1
|
||||
TSM.db.global.priceColumn = TSM.db.global.priceColumn > 2 and 1 or TSM.db.global.priceColumn
|
||||
self:SetText(GetPriceColumnText())
|
||||
wipe(private.logST.cache)
|
||||
private:UpdateLogSTData()
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local st = TSMAPI:CreateScrollingTable(parent, stCols, handlers)
|
||||
st:SetParent(parent)
|
||||
st:SetAllPoints()
|
||||
st:EnableSorting(true, 6)
|
||||
st:DisableSelection(true)
|
||||
return st
|
||||
end
|
||||
|
||||
function private:UpdateAuctionsSTData()
|
||||
if not private.auctionsST:IsVisible() or not private.auctionsST.sortInfo then return end
|
||||
|
||||
local results = {}
|
||||
if private.auctionsST.isCurrentItem then
|
||||
local itemString
|
||||
if type(private.auctionsST.isCurrentItem) == "string" or type(private.auctionsST.isCurrentItem) == "number" then
|
||||
itemString = private.auctionsST.isCurrentItem
|
||||
else
|
||||
itemString = TSM[private.mode]:GetCurrentItem().itemString
|
||||
end
|
||||
if itemString and TSM.Scan.auctionData[itemString] then
|
||||
tinsert(results, TSM.Scan.auctionData[itemString])
|
||||
private.auctionsST:SetExpanded(itemString, true)
|
||||
end
|
||||
else
|
||||
for _, auction in pairs(TSM.Scan.auctionData) do
|
||||
-- combine auctions with the same buyout / count / seller
|
||||
tinsert(results, auction)
|
||||
end
|
||||
end
|
||||
|
||||
private.auctionsST:SetData(results)
|
||||
end
|
||||
|
||||
function private:GetLogSTRow(record, recordIndex)
|
||||
if private.logST.cache[record] then
|
||||
return private.logST.cache[record]
|
||||
end
|
||||
|
||||
local name, link = TSMAPI:GetSafeItemInfo(record.itemString)
|
||||
local buyout, seller, isWhitelist, isPlayer, lowestBuyout, _
|
||||
if record.reason ~= "cancelAll" then
|
||||
buyout, _, seller, isWhitelist, isPlayer = TSM.Scan:GetLowestAuction(record.itemString, record.operation)
|
||||
lowestBuyout = buyout
|
||||
if TSM.db.global.priceColumn == 1 then
|
||||
buyout = record.buyout
|
||||
end
|
||||
end
|
||||
|
||||
local sellerText
|
||||
if seller then
|
||||
if isPlayer then
|
||||
sellerText = "|cffffff00"..seller.."|r"
|
||||
elseif isWhiteList then
|
||||
sellerText = TSMAPI.Design:GetInlineColor("link2")..seller.."|r"
|
||||
else
|
||||
sellerText = "|cffffffff"..seller.."|r"
|
||||
end
|
||||
else
|
||||
sellerText = "|cffffffff---|r"
|
||||
end
|
||||
|
||||
local color = TSM.Log:GetColor(record.mode, record.reason)
|
||||
local infoText = (color or "|cffffffff")..(record.info or "---").."|r"
|
||||
|
||||
local row = {
|
||||
cols = {
|
||||
{
|
||||
value = link,
|
||||
sortArg = name or "",
|
||||
},
|
||||
{
|
||||
value = record.operation and TSM.operationNameLookup[record.operation] or "---",
|
||||
sortArg = record.operation and TSM.operationNameLookup[record.operation] or "---",
|
||||
},
|
||||
{
|
||||
value = TSMAPI:FormatTextMoney(buyout, nil, true) or "---",
|
||||
sortArg = buyout or 0,
|
||||
},
|
||||
{
|
||||
value = sellerText,
|
||||
sortArg = seller or "~",
|
||||
},
|
||||
{
|
||||
value = infoText,
|
||||
sortArg = record.info or "~",
|
||||
},
|
||||
{ -- invisible column at the end for default sorting
|
||||
value = "",
|
||||
sortArg = recordIndex,
|
||||
},
|
||||
},
|
||||
link = link or name or itemString,
|
||||
itemString = record.itemString,
|
||||
operation = record.operation,
|
||||
buyout = buyout,
|
||||
lowestBuyout = lowestBuyout,
|
||||
seller = seller,
|
||||
info = infoText,
|
||||
}
|
||||
|
||||
private.logST.cache[record] = row
|
||||
return row
|
||||
end
|
||||
|
||||
function private:UpdateLogSTData()
|
||||
local rows = {}
|
||||
for i, record in ipairs(TSM.Log:GetData()) do
|
||||
tinsert(rows, private:GetLogSTRow(record, i))
|
||||
end
|
||||
private.logST:SetData(rows)
|
||||
|
||||
if #private.logST.rowData > private.logST.NUM_ROWS then
|
||||
TSMAPI:CreateTimeDelay("logSTOffset", 0.08, function()
|
||||
private.logST:SetScrollOffset(#private.logST.rowData - private.logST.NUM_ROWS)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function private:UpdateLogSTHighlight(currentItem)
|
||||
if not currentItem then return private.logST:SetHighlighted() end
|
||||
|
||||
for i=1, #private.logST.rowData do
|
||||
local data = private.logST.rowData[i]
|
||||
if data and data.operation == currentItem.operation and data.itemString == currentItem.itemString then
|
||||
private.logST:SetHighlighted(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function private:UpdateSTData()
|
||||
private:UpdateLogSTData()
|
||||
private:UpdateAuctionsSTData()
|
||||
end
|
||||
|
||||
local function SetGoldText()
|
||||
local line1, line2 = TSM.Post:GetAHGoldTotal()
|
||||
local text = format(L["Done Posting\n\nTotal value of your auctions: %s\nIncoming Gold: %s"], line1, line2)
|
||||
private.infoText:SetInfo(text)
|
||||
end
|
||||
|
||||
function private:Stopped(notDone)
|
||||
TSM.Manage:UnregisterAllMessages()
|
||||
private.buttons:Disable(true)
|
||||
private.statusBar:UpdateStatus(100, 100)
|
||||
private.contentButtons.currAuctionsButton:Hide()
|
||||
|
||||
if private.mode == "Post" then
|
||||
TSMAPI:CreateTimeDelay(0.5, SetGoldText)
|
||||
SetGoldText()
|
||||
private.statusBar:SetStatusText(L["Post Scan Finished"])
|
||||
elseif private.mode == "Cancel" then
|
||||
private.infoText:SetInfo(L["Done Canceling"])
|
||||
private.statusBar:SetStatusText(L["Cancel Scan Finished"])
|
||||
elseif private.mode == "Reset" then
|
||||
if not notDone then
|
||||
private.infoText:SetInfo(L["No Items to Reset"])
|
||||
end
|
||||
private.statusBar:SetStatusText(L["Reset Scan Finished"])
|
||||
end
|
||||
private.buttons.stop:SetText(L["Restart"])
|
||||
private.buttons.stop.isDone = true
|
||||
end
|
||||
|
||||
|
||||
function GUI:CreateSelectionFrame(parent)
|
||||
local frame = CreateFrame("Frame", nil, parent.content)
|
||||
frame:SetAllPoints()
|
||||
TSMAPI.Design:SetFrameBackdropColor(frame)
|
||||
|
||||
local stContainer = CreateFrame("Frame", nil, frame)
|
||||
stContainer:SetPoint("TOPLEFT", 5, -20)
|
||||
stContainer:SetPoint("BOTTOMRIGHT", -200, 30)
|
||||
TSMAPI.Design:SetFrameColor(stContainer)
|
||||
frame.groupTree = TSMAPI:CreateGroupTree(stContainer, "Auctioning", "Auctioning_AH")
|
||||
|
||||
-- top row (auto updater)
|
||||
local text = TSMAPI.GUI:CreateLabel(stContainer)
|
||||
text:SetFont(TSMAPI.Design:GetContentFont(), 24)
|
||||
text:SetPoint("TOP", 96, 76)
|
||||
text:SetHeight(24)
|
||||
text:SetJustifyH("CENTER")
|
||||
text:SetJustifyV("CENTER")
|
||||
text:SetText(TSMAPI.Design:GetInlineColor("link").."TSM_Auctioning")
|
||||
local ag = text:CreateAnimationGroup()
|
||||
local a1 = ag:CreateAnimation("Alpha")
|
||||
a1:SetChange(-.5)
|
||||
a1:SetDuration(.5)
|
||||
ag:SetLooping("BOUNCE")
|
||||
ag:Play()
|
||||
|
||||
local helpText = TSMAPI.GUI:CreateLabel(frame)
|
||||
helpText:SetPoint("TOP", stContainer, 0, 20)
|
||||
helpText:SetJustifyH("CENTER")
|
||||
helpText:SetJustifyV("CENTER")
|
||||
helpText:SetText(L["Select the groups which you would like to include in the scan."])
|
||||
frame.helpText = helpText
|
||||
|
||||
local btnWidth = floor((stContainer:GetWidth() - 10)/3)
|
||||
local postBtn = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
postBtn:SetPoint("BOTTOMLEFT", 5, 5)
|
||||
postBtn:SetHeight(20)
|
||||
postBtn:SetWidth(btnWidth)
|
||||
postBtn:SetText(L["Start Post Scan"])
|
||||
postBtn:SetScript("OnClick", function()
|
||||
private.mode = "Post"
|
||||
private.specialMode = nil
|
||||
GUI:StartScan(parent)
|
||||
end)
|
||||
frame.postBtn = postBtn
|
||||
|
||||
local cancelBtn = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
cancelBtn:SetPoint("BOTTOMLEFT", postBtn, "BOTTOMRIGHT", 5, 0)
|
||||
cancelBtn:SetHeight(20)
|
||||
cancelBtn:SetWidth(btnWidth)
|
||||
cancelBtn:SetText(L["Start Cancel Scan"])
|
||||
cancelBtn:SetScript("OnClick", function()
|
||||
private.mode = "Cancel"
|
||||
private.specialMode = nil
|
||||
GUI:StartScan(parent)
|
||||
end)
|
||||
frame.cancelBtn = cancelBtn
|
||||
|
||||
local resetBtn = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
resetBtn:SetPoint("BOTTOMLEFT", cancelBtn, "BOTTOMRIGHT", 5, 0)
|
||||
resetBtn:SetHeight(20)
|
||||
resetBtn:SetWidth(btnWidth)
|
||||
resetBtn:SetText(L["Start Reset Scan"])
|
||||
resetBtn:SetScript("OnClick", function()
|
||||
private.mode = "Reset"
|
||||
private.specialMode = nil
|
||||
GUI:StartScan(parent)
|
||||
end)
|
||||
frame.resetBtn = resetBtn
|
||||
|
||||
local customScanFrame = CreateFrame("Frame", nil, frame)
|
||||
customScanFrame:SetPoint("TOPLEFT", stContainer:GetWidth() + 10, 0)
|
||||
customScanFrame:SetPoint("BOTTOMRIGHT")
|
||||
TSMAPI.Design:SetFrameColor(customScanFrame)
|
||||
private.customScanFrame = customScanFrame
|
||||
|
||||
local title = TSMAPI.GUI:CreateLabel(customScanFrame)
|
||||
title:SetPoint("TOP", 0, -2)
|
||||
title:SetJustifyH("CENTER")
|
||||
title:SetJustifyV("CENTER")
|
||||
title:SetText(L["Other Auctioning Searches"])
|
||||
customScanFrame.title = title
|
||||
|
||||
TSMAPI.GUI:CreateHorizontalLine(customScanFrame, -20)
|
||||
|
||||
local cancelAllBtn = TSMAPI.GUI:CreateButton(customScanFrame, 16)
|
||||
cancelAllBtn:SetPoint("TOPLEFT", 4, -24)
|
||||
cancelAllBtn:SetPoint("TOPRIGHT", -4, -24)
|
||||
cancelAllBtn:SetHeight(20)
|
||||
cancelAllBtn:SetText(L["Cancel All Auctions"])
|
||||
cancelAllBtn:SetScript("OnClick", function()
|
||||
private.mode = "Cancel"
|
||||
private.specialMode = "CancelAll"
|
||||
GUI:StartScan(parent)
|
||||
end)
|
||||
cancelAllBtn.tooltip = L["Will cancel all your auctions, including ones which you didn't post with Auctioning."]
|
||||
customScanFrame.cancelAllBtn = cancelAllBtn
|
||||
|
||||
TSMAPI.GUI:CreateHorizontalLine(customScanFrame, -48)
|
||||
|
||||
local cancelFilterText = TSMAPI.GUI:CreateLabel(customScanFrame, "small")
|
||||
cancelFilterText:SetPoint("TOPLEFT", 4, -52)
|
||||
cancelFilterText:SetPoint("TOPRIGHT", -4, -52)
|
||||
cancelFilterText:SetJustifyH("LEFT")
|
||||
cancelFilterText:SetJustifyV("CENTER")
|
||||
cancelFilterText:SetText(L["Cancel Filter:"])
|
||||
customScanFrame.cancelFilterText = cancelFilterText
|
||||
|
||||
local filterEditBox = TSMAPI.GUI:CreateInputBox(customScanFrame, "TSMAuctioningFilterSearchEditbox")
|
||||
filterEditBox:SetPoint("TOPLEFT", 4, -72)
|
||||
filterEditBox:SetPoint("TOPRIGHT", -4, -72)
|
||||
filterEditBox:SetHeight(20)
|
||||
customScanFrame.filterEditBox = filterEditBox
|
||||
|
||||
local cancelFilterBtn = TSMAPI.GUI:CreateButton(customScanFrame, 16)
|
||||
cancelFilterBtn:SetPoint("TOPLEFT", 4, -96)
|
||||
cancelFilterBtn:SetPoint("TOPRIGHT", -4, -96)
|
||||
cancelFilterBtn:SetHeight(20)
|
||||
cancelFilterBtn:SetText("Cancel Items Matching Filter")
|
||||
cancelFilterBtn:SetScript("OnClick", function()
|
||||
local filter = filterEditBox:GetText():trim()
|
||||
if filter == "" then return TSM:Print(L["The filter cannot be empty. If you'd like to cancel all auctions, use the 'Cancel All Auctions' button."]) end
|
||||
private.mode = "Cancel"
|
||||
private.specialMode = filterEditBox:GetText()
|
||||
GUI:StartScan(parent)
|
||||
end)
|
||||
cancelFilterBtn.tooltip = L["Will cancel all your auctions which match the specified filter, including ones which you didn't post with Auctioning."]
|
||||
customScanFrame.cancelFilterBtn = cancelFilterBtn
|
||||
|
||||
TSMAPI.GUI:CreateHorizontalLine(customScanFrame, -120)
|
||||
|
||||
local durationList = {}
|
||||
local durationText = {L["Under 30min"], L["30min to 2hrs"], L["2 to 12 hrs"]}
|
||||
for i=1, 3 do -- go up to long duration
|
||||
durationList[i] = format("%s (%s)", _G["AUCTION_TIME_LEFT"..i], durationText[i])
|
||||
end
|
||||
local cancelDurationDropdown = TSMAPI.GUI:CreateDropdown(customScanFrame, durationList, L["Select a duration in this dropdown and click on the button below to cancel all auctions at or below this duration."])
|
||||
cancelDurationDropdown:SetPoint("TOPLEFT", 2, -124)
|
||||
cancelDurationDropdown:SetPoint("TOPRIGHT", 0, -124)
|
||||
cancelDurationDropdown:SetHeight(20)
|
||||
cancelDurationDropdown:SetLabel(L["Low Duration"])
|
||||
cancelDurationDropdown:SetValue(1)
|
||||
|
||||
local cancelDurationBtn = TSMAPI.GUI:CreateButton(customScanFrame, 16)
|
||||
cancelDurationBtn:SetPoint("TOPLEFT", 4, -172)
|
||||
cancelDurationBtn:SetPoint("TOPRIGHT", -4, -172)
|
||||
cancelDurationBtn:SetHeight(20)
|
||||
cancelDurationBtn:SetText(L["Cancel Low Duration"])
|
||||
cancelDurationBtn:SetScript("OnClick", function()
|
||||
private.mode = "Cancel"
|
||||
private.specialMode = cancelDurationDropdown:GetValue()
|
||||
GUI:StartScan(parent)
|
||||
end)
|
||||
cancelDurationBtn.tooltip = L["Will cancel all your auctions at or below the specified duration, including ones you didn't post with Auctioning."]
|
||||
customScanFrame.cancelDurationBtn = cancelDurationBtn
|
||||
|
||||
TSMAPI.GUI:CreateHorizontalLine(customScanFrame, -196)
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function GUI:CreateScanFrame(parent)
|
||||
local frame = CreateFrame("Frame", nil, parent)
|
||||
frame:SetAllPoints()
|
||||
local contentFrame = CreateFrame("Frame", nil, frame)
|
||||
contentFrame:SetAllPoints(parent.content)
|
||||
TSMAPI.Design:SetFrameColor(contentFrame)
|
||||
frame.content = contentFrame
|
||||
|
||||
local statusBarFrame = CreateFrame("Frame", nil, frame.content)
|
||||
statusBarFrame:SetPoint("TOPLEFT", frame.content, "BOTTOMLEFT", 165, -2)
|
||||
statusBarFrame:SetWidth(355)
|
||||
statusBarFrame:SetHeight(30)
|
||||
private.statusBar = TSMAPI.GUI:CreateStatusBar(statusBarFrame, "TSMAuctioningStatusBar")
|
||||
|
||||
private.buttons = private:CreateButtons(frame)
|
||||
|
||||
private.contentButtons = private.contentButtons or private:CreateContentButtons(frame)
|
||||
private.contentButtons:Show()
|
||||
private.contentButtons:UpdateMode()
|
||||
|
||||
private.infoText = private.infoText or private:CreateInfoText(frame)
|
||||
private.infoText:Show()
|
||||
|
||||
private.auctionsST = private:CreateAuctionsST(frame.content)
|
||||
private.logST = private:CreateLogST(frame.content)
|
||||
return frame
|
||||
end
|
||||
|
||||
function GUI:StartScan(frame)
|
||||
private.selectionFrame:Hide()
|
||||
private.scanFrame = private.scanFrame or GUI:CreateScanFrame(frame)
|
||||
private.scanFrame:Show()
|
||||
private.statusBar:Show()
|
||||
private.buttons:Show()
|
||||
private.buttons:UpdateMode()
|
||||
private.buttons:Disable()
|
||||
private.buttons.stop.isDone = nil
|
||||
private.buttons.stop:SetText(L["Stop"])
|
||||
private.contentButtons:Show()
|
||||
private.contentButtons:UpdateMode()
|
||||
private.infoText:Show()
|
||||
private.contentButtons.logButton:Click()
|
||||
private.auctionsST:SetData({})
|
||||
private.logST:SetData({})
|
||||
private.logST.cache = {}
|
||||
|
||||
if private.mode == "Reset" then
|
||||
private.buttons:Hide()
|
||||
private.contentButtons:Hide()
|
||||
private.auctionsST:Hide()
|
||||
private.logST:Hide()
|
||||
TSM.Reset:Show(frame)
|
||||
end
|
||||
|
||||
|
||||
local options = {itemOperations={}}
|
||||
if private.specialMode then
|
||||
options.specialMode = private.specialMode
|
||||
else
|
||||
for groupName, data in pairs(private.selectionFrame.groupTree:GetSelectedGroupInfo()) do
|
||||
groupName = TSMAPI:FormatGroupPath(groupName, true)
|
||||
for _, opName in ipairs(data.operations) do
|
||||
TSMAPI:UpdateOperation("Auctioning", opName)
|
||||
local opSettings = TSM.operations[opName]
|
||||
if not opSettings then
|
||||
-- operation doesn't exist anymore in Auctioning
|
||||
TSM:Printf(L["'%s' has an Auctioning operation of '%s' which no longer exists. Auctioning will ignore this group until this is fixed."], groupName, opName)
|
||||
else
|
||||
-- it's a valid operation
|
||||
TSM.operationNameLookup[opSettings] = opName
|
||||
for itemString in pairs(data.items) do
|
||||
options.itemOperations[itemString] = options.itemOperations[itemString] or {}
|
||||
tinsert(options.itemOperations[itemString], opSettings)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TSMAPI:CreateTimeDelay("aucStartDelay", 0.1, function() TSM.Manage:StartScan(private, options) end)
|
||||
end
|
||||
|
||||
function GUI:ShowSelectionFrame(frame)
|
||||
if private.scanFrame then private.scanFrame:Hide() end
|
||||
private.selectionFrame = private.selectionFrame or GUI:CreateSelectionFrame(frame)
|
||||
private.selectionFrame:Show()
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
end
|
||||
|
||||
function GUI:HideSelectionFrame()
|
||||
private.selectionFrame:Hide()
|
||||
if private.scanFrame then private.scanFrame:Hide() end
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
TSM.Reset:Hide()
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Log = TSM:NewModule("Log", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning")
|
||||
|
||||
local records = {}
|
||||
|
||||
local RED = "|cffff2211"
|
||||
local ORANGE = "|cffff8811"
|
||||
local GREEN = "|cff22ff22"
|
||||
local CYAN = "|cff99ffff"
|
||||
|
||||
local info = {
|
||||
post = {
|
||||
invalid = {L["Item/Group is invalid."], RED},
|
||||
notEnough = {L["Not enough items in bags."], ORANGE},
|
||||
belowMinPrice = {L["Cheapest auction below min price."], ORANGE},
|
||||
tooManyPosted = {L["Maximum amount already posted."], CYAN},
|
||||
postingNormal = {L["Posting at normal price."], GREEN},
|
||||
postingResetMin = {L["Below min price. Posting at min price."], GREEN},
|
||||
postingResetMax = {L["Below min price. Posting at max price."], GREEN},
|
||||
postingResetNormal = {L["Below min price. Posting at normal price."], GREEN},
|
||||
aboveMaxMin = {L["Above max price. Posting at min price."], GREEN},
|
||||
aboveMaxMax = {L["Above max price. Posting at max price."], GREEN},
|
||||
aboveMaxNormal = {L["Above max price. Posting at normal price."], GREEN},
|
||||
postingPlayer = {L["Posting at your current price."], GREEN},
|
||||
postingWhitelist = {L["Posting at whitelisted player's price."], GREEN},
|
||||
notPostingWhitelist = {L["Lowest auction by whitelisted player."], ORANGE},
|
||||
postingUndercut = {L["Undercutting competition."], GREEN},
|
||||
invalidSeller = {L["Invalid seller data returned by server."], RED},
|
||||
},
|
||||
cancel = {
|
||||
bid = {L["Auction has been bid on."], CYAN},
|
||||
atReset = {L["Not canceling auction at reset price."], GREEN},
|
||||
reset = {L["Canceling to repost at reset price."], CYAN},
|
||||
belowMinPrice = {L["Not canceling auction below min price."], ORANGE},
|
||||
undercut = {L["You've been undercut."], RED},
|
||||
whitelistUndercut = {L["Undercut by whitelisted player."], RED},
|
||||
atNormal = {L["At normal price and not undercut."], GREEN},
|
||||
atAboveMax = {L["At above max price and not undercut."], GREEN},
|
||||
repost = {L["Canceling to repost at higher price."], CYAN},
|
||||
notUndercut = {L["Your auction has not been undercut."], GREEN},
|
||||
cancelAll = {L["Canceling all auctions."], CYAN},
|
||||
notLowest = {L["Canceling auction which you've undercut."], CYAN},
|
||||
invalidSeller = {L["Invalid seller data returned by server."], RED},
|
||||
atWhitelist = {L["Posted at whitelisted player's price."], GREEN},
|
||||
keepPosted = {L["Keeping undercut auctions posted."], CYAN},
|
||||
},
|
||||
}
|
||||
|
||||
function Log:GetInfo(mode, reason)
|
||||
return info[mode][reason] and info[mode][reason][1]
|
||||
end
|
||||
|
||||
function Log:GetColor(mode, reason)
|
||||
return mode and reason and info[mode] and info[mode][reason] and info[mode][reason][2]
|
||||
end
|
||||
|
||||
function Log:AddLogRecord(itemString, mode, action, reason, operation, buyout)
|
||||
local info = Log:GetInfo(mode, reason)
|
||||
local record = {itemString=itemString, info=info, action=action, mode=mode, reason=reason, operation=operation, buyout=buyout}
|
||||
tinsert(records, record)
|
||||
end
|
||||
|
||||
function Log:GetInfoForItem(itemString)
|
||||
for _, record in ipairs(records) do
|
||||
if record.itemString == itemString then
|
||||
return record.info
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Log:GetData()
|
||||
return records
|
||||
end
|
||||
|
||||
function Log:Clear()
|
||||
wipe(records)
|
||||
end
|
||||
@@ -0,0 +1,823 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
-- load the parent file (TSM) into a local variable and register this file as a module
|
||||
local TSM = select(2, ...)
|
||||
local Options = TSM:NewModule("Options", "AceEvent-3.0", "AceHook-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
local AceGUI = LibStub("AceGUI-3.0") -- load the AceGUI libraries
|
||||
|
||||
|
||||
function Options:Load(parent, operation, group)
|
||||
Options.treeGroup = AceGUI:Create("TSMTreeGroup")
|
||||
Options.treeGroup:SetLayout("Fill")
|
||||
Options.treeGroup:SetCallback("OnGroupSelected", function(...) Options:SelectTree(...) end)
|
||||
Options.treeGroup:SetStatusTable(TSM.db.global.optionsTreeStatus)
|
||||
parent:AddChild(Options.treeGroup)
|
||||
|
||||
Options:UpdateTree()
|
||||
if operation then
|
||||
if operation == "" then
|
||||
Options.currentGroup = group
|
||||
Options.treeGroup:SelectByPath(3)
|
||||
Options.currentGroup = nil
|
||||
else
|
||||
Options.treeGroup:SelectByPath(3, operation)
|
||||
end
|
||||
else
|
||||
Options.treeGroup:SelectByPath(1)
|
||||
end
|
||||
end
|
||||
|
||||
function Options:UpdateTree()
|
||||
local operationTreeChildren = {}
|
||||
|
||||
for name in pairs(TSM.operations) do
|
||||
tinsert(operationTreeChildren, { value = name, text = name })
|
||||
end
|
||||
|
||||
sort(operationTreeChildren, function(a, b) return a.value < b.value end)
|
||||
|
||||
Options.treeGroup:SetTree({ { value = 1, text = L["Options"] }, { value = 2, text = L["Whitelist"] }, { value = 3, text = L["Operations"], children = operationTreeChildren } })
|
||||
end
|
||||
|
||||
function Options:SelectTree(treeGroup, _, selection)
|
||||
treeGroup:ReleaseChildren()
|
||||
|
||||
local major, minor = ("\001"):split(selection)
|
||||
major = tonumber(major)
|
||||
if major == 1 then
|
||||
Options:DrawGeneralSettings(treeGroup)
|
||||
elseif major == 2 then
|
||||
Options:DrawWhitelistSettings(treeGroup)
|
||||
elseif minor then
|
||||
Options:DrawOperationSettings(treeGroup, minor)
|
||||
else
|
||||
Options:DrawNewOperation(treeGroup)
|
||||
end
|
||||
end
|
||||
|
||||
function Options:DrawGeneralSettings(container)
|
||||
local macroOptions = { down = true, up = true, ctrl = true, shift = false, alt = false }
|
||||
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["General Options"],
|
||||
children = {
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Cancel Auctions with Bids"],
|
||||
settingInfo = { TSM.db.global, "cancelWithBid" },
|
||||
tooltip = L["Will cancel auctions even if they have a bid on them, you will take an additional gold cost if you cancel an auction with bid."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Round Normal Price"],
|
||||
settingInfo = { TSM.db.global, "roundNormalPrice" },
|
||||
tooltip = L["If checked, whenever you post an item at its normal price, the buyout will be rounded up to the nearest gold."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Disable Invalid Price Warnings"],
|
||||
settingInfo = { TSM.db.global, "disableInvalidMsg" },
|
||||
tooltip = L["If checked, TSM will not print out a chat message when you have an invalid price for an item. However, it will still show as invalid in the log."],
|
||||
},
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["Default Operation Tab"],
|
||||
list = { L["General"], L["Post"], L["Cancel"], L["Reset"] },
|
||||
settingInfo = { TSM.db.global, "defaultOperationTab" },
|
||||
tooltip = L["This dropdown determines the default tab when you visit an operation."],
|
||||
},
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["Enable Sounds"],
|
||||
list = {L["None"], "AuctionWindowOpen", "Fishing Reel in", "HumanExploration", "LEVELUP", "MapPing", "MONEYFRAMEOPEN", "QUESTCOMPLETED", "ReadyCheck"},
|
||||
settingInfo = { TSM.db.global, "scanCompleteSound" },
|
||||
tooltip = L["Play the selected sound when a post / cancel scan is complete and items are ready to be posted / canceled (the gray bar is all the way across).Select None to disable sounds"],
|
||||
},
|
||||
{
|
||||
type = "Button",
|
||||
text = L["Test Selected Sound"],
|
||||
callback = function()
|
||||
if TSM.db.global.scanCompleteSound ~= 1 then
|
||||
PlaySound(TSM.Options:GetScanCompleteSound(TSM.db.global.scanCompleteSound), "Master")
|
||||
end
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "Spacer",
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Macro Help"],
|
||||
children = {
|
||||
{
|
||||
type = "Label",
|
||||
text = format(L["There are two ways of making clicking the Post / Cancel Auction button easier. You can put %s and %s in a macro (on separate lines), or use the utility below to have a macro automatically made and bound to scrollwheel for you."], "\"" .. TSMAPI.Design:GetInlineColor("link") .. "/click TSMAuctioningPostButton|r\"", "\"" .. TSMAPI.Design:GetInlineColor("link") .. "/click TSMAuctioningCancelButton|r\""),
|
||||
relativeWidth = 1,
|
||||
},
|
||||
{
|
||||
type = "HeadingLine"
|
||||
},
|
||||
{
|
||||
type = "Label",
|
||||
text = L["ScrollWheel Direction (both recommended):"],
|
||||
relativeWidth = 0.59,
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Up"],
|
||||
relativeWidth = 0.2,
|
||||
settingInfo = { macroOptions, "up" },
|
||||
tooltip = L["Will bind ScrollWheelUp (plus modifiers below) to the macro created."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Down"],
|
||||
relativeWidth = 0.2,
|
||||
settingInfo = { macroOptions, "down" },
|
||||
tooltip = L["Will bind ScrollWheelDown (plus modifiers below) to the macro created."],
|
||||
},
|
||||
{
|
||||
type = "Label",
|
||||
text = L["Modifiers:"],
|
||||
relativeWidth = 0.24,
|
||||
fontObject = GameFontNormal,
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = "ALT",
|
||||
relativeWidth = 0.25,
|
||||
settingInfo = { macroOptions, "alt" },
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = "CTRL",
|
||||
relativeWidth = 0.25,
|
||||
settingInfo = { macroOptions, "ctrl" },
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = "SHIFT",
|
||||
relativeWidth = 0.25,
|
||||
settingInfo = { macroOptions, "shift" },
|
||||
},
|
||||
{
|
||||
type = "Button",
|
||||
relativeWidth = 1,
|
||||
text = L["Create Macro and Bind ScrollWheel (with selected options)"],
|
||||
callback = function()
|
||||
DeleteMacro("TSMAucBClick")
|
||||
CreateMacro("TSMAucBClick", 1, "/click TSMAuctioningCancelButton\n/click TSMAuctioningPostButton")
|
||||
|
||||
local modString = ""
|
||||
if macroOptions.ctrl then
|
||||
modString = modString .. "CTRL-"
|
||||
end
|
||||
if macroOptions.alt then
|
||||
modString = modString .. "ALT-"
|
||||
end
|
||||
if macroOptions.shift then
|
||||
modString = modString .. "SHIFT-"
|
||||
end
|
||||
|
||||
local bindingNum = GetCurrentBindingSet()
|
||||
bindingNum = (bindingNum == 1) and 2 or 1
|
||||
|
||||
if macroOptions.up then
|
||||
SetBinding(modString .. "MOUSEWHEELUP", nil, bindingNum)
|
||||
SetBinding(modString .. "MOUSEWHEELUP", "MACRO TSMAucBClick", bindingNum)
|
||||
end
|
||||
if macroOptions.down then
|
||||
SetBinding(modString .. "MOUSEWHEELDOWN", nil, bindingNum)
|
||||
SetBinding(modString .. "MOUSEWHEELDOWN", "MACRO TSMAucBClick", bindingNum)
|
||||
end
|
||||
SaveBindings(2)
|
||||
|
||||
TSM:Print(L["Macro created and keybinding set!"])
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawWhitelistSettings(container)
|
||||
local function AddPlayer(self, _, value)
|
||||
value = string.trim(strlower(value or ""))
|
||||
if value == "" then return TSM:Print(L["No name entered."]) end
|
||||
|
||||
if TSM.db.factionrealm.whitelist[value] then
|
||||
TSM:Printf(L["The player \"%s\" is already on your whitelist."], TSM.db.factionrealm.whitelist[value])
|
||||
return
|
||||
end
|
||||
|
||||
for player in pairs(TSM.db.factionrealm.player) do
|
||||
if strlower(player) == value then
|
||||
TSM:Printf(L["You do not need to add \"%s\", alts are whitelisted automatically."], player)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
TSM.db.factionrealm.whitelist[strlower(value)] = value
|
||||
container:SelectByPath(2)
|
||||
end
|
||||
|
||||
local page = {
|
||||
{
|
||||
-- scroll frame to contain everything
|
||||
type = "ScrollFrame",
|
||||
layout = "List",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Help"],
|
||||
children = {
|
||||
{
|
||||
type = "Label",
|
||||
relativeWidth = 1,
|
||||
fontObject = GameFontNormal,
|
||||
text = L["Whitelists allow you to set other players besides you and your alts that you do not want to undercut; however, if somebody on your whitelist matches your buyout but lists a lower bid it will still consider them undercutting."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
relativeWidth = 0.49,
|
||||
label = L["Match Whitelist Players"],
|
||||
settingInfo = { TSM.db.global, "matchWhitelist" },
|
||||
tooltip = L["If enabled, instead of not posting when a whitelisted player has an auction posted, Auctioning will match their price."],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Add player"],
|
||||
children = {
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Player name"],
|
||||
relativeWidth = 0.5,
|
||||
callback = AddPlayer,
|
||||
tooltip = L["Add a new player to your whitelist."],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Whitelist"],
|
||||
children = {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name in pairs(TSM.db.factionrealm.whitelist) do
|
||||
tinsert(page[1].children[3].children,
|
||||
{
|
||||
type = "Label",
|
||||
text = TSM.db.factionrealm.whitelist[name],
|
||||
fontObject = GameFontNormal,
|
||||
})
|
||||
tinsert(page[1].children[3].children,
|
||||
{
|
||||
type = "Button",
|
||||
text = L["Delete"],
|
||||
relativeWidth = 0.3,
|
||||
callback = function(self)
|
||||
TSM.db.factionrealm.whitelist[name] = nil
|
||||
container:SelectByPath(2)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
if #(page[1].children[3].children) == 0 then
|
||||
tinsert(page[1].children[3].children,
|
||||
{
|
||||
type = "Label",
|
||||
text = L["You do not have any players on your whitelist yet."],
|
||||
fontObject = GameFontNormal,
|
||||
relativeWidth = 1,
|
||||
})
|
||||
end
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawNewOperation(container)
|
||||
local currentGroup = Options.currentGroup
|
||||
local page = {
|
||||
{
|
||||
-- scroll frame to contain everything
|
||||
type = "ScrollFrame",
|
||||
layout = "List",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["New Operation"],
|
||||
children = {
|
||||
{
|
||||
type = "Label",
|
||||
text = L["Auctioning operations contain settings for posting, canceling, and resetting items in a group. Type the name of the new operation into the box below and hit 'enter' to create a new Crafting operation."],
|
||||
relativeWidth = 1,
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Operation Name"],
|
||||
relativeWidth = 0.8,
|
||||
callback = function(self, _, name)
|
||||
name = (name or ""):trim()
|
||||
if name == "" then return end
|
||||
if TSM.operations[name] then
|
||||
self:SetText("")
|
||||
return TSM:Printf(L["Error creating operation. Operation with name '%s' already exists."], name)
|
||||
end
|
||||
TSM.operations[name] = CopyTable(TSM.operationDefaults)
|
||||
Options:UpdateTree()
|
||||
Options.treeGroup:SelectByPath(3, name)
|
||||
TSMAPI:NewOperationCallback("Auctioning", currentGroup, name)
|
||||
end,
|
||||
tooltip = L["Give the new operation a name. A descriptive name will help you find this operation later."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawOperationSettings(container, operationName)
|
||||
local tg = AceGUI:Create("TSMTabGroup")
|
||||
tg:SetLayout("Fill")
|
||||
tg:SetFullHeight(true)
|
||||
tg:SetFullWidth(true)
|
||||
tg:SetTabs({ { value = 1, text = L["General"] }, { value = 2, text = L["Post"] }, { value = 3, text = L["Cancel"] }, { value = 4, text = L["Reset"] }, { value = 5, text = TSMAPI.Design:GetInlineColor("advanced") .. L["Relationships"] .. "|r" }, { value = 6, text = L["Management"] } })
|
||||
tg:SetCallback("OnGroupSelected", function(self, _, value)
|
||||
tg:ReleaseChildren()
|
||||
TSMAPI:UpdateOperation("Auctioning", operationName)
|
||||
if value == 1 then
|
||||
Options:DrawOperationGeneral(self, operationName)
|
||||
elseif value == 2 then
|
||||
Options:DrawOperationPost(self, operationName)
|
||||
elseif value == 3 then
|
||||
Options:DrawOperationCancel(self, operationName)
|
||||
elseif value == 4 then
|
||||
Options:DrawOperationReset(self, operationName)
|
||||
elseif value == 5 then
|
||||
Options:DrawOperationRelationships(self, operationName)
|
||||
elseif value == 6 then
|
||||
TSMAPI:DrawOperationManagement(TSM, self, operationName)
|
||||
end
|
||||
end)
|
||||
container:AddChild(tg)
|
||||
tg:SelectTab(TSM.db.global.defaultOperationTab)
|
||||
end
|
||||
|
||||
function Options:DrawOperationGeneral(container, operationName)
|
||||
local operation = TSM.operations[operationName]
|
||||
local durationList = { [0] = L["<none>"] }
|
||||
for i = 1, 3 do -- go up to long duration
|
||||
durationList[i] = format("%s (%s)", _G["AUCTION_TIME_LEFT" .. i], _G["AUCTION_TIME_LEFT" .. i .. "_DETAIL"])
|
||||
end
|
||||
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["General Operation Options"],
|
||||
children = {
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Match Stack Size"],
|
||||
settingInfo = { operation, "matchStackSize" },
|
||||
disabled = operation.relationships.matchStackSize,
|
||||
tooltip = L["If checked, Auctioning will ignore all auctions that are posted at a different stack size than your auctions. For example, if there are stacks of 1, 5, and 20 up and you're posting in stacks of 1, it'll ignore all stacks of 5 and 20."],
|
||||
},
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["Ignore Low Duration Auctions"],
|
||||
settingInfo = { operation, "ignoreLowDuration" },
|
||||
relativeWidth = 0.5,
|
||||
list = durationList,
|
||||
disabled = operation.relationships.ignoreLowDuration,
|
||||
tooltip = L["Any auctions at or below the selected duration will be ignored. Selecting \"<none>\" will cause no auctions to be ignored based on duration."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawOperationPost(container, operationName)
|
||||
local operation = TSM.operations[operationName]
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Auction Settings"],
|
||||
children = {
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["Duration"],
|
||||
settingInfo = { operation, "duration" },
|
||||
relativeWidth = 0.5,
|
||||
list = { [12] = AUCTION_DURATION_ONE, [24] = AUCTION_DURATION_TWO, [48] = AUCTION_DURATION_THREE },
|
||||
disabled = operation.relationships.duration,
|
||||
tooltip = L["How long auctions should be up for."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Post Cap"],
|
||||
settingInfo = { operation, "postCap" },
|
||||
relativeWidth = 0.49,
|
||||
min = 0,
|
||||
max = 500,
|
||||
step = 1,
|
||||
disabled = operation.relationships.postCap,
|
||||
tooltip = L["How many auctions at the lowest price tier can be up at any one time. Setting this to 0 disables posting for any groups this operation is applied to."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Stack Size"],
|
||||
settingInfo = { operation, "stackSize" },
|
||||
min = 1,
|
||||
max = 1000,
|
||||
step = 1,
|
||||
relativeWidth = 0.5,
|
||||
disabled = operation.relationships.stackSize,
|
||||
tooltip = L["How many items should be in a single auction, 20 will mean they are posted in stacks of 20."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Use Stack Size as Cap"],
|
||||
settingInfo = { operation, "stackSizeIsCap" },
|
||||
disabled = operation.relationships.stackSizeIsCap,
|
||||
tooltip = L["If you don't have enough items for a full post, it will post with what you have."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Keep Quantity"],
|
||||
settingInfo = { operation, "keepQuantity" },
|
||||
min = 0,
|
||||
max = 1000,
|
||||
step = 1,
|
||||
relativeWidth = 0.5,
|
||||
tooltip = L["How many items you want to keep in your bags and not have Auctioning post."],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "Spacer",
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Auction Price Settings"],
|
||||
children = {
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Bid percent"],
|
||||
settingInfo = { operation, "bidPercent" },
|
||||
isPercent = true,
|
||||
min = 0,
|
||||
max = 1,
|
||||
step = 0.01,
|
||||
relativeWidth = 0.5,
|
||||
disabled = operation.relationships.bidPercent,
|
||||
tooltip = L["Percentage of the buyout as bid, if you set this to 90% then a 100g buyout will have a 90g bid."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Undercut Amount"],
|
||||
settingInfo = { operation, "undercut" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
disabled = operation.relationships.undercut,
|
||||
tooltip = L["How much to undercut other auctions by. Format is in \"#g#s#c\". For example, \"50g30s\" means 50 gold, 30 silver, and no copper."],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "Spacer",
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Posting Price Settings"],
|
||||
children = {
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Minimum Price"],
|
||||
settingInfo = { operation, "minPrice" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
disabled = operation.relationships.minPrice,
|
||||
tooltip = L["The lowest price you want an item to be posted for. Auctioning will not undercut auctions below this price."],
|
||||
},
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["When Below Minimum"],
|
||||
relativeWidth = 0.5,
|
||||
list = { ["none"] = L["Don't Post Items"], ["minPrice"] = L["Post at Minimum Price"], ["maxPrice"] = L["Post at Maximum Price"], ["normalPrice"] = L["Post at Normal Price"], ["ignore"] = L["Ignore Auctions Below Minimum"] },
|
||||
settingInfo = { operation, "priceReset" },
|
||||
disabled = operation.relationships.priceReset,
|
||||
tooltip = L["This dropdown determines what Auctioning will do when the market for an item goes below your minimum price. You can not post the items, post at one of your configured prices, or have Auctioning ignore all the auctions below your minimum price (and likely undercut the lowest auction above your mimimum price)."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Maximum Price"],
|
||||
settingInfo = { operation, "maxPrice" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
disabled = operation.relationships.maxPrice,
|
||||
tooltip = L["The maximum price you want an item to be posted for. Auctioning will not undercut auctions above this price."],
|
||||
},
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["When Above Maximum"],
|
||||
relativeWidth = 0.5,
|
||||
list = { ["minPrice"] = L["Post at Minimum Price"], ["maxPrice"] = L["Post at Maximum Price"], ["normalPrice"] = L["Post at Normal Price"] },
|
||||
settingInfo = { operation, "aboveMax" },
|
||||
disabled = operation.relationships.aboveMax,
|
||||
tooltip = L["This dropdown determines what Auctioning will do when the market for an item goes above your maximum price. You can post the items at one of your configured prices."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Normal Price"],
|
||||
settingInfo = { operation, "normalPrice" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
disabled = operation.relationships.normalPrice,
|
||||
tooltip = L["Price to post at if there are none of an item currently on the AH."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawOperationCancel(container, operationName)
|
||||
local operation = TSM.operations[operationName]
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Cancel Settings"],
|
||||
children = {
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Cancel Undercut Auctions"],
|
||||
settingInfo = { operation, "cancelUndercut" },
|
||||
callback = function() container:ReloadTab() end,
|
||||
disabled = operation.relationships.cancelUndercut,
|
||||
tooltip = L["If checked, a cancel scan will cancel any auctions which have been undercut and are still above your minimum price."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Keep Posted"],
|
||||
settingInfo = { operation, "keepPosted" },
|
||||
disabled = not operation.cancelUndercut or operation.relationships.keepPosted,
|
||||
relativeWidth = 0.49,
|
||||
min = 0,
|
||||
max = 500,
|
||||
step = 1,
|
||||
tooltip = L["This number of undercut auctions will be kept on the auction house (not canceled) when doing a cancel scan."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Cancel to Repost Higher"],
|
||||
settingInfo = { operation, "cancelRepost" },
|
||||
callback = function() container:ReloadTab() end,
|
||||
disabled = operation.relationships.cancelRepost,
|
||||
tooltip = L["If checked, a cancel scan will cancel any auctions which can be reposted for a higher price."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Repost Higher Threshold"],
|
||||
settingInfo = { operation, "cancelRepostThreshold" },
|
||||
disabled = not operation.cancelRepost or operation.relationships.cancelRepostThreshold,
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["If an item can't be posted for at least this amount higher than its current value, it won't be canceled to repost higher."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawOperationReset(container, operationName)
|
||||
local operation = TSM.operations[operationName]
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["General Reset Settings"],
|
||||
children = {
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Enable Reset Scan"],
|
||||
relativeWidth = 1,
|
||||
settingInfo = { operation, "resetEnabled" },
|
||||
callback = function() container:ReloadTab() end,
|
||||
disabled = operation.relationships.resetEnabled,
|
||||
tooltip = L["If checked, groups which the opperation applies to will be included in a reset scan."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Max Quantity to Buy"],
|
||||
settingInfo = { operation, "resetMaxQuantity" },
|
||||
disabled = not operation.resetEnabled or operation.relationships.resetMaxQuantity,
|
||||
relativeWidth = 0.5,
|
||||
min = 1,
|
||||
max = 1000,
|
||||
step = 1,
|
||||
tooltip = L["This is the maximum quantity of an item you want to buy in a single reset scan."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Max Inventory Quantity"],
|
||||
settingInfo = { operation, "resetMaxInventory" },
|
||||
disabled = not operation.resetEnabled or operation.relationships.resetMaxInventory,
|
||||
relativeWidth = 0.49,
|
||||
min = 1,
|
||||
max = 1000,
|
||||
step = 1,
|
||||
tooltip = L["This is the maximum quantity of an item you want to have in your inventory after a reset scan."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Max Reset Cost"],
|
||||
settingInfo = { operation, "resetMaxCost" },
|
||||
disabled = not operation.resetEnabled or operation.relationships.resetMaxCost,
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["The maximum amount that you want to spend in order to reset a particular item. This is the total amount, not a per-item amount."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Min Reset Profit"],
|
||||
settingInfo = { operation, "resetMinProfit" },
|
||||
disabled = not operation.resetEnabled or operation.relationships.resetMinProfit,
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["The minimum profit you would want to make from doing a reset. This is a per-item price where profit is the price you reset to minus the average price you spent per item."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Price Resolution"],
|
||||
settingInfo = { operation, "resetResolution" },
|
||||
disabled = not operation.resetEnabled or operation.relationships.resetResolution,
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["This determines what size range of prices should be considered a single price point for the reset scan. For example, if this is set to 1s, an auction at 20g50s20c and an auction at 20g49s45c will both be considered to be the same price level."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Max Cost Per Item"],
|
||||
settingInfo = { operation, "resetMaxItemCost" },
|
||||
disabled = not operation.resetEnabled or operation.relationships.resetMaxItemCost,
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["This is the maximum amount you want to pay for a single item when reseting."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawOperationRelationships(container, operationName)
|
||||
local settingInfo = {
|
||||
{
|
||||
label = L["General Settings"],
|
||||
{ key = "matchStackSize", label = L["Match Stack Size"] },
|
||||
{ key = "ignoreLowDuration", label = L["Ignore Low Duration Auctions"] },
|
||||
},
|
||||
{
|
||||
label = L["Post Settings"],
|
||||
{ key = "duration", label = L["Duration"] },
|
||||
{ key = "postCap", label = L["Post Cap"] },
|
||||
{ key = "stackSize", label = L["Stack Size"] },
|
||||
{ key = "stackSizeIsCap", label = L["Use Stack Size as Cap"] },
|
||||
{ key = "keepQuantity", label = L["Keep Quantity"] },
|
||||
{ key = "bidPercent", label = L["Bid percent"] },
|
||||
{ key = "undercut", label = L["Undercut Amount"] },
|
||||
{ key = "minPrice", label = L["Minimum Price"] },
|
||||
{ key = "priceReset", label = L["When Below Minimum"] },
|
||||
{ key = "maxPrice", label = L["Maximum Price"] },
|
||||
{ key = "aboveMax", label = L["When Above Maximum"] },
|
||||
{ key = "normalPrice", label = L["Normal Price"] },
|
||||
},
|
||||
{
|
||||
label = L["Cancel Settings"],
|
||||
{ key = "cancelUndercut", label = L["Cancel Undercut Auctions"] },
|
||||
{ key = "keepPosted", label = L["Keep Posted"] },
|
||||
{ key = "cancelRepost", label = L["Cancel to Repost Higher"] },
|
||||
{ key = "cancelRepostThreshold", label = L["Repost Higher Threshold"] },
|
||||
},
|
||||
{
|
||||
label = L["Reset Settings"],
|
||||
{ key = "resetEnabled", label = L["Enable Reset Scan"] },
|
||||
{ key = "resetMaxQuantity", label = L["Max Quantity to Buy"] },
|
||||
{ key = "resetMaxInventory", label = L["Max Inventory Quantity"] },
|
||||
{ key = "resetMaxCost", label = L["Max Reset Cost"] },
|
||||
{ key = "resetMinProfit", label = L["Min Reset Profit"] },
|
||||
{ key = "resetResolution", label = L["Price Resolution"] },
|
||||
{ key = "resetMaxItemCost", label = L["Max Cost Per Item"] },
|
||||
},
|
||||
}
|
||||
TSMAPI:ShowOperationRelationshipTab(TSM, container, TSM.operations[operationName], settingInfo)
|
||||
end
|
||||
|
||||
function Options:LoadTooltipOptions(container)
|
||||
local page = {
|
||||
{
|
||||
type = "SimpleGroup",
|
||||
layout = "Flow",
|
||||
fullHeight = true,
|
||||
children = {
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Show Auctioning values in Tooltip"],
|
||||
settingInfo = { TSM.db.global, "tooltip" },
|
||||
callback = function() container:ReloadTab() end,
|
||||
tooltip = L["If checked, the minimum, normal and maximum prices of the first operation for the item will be shown in tooltips."],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:GetScanCompleteSound(index)
|
||||
--L["None"], "AuctionWindowOpen", "Fishing Reel in", "HumanExploration", "LEVELUP", "MapPing", "MONEYFRAMEOPEN", "QUESTCOMPLETED", "ReadyCheck"
|
||||
if index == 2 then
|
||||
return "AuctionWindowOpen"
|
||||
elseif index == 3 then
|
||||
return "Fishing Reel in"
|
||||
elseif index == 4 then
|
||||
return "HumanExploration"
|
||||
elseif index == 5 then
|
||||
return "LEVELUP"
|
||||
elseif index == 6 then
|
||||
return "MapPing"
|
||||
elseif index == 7 then
|
||||
return "MONEYFRAMEOPEN"
|
||||
elseif index == 8 then
|
||||
return "QUESTCOMPLETED"
|
||||
elseif index == 9 then
|
||||
return "ReadyCheck"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,527 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Post = TSM:NewModule("Post", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
|
||||
local bagInfo, bagState = {}, {}
|
||||
local bagInfoUpdate = 0
|
||||
local postQueue, currentItem, itemLocations = {}, {}, {}
|
||||
local totalToPost, totalPosted, count = 0, 0, 0
|
||||
local isScanning, GUI
|
||||
|
||||
function Post:ValidateOperation(itemString, operation)
|
||||
local itemLink, salePrice = TSMAPI:Select({2, 11}, TSMAPI:GetSafeItemInfo(itemString))
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString)
|
||||
|
||||
-- don't post this item if their settings are invalid
|
||||
if operation.postCap == 0 then
|
||||
return -- posting is disabled
|
||||
elseif not prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not post %s because your minimum price (%s) is invalid. Check your settings."], itemLink or itemString, operation.minPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "invalid", operation)
|
||||
elseif not prices.maxPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not post %s because your maximum price (%s) is invalid. Check your settings."], itemLink or itemString, operation.maxPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "invalid", operation)
|
||||
elseif not prices.normalPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not post %s because your normal price (%s) is invalid. Check your settings."], itemLink or itemString, operation.normalPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "invalid", operation)
|
||||
elseif not prices.undercut then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not post %s because your undercut (%s) is invalid. Check your settings."], itemLink or itemString, operation.undercut)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "invalid")
|
||||
elseif prices.normalPrice < prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not post %s because your normal price (%s) is lower than your minimum price (%s). Check your settings."], itemLink or itemString, operation.normalPrice, operation.minPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "invalid", operation)
|
||||
elseif prices.maxPrice < prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not post %s because your maximum price (%s) is lower than your minimum price (%s). Check your settings."], itemLink or itemString, operation.maxPrice, operation.minPrice)
|
||||
end
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "invalid", operation)
|
||||
elseif salePrice > 0 and prices.minPrice <= salePrice*1.05 then
|
||||
TSM:Printf(L["WARNING: You minimum price for %s is below its vendorsell price (with AH cut taken into account). Consider raising your minimum price, or vendoring the item."], itemLink or itemString)
|
||||
return true -- just a warning, doesn't make this invalid
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function Post:UpdateBagState()
|
||||
if time() == bagInfoUpdate then return end
|
||||
wipe(bagInfo)
|
||||
wipe(bagState)
|
||||
for bag, slot, itemString, quantity in TSMAPI:GetBagIterator(true) do
|
||||
tinsert(bagInfo, {bag, slot, itemString, quantity})
|
||||
bagState[itemString] = (bagState[itemString] or 0) + quantity
|
||||
end
|
||||
bagInfoUpdate = time()
|
||||
end
|
||||
|
||||
function Post:GetScanListAndSetup(GUIRef, options)
|
||||
-- setup stuff
|
||||
GUI = GUIRef
|
||||
isScanning = true
|
||||
wipe(postQueue)
|
||||
wipe(currentItem)
|
||||
wipe(itemLocations)
|
||||
wipe(TSM.operationLookup)
|
||||
totalToPost, totalPosted, count = 0, 0, 0
|
||||
|
||||
local tempList, scanList = {}, {}
|
||||
|
||||
Post:UpdateBagState()
|
||||
|
||||
local function HasEnoughToPost(operation, itemString)
|
||||
local maxStackSize = select(8, TSMAPI:GetSafeItemInfo(itemString)) or 1
|
||||
local perAuction = min(maxStackSize, operation.stackSize)
|
||||
local perAuctionIsCap = operation.stackSizeIsCap
|
||||
local num = (bagState[itemString] or 0) - operation.keepQuantity
|
||||
return num >= perAuction or (perAuctionIsCap and num > 0)
|
||||
end
|
||||
|
||||
for itemString in pairs(bagState) do
|
||||
local operations = options.itemOperations[itemString]
|
||||
if not tempList[itemString] and operations then
|
||||
for _, operation in ipairs(operations) do
|
||||
if operation.postCap > 0 and HasEnoughToPost(operation, itemString) then
|
||||
tempList[itemString] = tempList[itemString] or {}
|
||||
tinsert(tempList[itemString], operation)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for itemString, operations in pairs(tempList) do
|
||||
TSM.operationLookup[itemString] = operations
|
||||
local isValid = true
|
||||
for _, operation in ipairs(operations) do
|
||||
if not Post:ValidateOperation(itemString, operation) then
|
||||
isValid = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
if #options.itemOperations[itemString] ~= #operations then
|
||||
local j = 1
|
||||
for i=1, #options.itemOperations[itemString] do
|
||||
if options.itemOperations[itemString][i] ~= operations[j] then
|
||||
TSM.Log:AddLogRecord(itemString, "post", "Skip", "notEnough", options.itemOperations[itemString][i])
|
||||
else
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if isValid then
|
||||
tinsert(scanList, itemString)
|
||||
end
|
||||
end
|
||||
|
||||
TSMAPI:FireEvent("AUCTIONING:POST:START", {numItems=#scanList, isGroup=true})
|
||||
return scanList
|
||||
end
|
||||
|
||||
function Post:ProcessItem(itemString)
|
||||
local operations = TSM.operationLookup[itemString]
|
||||
if not operations then return end
|
||||
|
||||
local numInBags = Post:GetNumInBags(itemString)
|
||||
for _, operation in ipairs(operations) do
|
||||
local toPost, reason, buyout
|
||||
numInBags = numInBags - operation.keepQuantity
|
||||
toPost, reason, numInBags = Post:ShouldPost(itemString, operation, numInBags)
|
||||
numInBags = numInBags + operation.keepQuantity -- restore for the next operation if there are multiple
|
||||
local data = {}
|
||||
|
||||
if toPost then
|
||||
local bid
|
||||
bid, buyout, reason = Post:GetPostPrice(itemString, operation)
|
||||
local postTime = (operation.duration == 48 and 3) or (operation.duration == 24 and 2) or 1
|
||||
|
||||
for i = 1, #toPost do
|
||||
local stackSize, numStacks = unpack(toPost[i])
|
||||
|
||||
-- Increase the bid/buyout based on how many items we're posting
|
||||
local stackBid, stackBuyout = floor(bid * stackSize), floor(buyout * stackSize)
|
||||
Post:QueueItemToPost(itemString, numStacks, stackSize, stackBid, stackBuyout, postTime, operation)
|
||||
tinsert(data, { numStacks = numStacks, stackSize = stackSize, buyout = buyout, postTime = postTime })
|
||||
end
|
||||
end
|
||||
|
||||
TSM.Log:AddLogRecord(itemString, "post", (toPost and L["Post"] or L["Skip"]), reason, operation, buyout)
|
||||
if #postQueue > 0 and not currentItem.bag then
|
||||
Post:SetupForAction()
|
||||
end
|
||||
|
||||
if numInBags < 0 then error("less than 0") end
|
||||
if numInBags == 0 then break end
|
||||
end
|
||||
end
|
||||
|
||||
function Post:ShouldPost(itemString, operation, numInBags)
|
||||
local maxStackSize = select(8, TSMAPI:GetSafeItemInfo(itemString))
|
||||
local perAuction = min(maxStackSize, operation.stackSize)
|
||||
local maxCanPost = floor(numInBags / perAuction)
|
||||
local perAuctionIsCap = operation.stackSizeIsCap
|
||||
|
||||
if maxCanPost == 0 then
|
||||
if perAuctionIsCap then
|
||||
perAuction = numInBags
|
||||
maxCanPost = 1
|
||||
else
|
||||
return nil, "notEnough", numInBags -- not enough for single post
|
||||
end
|
||||
end
|
||||
|
||||
local activeAuctions = 0
|
||||
local extraStack
|
||||
local buyout, bid, _, isWhitelist, isPlayer, isInvalidSeller = TSM.Scan:GetLowestAuction(itemString, operation)
|
||||
|
||||
if isInvalidSeller then
|
||||
TSM:Printf(L["Seller name of lowest auction for item %s was not returned from server. Skipping this item."], select(2, TSMAPI:GetSafeItemInfo(itemString)))
|
||||
return nil, "invalidSeller", numInBags
|
||||
end
|
||||
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString)
|
||||
if buyout and buyout <= prices.minPrice then
|
||||
-- lowest is below min price
|
||||
if not prices.resetPrice then
|
||||
-- lowest is below the min price and there's no reset price
|
||||
return nil, "belowMinPrice", numInBags
|
||||
else
|
||||
-- lowest is below the min price, but there is a reset price
|
||||
local priceResetBuyout = prices.resetPrice
|
||||
local priceResetBid = priceResetBuyout * operation.bidPercent
|
||||
activeAuctions = TSM.Scan:GetPlayerAuctionCount(itemString, priceResetBuyout, priceResetBid, perAuction, operation)
|
||||
end
|
||||
elseif isWhitelist and not isPlayer and not TSM.db.global.matchWhitelist then
|
||||
-- lowest is somebody on the whitelist and we aren't price matching
|
||||
return nil, "notPostingWhitelist", numInBags
|
||||
elseif isPlayer or isWhitelist then
|
||||
-- Either the player or a whitelist person is the lowest teir so use this tiers quantity of items
|
||||
activeAuctions = TSM.Scan:GetPlayerAuctionCount(itemString, buyout or 0, bid or 0, perAuction, operation)
|
||||
end
|
||||
|
||||
-- If we have a post cap of 20, and 10 active auctions, but we can only have 5 of the item then this will only let us create 5 auctions
|
||||
-- however, if we have 20 of the item it will let us post another 10
|
||||
local auctionsCreated = min(operation.postCap - activeAuctions, maxCanPost)
|
||||
if auctionsCreated <= 0 then
|
||||
return nil, "tooManyPosted", numInBags
|
||||
end
|
||||
|
||||
if (auctionsCreated + activeAuctions) < operation.postCap then
|
||||
-- can post at least one more
|
||||
local extra = numInBags % perAuction
|
||||
if perAuctionIsCap and extra > 0 then
|
||||
extraStack = extra
|
||||
end
|
||||
end
|
||||
|
||||
if Post:FindItemSlot(itemString) then
|
||||
local posts = { { perAuction, auctionsCreated } }
|
||||
numInBags = numInBags - perAuction * auctionsCreated
|
||||
if extraStack then
|
||||
numInBags = numInBags - extraStack
|
||||
tinsert(posts, { extraStack, 1 })
|
||||
end
|
||||
-- third return value specifies whether there's extra left over in the player's bags after this operation
|
||||
return posts, nil, numInBags
|
||||
end
|
||||
end
|
||||
|
||||
function Post:GetPostPrice(itemString, operation)
|
||||
local lowestBuyout, lowestBid, lowestOwner, isWhitelist, isPlayer = TSM.Scan:GetLowestAuction(itemString, operation)
|
||||
local bid, buyout, info
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString)
|
||||
if not lowestOwner then
|
||||
-- No other auctions up, default to normalPrice
|
||||
info = "postingNormal"
|
||||
buyout = prices.normalPrice
|
||||
elseif prices.resetPrice and lowestBuyout <= prices.minPrice then
|
||||
-- item is below min price and a priceReset is set
|
||||
if operation.priceReset == "minPrice" then
|
||||
info = "postingResetMin"
|
||||
elseif operation.priceReset == "maxPrice" then
|
||||
info = "postingResetMax"
|
||||
elseif operation.priceReset == "normalPrice" then
|
||||
info = "postingResetNormal"
|
||||
else
|
||||
-- should never happen, but better to throw an error here than cause issues later on
|
||||
error("Unknown 'below minimum' price setting.")
|
||||
end
|
||||
buyout = prices.resetPrice
|
||||
elseif isPlayer or (isWhitelist and lowestBuyout - prices.undercut <= prices.maxPrice) then
|
||||
-- Either we already have one up or someone on the whitelist does
|
||||
bid, buyout = min(lowestBid, lowestBuyout), lowestBuyout
|
||||
info = isPlayer and "postingPlayer" or "postingWhitelist"
|
||||
else
|
||||
-- we've been undercut and we are going to undercut back
|
||||
buyout = lowestBuyout - prices.undercut
|
||||
-- if the cheapest is above our max price, follow the aboveMax setting
|
||||
if buyout > prices.maxPrice then
|
||||
if operation.aboveMax == "minPrice" then
|
||||
info = "aboveMaxMin"
|
||||
elseif operation.aboveMax == "maxPrice" then
|
||||
info = "aboveMaxMax"
|
||||
elseif operation.aboveMax == "normalPrice" then
|
||||
info = "aboveMaxNormal"
|
||||
else
|
||||
-- should never happen, but better to throw an error here than cause issues later on
|
||||
error("Unknown 'above maximum' price setting.")
|
||||
end
|
||||
buyout = prices.aboveMax
|
||||
end
|
||||
-- make sure the buyout and bid aren't below the minPrice
|
||||
buyout = max(buyout, prices.minPrice)
|
||||
-- Check if the bid is too low
|
||||
bid = max(buyout * operation.bidPercent, prices.minPrice)
|
||||
info = info or "postingUndercut"
|
||||
end
|
||||
|
||||
-- set the bid if it hasn't been set
|
||||
bid = bid or (buyout * operation.bidPercent)
|
||||
return bid, buyout, info
|
||||
end
|
||||
|
||||
function Post:QueueItemToPost(itemString, numStacks, stackSize, bid, buyout, postTime, operation)
|
||||
itemLocations[itemString] = itemLocations[itemString] or Post:FindItemSlot(itemString, true)
|
||||
|
||||
for i = 1, numStacks do
|
||||
local oBag, oSlot
|
||||
for j = 1, #itemLocations[itemString] do
|
||||
if itemLocations[itemString][j].quantity >= stackSize then
|
||||
oBag, oSlot = itemLocations[itemString][j].bag, itemLocations[itemString][j].slot
|
||||
itemLocations[itemString][j].quantity = itemLocations[itemString][j].quantity - stackSize
|
||||
break
|
||||
end
|
||||
end
|
||||
if not oBag or not oSlot then
|
||||
oBag, oSlot = Post:FindItemSlot(itemString)
|
||||
if not (oBag and oSlot) then break end
|
||||
end
|
||||
tinsert(postQueue, { bag = oBag, slot = oSlot, bid = bid, buyout = buyout, postTime = postTime, stackSize = stackSize, numStacks = (numStacks - i + 1), itemString = itemString, operation = operation })
|
||||
totalToPost = totalToPost + 1
|
||||
end
|
||||
TSM.Manage:UpdateStatus("manage", totalPosted, totalToPost)
|
||||
end
|
||||
|
||||
function Post:FindItemSlot(findItemString, allLocations)
|
||||
local locations = {}
|
||||
Post:UpdateBagState()
|
||||
for _, data in ipairs(bagInfo) do
|
||||
local bag, slot, itemString, quantity = unpack(data)
|
||||
if findItemString == itemString then
|
||||
if not allLocations then
|
||||
return bag, slot
|
||||
end
|
||||
tinsert(locations, { bag = bag, slot = slot, quantity = quantity })
|
||||
end
|
||||
end
|
||||
return allLocations and locations
|
||||
end
|
||||
|
||||
function Post:GetNumInBags(itemString)
|
||||
local num = 0
|
||||
Post:UpdateBagState()
|
||||
return bagState[itemString] or 0
|
||||
end
|
||||
|
||||
local timeout = CreateFrame("Frame")
|
||||
timeout:Hide()
|
||||
timeout:SetScript("OnUpdate", function(self, elapsed)
|
||||
self.timeLeft = self.timeLeft - elapsed
|
||||
if self.timeLeft <= 0 or (postQueue[1] and postQueue[1].bag and postQueue[1].slot and not select(3, GetContainerItemInfo(postQueue[1].bag, postQueue[1].slot)) and not AuctionsCreateAuctionButton:IsEnabled()) then
|
||||
tremove(postQueue, 1)
|
||||
Post:UpdateItem()
|
||||
end
|
||||
end)
|
||||
|
||||
function Post:SetupForAction()
|
||||
Post:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||
timeout:Hide()
|
||||
ClearCursor()
|
||||
TSM.Manage:UpdateStatus("manage", totalPosted, totalToPost)
|
||||
wipe(currentItem)
|
||||
currentItem = postQueue[1]
|
||||
TSM.Manage:SetCurrentItem(currentItem)
|
||||
GUI.buttons:Enable()
|
||||
end
|
||||
|
||||
-- Check if an auction was posted and move on if so
|
||||
function Post:CHAT_MSG_SYSTEM(_, msg)
|
||||
if msg == ERR_AUCTION_STARTED then
|
||||
count = count + 1
|
||||
TSM.Manage:UpdateStatus("confirm", count, totalToPost)
|
||||
end
|
||||
end
|
||||
|
||||
local countFrame = CreateFrame("Frame")
|
||||
countFrame:Hide()
|
||||
countFrame.count = -1
|
||||
countFrame.timeLeft = 10
|
||||
countFrame:SetScript("OnUpdate", function(self, elapsed)
|
||||
self.timeLeft = self.timeLeft - elapsed
|
||||
if count >= totalToPost or self.timeLeft <= 0 then
|
||||
self:Hide()
|
||||
Post:Stop()
|
||||
elseif count ~= self.count then
|
||||
self.count = count
|
||||
self.timeLeft = (totalToPost - count) * 2
|
||||
end
|
||||
end)
|
||||
|
||||
local function DelayFrame()
|
||||
if #postQueue > 0 then
|
||||
Post:UpdateItem()
|
||||
TSMAPI:CancelFrame("postDelayFrame")
|
||||
elseif not isScanning then
|
||||
TSM.Manage:UpdateStatus("manage", totalPosted, totalToPost)
|
||||
Post:Stop()
|
||||
TSMAPI:CancelFrame("postDelayFrame")
|
||||
end
|
||||
end
|
||||
|
||||
function Post:UpdateItem()
|
||||
ClearCursor()
|
||||
timeout:Hide()
|
||||
if #postQueue == 0 then
|
||||
GUI.buttons:Disable()
|
||||
if isScanning then
|
||||
TSMAPI:CreateFunctionRepeat("postDelayFrame", DelayFrame)
|
||||
else
|
||||
TSM.Manage:UpdateStatus("manage", totalPosted + 1, totalToPost)
|
||||
countFrame:Show()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
totalPosted = totalPosted + 1
|
||||
TSM.Manage:UpdateStatus("manage", totalPosted, totalToPost)
|
||||
wipe(currentItem)
|
||||
currentItem = postQueue[1]
|
||||
TSM.Manage:SetCurrentItem(currentItem)
|
||||
GUI.buttons:Enable()
|
||||
end
|
||||
|
||||
function Post:DoAction()
|
||||
timeout.timeLeft = 0.1
|
||||
timeout:Show()
|
||||
if not AuctionFrameAuctions.duration then
|
||||
-- Fix in case Blizzard_AuctionUI hasn't set this value yet (which could cause an error)
|
||||
AuctionFrameAuctions.duration = 2
|
||||
end
|
||||
|
||||
if not currentItem.itemString then
|
||||
timeout:Hide()
|
||||
Post:SkipItem()
|
||||
return
|
||||
end
|
||||
|
||||
if type(currentItem.bag) ~= "number" or type(currentItem.slot) ~= "number" then
|
||||
local bag, slot = Post:FindItemSlot(currentItem.itemString)
|
||||
if not bag or not slot then
|
||||
local link = select(2, TSMAPI:GetSafeItemInfo(currentItem.itemString)) or currentItem.itemString
|
||||
TSM:Printf(L["Auctioning could not find %s in your bags so has skipped posting it. Running the scan again should resolve this issue."], link)
|
||||
timeout:Hide()
|
||||
Post:SkipItem()
|
||||
return
|
||||
end
|
||||
currentItem.bag = bag
|
||||
currentItem.slot = slot
|
||||
end
|
||||
local itemString = TSMAPI:GetBaseItemString(GetContainerItemLink(currentItem.bag, currentItem.slot), true)
|
||||
if itemString ~= currentItem.itemString then
|
||||
TSM:Print(L["Please don't move items around in your bags while a post scan is running! The item was skipped to avoid an incorrect item being posted."])
|
||||
timeout:Hide()
|
||||
Post:SkipItem()
|
||||
return
|
||||
end
|
||||
|
||||
PickupContainerItem(currentItem.bag, currentItem.slot)
|
||||
ClickAuctionSellItemButton(AuctionsItemButton, "LeftButton")
|
||||
StartAuction(currentItem.bid, currentItem.buyout, currentItem.postTime, currentItem.stackSize, 1)
|
||||
GUI.buttons:Disable()
|
||||
end
|
||||
|
||||
function Post:SkipItem()
|
||||
local toSkip = {}
|
||||
local skipped = tremove(postQueue, 1)
|
||||
count = count + 1
|
||||
for i, info in ipairs(postQueue) do
|
||||
if info.itemString == skipped.itemString and info.bid == skipped.bid and info.buyout == skipped.buyout then
|
||||
tinsert(toSkip, i)
|
||||
end
|
||||
end
|
||||
sort(toSkip, function(a, b) return a > b end)
|
||||
for _, index in ipairs(toSkip) do
|
||||
tremove(postQueue, index)
|
||||
count = count + 1
|
||||
totalPosted = totalPosted + 1
|
||||
end
|
||||
TSM.Manage:UpdateStatus("manage", totalPosted, totalToPost)
|
||||
TSM.Manage:UpdateStatus("confirm", count, totalToPost)
|
||||
Post:UpdateItem()
|
||||
end
|
||||
|
||||
function Post:Stop()
|
||||
GUI:Stopped()
|
||||
TSMAPI:CancelFrame("postDelayFrame")
|
||||
Post:UnregisterAllEvents()
|
||||
TSMAPI:FireEvent("AUCTIONING:POST:STOPPED")
|
||||
|
||||
wipe(currentItem)
|
||||
totalToPost, totalPosted = 0, 0
|
||||
isScanning = false
|
||||
end
|
||||
|
||||
function Post:GetAHGoldTotal()
|
||||
local total = 0
|
||||
local incomingTotal = 0
|
||||
for i = 1, GetNumAuctionItems("owner") do
|
||||
local count, _, _, _, _, _, buyoutAmount = select(3, GetAuctionItemInfo("owner", i))
|
||||
total = total + buyoutAmount
|
||||
if count == 0 then
|
||||
incomingTotal = incomingTotal + buyoutAmount
|
||||
end
|
||||
end
|
||||
return TSMAPI:FormatTextMoneyIcon(total), TSMAPI:FormatTextMoneyIcon(incomingTotal)
|
||||
end
|
||||
|
||||
function Post:GetCurrentItem()
|
||||
return currentItem
|
||||
end
|
||||
|
||||
function Post:EditPostPrice(itemString, buyout, operation)
|
||||
local bid = buyout * operation.bidPercent
|
||||
|
||||
if currentItem.itemString == itemString then
|
||||
currentItem.buyout = buyout
|
||||
currentItem.bid = bid
|
||||
end
|
||||
|
||||
for _, data in ipairs(postQueue) do
|
||||
if data.itemString == itemString then
|
||||
data.buyout = buyout
|
||||
data.bid = bid
|
||||
end
|
||||
end
|
||||
TSM.Manage:SetCurrentItem(currentItem)
|
||||
end
|
||||
|
||||
function Post:DoneScanning()
|
||||
isScanning = false
|
||||
return totalToPost
|
||||
end
|
||||
@@ -0,0 +1,735 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Reset = TSM:NewModule("Reset", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
|
||||
local resetData, summarySTCache, showCache, itemsReset, justBought = {}, {}, {}, {}, {}
|
||||
local isScanning, doneScanningText, currentItem, GUI
|
||||
local summaryST, auctionST, resetButtons
|
||||
local currentAuction
|
||||
|
||||
function Reset:Show(frame)
|
||||
summaryST = summaryST or Reset:CreateSummaryST(frame.content)
|
||||
summaryST:Show()
|
||||
summaryST:SetData({})
|
||||
|
||||
auctionST = auctionST or Reset:CreateAuctionST(frame.content)
|
||||
auctionST:Hide()
|
||||
auctionST:SetData({})
|
||||
|
||||
resetButtons = resetButtons or Reset:CreateResetButtons(frame)
|
||||
resetButtons:Show()
|
||||
resetButtons.stop:Enable()
|
||||
resetButtons.stop.isDone = nil
|
||||
resetButtons.stop:SetText(L["Stop"])
|
||||
resetButtons:Disable()
|
||||
end
|
||||
|
||||
function Reset:Hide()
|
||||
if summaryST then
|
||||
summaryST:SetData({})
|
||||
summaryST:Hide()
|
||||
|
||||
auctionST:SetData({})
|
||||
auctionST:Hide()
|
||||
|
||||
resetButtons:Hide()
|
||||
Reset.isSearching = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function ColSortMethod(st, aRow, bRow, col)
|
||||
local a, b = st:GetCell(aRow, col), st:GetCell(bRow, col)
|
||||
local column = st.cols[col]
|
||||
local direction = column.sort or column.defaultsort or "dsc"
|
||||
local aValue, bValue = ((a.args or {})[1] or a.value), ((b.args or {})[1] or b.value)
|
||||
if direction == "asc" then
|
||||
return aValue < bValue
|
||||
else
|
||||
return aValue > bValue
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:CreateSummaryST(parent)
|
||||
local stCols = {
|
||||
{
|
||||
name = L["Item"],
|
||||
width = 0.31,
|
||||
},
|
||||
{
|
||||
name = L["Operation"],
|
||||
width = 0.17,
|
||||
},
|
||||
{
|
||||
name = L["Quantity (Yours)"],
|
||||
width = 0.13,
|
||||
align = "CENTER"
|
||||
},
|
||||
{
|
||||
name = L["Total Cost"],
|
||||
width = 0.12,
|
||||
align = "RIGHT",
|
||||
},
|
||||
{
|
||||
name = L["Target Price"],
|
||||
width = 0.12,
|
||||
align = "RIGHT",
|
||||
},
|
||||
{
|
||||
name = L["Profit Per Item"],
|
||||
width = 0.12,
|
||||
align = "RIGHT",
|
||||
},
|
||||
}
|
||||
|
||||
local handlers = {
|
||||
OnEnter = function(_, data, self)
|
||||
if not data.operation then return end
|
||||
local prices = TSM.Util:GetItemPrices(data.operation, data.itemString, true)
|
||||
GameTooltip:SetOwner(self, "ANCHOR_NONE")
|
||||
GameTooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT")
|
||||
GameTooltip:AddLine(data.itemLink)
|
||||
GameTooltip:AddLine(L["Max Cost:"].." "..(TSMAPI:FormatTextMoney(prices.resetMaxCost, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Min Profit:"].." "..(TSMAPI:FormatTextMoney(prices.resetMinProfit, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Max Quantity:"].." "..(TSMAPI:FormatTextMoney(data.operation.resetMaxQuantity, "|cffffffff") or "---"))
|
||||
GameTooltip:AddLine(L["Max Price Per:"].." "..(TSMAPI:FormatTextMoney(data.operation.resetMaxPricePer, "|cffffffff") or "---"))
|
||||
|
||||
if TSM.Reset:IsScanning() then
|
||||
GameTooltip:AddLine("\n"..L["Must wait for scan to finish before starting to reset."])
|
||||
else
|
||||
GameTooltip:AddLine(TSMAPI.Design:GetInlineColor("link2").."\n"..L["Click to show auctions for this item."].."|r")
|
||||
GameTooltip:AddLine(TSMAPI.Design:GetInlineColor("link2")..L["Shift-Right-Click to show the options for this item's Auctioning group."].."|r")
|
||||
end
|
||||
GameTooltip:Show()
|
||||
end,
|
||||
OnLeave = function()
|
||||
GameTooltip:Hide()
|
||||
end,
|
||||
OnClick = function(_, data, _, button)
|
||||
if TSM.Reset:IsScanning() then return end
|
||||
if button == "LeftButton" then
|
||||
summaryST:Hide()
|
||||
auctionST:Show()
|
||||
resetButtons.summaryButton:Enable()
|
||||
|
||||
currentItem = CopyTable(data)
|
||||
Reset:UpdateAuctionST()
|
||||
Reset:SelectAuctionRow(auctionST.rowData[1])
|
||||
currentItem.isReset = true
|
||||
TSM.Manage:SetInfoText(currentItem)
|
||||
elseif button == "RightButton" then
|
||||
if IsShiftKeyDown() then
|
||||
TSMAPI:ShowOperationOptions("Auctioning", TSM.operationNameLookup[data.operation])
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local st = TSMAPI:CreateScrollingTable(parent, stCols, handlers)
|
||||
st:SetParent(parent)
|
||||
st:SetAllPoints()
|
||||
st:EnableSorting(true)
|
||||
return st
|
||||
end
|
||||
|
||||
function Reset:CreateAuctionST(parent)
|
||||
local stCols = {
|
||||
{
|
||||
name = L["Seller"],
|
||||
width = 0.4,
|
||||
},
|
||||
{
|
||||
name = L["Stack Size"],
|
||||
width = 0.2,
|
||||
align = "CENTER",
|
||||
},
|
||||
{
|
||||
name = L["Auction Buyout"],
|
||||
width = 0.35,
|
||||
align = "RIGHT",
|
||||
},
|
||||
}
|
||||
|
||||
local handlers = {
|
||||
OnClick = function(_, data)
|
||||
Reset:SelectAuctionRow(data)
|
||||
end,
|
||||
}
|
||||
|
||||
local st = TSMAPI:CreateScrollingTable(parent, stCols, handlers)
|
||||
st:SetParent(parent)
|
||||
st:SetAllPoints()
|
||||
st:EnableSorting(false)
|
||||
return st
|
||||
end
|
||||
|
||||
function Reset:CreateResetButtons(parent)
|
||||
local height = 24
|
||||
local frame = CreateFrame("Frame", nil, parent)
|
||||
frame:SetHeight(height)
|
||||
frame:SetWidth(210)
|
||||
frame:SetPoint("BOTTOMRIGHT", -92, 6)
|
||||
|
||||
frame.Disable = function(self)
|
||||
self.buyout:Disable()
|
||||
self.cancel:Disable()
|
||||
self.summaryButton:Disable()
|
||||
end
|
||||
|
||||
local function OnCancelClick(self)
|
||||
if self.auction then
|
||||
for i=GetNumAuctionItems("owner"), 1, -1 do
|
||||
if Reset:VerifyAuction(i, "owner", self.auction.record, self.auction.itemString) then
|
||||
CancelAuction(i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
self.auction = nil
|
||||
self:Disable()
|
||||
Reset:RegisterMessage("TSM_AH_EVENTS", Reset.RemoveCurrentAuction)
|
||||
TSMAPI:WaitForAuctionEvents("Cancel")
|
||||
end
|
||||
|
||||
local function OnStopClick(self)
|
||||
if self.isDone then
|
||||
Reset:Hide()
|
||||
TSM.GUI:ShowSelectionFrame()
|
||||
else
|
||||
TSM.Manage:OnGUIEvent("stop")
|
||||
GUI:Stopped(true)
|
||||
Reset:DoneScanning()
|
||||
end
|
||||
end
|
||||
|
||||
local function ReturnToSummary()
|
||||
frame:Disable()
|
||||
auctionST:Hide()
|
||||
summaryST:Show()
|
||||
Reset:UpdateSummaryST()
|
||||
end
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 22, "TSMAuctioningResetBuyoutButton")
|
||||
button:SetPoint("TOPLEFT", -5, 0)
|
||||
button:SetWidth(80)
|
||||
button:SetHeight(height)
|
||||
button:SetText(BUYOUT)
|
||||
button:SetScript("OnClick", Reset.BuyAuction)
|
||||
frame.buyout = button
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 18, "TSMAuctioningResetCancelButton")
|
||||
button:SetPoint("TOPLEFT", frame.buyout, "TOPRIGHT", 5, 0)
|
||||
button:SetWidth(70)
|
||||
button:SetHeight(height)
|
||||
button:SetText(L["Cancel"])
|
||||
button:SetScript("OnClick", OnCancelClick)
|
||||
frame.cancel = button
|
||||
|
||||
local button = TSMAPI.GUI:CreateButton(frame, 18, "TSMAuctioningResetStopButton")
|
||||
button:SetPoint("TOPLEFT", frame.cancel, "TOPRIGHT", 5, 0)
|
||||
button:SetWidth(60)
|
||||
button:SetHeight(height)
|
||||
button:SetText(L["Stop"])
|
||||
button:SetScript("OnClick", OnStopClick)
|
||||
button.isDone = nil
|
||||
frame.stop = button
|
||||
|
||||
local summaryButton = TSMAPI.GUI:CreateButton(frame, 16)
|
||||
summaryButton:SetPoint("TOPRIGHT", parent, "TOPRIGHT", -10, -50)
|
||||
summaryButton:SetHeight(17)
|
||||
summaryButton:SetWidth(150)
|
||||
summaryButton:SetScript("OnClick", ReturnToSummary)
|
||||
summaryButton:SetText(L["Return to Summary"])
|
||||
frame.summaryButton = summaryButton
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function Reset:GetTotalQuantity(itemString)
|
||||
local playerTotal, altTotal = TSMAPI:ModuleAPI("ItemTracker", "playertotal", itemString)
|
||||
if playerTotal and altTotal then
|
||||
local guildTotal = TSMAPI:ModuleAPI("ItemTracker", "guildtotal", itemString) or 0
|
||||
local auctionTotal = TSMAPI:ModuleAPI("ItemTracker", "auctionstotal", itemString) or 0
|
||||
return playerTotal + altTotal + guildTotal + auctionTotal
|
||||
else
|
||||
return GetItemCount(itemString, true)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Reset:ValidateOperation(itemString, operation)
|
||||
local itemLink = select(2, TSMAPI:GetSafeItemInfo(itemString)) or itemString
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString, true)
|
||||
|
||||
-- don't reset this item if their settings are invalid
|
||||
if not prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your minimum price (%s) is invalid. Check your settings."], itemLink, operation.minPrice)
|
||||
end
|
||||
elseif not prices.maxPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your maximum price (%s) is invalid. Check your settings."], itemLink, operation.maxPrice)
|
||||
end
|
||||
elseif not prices.normalPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your normal price (%s) is invalid. Check your settings."], itemLink, operation.normalPrice)
|
||||
end
|
||||
elseif not prices.resetMaxCost then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your reset max cost (%s) is invalid. Check your settings."], itemLink, operation.resetMaxCost)
|
||||
end
|
||||
elseif not prices.resetMinProfit then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your reset min profit (%s) is invalid. Check your settings."], itemLink, operation.resetMinProfit)
|
||||
end
|
||||
elseif not prices.resetResolution then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your reset resolution (%s) is invalid. Check your settings."], itemLink, operation.resetResolution)
|
||||
end
|
||||
elseif not prices.resetMaxItemCost then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your reset max item cost (%s) is invalid. Check your settings."], itemLink, operation.resetMaxItemCost)
|
||||
end
|
||||
elseif not prices.undercut then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your undercut (%s) is invalid. Check your settings."], itemLink or itemString, operation.undercut)
|
||||
end
|
||||
elseif prices.maxPrice < prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your maximum price (%s) is lower than your minimum price (%s). Check your settings."], itemLink, operation.maxPrice, operation.minPrice)
|
||||
end
|
||||
elseif prices.normalPrice < prices.minPrice then
|
||||
if not TSM.db.global.disableInvalidMsg then
|
||||
TSM:Printf(L["Did not reset %s because your normal price (%s) is lower than your minimum price (%s). Check your settings."], itemLink, operation.normalPrice, operation.minPrice)
|
||||
end
|
||||
elseif Reset:GetTotalQuantity(itemString) >= operation.resetMaxInventory then
|
||||
-- already have at least max inventory - do nothing here
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:GetScanListAndSetup(GUIRef, options)
|
||||
local scanList, tempList, groupTemp = {}, {}, {}
|
||||
|
||||
GUI = GUIRef
|
||||
doneScanningText = nil
|
||||
isScanning = true
|
||||
wipe(resetData)
|
||||
wipe(summarySTCache)
|
||||
wipe(showCache)
|
||||
wipe(itemsReset)
|
||||
wipe(TSM.operationLookup)
|
||||
|
||||
local temp = {}
|
||||
for itemString, operations in pairs(options.itemOperations) do
|
||||
for _, operation in ipairs(operations) do
|
||||
if operation.resetEnabled and Reset:ValidateOperation(itemString, operation) then
|
||||
temp[itemString] = temp[itemString] or {}
|
||||
tinsert(temp[itemString], operation)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for itemString, operations in pairs(temp) do
|
||||
TSM.operationLookup[itemString] = operations
|
||||
tinsert(scanList, itemString)
|
||||
end
|
||||
|
||||
return scanList
|
||||
end
|
||||
|
||||
function Reset:ProcessItem(itemString)
|
||||
local operations = TSM.operationLookup[itemString]
|
||||
if not operations then return end
|
||||
|
||||
for _, operation in ipairs(operations) do
|
||||
Reset:ProcessItemOperation(itemString, operation)
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:ProcessItemOperation(itemString, operation)
|
||||
local scanData = TSM.Scan.auctionData[itemString]
|
||||
if not scanData then return end
|
||||
local prices = TSM.Util:GetItemPrices(operation, itemString, true)
|
||||
local priceLevels = {}
|
||||
local addNormal, isFirstItem = true, true
|
||||
local currentPriceLevel = -math.huge
|
||||
|
||||
for _, record in ipairs(scanData.compactRecords) do
|
||||
local itemBuyout = record:GetItemBuyout()
|
||||
if itemBuyout then
|
||||
if not isFirstItem and itemBuyout > prices.minPrice and itemBuyout < prices.maxPrice and itemBuyout > (currentPriceLevel + prices.resetResolution) then
|
||||
if itemBuyout >= prices.normalPrice then
|
||||
addNormal = false
|
||||
end
|
||||
currentPriceLevel = itemBuyout
|
||||
tinsert(priceLevels, itemBuyout)
|
||||
end
|
||||
isFirstItem = false
|
||||
end
|
||||
end
|
||||
|
||||
if addNormal then
|
||||
tinsert(priceLevels, prices.normalPrice)
|
||||
end
|
||||
|
||||
for _, targetPrice in ipairs(priceLevels) do
|
||||
local playerCost, cost, quantity, maxItemCost, playerQuantity = 0, 0, 0, 0, 0
|
||||
|
||||
for _, record in ipairs(scanData.compactRecords) do
|
||||
local itemBuyout = record:GetItemBuyout()
|
||||
if itemBuyout then
|
||||
if itemBuyout >= targetPrice then
|
||||
break
|
||||
end
|
||||
|
||||
if itemBuyout > maxItemCost then
|
||||
maxItemCost = itemBuyout
|
||||
end
|
||||
|
||||
if not record:IsPlayer() then
|
||||
cost = cost + (record:GetItemBuyout() * record.totalQuantity)
|
||||
else
|
||||
playerQuantity = playerQuantity + record.totalQuantity
|
||||
playerCost = playerCost + (record:GetItemBuyout() * record.totalQuantity)
|
||||
end
|
||||
quantity = quantity + record.totalQuantity
|
||||
end
|
||||
end
|
||||
|
||||
local profit = (targetPrice * quantity - (cost + playerCost)) / quantity
|
||||
if profit > 0 then
|
||||
tinsert(resetData, {prices=prices, itemString=itemString, targetPrice=targetPrice, cost=cost, quantity=quantity, profit=profit, maxItemCost=maxItemCost, playerQuantity=playerQuantity, operation=operation})
|
||||
end
|
||||
end
|
||||
|
||||
Reset:UpdateSummaryST()
|
||||
end
|
||||
|
||||
function Reset:ShouldShow(data)
|
||||
local result = {validCost=true, validQuantity=true, validProfit=true, isValid=true}
|
||||
|
||||
if data.cost > data.prices.resetMaxCost or data.maxItemCost > data.prices.resetMaxItemCost then
|
||||
result.validCost = false
|
||||
end
|
||||
|
||||
if data.quantity > data.operation.resetMaxQuantity or data.quantity > (data.operation.resetMaxInventory - Reset:GetTotalQuantity(data.itemString)) then
|
||||
result.validQuantity = false
|
||||
end
|
||||
|
||||
if data.profit < data.prices.resetMinProfit then
|
||||
result.validProfit = false
|
||||
end
|
||||
|
||||
return (result.validCost and result.validQuantity and result.validProfit), result
|
||||
end
|
||||
|
||||
function Reset:GetSummarySTRow(data)
|
||||
local function GetQuantityText(quantity, playerQuantity, isValid)
|
||||
if isValid then
|
||||
if playerQuantity > 0 then
|
||||
return quantity..TSMAPI.Design:GetInlineColor("link2").."("..playerQuantity..")|r"
|
||||
else
|
||||
return quantity
|
||||
end
|
||||
end
|
||||
|
||||
return "|cffff2222"..quantity.."|r"
|
||||
end
|
||||
|
||||
local function GetPriceText(amount, isValid)
|
||||
local color
|
||||
if not isValid then
|
||||
color = "|cffff2222"
|
||||
end
|
||||
|
||||
return TSMAPI:FormatTextMoney(amount, color, true) or "---"
|
||||
end
|
||||
|
||||
local name, itemLink = TSMAPI:GetSafeItemInfo(data.itemString)
|
||||
local _, shouldShowDetails = Reset:ShouldShow(data)
|
||||
|
||||
local row = {
|
||||
cols = {
|
||||
{
|
||||
value = itemLink,
|
||||
sortArg = name,
|
||||
},
|
||||
{
|
||||
value = data.operation and TSM.operationNameLookup[data.operation] or "---",
|
||||
sortArg = data.operation and TSM.operationNameLookup[data.operation] or "---",
|
||||
},
|
||||
{
|
||||
value = GetQuantityText(data.quantity, data.playerQuantity, shouldShowDetails.validQuantity),
|
||||
sortArg = data.quantity,
|
||||
},
|
||||
{
|
||||
value = GetPriceText(data.cost or 0, shouldShowDetails.validCost),
|
||||
sortArg = data.cost or 0,
|
||||
},
|
||||
{
|
||||
value = GetPriceText(data.targetPrice, true),
|
||||
sortArg = data.targetPrice,
|
||||
},
|
||||
{
|
||||
value = GetPriceText(data.profit, shouldShowDetails.validProfit),
|
||||
sortArg = data.profit,
|
||||
},
|
||||
},
|
||||
itemString = data.itemString,
|
||||
targetPrice = data.targetPrice,
|
||||
num = data.quantity,
|
||||
profit = data.profit,
|
||||
operation = data.operation,
|
||||
}
|
||||
|
||||
return row
|
||||
end
|
||||
|
||||
function Reset:UpdateSummaryST()
|
||||
local rows = {}
|
||||
local num = 0
|
||||
|
||||
for _, data in ipairs(resetData) do
|
||||
if not itemsReset[data.itemString] then
|
||||
if showCache[data] == nil then
|
||||
showCache[data] = Reset:ShouldShow(data) or false
|
||||
end
|
||||
if showCache[data] then
|
||||
local key = data.itemString .. data.targetPrice
|
||||
if not summarySTCache[key] then num = num + 1 end
|
||||
summarySTCache[key] = summarySTCache[key] or Reset:GetSummarySTRow(data)
|
||||
tinsert(rows, summarySTCache[key])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
summaryST:SetData(rows)
|
||||
|
||||
if doneScanningText then
|
||||
TSM.Manage:SetInfoText(doneScanningText)
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:GetAuctionSTRow(record, index)
|
||||
local function GetSellerText(name)
|
||||
if TSMAPI:IsPlayer(name) then
|
||||
return "|cff99ffff" .. name .. "|r"
|
||||
elseif TSM.db.factionrealm.whitelist[strlower(name)] then
|
||||
return name .. " |cffff2222(" .. L["Whitelist"] .. ")|r"
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
local row = {
|
||||
cols = {
|
||||
{
|
||||
value = GetSellerText(record.seller),
|
||||
sortArg = record.seller,
|
||||
},
|
||||
{
|
||||
value = record.count,
|
||||
sortArg = record.count,
|
||||
},
|
||||
{
|
||||
value = TSMAPI:FormatTextMoney(record.buyout, nil, true) or "---",
|
||||
sortArg = record.buyout,
|
||||
},
|
||||
},
|
||||
record = record,
|
||||
itemString = TSMAPI:GetBaseItemString(record.parent:GetItemString(), true),
|
||||
index = index,
|
||||
}
|
||||
|
||||
return row
|
||||
end
|
||||
|
||||
function Reset:UpdateAuctionST()
|
||||
local scanData = TSM.Scan.auctionData[currentItem.itemString]
|
||||
|
||||
local rows = {}
|
||||
|
||||
for i, record in ipairs(scanData.records) do
|
||||
local itemBuyout = record:GetItemBuyout()
|
||||
if itemBuyout and itemBuyout >= currentItem.targetPrice then
|
||||
break
|
||||
end
|
||||
|
||||
tinsert(rows, Reset:GetAuctionSTRow(record, i))
|
||||
end
|
||||
|
||||
auctionST:SetData(rows)
|
||||
end
|
||||
|
||||
function Reset:SelectAuctionRow(data)
|
||||
local function OnAuctionFound(index)
|
||||
local row = auctionST.rowData[auctionST:GetSelection()]
|
||||
|
||||
resetButtons.summaryButton:Enable()
|
||||
resetButtons.buyout:Enable()
|
||||
resetButtons.buyout.auction = {index=index, row=row.itemString, record=row.record}
|
||||
end
|
||||
|
||||
local row = data
|
||||
resetButtons.buyout:Disable()
|
||||
resetButtons.cancel:Disable()
|
||||
justBought = {}
|
||||
|
||||
if row.record:IsPlayer() then
|
||||
resetButtons.summaryButton:Enable()
|
||||
resetButtons.cancel:Enable()
|
||||
resetButtons.cancel.auction = {record=row.record, itemString=row.itemString}
|
||||
else
|
||||
Reset:FindCurrentAuctionForBuyout(row.itemString, row.record.buyout, row.record.count)
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:RemoveCurrentAuction()
|
||||
Reset:UnregisterMessage("TSM_AH_EVENTS")
|
||||
if not currentItem then return end
|
||||
local scanData = TSM.Scan.auctionData[currentItem.itemString]
|
||||
if not scanData then return end
|
||||
local row = auctionST.rowData[auctionST:GetSelection()]
|
||||
if not row then return end
|
||||
|
||||
scanData:RemoveRecord(row.index)
|
||||
itemsReset[row.itemString] = true
|
||||
Reset:UpdateAuctionST()
|
||||
|
||||
if #auctionST.rowData == 0 then
|
||||
TSM.Scan.auctionData[row.itemString] = nil
|
||||
resetButtons.summaryButton:Enable()
|
||||
resetButtons.summaryButton:Click()
|
||||
Reset:UpdateSummaryST()
|
||||
else
|
||||
TSMAPI:CreateTimeDelay("resetBuyDelay", 0.2, function() Reset:SelectAuctionRow(auctionST.rowData[1]) end)
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:VerifyAuction(index, tab, record, itemString)
|
||||
local iString = TSMAPI:GetBaseItemString(GetAuctionItemLink(tab, index), true)
|
||||
local _, _, count, _, _, _, minBid, _, buyout, bid = GetAuctionItemInfo(tab, index)
|
||||
return (iString == itemString and bid == record.bid and minBid == record.minBid and buyout == record.buyout and count == record.count)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Reset:GetStatus()
|
||||
return 0, 0, 100
|
||||
end
|
||||
|
||||
function Reset:DoAction()
|
||||
|
||||
end
|
||||
|
||||
function Reset:SkipItem()
|
||||
|
||||
end
|
||||
|
||||
function Reset:Stop()
|
||||
isScanning = false
|
||||
end
|
||||
|
||||
function Reset:DoneScanning()
|
||||
local num, totalProfit = 0, 0
|
||||
local temp = {}
|
||||
|
||||
for _, data in ipairs(resetData) do
|
||||
if not temp[data.itemString] and Reset:ShouldShow(data) then
|
||||
temp[data.itemString] = true
|
||||
num = num + 1
|
||||
totalProfit = totalProfit + data.profit * data.quantity
|
||||
end
|
||||
end
|
||||
|
||||
resetButtons.stop:SetText(L["Restart"])
|
||||
resetButtons.stop.isDone = true
|
||||
isScanning = false
|
||||
doneScanningText = format(L["Done Scanning!\n\nCould potentially reset %d items for %s profit."], num, TSMAPI:FormatTextMoneyIcon(totalProfit))
|
||||
TSM.Manage:SetInfoText(doneScanningText)
|
||||
end
|
||||
|
||||
function Reset:SetupForAction()
|
||||
|
||||
end
|
||||
|
||||
function Reset:GetCurrentItem()
|
||||
|
||||
end
|
||||
|
||||
function Reset:IsScanning()
|
||||
return isScanning
|
||||
end
|
||||
|
||||
|
||||
local function ValidateAuction(index, listType)
|
||||
local itemString = TSMAPI:GetBaseItemString(GetAuctionItemLink(listType, index), true)
|
||||
local _, _, count, _, _, _, _, _, buyout = GetAuctionItemInfo(listType, index)
|
||||
return count == currentAuction.count and buyout == currentAuction.buyout and itemString == currentAuction.itemString
|
||||
end
|
||||
|
||||
function Reset:BuyAuction()
|
||||
local altIndex, mainIndex, foundAuction
|
||||
TSMAPI:CancelFrame("resetFindRepeat")
|
||||
Reset.isSearching = nil
|
||||
|
||||
for i=GetNumAuctionItems("list"), 1, -1 do
|
||||
if ValidateAuction(i, "list") then
|
||||
if not justBought[i] then
|
||||
mainIndex = i
|
||||
break
|
||||
else
|
||||
altIndex = altIndex or i
|
||||
end
|
||||
end
|
||||
end
|
||||
if mainIndex or altIndex then
|
||||
PlaceAuctionBid("list", mainIndex or altIndex, currentAuction.buyout)
|
||||
foundAuction = true
|
||||
justBought[mainIndex or altIndex] = true
|
||||
end
|
||||
|
||||
resetButtons.buyout:Disable()
|
||||
if foundAuction then
|
||||
-- wait for all the events that are triggered by this action
|
||||
Reset:RegisterMessage("TSM_AH_EVENTS", Reset.RemoveCurrentAuction)
|
||||
TSMAPI:WaitForAuctionEvents("Buyout")
|
||||
else
|
||||
TSM:Print(L["Auction not found. Skipped."])
|
||||
Reset:RemoveCurrentAuction()
|
||||
end
|
||||
end
|
||||
|
||||
function Reset:OnAuctionFound(index)
|
||||
if not Reset.isSearching then return end
|
||||
resetButtons.buyout:Enable()
|
||||
end
|
||||
|
||||
function Reset:FindCurrentAuctionForBuyout(itemString, buyout, count)
|
||||
currentAuction = {itemString=itemString, buyout=buyout, count=count}
|
||||
TSMAPI:CancelFrame("resetFindRepeat")
|
||||
TSMAPI.AuctionScan:FindAuction(function(...) Reset:OnAuctionFound(...) end, currentAuction)
|
||||
TSMAPI:CreateTimeDelay("resetFindRepeat", 0.1, function(...)
|
||||
local isFindScanning = TSMAPI.AuctionScan:IsFindScanning()
|
||||
if TSMAPI:AHTabIsVisible("Auctioning") then
|
||||
if not isFindScanning then
|
||||
TSMAPI.AuctionScan:FindAuction(function(...) Reset:OnAuctionFound(...) end, currentAuction)
|
||||
else
|
||||
if isFindScanning ~= currentAuction.itemString then
|
||||
TSMAPI.AuctionScan:FindAuction(function(...) Reset:OnAuctionFound(...) end, currentAuction)
|
||||
end
|
||||
end
|
||||
end
|
||||
end, 0.1)
|
||||
Reset.isSearching = true
|
||||
end
|
||||
@@ -0,0 +1,200 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Scan = TSM:NewModule("Scan", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
|
||||
Scan.auctionData = {}
|
||||
Scan.skipped = {}
|
||||
|
||||
|
||||
local function CallbackHandler(event, ...)
|
||||
if event == "QUERY_COMPLETE" then
|
||||
local filterList = ...
|
||||
local numItems = 0
|
||||
for _, v in ipairs(filterList) do
|
||||
numItems = numItems + #v.items
|
||||
end
|
||||
Scan.filterList = filterList
|
||||
Scan.numFilters = #filterList
|
||||
Scan:ScanNextFilter()
|
||||
elseif event == "QUERY_UPDATE" then
|
||||
local current, total, skipped = ...
|
||||
TSM.Manage:UpdateStatus("query", current, total)
|
||||
for _, itemString in ipairs(skipped) do
|
||||
TSM.Manage:ProcessScannedItem(itemString)
|
||||
tinsert(Scan.skipped, itemString)
|
||||
end
|
||||
elseif event == "SCAN_PAGE_UPDATE" then
|
||||
TSM.Manage:UpdateStatus("page", ...)
|
||||
elseif event == "SCAN_INTERRUPTED" then
|
||||
TSM.Manage:ScanComplete(true)
|
||||
elseif event == "SCAN_TIMEOUT" then
|
||||
tremove(Scan.filterList, 1)
|
||||
Scan:ScanNextFilter()
|
||||
elseif event == "SCAN_COMPLETE" then
|
||||
local data = ...
|
||||
for _, itemString in ipairs(Scan.filterList[1].items) do
|
||||
-- make sure we haven't already scanned this item (possible with common search terms)
|
||||
if not Scan.auctionData[itemString] then
|
||||
Scan:ProcessItem(itemString, data[itemString])
|
||||
TSM.Manage:ProcessScannedItem(itemString)
|
||||
end
|
||||
end
|
||||
tremove(Scan.filterList, 1)
|
||||
Scan:ScanNextFilter()
|
||||
end
|
||||
end
|
||||
|
||||
function Scan:StartItemScan(itemList)
|
||||
wipe(Scan.auctionData)
|
||||
wipe(Scan.skipped)
|
||||
TSMAPI:GenerateQueries(itemList, CallbackHandler)
|
||||
TSM.Manage:UpdateStatus("query", 0, -1)
|
||||
end
|
||||
|
||||
function Scan:ScanNextFilter()
|
||||
if #Scan.filterList == 0 then
|
||||
TSM.Manage:UpdateStatus("scan", Scan.numFilters, Scan.numFilters)
|
||||
return TSM.Manage:ScanComplete()
|
||||
end
|
||||
TSM.Manage:UpdateStatus("scan", Scan.numFilters-#Scan.filterList, Scan.numFilters)
|
||||
TSMAPI.AuctionScan:RunQuery(Scan.filterList[1], CallbackHandler, true)
|
||||
end
|
||||
|
||||
function Scan:ProcessItem(itemString, auctionItem)
|
||||
if not itemString or not auctionItem then return end
|
||||
auctionItem:SetRecordParams({"GetItemBuyout", "GetItemDisplayedBid", "seller", "count"})
|
||||
auctionItem:PopulateCompactRecords()
|
||||
auctionItem:SetAlts(TSM.db.factionrealm.player)
|
||||
if #auctionItem.records > 0 then
|
||||
auctionItem:SetMarketValue(TSMAPI:GetItemValue(itemString, "DBMarket"))
|
||||
Scan.auctionData[itemString] = auctionItem
|
||||
end
|
||||
end
|
||||
|
||||
function Scan:ShouldIgnoreAuction(record, operation)
|
||||
if type(operation) ~= "table" then return end
|
||||
if record.timeLeft <= operation.ignoreLowDuration then
|
||||
-- ignoring low duration
|
||||
return true
|
||||
elseif operation.matchStackSize and record.count ~= operation.stackSize then
|
||||
-- matching stack size
|
||||
return true
|
||||
else
|
||||
local minPrice = TSM.Util:GetItemPrices(operation, record.parent:GetItemString()).minPrice
|
||||
if operation.priceReset == "ignore" and minPrice and record:GetItemBuyout() and record:GetItemBuyout() <= minPrice then
|
||||
-- ignoring auctions below threshold
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This gets how many auctions are posted specifically on this tier, it does not get how many of the items they up at this tier
|
||||
-- but purely the number of auctions
|
||||
function Scan:GetPlayerAuctionCount(itemString, findBuyout, findBid, findQuantity, operation)
|
||||
findBuyout = floor(findBuyout)
|
||||
findBid = floor(findBid)
|
||||
|
||||
local quantity = 0
|
||||
for _, record in ipairs(Scan.auctionData[itemString].compactRecords) do
|
||||
if not Scan:ShouldIgnoreAuction(record, operation) and record:IsPlayer() then
|
||||
if record:GetItemBuyout() == findBuyout and record:GetItemDisplayedBid() == findBid and record.count == findQuantity then
|
||||
quantity = quantity + record.numAuctions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return quantity
|
||||
end
|
||||
|
||||
-- gets the buyout / bid of the second lowest auction for this item
|
||||
function Scan:GetSecondLowest(itemString, lowestBuyout, operation)
|
||||
local auctionItem = Scan.auctionData[itemString]
|
||||
if not auctionItem then return end
|
||||
|
||||
local buyout, bid
|
||||
for _, record in ipairs(auctionItem.compactRecords) do
|
||||
if not Scan:ShouldIgnoreAuction(record, operation) then
|
||||
local recordBuyout = record:GetItemBuyout()
|
||||
if recordBuyout and (not buyout or recordBuyout < buyout) and recordBuyout > lowestBuyout then
|
||||
buyout, bid = recordBuyout, record:GetItemDisplayedBid()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return buyout, bid
|
||||
end
|
||||
|
||||
-- Find out the lowest price for this item
|
||||
function Scan:GetLowestAuction(auctionItem, operation)
|
||||
if type(auctionItem) == "string" or type(auctionItem) == "number" then -- it's an itemString
|
||||
auctionItem = Scan.auctionData[auctionItem]
|
||||
end
|
||||
if not auctionItem then return end
|
||||
|
||||
-- Find lowest
|
||||
local buyout, bid, owner, invalidSellerEntry
|
||||
for _, record in ipairs(auctionItem.compactRecords) do
|
||||
if not Scan:ShouldIgnoreAuction(record, operation) then
|
||||
local recordBuyout = record:GetItemBuyout()
|
||||
if recordBuyout then
|
||||
local recordBid = record:GetItemDisplayedBid()
|
||||
if not buyout or recordBuyout < buyout or (recordBuyout == buyout and recordBid < bid) then
|
||||
buyout, bid, owner = recordBuyout, recordBid, record.seller
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if owner == "?" and next(TSM.db.factionrealm.whitelist) then
|
||||
invalidSellerEntry = true
|
||||
end
|
||||
|
||||
-- Now that we know the lowest, find out if this price "level" is a friendly person
|
||||
-- the reason we do it like this, is so if Apple posts an item at 50g, Orange posts one at 50g
|
||||
-- but you only have Apple on your white list, it'll undercut it because Orange posted it as well
|
||||
local isWhitelist, isPlayer = true, true
|
||||
for _, record in ipairs(auctionItem.compactRecords) do
|
||||
if not Scan:ShouldIgnoreAuction(record, operation) then
|
||||
local recordBuyout = record:GetItemBuyout()
|
||||
if not record:IsPlayer() and recordBuyout and recordBuyout == buyout then
|
||||
isPlayer = nil
|
||||
if not TSM.db.factionrealm.whitelist[strlower(record.seller)] then
|
||||
isWhitelist = nil
|
||||
end
|
||||
|
||||
-- If the lowest we found was from the player, but someone else is matching it (and they aren't on our white list)
|
||||
-- then we swap the owner to that person
|
||||
buyout, bid, owner = recordBuyout, record:GetItemDisplayedBid(), record.seller
|
||||
end
|
||||
end
|
||||
end
|
||||
if owner == "?" and next(TSM.db.factionrealm.whitelist) then
|
||||
invalidSellerEntry = true
|
||||
end
|
||||
|
||||
return buyout, bid, owner, isWhitelist, isPlayer, invalidSellerEntry
|
||||
end
|
||||
|
||||
function Scan:GetPlayerLowestBuyout(auctionItem, operation)
|
||||
if not auctionItem then return end
|
||||
|
||||
-- Find lowest
|
||||
local buyout
|
||||
for _, record in ipairs(auctionItem.compactRecords) do
|
||||
if not Scan:ShouldIgnoreAuction(record, operation) then
|
||||
local recordBuyout = record:GetItemBuyout()
|
||||
if record:IsPlayer() and recordBuyout and (not buyout or recordBuyout < buyout) then
|
||||
buyout = recordBuyout
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return buyout
|
||||
end
|
||||
@@ -0,0 +1,332 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Util = TSM:NewModule("Util")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
|
||||
local currentBank = nil
|
||||
local bFrame = nil
|
||||
local buttonFrame = nil
|
||||
local groupTree = nil
|
||||
|
||||
function Util:OnEnable()
|
||||
TSM:RegisterEvent("GUILDBANKFRAME_OPENED", function(event)
|
||||
currentBank = "guildbank"
|
||||
end)
|
||||
|
||||
TSM:RegisterEvent("BANKFRAME_OPENED", function(event)
|
||||
currentBank = "bank"
|
||||
end)
|
||||
|
||||
TSM:RegisterEvent("GUILDBANKFRAME_CLOSED", function(event, addon)
|
||||
currentBank = nil
|
||||
end)
|
||||
|
||||
TSM:RegisterEvent("BANKFRAME_CLOSED", function(event)
|
||||
currentBank = nil
|
||||
end)
|
||||
end
|
||||
|
||||
local function GetItemPrice(operationPrice, itemString)
|
||||
local func = TSMAPI:ParseCustomPrice(operationPrice)
|
||||
local price = func and func(itemString)
|
||||
return price ~= 0 and price or nil
|
||||
end
|
||||
|
||||
function Util:GetItemPrices(operation, itemString, isResetScan)
|
||||
local prices = {}
|
||||
|
||||
prices.cost = GetItemPrice("crafting", itemString)
|
||||
|
||||
prices.undercut = GetItemPrice(operation.undercut, itemString)
|
||||
prices.minPrice = GetItemPrice(operation.minPrice, itemString)
|
||||
prices.maxPrice = GetItemPrice(operation.maxPrice, itemString)
|
||||
prices.normalPrice = GetItemPrice(operation.normalPrice, itemString)
|
||||
prices.cancelRepostThreshold = GetItemPrice(operation.cancelRepostThreshold, itemString)
|
||||
if isResetScan then
|
||||
prices.resetMaxCost = GetItemPrice(operation.resetMaxCost, itemString)
|
||||
prices.resetMinProfit = GetItemPrice(operation.resetMinProfit, itemString)
|
||||
prices.resetResolution = GetItemPrice(operation.resetResolution, itemString)
|
||||
prices.resetMaxItemCost = GetItemPrice(operation.resetMaxItemCost, itemString)
|
||||
end
|
||||
if TSM.db.global.roundNormalPrice and prices.normalPrice then
|
||||
prices.normalPrice = ceil(prices.normalPrice / COPPER_PER_GOLD) * COPPER_PER_GOLD
|
||||
end
|
||||
prices.resetPrice = operation.priceReset ~= "none" and operation.priceReset ~= "ignore" and prices[operation.priceReset]
|
||||
prices.aboveMax = operation.aboveMax ~= "none" and prices[operation.aboveMax]
|
||||
return prices
|
||||
end
|
||||
|
||||
local function createButton(text, parent, func)
|
||||
local btn = TSMAPI.GUI:CreateButton(bFrame, 15, "Button")
|
||||
btn:SetText(text)
|
||||
btn:SetHeight(17)
|
||||
btn:SetWidth(230)
|
||||
return btn
|
||||
end
|
||||
|
||||
function Util:createTab(parent)
|
||||
|
||||
bFrame = CreateFrame("Frame", nil, parent)
|
||||
--TSMAPI.Design:SetFrameColor(bFrame)
|
||||
bFrame:Hide()
|
||||
|
||||
--size--
|
||||
bFrame:SetAllPoints()
|
||||
|
||||
--GroupTree--
|
||||
local tFrame = CreateFrame("Frame", nil, bFrame)
|
||||
tFrame:SetPoint("TOPLEFT", 0, -5)
|
||||
tFrame:SetPoint("TOPRIGHT", 0, -5)
|
||||
tFrame:SetPoint("BOTTOMLEFT", 0, 120)
|
||||
tFrame:SetPoint("BOTTOMRIGHT", 0, 120)
|
||||
|
||||
groupTree = TSMAPI:CreateGroupTree(tFrame, "Auctioning", "Auctioning_Bank")
|
||||
groupTree:SetPoint("TOPLEFT", 5, -5)
|
||||
groupTree:SetPoint("BOTTOMRIGHT", -5, 5)
|
||||
|
||||
--Buttons--
|
||||
buttonFrame = CreateFrame("Frame", nil, bFrame)
|
||||
buttonFrame:SetPoint("TOPLEFT", 0, -330)
|
||||
buttonFrame:SetPoint("TOPRIGHT", 0, -330)
|
||||
buttonFrame:SetPoint("BOTTOMLEFT")
|
||||
buttonFrame:SetPoint("BOTTOMRIGHT")
|
||||
|
||||
buttonFrame.btnToBank = createButton(L["Move Group To Bank"], buttonFrame, nil)
|
||||
buttonFrame.btnToBank:SetPoint("BOTTOM", buttonFrame, "BOTTOM", 0, 95)
|
||||
|
||||
buttonFrame.btnNonGroup = createButton(L["Move Non Group Items to Bank"], buttonFrame, nil)
|
||||
buttonFrame.btnNonGroup:SetPoint("BOTTOM", buttonFrame, "BOTTOM", 0, 75)
|
||||
|
||||
buttonFrame.btnToBags = createButton(L["Move Post Cap To Bags"], buttonFrame, nil)
|
||||
buttonFrame.btnToBags:SetPoint("BOTTOM", buttonFrame, "BOTTOM", 0, 45)
|
||||
|
||||
buttonFrame.btnAHToBags = createButton(L["Move AH Shortfall To Bags"], buttonFrame, nil)
|
||||
buttonFrame.btnAHToBags:SetPoint("BOTTOM", buttonFrame, "BOTTOM", 0, 25)
|
||||
|
||||
buttonFrame.btnAllToBags = createButton(L["Move Group To Bags"], buttonFrame, nil)
|
||||
buttonFrame.btnAllToBags:SetPoint("BOTTOM", buttonFrame, "BOTTOM", 0, 5)
|
||||
|
||||
Util:updateButtons()
|
||||
|
||||
return bFrame
|
||||
end
|
||||
|
||||
function Util:updateButtons()
|
||||
------------------
|
||||
-- Move to Bank --
|
||||
------------------
|
||||
buttonFrame.btnToBank:SetScript("OnClick", function(self)
|
||||
Util:groupTree(groupTree:GetSelectedGroupInfo(), "bags")
|
||||
end)
|
||||
|
||||
-----------------------------------
|
||||
-- Move Non Group Items to Bank --
|
||||
-----------------------------------
|
||||
buttonFrame.btnNonGroup:SetScript("OnClick", function(self)
|
||||
Util:nonGroupTree(groupTree:GetSelectedGroupInfo(), "bags")
|
||||
end)
|
||||
|
||||
----------------------------
|
||||
-- Move Post Cap to Bags --
|
||||
----------------------------
|
||||
buttonFrame.btnToBags:SetScript("OnClick", function(self)
|
||||
Util:groupTree(groupTree:GetSelectedGroupInfo(), currentBank)
|
||||
end)
|
||||
|
||||
--------------------------------
|
||||
-- Move AH Shortfall to Bags --
|
||||
--------------------------------
|
||||
buttonFrame.btnAHToBags:SetScript("OnClick", function(self)
|
||||
Util:groupTree(groupTree:GetSelectedGroupInfo(), currentBank, false, true)
|
||||
end)
|
||||
|
||||
|
||||
----------------------------
|
||||
-- Move All to Bags --
|
||||
----------------------------
|
||||
buttonFrame.btnAllToBags:SetScript("OnClick", function(self)
|
||||
Util:groupTree(groupTree:GetSelectedGroupInfo(), currentBank, true)
|
||||
end)
|
||||
end
|
||||
|
||||
function Util:groupTree(grpInfo, src, all, ah)
|
||||
local next = next
|
||||
local newgrp = {}
|
||||
local totalItems = Util:getTotalItems(src)
|
||||
local bagItems = Util:getTotalItems("bags") or {}
|
||||
for groupName, data in pairs(grpInfo) do
|
||||
groupName = TSMAPI:FormatGroupPath(groupName, true)
|
||||
for _, opName in ipairs(data.operations) do
|
||||
TSMAPI:UpdateOperation("Auctioning", opName)
|
||||
local opSettings = TSM.operations[opName]
|
||||
|
||||
if not opSettings then
|
||||
-- operation doesn't exist anymore in Auctioning
|
||||
TSM:Printf(L["'%s' has an Auctioning operation of '%s' which no longer exists."], groupName, opName)
|
||||
else
|
||||
--it's a valid operation
|
||||
for itemString in pairs(data.items) do
|
||||
local totalq = 0
|
||||
local usedq = 0
|
||||
local maxPost = opSettings.stackSize * opSettings.postCap
|
||||
|
||||
if totalItems then
|
||||
totalq = totalItems[itemString] or 0
|
||||
end
|
||||
|
||||
if src == "bags" then -- move them all back to bank/gbank
|
||||
if totalq > 0 then
|
||||
newgrp[itemString] = totalq * -1
|
||||
totalItems[itemString] = nil -- remove the current bag count in case we loop round for another operation
|
||||
end
|
||||
else -- move from bank/gbank to bags
|
||||
if totalq > 0 then
|
||||
if all then
|
||||
newgrp[itemString] = totalq
|
||||
totalq = 0
|
||||
else
|
||||
local quantity = maxPost - (bagItems[itemString] or 0)
|
||||
newgrp[itemString] = (newgrp[itemString] or 0) + quantity
|
||||
totalq = totalq - quantity -- remove this operations qty to move from source quantity in case we loop again for another operation
|
||||
if bagItems[itemString] then --remove this operations maxPost quantity from the bag total in case we loop again for another operation
|
||||
bagItems[itemString] = bagItems[itemString] - maxPost
|
||||
if bagItems[itemString] <= 0 then
|
||||
bagItems[itemString] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if src ~= "bags" and ah then -- remove ah/mail quantities from the total to move
|
||||
local playermail = TSMAPI:ModuleAPI("ItemTracker", "playermail")
|
||||
local playerauctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions")
|
||||
for itemString in pairs(newgrp) do
|
||||
if playerauctions then
|
||||
newgrp[itemString] = newgrp[itemString] - (playerauctions[itemString] or 0)
|
||||
end
|
||||
if playermail then
|
||||
newgrp[itemString] = newgrp[itemString] - (playermail[itemString] or 0)
|
||||
end
|
||||
if newgrp[itemString] < 0 then
|
||||
newgrp[itemString] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(newgrp) == nil then
|
||||
TSM:Print(L["Nothing to Move"])
|
||||
else
|
||||
TSM:Print(L["Preparing to Move"])
|
||||
TSMAPI:MoveItems(newgrp, TSM.PrintMsg)
|
||||
end
|
||||
end
|
||||
|
||||
function Util:nonGroupTree(grpInfo, src)
|
||||
local next = next
|
||||
local newgrp = {}
|
||||
local bagItems = Util:getTotalItems("bags")
|
||||
for groupName, data in pairs(grpInfo) do
|
||||
groupName = TSMAPI:FormatGroupPath(groupName, true)
|
||||
for _, opName in ipairs(data.operations) do
|
||||
TSMAPI:UpdateOperation("Auctioning", opName)
|
||||
local opSettings = TSM.operations[opName]
|
||||
|
||||
if not opSettings then
|
||||
-- operation doesn't exist anymore in Auctioning
|
||||
TSM:Printf(L["'%s' has an Auctioning operation of '%s' which no longer exists."], groupName, opName)
|
||||
else
|
||||
-- it's a valid operation so remove all the items from bagItems so we are left with non group items to move
|
||||
for itemString in pairs(data.items) do
|
||||
if bagItems then
|
||||
if bagItems[itemString] then
|
||||
bagItems[itemString] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
for itemString, quantity in pairs(bagItems) do
|
||||
quantity = quantity * -1
|
||||
if newgrp[itemString] then
|
||||
newgrp[itemString] = newgrp[itemString] + quantity
|
||||
else
|
||||
newgrp[itemString] = quantity
|
||||
end
|
||||
end
|
||||
|
||||
if next(newgrp) == nil then
|
||||
TSM:Print(L["Nothing to Move"])
|
||||
else
|
||||
TSM:Print(L["Preparing to Move"])
|
||||
TSMAPI:MoveItems(newgrp, TSM.PrintMsg)
|
||||
end
|
||||
end
|
||||
|
||||
function TSM.PrintMsg(message)
|
||||
TSM:Print(message)
|
||||
end
|
||||
|
||||
function Util:getTotalItems(src)
|
||||
local results = {}
|
||||
if src == "bank" then
|
||||
local function ScanBankBag(bag)
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
if not TSMAPI:IsSoulbound(bag, slot) then
|
||||
local itemString = TSMAPI:GetBaseItemString(GetContainerItemLink(bag, slot), true)
|
||||
if itemString then
|
||||
local quantity = select(2, GetContainerItemInfo(bag, slot))
|
||||
if not results[itemString] then results[itemString] = 0 end
|
||||
results[itemString] = results[itemString] + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for bag = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
|
||||
ScanBankBag(bag)
|
||||
end
|
||||
ScanBankBag(-1)
|
||||
|
||||
return results
|
||||
elseif src == "guildbank" then
|
||||
for bag = 1, GetNumGuildBankTabs() do
|
||||
for slot = 1, MAX_GUILDBANK_SLOTS_PER_TAB or 98 do
|
||||
local link = GetGuildBankItemLink(bag, slot)
|
||||
local itemString = TSMAPI:GetBaseItemString(link, true)
|
||||
if itemString then
|
||||
local quantity = select(2, GetGuildBankItemInfo(bag, slot))
|
||||
if not results[itemString] then results[itemString] = 0 end
|
||||
results[itemString] = results[itemString] + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return results
|
||||
elseif src == "bags" then
|
||||
for bag, slot, itemString, quantity, locked in TSMAPI:GetBagIterator(true) do
|
||||
if currentBank == "guildbank" then
|
||||
if not TSMAPI:IsSoulbound(bag, slot) then
|
||||
results[itemString] = (results[itemString] or 0) + quantity
|
||||
end
|
||||
else
|
||||
results[itemString] = (results[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
@@ -0,0 +1,179 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Auctioning --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
-- This file is to contain things that are common between different scan types.
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Manage = TSM:NewModule("Manage", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
|
||||
|
||||
local scanStatus = {}
|
||||
local GUI, Util, mode
|
||||
|
||||
function Manage:StartScan(GUIRef, options)
|
||||
GUI = GUIRef
|
||||
mode = GUI.mode
|
||||
Util = TSM[mode]
|
||||
GUI.OnAction = Manage.OnGUIEvent
|
||||
wipe(scanStatus)
|
||||
TSM.Log:Clear()
|
||||
|
||||
local scanList = Util:GetScanListAndSetup(GUI, options)
|
||||
GUI:UpdateSTData()
|
||||
if #scanList == 0 then
|
||||
GUI:Stopped()
|
||||
return
|
||||
end
|
||||
|
||||
if options and options.noScan then -- no scanning required
|
||||
Manage:StartNoScanScan(GUIRef, scanList)
|
||||
return
|
||||
end
|
||||
|
||||
GUI.statusBar:SetStatusText(L["Starting Scan..."])
|
||||
GUI.statusBar:UpdateStatus(0, 0)
|
||||
GUI.infoText:SetInfo(L["Running Scan..."])
|
||||
TSM.Scan:StartItemScan(scanList)
|
||||
end
|
||||
|
||||
function Manage:StartNoScanScan(GUIRef, scanList)
|
||||
GUI.infoText:SetInfo(L["Processing Items..."])
|
||||
GUI.statusBar:UpdateStatus(0, 0)
|
||||
TSMAPI:CancelFrame("auctioningNoScanProcessing")
|
||||
scanStatus.query = {1, 1}
|
||||
|
||||
local totalToScan = #scanList
|
||||
local function ProcessNoScanItems()
|
||||
local numLeft = #scanList
|
||||
for i=1, min(numLeft, 10) do
|
||||
Manage:ProcessScannedItem(tremove(scanList, 1), (i ~= min(numLeft, 10) and i ~= 1))
|
||||
Manage:UpdateStatus("scan", totalToScan-#scanList, totalToScan)
|
||||
end
|
||||
|
||||
if #scanList == 0 then
|
||||
TSMAPI:CancelFrame("auctioningNoScanProcessing")
|
||||
Manage:ScanComplete()
|
||||
end
|
||||
end
|
||||
TSMAPI:CreateTimeDelay("auctioningNoScanProcessing", 0, ProcessNoScanItems, 0.1)
|
||||
end
|
||||
|
||||
function Manage:OnGUIEvent(event)
|
||||
if event == "action" then
|
||||
Util:DoAction()
|
||||
elseif event == "skip" then
|
||||
Util:SkipItem()
|
||||
elseif event == "stop" then
|
||||
TSMAPI:CancelFrame("auctioningNoScanProcessing")
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
Util:Stop()
|
||||
end
|
||||
TSMAPI:CreateTimeDelay("aucManageSTUpdate", 0.01, GUI.UpdateAuctionsSTData)
|
||||
end
|
||||
|
||||
function Manage:ProcessScannedItem(itemString, noUpdate)
|
||||
Util:ProcessItem(itemString)
|
||||
if not noUpdate then
|
||||
GUI:UpdateSTData()
|
||||
end
|
||||
end
|
||||
|
||||
function Manage:ScanComplete(interrupted)
|
||||
if interrupted then
|
||||
Util:Stop(true)
|
||||
else
|
||||
local numToManage = Util:DoneScanning()
|
||||
TSMAPI:FireEvent("AUCTIONING:SCANDONE", {num=numToManage})
|
||||
if numToManage == 0 then
|
||||
Util:Stop()
|
||||
elseif TSM.db.global.scanCompleteSound ~= 1 then
|
||||
PlaySound(TSM.Options:GetScanCompleteSound(TSM.db.global.scanCompleteSound), "Master")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- these functions help display the status text which goes inside the statusbar
|
||||
local function IsStepStarted(step)
|
||||
return scanStatus[step] and scanStatus[step][1] and scanStatus[step][2]
|
||||
end
|
||||
local function IsStepDone(step)
|
||||
return IsStepStarted(step) and scanStatus[step][1] == scanStatus[step][2]
|
||||
end
|
||||
-- update the statusbar
|
||||
function Manage:UpdateStatus(statusType, current, total)
|
||||
scanStatus[statusType] = {current, total}
|
||||
if statusType == "query" then
|
||||
if total >= 0 then
|
||||
GUI.statusBar:SetStatusText(format(L["Preparing Filter %d / %d"], current, total))
|
||||
else
|
||||
GUI.statusBar:SetStatusText(format(L["Preparing Filters..."], current, total))
|
||||
end
|
||||
elseif IsStepDone("scan") and IsStepDone("manage") and IsStepDone("confirm") then -- scan complete
|
||||
GUI.statusBar:SetStatusText(L["Scan Complete!"])
|
||||
else
|
||||
local parts = {}
|
||||
if IsStepDone("scan") then
|
||||
tinsert(parts, L["Done Scanning"])
|
||||
elseif IsStepStarted("scan") then
|
||||
if IsStepStarted("page") then
|
||||
tinsert(parts, format(L["Scanning %d / %d (Page %d / %d)"], scanStatus.scan[1], scanStatus.scan[2], scanStatus.page[1], scanStatus.page[2]))
|
||||
else
|
||||
tinsert(parts, format(L["Scanning %d / %d"], scanStatus.scan[1], scanStatus.scan[2]))
|
||||
end
|
||||
end
|
||||
if IsStepDone("manage") then
|
||||
if mode == "Post" then
|
||||
tinsert(parts, L["Done Posting"])
|
||||
elseif mode == "Cancel" then
|
||||
tinsert(parts, L["Done Canceling"])
|
||||
end
|
||||
if IsStepStarted("confirm") then
|
||||
tinsert(parts, format(L["Confirming %d / %d"], scanStatus.confirm[1]+1, scanStatus.confirm[2]))
|
||||
else
|
||||
tinsert(parts, format(L["Confirming %d / %d"], 1, scanStatus.manage[2]))
|
||||
end
|
||||
elseif IsStepDone("scan") and IsStepStarted("manage") then
|
||||
if mode == "Post" then
|
||||
tinsert(parts, format(L["Posting %d / %d"], scanStatus.manage[1]+1, scanStatus.manage[2]))
|
||||
elseif mode == "Cancel" then
|
||||
tinsert(parts, format(L["Canceling %d / %d"], scanStatus.manage[1]+1, scanStatus.manage[2]))
|
||||
end
|
||||
if IsStepStarted("confirm") then
|
||||
tinsert(parts, format(L["Confirming %d / %d"], scanStatus.confirm[1]+1, scanStatus.confirm[2]))
|
||||
else
|
||||
tinsert(parts, format(L["Confirming %d / %d"], 1, scanStatus.manage[2]))
|
||||
end
|
||||
end
|
||||
GUI.statusBar:SetStatusText(table.concat(parts, " - "))
|
||||
end
|
||||
|
||||
if IsStepDone("query") then
|
||||
local scanCurrent = scanStatus.scan and scanStatus.scan[1] or 0
|
||||
local scanTotal = scanStatus.scan and scanStatus.scan[2] or 1
|
||||
local confirmCurrent = scanStatus.confirm and scanStatus.confirm[1] or 0
|
||||
local confirmTotal = scanStatus.confirm and scanStatus.confirm[2] or 1
|
||||
GUI.statusBar:UpdateStatus(100*confirmCurrent/confirmTotal, 100*scanCurrent/scanTotal)
|
||||
end
|
||||
end
|
||||
|
||||
function Manage:SetCurrentItem(currentItem)
|
||||
if currentItem and currentItem.itemString then
|
||||
GUI.infoText:SetInfo(currentItem)
|
||||
end
|
||||
end
|
||||
|
||||
function Manage:GetCurrentItem()
|
||||
return GUI.infoText:GetInfo()
|
||||
end
|
||||
|
||||
function Manage:SetInfoText(text)
|
||||
if type(text) ~= "table" then
|
||||
GUI:UpdateLogSTHighlight()
|
||||
end
|
||||
GUI.infoText:SetInfo(text)
|
||||
end
|
||||
Reference in New Issue
Block a user