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
+183
View File
@@ -0,0 +1,183 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskillmaster_warehousing --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- This file contains various delay APIs
local TSM = select(2, ...)
local delays = {}
local events = {}
local private = {} -- registers for tracing at the end
-- OnUpdate script handler for delay frames
local function DelayFrameOnUpdate(self, elapsed)
if self.inUse == "repeat" then
self.callback()
elseif self.inUse == "delay" then
self.timeLeft = self.timeLeft - elapsed
if self.timeLeft <= 0 then
if self.repeatDelay then
self.timeLeft = self.repeatDelay
else
TSMAPI:CancelFrame(self)
end
if self.callback then
self.callback()
end
end
end
end
-- Helper function for creating delay frames
local function CreateDelayFrame()
local delay = CreateFrame("Frame")
delay:Hide()
delay:SetScript("OnUpdate", DelayFrameOnUpdate)
return delay
end
--- Creates a time-based delay. The callback function will be called after the specified duration.
-- Use TSMAPI:CancelFrame(label) to cancel delays (usually just used for repetitive delays).
-- @param label An arbitrary label for this delay. If a delay with this label has already been started, the request will be ignored.
-- @param duration How long before the callback should be called. This is generally accuate within 50ms (depending on frame rate).
-- @param callback The function to be called after the duration expires.
-- @param repeatDelay If you want this delay to repeat until canceled, after the initial duration expires, will restart the callback with this duration. Passing nil means no repeating.
-- @return Returns an error message as the second return value on error.
function TSMAPI:CreateTimeDelay(...)
local label, duration, callback, repeatDelay
if type(select(1, ...)) == "number" then
-- use unique string as placeholder label if none specified
label = tostring({})
duration, callback, repeatDelay = ...
else
label, duration, callback, repeatDelay = ...
end
if not label or type(duration) ~= "number" or type(callback) ~= "function" then return nil, "invalid args", label, duration, callback, repeatDelay end
local frameNum
for i, frame in ipairs(delays) do
if frame.label == label then return end
if not frame.inUse then
frameNum = i
end
end
if not frameNum then
-- all the frames are in use, create a new one
tinsert(delays, CreateDelayFrame())
frameNum = #delays
end
local frame = delays[frameNum]
frame.inUse = "delay"
frame.repeatDelay = repeatDelay
frame.label = label
frame.timeLeft = duration
frame.callback = callback
frame:Show()
end
--- The passed callback function will be called once every OnUpdate until canceled via TSMAPI:CancelFrame(label).
-- @param label An arbitrary label for this delay. If a delay with this label has already been started, the request will be ignored.
-- @param callback The function to be called every OnUpdate.
-- @return Returns an error message as the second return value on error.
function TSMAPI:CreateFunctionRepeat(label, callback)
if not label or label == "" or type(callback) ~= "function" then return nil, "invalid args", label, callback end
local frameNum
for i, frame in ipairs(delays) do
if frame.label == label then return end
if not frame.inUse then
frameNum = i
end
end
if not frameNum then
-- all the frames are in use, create a new one
tinsert(delays, CreateDelayFrame())
frameNum = #delays
end
local frame = delays[frameNum]
frame.inUse = "repeat"
frame.label = label
frame.callback = callback
frame:Show()
end
--- Cancels a frame created through TSMAPI:CreateTimeDelay() or TSMAPI:CreateFunctionRepeat().
-- Frames are automatically recycled to avoid memory leaks.
-- @param label The label of the frame you want to cancel.
function TSMAPI:CancelFrame(label)
if label == "" then return end
local delayFrame
if type(label) == "table" then
delayFrame = label
else
for i, frame in ipairs(delays) do
if frame.label == label then
delayFrame = frame
end
end
end
if delayFrame then
delayFrame:Hide()
delayFrame.label = nil
delayFrame.inUse = nil
delayFrame.validate = nil
delayFrame.timeLeft = nil
end
end
local function EventFrameOnUpdate(self)
for event, data in pairs(self.events) do
if data.eventPending and GetTime() > (data.lastCallback + data.bucketTime) then
data.eventPending = nil
data.lastCallback = GetTime()
data.callback()
end
end
end
local function EventFrameOnEvent(self, event)
self.events[event].eventPending = true
end
local function CreateEventFrame()
local event = CreateFrame("Frame")
event:Show()
event:SetScript("OnEvent", EventFrameOnEvent)
event:SetScript("OnUpdate", EventFrameOnUpdate)
event.events = {}
return event
end
function TSMAPI:CreateEventBucket(event, callback, bucketTime)
local eventFrame
for _, frame in ipairs(events) do
if not frame.events[event] then
eventFrame = frame
break
end
end
if not eventFrame then
eventFrame = CreateEventFrame()
tinsert(events, eventFrame)
end
eventFrame:RegisterEvent(event)
eventFrame.events[event] = {callback=callback, bucketTime=bucketTime, lastCallback=0}
end
TSMAPI:CreateTimeDelay(0.1, function()
-- This MUST be at the end for this file since RegisterForTracing uses TSMAPI:CreateTimeDelay() which is defined in this file.
TSMAPI:RegisterForTracing(private, "TradeSkillMaster.Delay_private")
end)
+214
View File
@@ -0,0 +1,214 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskillmaster_warehousing --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- This file contains APIs related to inventory information (bags/bank)
local TSM = select(2, ...)
local private = {}
TSMAPI:RegisterForTracing(private, "TradeSkillMaster.Util_private")
private.bagUpdateCallbacks = {}
private.bankUpdateCallbacks = {}
private.bagState = {}
private.bankState = {}
function private:OnBagUpdate()
local newState = {}
local didChange
for bag, slot, itemString, quantity in TSMAPI:GetBagIterator() do
newState[itemString] = (newState[itemString] or 0) + quantity
if not private.bagState[itemString] then
didChange = true
elseif private.bagState[itemString] then
if private.bagState[itemString] ~= quantity then
didChange = true
end
private.bagState[itemString] = nil
end
end
didChange = didChange or (next(private.bagState) and true)
private.bagState = newState
if didChange then
for _, callback in ipairs(private.bagUpdateCallbacks) do
callback(private.bagState)
end
end
end
function private:OnBankUpdate()
if not private.bankOpened then return end
local newState = {}
local didChange
for bag, slot, itemString, quantity in TSMAPI:GetBankIterator() do
newState[itemString] = (newState[itemString] or 0) + quantity
if not private.bankState[itemString] then
didChange = true
elseif private.bankState[itemString] then
if private.bankState[itemString] ~= quantity then
didChange = true
end
private.bankState[itemString] = nil
end
end
didChange = didChange or (next(private.bankState) and true)
private.bankState = newState
if didChange then
for _, callback in ipairs(private.bankUpdateCallbacks) do
callback(private.bankState)
end
end
end
function TSMAPI:RegisterForBagChange(callback)
assert(type(callback) == "function", format("Expected function, got %s.", type(callback)))
tinsert(private.bagUpdateCallbacks, callback)
end
function TSMAPI:RegisterForBankChange(callback)
assert(type(callback) == "function", format("Expected function, got %s.", type(callback)))
tinsert(private.bankUpdateCallbacks, callback)
end
-- Makes sure this bag is an actual bag and not an ammo, soul shard, etc bag
function private:IsValidBag(bag)
if bag == 0 then return true end
-- family 0 = bag with no type, family 1/2/4 are special bags that can only hold certain types of items
local itemFamily = GetItemFamily(GetInventoryItemLink("player", ContainerIDToInventoryID(bag)))
return itemFamily and (itemFamily == 0 or itemFamily > 4)
end
function TSMAPI:GetBagIterator(autoBaseItems, includeSoulbound)
local bags, b, s = {}, 1, 0
for bag=0, NUM_BAG_SLOTS do
if private:IsValidBag(bag) then
tinsert(bags, bag)
end
end
local iter
iter = function()
if bags[b] then
if s < GetContainerNumSlots(bags[b]) then
s = s + 1
else
s = 1
b = b + 1
if not bags[b] then return end
end
local link = GetContainerItemLink(bags[b], s)
if not link then
-- no item here, try the next slot
return iter()
end
local itemString
if autoBaseItems then
itemString = TSMAPI:GetBaseItemString(link, true)
else
itemString = TSMAPI:GetItemString(link)
end
if not itemString then
-- ignore invalid item
return iter()
end
if not includeSoulbound and TSMAPI:IsSoulbound(bags[b], s) then
-- ignore soulbound item
return iter()
end
local _, quantity, locked = GetContainerItemInfo(bags[b], s)
return bags[b], s, itemString, quantity, locked
end
end
return iter
end
function TSMAPI:GetBankIterator(autoBaseItems, includeSoulbound)
local bags, b, s = {}, 1, 0
tinsert(bags, -1)
for bag=NUM_BAG_SLOTS+1, NUM_BAG_SLOTS+NUM_BANKBAGSLOTS do
if private:IsValidBag(bag) then
tinsert(bags, bag)
end
end
local iter
iter = function()
if bags[b] then
if s < GetContainerNumSlots(bags[b]) then
s = s + 1
else
s = 1
b = b + 1
if not bags[b] then return end
end
local link = GetContainerItemLink(bags[b], s)
local itemString
if autoBaseItems then
itemString = TSMAPI:GetBaseItemString(link, true)
else
itemString = TSMAPI:GetItemString(link)
end
if not itemString or (not includeSoulbound and TSMAPI:IsSoulbound(bags[b], s)) then
return iter()
else
local _, quantity, locked = GetContainerItemInfo(bags[b], s)
return bags[b], s, itemString, quantity, locked
end
end
end
return iter
end
function TSMAPI:ItemWillGoInBag(link, bag)
if not link or not bag then return end
if bag == 0 then return true end
local itemFamily = GetItemFamily(link)
local bagFamily = GetItemFamily(GetBagName(bag))
if not bagFamily then return end
return bagFamily == 0 or bit.band(itemFamily, bagFamily) > 0
end
do
local BUCKET_TIME = 0.5
local function EventHandler(event, bag)
if event == "BANKFRAME_OPENED" then
private.bankOpened = true
elseif event == "BANKFRAME_CLOSED" then
private.bankOpened = nil
end
if event == "BAG_UPDATE" then
if bag > NUM_BAG_SLOTS then
TSMAPI:CreateTimeDelay("bankStateUpdate", BUCKET_TIME, private.OnBankUpdate)
else
TSMAPI:CreateTimeDelay("bagStateUpdate", BUCKET_TIME, private.OnBagUpdate)
end
elseif event == "PLAYER_ENTERING_WORLD" then
TSMAPI:CreateTimeDelay("bagStateUpdate", BUCKET_TIME, private.OnBagUpdate)
TSMAPI:CreateTimeDelay("bankStateUpdate", BUCKET_TIME, private.OnBankUpdate)
elseif event == "BANKFRAME_OPENED" or event == "PLAYERBANKSLOTS_CHANGED" then
TSMAPI:CreateTimeDelay("bankStateUpdate", BUCKET_TIME, private.OnBankUpdate)
end
end
TSM.RegisterEvent(private, "BAG_UPDATE", EventHandler)
TSM.RegisterEvent(private, "BANKFRAME_OPENED", EventHandler)
TSM.RegisterEvent(private, "BANKFRAME_CLOSED", EventHandler)
TSM.RegisterEvent(private, "PLAYER_ENTERING_WORLD", EventHandler)
TSM.RegisterEvent(private, "PLAYERBANKSLOTS_CHANGED", EventHandler)
end
+199
View File
@@ -0,0 +1,199 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskillmaster_warehousing --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- This file contains APIs related to items (itemLinks/itemStrings/etc)
local TSM = select(2, ...)
function TSMAPI:SafeTooltipLink(link)
-- if strmatch(link, "battlepet") then
-- local _, speciesID, level, breedQuality, maxHealth, power, speed, battlePetID = strsplit(":", link)
-- BattlePetToolTip_Show(tonumber(speciesID), tonumber(level), tonumber(breedQuality), tonumber(maxHealth), tonumber(power), tonumber(speed), gsub(gsub(link, "^(.*)%[", ""), "%](.*)$", ""))
-- else
GameTooltip:SetHyperlink(link)
-- end
end
function TSMAPI:GetItemString(item)
if type(item) == "string" then
item = item:trim()
end
if type(item) ~= "string" and type(item) ~= "number" then
return nil, "invalid arg type"
end
item = select(2, TSMAPI:GetSafeItemInfo(item)) or item
if tonumber(item) then
return "item:"..item..":0:0:0:0:0:0"
end
local itemInfo = {strfind(item, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?")}
if not itemInfo[11] then return nil, "invalid link" end
itemInfo[11] = tonumber(itemInfo[11]) or 0
if itemInfo[4] == "item" then
for i=6, 10 do itemInfo[i] = 0 end
return table.concat(itemInfo, ":", 4, 11)
else
return table.concat(itemInfo, ":", 4, 7)
end
end
function TSMAPI:GetBaseItemString(itemString, doGroupLookup)
if type(itemString) ~= "string" then return end
if strsub(itemString, 1, 2) == "|c" then
-- this is an itemLink so get the itemString first
itemString = TSMAPI:GetItemString(itemString)
if not itemString then return end
end
local parts = {(":"):split(itemString)}
for i=3, #parts do
parts[i] = 0
end
local baseItemString = table.concat(parts, ":")
if not doGroupLookup then return baseItemString end
if TSM.db.profile.items[itemString] and TSM.db.profile.items[baseItemString] then
return itemString
elseif TSM.db.profile.items[baseItemString] then
return baseItemString
else
return itemString
end
end
local itemInfoCache = {}
local PET_CAGE_ITEM_INFO = {isDefault=true, 0, "Battle Pets", "", 1, "", "", 0}
function TSMAPI:GetSafeItemInfo(link)
if type(link) ~= "string" then return end
if not itemInfoCache[link] then
-- if strmatch(link, "battlepet:") then
-- local _, speciesID, level, quality, health, power, speed, petID = strsplit(":", link)
-- if not tonumber(speciesID) then return end
-- level, quality, health, power, speed, petID = level or 0, quality or 0, health or 0, power or 0, speed or 0, petID or "0"
-- local name, texture = C_PetJournal.GetPetInfoBySpeciesID(tonumber(speciesID))
-- if name == "" then return end
-- level, quality = tonumber(level), tonumber(quality)
-- petID = strsub(petID, 1, (strfind(petID, "|") or #petID)-1)
-- link = ITEM_QUALITY_COLORS[quality].hex.."|Hbattlepet:"..speciesID..":"..level..":"..quality..":"..health..":"..power..":"..speed..":"..petID.."|h["..name.."]|h|r"
-- if PET_CAGE_ITEM_INFO.isDefault then
-- local data = {select(5, GetItemInfo(82800))}
-- if #data > 0 then
-- PET_CAGE_ITEM_INFO = data
-- end
-- end
-- local minLvl, iType, _, stackSize, _, _, vendorPrice = unpack(PET_CAGE_ITEM_INFO)
-- local subType, equipLoc = 0, ""
-- itemInfoCache[link] = {name, link, quality, level, minLvl, iType, subType, stackSize, equipLoc, texture, vendorPrice}
-- elseif strmatch(link, "item:") then
if strmatch(link, "item:") then
itemInfoCache[link] = {GetItemInfo(link)}
end
if itemInfoCache[link] and #itemInfoCache[link] == 0 then itemInfoCache[link] = nil end
end
if not itemInfoCache[link] then return end
return unpack(itemInfoCache[link])
end
--- Attempts to get the itemID from a given itemLink/itemString.
-- @param itemLink The link or itemString for the item.
-- @param ignoreGemID If true, will not attempt to get the equivalent id for the item (ie for old gems where there are multiple ids for a single item).
-- @return Returns the itemID as the first parameter. On error, will return nil as the first parameter and an error message as the second.
function TSMAPI:GetItemID(itemLink)
if not itemLink or type(itemLink) ~= "string" then return nil, "invalid args" end
local test = select(2, strsplit(":", itemLink))
if not test then return nil, "invalid link" end
local s, e = strfind(test, "[0-9]+")
if not (s and e) then return nil, "not an itemLink" end
local itemID = tonumber(strsub(test, s, e))
if not itemID then return nil, "invalid number" end
return itemID
end
-- check if an item is soulbound or not
local function GetTooltipCharges(tooltip)
for id=1, tooltip:NumLines() do
local text = _G["TSMSoulboundScanTooltipTextLeft" .. id]
if text and text:GetText() then
local maxCharges = strmatch(text:GetText(), "^([0-9]+) Charges?$")
if maxCharges then
return maxCharges
end
end
end
end
local scanTooltip
local resultsCache = {}
function TSMAPI:IsSoulbound(bag, slot)
if not scanTooltip then
scanTooltip = CreateFrame("GameTooltip", "TSMSoulboundScanTooltip", UIParent, "GameTooltipTemplate")
scanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
end
scanTooltip:ClearLines()
local slotID, link
if type(bag) == "string" then
-- if strfind(bag, "battlepet") then return end
slotID = bag
scanTooltip:SetHyperlink(slotID)
elseif bag and slot then
slotID = bag.."@"..slot
link = GetContainerItemLink(bag, slot)
if resultsCache[slotID] then
if resultsCache[slotID].link and resultsCache[slotID].link == link then
return resultsCache[slotID].soulbound
elseif not resultsCache[slotID].link and (GetTime() - (resultsCache[slotID].lastUpdate or 0)) < 0.5 then
return resultsCache[slotID].soulbound
end
end
local itemID = GetContainerItemID(bag, slot)
local maxCharges
if itemID then
-- scanTooltip:SetItemByID(itemID)
scanTooltip:SetHyperlink("item:"..itemID)
maxCharges = GetTooltipCharges(scanTooltip)
end
scanTooltip:SetBagItem(bag, slot)
if maxCharges then
if GetTooltipCharges(scanTooltip) ~= maxCharges then
resultsCache[slotID] = {soulbound=true}
return resultsCache[slotID].soulbound
end
end
else
return
end
if resultsCache[slotID] then
if resultsCache[slotID].link and resultsCache[slotID].link == link then
return resultsCache[slotID].soulbound
elseif not resultsCache[slotID].link and (GetTime() - (resultsCache[slotID].lastUpdate or 0)) < 0.5 then
return resultsCache[slotID].soulbound
end
end
resultsCache[slotID] = {soulbound=false, link=link}
for id=1, scanTooltip:NumLines() do
local text = _G["TSMSoulboundScanTooltipTextLeft" .. id]
text = text and text:GetText()
if text and ((text == ITEM_BIND_ON_PICKUP and id < 4) or text == ITEM_SOULBOUND or text == ITEM_BIND_QUEST) then
resultsCache[slotID] = {soulbound=true}
break
end
end
resultsCache[slotID].lastUpdate = GetTime()
return resultsCache[slotID].soulbound
end
+232
View File
@@ -0,0 +1,232 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskillmaster_warehousing --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- This file contains various money APIs
local TSM = select(2, ...)
TSM.GOLD_TEXT = "|cffffd700g|r"
TSM.SILVER_TEXT = "|cffc7c7cfs|r"
TSM.COPPER_TEXT = "|cffeda55fc|r"
local private = {}
TSMAPI:RegisterForTracing(private, "TradeSkillMaster.Money_private")
local GOLD_ICON = "|TInterface\\MoneyFrame\\UI-GoldIcon:0|t"
local SILVER_ICON = "|TInterface\\MoneyFrame\\UI-SilverIcon:0|t"
local COPPER_ICON = "|TInterface\\MoneyFrame\\UI-CopperIcon:0|t"
function private:PadNumber(num, pad)
if num < 10 and pad then
return format("%02d", num)
end
return tostring(num)
end
--- Creates a formatted money string from a copper value.
-- @param money The money value in copper.
-- @param color The color to make the money text (minus the 'g'/'s'/'c'). If nil, will not add any extra color formatting.
-- @param pad If true, the formatted string will be left padded.
-- @param trim If true, will remove any 0 valued tokens. For example, "1g" instead of "1g0s0c". If money is zero, will return "0c".
-- @param disabled If true, the g/s/c text will not be colored.
-- @return Returns the formatted money text according to the parameters.
function TSMAPI:FormatTextMoney(money, color, pad, trim, disabled)
local money = tonumber(money)
if not money then return end
local isNegative = money < 0
money = abs(money)
local gold = floor(money / COPPER_PER_GOLD)
local silver = floor((money - (gold * COPPER_PER_GOLD)) / COPPER_PER_SILVER)
local copper = floor(money%COPPER_PER_SILVER)
local text = ""
local isFirst = true
-- Trims 0 silver and/or 0 copper from the text
if trim then
if gold > 0 then
if color then
text = format("%s%s ", color..private:PadNumber(gold, pad and not isFirst).."|r", disabled and "g" or TSM.GOLD_TEXT)
else
text = format("%s%s ", private:PadNumber(gold, pad and not isFirst), disabled and "g" or TSM.GOLD_TEXT)
end
isFirst = false
end
if silver > 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(silver, pad and not isFirst).."|r", disabled and "s" or TSM.SILVER_TEXT)
else
text = format("%s%s%s ", text, private:PadNumber(silver, pad and not isFirst), disabled and "s" or TSM.SILVER_TEXT)
end
isFirst = false
end
if copper > 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(copper, pad and not isFirst).."|r", disabled and "c" or TSM.COPPER_TEXT)
else
text = format("%s%s%s ", text, private:PadNumber(copper, pad and not isFirst), disabled and "c" or TSM.COPPER_TEXT)
end
isFirst = false
end
if money == 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(copper, pad and not isFirst).."|r", disabled and "c" or TSM.COPPER_TEXT)
else
text = format("%s%s%s ", text, private:PadNumber(copper, pad and not isFirst), disabled and "c" or TSM.COPPER_TEXT)
end
isFirst = false
end
else
-- Add gold
if gold > 0 then
if color then
text = format("%s%s ", color..private:PadNumber(gold, pad and not isFirst).."|r", disabled and "g" or TSM.GOLD_TEXT)
else
text = format("%s%s ", private:PadNumber(gold, pad and not isFirst), disabled and "g" or TSM.GOLD_TEXT)
end
isFirst = false
end
-- Add silver
if gold > 0 or silver > 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(silver, pad and not isFirst).."|r", disabled and "s" or TSM.SILVER_TEXT)
else
text = format("%s%s%s ", text, private:PadNumber(silver, pad and not isFirst), disabled and "s" or TSM.SILVER_TEXT)
end
isFirst = false
end
-- Add copper
if color then
text = format("%s%s%s ", text, color..private:PadNumber(copper, pad and not isFirst).."|r", disabled and "c" or TSM.COPPER_TEXT)
else
text = format("%s%s%s ", text, private:PadNumber(copper, pad and not isFirst), disabled and "c" or TSM.COPPER_TEXT)
end
end
if isNegative then
if color then
return color .. "-|r" .. text:trim()
else
return "-" .. text:trim()
end
else
return text:trim()
end
end
--- Creates a formatted money string from a copper value and uses coin icon.
-- @param money The money value in copper.
-- @param color The color to make the money text (minus the coin icons). If nil, will not add any extra color formatting.
-- @param pad If true, the formatted string will be left padded.
-- @param trim If true, will not remove any 0 valued tokens. For example, "1g" instead of "1g0s0c". If money is zero, will return "0c".
-- @return Returns the formatted money text according to the parameters.
function TSMAPI:FormatTextMoneyIcon(money, color, pad, trim)
local money = tonumber(money)
if not money then return end
local isNegative = money < 0
money = abs(money)
local gold = floor(money / COPPER_PER_GOLD)
local silver = floor((money - (gold * COPPER_PER_GOLD)) / COPPER_PER_SILVER)
local copper = floor(money%COPPER_PER_SILVER)
local text = ""
local isFirst = true
-- Trims 0 silver and/or 0 copper from the text
if trim then
if gold > 0 then
if color then
text = format("%s%s ", color..private:PadNumber(gold, pad and not isFirst).."|r", GOLD_ICON)
else
text = format("%s%s ", private:PadNumber(gold, pad and not isFirst), GOLD_ICON)
end
isFirst = false
end
if silver > 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(silver, pad and not isFirst).."|r", SILVER_ICON)
else
text = format("%s%s%s ", text, private:PadNumber(silver, pad and not isFirst), SILVER_ICON)
end
isFirst = false
end
if copper > 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(copper, pad and not isFirst).."|r", COPPER_ICON)
else
text = format("%s%s%s ", text, private:PadNumber(copper, pad and not isFirst), COPPER_ICON)
end
isFirst = false
end
if money == 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(copper, pad and not isFirst).."|r", COPPER_ICON)
else
text = format("%s%s%s ", text, private:PadNumber(copper, pad and not isFirst), COPPER_ICON)
end
isFirst = false
end
else
-- Add gold
if gold > 0 then
if color then
text = format("%s%s ", color..private:PadNumber(gold, pad and not isFirst).."|r", GOLD_ICON)
else
text = format("%s%s ", private:PadNumber(gold, pad and not isFirst), GOLD_ICON)
end
isFirst = false
end
-- Add silver
if gold > 0 or silver > 0 then
if color then
text = format("%s%s%s ", text, color..private:PadNumber(silver, pad and not isFirst).."|r", SILVER_ICON)
else
text = format("%s%s%s ", text, private:PadNumber(silver, pad and not isFirst), SILVER_ICON)
end
isFirst = false
end
-- Add copper
if color then
text = format("%s%s%s ", text, color..private:PadNumber(copper, pad and not isFirst).."|r", COPPER_ICON)
else
text = format("%s%s%s ", text, private:PadNumber(copper, pad and not isFirst), COPPER_ICON)
end
end
if isNegative then
if color then
return color .. "-|r" .. text:trim()
else
return "-" .. text:trim()
end
else
return text:trim()
end
end
-- Converts a formated money string back to the copper value
function TSMAPI:UnformatTextMoney(value)
-- remove any colors
value = gsub(value, "|cff([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])", "")
value = gsub(value, "|r", "")
-- extract gold/silver/copper values
local gold = tonumber(string.match(value, "([0-9]+)g"))
local silver = tonumber(string.match(value, "([0-9]+)s"))
local copper = tonumber(string.match(value, "([0-9]+)c"))
if gold or silver or copper then
-- Convert it all into copper
copper = (copper or 0) + ((gold or 0) * COPPER_PER_GOLD) + ((silver or 0) * COPPER_PER_SILVER)
end
return copper
end
+100
View File
@@ -0,0 +1,100 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskillmaster_warehousing --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- This file contains various utility APIs
local TSM = select(2, ...)
local private = {}
TSMAPI:RegisterForTracing(private, "TradeSkillMaster.Util_private")
--- Shows a popup dialog with the given name and ensures it's visible over the TSM frame by setting the frame strata to TOOLTIP.
-- @param name The name of the static popup dialog to be shown.
function TSMAPI:ShowStaticPopupDialog(name)
StaticPopupDialogs[name].preferredIndex = 3
StaticPopup_Show(name)
for i=1, 100 do
if _G["StaticPopup" .. i] and _G["StaticPopup" .. i].which == name then
_G["StaticPopup" .. i]:SetFrameStrata("TOOLTIP")
break
end
end
end
function TSMAPI:GetCharacters()
return CopyTable(TSM.db.factionrealm.characters)
end
local orig = ChatFrame_OnEvent
function ChatFrame_OnEvent(self, event, ...)
local msg = select(1, ...)
if (event == "CHAT_MSG_SYSTEM") then
if (msg == ERR_AUCTION_STARTED) then -- absorb the Auction Created message
return
end
if (msg == ERR_AUCTION_REMOVED) then -- absorb the Auction Cancelled message
return
end
end
return orig(self, event, ...)
end
-- A more versitile replacement for lua's select() function
-- If a list of indices is passed as the first parameter, only
-- those values will be returned, otherwise, the default select()
-- behavior will be followed.
function private:SelectHelper(positions, ...)
if #positions == 0 then return end
return select(tremove(positions), ...), private:SelectHelper(positions, ...)
end
function TSMAPI:Select(positions, ...)
if type(positions) == "number" then
return select(positions, ...)
elseif type(positions) == "table" then
-- reverse the list and make a copy of it
local newPositions = {}
for i=#positions, 1, -1 do
tinsert(newPositions, positions[i])
end
return private:SelectHelper(newPositions, ...)
else
error(format("Bad argument #1. Expected number or table, got %s", type(positions)))
end
end
-- custom string splitting function that doesn't stack overflow
function TSMAPI:SafeStrSplit(str, sep)
local parts = {}
local s = 1
while true do
local e = strfind(str, sep, s)
if not e then
tinsert(parts, strsub(str, s))
break
end
tinsert(parts, strsub(str, s, e-1))
s = e + 1
end
return parts
end
local MAGIC_CHARACTERS = {'[', ']', '(', ')', '.', '+', '-', '*', '?', '^', '$'}
function TSMAPI:StrEscape(str)
str = gsub(str, "%%", "\001")
for _, char in ipairs(MAGIC_CHARACTERS) do
str = gsub(str, "%"..char, "%%"..char)
end
str = gsub(str, "\001", "%%%%")
return str
end
function TSMAPI:IsPlayer(target)
return strlower(target) == strlower(UnitName("player")) or (strfind(target, "-") and strlower(target) == strlower(UnitName("player").."-"..GetRealmName()))
end