restructuring
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
local m = {}
|
||||
Aux.completion = m
|
||||
|
||||
function m:complete()
|
||||
if IsControlKeyDown() then -- TODO problem is ctrl-v, maybe find a better solution
|
||||
return
|
||||
end
|
||||
|
||||
local filter_string = this:GetText()
|
||||
|
||||
local completed_filter_string = ({strfind(filter_string, '([^;]*)/[^/;]*$')})[3]
|
||||
local _, suggestions = Aux.scan_util.filter_from_string(completed_filter_string or '')
|
||||
|
||||
local start_index, _, current_modifier = strfind(filter_string, '([^/;]*)$')
|
||||
current_modifier = current_modifier or ''
|
||||
|
||||
for _, suggestion in ipairs(suggestions) do
|
||||
if strsub(strupper(suggestion), 1, strlen(current_modifier)) == strupper(current_modifier) then
|
||||
this:SetText(strlower(strsub(filter_string, 1, start_index - 1).. suggestion))
|
||||
this:HighlightText(strlen(filter_string), -1)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function m.completor(options)
|
||||
return function(self)
|
||||
if IsControlKeyDown() then -- TODO problem is ctrl-v, maybe find a better solution
|
||||
return
|
||||
end
|
||||
|
||||
local text = self:GetText()
|
||||
|
||||
for _, item_name in ipairs(options()) do
|
||||
if strsub(strupper(item_name), 1, strlen(text)) == strupper(text) then
|
||||
self:SetText(strlower(item_name))
|
||||
self:HighlightText(strlen(text), -1)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
<Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
|
||||
|
||||
<Script file="completion.lua"/>
|
||||
|
||||
<Frame name="AuxCompletionDropDown" inherits="UIDropDownMenuTemplate" hidden="true">
|
||||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="555" y="0"/></Offset></Anchor></Anchors>
|
||||
</Frame>
|
||||
</Ui>
|
||||
+406
@@ -0,0 +1,406 @@
|
||||
local TOOLTIP_LENGTH = 30
|
||||
|
||||
local private, public = {}, {}
|
||||
Aux.info = public
|
||||
|
||||
function public.inventory_index(slot)
|
||||
local inventory_index_map = {
|
||||
INVTYPE_AMMO = {0},
|
||||
INVTYPE_HEAD = {1},
|
||||
INVTYPE_NECK = {2},
|
||||
INVTYPE_SHOULDER = {3},
|
||||
INVTYPE_BODY = {4},
|
||||
INVTYPE_CHEST = {5},
|
||||
INVTYPE_ROBE = {5},
|
||||
INVTYPE_WAIST = {6},
|
||||
INVTYPE_LEGS = {7},
|
||||
INVTYPE_FEET = {8},
|
||||
INVTYPE_WRIST = {9},
|
||||
INVTYPE_HAND = {10},
|
||||
INVTYPE_FINGER = {11, 12},
|
||||
INVTYPE_TRINKET = {13, 14},
|
||||
INVTYPE_CLOAK = {15},
|
||||
INVTYPE_2HWEAPON = {16, 17},
|
||||
INVTYPE_WEAPONMAINHAND = {16, 17},
|
||||
INVTYPE_WEAPON = {16, 17},
|
||||
INVTYPE_WEAPONOFFHAND = {16, 17},
|
||||
INVTYPE_HOLDABLE = {16, 17},
|
||||
INVTYPE_SHIELD = {16, 17},
|
||||
INVTYPE_RANGED = {18},
|
||||
INVTYPE_RANGEDRIGHT = {18},
|
||||
INVTYPE_TABARD = {19},
|
||||
}
|
||||
|
||||
return unpack(inventory_index_map[slot] or {})
|
||||
end
|
||||
|
||||
function public.container_item(bag, slot)
|
||||
local hyperlink = GetContainerItemLink(bag, slot)
|
||||
|
||||
if not hyperlink then
|
||||
return
|
||||
end
|
||||
|
||||
local item_id, suffix_id, unique_id, enchant_id = public.parse_hyperlink(hyperlink)
|
||||
local item_info = public.item(item_id, suffix_id, unique_id, enchant_id)
|
||||
|
||||
local texture, count, locked, quality, readable, lootable = GetContainerItemInfo(bag, slot) -- quality not working?
|
||||
local tooltip = public.tooltip(function(tt) tt:SetBagItem(bag, slot) end)
|
||||
local max_charges = private.max_item_charges(item_id)
|
||||
local charges = max_charges and private.item_charges(tooltip)
|
||||
local aux_quantity = charges or count
|
||||
|
||||
return {
|
||||
item_id = item_id,
|
||||
suffix_id = suffix_id,
|
||||
unique_id = unique_id,
|
||||
enchant_id = enchant_id,
|
||||
|
||||
hyperlink = hyperlink,
|
||||
itemstring = item_info.itemstring,
|
||||
item_key = item_id..':'..suffix_id,
|
||||
|
||||
name = item_info.name,
|
||||
texture = texture,
|
||||
level = item_info.level,
|
||||
type = item_info.type,
|
||||
subtype = item_info.subtype,
|
||||
slot = item_info.slot,
|
||||
quality = item_info.quality,
|
||||
max_stack = item_info.max_stack,
|
||||
|
||||
count = count,
|
||||
locked = locked,
|
||||
readable = readable,
|
||||
lootable = lootable,
|
||||
|
||||
tooltip = tooltip,
|
||||
max_charges = max_charges,
|
||||
charges = charges,
|
||||
aux_quantity = aux_quantity,
|
||||
}
|
||||
end
|
||||
|
||||
function public.auction_sell_item()
|
||||
local name, texture, count, quality, usable, vendor_price = GetAuctionSellItemInfo()
|
||||
|
||||
if name then
|
||||
|
||||
local unit_vendor_price = vendor_price / count
|
||||
local tooltip = public.tooltip(function(tt) tt:SetAuctionSellItem() end)
|
||||
local charges = private.item_charges(tooltip)
|
||||
local aux_quantity = charges > 1 and charges or count
|
||||
|
||||
return {
|
||||
name = name,
|
||||
texture = texture,
|
||||
quality = quality,
|
||||
stack_size = count,
|
||||
usable = usable,
|
||||
vendor_price = vendor_price,
|
||||
unit_vendor_price = unit_vendor_price,
|
||||
|
||||
tooltip = tooltip,
|
||||
aux_quantity = aux_quantity,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function public.auction(index, query_type)
|
||||
query_type = query_type or 'list'
|
||||
|
||||
local hyperlink = GetAuctionItemLink(query_type, index)
|
||||
|
||||
if not hyperlink then
|
||||
return
|
||||
end
|
||||
|
||||
local item_id, suffix_id, unique_id, enchant_id = public.parse_hyperlink(hyperlink)
|
||||
local item_info = public.item(item_id, suffix_id, unique_id, enchant_id)
|
||||
|
||||
local name, texture, count, quality, usable, level, start_price, min_increment, buyout_price, high_bid, high_bidder, owner, sale_status = GetAuctionItemInfo(query_type, index)
|
||||
|
||||
local duration = GetAuctionItemTimeLeft(query_type, index)
|
||||
local tooltip = public.tooltip(function(tt) tt:SetAuctionItem(query_type, index) end)
|
||||
local max_charges = private.max_item_charges(item_id)
|
||||
local charges = max_charges and private.item_charges(tooltip)
|
||||
local aux_quantity = charges or count
|
||||
local blizzard_bid = high_bid > 0 and high_bid or start_price
|
||||
local bid_price = high_bid > 0 and (high_bid + min_increment) or start_price
|
||||
|
||||
return {
|
||||
item_id = item_id,
|
||||
suffix_id = suffix_id,
|
||||
unique_id = unique_id,
|
||||
enchant_id = enchant_id,
|
||||
|
||||
hyperlink = hyperlink,
|
||||
itemstring = item_info.itemstring,
|
||||
item_key = item_id..':'..suffix_id,
|
||||
search_signature = Aux.util.join({item_id, suffix_id, enchant_id, start_price, buyout_price, bid_price, aux_quantity, duration, query_type == 'owner' and high_bidder or (high_bidder and 1 or 0), aux_ignore_owner and (Aux.is_player(owner) and 0 or 1) or (owner or '?')}, ':'),
|
||||
|
||||
name = name,
|
||||
texture = texture,
|
||||
level = item_info.level,
|
||||
type = item_info.type,
|
||||
subtype = item_info.subtype,
|
||||
slot = item_info.slot,
|
||||
quality = quality,
|
||||
max_stack = item_info.max_stack,
|
||||
|
||||
count = count,
|
||||
start_price = start_price,
|
||||
high_bid = high_bid,
|
||||
min_increment = min_increment,
|
||||
blizzard_bid = blizzard_bid,
|
||||
bid_price = bid_price,
|
||||
buyout_price = buyout_price,
|
||||
unit_blizzard_bid = blizzard_bid / aux_quantity,
|
||||
unit_bid_price = bid_price / aux_quantity,
|
||||
unit_buyout_price = buyout_price / aux_quantity,
|
||||
high_bidder = high_bidder,
|
||||
owner = owner,
|
||||
sale_status = sale_status,
|
||||
duration = duration,
|
||||
usable = usable,
|
||||
|
||||
tooltip = tooltip,
|
||||
max_charges = max_charges,
|
||||
charges = charges,
|
||||
aux_quantity = aux_quantity,
|
||||
}
|
||||
end
|
||||
|
||||
function public.bid_update(auction_record)
|
||||
auction_record.high_bid = auction_record.bid_price
|
||||
auction_record.blizzard_bid = auction_record.bid_price
|
||||
auction_record.min_increment = Aux.min_bid_increment(auction_record.bid_price)
|
||||
auction_record.bid_price = auction_record.bid_price + auction_record.min_increment
|
||||
auction_record.unit_blizzard_bid = auction_record.blizzard_bid / auction_record.aux_quantity
|
||||
auction_record.unit_bid_price = auction_record.bid_price / auction_record.aux_quantity
|
||||
auction_record.high_bidder = 1
|
||||
auction_record.search_signature = Aux.util.join({auction_record.item_id, auction_record.suffix_id, auction_record.enchant_id, auction_record.start_price, auction_record.buyout_price, auction_record.bid_price, auction_record.aux_quantity, auction_record.duration, 1, aux_ignore_owner and (Aux.is_player(auction_record.owner) and 0 or 1) or (auction_record.owner or '?')}, ':')
|
||||
end
|
||||
|
||||
function public.set_tooltip(itemstring, owner, anchor)
|
||||
GameTooltip:SetOwner(owner, anchor)
|
||||
GameTooltip:SetHyperlink(itemstring)
|
||||
end
|
||||
|
||||
function public.set_shopping_tooltip(slot)
|
||||
local index1, index2 = public.inventory_index(slot)
|
||||
|
||||
local tooltips = {}
|
||||
if index1 then
|
||||
local tooltip = public.tooltip(function(tt) tt:SetInventoryItem('player', index1) end)
|
||||
if getn(tooltip) > 0 then
|
||||
tinsert(tooltips, tooltip)
|
||||
end
|
||||
end
|
||||
if index2 then
|
||||
local tooltip = public.tooltip(function(tt) tt:SetInventoryItem('player', index2) end)
|
||||
if getn(tooltip) > 0 then
|
||||
tinsert(tooltips, tooltip)
|
||||
end
|
||||
end
|
||||
|
||||
if tooltips[1] then
|
||||
tinsert(tooltips[1], 1, { left_text = 'Currently Equipped', left_color = { 0.5, 0.5, 0.5 } })
|
||||
|
||||
ShoppingTooltip1:SetOwner(GameTooltip, 'ANCHOR_BOTTOMRIGHT')
|
||||
public.load_tooltip(ShoppingTooltip1, tooltips[1])
|
||||
ShoppingTooltip1:Show()
|
||||
ShoppingTooltip1:SetPoint('TOPLEFT', GameTooltip, 'TOPRIGHT', 0, -10)
|
||||
end
|
||||
|
||||
if tooltips[2] then
|
||||
tinsert(tooltips[2], 1, { left_text = 'Currently Equipped', left_color = { 0.5, 0.5, 0.5 } })
|
||||
|
||||
ShoppingTooltip2:SetOwner(ShoppingTooltip1, 'ANCHOR_BOTTOMRIGHT')
|
||||
public.load_tooltip(ShoppingTooltip2, tooltips[2])
|
||||
ShoppingTooltip2:Show()
|
||||
ShoppingTooltip2:SetPoint('TOPLEFT', ShoppingTooltip1, 'TOPRIGHT')
|
||||
end
|
||||
end
|
||||
|
||||
function public.tooltip_match(entry, tooltip)
|
||||
return Aux.util.any(tooltip, function(line)
|
||||
local left_match = line.left_text and strupper(line.left_text) == strupper(entry)
|
||||
local right_match = line.right_text and strupper(line.right_text) == strupper(entry)
|
||||
return left_match or right_match
|
||||
end)
|
||||
end
|
||||
|
||||
function public.tooltip_find(pattern, tooltip)
|
||||
local count = 0
|
||||
for _, line in ipairs(tooltip) do
|
||||
if line.left_text and strfind(line.left_text, pattern) then
|
||||
count = count + 1
|
||||
end
|
||||
if line.right_text and strfind(line.right_text, pattern) then
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function public.load_tooltip(frame, tooltip)
|
||||
for _, line in ipairs(tooltip) do
|
||||
if line.right_text then
|
||||
frame:AddDoubleLine(line.left_text, line.right_text, line.left_color[1], line.left_color[2], line.left_color[3], line.right_color[1], line.right_color[2], line.right_color[3])
|
||||
else
|
||||
frame:AddLine(line.left_text, line.left_color[1], line.left_color[2], line.left_color[3], true)
|
||||
end
|
||||
end
|
||||
for i = 1,TOOLTIP_LENGTH do -- TODO why is this needed?
|
||||
getglobal(frame:GetName()..'TextLeft'..i):SetJustifyH('LEFT')
|
||||
getglobal(frame:GetName()..'TextRight'..i):SetJustifyH('LEFT')
|
||||
end
|
||||
end
|
||||
|
||||
function public.display_name(item_id, plain, uncolored)
|
||||
local item_info = Aux.info.item(item_id)
|
||||
if item_info then
|
||||
local name = item_info.name
|
||||
if not plain then
|
||||
name = '['..name..']'
|
||||
end
|
||||
if not uncolored then
|
||||
name = ({GetItemQualityColor(item_info.quality)})[4]..name..FONT_COLOR_CODE_CLOSE
|
||||
end
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
function public.auctionable(tooltip, quality, lootable)
|
||||
local durability, max_durability = public.durability(tooltip)
|
||||
return not lootable
|
||||
and (not quality or quality < 6)
|
||||
and not public.tooltip_match(ITEM_BIND_ON_PICKUP, tooltip)
|
||||
and not public.tooltip_match(ITEM_BIND_QUEST, tooltip)
|
||||
and not public.tooltip_match(ITEM_SOULBOUND, tooltip)
|
||||
and (not public.tooltip_match(ITEM_CONJURED, tooltip) or public.tooltip_find(ITEM_MIN_LEVEL, tooltip) > 1)
|
||||
and not (durability and durability < max_durability)
|
||||
end
|
||||
|
||||
function public.tooltip(setter)
|
||||
for i = 1, TOOLTIP_LENGTH do
|
||||
getglobal('AuxTooltipTextLeft'..i):SetText()
|
||||
getglobal('AuxTooltipTextRight'..i):SetText()
|
||||
end
|
||||
|
||||
AuxTooltip:SetOwner(UIParent, 'ANCHOR_NONE')
|
||||
AuxTooltip.money = 0
|
||||
setter(AuxTooltip)
|
||||
AuxTooltip:Show()
|
||||
|
||||
local tooltip = { money=AuxTooltip.money }
|
||||
for i = 1, TOOLTIP_LENGTH do
|
||||
|
||||
local left_text = getglobal('AuxTooltipTextLeft'..i):GetText()
|
||||
local left_color = { getglobal('AuxTooltipTextLeft'..i):GetTextColor() }
|
||||
|
||||
local right_text = getglobal('AuxTooltipTextRight'..i):GetText()
|
||||
local right_color = { getglobal('AuxTooltipTextRight'..i):GetTextColor() }
|
||||
|
||||
if left_text or right_text then
|
||||
tinsert(tooltip, {
|
||||
left_text = left_text,
|
||||
left_color = left_color,
|
||||
right_text = right_text,
|
||||
right_color = right_color,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, TOOLTIP_LENGTH do
|
||||
getglobal('AuxTooltipTextLeft'..i):SetText()
|
||||
getglobal('AuxTooltipTextRight'..i):SetText()
|
||||
end
|
||||
|
||||
return tooltip
|
||||
end
|
||||
|
||||
function private.item_charges(tooltip)
|
||||
for _, line in ipairs(tooltip) do
|
||||
local pattern = '^'..gsub(gsub(ITEM_SPELL_CHARGES_P1, '%%d', '(%%d+)'), '%%%d+%$d', '(%%d+)')..'$'
|
||||
|
||||
local _, _, left_charges_string = strfind(line.left_text or '', pattern)
|
||||
local _, _, right_charges_string = strfind(line.right_text or '', pattern)
|
||||
|
||||
local charges = tonumber(left_charges_string) or tonumber(right_charges_string)
|
||||
if charges then
|
||||
return charges
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function private.max_item_charges(item_id)
|
||||
return ({
|
||||
-- wizard oil
|
||||
[20744] = 5,
|
||||
[20746] = 5,
|
||||
[20750] = 5,
|
||||
[20749] = 5,
|
||||
|
||||
-- mana oil
|
||||
[20745] = 5,
|
||||
[20747] = 5,
|
||||
[20748] = 5,
|
||||
|
||||
-- discombobulator
|
||||
[4388] = 5,
|
||||
|
||||
-- recombobulator
|
||||
[4381] = 10,
|
||||
[18637] = 10,
|
||||
|
||||
-- ... TODO
|
||||
|
||||
})[item_id]
|
||||
end
|
||||
|
||||
function public.durability(tooltip)
|
||||
for _, line in ipairs(tooltip) do
|
||||
local pattern = '^'..gsub(gsub(DURABILITY_TEMPLATE, '%%d', '(%%d+)'), '%%%d+%$d', '(%%d+)')..'$'
|
||||
local _, _, left_durability_string, left_max_durability_string = strfind(line.left_text or '', pattern)
|
||||
local _, _, right_durability_string, right_max_durability_string = strfind(line.right_text or '', pattern)
|
||||
local durability = tonumber(left_durability_string) or tonumber(right_durability_string)
|
||||
local max_durability = tonumber(left_max_durability_string) or tonumber(right_max_durability_string)
|
||||
if durability then
|
||||
return durability, max_durability
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function public.item_key(hyperlink)
|
||||
local item_id, suffix_id = public.parse_hyperlink(hyperlink)
|
||||
return item_id..':'..suffix_id
|
||||
end
|
||||
|
||||
function public.parse_hyperlink(hyperlink)
|
||||
local _, _, item_id, enchant_id, suffix_id, unique_id, name = strfind(hyperlink, '|c%x%x%x%x%x%x%x%x|Hitem:(%d*):(%d*):(%d*):(%d*)[:0-9]*|h%[(.-)%]|h|r')
|
||||
return tonumber(item_id) or 0, tonumber(suffix_id) or 0, tonumber(unique_id) or 0, tonumber(enchant_id) or 0, name
|
||||
end
|
||||
|
||||
function public.itemstring(item_id, suffix_id, unique_id, enchant_id)
|
||||
return 'item:'..(item_id or 0)..':'..(enchant_id or 0)..':'..(suffix_id or 0)..':'..(unique_id or 0)
|
||||
end
|
||||
|
||||
function public.item(item_id, suffix_id)
|
||||
local itemstring = 'item:'..(item_id or 0)..':0:'..(suffix_id or 0)..':0'
|
||||
local name, itemstring, quality, level, class, subclass, max_stack, slot, texture = GetItemInfo(itemstring)
|
||||
return name and {
|
||||
name = name,
|
||||
itemstring = itemstring,
|
||||
quality = quality,
|
||||
level = level,
|
||||
class = class,
|
||||
subclass = subclass,
|
||||
slot = slot,
|
||||
max_stack = max_stack,
|
||||
texture = texture,
|
||||
} or Aux.cache.item_info(item_id)
|
||||
end
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
local m = {}
|
||||
Aux.money = m
|
||||
|
||||
local GOLD_TEXT = '|cffffd70ag|r'
|
||||
local SILVER_TEXT = '|cffc7c7cfs|r'
|
||||
local COPPER_TEXT = '|cffeda55fc|r'
|
||||
|
||||
do
|
||||
local COPPER_PER_SILVER = 100
|
||||
local COPPER_PER_GOLD = 10000
|
||||
|
||||
function m.to_GSC(money)
|
||||
local gold = floor(money / COPPER_PER_GOLD)
|
||||
local silver = floor(mod(money, COPPER_PER_GOLD) / COPPER_PER_SILVER)
|
||||
local copper = mod(money, COPPER_PER_SILVER)
|
||||
return gold, silver, copper
|
||||
end
|
||||
|
||||
function m.from_GSC(gold, silver, copper)
|
||||
return gold * COPPER_PER_GOLD + silver * COPPER_PER_SILVER + copper
|
||||
end
|
||||
end
|
||||
|
||||
function m.to_string(money, pad, trim, decimal_points, color, no_color)
|
||||
|
||||
local is_negative = money < 0
|
||||
money = abs(money)
|
||||
local gold, silver, copper = m.to_GSC(money)
|
||||
|
||||
-- rounding
|
||||
if decimal_points then
|
||||
copper = tonumber(format('%.'..decimal_points..'f', copper))
|
||||
end
|
||||
|
||||
local gold_text, silver_text, copper_text
|
||||
if no_color then
|
||||
gold_text, silver_text, copper_text = 'g', 's', 'c'
|
||||
else
|
||||
gold_text, silver_text, copper_text = GOLD_TEXT, SILVER_TEXT, COPPER_TEXT
|
||||
end
|
||||
|
||||
local text
|
||||
if trim then
|
||||
local parts = {}
|
||||
if gold > 0 then
|
||||
tinsert(parts, m.format_number(gold, false, nil, color)..gold_text)
|
||||
end
|
||||
if silver > 0 then
|
||||
tinsert(parts, m.format_number(silver, pad, nil, color)..silver_text)
|
||||
end
|
||||
if copper > 0 or gold == 0 and silver == 0 then
|
||||
tinsert(parts, m.format_number(copper, pad, decimal_points, color)..copper_text)
|
||||
end
|
||||
text = Aux.util.join(parts, ' ')
|
||||
else
|
||||
if gold > 0 then
|
||||
text = m.format_number(gold, false, nil, color)..gold_text..' '..m.format_number(silver, pad, nil, color)..silver_text..' '..m.format_number(copper, pad, decimal_points, color)..copper_text
|
||||
elseif silver > 0 then
|
||||
text = m.format_number(silver, false, nil, color)..silver_text..' '..m.format_number(copper, pad, decimal_points, color)..copper_text
|
||||
else
|
||||
text = m.format_number(copper, false, decimal_points, color)..copper_text
|
||||
end
|
||||
end
|
||||
|
||||
if is_negative then
|
||||
if color then
|
||||
text = color..'-|r'..text
|
||||
else
|
||||
text = '-'..text
|
||||
end
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function m.from_string(value)
|
||||
value = strlower(value)
|
||||
|
||||
-- remove any colors
|
||||
value = gsub(gsub(value, '\124c([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])', ''), '\124r', '')
|
||||
|
||||
-- extract gold/silver/copper values
|
||||
local gold = tonumber(({strfind(value, '(%d*%.?%d+)g')})[3])
|
||||
local silver = tonumber(({strfind(value, '(%d*%.?%d+)s')})[3])
|
||||
local copper = tonumber(({strfind(value, '(%d*%.?%d+)c')})[3])
|
||||
if not gold and not silver and not copper then return end
|
||||
|
||||
-- test that there are no extra characters (other than spaces)
|
||||
value = gsub(value, '%d*%.?%d+g', '', 1)
|
||||
value = gsub(value, '%d*%.?%d+s', '', 1)
|
||||
value = gsub(value, '%d*%.?%d+c', '', 1)
|
||||
if strfind(value, '%S') then return end
|
||||
|
||||
return m.from_GSC(gold or 0, silver or 0, copper or 0)
|
||||
end
|
||||
|
||||
function m.format_number(num, pad, decimal_padding, color)
|
||||
|
||||
local padding = pad and 2 + (decimal_padding and decimal_padding + 1 or 0) or 0
|
||||
num = format('%0'..padding..'.0'..(decimal_padding or 0)..'f', num)
|
||||
|
||||
if color then
|
||||
return color..num..'|r'
|
||||
else
|
||||
return num
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,144 @@
|
||||
local private, public = {}, {}
|
||||
Aux.persistence = public
|
||||
|
||||
aux_datasets = {}
|
||||
|
||||
function public.on_load()
|
||||
Aux.control.as_soon_as(function() private.faction = UnitFactionGroup('player') return private.faction end, Aux.util.pass)
|
||||
private.realm = GetCVar('realmName')
|
||||
end
|
||||
|
||||
function private.get_dataset_key()
|
||||
return private.realm..'|'..private.faction
|
||||
end
|
||||
|
||||
function public.load_dataset()
|
||||
local dataset_key = private.get_dataset_key()
|
||||
aux_datasets[dataset_key] = aux_datasets[dataset_key] or {}
|
||||
return aux_datasets[dataset_key]
|
||||
end
|
||||
|
||||
function public.read(schema, str)
|
||||
if schema == 'string' then
|
||||
return str
|
||||
elseif schema == 'boolean' then
|
||||
return str == '1'
|
||||
elseif schema == 'number' then
|
||||
return tonumber(str)
|
||||
elseif type(schema) == 'table' and schema[1] == 'list' then
|
||||
return public.read_list(schema, str)
|
||||
elseif type(schema) == 'table' and schema[1] == 'record' then
|
||||
return public.read_record(schema, str)
|
||||
else
|
||||
error('Unknown schema.')
|
||||
end
|
||||
end
|
||||
|
||||
function public.write(schema, obj)
|
||||
if schema == 'string' then
|
||||
return obj or ''
|
||||
elseif schema == 'boolean' then
|
||||
return obj and '1' or '0'
|
||||
elseif schema == 'number' then
|
||||
return obj and tostring(obj) or ''
|
||||
elseif type(schema) == 'table' and schema[1] == 'list' then
|
||||
return public.write_list(schema, obj)
|
||||
elseif type(schema) == 'table' and schema[1] == 'record' then
|
||||
return public.write_record(schema, obj)
|
||||
else
|
||||
error('Unknown schema.')
|
||||
end
|
||||
end
|
||||
|
||||
function public.read_list(schema, str)
|
||||
if str == '' then
|
||||
return {}
|
||||
end
|
||||
|
||||
local separator = schema[2]
|
||||
local element_type = schema[3]
|
||||
local parts = Aux.util.split(str, separator)
|
||||
return Aux.util.map(parts, function(part)
|
||||
return public.read(element_type, part)
|
||||
end)
|
||||
end
|
||||
|
||||
function public.write_list(schema, list)
|
||||
local separator = schema[2]
|
||||
local element_type = schema[3]
|
||||
local parts = Aux.util.map(list, function(element)
|
||||
return public.write(element_type, element)
|
||||
end)
|
||||
return Aux.util.join(parts, separator)
|
||||
end
|
||||
|
||||
function public.read_record(schema, str)
|
||||
local separator = schema[2]
|
||||
local record = {}
|
||||
local parts = Aux.util.split(str, separator)
|
||||
for i=3,getn(schema) do
|
||||
local key, type = next(schema[i])
|
||||
record[key] = public.read(type, parts[i - 2])
|
||||
end
|
||||
return record
|
||||
end
|
||||
|
||||
function public.write_record(schema, record)
|
||||
local separator = schema[2]
|
||||
local parts = {}
|
||||
for i=3,getn(schema) do
|
||||
local key, type = next(schema[i])
|
||||
tinsert(parts, public.write(type, record[key]))
|
||||
end
|
||||
return Aux.util.join(parts, separator)
|
||||
end
|
||||
|
||||
function public.serialize(data, separator, compactor)
|
||||
|
||||
local data_string = ''
|
||||
local i = 1
|
||||
while i <= getn(data) do
|
||||
local element, count = data[i], 1
|
||||
while compactor and data[i + 1] == element do
|
||||
count = count + 1
|
||||
i = i + 1
|
||||
end
|
||||
local part = count > 1 and element..compactor..count or element
|
||||
data_string = data_string..(i == 1 and '' or separator)..part
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
return data_string
|
||||
end
|
||||
|
||||
function public.deserialize(data_string, separator, compactor)
|
||||
if not data_string or data_string == '' then
|
||||
return {}
|
||||
end
|
||||
|
||||
local data = {}
|
||||
while true do
|
||||
local start_index, _ = strfind(data_string, separator, 1, true)
|
||||
|
||||
local part
|
||||
if start_index then
|
||||
part = strsub(data_string, 1, start_index - 1)
|
||||
data_string = strsub(data_string, start_index + 1)
|
||||
else
|
||||
part = strsub(data_string, 1)
|
||||
end
|
||||
|
||||
if compactor and strfind(part, compactor, 1, true) then
|
||||
local compactor_index, _ = strfind(part, compactor, 1, true)
|
||||
for i=1, tonumber(strsub(part, compactor_index + 1)) do
|
||||
tinsert(data, strsub(part, 1, compactor_index - 1))
|
||||
end
|
||||
else
|
||||
tinsert(data, part)
|
||||
end
|
||||
|
||||
if not start_index then
|
||||
return data
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,735 @@
|
||||
local m = {}
|
||||
Aux.scan_util = m
|
||||
|
||||
function m.default_filter(str)
|
||||
return {
|
||||
arity = 0,
|
||||
test = function()
|
||||
return function(auction_record)
|
||||
return Aux.util.any(auction_record.tooltip, function(entry)
|
||||
return strfind(strupper(entry.left_text or ''), strupper(str or ''), 1, true) or strfind(strupper(entry.right_text or ''), strupper(str or ''), 1, true)
|
||||
end)
|
||||
end
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
m.filters = {
|
||||
|
||||
['utilizable'] = {
|
||||
arity = 0,
|
||||
test = function()
|
||||
return function(auction_record)
|
||||
return auction_record.usable and not Aux.info.tooltip_match(ITEM_SPELL_KNOWN, auction_record.tooltip)
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
['tooltip'] = {
|
||||
arity = 1,
|
||||
test = function(str)
|
||||
if str then
|
||||
return m.default_filter(str).test()
|
||||
else
|
||||
return false, {}, 'Erroneous tooltip modifier'
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
['item'] = {
|
||||
arity = 1,
|
||||
test = function(name)
|
||||
if not name then
|
||||
return false, aux_auctionable_items, 'Erroneous item modifier'
|
||||
end
|
||||
|
||||
return function(auction_record)
|
||||
return strlower(Aux.info.item(auction_record.item_id).name) == name
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['left'] = {
|
||||
arity = 1,
|
||||
test = function(duration)
|
||||
if not duration then
|
||||
return false, {'30m', '2h', '8h', '24h'}, 'Erroneous time left modifier'
|
||||
end
|
||||
|
||||
local code = ({
|
||||
['30m'] = 1,
|
||||
['2h'] = 2,
|
||||
['8h'] = 3,
|
||||
['24h'] = 4,
|
||||
})[duration or '']
|
||||
|
||||
if not code then
|
||||
return false, {}, 'Erroneous time left modifier'
|
||||
end
|
||||
|
||||
return function(auction_record)
|
||||
return auction_record.duration == code
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['rarity'] = {
|
||||
arity = 1,
|
||||
test = function(rarity)
|
||||
if not rarity then
|
||||
return false, {'poor', 'common', 'uncommon', 'rare', 'epic'}, 'Erroneous rarity modifier'
|
||||
end
|
||||
|
||||
local code = ({
|
||||
['poor'] = 0,
|
||||
['common'] = 1,
|
||||
['uncommon'] = 2,
|
||||
['rare'] = 3,
|
||||
['epic'] = 4,
|
||||
})[rarity or '']
|
||||
if not code then
|
||||
return false, {}, 'Erroneous rarity modifier'
|
||||
end
|
||||
|
||||
return function(auction_record)
|
||||
return auction_record.quality == code
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['min-lvl'] = {
|
||||
arity = 1,
|
||||
test = function(level)
|
||||
level = tonumber(level or '')
|
||||
if level then
|
||||
return function(auction_record)
|
||||
return auction_record.level >= level
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous min level modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['max-lvl'] = {
|
||||
arity = 1,
|
||||
test = function(level)
|
||||
level = tonumber(level or '')
|
||||
if level then
|
||||
return function(auction_record)
|
||||
return auction_record.level <= level
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous max level modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['min-unit-bid'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
return auction_record.unit_bid_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous min bid modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['min-unit-buy'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
return auction_record.unit_buyout_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous min buyout modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['max-unit-bid'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
return auction_record.unit_bid_price <= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous max bid modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['max-unit-buy'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
return auction_record.buyout_price > 0 and auction_record.unit_buyout_price <= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous max buyout modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['bid-pct'] = {
|
||||
arity = 1,
|
||||
test = function(pct)
|
||||
pct = tonumber(pct)
|
||||
if pct then
|
||||
return function(auction_record)
|
||||
return auction_record.unit_buyout_price > 0
|
||||
and Aux.history.value(auction_record.item_key)
|
||||
and auction_record.unit_buyout_price / Aux.history.value(auction_record.item_key) * 100 <= pct
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous bid percentage modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['buy-pct'] = {
|
||||
arity = 1,
|
||||
test = function(pct)
|
||||
pct = tonumber(pct)
|
||||
if pct then
|
||||
return function(auction_record)
|
||||
return auction_record.unit_buyout_price > 0
|
||||
and Aux.history.value(auction_record.item_key)
|
||||
and auction_record.unit_buyout_price / Aux.history.value(auction_record.item_key) * 100 <= pct
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous buyout percentage modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['bid-profit'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
return Aux.history.value(auction_record.item_key) and Aux.history.value(auction_record.item_key) * auction_record.aux_quantity - auction_record.bid_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous bid profit modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['buy-profit'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
return auction_record.buyout_price > 0 and Aux.history.value(auction_record.item_key) and Aux.history.value(auction_record.item_key) * auction_record.aux_quantity - auction_record.buyout_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous buyout profit modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['bid-dis-profit'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
local disenchant_value = Aux.disenchant.value(auction_record.slot, auction_record.quality, auction_record.level)
|
||||
return disenchant_value and disenchant_value - auction_record.bid_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous bid disenchant profit modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['buy-dis-profit'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
local disenchant_value = Aux.disenchant.value(auction_record.slot, auction_record.quality, auction_record.level)
|
||||
return auction_record.buyout_price > 0 and disenchant_value and disenchant_value - auction_record.buyout_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous buyout disenchant profit modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['bid-vend-profit'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
local vendor_price = Aux.cache.merchant_info(auction_record.item_id)
|
||||
return vendor_price and vendor_price * auction_record.aux_quantity - auction_record.bid_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous bid vendor profit Modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['buy-vend-profit'] = {
|
||||
arity = 1,
|
||||
test = function(amount)
|
||||
amount = Aux.money.from_string(amount or '') or 0
|
||||
if amount > 0 then
|
||||
return function(auction_record)
|
||||
local vendor_price = Aux.cache.merchant_info(auction_record.item_id)
|
||||
return auction_record.buyout_price > 0 and vendor_price and vendor_price * auction_record.aux_quantity - auction_record.buyout_price >= amount
|
||||
end
|
||||
else
|
||||
return false, {}, 'Erroneous buyout vendor profit Modifier'
|
||||
end
|
||||
end
|
||||
},
|
||||
|
||||
['discard'] = {
|
||||
arity = 0,
|
||||
test = function()
|
||||
return function()
|
||||
return false
|
||||
end
|
||||
end
|
||||
},
|
||||
}
|
||||
|
||||
function m.find(auction_record, status_bar, on_abort, on_failure, on_success)
|
||||
|
||||
local function test(index)
|
||||
local auction_info = Aux.info.auction(index, auction_record.query_type)
|
||||
return auction_info and auction_info.search_signature == auction_record.search_signature
|
||||
end
|
||||
|
||||
local queries = {}
|
||||
tinsert(queries, {})
|
||||
|
||||
if auction_record.blizzard_query then
|
||||
|
||||
local blizzard_query1 = Aux.util.copy_table(auction_record.blizzard_query)
|
||||
blizzard_query1.first_page = auction_record.page
|
||||
blizzard_query1.last_page = auction_record.page
|
||||
tinsert(queries, {
|
||||
blizzard_query = blizzard_query1,
|
||||
})
|
||||
|
||||
if auction_record.page > 0 then
|
||||
local blizzard_query2 = Aux.util.copy_table(auction_record.blizzard_query)
|
||||
blizzard_query2.first_page = auction_record.page - 1
|
||||
blizzard_query2.last_page = auction_record.page - 1
|
||||
tinsert(queries, {
|
||||
blizzard_query = blizzard_query1,
|
||||
})
|
||||
end
|
||||
|
||||
local item_query = m.item_query(auction_record.item_id, 1, 1)
|
||||
if not Aux.util.table_eq(auction_record.blizzard_query, item_query.blizzard_query) then
|
||||
tinsert(queries, item_query)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local found
|
||||
return Aux.scan.start{
|
||||
type = auction_record.query_type,
|
||||
queries = queries,
|
||||
on_scan_start = function()
|
||||
status_bar:update_status(0, 0)
|
||||
status_bar:set_text('Searching auction...')
|
||||
end,
|
||||
on_start_query = function(query_index)
|
||||
status_bar:update_status((query_index - 1) / getn(queries) * 100, 0)
|
||||
end,
|
||||
on_auction = function(auction_record, ctrl)
|
||||
if test(auction_record.index) then
|
||||
found = true
|
||||
ctrl.suspend()
|
||||
status_bar:update_status(100, 100)
|
||||
status_bar:set_text('Auction found')
|
||||
return on_success(auction_record.index)
|
||||
end
|
||||
end,
|
||||
on_abort = function()
|
||||
if not found then
|
||||
status_bar:update_status(100, 100)
|
||||
status_bar:set_text('Auction not found')
|
||||
return on_abort()
|
||||
end
|
||||
end,
|
||||
on_complete = function()
|
||||
status_bar:update_status(100, 100)
|
||||
status_bar:set_text('Auction not found')
|
||||
return on_failure()
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
function m.filter_builder()
|
||||
local filter = ''
|
||||
return {
|
||||
append = function(self, modifier)
|
||||
modifier = modifier
|
||||
filter = filter == '' and modifier or filter..'/'..modifier
|
||||
end,
|
||||
prepend = function(self, modifier)
|
||||
modifier = modifier
|
||||
filter = filter == '' and modifier or modifier..'/'..filter
|
||||
end,
|
||||
get = function(self)
|
||||
return filter
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
function m.item_query(item_id, first_page, last_page)
|
||||
|
||||
local item_info = Aux.info.item(item_id)
|
||||
|
||||
if item_info then
|
||||
local filter = m.filter_from_string(item_info.name..'/exact/'..(first_page or '')..':'..(last_page or ''))
|
||||
return {
|
||||
validator = filter.validator,
|
||||
blizzard_query = filter.blizzard_query,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function m.parse_filter_string(filter_string)
|
||||
local parts = Aux.util.split(filter_string, ';')
|
||||
|
||||
local filters = {}
|
||||
for _, str in ipairs(parts) do
|
||||
str = Aux.util.trim(str)
|
||||
|
||||
local filter, _, error = m.filter_from_string(str)
|
||||
|
||||
if not filter then
|
||||
Aux.log('Invalid filter: '..error)
|
||||
return
|
||||
elseif filter.name and strlen(filter.name) > 63 then
|
||||
|
||||
else
|
||||
tinsert(filters, filter)
|
||||
end
|
||||
end
|
||||
|
||||
return filters
|
||||
end
|
||||
|
||||
function m.filter_from_string(filter_term)
|
||||
local parts = Aux.util.map(Aux.util.split(filter_term, '/'), function(part) return strlower(Aux.util.trim(part)) end)
|
||||
|
||||
local blizzard_filter = {}
|
||||
local post_filter = {}
|
||||
local prettified = m.filter_builder()
|
||||
local polish_notation_counter = 0
|
||||
local i = 1
|
||||
|
||||
local function non_blizzard_modifier(str)
|
||||
local filter = m.filters[str]
|
||||
if filter then
|
||||
prettified:append('|cffffff00'..str..'|r')
|
||||
else
|
||||
filter = filter or m.default_filter(str)
|
||||
prettified:append('|cffff9218'..str..'|r')
|
||||
end
|
||||
|
||||
local args = {}
|
||||
for j=1, filter.arity do
|
||||
local arg = parts[i - 1 + j]
|
||||
if arg then
|
||||
tinsert(args, arg)
|
||||
prettified:append('|cffff9218'..arg..'|r')
|
||||
end
|
||||
end
|
||||
i = i + filter.arity
|
||||
|
||||
local test, suggestions, error = filter.test(unpack(args))
|
||||
if test then
|
||||
tinsert(post_filter, test)
|
||||
else
|
||||
return error, i > getn(parts) and suggestions or {}
|
||||
end
|
||||
end
|
||||
|
||||
while i <= getn(parts) do
|
||||
local str = parts[i]
|
||||
i = i + 1
|
||||
|
||||
if polish_notation_counter > 0 or str == 'and' or str == 'or' or str == 'not' then
|
||||
polish_notation_counter = polish_notation_counter == 0 and polish_notation_counter + 1 or polish_notation_counter
|
||||
if str == 'and' or str == 'or' then
|
||||
polish_notation_counter = polish_notation_counter + 1
|
||||
tinsert(post_filter, str)
|
||||
prettified:append('|cffffff00'..str..'|r')
|
||||
elseif str == 'not' then
|
||||
tinsert(post_filter, str)
|
||||
prettified:append('|cffffff00'..str..'|r')
|
||||
elseif str ~= '' then
|
||||
polish_notation_counter = polish_notation_counter - 1
|
||||
local error, suggestions = non_blizzard_modifier(str)
|
||||
if error then
|
||||
return false, suggestions, error
|
||||
end
|
||||
end
|
||||
elseif strfind(str, '^%d*:%d*$') then
|
||||
if not blizzard_filter.first_page and not blizzard_filter.last_page then
|
||||
local _, _, first_page, last_page = strfind(str, '^(%d*):(%d*)$')
|
||||
if tonumber(first_page) and tonumber(first_page) < 1 or tonumber(last_page) and tonumber(last_page) < 1 then
|
||||
return false, {}, 'Erroneous page range modifier'
|
||||
end
|
||||
blizzard_filter.first_page = tonumber(first_page)
|
||||
blizzard_filter.last_page = tonumber(last_page)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous page range modifier'
|
||||
end
|
||||
elseif tonumber(str) then
|
||||
if tonumber(str) < 1 or tonumber(str) > 60 then
|
||||
return false, {}, 'Erroneous level range modifier'
|
||||
end
|
||||
if not blizzard_filter.min_level then
|
||||
blizzard_filter.min_level = tonumber(str)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
elseif not blizzard_filter.max_level and tonumber(str) >= blizzard_filter.min_level then
|
||||
blizzard_filter.max_level = tonumber(str)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous level range modifier'
|
||||
end
|
||||
elseif Aux.item_class_index(str) and not (blizzard_filter.class and not blizzard_filter.subclass and str == strlower(({ GetAuctionItemClasses() })[10])) then
|
||||
if not blizzard_filter.class then
|
||||
blizzard_filter.class = Aux.item_class_index(str)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous item class modifier'
|
||||
end
|
||||
elseif blizzard_filter.class and Aux.item_subclass_index(blizzard_filter.class, str) then
|
||||
if not blizzard_filter.subclass then
|
||||
blizzard_filter.subclass = Aux.item_subclass_index(blizzard_filter.class, str)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous item subclass modifier'
|
||||
end
|
||||
elseif blizzard_filter.subclass and Aux.item_slot_index(blizzard_filter.class, blizzard_filter.subclass, str) then
|
||||
if not blizzard_filter.slot then
|
||||
blizzard_filter.slot = Aux.item_slot_index(blizzard_filter.class, blizzard_filter.subclass, str)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous item slot modifier'
|
||||
end
|
||||
elseif Aux.item_quality_index(str) then
|
||||
if not blizzard_filter.quality then
|
||||
blizzard_filter.quality = Aux.item_quality_index(str)
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous rarity modifier'
|
||||
end
|
||||
elseif str == 'usable' then
|
||||
if not blizzard_filter.usable then
|
||||
blizzard_filter.usable = true
|
||||
prettified:append(Aux.gui.inline_color({216, 225, 211, 1})..str..'|r')
|
||||
else
|
||||
return false, {}, 'Erroneous usable only modifier'
|
||||
end
|
||||
elseif str == 'exact' then
|
||||
if not blizzard_filter.exact then
|
||||
blizzard_filter.exact = true
|
||||
else
|
||||
return false, {}, 'Erroneous exact only modifier'
|
||||
end
|
||||
elseif i == 2 and not m.filters[str] then
|
||||
blizzard_filter.name = str
|
||||
elseif str ~= '' then
|
||||
local error, suggestions = non_blizzard_modifier(str)
|
||||
if error then
|
||||
return false, suggestions, error
|
||||
end
|
||||
else
|
||||
return false, {}, 'Empty modifier'
|
||||
end
|
||||
end
|
||||
|
||||
if polish_notation_counter ~= 0 then
|
||||
local suggestions = {}
|
||||
for filter, _ in pairs(m.filters) do
|
||||
tinsert(suggestions, strlower(filter))
|
||||
tinsert(suggestions, 'and')
|
||||
tinsert(suggestions, 'or')
|
||||
tinsert(suggestions, 'not')
|
||||
end
|
||||
return false, i > getn(parts) and suggestions, 'Malformed expression'
|
||||
end
|
||||
|
||||
if blizzard_filter.exact then
|
||||
if blizzard_filter.min_level
|
||||
or blizzard_filter.max_level
|
||||
or blizzard_filter.class
|
||||
or blizzard_filter.subclass
|
||||
or blizzard_filter.slot
|
||||
or blizzard_filter.quality
|
||||
or blizzard_filter.usable
|
||||
or not blizzard_filter.name
|
||||
then
|
||||
return false, {}, 'Erroneous exact only modifier'
|
||||
else
|
||||
prettified:prepend(Aux.info.display_name(Aux.cache.item_id(blizzard_filter.name)) or Aux.gui.inline_color({216, 225, 211, 1})..'['..blizzard_filter.name..']|r')
|
||||
end
|
||||
elseif blizzard_filter.name then
|
||||
if blizzard_filter.name == '' then
|
||||
prettified:prepend('|cffff0000'..'No Filter'..'|r')
|
||||
else
|
||||
prettified:prepend(Aux.gui.inline_color({216, 225, 211, 1})..blizzard_filter.name..'|r')
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
blizzard_query = m.blizzard_query(blizzard_filter),
|
||||
validator = m.validator(blizzard_filter, post_filter),
|
||||
prettified = prettified:get(),
|
||||
}, m.suggestions(blizzard_filter, getn(parts))
|
||||
end
|
||||
|
||||
function m.suggestions(blizzard_filter, num_parts)
|
||||
|
||||
local suggestions = {}
|
||||
|
||||
if blizzard_filter.name
|
||||
and not blizzard_filter.min_level
|
||||
and not blizzard_filter.max_level
|
||||
and not blizzard_filter.class
|
||||
and not blizzard_filter.subclass
|
||||
and not blizzard_filter.slot
|
||||
and not blizzard_filter.quality
|
||||
and not blizzard_filter.usable
|
||||
then
|
||||
tinsert(suggestions, 'exact')
|
||||
end
|
||||
|
||||
tinsert(suggestions, 'and')
|
||||
tinsert(suggestions, 'or')
|
||||
tinsert(suggestions, 'not')
|
||||
tinsert(suggestions, 'tt')
|
||||
|
||||
for filter, _ in pairs(m.filters) do
|
||||
tinsert(suggestions, strlower(filter))
|
||||
end
|
||||
|
||||
-- classes
|
||||
if not blizzard_filter.class then
|
||||
for _, class in ipairs({ GetAuctionItemClasses() }) do
|
||||
tinsert(suggestions, class)
|
||||
end
|
||||
end
|
||||
|
||||
-- subclasses
|
||||
if blizzard_filter.class and not blizzard_filter.subclass then
|
||||
for _, subclass in ipairs({ GetAuctionItemSubClasses(blizzard_filter.class) }) do
|
||||
tinsert(suggestions, subclass)
|
||||
end
|
||||
end
|
||||
|
||||
-- slots
|
||||
if blizzard_filter.class and blizzard_filter.subclass and not blizzard_filter.slot then
|
||||
for _, invtype in ipairs({ GetAuctionInvTypes(blizzard_filter.class, blizzard_filter.subclass) }) do
|
||||
tinsert(suggestions, getglobal(invtype))
|
||||
end
|
||||
end
|
||||
|
||||
-- usable
|
||||
if not blizzard_filter.usable then
|
||||
tinsert(suggestions, 'usable')
|
||||
end
|
||||
|
||||
-- rarities
|
||||
if not blizzard_filter.quality then
|
||||
for i=0,4 do
|
||||
tinsert(suggestions, getglobal('ITEM_QUALITY'..i..'_DESC'))
|
||||
end
|
||||
end
|
||||
|
||||
-- item names
|
||||
if num_parts == 1 and blizzard_filter.name == '' then
|
||||
for _, name in aux_auctionable_items do
|
||||
tinsert(suggestions, name..'/exact')
|
||||
end
|
||||
end
|
||||
|
||||
return suggestions
|
||||
end
|
||||
|
||||
function m.blizzard_query(filter)
|
||||
|
||||
local item_info, class_index, subclass_index, slot_index
|
||||
if filter.exact then
|
||||
local item_id = Aux.cache.item_id(filter.name)
|
||||
item_info = Aux.info.item(item_id)
|
||||
class_index = item_info and Aux.item_class_index(item_info.class)
|
||||
subclass_index = class_index and item_info.subclass and Aux.item_subclass_index(class_index, item_info.subclass)
|
||||
slot_index = subclass_index and item_info.slot and Aux.item_slot_index(class_index, subclass_index, item_info.slot)
|
||||
end
|
||||
|
||||
return {
|
||||
first_page = filter.first_page and filter.first_page - 1,
|
||||
last_page = filter.last_page and filter.last_page - 1,
|
||||
name = filter.name,
|
||||
min_level = item_info and item_info.level or filter.min_level,
|
||||
max_level = item_info and item_info.level or filter.max_level,
|
||||
class = item_info and class_index or filter.class,
|
||||
subclass = item_info and subclass_index or filter.subclass,
|
||||
slot = item_info and item_info.class and slot_index or filter.slot,
|
||||
usable = item_info and item_info.usable or filter.usable and 1 or 0,
|
||||
quality = item_info and item_info.quality or filter.quality,
|
||||
}
|
||||
end
|
||||
|
||||
function m.validator(blizzard_filter, post_filter)
|
||||
|
||||
return function(record)
|
||||
if blizzard_filter.exact and strlower(Aux.info.item(record.item_id).name) ~= blizzard_filter.name then
|
||||
return
|
||||
end
|
||||
if blizzard_filter.min_level and record.level < blizzard_filter.min_level then
|
||||
return
|
||||
end
|
||||
if blizzard_filter.max_level and record.level > blizzard_filter.max_level then
|
||||
return
|
||||
end
|
||||
if getn(post_filter) > 0 then
|
||||
local stack = {}
|
||||
for i=getn(post_filter),1,-1 do
|
||||
local op = post_filter[i]
|
||||
if op == 'and' then
|
||||
local a, b = tremove(stack), tremove(stack)
|
||||
tinsert(stack, a and b)
|
||||
elseif op == 'or' then
|
||||
local a, b = tremove(stack), tremove(stack)
|
||||
tinsert(stack, a or b)
|
||||
elseif op == 'not' then
|
||||
tinsert(stack, not tremove(stack))
|
||||
else
|
||||
tinsert(stack, op(record) and true or false)
|
||||
end
|
||||
end
|
||||
return Aux.util.all(stack, Aux.util.id)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
local private, public = {}, {}
|
||||
Aux.sort = public
|
||||
|
||||
public.LT = {}
|
||||
public.EQ = {}
|
||||
public.GT = {}
|
||||
|
||||
-- stable sorting
|
||||
function public.merge_sort(A, comp)
|
||||
local n = getn(A)
|
||||
local B = {}
|
||||
|
||||
local width = 1
|
||||
while width <= n do
|
||||
|
||||
for i=1, n, 2 * width do
|
||||
private.merge(A, i, min(i + width, n), min(i + 2 * width - 1, n), B, comp)
|
||||
end
|
||||
|
||||
private.copy_array(B, A, n)
|
||||
|
||||
width = 2 * width
|
||||
end
|
||||
end
|
||||
|
||||
function private.merge(A, start1, start2, last, B, comp)
|
||||
local i1 = start1
|
||||
local i2 = start2
|
||||
|
||||
for i=start1,last do
|
||||
if i1 < start2 and (i2 > last or comp(A[i1], A[i2]) == public.LT or comp(A[i1], A[i2]) == public.EQ) then
|
||||
B[i] = A[i1]
|
||||
i1 = i1 + 1
|
||||
else
|
||||
B[i] = A[i2]
|
||||
i2 = i2 + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function private.copy_array(A, B, n)
|
||||
for i=1,n do
|
||||
B[i] = A[i]
|
||||
end
|
||||
end
|
||||
|
||||
function public.invert_order(ordering)
|
||||
if ordering == public.LT then
|
||||
return public.GT
|
||||
elseif ordering == public.GT then
|
||||
return public.LT
|
||||
else
|
||||
return public.EQ
|
||||
end
|
||||
end
|
||||
|
||||
function public.compare(a, b, desc)
|
||||
if a < b then
|
||||
return desc and public.GT or public.LT
|
||||
elseif a > b then
|
||||
return desc and public.LT or public.GT
|
||||
else
|
||||
return public.EQ
|
||||
end
|
||||
end
|
||||
|
||||
function public.compare_from_lt(lt)
|
||||
return function(a, b)
|
||||
if lt(a, b) then
|
||||
return public.LT
|
||||
elseif lt(b, a) then
|
||||
return public.GT
|
||||
else
|
||||
return public.EQ
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function public.multi_lt(...)
|
||||
for i=1,arg.n-1,2 do
|
||||
if arg[i] ~= arg[i+1] then
|
||||
return arg[i] < arg[i+1]
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
local private, public = {}, {}
|
||||
Aux.util = public
|
||||
|
||||
function Aux.util.pass()
|
||||
end
|
||||
|
||||
function public.id(object)
|
||||
return object
|
||||
end
|
||||
|
||||
function public.table_eq(t1, t2)
|
||||
if not t1 or not t2 then
|
||||
return false
|
||||
end
|
||||
|
||||
for key, value in t1 do
|
||||
if t2[key] ~= value then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function public.wipe(table)
|
||||
while getn(table) > 0 do
|
||||
tremove(table)
|
||||
end
|
||||
for k, _ in pairs(table) do
|
||||
table[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function public.copy_table(table)
|
||||
local copy = {}
|
||||
for k, v in pairs(table) do
|
||||
copy[k] = v
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
function public.cons(element, list)
|
||||
local new_list = public.copy_table(list)
|
||||
tinsert(new_list, 1, element)
|
||||
return new_list
|
||||
end
|
||||
|
||||
function public.trim(string)
|
||||
string = gsub(string, '^%s*', '')
|
||||
string = gsub(string, '%s*$', '')
|
||||
return string
|
||||
end
|
||||
|
||||
function public.inventory()
|
||||
local bag, slot = 0, 0
|
||||
|
||||
return function()
|
||||
if not GetBagName(bag) or slot >= GetContainerNumSlots(bag) then
|
||||
repeat
|
||||
bag = bag + 1
|
||||
until GetBagName(bag) or bag > 4
|
||||
slot = 1
|
||||
else
|
||||
slot = slot + 1
|
||||
end
|
||||
|
||||
if bag <= 4 then
|
||||
return { bag, slot }, public.bag_type(bag)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local bag_types = { GetAuctionItemSubClasses(3) }
|
||||
|
||||
function public.bag_type(bag)
|
||||
if bag == 0 then
|
||||
return 1
|
||||
end
|
||||
|
||||
local link = GetInventoryItemLink('player', ContainerIDToInventoryID(bag))
|
||||
if link then
|
||||
local item_id = Aux.info.parse_hyperlink(GetInventoryItemLink('player', ContainerIDToInventoryID(bag)))
|
||||
local item_info = Aux.info.item(item_id)
|
||||
return Aux.item_subclass_index(3, item_info.subclass)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function public.safe_index(...)
|
||||
local target = arg[1]
|
||||
|
||||
for i=2,arg.n do
|
||||
if not target then
|
||||
return
|
||||
end
|
||||
target = target[arg[i]]
|
||||
end
|
||||
|
||||
return target
|
||||
end
|
||||
|
||||
function Aux_PluralizeIf(word, count)
|
||||
|
||||
if count and count == 1 then
|
||||
return word
|
||||
else
|
||||
return word..'s'
|
||||
end
|
||||
end
|
||||
|
||||
function Aux.util.without_errors(f)
|
||||
local orig = UIErrorsFrame.AddMessage
|
||||
UIErrorsFrame.AddMessage = Aux.util.pass
|
||||
f()
|
||||
UIErrorsFrame.AddMessage = orig
|
||||
end
|
||||
|
||||
function Aux.util.without_sound(f)
|
||||
local orig = GetCVar('MasterSoundEffects')
|
||||
SetCVar('MasterSoundEffects', 0)
|
||||
f()
|
||||
SetCVar('MasterSoundEffects', orig)
|
||||
end
|
||||
|
||||
function Aux.util.iter(array)
|
||||
local with_index = ipairs(array)
|
||||
return function()
|
||||
local _, value = with_index
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
function Aux.util.set_add(set, key)
|
||||
set[key] = true
|
||||
end
|
||||
|
||||
function Aux.util.set_remove(set, key)
|
||||
set[key] = nil
|
||||
end
|
||||
|
||||
function Aux.util.set_contains(set, key)
|
||||
return set[key] ~= nil
|
||||
end
|
||||
|
||||
function Aux.util.set_size(set)
|
||||
local size = 0
|
||||
for _,_ in pairs(set) do
|
||||
size = size + 1
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
function Aux.util.set_to_array(set)
|
||||
local array = {}
|
||||
for element, _ in pairs(set) do
|
||||
tinsert(array, element)
|
||||
end
|
||||
return array
|
||||
end
|
||||
|
||||
function Aux.util.any(xs, p)
|
||||
holds = false
|
||||
for _, x in ipairs(xs) do
|
||||
holds = holds or p(x)
|
||||
end
|
||||
return holds
|
||||
end
|
||||
|
||||
function Aux.util.all(xs, p)
|
||||
holds = true
|
||||
for _, x in ipairs(xs) do
|
||||
holds = holds and p(x)
|
||||
end
|
||||
return holds
|
||||
end
|
||||
|
||||
function Aux.util.set_filter(xs, p)
|
||||
ys = {}
|
||||
for x, _ in pairs(xs) do
|
||||
if p(x) then
|
||||
Aux.util.set_add(ys, x)
|
||||
end
|
||||
end
|
||||
return ys
|
||||
end
|
||||
|
||||
function Aux.util.filter(xs, p)
|
||||
ys = {}
|
||||
for _, x in ipairs(xs) do
|
||||
if p(x) then
|
||||
tinsert(ys, x)
|
||||
end
|
||||
end
|
||||
return ys
|
||||
end
|
||||
|
||||
function Aux.util.map(xs, f)
|
||||
ys = {}
|
||||
for _, x in ipairs(xs) do
|
||||
tinsert(ys, f(x))
|
||||
end
|
||||
return ys
|
||||
end
|
||||
|
||||
function Aux.util.take(n, xs)
|
||||
ys = {}
|
||||
for i=1,n do
|
||||
if xs[i] then
|
||||
tinsert(ys, xs[i])
|
||||
end
|
||||
end
|
||||
return ys
|
||||
end
|
||||
|
||||
function Aux.util.index_of(value, array)
|
||||
for i, item in ipairs(array) do
|
||||
if item == value then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local GSC_GOLD = "ffd100"
|
||||
local GSC_SILVER = "e6e6e6"
|
||||
local GSC_COPPER = "c8602c"
|
||||
local GSC_RED = "ff0000"
|
||||
|
||||
local GSC_3 = "|cff"..GSC_GOLD.."%d|cff000000.|cff"..GSC_SILVER.."%02d|cff000000.|cff"..GSC_COPPER.."%02d|r"
|
||||
local GSC_2 = "|cff"..GSC_SILVER.."%d|cff000000.|cff"..GSC_COPPER.."%02d|r"
|
||||
local GSC_1 = "|cff"..GSC_COPPER.."%d|r"
|
||||
|
||||
local GSC_3N = "|cff"..GSC_RED.."(|cff"..GSC_GOLD.."%d|cff000000.|cff"..GSC_SILVER.."%02d|cff000000.|cff"..GSC_COPPER.."%02d|cff"..GSC_RED..")|r"
|
||||
local GSC_2N = "|cff"..GSC_RED.."(|cff"..GSC_SILVER.."%d|cff000000.|cff"..GSC_COPPER.."%02d|cff"..GSC_RED..")|r"
|
||||
local GSC_1N = "|cff"..GSC_RED.."(|cff"..GSC_COPPER.."%d|cff"..GSC_RED..")|r"
|
||||
|
||||
function Aux.util.money_string(money)
|
||||
money = floor(tonumber(money) or 0)
|
||||
local negative = money < 0
|
||||
money = abs(money)
|
||||
|
||||
local g = floor(money / 10000)
|
||||
money = money - g * 10000
|
||||
local s = floor(money / 100)
|
||||
money = money - s * 100
|
||||
local c = money
|
||||
|
||||
if g > 0 then
|
||||
if negative then
|
||||
return format(GSC_3N, g, s, c)
|
||||
else
|
||||
return format(GSC_3, g, s, c)
|
||||
end
|
||||
elseif s > 0 then
|
||||
if negative then
|
||||
return format(GSC_2N, s, c)
|
||||
else
|
||||
return format(GSC_2, s, c)
|
||||
end
|
||||
else
|
||||
if negative then
|
||||
return format(GSC_1N, c)
|
||||
else
|
||||
return format(GSC_1, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Aux.util.group_by(tables, equal)
|
||||
local groups = {}
|
||||
for _, table in ipairs(tables) do
|
||||
local found_group
|
||||
for _, group in ipairs(groups) do
|
||||
if equal(table, group[1]) then
|
||||
tinsert(group, table)
|
||||
found_group = true
|
||||
end
|
||||
end
|
||||
if not found_group then
|
||||
tinsert(groups, { table })
|
||||
end
|
||||
end
|
||||
return groups
|
||||
end
|
||||
|
||||
function Aux.util.set()
|
||||
local self = {}
|
||||
|
||||
local data = {}
|
||||
|
||||
function self:add(value)
|
||||
data[value] = true
|
||||
end
|
||||
|
||||
function self:add_all(values)
|
||||
for _, value in ipairs(values) do
|
||||
self:add(value)
|
||||
end
|
||||
end
|
||||
|
||||
function self:remove(value)
|
||||
data[value] = nil
|
||||
end
|
||||
|
||||
function self:remove_all(values)
|
||||
for _, value in ipairs(values) do
|
||||
self:remove(value)
|
||||
end
|
||||
end
|
||||
|
||||
function self:contains(value)
|
||||
return data[value] ~= nil
|
||||
end
|
||||
|
||||
function self:values()
|
||||
local values = {}
|
||||
for value, _ in pairs(data) do
|
||||
tinsert(values, value)
|
||||
end
|
||||
return values
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function public.join(array, separator)
|
||||
local str = ''
|
||||
for i, element in ipairs(array) do
|
||||
if i > 1 then
|
||||
str = str..separator
|
||||
end
|
||||
str = str..element
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
function public.tokenize(str)
|
||||
local tokens = {}
|
||||
for token in string.gfind(str, '%S+') do
|
||||
tinsert(tokens, token)
|
||||
end
|
||||
return tokens
|
||||
end
|
||||
|
||||
function public.split(str, separator)
|
||||
|
||||
local array = {}
|
||||
while true do
|
||||
local start_index, _ = strfind(str, separator, 1, true)
|
||||
|
||||
if start_index then
|
||||
local part = strsub(str, 1, start_index - 1)
|
||||
tinsert(array, part)
|
||||
str = strsub(str, start_index + 1)
|
||||
else
|
||||
local part = strsub(str, 1)
|
||||
tinsert(array, part)
|
||||
return array
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function public.format_money(money, exact, color)
|
||||
color = color or '|r'
|
||||
|
||||
local TEXT_NONE = '0'
|
||||
|
||||
local GSC_GOLD = 'ffd100'
|
||||
local GSC_SILVER = 'e6e6e6'
|
||||
local GSC_COPPER = 'c8602c'
|
||||
local GSC_START = '|cff%s%d|r'
|
||||
local GSC_PART = color..'.|cff%s%02d|r'
|
||||
local GSC_NONE = '|cffa0a0a0'..TEXT_NONE..'|r'
|
||||
|
||||
if not exact and money >= 10000 then
|
||||
-- Round to nearest silver
|
||||
money = math.floor(money / 100 + 0.5) * 100
|
||||
end
|
||||
local g, s, c = Aux.money.to_GSC(money)
|
||||
|
||||
local gsc = ''
|
||||
|
||||
local fmt = GSC_START
|
||||
if g > 0 then
|
||||
gsc = gsc..string.format(fmt, GSC_GOLD, g)
|
||||
fmt = GSC_PART
|
||||
end
|
||||
if s > 0 or c > 0 then
|
||||
gsc = gsc..string.format(fmt, GSC_SILVER, s)
|
||||
fmt = GSC_PART
|
||||
end
|
||||
if c > 0 then
|
||||
gsc = gsc..string.format(fmt, GSC_COPPER, c)
|
||||
end
|
||||
if gsc == '' then
|
||||
gsc = GSC_NONE
|
||||
end
|
||||
return gsc
|
||||
end
|
||||
Reference in New Issue
Block a user