Add Vanilla compatibility layer and installation guide
This commit is contained in:
+567
@@ -0,0 +1,567 @@
|
||||
-- Compat.lua: bridges the WoW 3.3 / Lua 5.1 constructs used by Auctionator 2.6.2 to the 1.12 client
|
||||
-- (Lua 5.0, vanilla auction API). Loaded first. Everything here is prefixed Atr_ unless noted.
|
||||
|
||||
AtrNS = AtrNS or {}
|
||||
|
||||
local G = getfenv(0)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- small language helpers
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- strsplit(delim, str): pieces as multiple return values; delim is matched literally
|
||||
function Atr_strsplit(delim, str, pieces)
|
||||
if str == nil then return nil end
|
||||
local t, pos = {}, 1
|
||||
while true do
|
||||
local s, e = string.find(str, delim, pos, true)
|
||||
if (not s) or (pieces and getn(t) >= pieces - 1) then
|
||||
tinsert(t, string.sub(str, pos))
|
||||
break
|
||||
end
|
||||
tinsert(t, string.sub(str, pos, s - 1))
|
||||
pos = e + 1
|
||||
end
|
||||
return unpack(t)
|
||||
end
|
||||
|
||||
-- Atr_hooksecurefunc(table, "Method", fn) / Atr_hooksecurefunc("Global", fn): runs fn after the original.
|
||||
-- Auctionator always uses its own copy: 1.12 has no hooksecurefunc, and addons loaded earlier define
|
||||
-- incompatible globals (Atlas-CFM's only knows the ("Global", fn) form, so every tooltip hook was a no-op).
|
||||
function Atr_hooksecurefunc(a1, a2, a3)
|
||||
local tbl, name, fn
|
||||
if type(a1) == "string" then
|
||||
tbl, name, fn = G, a1, a2
|
||||
else
|
||||
tbl, name, fn = a1, a2, a3
|
||||
end
|
||||
local orig = tbl[name]
|
||||
if type(orig) ~= "function" then return end
|
||||
tbl[name] = function(p1, p2, p3, p4, p5, p6, p7, p8, p9)
|
||||
local r1, r2, r3, r4 = orig(p1, p2, p3, p4, p5, p6, p7, p8, p9)
|
||||
fn(p1, p2, p3, p4, p5, p6, p7, p8, p9)
|
||||
return r1, r2, r3, r4
|
||||
end
|
||||
end
|
||||
|
||||
-- Lua errors coming from this addon are also echoed to the chat frame (once per message), so they show up
|
||||
-- in screenshots even when the error popup is off. The previous handler still runs.
|
||||
do
|
||||
local seen = {}
|
||||
|
||||
-- errors caught by pcall (tooltip hooks) are reported here, once per message
|
||||
function Atr_ReportError(msg)
|
||||
msg = tostring(msg)
|
||||
if seen[msg] then return end
|
||||
seen[msg] = true
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff3333Auctionator error:|r " .. msg)
|
||||
end
|
||||
end
|
||||
|
||||
local prev = (G.geterrorhandler and geterrorhandler()) or G._ERRORMESSAGE
|
||||
if G.seterrorhandler and prev then
|
||||
seterrorhandler(function(msg)
|
||||
if type(msg) == "string" and string.find(msg, "Auctionator") and not seen[msg] then
|
||||
seen[msg] = true
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff3333Auctionator error:|r " .. msg)
|
||||
end
|
||||
end
|
||||
return prev(msg)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function Atr_GetVersion()
|
||||
return "1.0.0"
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- item info (3.x layout: name, link, rarity, ilevel, minLevel, type, subType, stack, equipLoc, texture, sellPrice)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local linkByName = {} -- lower(name) -> item link, filled from everything we see
|
||||
|
||||
function Atr_RememberItemLink(name, link)
|
||||
if name and link then linkByName[string.lower(name)] = link end
|
||||
end
|
||||
|
||||
local function ItemIdOf(x)
|
||||
if type(x) == "number" then return x end
|
||||
if type(x) ~= "string" then return nil end
|
||||
local _, _, id = string.find(x, "item:(%d+)")
|
||||
if id then return tonumber(id) end
|
||||
local l = linkByName[string.lower(x)]
|
||||
if l then
|
||||
local _, _, id2 = string.find(l, "item:(%d+)")
|
||||
if id2 then return tonumber(id2) end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Atr_ItemIdFromAnything(x)
|
||||
return ItemIdOf(x)
|
||||
end
|
||||
|
||||
function Atr_GetSellValueById(id)
|
||||
if id and G.SellValues then
|
||||
local v = G.SellValues["item:" .. id]
|
||||
if v then return v end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Atr_GetItemInfo(x)
|
||||
local id = ItemIdOf(x)
|
||||
if not id then return nil end
|
||||
local a, b, c, d, e, f, g, h, i, j = GetItemInfo("item:" .. id .. ":0:0:0")
|
||||
if not a then return nil end
|
||||
local name, link, rarity, ilevel, minLevel, itemType, subType, stack, equip, texture
|
||||
if type(e) == "string" then
|
||||
-- 1.12 layout: name, link, rarity, minLevel, type, subType, stack, equipLoc, texture
|
||||
name, link, rarity, minLevel, itemType, subType, stack, equip, texture = a, b, c, d, e, f, g, h, i
|
||||
else
|
||||
-- 2.x+ layout (extended clients)
|
||||
name, link, rarity, ilevel, minLevel, itemType, subType, stack, equip, texture = a, b, c, d, e, f, g, h, i, j
|
||||
end
|
||||
if link then Atr_RememberItemLink(name, link) end
|
||||
return name, link, rarity, ilevel, minLevel, itemType, subType, stack, equip, texture, Atr_GetSellValueById(id)
|
||||
end
|
||||
|
||||
function Atr_GetItemIcon(x)
|
||||
local _, _, _, _, _, _, _, _, _, texture = Atr_GetItemInfo(x)
|
||||
return texture
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- cursor / inventory
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function Atr_CursorIsItem()
|
||||
return CursorHasItem() and true or false
|
||||
end
|
||||
|
||||
local function DropCursorAnywhere()
|
||||
if not CursorHasItem() then return end
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, (GetContainerNumSlots(bag) or 0) do
|
||||
if not GetContainerItemLink(bag, slot) then
|
||||
PickupContainerItem(bag, slot)
|
||||
if not CursorHasItem() then return end
|
||||
end
|
||||
end
|
||||
end
|
||||
if G.ClearCursor then ClearCursor() end
|
||||
end
|
||||
Atr_DropCursorAnywhere = DropCursorAnywhere
|
||||
|
||||
local function LinkId(link)
|
||||
if not link then return nil end
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
return id and tonumber(id) or nil
|
||||
end
|
||||
|
||||
-- link of the item currently sitting in the auction sell slot
|
||||
function Atr_SellSlotLink()
|
||||
local name, texture, count, quality, canUse, price, maxStack, link = GetAuctionSellItemInfo()
|
||||
if not name then return nil end
|
||||
if link then
|
||||
Atr_RememberItemLink(name, link)
|
||||
return link, name, count, maxStack, price
|
||||
end
|
||||
local l = linkByName[string.lower(name)]
|
||||
return l, name, count, maxStack, price
|
||||
end
|
||||
|
||||
-- total of an item (by name) in bags; a stack inside the auction slot is counted once
|
||||
function Atr_CountItemInBags(itemName)
|
||||
local total, lockedCounts = 0, {}
|
||||
local lname = itemName and string.lower(itemName)
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, (GetContainerNumSlots(bag) or 0) do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
local _, _, nm = string.find(link, "%[(.-)%]")
|
||||
if nm and string.lower(nm) == lname then
|
||||
local _, count, locked = GetContainerItemInfo(bag, slot)
|
||||
total = total + (count or 1)
|
||||
if locked then lockedCounts[count or 1] = true end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local slotLink, slotName, slotCount = Atr_SellSlotLink()
|
||||
if slotName and string.lower(slotName) == lname and slotCount and not lockedCounts[slotCount] then
|
||||
total = total + slotCount
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- auction house call adapters
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- 1.12 has no getAll; class/subclass/slot indexes of 0 mean "any" and must be nil
|
||||
function Atr_QueryAuctionItems(name, minLevel, maxLevel, invType, itemClass, itemSubclass, page, usable, quality)
|
||||
if minLevel == "" then minLevel = nil end
|
||||
if maxLevel == "" then maxLevel = nil end
|
||||
if invType == 0 then invType = nil end
|
||||
if itemClass == 0 then itemClass = nil end
|
||||
if itemSubclass == 0 then itemSubclass = nil end
|
||||
if usable == 0 then usable = nil end
|
||||
if quality == 0 or quality == -1 then quality = nil end
|
||||
QueryAuctionItems(name or "", minLevel, maxLevel, invType, itemClass, itemSubclass, page or 0, usable, quality)
|
||||
end
|
||||
|
||||
function Atr_CanSendAuctionQuery()
|
||||
local can = CanSendAuctionQuery()
|
||||
return can, false
|
||||
end
|
||||
|
||||
-- durations: 1,2,3 as Auctionator uses them -> minutes understood by StartAuction on this server
|
||||
AtrNS.durationMinutes = { 120, 480, 1440 }
|
||||
AtrNS.durationText = { "6 hours", "24 hours", "72 hours" }
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- multi stack posting (the 3.3 client did this in StartAuction itself)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local post = nil
|
||||
local driver = CreateFrame("Frame", "AtrCompatDriver")
|
||||
local acc = 0
|
||||
|
||||
local function FindStack(id, size)
|
||||
local best, bestCount
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, (GetContainerNumSlots(bag) or 0) do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link and LinkId(link) == id then
|
||||
local _, count, locked = GetContainerItemInfo(bag, slot)
|
||||
if count and not locked and count >= size then
|
||||
if count == size then return bag, slot, count end
|
||||
if not bestCount or count < bestCount then
|
||||
best = { bag, slot }
|
||||
bestCount = count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if best then return best[1], best[2], bestCount end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function ClearSlot()
|
||||
if not GetAuctionSellItemInfo() then return end
|
||||
if CursorHasItem() and G.ClearCursor then ClearCursor() end
|
||||
ClickAuctionSellItemButton()
|
||||
DropCursorAnywhere()
|
||||
end
|
||||
|
||||
local function Finish(msg)
|
||||
local p = post
|
||||
post = nil
|
||||
if p and msg and G.Atr_OnAuctionMultiSellFailureMsg then
|
||||
Atr_OnAuctionMultiSellFailureMsg(msg)
|
||||
elseif msg and DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffffAuctionator:|r " .. msg)
|
||||
end
|
||||
ClearSlot()
|
||||
if p and p.multi and p.done < p.n and G.Atr_OnAuctionMultiSellFailure then
|
||||
Atr_OnAuctionMultiSellFailure()
|
||||
end
|
||||
end
|
||||
|
||||
local function Step()
|
||||
local p = post
|
||||
if not p then return end
|
||||
local now = GetTime()
|
||||
if not AtrNS.ahOpen and AuctionFrame and not AuctionFrame:IsVisible() then
|
||||
Finish("Auction house closed, posting stopped.")
|
||||
return
|
||||
end
|
||||
if p.state == "prep" then
|
||||
if now < p.t then return end
|
||||
local link, name, count = Atr_SellSlotLink()
|
||||
if name then
|
||||
if LinkId(link) == p.id and count == p.size then
|
||||
p.state = "ready"
|
||||
return
|
||||
end
|
||||
ClearSlot()
|
||||
p.t = now + 0.4
|
||||
return
|
||||
end
|
||||
local bag, slot, count2 = FindStack(p.id, p.size)
|
||||
if not bag then
|
||||
Finish("Not enough items to finish posting (" .. p.done .. " of " .. p.n .. " posted).")
|
||||
return
|
||||
end
|
||||
if CursorHasItem() and G.ClearCursor then ClearCursor() end
|
||||
if count2 == p.size then
|
||||
PickupContainerItem(bag, slot)
|
||||
else
|
||||
SplitContainerItem(bag, slot, p.size)
|
||||
end
|
||||
ClickAuctionSellItemButton()
|
||||
p.state = "placing"
|
||||
p.t = now
|
||||
elseif p.state == "placing" then
|
||||
local link, name, count = Atr_SellSlotLink()
|
||||
if name and count == p.size then
|
||||
p.state = "ready"
|
||||
elseif now - p.t > 3 then
|
||||
if CursorHasItem() then DropCursorAnywhere() end
|
||||
Finish("Could not place the item in the auction slot (" .. p.done .. " of " .. p.n .. " posted).")
|
||||
end
|
||||
elseif p.state == "ready" then
|
||||
StartAuction(p.bid, p.buyout, p.minutes)
|
||||
p.state = "posting"
|
||||
p.t = now
|
||||
elseif p.state == "posting" then
|
||||
local name = GetAuctionSellItemInfo()
|
||||
if (not name) and now - p.t > 0.3 then
|
||||
p.done = p.done + 1
|
||||
if p.multi and G.Atr_OnAuctionMultiSellUpdate then
|
||||
local sv1, sv2 = G.arg1, G.arg2
|
||||
G.arg1, G.arg2 = p.done, p.n
|
||||
Atr_OnAuctionMultiSellUpdate()
|
||||
G.arg1, G.arg2 = sv1, sv2
|
||||
end
|
||||
if p.done >= p.n then
|
||||
post = nil
|
||||
else
|
||||
p.state = "prep"
|
||||
p.t = now + 0.3
|
||||
end
|
||||
elseif now - p.t > 6 then
|
||||
Finish("The server did not confirm the auction (" .. p.done .. " of " .. p.n .. " posted).")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
driver:SetScript("OnUpdate", function()
|
||||
if not post then return end
|
||||
acc = acc + arg1
|
||||
if acc < 0.1 then return end
|
||||
acc = 0
|
||||
Step()
|
||||
end)
|
||||
|
||||
driver:RegisterEvent("UI_ERROR_MESSAGE")
|
||||
driver:RegisterEvent("AUCTION_HOUSE_CLOSED")
|
||||
driver:SetScript("OnEvent", function()
|
||||
if not post then return end
|
||||
if event == "AUCTION_HOUSE_CLOSED" then
|
||||
post = nil
|
||||
elseif event == "UI_ERROR_MESSAGE" and (post.state == "placing" or post.state == "ready" or post.state == "posting") then
|
||||
Finish("Posting stopped: " .. tostring(arg1))
|
||||
end
|
||||
end)
|
||||
|
||||
function Atr_PostingInProgress()
|
||||
return post ~= nil
|
||||
end
|
||||
|
||||
-- startingBid / buyout are per stack; duration is 1,2,3
|
||||
function Atr_StartAuction(startingBid, buyout, duration, stackSize, numStacks)
|
||||
if post then return end
|
||||
local link, name, count = Atr_SellSlotLink()
|
||||
local id = LinkId(link)
|
||||
stackSize = stackSize or count or 1
|
||||
numStacks = numStacks or 1
|
||||
if not name then return end
|
||||
local minutes = AtrNS.durationMinutes[duration] or duration or 1440
|
||||
if numStacks == 1 and count == stackSize then
|
||||
StartAuction(startingBid, buyout, minutes)
|
||||
return
|
||||
end
|
||||
if not id then
|
||||
StartAuction(startingBid, buyout, minutes)
|
||||
return
|
||||
end
|
||||
post = { id = id, size = stackSize, n = numStacks, done = 0, bid = startingBid, buyout = buyout,
|
||||
minutes = minutes, state = "prep", t = GetTime(), multi = (numStacks > 1) }
|
||||
if post.multi and G.Atr_OnAuctionMultiSellStart then Atr_OnAuctionMultiSellStart() end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- selected row in the lists. The 3.x code locked the button in its PUSHED state; the list buttons have
|
||||
-- no NormalTexture and the 1.12 client never hid the pushed texture again, so every clicked row stayed
|
||||
-- yellow. The rows now carry their own selection texture instead (the XML PushedTextures are removed).
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function Atr_SetRowSelected(row, on)
|
||||
local sel = row.atrSel
|
||||
if not sel then
|
||||
sel = row:CreateTexture(nil, "BACKGROUND")
|
||||
sel:SetTexture("Interface\\HelpFrame\\HelpFrameButton-Highlight")
|
||||
sel:SetAllPoints(row)
|
||||
local name = row:GetName() or ""
|
||||
if string.find(name, "^AuctionatorEntry") then
|
||||
sel:SetTexCoord(0.25, 0.35, 0.0, 0.6)
|
||||
else
|
||||
sel:SetTexCoord(0.15, 0.25, 0.0, 0.6)
|
||||
if sel.SetBlendMode then sel:SetBlendMode("ADD") end
|
||||
end
|
||||
row.atrSel = sel
|
||||
end
|
||||
if on then sel:Show() else sel:Hide() end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Blizzard coins instead of g/s/c letters (1.12 text cannot hold inline textures, so prices use small
|
||||
-- money frames: tooltips, the Stack Price column, the deposit line)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local moneyFrames = 0
|
||||
|
||||
function Atr_CreateMoneyFrame(parent, moneyType)
|
||||
moneyFrames = moneyFrames + 1
|
||||
local f = CreateFrame("Frame", "AtrMoneyFrame" .. moneyFrames, parent, "SmallMoneyFrameTemplate")
|
||||
local saved = G.this
|
||||
G.this = f
|
||||
f.small = 1
|
||||
MoneyFrame_SetType(moneyType or "STATIC")
|
||||
G.this = saved
|
||||
return f
|
||||
end
|
||||
|
||||
function Atr_SetMoney(frame, money)
|
||||
MoneyFrame_Update(frame:GetName(), money or 0)
|
||||
end
|
||||
|
||||
-- tooltips: one pooled money frame per priced line, hidden whenever the tooltip is reused or hidden
|
||||
local function TipHideMoney(tip, resetWidth)
|
||||
if tip.atrMoney then
|
||||
for i = 1, getn(tip.atrMoney) do tip.atrMoney[i]:Hide() end
|
||||
end
|
||||
tip.atrMoneyUsed = 0
|
||||
if resetWidth and tip.atrMinWidth then
|
||||
tip.atrMinWidth = nil
|
||||
tip:SetMinimumWidth(0)
|
||||
end
|
||||
end
|
||||
|
||||
local function TipHook(tip)
|
||||
if tip.atrMoney then return end
|
||||
tip.atrMoney = {}
|
||||
local origHide = tip:GetScript("OnHide")
|
||||
tip:SetScript("OnHide", function()
|
||||
TipHideMoney(tip, true)
|
||||
if origHide then origHide() end
|
||||
end)
|
||||
Atr_hooksecurefunc(tip, "SetOwner", function(t) TipHideMoney(tip, true) end)
|
||||
Atr_hooksecurefunc(tip, "ClearLines", function(t) TipHideMoney(tip, true) end)
|
||||
end
|
||||
|
||||
function Atr_TipBeginMoney(tip)
|
||||
TipHideMoney(tip, false)
|
||||
end
|
||||
|
||||
function Atr_TipAddMoneyLine(tip, label, money)
|
||||
TipHook(tip)
|
||||
tip:AddDoubleLine(label, " ")
|
||||
local n = tip:NumLines()
|
||||
local used = (tip.atrMoneyUsed or 0) + 1
|
||||
tip.atrMoneyUsed = used
|
||||
local mf = tip.atrMoney[used]
|
||||
if not mf then
|
||||
mf = Atr_CreateMoneyFrame(tip, "STATIC")
|
||||
tip.atrMoney[used] = mf
|
||||
end
|
||||
Atr_SetMoney(mf, money)
|
||||
mf:ClearAllPoints()
|
||||
local tname = tip:GetName()
|
||||
local left = getglobal(tname .. "TextLeft" .. n)
|
||||
local right = getglobal(tname .. "TextRight" .. n)
|
||||
if right then
|
||||
mf:SetPoint("RIGHT", right, "RIGHT", 13, 0) -- the coins sit 13px inside the frame's right edge
|
||||
elseif left then
|
||||
mf:SetPoint("LEFT", left, "RIGHT", 8, 0)
|
||||
end
|
||||
mf:Show()
|
||||
local need = (left and left:GetStringWidth() or 80) + mf:GetWidth() + 30
|
||||
if need > (tip.atrMinWidth or 0) then
|
||||
tip.atrMinWidth = need
|
||||
tip:SetMinimumWidth(need)
|
||||
end
|
||||
end
|
||||
|
||||
-- Stack Price column of the auction list rows
|
||||
function Atr_ShowRowStackMoney(row, money)
|
||||
local mf = row.atrStackMoney
|
||||
if not money then
|
||||
if mf then mf:Hide() end
|
||||
return
|
||||
end
|
||||
if not mf then
|
||||
mf = Atr_CreateMoneyFrame(row, "STATIC")
|
||||
mf:SetPoint("RIGHT", row, "LEFT", 573, 0) -- right edge of the 120px column at x=440
|
||||
row.atrStackMoney = mf
|
||||
end
|
||||
Atr_SetMoney(mf, money)
|
||||
mf:Show()
|
||||
end
|
||||
|
||||
-- "Deposit:" line of the Sell tab
|
||||
function Atr_ShowDepositMoney(money, suffix)
|
||||
local mf = AtrNS.depositMoney
|
||||
if not money then
|
||||
if mf then mf:Hide() end
|
||||
return
|
||||
end
|
||||
if not mf then
|
||||
mf = Atr_CreateMoneyFrame(Atr_Deposit_Text:GetParent(), "STATIC")
|
||||
mf:SetPoint("LEFT", Atr_Deposit_Text, "RIGHT", 2, 0)
|
||||
local fs = mf:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||
fs:SetPoint("LEFT", mf, "RIGHT", -8, 0)
|
||||
mf.atrSuffix = fs
|
||||
AtrNS.depositMoney = mf
|
||||
end
|
||||
Atr_SetMoney(mf, money)
|
||||
mf.atrSuffix:SetText(suffix or "")
|
||||
mf:Show()
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- odds and ends the 3.x code takes for granted
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function Atr_ItemStackSize(link)
|
||||
if not link then return 0 end
|
||||
local _, _, _, _, _, _, _, stack = Atr_GetItemInfo(link)
|
||||
return stack or 0
|
||||
end
|
||||
|
||||
-- no sort-clear call on 1.12; Auctionator only used it to start from a known state
|
||||
function Atr_SortAuctionClearSort(kind)
|
||||
end
|
||||
|
||||
-- the stock helper returns nil until the first scroll
|
||||
do
|
||||
local origGetOffset = G.FauxScrollFrame_GetOffset
|
||||
if origGetOffset then
|
||||
function FauxScrollFrame_GetOffset(frame)
|
||||
return origGetOffset(frame) or 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not G.ClearCursor then
|
||||
function ClearCursor()
|
||||
if CursorHasItem() then Atr_DropCursorAnywhere() end
|
||||
end
|
||||
end
|
||||
|
||||
-- addon memory reporting does not exist on 1.12 (only used by /atr mem)
|
||||
if not G.UpdateAddOnMemoryUsage then
|
||||
function UpdateAddOnMemoryUsage() end
|
||||
end
|
||||
if not G.GetAddOnMemoryUsage then
|
||||
function GetAddOnMemoryUsage() return 0 end
|
||||
end
|
||||
if not G.GetAddOnMetadata then
|
||||
function GetAddOnMetadata() return Atr_GetVersion() end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
## Interface: 11200
|
||||
## Title: OctoAuctionator
|
||||
## Version: 1.0.0
|
||||
## Author: John The Baptist (port of Auctionator 2.6.2 by Zirco)
|
||||
## Notes: Auctionator 2.6.2 ported to the 1.12 client: Buy, Sell and More tabs, shopping lists, Full Scan, tooltip prices
|
||||
## OptionalDeps: SellValue
|
||||
## SavedVariablesPerCharacter: AUCTIONATOR_SHOW_ST_PRICE, AUCTIONATOR_ENABLE_ALT, AUCTIONATOR_OPEN_FIRST, AUCTIONATOR_OPEN_BUY, AUCTIONATOR_OPEN_ALL_BAGS, AUCTIONATOR_DEF_DURATION, AUCTIONATOR_SHOW_TIPS, AUCTIONATOR_V_TIPS, AUCTIONATOR_A_TIPS, AUCTIONATOR_D_TIPS, AUCTIONATOR_SHIFT_TIPS, AUCTIONATOR_DE_DETAILS_TIPS, AUCTIONATOR_DEFTAB
|
||||
## SavedVariables: AUCTIONATOR_SAVEDVARS, AUCTIONATOR_PRICING_HISTORY, AUCTIONATOR_SHOPPING_LISTS, AUCTIONATOR_PRICE_DATABASE, AUCTIONATOR_LAST_SCAN_TIME, AUCTIONATOR_TOONS, AUCTIONATOR_STACKING_PREFS, AUCTIONATOR_SCAN_MINLEVEL
|
||||
|
||||
Compat.lua
|
||||
|
||||
Locales\enUS.lua
|
||||
|
||||
zcUtils.lua
|
||||
|
||||
Auctionator.lua
|
||||
AuctionatorShop.lua
|
||||
|
||||
Auctionator.xml
|
||||
|
||||
AuctionatorLocalize.lua
|
||||
AuctionatorPane.lua
|
||||
AuctionatorScan.lua
|
||||
AuctionatorQuery.lua
|
||||
AuctionatorHints.lua
|
||||
AuctionatorVendor.lua
|
||||
AuctionatorConflicts.lua
|
||||
AuctionatorAPI.lua
|
||||
AuctionatorConfig.lua
|
||||
AuctionatorBuy.lua
|
||||
|
||||
AuctionatorConfig.xml
|
||||
|
||||
AuctionatorOptions.lua
|
||||
@@ -1,3 +1,49 @@
|
||||
# OctoAuctionator
|
||||
|
||||
Classic Auctionator 2.6.2 port for OctoWoW 1.18.1. Buy, Sell and More tabs. Made by John The Baptist; original addon by Zirco.
|
||||
# OctoAuctionator 1.0.0
|
||||
|
||||
The classic **Auctionator 2.6.2** auction house (Buy / Sell / More... tabs) ported to **OctoWoW 1.18.1** (1.12.1 client).
|
||||
A free addon.
|
||||
|
||||
**Made by John The Baptist.**
|
||||
|
||||
## What it does
|
||||
|
||||
- **Buy:** type a name and press Search. Results fill in while the pages are still coming in, so you can already pick
|
||||
a row and press Buy (the scan pauses for the purchase and then carries on). Click **Item Price** to flip
|
||||
cheapest-first / most-expensive-first. Recent searches and your own shopping lists sit on the left.
|
||||
- **Sell:** drop an item in the slot and it searches that item, shows the current auctions and recommends a buyout
|
||||
just under the cheapest one. Set the stack size and number of stacks, pick 6 / 24 / 72 hours, Create Auction.
|
||||
- **More...:** your own items: what you have on the AH right now (check for undercuts) and everything you posted before.
|
||||
- **Full Scan:** optional. Scans the whole auction house and stores the lowest prices for the tooltips.
|
||||
- **Tooltips:** auction price of an item (and the vendor price if you use SellValue), shown with the game's own coins.
|
||||
|
||||
**About speed:** the server sends 50 auctions per page and only while the auction window is open; the 1.12 client has
|
||||
no "get all". A normal search is a page or a few; a Full Scan of a big auction house takes a while.
|
||||
|
||||
## Install
|
||||
|
||||
1. Download **OctoAuctionator-1.0.0.zip** from Releases or the forum attachment.
|
||||
2. Extract it into your WoW `Interface/AddOns` folder.
|
||||
3. Restart WoW and enable **OctoAuctionator** at character selection.
|
||||
|
||||
The folder must contain `Interface/AddOns/OctoAuctionator/OctoAuctionator.toc`.
|
||||
Turn off other auction house addons (aux, other Auctionator versions) to avoid two UIs fighting over the window.
|
||||
**SellValue** is optional (vendor prices in tooltips).
|
||||
|
||||
## Usage
|
||||
|
||||
- Open the auction house: the **Buy**, **Sell** and **More...** tabs are next to Browse / Bids / Auctions.
|
||||
- The **Auctionator** button (top right) opens the options; **Full Scan...** starts a full scan.
|
||||
- `/atr clear fullscandb` clears the stored scan prices, `/atr clear posthistory` clears your posting history.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Credits
|
||||
|
||||
Original addon: **Auctionator 2.6.2 by Zirco** (WoWInterface). This version keeps his interface and code and adapts
|
||||
them to the 1.12 client and this server.
|
||||
|
||||
*It's not much, but it's honest work.*
|
||||
|
||||
+857
@@ -0,0 +1,857 @@
|
||||
|
||||
-- Zirco's utilities
|
||||
|
||||
-- This module should contain no globals as it is intended to be "linked" in to each of Zirco's addons
|
||||
|
||||
|
||||
local addonName, addonTable = "Auctionator", AtrNS;
|
||||
local zc = {};
|
||||
|
||||
addonTable.zc = zc;
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.RGBtoHEX (r,g,b)
|
||||
|
||||
local hex = "";
|
||||
|
||||
return string.format ("%02x%02x%02x", r * 255, g * 255, b * 255);
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.EnableDisable (elem, b)
|
||||
|
||||
if (b) then
|
||||
elem:Enable();
|
||||
else
|
||||
elem:Disable();
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.ShowHide (elem, b)
|
||||
|
||||
if (b) then
|
||||
elem:Show();
|
||||
else
|
||||
elem:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.SetTextIf (elem, b, t1, t2)
|
||||
|
||||
if (b) then
|
||||
elem:SetText(t1);
|
||||
else
|
||||
elem:SetText(t2);
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.Val (val, ifNilVal)
|
||||
|
||||
if (val == nil) then
|
||||
return ifNilVal;
|
||||
end
|
||||
|
||||
return val;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.Min (a, b)
|
||||
|
||||
if (a == nil) then
|
||||
return b;
|
||||
end
|
||||
|
||||
if (b == nil) then
|
||||
return a;
|
||||
end
|
||||
|
||||
return math.min (tonumber (a), tonumber (b));
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.Max (a, b)
|
||||
|
||||
if (a == nil) then
|
||||
return b;
|
||||
end
|
||||
|
||||
if (b == nil) then
|
||||
return a;
|
||||
end
|
||||
|
||||
return math.max (tonumber (a), tonumber (b));
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.If (b, x, y)
|
||||
|
||||
if (b ~= nil and b ~= false) then
|
||||
return x;
|
||||
end
|
||||
|
||||
return y;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.PrintKeysSorted (t)
|
||||
|
||||
local ta = {};
|
||||
|
||||
for a,v in pairs (t) do
|
||||
table.insert (ta, a);
|
||||
end
|
||||
|
||||
table.sort (ta, function (a,b) return (string.lower(a) < string.lower(b)); end);
|
||||
|
||||
for x = 1, getn(ta) do
|
||||
zc.msg_pink (x.." "..ta[x]);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.UTF8_Truncate (s, newlen)
|
||||
|
||||
if (string.len (s) <= newlen) then
|
||||
return s;
|
||||
end
|
||||
|
||||
local x, c;
|
||||
|
||||
for x = newlen, 1, -1 do
|
||||
c = string.byte (s, x+1);
|
||||
if (c ~= nil and (c < 128 or c >= 192)) then -- the next byte starts a character, so cut here
|
||||
return string.sub (s, 1, x);
|
||||
end
|
||||
end
|
||||
|
||||
return string.sub (s, 1, newlen);
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.GetArrayElemOrFirst (a, x)
|
||||
|
||||
if (a and getn(a) > 0) then
|
||||
if (x == nil or x < 1 or x > getn(a)) then
|
||||
x = 1;
|
||||
end
|
||||
|
||||
return a[x];
|
||||
end
|
||||
|
||||
return nil;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.GetArrayElemOrNil (a, x)
|
||||
|
||||
if (a and getn(a) > 0) then
|
||||
if (x == nil or x < 1 or x > getn(a)) then
|
||||
return nil;
|
||||
end
|
||||
|
||||
return a[x];
|
||||
end
|
||||
|
||||
return nil;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.padstring (s, n, c)
|
||||
while (string.len (s) < n) do
|
||||
s = c..s;
|
||||
end
|
||||
|
||||
return s;
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
local encTable = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
|
||||
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
|
||||
"0","1","2","3","4","5","6","7","8","9",
|
||||
"-", "_" };
|
||||
|
||||
|
||||
local decTable;
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
local function BuildDecTable()
|
||||
|
||||
if (decTable == nil) then
|
||||
decTable = {};
|
||||
local i;
|
||||
for i = 1,64 do
|
||||
decTable[encTable[i]] = i-1;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.enc64 (n)
|
||||
|
||||
if (n == 0) then
|
||||
return encTable[1];
|
||||
end
|
||||
|
||||
local k = n;
|
||||
local result = "";
|
||||
|
||||
while k > 0 do
|
||||
local x = mod (k, 64);
|
||||
result = encTable[x+1]..result;
|
||||
k = floor (k / 64);
|
||||
end
|
||||
|
||||
return result;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.dec64 (s)
|
||||
|
||||
if (s == nil or s == "") then
|
||||
return 0;
|
||||
end
|
||||
|
||||
BuildDecTable();
|
||||
|
||||
local result = 0;
|
||||
local len = string.len (s);
|
||||
local x;
|
||||
|
||||
for x = 1, len do
|
||||
result = result * 64;
|
||||
result = result + decTable[string.sub(s,x,x)];
|
||||
end
|
||||
|
||||
return result;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function ZF (s)
|
||||
BuildDecTable();
|
||||
|
||||
local s2 = "";
|
||||
local n;
|
||||
|
||||
for n = 1, string.len(s) do
|
||||
local c = string.sub(s, n,n);
|
||||
local x = decTable[c];
|
||||
|
||||
if (x == nil) then
|
||||
s2 = s2..c;
|
||||
else
|
||||
if (x < 32) then x = x + 32;
|
||||
else x = x - 32;
|
||||
end;
|
||||
s2 = s2..encTable[x+1];
|
||||
end
|
||||
end
|
||||
|
||||
return s2;
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.words(str)
|
||||
local t = {}
|
||||
local function helper(word) table.insert(t, word) return "" end
|
||||
local rest = string.gsub (str, "%w+", helper);
|
||||
if (not string.find (rest, "%S")) then
|
||||
if (getn(t) == 1) then return t[1]; end;
|
||||
if (getn(t) == 2) then return t[1],t[2]; end;
|
||||
if (getn(t) == 3) then return t[1],t[2],t[3]; end;
|
||||
if (getn(t) == 4) then return t[1],t[2],t[3],t[4]; end;
|
||||
if (getn(t) == 5) then return t[1],t[2],t[3],t[4],t[5]; end;
|
||||
return t;
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
local gDeferredCalls = {};
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.AddDeferredCall (seconds, funcname, param1, param2, tag) -- tag is optional. if present used to overwrite prior call with same tag
|
||||
|
||||
local now = time();
|
||||
|
||||
local cfdEntry = {};
|
||||
|
||||
cfdEntry.funcname = funcname;
|
||||
cfdEntry.param1 = param1;
|
||||
cfdEntry.param2 = param2;
|
||||
cfdEntry.when = now + seconds;
|
||||
cfdEntry.tag = "";
|
||||
|
||||
if (tag) then
|
||||
cfdEntry.tag = tag;
|
||||
|
||||
for i = 1, getn(gDeferredCalls) do
|
||||
if (gDeferredCalls[i].tag == tag) then
|
||||
gDeferredCalls[i] = cfdEntry; -- overwrite
|
||||
return;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.insert (gDeferredCalls, cfdEntry);
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.CheckDeferredCall ()
|
||||
|
||||
local now = time();
|
||||
local i;
|
||||
|
||||
for i = 1, getn(gDeferredCalls) do
|
||||
if (gDeferredCalls[i].when < now) then
|
||||
local fcn = getglobal(gDeferredCalls[i].funcname);
|
||||
local p1 = gDeferredCalls[i].param1;
|
||||
local p2 = gDeferredCalls[i].param2;
|
||||
table.remove (gDeferredCalls, i);
|
||||
if (type(fcn) == 'function') then
|
||||
fcn(p1, p2);
|
||||
end
|
||||
|
||||
return; -- only do one
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.periodic (elem, name, period, elapsed)
|
||||
|
||||
local t = elem[name] or 0;
|
||||
|
||||
t = t + elapsed;
|
||||
|
||||
if (t > period) then
|
||||
elem[name] = 0;
|
||||
return true;
|
||||
end
|
||||
|
||||
elem[name] = t;
|
||||
return false;
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.tableIsEmpty (t)
|
||||
|
||||
local n, v;
|
||||
for n, v in pairs (t) do
|
||||
return false;
|
||||
end
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.PrintTable (t, indent)
|
||||
|
||||
if (not indent) then
|
||||
indent = 0;
|
||||
end
|
||||
|
||||
local x
|
||||
local padding = "";
|
||||
for x = 1,indent do
|
||||
padding = padding.." ";
|
||||
end
|
||||
|
||||
zc.msg ("-------");
|
||||
|
||||
for n, v in pairs (t) do
|
||||
if (type(v) == "table") then
|
||||
zc.msg (padding..n, "TABLE");
|
||||
zc.PrintTable(v, indent+1);
|
||||
elseif (type(v) == "userdata") then
|
||||
zc.msg (padding..n, "userdata");
|
||||
else
|
||||
zc.msg (padding..n, v);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.ItemIDfromLink (itemLink)
|
||||
|
||||
if (itemLink == nil) then
|
||||
return 0,0,0;
|
||||
end
|
||||
|
||||
-- 1.12 item strings are item:id:enchant:suffix:unique
|
||||
local found, _, itemString = string.find(itemLink, "^|c%x+|H(.+)|h%[.*%]")
|
||||
|
||||
if (itemString == nil) then
|
||||
found, _, itemString = string.find (itemLink, "(item:[%-%d:]+)");
|
||||
end
|
||||
|
||||
if (itemString == nil) then
|
||||
return 0,0,0;
|
||||
end
|
||||
|
||||
local _, itemId, _, suffixId, uniqueId = Atr_strsplit (":", itemString)
|
||||
|
||||
return itemId, suffixId or 0, uniqueId or 0;
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.BoolToString (b)
|
||||
if (b) then
|
||||
return "true";
|
||||
end
|
||||
|
||||
return "false";
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.BoolToNum (b)
|
||||
if (b) then
|
||||
return 1;
|
||||
end
|
||||
|
||||
return 0;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.NumToBool (n)
|
||||
if (n == 0) then
|
||||
return false;
|
||||
end
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.pluralizeIf (word, count)
|
||||
|
||||
if (count and count == 1) then
|
||||
return word;
|
||||
else
|
||||
return zc.pluralize(word);
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.pluralize (word)
|
||||
|
||||
return word.."s";
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.round (v)
|
||||
return math.floor (v + 0.5);
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.msg_red (...) zc.msg_color (1, 0, 0, unpack(arg)); end
|
||||
function zc.msg_pink (...) zc.msg_color (1, .6, .6, unpack(arg)); end
|
||||
function zc.msg_yellow (...) zc.msg_color (1, 1, 0, unpack(arg)); end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.msg_color (r, g, b, ...)
|
||||
|
||||
local options = {};
|
||||
options.r = r;
|
||||
options.g = g;
|
||||
options.b = b;
|
||||
|
||||
zc.msg_ex (options, unpack(arg));
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.msg_str (...)
|
||||
|
||||
local options = {};
|
||||
options.str = true;
|
||||
|
||||
return zc.msg_ex (options, unpack(arg));
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.msg_atr (...)
|
||||
|
||||
zc.msg_yellow ("|cff00ffff<Auctionator>|r", unpack(arg));
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.HSV2RGB (h, s, v)
|
||||
|
||||
local r, g, b;
|
||||
|
||||
local hi = mod (math.floor(h/60), 6);
|
||||
local f = h/60 - math.floor(h/60);
|
||||
local p = v * (1-s);
|
||||
local q = v * (1-(f*s));
|
||||
local t = v * (1-((1-f)*s));
|
||||
|
||||
if (hi == 0) then return v, t, p; end
|
||||
if (hi == 1) then return q, v, p; end
|
||||
if (hi == 2) then return p, v, t; end
|
||||
if (hi == 3) then return p, q, v; end
|
||||
if (hi == 4) then return t, p, v; end
|
||||
if (hi == 5) then return v, p, q; end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.md (...)
|
||||
-- developer trace output: disabled in the 1.12 port
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.msg (...)
|
||||
|
||||
local options = {};
|
||||
|
||||
zc.msg_ex (options, unpack(arg));
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.msg_ex (options, ...)
|
||||
|
||||
if (not DEFAULT_CHAT_FRAME) then
|
||||
return;
|
||||
end
|
||||
|
||||
local msg = "";
|
||||
|
||||
local i;
|
||||
local m;
|
||||
|
||||
for i = 1, arg.n do
|
||||
|
||||
local v = arg[i];
|
||||
|
||||
if (type(v) == "boolean") then m = zc.BoolToString(v);
|
||||
elseif (type(v) == "table") then m = "<table>";
|
||||
elseif (v == nil) then m = "<nil>";
|
||||
else m = v;
|
||||
end
|
||||
|
||||
msg = msg.." "..m;
|
||||
|
||||
end
|
||||
|
||||
if (options.str) then
|
||||
return msg;
|
||||
end
|
||||
|
||||
if (options.r ~= nil) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage (msg, options.r, options.g, options.b);
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage (msg);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.val2gsc (v)
|
||||
local rv = zc.round(v)
|
||||
|
||||
local g = math.floor (rv/10000);
|
||||
|
||||
rv = rv - g*10000;
|
||||
|
||||
local s = math.floor (rv/100);
|
||||
|
||||
rv = rv - s*100;
|
||||
|
||||
local c = rv;
|
||||
|
||||
return g, s, c
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.priceToString (val)
|
||||
|
||||
local gold, silver, copper = zc.val2gsc(val);
|
||||
|
||||
local st = "";
|
||||
|
||||
|
||||
if (gold ~= 0) then
|
||||
st = gold.."g ";
|
||||
end
|
||||
|
||||
|
||||
if (st ~= "") then
|
||||
st = st..format("%02is ", silver);
|
||||
elseif (silver ~= 0) then
|
||||
st = st..silver.."s ";
|
||||
end
|
||||
|
||||
|
||||
if (st ~= "") then
|
||||
st = st..format("%02ic", copper);
|
||||
elseif (copper ~= 0) then
|
||||
st = st..copper.."c";
|
||||
end
|
||||
|
||||
return st;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
local goldicon = "|cffffd100g|r"
|
||||
local silvericon = "|cffc7c7cfs|r"
|
||||
local coppericon = "|cffeda55fc|r"
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.priceToMoneyString (val, noZeroCoppers)
|
||||
|
||||
local gold, silver, copper = zc.val2gsc(val);
|
||||
|
||||
local st = "";
|
||||
|
||||
if (gold ~= 0) then
|
||||
st = gold..goldicon.." ";
|
||||
end
|
||||
|
||||
|
||||
if (st ~= "") then
|
||||
st = st..format("%02i%s ", silver, silvericon);
|
||||
elseif (silver ~= 0) then
|
||||
st = st..silver..silvericon.." ";
|
||||
end
|
||||
|
||||
if (noZeroCoppers and copper == 0) then
|
||||
return st;
|
||||
end
|
||||
|
||||
if (st ~= "") then
|
||||
st = st..format("%02i%s", copper, coppericon);
|
||||
elseif (copper ~= 0) then
|
||||
st = st..copper..coppericon;
|
||||
end
|
||||
|
||||
return st;
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.StringSame (s1, s2)
|
||||
if (s1 == nil and s2 == nil) then
|
||||
return true;
|
||||
end
|
||||
|
||||
if (s1 == nil or s2 == nil) then
|
||||
return false;
|
||||
end
|
||||
|
||||
if (s1 == s2) then -- maybe will fix german umlaut problem?
|
||||
return true;
|
||||
end
|
||||
|
||||
return (string.lower (s1) == string.lower (s2));
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.StringContains (s, sub)
|
||||
if (sub == nil or sub == "") then
|
||||
return false;
|
||||
end
|
||||
|
||||
local start, stop = string.find (string.lower(s), string.lower(sub), 1, true);
|
||||
|
||||
return (start ~= nil);
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.StringEndsWith (s, sub)
|
||||
|
||||
if (sub == nil or sub == "") then
|
||||
return false;
|
||||
end
|
||||
|
||||
local i = string.len(s) - string.len(sub);
|
||||
|
||||
if (i < 0) then
|
||||
return false;
|
||||
end
|
||||
|
||||
local sEnd = string.sub (s, i+1);
|
||||
|
||||
return (string.lower (sEnd) == string.lower (sub));
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.StringStartsWith (s, sub)
|
||||
|
||||
if (s == nil or sub == nil or sub == "") then
|
||||
return false;
|
||||
end
|
||||
|
||||
local sublen = string.len (sub);
|
||||
|
||||
if (string.len (s) < sublen) then
|
||||
return false;
|
||||
end
|
||||
|
||||
return (string.lower (string.sub(s, 1, sublen)) == string.lower(sub));
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.CopyDeep (src)
|
||||
|
||||
local result = {};
|
||||
|
||||
for n, v in pairs (src) do
|
||||
if (type(v) == "table") then
|
||||
result[n] = zc.CopyDeep(v);
|
||||
else
|
||||
result[n] = v;
|
||||
end
|
||||
end
|
||||
|
||||
return result;
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.printableLink (link)
|
||||
|
||||
if (link == nil) then
|
||||
return "nil";
|
||||
end
|
||||
|
||||
local printable = gsub(link, "\124", "\124\124");
|
||||
|
||||
return printable;
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.printmem ()
|
||||
|
||||
local cmem = math.floor(collectgarbage ("count"))
|
||||
|
||||
UpdateAddOnMemoryUsage();
|
||||
local mem = GetAddOnMemoryUsage("OctoAuctionator");
|
||||
zc.msg_atr (math.floor(mem).." KB (total LUA: "..cmem.." KB)");
|
||||
end
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.printstack (options)
|
||||
|
||||
return {}; -- needs debugstack(), which the 1.12 client does not have
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.tallyAdd (ttable, value)
|
||||
|
||||
if (ttable[value]) then
|
||||
ttable[value] = ttable[value] + 1;
|
||||
else
|
||||
ttable[value] = 1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
function zc.tallyPrint (ttable, options)
|
||||
|
||||
local sortedTable = {};
|
||||
local total = 0;
|
||||
|
||||
local n = 1;
|
||||
for value,count in pairs(ttable) do
|
||||
|
||||
sortedTable[n] = {};
|
||||
sortedTable[n].value = value;
|
||||
sortedTable[n].count = count;
|
||||
|
||||
total = total + count;
|
||||
|
||||
n = n + 1;
|
||||
end
|
||||
|
||||
|
||||
if (options.sortByValue and options.sortDesc) then table.sort (sortedTable, function(x,y) return x.value > y.value; end);
|
||||
elseif (options.sortByValue and not options.sortDesc) then table.sort (sortedTable, function(x,y) return x.value < y.value; end);
|
||||
elseif (options.sortDesc) then table.sort (sortedTable, function(x,y) return x.count > y.count; end);
|
||||
else table.sort (sortedTable, function(x,y) return x.count < y.count; end);
|
||||
end
|
||||
|
||||
|
||||
for n = 1, getn(sortedTable) do
|
||||
|
||||
if (not options.printCount or n < options.printCount) then
|
||||
zc.msg_pink (sortedTable[n].count.." "..sortedTable[n].value);
|
||||
end
|
||||
end
|
||||
|
||||
zc.msg_yellow ("Total: "..total);
|
||||
end
|
||||
Reference in New Issue
Block a user