This commit is contained in:
Andrew6810
2022-11-05 21:19:42 -07:00
parent b79f4bd588
commit f3e579cb57
386 changed files with 93729 additions and 2 deletions
@@ -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
+957
View File
@@ -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