init
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
local TSM = select(2, ...)
|
||||
local Destroying = TSM:NewModule("Destroying")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Shopping") -- loads the localization table
|
||||
|
||||
local private = {sources={}}
|
||||
|
||||
|
||||
function Destroying:OnEnable()
|
||||
TSMAPI:CreateTimeDelay("shoppingDestroyingUpdateTargets", 0, private.UpdateTargetItems, 60) --1)
|
||||
TSM.db.global.destroyingTargetItems = TSM.db.global.destroyingTargetItems or {}
|
||||
end
|
||||
|
||||
function private:UpdateTargetItems()
|
||||
local update
|
||||
for itemString in pairs(TSMAPI.InkConversions) do
|
||||
private.sources[itemString] = "mill"
|
||||
if not TSM.db.global.destroyingTargetItems[itemString] then
|
||||
update = true
|
||||
local name = TSMAPI:GetSafeItemInfo(itemString)
|
||||
if name then
|
||||
TSM.db.global.destroyingTargetItems[itemString] = name
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, itemString in ipairs(TSMAPI:GetConversionTargetItems("mill")) do
|
||||
private.sources[itemString] = "mill"
|
||||
if not TSM.db.global.destroyingTargetItems[itemString] then
|
||||
update = true
|
||||
local name = TSMAPI:GetSafeItemInfo(itemString)
|
||||
if name then
|
||||
TSM.db.global.destroyingTargetItems[itemString] = name
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, itemString in ipairs(TSMAPI:GetConversionTargetItems("prospect")) do
|
||||
private.sources[itemString] = "prospect"
|
||||
if not TSM.db.global.destroyingTargetItems[itemString] then
|
||||
update = true
|
||||
local name = TSMAPI:GetSafeItemInfo(itemString)
|
||||
if name then
|
||||
TSM.db.global.destroyingTargetItems[itemString] = name
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, itemString in ipairs(TSMAPI:GetEnchantingTargetItems()) do
|
||||
private.sources[itemString] = "disenchant"
|
||||
if not TSM.db.global.destroyingTargetItems[itemString] then
|
||||
update = true
|
||||
local name = TSMAPI:GetSafeItemInfo(itemString)
|
||||
if name then
|
||||
TSM.db.global.destroyingTargetItems[itemString] = name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not update then
|
||||
TSMAPI:CancelFrame("shoppingDestroyingUpdateTargets")
|
||||
end
|
||||
end
|
||||
|
||||
function Destroying:StartDestroyingSearch(target, filter, isCrafting)
|
||||
if not private.sources[target] then return TSM:Printf(L["Invalid destroy target: '%s'"], target) end
|
||||
|
||||
TSM.isCrafting = isCrafting
|
||||
Destroying.maxQuantity = filter.maxQuantity
|
||||
filter.maxPrice = nil
|
||||
if private.sources[target] == "mill" then
|
||||
private:TryStarting(private.StartMillingSearch, target, filter)
|
||||
elseif private.sources[target] == "prospect" then
|
||||
private:TryStarting(private.StartProspectingSearch, target, filter)
|
||||
elseif private.sources[target] == "disenchant" then
|
||||
private:TryStarting(private.StartDisenchantingSearch, target, filter)
|
||||
end
|
||||
TSMAPI:FireEvent("SHOPPING:SEARCH:STARTDESTROYSCAN", {target=target, filter=filter})
|
||||
end
|
||||
|
||||
function private:TryStarting(func, target, filter, attempt)
|
||||
attempt = attempt or 0
|
||||
if attempt <= 10 and not func(target, filter, attempt == 10) then
|
||||
TSMAPI:CreateTimeDelay("destroySearchTryStart", 0.1, function() private:TryStarting(func, target, filter, attempt+1) end)
|
||||
end
|
||||
end
|
||||
|
||||
function private:AddItemQuery(itemList, filter, itemString)
|
||||
local name = TSMAPI:GetSafeItemInfo(itemString)
|
||||
if name then
|
||||
local query = CopyTable(filter)
|
||||
query.name = name
|
||||
tinsert(itemList, query)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function private.StartMillingSearch(target, filter, lastAttempt)
|
||||
local matItemString = target
|
||||
local inkItemString, pigmentItemString
|
||||
if TSMAPI.InkConversions[target] then
|
||||
inkItemString = target
|
||||
pigmentItemString = TSMAPI.InkConversions[target].pigment
|
||||
else
|
||||
for itemString, data in pairs(TSMAPI.InkConversions) do
|
||||
if target == data.pigment then
|
||||
inkItemString = itemString
|
||||
pigmentItemString = target
|
||||
break
|
||||
end
|
||||
end
|
||||
if not inkItemString then return TSM:Printf(L["Unknown milling search target: '%s'"], target) end
|
||||
end
|
||||
|
||||
private.evenFilter = {}
|
||||
private.conversions = {}
|
||||
private.conversions[inkItemString] = 1
|
||||
private.conversions[pigmentItemString] = 1 / TSMAPI.InkConversions[inkItemString].pigmentPerInk
|
||||
local itemList = {}
|
||||
|
||||
-- add ink and pigment
|
||||
if not private:AddItemQuery(itemList, filter, inkItemString) and not lastAttempt then return end
|
||||
if not private:AddItemQuery(itemList, filter, pigmentItemString) and not lastAttempt then return end
|
||||
|
||||
-- add primary herbs
|
||||
for itemString, data in pairs(TSMAPI:GetItemConversions(pigmentItemString)) do
|
||||
if not private:AddItemQuery(itemList, filter, itemString) and not lastAttempt then return end
|
||||
private.evenFilter[itemString] = filter.evenOnly
|
||||
private.conversions[itemString] = data.rate / TSMAPI.InkConversions[inkItemString].pigmentPerInk
|
||||
end
|
||||
|
||||
-- deal with vendor trades
|
||||
local otherInks = TSMAPI.Conversions[inkItemString]
|
||||
for otherInk, otherInkData in pairs(otherInks or {}) do
|
||||
if not TSMAPI.Conversions[otherInk] and otherInkData.source == "vendortrade" and TSMAPI.InkConversions[otherInk] then
|
||||
local vendorTradeRate = otherInkData.rate
|
||||
for itemString, millData in pairs(TSMAPI:GetItemConversions(TSMAPI.InkConversions[otherInk].pigment)) do
|
||||
if not private:AddItemQuery(itemList, filter, itemString) and not lastAttempt then return end
|
||||
private.evenFilter[itemString] = filter.evenOnly
|
||||
private.conversions[itemString] = vendorTradeRate * millData.rate / TSMAPI.InkConversions[inkItemString].pigmentPerInk
|
||||
end
|
||||
if not private:AddItemQuery(itemList, filter, otherInk) and not lastAttempt then return end
|
||||
if not private:AddItemQuery(itemList, filter, TSMAPI.InkConversions[otherInk].pigment) and not lastAttempt then return end
|
||||
private.conversions[otherInk] = vendorTradeRate
|
||||
private.conversions[TSMAPI.InkConversions[otherInk].pigment] = vendorTradeRate / TSMAPI.InkConversions[otherInk].pigmentPerInk
|
||||
end
|
||||
end
|
||||
|
||||
private.mode = "mill"
|
||||
private.target = inkItemString
|
||||
if TSM.isCrafting then
|
||||
local func = TSMAPI:ParseCustomPrice("matprice")
|
||||
local price = func and func(matItemString) or nil
|
||||
private.targetMarketValue = price
|
||||
TSM.Util:ShowSearchFrame(true, L["% Mat Price"])
|
||||
else
|
||||
private.targetMarketValue = TSM:GetMaxPrice(TSM.db.global.marketValueSource, inkItemString)
|
||||
TSM.Util:ShowSearchFrame(true, L["% Target Value"])
|
||||
end
|
||||
TSM.Search:SetSearchBarDisabled(true)
|
||||
TSM.Util:StartFilterScan(itemList, private.ScanCallback)
|
||||
return true
|
||||
end
|
||||
|
||||
function private.StartProspectingSearch(target, filter, lastAttempt)
|
||||
local itemList = {}
|
||||
private.evenFilter = {}
|
||||
if not private:AddItemQuery(itemList, filter, target) and not lastAttempt then return end
|
||||
for itemString in pairs(TSMAPI:GetItemConversions(target)) do
|
||||
if not private:AddItemQuery(itemList, filter, itemString) and not lastAttempt then return end
|
||||
private.evenFilter[itemString] = filter.evenOnly
|
||||
end
|
||||
|
||||
private.mode = "prospect"
|
||||
private.target = target
|
||||
if TSM.isCrafting then
|
||||
local func = TSMAPI:ParseCustomPrice("matprice")
|
||||
local price = func and func(target) or nil
|
||||
private.targetMarketValue = price
|
||||
TSM.Util:ShowSearchFrame(true, L["% Max Price"])
|
||||
else
|
||||
private.targetMarketValue = TSM:GetMaxPrice(TSM.db.global.marketValueSource, target)
|
||||
TSM.Util:ShowSearchFrame(true, L["% Target Value"])
|
||||
end
|
||||
TSM.Search:SetSearchBarDisabled(true)
|
||||
TSM.Util:StartFilterScan(itemList, private.ScanCallback)
|
||||
return true
|
||||
end
|
||||
|
||||
function private.StartDisenchantingSearch(target, filter, lastAttempt)
|
||||
local disenchantData = TSMAPI:GetDisenchantData(target)
|
||||
if not disenchantData then return end
|
||||
|
||||
local queries = {}
|
||||
local query = TSMAPI:GetAuctionQueryInfo(target)
|
||||
if not query and not lastAttempt then return end
|
||||
if query then
|
||||
tinsert(queries, query)
|
||||
end
|
||||
for itemType, rarityData in pairs(disenchantData.itemTypes) do
|
||||
local class = 0
|
||||
if itemType == "Weapon" then
|
||||
class = 1
|
||||
elseif itemType == "Armor" then
|
||||
class = 2
|
||||
end
|
||||
for rarity, data in pairs(rarityData) do
|
||||
local minILevel = data[1].minItemLevel or 0
|
||||
local maxILevel = data[#data].maxItemLevel or 0
|
||||
local query = {name="", class=class, subClass=0, minLevel=disenchantData.minLevel, maxLevel=disenchantData.maxLevel, minILevel=minILevel, maxILevel=maxILevel, quality=rarity}
|
||||
tinsert(queries, query)
|
||||
end
|
||||
end
|
||||
|
||||
for itemString, data in pairs(TSMAPI.Conversions[target] or {}) do
|
||||
local query = TSMAPI:GetAuctionQueryInfo(itemString)
|
||||
if not query and not lastAttempt then return end
|
||||
if query then
|
||||
tinsert(queries, query)
|
||||
end
|
||||
end
|
||||
|
||||
private.mode = "disenchant"
|
||||
private.target = target
|
||||
if TSM.isCrafting then
|
||||
local func = TSMAPI:ParseCustomPrice("matprice")
|
||||
local price = func and func(target) or nil
|
||||
private.targetMarketValue = price
|
||||
TSM.Util:ShowSearchFrame(true, L["% Max Price"])
|
||||
else
|
||||
private.targetMarketValue = TSM:GetMaxPrice(TSM.db.global.marketValueSource, target)
|
||||
TSM.Util:ShowSearchFrame(true, L["% Target Value"])
|
||||
end
|
||||
TSM.Search:SetSearchBarDisabled(true)
|
||||
TSM.Util:StartFilterScan(queries, private.ScanCallback)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function private.ScanCallback(event, ...)
|
||||
if event == "filter" then
|
||||
return
|
||||
elseif event == "process" then
|
||||
local itemString, auctionItem = ...
|
||||
local rate, shouldEvenFilter
|
||||
if private.mode == "mill" then
|
||||
rate = private.conversions[itemString]
|
||||
shouldEvenFilter = private.evenFilter[itemString]
|
||||
elseif private.mode == "disenchant" then
|
||||
if TSMAPI.Conversions[private.target] and TSMAPI.Conversions[private.target][itemString] then
|
||||
rate = TSMAPI.Conversions[private.target][itemString].rate
|
||||
else
|
||||
rate = TSMAPI:GetEnchantingConversionNum(private.target, itemString)
|
||||
end
|
||||
elseif private.mode == "prospect" then
|
||||
shouldEvenFilter = private.evenFilter[itemString]
|
||||
local conversions = TSMAPI:GetItemConversions(private.target)
|
||||
rate = conversions and conversions[itemString] and conversions[itemString].rate
|
||||
rate = rate and (rate / 5)
|
||||
end
|
||||
if itemString == private.target then
|
||||
auctionItem.destroyingNum = 1
|
||||
auctionItem:SetMarketValue(private.targetMarketValue)
|
||||
else
|
||||
if not rate then return end
|
||||
if shouldEvenFilter then
|
||||
auctionItem:FilterRecords(function(record) return record.count%5 ~= 0 end)
|
||||
end
|
||||
auctionItem.destroyingNum = 1/rate
|
||||
if private.targetMarketValue then
|
||||
auctionItem:SetMarketValue(private.targetMarketValue*rate)
|
||||
end
|
||||
end
|
||||
return auctionItem
|
||||
elseif event == "done" then
|
||||
TSM.Search:SetSearchBarDisabled(false)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,362 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Shopping --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_shopping --
|
||||
-- --
|
||||
-- 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_Shopping") -- 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(2)
|
||||
Options.currentGroup = nil
|
||||
else
|
||||
Options.treeGroup:SelectByPath(2, 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["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 minor then
|
||||
Options:DrawOperationSettings(treeGroup, minor)
|
||||
else
|
||||
Options:DrawNewOperation(treeGroup)
|
||||
end
|
||||
end
|
||||
|
||||
function Options:DrawGeneralSettings(container)
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["General Options"],
|
||||
children = {
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Default Post Undercut Amount"],
|
||||
settingInfo = { TSM.db.global, "postUndercut" },
|
||||
relativeWidth = 0.5,
|
||||
acceptCustom = true,
|
||||
callback = function(_, _, value) TSMAPI.AuctionControl.undercut = value end,
|
||||
tooltip = L["What to set the default undercut to when posting items with Shopping."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Market Value Price Source"],
|
||||
settingInfo = { TSM.db.global, "marketValueSource" },
|
||||
relativeWidth = 0.5,
|
||||
acceptCustom = true,
|
||||
tooltip = L["This is how Shopping calculates the '% Market Value' column in the search results."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Max Disenchant Search Percent"],
|
||||
settingInfo = { TSM.db.global, "maxDeSearchPercent" },
|
||||
min = .1,
|
||||
max = 1,
|
||||
step = .01,
|
||||
isPercent = true,
|
||||
relativeWidth = 1,
|
||||
tooltip = L["This is the maximum percentage of disenchant value that the Other > Disenchant search will display results for."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Min Disenchant Level"],
|
||||
settingInfo = { TSM.db.global, "minDeSearchLvl" },
|
||||
min = 1,
|
||||
max = 450,
|
||||
step = 1,
|
||||
isPercent = false,
|
||||
relativeWidth = 0.5,
|
||||
callback = function(self, _, value)
|
||||
if value > TSM.db.global.maxDeSearchLvl then
|
||||
TSM:Print(TSMAPI.Design:GetInlineColor("link2") .. L["Warning: The min disenchant level must be lower than the max disenchant level."] .. "|r")
|
||||
end
|
||||
TSM.db.global.minDeSearchLvl = min(value, TSM.db.global.maxDeSearchLvl)
|
||||
end,
|
||||
tooltip = L["This is the minimum item level that the Other > Disenchant search will display results for."],
|
||||
},
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Max Disenchant Level"],
|
||||
settingInfo = { TSM.db.global, "maxDeSearchLvl" },
|
||||
min = 1,
|
||||
max = 450,
|
||||
step = 1,
|
||||
isPercent = false,
|
||||
callback = function(self, _, value)
|
||||
if value < TSM.db.global.minDeSearchLvl then
|
||||
TSM:Print(TSMAPI.Design:GetInlineColor("link2") .. L["Warning: The max disenchant level must be higher than the min disenchant level."] .. "|r")
|
||||
end
|
||||
TSM.db.global.maxDeSearchLvl = max(value, TSM.db.global.minDeSearchLvl)
|
||||
end,
|
||||
relativeWidth = 0.5,
|
||||
tooltip = L["This is the maximum item level that the Other > Disenchant search will display results for."],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "Spacer",
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = "Posting Options",
|
||||
children = {
|
||||
{
|
||||
type = "Slider",
|
||||
label = L["Bid Percent"],
|
||||
settingInfo = { TSM.db.global, "postBidPercent" },
|
||||
min = .1,
|
||||
max = 1,
|
||||
step = .01,
|
||||
isPercent = true,
|
||||
relativeWidth = 0.5,
|
||||
tooltip = L["This is the percentage of your buyout price that your bid will be set to when posting auctions with Shopping."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Normal Post Price"],
|
||||
settingInfo = { TSM.db.global, "normalPostPrice" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["This is the default price Shopping will suggest to post items at when there's no others posted."],
|
||||
},
|
||||
{
|
||||
type = "HeadingLine"
|
||||
},
|
||||
{
|
||||
type = "Dropdown",
|
||||
label = L["Quick Posting Duration"],
|
||||
list = { AUCTION_DURATION_ONE, AUCTION_DURATION_TWO, AUCTION_DURATION_THREE },
|
||||
settingInfo = { TSM.db.global, "quickPostingDuration" },
|
||||
relativeWidth = 0.5,
|
||||
tooltip = L["The duration at which items will be posted via the 'Quick Posting' frame."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Quick Posting Price"],
|
||||
settingInfo = { TSM.db.global, "quickPostingPrice" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
tooltip = L["This price is used to determine what items will be posted at through the 'Quick Posting' frame."],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["Sniper Options"],
|
||||
children = {
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Below Vendor Sell Price"],
|
||||
settingInfo = { TSM.db.global, "sniperVendorPrice" },
|
||||
relativeWidth = 0.5,
|
||||
tooltip = L["Items which are below their vendor sell price will be displayed in Sniper searches."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Below Max Price"],
|
||||
settingInfo = { TSM.db.global, "sniperMaxPrice" },
|
||||
relativeWidth = 0.49,
|
||||
tooltip = L["Items which are below their maximum price (per their group / Shopping operation) will be displayed in Sniper searches."],
|
||||
},
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Below Custom Price ('0c' to disable)"],
|
||||
settingInfo = { TSM.db.global, "sniperCustomPrice" },
|
||||
relativeWidth = 0.5,
|
||||
acceptCustom = true,
|
||||
tooltip = L["Items which are below this custom price will be displayed in Sniper searches."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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["Shopping operations contain settings items which you regularly buy from the auction house."],
|
||||
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(2, name)
|
||||
TSMAPI:NewOperationCallback("Shopping", 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["Relationships"] }, { value = 3, text = L["Management"] } })
|
||||
tg:SetCallback("OnGroupSelected", function(self, _, value)
|
||||
tg:ReleaseChildren()
|
||||
TSMAPI:UpdateOperation("Shopping", operationName)
|
||||
if value == 1 then
|
||||
Options:DrawOperationGeneral(self, operationName)
|
||||
elseif value == 2 then
|
||||
Options:DrawOperationRelationships(self, operationName)
|
||||
elseif value == 3 then
|
||||
TSMAPI:DrawOperationManagement(TSM, self, operationName)
|
||||
end
|
||||
end)
|
||||
container:AddChild(tg)
|
||||
tg:SelectTab(1)
|
||||
end
|
||||
|
||||
function Options:DrawOperationGeneral(container, operationName)
|
||||
local operation = TSM.operations[operationName]
|
||||
local page = {
|
||||
{
|
||||
type = "ScrollFrame",
|
||||
layout = "list",
|
||||
children = {
|
||||
{
|
||||
type = "InlineGroup",
|
||||
layout = "flow",
|
||||
title = L["General Operation Options"],
|
||||
children = {
|
||||
{
|
||||
type = "EditBox",
|
||||
label = L["Maximum Auction Price (per item)"],
|
||||
settingInfo = { operation, "maxPrice" },
|
||||
relativeWidth = 0.49,
|
||||
acceptCustom = true,
|
||||
disabled = operation.relationships.maxprice,
|
||||
tooltip = L["The highest price per item you will pay for items in affected by this operation."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Show Auctions Above Max Price"],
|
||||
settingInfo = { operation, "showAboveMaxPrice" },
|
||||
disabled = operation.relationships.showAboveMaxPrice,
|
||||
tooltip = L["If checked, auctions above the max price will be shown."],
|
||||
},
|
||||
{
|
||||
type = "CheckBox",
|
||||
label = L["Even (5/10/15/20) Stacks Only"],
|
||||
settingInfo = { operation, "evenStacks" },
|
||||
disabled = operation.relationships.evenStacks,
|
||||
tooltip = L["If checked, only auctions posted in even quantities will be considered for purchasing."],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
|
||||
function Options:DrawOperationRelationships(container, operationName)
|
||||
local settingInfo = {
|
||||
{
|
||||
label = L["General Settings"],
|
||||
{ key = "maxPrice", label = L["Maximum Auction Price (per item)"] },
|
||||
{ key = "showAboveMaxPrice", label = L["Show Auctions Above Max Price"] },
|
||||
{ key = "evenStacks", label = L["Even (5/10/15/20) Stacks Only"] },
|
||||
},
|
||||
}
|
||||
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 Shopping Max Price in Tooltip"],
|
||||
settingInfo = { TSM.db.global, "tooltip" },
|
||||
callback = function(_, _, value) container:ReloadTab() end,
|
||||
tooltip = L["If checked, the maximum shopping price will be shown in the tooltip for the item."],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
TSMAPI:BuildPage(container, page)
|
||||
end
|
||||
@@ -0,0 +1,589 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Shopping --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_shopping --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Search = TSM:NewModule("Search", "AceEvent-3.0", "AceHook-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Shopping") -- loads the localization table
|
||||
local private = {}
|
||||
|
||||
-- ------------------------------------------------ --
|
||||
-- GUI Creation functions --
|
||||
-- ------------------------------------------------ --
|
||||
|
||||
function Search:Show(frame)
|
||||
TSM.Util:SetParent(frame)
|
||||
private.searchBar = private.searchBar or private:CreateSearchBar(frame)
|
||||
private.searchBar:Show()
|
||||
private.searchBar.editBox:SetFocus()
|
||||
private.searchBar.editBox:SetText("")
|
||||
private.searchBar:Enable()
|
||||
private.searchBar.normal:Click()
|
||||
TSM.Sidebar:Show(frame)
|
||||
if TSM.db.global.sidebarBtn > #private.searchBar.buttons then
|
||||
TSM.db.global.sidebarBtn = 0
|
||||
end
|
||||
if TSM.db.global.sidebarBtn > 0 then
|
||||
if not private.searchBar.buttons[TSM.db.global.sidebarBtn].isSelected then
|
||||
private.searchBar.buttons[TSM.db.global.sidebarBtn]:Click()
|
||||
end
|
||||
else
|
||||
TSM.Sidebar:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function Search:Hide()
|
||||
if not private.searchBar then return end
|
||||
private.searchBar:Hide()
|
||||
TSM.Util:HideSearchFrame()
|
||||
TSMAPI.AuctionControl:HideControlButtons()
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
TSM.Sidebar:Hide()
|
||||
end
|
||||
|
||||
function private:CreateSearchBar(parent)
|
||||
local function StartSearch(searchQuery)
|
||||
if private.mode == "normal" then
|
||||
Search:StartFilterSearch(searchQuery)
|
||||
elseif private.mode == "destroy" then
|
||||
private.searchBar.editBox:SetText(searchQuery)
|
||||
local filters = Search:GetFilters(searchQuery)
|
||||
if filters and #filters == 1 then
|
||||
for itemString, name in pairs(TSM.db.global.destroyingTargetItems) do
|
||||
if strlower(name) == strlower(filters.currentFilter) then
|
||||
return TSM.Destroying:StartDestroyingSearch(itemString, filters[1])
|
||||
end
|
||||
end
|
||||
TSM:Printf(L["Invalid target item for destroy search: '%s'"], filters.currentFilter)
|
||||
else
|
||||
TSM:Printf(L["Invalid destroy search: '%s'"], searchQuery)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function HandleModifiedItemClick(link)
|
||||
local putIntoChat = Search.hooks.HandleModifiedItemClick(link)
|
||||
if not putIntoChat and private.searchBar:IsVisible() and not private.searchBar.isDisabled and TSMAPI:AHTabIsVisible("Shopping") then
|
||||
local name = TSMAPI:GetSafeItemInfo(link)
|
||||
if name then
|
||||
StartSearch(name.."/exact")
|
||||
return true
|
||||
end
|
||||
end
|
||||
return putIntoChat
|
||||
end
|
||||
local function InsertLink(link)
|
||||
local putIntoChat = Search.hooks.ChatEdit_InsertLink(link)
|
||||
if not putIntoChat then
|
||||
if private.searchBar:IsVisible() and not private.searchBar.isDisabled and TSMAPI:AHTabIsVisible("Shopping") then
|
||||
local name = TSMAPI:GetSafeItemInfo(link)
|
||||
if name then
|
||||
StartSearch(name.."/exact")
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return putIntoChat
|
||||
end
|
||||
Search:RawHook("ChatEdit_InsertLink", InsertLink, true)
|
||||
Search:RawHook("HandleModifiedItemClick", HandleModifiedItemClick, true)
|
||||
|
||||
local function OnChar(self)
|
||||
local text = self:GetText()
|
||||
if private.mode == "normal" then
|
||||
for i=1, #TSM.db.global.previousSearches do
|
||||
local prevSearch = strlower(TSM.db.global.previousSearches[i])
|
||||
if strsub(prevSearch, 1, #text) == strlower(text) then
|
||||
self:SetText(prevSearch)
|
||||
self:HighlightText(#text, -1)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif private.mode == "destroy" then
|
||||
for _, name in pairs(TSM.db.global.destroyingTargetItems) do
|
||||
name = strlower(name)
|
||||
if strsub(name, 1, #text) == strlower(text) then
|
||||
self:SetText(name)
|
||||
self:HighlightText(#text, -1)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEditFocusGained(self)
|
||||
self:HighlightText()
|
||||
end
|
||||
|
||||
local function OnEditFocusLost(self)
|
||||
self:HighlightText()
|
||||
end
|
||||
|
||||
local function OnUpdate(self)
|
||||
-- if self:IsEnabled() and not TSMAPI:AHTabIsVisible("Shopping") then
|
||||
if not TSMAPI:AHTabIsVisible("Shopping") then
|
||||
self:ClearFocus()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEnter(self)
|
||||
GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
|
||||
GameTooltip:SetMinimumWidth(400)
|
||||
GameTooltip:AddLine(L["Enter what you want to search for in this box. You can also use the following options for more complicated searches."].."\n", 1, 1, 1, 1)
|
||||
GameTooltip:AddLine(format("|cffffff00"..L["Multiple Search Terms:|r You can search for multiple things at once by simply separated them with a ';'. For example '%scopper ore; gold ore|r' will search for both copper and gold ore."].."\n", TSMAPI.Design:GetInlineColor("link2")), 1, 1, 1, 1)
|
||||
GameTooltip:AddLine(format("|cffffff00"..L["Inline Filters:|r You can easily add common search filters to your search such as rarity, level, and item type. For example '%sarmor/leather/epic/80/i200/i285|r' will search for all leather armor of epic quality that requires level 80 and has an ilvl between 200 and 285 inclusive. Also, '%sinferno ruby/exact|r' will display only raw inferno rubys (none of the cuts)."].."\n", TSMAPI.Design:GetInlineColor("link2"), TSMAPI.Design:GetInlineColor("link2")), 1, 1, 1, 1)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
|
||||
local searchBarFrame = CreateFrame("Frame", nil, parent)
|
||||
searchBarFrame:SetAllPoints()
|
||||
searchBarFrame:Hide()
|
||||
|
||||
local eb = TSMAPI.GUI:CreateInputBox(searchBarFrame)
|
||||
eb:SetPoint("TOPLEFT", 85, -5)
|
||||
eb:SetHeight(22)
|
||||
eb:SetWidth(600)
|
||||
eb:SetScript("OnShow", eb.SetFocus)
|
||||
eb:SetScript("OnEnterPressed", function() StartSearch(private.searchBar.editBox:GetText()) end)
|
||||
eb:SetScript("OnChar", OnChar)
|
||||
eb:SetScript("OnEditFocusGained", OnEditFocusGained)
|
||||
eb:SetScript("OnEditFocusLost", OnEditFocusLost)
|
||||
eb:SetScript("OnEnter", OnEnter)
|
||||
eb:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
||||
eb:SetScript("OnUpdate", OnUpdate)
|
||||
searchBarFrame.editBox = eb
|
||||
|
||||
local btn = TSMAPI.GUI:CreateButton(searchBarFrame, 20)
|
||||
btn:SetPoint("TOPLEFT", eb, "TOPRIGHT", 4, 0)
|
||||
btn:SetPoint("BOTTOMLEFT", eb, "BOTTOMRIGHT", 4, 0)
|
||||
btn:SetWidth(85)
|
||||
btn:SetText(SEARCH)
|
||||
btn:SetScript("OnClick", function() StartSearch(private.searchBar.editBox:GetText()) end)
|
||||
searchBarFrame.button = btn
|
||||
|
||||
local btn = TSMAPI.GUI:CreateButton(searchBarFrame, 16)
|
||||
btn:SetPoint("TOPLEFT", searchBarFrame.button, "TOPRIGHT", 4, 0)
|
||||
btn:SetPoint("BOTTOMLEFT", searchBarFrame.button, "BOTTOMRIGHT", 4, 0)
|
||||
btn:SetPoint("TOPRIGHT", -5, -5)
|
||||
btn:SetText(L["Stop"])
|
||||
btn:Disable()
|
||||
btn:SetScript("OnClick", function() TSM.Util:StopScan() searchBarFrame:Enable() end)
|
||||
searchBarFrame.stop = btn
|
||||
|
||||
local function OnModeChange(self)
|
||||
searchBarFrame.normal:UnlockHighlight()
|
||||
searchBarFrame.destroy:UnlockHighlight()
|
||||
self:LockHighlight()
|
||||
if self.mode ~= private.mode then
|
||||
private.mode = self.mode
|
||||
private:UpdateMode()
|
||||
end
|
||||
end
|
||||
|
||||
local btn = TSMAPI.GUI:CreateButton(searchBarFrame, 14)
|
||||
btn:SetPoint("TOPLEFT", eb, "BOTTOMLEFT", 0, -8)
|
||||
btn:SetHeight(16)
|
||||
btn:SetWidth(110)
|
||||
btn:SetText(L["Normal Mode"])
|
||||
btn:SetScript("OnClick", OnModeChange)
|
||||
btn.mode = "normal"
|
||||
btn.tooltip = L["When in normal mode, you may run simple and filtered searches of the auction house."]
|
||||
searchBarFrame.normal = btn
|
||||
|
||||
local btn = TSMAPI.GUI:CreateButton(searchBarFrame, 14)
|
||||
btn:SetPoint("TOPLEFT", searchBarFrame.normal, "BOTTOMLEFT", 0, -4)
|
||||
btn:SetPoint("TOPRIGHT", searchBarFrame.normal, "BOTTOMRIGHT", 0, -4)
|
||||
btn:SetHeight(16)
|
||||
btn:SetText(L["Destroy Mode"])
|
||||
btn:SetScript("OnClick", OnModeChange)
|
||||
btn.mode = "destroy"
|
||||
btn.tooltip = L["When in destroy mode, you simply enter a target item (ink/pigment, enchanting mat, gem, etc) into the search box to search for everything you can destroy to get that item."]
|
||||
searchBarFrame.destroy = btn
|
||||
|
||||
local line = TSMAPI.GUI:CreateHorizontalLine(searchBarFrame, 0)
|
||||
line:ClearAllPoints()
|
||||
line:SetHeight(4)
|
||||
line:SetPoint("TOPLEFT", eb, "BOTTOMLEFT", 120, -7)
|
||||
line:SetPoint("TOPRIGHT", 0, -34)
|
||||
|
||||
local pagesLabel = TSMAPI.GUI:CreateLabel(searchBarFrame)
|
||||
pagesLabel:SetPoint("TOPLEFT", eb, "BOTTOMLEFT", 125, -15)
|
||||
pagesLabel:SetHeight(20)
|
||||
pagesLabel:SetJustifyH("CENTER")
|
||||
pagesLabel:SetJustifyV("CENTER")
|
||||
pagesLabel:SetText(L["Sidebar Pages:"])
|
||||
pagesLabel:SetWidth(pagesLabel:GetWidth() + 5)
|
||||
|
||||
local buttons = {}
|
||||
local function OnClick(self)
|
||||
self.isSelected = not self.isSelected
|
||||
for _, btn in ipairs(buttons) do
|
||||
btn:UnlockHighlight()
|
||||
if btn ~= self then
|
||||
btn.isSelected = false
|
||||
end
|
||||
end
|
||||
if self.isSelected then
|
||||
TSM.db.global.sidebarBtn = self.index
|
||||
self:LockHighlight()
|
||||
TSM.Sidebar:Show()
|
||||
else
|
||||
TSM.db.global.sidebarBtn = 0
|
||||
self:UnlockHighlight()
|
||||
TSM.Sidebar:Hide()
|
||||
end
|
||||
TSM.Sidebar:ButtonClick(self.label)
|
||||
end
|
||||
local pages, callbacks = TSM.Sidebar:GetPages()
|
||||
for i, label in ipairs(pages) do
|
||||
local btn = TSMAPI.GUI:CreateButton(searchBarFrame, 16)
|
||||
btn:SetPoint("TOPLEFT", buttons[i-1] or pagesLabel, "TOPRIGHT", 5, 0)
|
||||
btn:SetHeight(20)
|
||||
btn:SetText(label)
|
||||
btn:SetWidth(ceil(btn:GetTextWidth()+10))
|
||||
btn:SetScript("OnClick", OnClick)
|
||||
btn.label = label
|
||||
btn.index = i
|
||||
buttons[i] = btn
|
||||
end
|
||||
searchBarFrame.buttons = buttons
|
||||
|
||||
local line = TSMAPI.GUI:CreateHorizontalLine(searchBarFrame, 0)
|
||||
line:ClearAllPoints()
|
||||
line:SetHeight(4)
|
||||
line:SetPoint("TOPLEFT", eb, "BOTTOMLEFT", 120, -40)
|
||||
line:SetPoint("TOPRIGHT", 0, -67)
|
||||
|
||||
local line = TSMAPI.GUI:CreateVerticalLine(searchBarFrame, 0)
|
||||
line:ClearAllPoints()
|
||||
line:SetPoint("TOPLEFT", eb, "BOTTOMLEFT", 120, -7)
|
||||
line:SetHeight(33)
|
||||
line:SetWidth(4)
|
||||
|
||||
searchBarFrame.Disable = function(self)
|
||||
self.isDisabled = true
|
||||
self.editBox:ClearFocus()
|
||||
self.editBox:HighlightText(0, 0)
|
||||
-- self.editBox:Disable()
|
||||
self.button:Disable()
|
||||
self.stop:Enable()
|
||||
end
|
||||
searchBarFrame.Enable = function(self)
|
||||
self.isDisabled = nil
|
||||
-- self.editBox:Enable()
|
||||
self.button:Enable()
|
||||
self.stop:Disable()
|
||||
end
|
||||
|
||||
return searchBarFrame
|
||||
end
|
||||
|
||||
function private:UpdateMode()
|
||||
private.searchBar.editBox:SetText("")
|
||||
if private.mode == "nomal" then
|
||||
TSM.Util:ShowSearchFrame(nil, L["% Market Value"], true)
|
||||
elseif private.mode == "destroy" then
|
||||
TSM.Util:ShowSearchFrame(true, L["% Target Value"], true)
|
||||
end
|
||||
TSM.Util:StopScan()
|
||||
private.searchBar:Enable()
|
||||
end
|
||||
|
||||
local function ScanCallback(event, ...)
|
||||
if TSM.searchCallback then
|
||||
TSM.searchCallback(event)
|
||||
end
|
||||
if event == "filter" then
|
||||
local filter = ...
|
||||
return filter.maxPrice
|
||||
elseif event == "process" then
|
||||
local itemString, auctionItem = ...
|
||||
if auctionItem.query.maxPrice then
|
||||
auctionItem:FilterRecords(function(record)
|
||||
return (record:GetItemBuyout() or 0) > auctionItem.query.maxPrice
|
||||
end)
|
||||
end
|
||||
if TSM.isCrafting then
|
||||
local func = TSMAPI:ParseCustomPrice("matprice")
|
||||
local price = func and func(itemString) or nil
|
||||
auctionItem:SetMarketValue(price)
|
||||
else
|
||||
auctionItem:SetMarketValue(TSM:GetMaxPrice(TSM.db.global.marketValueSource, itemString))
|
||||
end
|
||||
return auctionItem
|
||||
elseif event == "done" then
|
||||
private.searchBar:Enable()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function Search:StartFilterSearch(filter, callback, isCrafting)
|
||||
TSM.isCrafting = isCrafting
|
||||
TSM.searchCallback = callback
|
||||
if strfind(filter, "item:([0-9]+):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?%-?([0-9]*)$") then --or strfind(filter, "battlepet:([0-9]+):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*)$") then
|
||||
filter = TSMAPI:GetSafeItemInfo(filter) or filter
|
||||
end
|
||||
if TSM.isCrafting then
|
||||
TSM.Util:ShowSearchFrame(nil, L["% Mat Price"])
|
||||
else
|
||||
TSM.Util:ShowSearchFrame(nil, L["% Market Value"])
|
||||
end
|
||||
private.searchBar.editBox:SetText(filter)
|
||||
private.searchBar:Disable()
|
||||
if filter ~= "" then
|
||||
for i=#TSM.db.global.previousSearches, 1, -1 do
|
||||
if strlower(TSM.db.global.previousSearches[i]) == strlower(filter) then
|
||||
tremove(TSM.db.global.previousSearches, i)
|
||||
end
|
||||
end
|
||||
tinsert(TSM.db.global.previousSearches, 1, filter)
|
||||
while #TSM.db.global.previousSearches > 100 do
|
||||
tremove(TSM.db.global.previousSearches)
|
||||
end
|
||||
TSM.Sidebar:UpdateCurrentFrame()
|
||||
end
|
||||
local isItemList, itemList = true, {}
|
||||
for _, searchTerm in ipairs({(";"):split(filter)}) do
|
||||
if tonumber(searchTerm) then
|
||||
tinsert(itemList, TSMAPI:GetItemString(searchTerm))
|
||||
else
|
||||
isItemList = nil
|
||||
end
|
||||
end
|
||||
TSMAPI:FireEvent("SHOPPING:SEARCH:STARTFILTERSCAN")
|
||||
|
||||
if isItemList then
|
||||
TSM.Util:StartItemScan(itemList, ScanCallback)
|
||||
else
|
||||
TSM.Util:StartFilterScan(Search:GetFilters(filter), ScanCallback)
|
||||
end
|
||||
end
|
||||
|
||||
function Search:SetSearchBarDisabled(disabled)
|
||||
if disabled then
|
||||
private.searchBar:Disable()
|
||||
else
|
||||
private.searchBar:Enable()
|
||||
end
|
||||
end
|
||||
|
||||
function Search:SetMode(mode)
|
||||
if mode == "normal" then
|
||||
private.searchBar.normal:Click()
|
||||
elseif mode == "destroy" then
|
||||
private.searchBar.destroy:Click()
|
||||
end
|
||||
end
|
||||
|
||||
function Search:SetSearchText(text)
|
||||
private.searchBar.editBox:SetText(text)
|
||||
end
|
||||
|
||||
|
||||
-- ------------------------------------------------ --
|
||||
-- Search Filter Util functions --
|
||||
-- ------------------------------------------------ --
|
||||
|
||||
local function GetMaxQuantity(str)
|
||||
if #str > 1 and strsub(str, 1, 1) == "x" then
|
||||
return tonumber(strsub(str, 2))
|
||||
end
|
||||
end
|
||||
|
||||
local function GetItemLevel(str)
|
||||
if #str > 1 and strsub(str, 1, 1) == "i" then
|
||||
return tonumber(strsub(str, 2))
|
||||
end
|
||||
end
|
||||
|
||||
local function GetItemClass(str)
|
||||
for i, class in ipairs({GetAuctionItemClasses()}) do
|
||||
if strlower(str) == strlower(class) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function GetItemSubClass(str, class)
|
||||
if not class then return end
|
||||
|
||||
for i, subClass in ipairs({GetAuctionItemSubClasses(class)}) do
|
||||
if strlower(str) == strlower(subClass) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function GetItemRarity(str)
|
||||
for i=0, 4 do
|
||||
local text = _G["ITEM_QUALITY"..i.."_DESC"]
|
||||
if strlower(str) == strlower(text) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function GetSearchFilterOptions(searchTerm)
|
||||
local parts = {("/"):split(searchTerm)}
|
||||
local queryString, class, subClass, minLevel, maxLevel, minILevel, maxILevel, rarity, usableOnly, exactOnly, evenOnly, maxQuantity, maxPrice
|
||||
|
||||
if #parts == 1 then
|
||||
return true, parts[1]
|
||||
elseif #parts == 0 then
|
||||
return false, L["Invalid Filter"]
|
||||
end
|
||||
|
||||
for i, str in ipairs(parts) do
|
||||
str = str:trim()
|
||||
|
||||
if tonumber(str) then
|
||||
if not minLevel then
|
||||
minLevel = tonumber(str)
|
||||
elseif not maxLevel then
|
||||
maxLevel = tonumber(str)
|
||||
else
|
||||
return false, L["Invalid Min Level"]
|
||||
end
|
||||
elseif GetMaxQuantity(str) then
|
||||
if not maxQuantity then
|
||||
maxQuantity = GetMaxQuantity(str)
|
||||
else
|
||||
return false, L["Invalid Max Quantity"]
|
||||
end
|
||||
elseif GetItemLevel(str) then
|
||||
if not minILevel then
|
||||
minILevel = GetItemLevel(str)
|
||||
elseif not maxILevel then
|
||||
maxILevel = GetItemLevel(str)
|
||||
else
|
||||
return false, L["Invalid Item Level"]
|
||||
end
|
||||
elseif not class and GetItemClass(str) then
|
||||
if not class then
|
||||
class = GetItemClass(str)
|
||||
else
|
||||
return false, L["Invalid Item Type"]
|
||||
end
|
||||
elseif GetItemSubClass(str, class) then
|
||||
if not subClass then
|
||||
subClass = GetItemSubClass(str, class)
|
||||
else
|
||||
return false, L["Invalid Item SubType"]
|
||||
end
|
||||
elseif GetItemRarity(str) then
|
||||
if not rarity then
|
||||
rarity = GetItemRarity(str)
|
||||
else
|
||||
return false, L["Invalid Item Rarity"]
|
||||
end
|
||||
elseif strlower(str) == "usable" then
|
||||
if not usableOnly then
|
||||
usableOnly = 1
|
||||
else
|
||||
return false, L["Invalid Usable Only Filter"]
|
||||
end
|
||||
elseif strlower(str) == "exact" then
|
||||
if not exactOnly then
|
||||
exactOnly = 1
|
||||
else
|
||||
return false, L["Invalid Exact Only Filter"]
|
||||
end
|
||||
elseif strlower(str) == "even" then
|
||||
if not evenOnly then
|
||||
evenOnly = 1
|
||||
else
|
||||
return false, L["Invalid Even Only Filter"]
|
||||
end
|
||||
elseif TSMAPI:UnformatTextMoney(str) then
|
||||
maxPrice = TSMAPI:UnformatTextMoney(str)
|
||||
elseif i == 1 then
|
||||
if strfind(str, "item:([0-9]+):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?%-?([0-9]*)$") then --or strfind(str, "battlepet:([0-9]+):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*):?([0-9]*)$") then
|
||||
queryString = TSMAPI:GetSafeItemInfo(str)
|
||||
else
|
||||
queryString = str
|
||||
end
|
||||
else
|
||||
return false, L["Unknown Filter"]
|
||||
end
|
||||
end
|
||||
|
||||
if maxLevel and minLevel and maxLevel < minLevel then
|
||||
local oldMaxLevel = maxLevel
|
||||
maxLevel = minLevel
|
||||
minLevel = oldMaxLevel
|
||||
end
|
||||
|
||||
if maxILevel and minILevel and maxILevel < minILevel then
|
||||
local oldMaxILevel = maxILevel
|
||||
maxILevel = minILevel
|
||||
minILevel = oldMaxILevel
|
||||
end
|
||||
|
||||
return true, queryString or "", class or 0, subClass or 0, minLevel or 0, maxLevel or 0, minILevel or 0, maxILevel or 0, rarity or -1, usableOnly or 0, exactOnly or nil, evenOnly or nil, maxQuantity or 0, maxPrice
|
||||
--return true, queryString or "", class or 0, subClass or 0, minLevel or 0, maxLevel or 0, minILevel or 0, maxILevel or 0, rarity or 0, usableOnly or 0, exactOnly or nil, evenOnly or nil, maxQuantity or 0, maxPrice
|
||||
end
|
||||
|
||||
-- gets all the filters for a given search term (possibly semicolon-deliminated list of search terms)
|
||||
function Search:GetFilters(searchQuery)
|
||||
local filters = {}
|
||||
local searchTerms = {(";"):split(searchQuery)}
|
||||
filters.num = 0
|
||||
|
||||
for i=1, #searchTerms do
|
||||
local searchTerm = searchTerms[i]:trim()
|
||||
if tonumber(searchTerm) then
|
||||
local filter = TSMAPI:GetAuctionQueryInfo(TSMAPI:GetItemString(searchTerm))
|
||||
if filter then
|
||||
tinsert(filters, filter)
|
||||
filters.num = filters.num + 1
|
||||
if filters.currentFilter then
|
||||
filters.currentFilter = filters.currentFilter.."; "..searchTerm
|
||||
else
|
||||
filters.currentFilter = searchTerm
|
||||
end
|
||||
if filters.currentSearchTerm then
|
||||
filters.currentSearchTerm = filters.currentSearchTerm .. "; "..searchTerm
|
||||
else
|
||||
filters.currentSearchTerm = searchTerm
|
||||
end
|
||||
end
|
||||
else
|
||||
local isValid, queryString, class, subClass, minLevel, maxLevel, minILevel, maxILevel, rarity, usableOnly, exactOnly, evenOnly, maxQuantity, maxPrice = GetSearchFilterOptions(searchTerm)
|
||||
|
||||
if not isValid then
|
||||
TSM:Print(L["Skipped the following search term because it's invalid."])
|
||||
TSM:Print("\""..searchTerm.."\": "..queryString)
|
||||
elseif strlenutf8(queryString) > 63 then
|
||||
TSM:Print(L["Skipped the following search term because it's too long. Blizzard does not allow search terms over 63 characters."])
|
||||
TSM:Print("\""..searchTerm.."\"")
|
||||
isValid = nil
|
||||
end
|
||||
|
||||
if isValid then
|
||||
filters.num = filters.num + 1
|
||||
if filters.currentFilter then
|
||||
filters.currentFilter = filters.currentFilter.."; "..queryString
|
||||
else
|
||||
filters.currentFilter = queryString
|
||||
end
|
||||
if filters.currentSearchTerm then
|
||||
filters.currentSearchTerm = filters.currentSearchTerm .. "; "..searchTerm
|
||||
else
|
||||
filters.currentSearchTerm = searchTerm
|
||||
end
|
||||
tinsert(filters, {name=queryString, usable=usableOnly, minLevel=minLevel, maxLevel=maxLevel, quality=rarity, class=class, subClass=subClass, minILevel=minILevel, maxILevel=maxILevel, exactOnly=exactOnly, evenOnly=evenOnly, maxQuantity=maxQuantity, maxPrice=maxPrice})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return filters
|
||||
end
|
||||
|
||||
function Search:GetCurrentSearchMode()
|
||||
return private.mode
|
||||
end
|
||||
@@ -0,0 +1,459 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Shopping --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_shopping --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local TSM = select(2, ...)
|
||||
local Util = TSM:NewModule("Util", "AceEvent-3.0", "AceHook-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Shopping") -- loads the localization table
|
||||
local private = {auctions={}}
|
||||
TSMAPI:RegisterForTracing(private, "TradeSkillMaster_Shopping_private")
|
||||
Util.shoppingLog = {}
|
||||
|
||||
|
||||
local function ControlCallback(event, ...)
|
||||
if event == "OnBuyout" then
|
||||
local auction = ...
|
||||
tinsert(Util.shoppingLog, {action="Buyout", link=auction.link, buyout=auction.buyout, count=auction.count})
|
||||
private:RemoveAuction(auction, event, TSMAPI:GetItemString(auction.link))
|
||||
elseif event == "OnCancel" then
|
||||
local auction = ...
|
||||
tinsert(Util.shoppingLog, {action="Cancel", link=auction.link, buyout=auction.buyout, count=auction.count})
|
||||
private:RemoveAuction(auction, event, TSMAPI:GetItemString(auction.link))
|
||||
elseif event == "OnPost" then
|
||||
local postInfo = ...
|
||||
local link = select(2, TSMAPI:GetSafeItemInfo(postInfo.itemString))
|
||||
for i=1, postInfo.numAuctions do
|
||||
tinsert(Util.shoppingLog, {auction="Post", link=link, buyout=postInfo.buyout, count=postInfo.stackSize})
|
||||
end
|
||||
private:AddPostedAuction(postInfo)
|
||||
end
|
||||
if TSM.searchCallback then
|
||||
TSM.searchCallback(event, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function private:HasInBags(baseItemString)
|
||||
for _, _, itemString in TSMAPI:GetBagIterator() do
|
||||
if TSMAPI:GetBaseItemString(itemString) == baseItemString then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function private:CreateSearchFrame()
|
||||
local function OnShow(self)
|
||||
if not self.info then return end
|
||||
if self.info.isDestroying then
|
||||
self.rtNormal:Hide()
|
||||
self.rtDestroying:Show()
|
||||
self.rt = private.searchFrame.rtDestroying
|
||||
else
|
||||
self.rtNormal:Show()
|
||||
self.rtDestroying:Hide()
|
||||
self.rt = private.searchFrame.rtNormal
|
||||
end
|
||||
self.rt:SetColHeadText(#self.rt.headCols, self.info.pctColName)
|
||||
end
|
||||
|
||||
local frame = CreateFrame("Frame", nil, private.parent.content)
|
||||
frame:Hide()
|
||||
frame:SetAllPoints()
|
||||
frame:SetScript("OnShow", OnShow)
|
||||
|
||||
local statusBarFrame = CreateFrame("Frame", nil, frame)
|
||||
statusBarFrame:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 165, -2)
|
||||
statusBarFrame:SetWidth(250)
|
||||
statusBarFrame:SetHeight(30)
|
||||
frame.statusBar = TSMAPI.GUI:CreateStatusBar(statusBarFrame, "TSMShoppingStatusBar")
|
||||
|
||||
local handlers = {
|
||||
OnClick = function(_, data, self, button)
|
||||
-- they clicked on a data row
|
||||
if button == "LeftButton" then
|
||||
-- go to the page for this item
|
||||
local record = data.auctionRecord
|
||||
TSMAPI.AuctionScan:FindAuction(function() end, {itemString=data.itemString, buyout=record.buyout, count=record.count, seller=record.seller}, true)
|
||||
|
||||
if data.auctionRecord:IsPlayer() then
|
||||
private.controlButtons.cancel:Enable()
|
||||
private.controlButtons.buyout:Disable()
|
||||
private.controlButtons.post:Disable()
|
||||
elseif data.auctionRecord.buyout == 0 then
|
||||
private.controlButtons.buyout:Disable()
|
||||
private.controlButtons.cancel:Disable()
|
||||
private.controlButtons.post:Disable()
|
||||
else
|
||||
private.controlButtons.buyout:Enable()
|
||||
private.controlButtons.cancel:Disable()
|
||||
private.controlButtons.post:Disable()
|
||||
end
|
||||
if private:HasInBags(TSMAPI:GetBaseItemString(data.itemString)) then
|
||||
private.controlButtons.post:Enable()
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local rt = TSMAPI:CreateAuctionResultsTable(frame, handlers, true)
|
||||
rt:SetData({})
|
||||
rt:SetSort(8, true)
|
||||
frame.rtNormal = rt
|
||||
|
||||
local rt2 = TSMAPI:CreateAuctionResultsTable(frame, handlers, true, true)
|
||||
rt2:SetData({})
|
||||
rt2:SetSort(5, true)
|
||||
frame.rtDestroying = rt2
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function Util:SetParent(parent)
|
||||
private.parent = parent
|
||||
end
|
||||
|
||||
function Util:ShowSearchFrame(isDestroying, pctColName, clearRT)
|
||||
if private.searchFrame and private.searchFrame:IsVisible() then
|
||||
Util:HideSearchFrame()
|
||||
end
|
||||
private.searchFrame = private.searchFrame or private:CreateSearchFrame()
|
||||
private.searchFrame.info = {isDestroying=isDestroying, pctColName=pctColName}
|
||||
private.searchFrame:Show()
|
||||
if clearRT then
|
||||
private.searchFrame.rtNormal:SetData({})
|
||||
private.searchFrame.rtDestroying:SetData({})
|
||||
end
|
||||
private.controlButtons = TSMAPI.AuctionControl:ShowControlButtons(private.parent, private.searchFrame.rt, ControlCallback, "Shopping", TSM.db.global.postBidPercent, TSM.db.global.postUndercut)
|
||||
private.controlButtons.buyout:Disable()
|
||||
private.controlButtons.cancel:Disable()
|
||||
private.controlButtons.post:Disable()
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
TSMAPI.AuctionScan:ClearCache()
|
||||
private.searchFrame.statusBar:SetStatusText("")
|
||||
private.searchFrame.statusBar:UpdateStatus(0, 0)
|
||||
private.mode = isDestroying and "destroy" or "normal"
|
||||
TSM.Search:SetMode(private.mode)
|
||||
end
|
||||
|
||||
function Util:HideSearchFrame()
|
||||
private.searchFrame:Hide()
|
||||
TSMAPI.AuctionControl:HideControlButtons()
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
TSMAPI.AuctionScan:ClearCache()
|
||||
end
|
||||
|
||||
|
||||
function Util:StartItemScan(itemList, callback)
|
||||
if type(itemList) ~= "table" then return end
|
||||
private:PrepareForScan(callback)
|
||||
if #itemList == 1 then private.searchItem = itemList[1] end
|
||||
TSMAPI:GenerateQueries(itemList, private.ScanCallback)
|
||||
end
|
||||
|
||||
function Util:StartFilterScan(filters, callback)
|
||||
if type(filters) ~= "table" then return end
|
||||
|
||||
private:PrepareForScan(callback)
|
||||
if #filters == 1 then
|
||||
for _, _, itemString in TSMAPI:GetBagIterator() do
|
||||
local name = TSMAPI:GetSafeItemInfo(itemString)
|
||||
if name and filters[1].name and strlower(name) == strlower(filters[1].name) then
|
||||
private.searchItem = itemString
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
private.filterList = filters
|
||||
private.numFilters = #private.filterList
|
||||
private:ScanNextFilter()
|
||||
end
|
||||
|
||||
function Util:StartLastPageScan(callback)
|
||||
private:PrepareForScan(callback, true)
|
||||
TSMAPI.AuctionScan:ScanLastPage(private.ScanCallback)
|
||||
end
|
||||
|
||||
function Util:StopScan()
|
||||
TSMAPI:CancelFrame("shoppingRestartSniper")
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
private:ScanComplete()
|
||||
end
|
||||
|
||||
|
||||
|
||||
function private:PrepareForScan(callback, isLastPageScan)
|
||||
TSMAPI:CancelFrame("shoppingRestartSniper")
|
||||
TSMAPI.AuctionScan:StopScan()
|
||||
private.searchItem = nil
|
||||
private.isLastPageScan = isLastPageScan
|
||||
private.callback = callback
|
||||
wipe(private.auctions)
|
||||
if private.isLastPageScan then
|
||||
private.searchFrame.statusBar:SetStatusText("Scanning last page...")
|
||||
else
|
||||
private.searchFrame.statusBar:SetStatusText(L["Preparing filters..."])
|
||||
end
|
||||
private.searchFrame.rt:SetData({})
|
||||
private.searchFrame.rt:SetDisabled(true)
|
||||
private.searchFrame.statusBar:UpdateStatus(0, 0)
|
||||
TSM.moduleAPICallback = nil
|
||||
end
|
||||
|
||||
local scanStatus, pageStatus
|
||||
function private.ScanCallback(event, ...)
|
||||
if event == "QUERY_COMPLETE" then
|
||||
private.filterList = ...
|
||||
private.numFilters = #private.filterList
|
||||
private:ScanNextFilter()
|
||||
elseif event == "QUERY_UPDATE" then
|
||||
local arg1, arg2 = ...
|
||||
private:UpdateStatus("query", arg1, arg2)
|
||||
elseif event == "SCAN_PAGE_UPDATE" then
|
||||
private:UpdateStatus("page", ...)
|
||||
elseif event == "SCAN_TIMEOUT" then
|
||||
tremove(private.filterList, 1)
|
||||
private:ScanNextFilter()
|
||||
elseif event == "SCAN_COMPLETE" then
|
||||
if not private.filterList or not private.filterList[1] then return end -- protect against sniper scan starts causing issues
|
||||
local data = ...
|
||||
if private.filterList[1].items then
|
||||
for _, itemString in ipairs(private.filterList[1].items) do
|
||||
if data[itemString] then
|
||||
if data[itemString].isBaseItem then
|
||||
for iString, auctionitem in pairs(data) do
|
||||
if iString ~= itemString and TSMAPI:GetBaseItemString(iString) == itemString then
|
||||
auctionitem.query = private.filterList[1]
|
||||
private:ProcessItem(iString, auctionitem)
|
||||
end
|
||||
end
|
||||
else
|
||||
data[itemString].query = private.filterList[1]
|
||||
private:ProcessItem(itemString, data[itemString])
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for itemString, auctionData in pairs(data) do
|
||||
if not auctionData.isBaseItem then
|
||||
auctionData.query = private.filterList[1]
|
||||
private:ProcessItem(itemString, auctionData)
|
||||
end
|
||||
end
|
||||
end
|
||||
private:UpdateRT()
|
||||
private.searchFrame.rt:ClearSelection()
|
||||
tremove(private.filterList, 1)
|
||||
private:ScanNextFilter()
|
||||
elseif event == "SCAN_LAST_PAGE_COMPLETE" then
|
||||
local data = ...
|
||||
for itemString, auctionData in pairs(data) do
|
||||
if not auctionData.isBaseItem then
|
||||
if auctionData and #auctionData.records > 0 then
|
||||
if private.auctions[itemString] then
|
||||
private.auctions[itemString].shouldCompact = true
|
||||
private.auctions[itemString]:PopulateCompactRecords()
|
||||
local existingRecords = {}
|
||||
for _, record in ipairs(private.auctions[itemString].compactRecords) do
|
||||
local key = strjoin("~", record.uniqueID, record.count, record.buyout, record.minBid, record.timeLeft)
|
||||
existingRecords[key] = true
|
||||
end
|
||||
for _, record in ipairs(auctionData.records) do
|
||||
local key = strjoin("~", record.uniqueID, record.count, record.buyout, record.minBid, record.timeLeft)
|
||||
if not existingRecords[key] then
|
||||
private.auctions[itemString]:AddRecord(record)
|
||||
else
|
||||
for _, record2 in ipairs(private.auctions[itemString].records) do
|
||||
local key2 = strjoin("~", record.uniqueID, record.count, record.buyout, record.minBid, record.timeLeft)
|
||||
if key2 == key and record2.seller ~= "?" then
|
||||
record2.seller = record.seller
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
private.auctions[itemString] = auctionData
|
||||
end
|
||||
private.auctions[itemString] = private.callback("process", itemString, private.auctions[itemString])
|
||||
end
|
||||
end
|
||||
end
|
||||
private:UpdateRT()
|
||||
private.searchFrame.rt:ClearSelection()
|
||||
TSMAPI:CreateTimeDelay("shoppingRestartSniper", 0, function() TSMAPI.AuctionScan:ScanLastPage(private.ScanCallback) end)
|
||||
end
|
||||
end
|
||||
|
||||
function private:ScanNextFilter()
|
||||
if #private.filterList == 0 then
|
||||
return private:ScanComplete()
|
||||
end
|
||||
pageStatus = {0, 1}
|
||||
private:UpdateStatus("scan", private.numFilters-#private.filterList+1, private.numFilters)
|
||||
TSMAPI.AuctionScan:RunQuery(private.filterList[1], private.ScanCallback, true, private.callback("filter", private.filterList[1]), true)
|
||||
end
|
||||
|
||||
function private:UpdateStatus(statusType, ...)
|
||||
if statusType == "query" then
|
||||
private.searchFrame.statusBar:SetStatusText(format(L["Preparing Filter %d / %d"], ...))
|
||||
private.searchFrame.statusBar:UpdateStatus(0, 0)
|
||||
else
|
||||
if statusType == "scan" then
|
||||
scanStatus = {...}
|
||||
elseif statusType == "page" then
|
||||
pageStatus = {...}
|
||||
end
|
||||
private.searchFrame.statusBar:SetStatusText(format(L["Scanning %d / %d (Page %d / %d)"], scanStatus[1], scanStatus[2], pageStatus[1]+1, pageStatus[2]))
|
||||
private.searchFrame.statusBar:UpdateStatus(100*(scanStatus[1]-1)/scanStatus[2], 100*pageStatus[1]/pageStatus[2])
|
||||
end
|
||||
end
|
||||
|
||||
function private:ScanComplete()
|
||||
if not private.callback then return end
|
||||
private.searchFrame.statusBar:SetStatusText(L["Done Scanning"])
|
||||
private.searchFrame.statusBar:UpdateStatus(100, 100)
|
||||
private.searchFrame.rt:SetDisabled(false)
|
||||
if #private.searchFrame.rt.auctionData == 1 then
|
||||
private.searchFrame.rt:SetExpanded(private.searchFrame.rt.auctionData[1]:GetItemString(), true)
|
||||
private.searchFrame.rt.rows[1].cols[1]:Click()
|
||||
elseif #private.searchFrame.rt.auctionData == 0 and private.searchItem and private:HasInBags(TSMAPI:GetBaseItemString(private.searchItem)) then
|
||||
private.controlButtons.post:Enable()
|
||||
local postPrice = TSM:GetMaxPrice(TSM.db.global.normalPostPrice, private.searchItem) or 0
|
||||
TSMAPI.AuctionControl:SetNoResultItem(private.searchItem, postPrice)
|
||||
end
|
||||
|
||||
if #private.searchFrame.rt.auctionData == 0 and TSM.moduleAPICallback then
|
||||
TSM.moduleAPICallback()
|
||||
end
|
||||
private.callback("done", private.auctions)
|
||||
TSMAPI:FireEvent("SHOPPING:SEARCH:SCANDONE", #private.searchFrame.rt.auctionData)
|
||||
end
|
||||
|
||||
-- processes scan data for a specific item
|
||||
function private:ProcessItem(itemString, auctionItem)
|
||||
-- make sure we haven't already scanned this item (possible with common search terms)
|
||||
if private.auctions[itemString] then return end
|
||||
if not itemString or not auctionItem then return end
|
||||
local query = auctionItem.query
|
||||
query.minILevel = query.minILevel or 0
|
||||
query.maxILevel = query.maxILevel or 0
|
||||
query.minLevel = query.minLevel or 0
|
||||
query.maxLevel = query.maxLevel or 0
|
||||
local name, _, _, ilvl, lvl = TSMAPI:GetSafeItemInfo(itemString)
|
||||
|
||||
-- check if this item is outside our level or ilvl filters
|
||||
if query.minILevel > 0 and (ilvl < query.minILevel or (query.maxILevel > 0 and ilvl > query.maxILevel)) then
|
||||
private.auctions[itemString] = nil
|
||||
return
|
||||
end
|
||||
if query.minLevel > 0 and (lvl < query.minLevel or (query.maxLevel > 0 and lvl > query.maxLevel)) then
|
||||
private.auctions[itemString] = nil
|
||||
return
|
||||
end
|
||||
|
||||
-- check for /exact filter
|
||||
if query.exactOnly and strlower(name) ~= strlower(query.name) then
|
||||
private.auctions[itemString] = nil
|
||||
return
|
||||
end
|
||||
|
||||
-- remove any records that don't have buyouts
|
||||
for i=#auctionItem.records, 1, -1 do
|
||||
local record = auctionItem.records[i]
|
||||
if not record.buyout or record.buyout == 0 then
|
||||
auctionItem:RemoveRecord(i)
|
||||
end
|
||||
end
|
||||
|
||||
-- check if this auctionItem has records left
|
||||
if #auctionItem.records == 0 then return end
|
||||
|
||||
auctionItem = private.callback("process", itemString, auctionItem)
|
||||
if not auctionItem or #auctionItem.records == 0 then return end
|
||||
|
||||
-- store auctionItem
|
||||
auctionItem:PopulateCompactRecords()
|
||||
private.auctions[itemString] = auctionItem
|
||||
end
|
||||
|
||||
function private:UpdateRT()
|
||||
local rtData = {}
|
||||
for _, obj in pairs(private.auctions) do
|
||||
tinsert(rtData, obj)
|
||||
end
|
||||
private.searchFrame.rt:SetData(rtData)
|
||||
end
|
||||
|
||||
function private:RemoveAuction(auction, event, itemString)
|
||||
if private.auctions[itemString] then
|
||||
-- remove this record from the auctionItem
|
||||
for i, record in ipairs(private.auctions[itemString].records) do
|
||||
if record.parent.itemLink == auction.link and record.buyout == auction.buyout and record.count == auction.count and record.seller == auction.seller then
|
||||
private.auctions[itemString]:RemoveRecord(i)
|
||||
if #private.auctions[itemString].records == 0 then
|
||||
private.auctions[itemString] = nil
|
||||
else
|
||||
-- handle max quantities on queries
|
||||
local query = private.auctions[itemString].query
|
||||
if event == "OnBuyout" and query then
|
||||
if private.mode == "normal" and (query.maxQuantity or 0) > 0 then
|
||||
query.maxQuantity = query.maxQuantity - auction.count
|
||||
if TSM.moduleAPICallback then TSM.moduleAPICallback(max(query.maxQuantity, 0), itemString, auction.count) end
|
||||
for item, auctionItem in pairs(private.auctions) do
|
||||
if auctionItem.query and auctionItem.query.maxQuantity and auctionItem.query.maxQuantity <= 0 then
|
||||
private.auctions[item] = nil
|
||||
end
|
||||
end
|
||||
if not private.auctions[itemString] then
|
||||
private.controlButtons.buyout:Disable()
|
||||
TSMAPI.AuctionControl:HideConfirmation()
|
||||
TSM:Printf(L["Maximum quantity purchased for %s."], auction.link)
|
||||
end
|
||||
elseif private.mode == "destroy" and (TSM.Destroying.maxQuantity or 0) > 0 then
|
||||
TSM.Destroying.maxQuantity = TSM.Destroying.maxQuantity - auction.count / auction.destroyingNum
|
||||
if TSM.moduleAPICallback then TSM.moduleAPICallback(max(TSM.Destroying.maxQuantity, 0), itemString, auction.count) end
|
||||
if TSM.Destroying.maxQuantity <= 0 then
|
||||
private.controlButtons.buyout:Disable()
|
||||
TSMAPI.AuctionControl:HideConfirmation()
|
||||
TSM:Printf(L["Maximum quantity purchased for destroy search."])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local baseItemString = TSMAPI:GetBaseItemString(itemString)
|
||||
if baseItemString ~= itemString then
|
||||
return private:RemoveAuction(auction, event, baseItemString)
|
||||
end
|
||||
|
||||
private:UpdateRT()
|
||||
local selected = private.searchFrame.rt:GetSelectedAuction()
|
||||
if not TSMAPI.AuctionControl:IsConfirmationVisible() then
|
||||
-- select the auction that was previously selected
|
||||
if not private.searchFrame.rt:GetSelectedAuction() and selected then
|
||||
-- we bought all of this auction, so select the new first occurace of this item
|
||||
private.searchFrame.rt:SetSelectedAuction(selected.parent:GetItemString())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function private:AddPostedAuction(postInfo)
|
||||
local link = select(2, TSMAPI:GetSafeItemInfo(postInfo.itemString))
|
||||
local texture = select(10, TSMAPI:GetSafeItemInfo(postInfo.itemString))
|
||||
if not private.auctions[postInfo.itemString] then
|
||||
private.auctions[postInfo.itemString] = TSMAPI.AuctionScan:NewAuctionItem()
|
||||
private.auctions[postInfo.itemString]:SetItemLink(link)
|
||||
private.auctions[postInfo.itemString]:SetTexture(texture)
|
||||
end
|
||||
private.auctions[postInfo.itemString]:AddAuctionRecord(postInfo.stackSize, postInfo.bid, 0, postInfo.buyout, 0, nil, UnitName("player"), postInfo.duration)
|
||||
private.auctions[postInfo.itemString]:PopulateCompactRecords()
|
||||
private:UpdateRT()
|
||||
private.searchFrame.rt:SetSelectedAuction()
|
||||
end
|
||||
Reference in New Issue
Block a user