AuctionLite-classic/CreateAuctions.lua

265 lignes
7.6 KiB
Lua

-------------------------------------------------------------------------------
-- CreateAuctions.lua
--
-- Create a group of auctions based on input in the "Sell" tab.
-------------------------------------------------------------------------------
local _
local L = LibStub("AceLocale-3.0"):GetLocale("AuctionLite", false)
-- Flag indicating whether we're currently posting auctions.
local Selling = false;
local MultisellCreated = 0;
local MultisellDone = false;
local MultisellError = false;
-- Current coroutine.
local Coro = nil;
-------------------------------------------------------------------------------
-- Helpers
-------------------------------------------------------------------------------
-- Count the number of items matching the link (ignoring uniqueId).
function AuctionLite:CountItems(targetLink)
local total = 0;
if targetLink ~= nil then
local i, j;
for i = 0, 4 do
local numItems = C_Container.GetContainerNumSlots(i);
for j = 1, numItems do
local link = self:RemoveUniqueId(C_Container.GetContainerItemLink(i, j));
if link == targetLink then
local slotInfo = C_Container.GetContainerItemInfo(i, j);
local count = slotInfo.stackCount;
total = total + count;
end
end
end
end
return total;
end
-- Find item in bags.
function AuctionLite:FindItem(targetLink)
local total = 0;
if targetLink ~= nil then
local i, j;
for i = 0, 4 do
local numItems = C_Container.GetContainerNumSlots(i);
for j = 1, numItems do
local location = ItemLocation:CreateFromBagAndSlot(i, j);
local link = self:RemoveUniqueId(C_Item.GetItemLink(location));
if link == targetLink then
return i, j;
end
end
end
end
return nil;
end
-------------------------------------------------------------------------------
-- Auction creation
-------------------------------------------------------------------------------
-- Start the auctions and print a message to the console.
function AuctionLite:StartAuctions(bid, buyout, time, size, stacks, name, link)
-- Make sure the item is present.
if GetAuctionSellItemInfo() == nil then
local container, slot = self:FindItem(link);
if container ~= nil then
ClearCursor();
PickupContainerItem(container, slot);
ClickAuctionSellItemButton();
end
end
-- Check again, just to be sure.
if GetAuctionSellItemInfo() ~= nil then
-- Grab our initial state.
local count = self:CountItems(link);
MultisellCreated = 0;
MultisellDone = false;
MultisellError = false;
-- Start the new auction, ignoring console spam.
PostAuction(bid, buyout, time, size, stacks);
self:IgnoreMessage(ERR_AUCTION_STARTED, stacks);
-- If it's a multisell, wait for it to complete. Note that we might
-- sell fewer items than originally requested if the user cancels.
if stacks > 1 then
self:WaitForMultisell();
stacks = MultisellCreated;
end
-- Now wait for the inventory to be updated so that CountItems doesn't
-- get confused later.
self:WaitForQuantity(link, count - (size * stacks));
-- And tell the user what we did.
self:Print(L["Created %d |4auction:auctions; of %s x%d (%s total)."]:
format(stacks, name, size, self:PrintMoney(stacks * buyout)));
end
end
-- Create new auctions based on the fields in the "Sell" tab.
function AuctionLite:CreateAuctionsCore()
-- TODO: check stack size against max size
if not Selling then
Selling = true;
local name, _, count, _, _, _, link, sellContainer, sellSlot =
self:GetAuctionSellItemInfoAndLink();
local stacks = SellStacks:GetNumber();
local size = SellSize:GetNumber();
local bid = MoneyInputFrame_GetCopper(SellBidPrice);
local buyout = MoneyInputFrame_GetCopper(SellBuyoutPrice);
local time = self:GetDuration();
local numItems = self:CountItems(link);
local maxSize = self:GetMaxStackSize(link);
-- If we're pricing per item, then get the stack price.
if self.db.profile.method == 1 then
bid = bid * size;
buyout = buyout * size;
end
-- Now do some sanity checks.
if name == nil then
self:Print(L["Error locating item in bags. Please try again!"]);
elseif bid == 0 then
self:Print(L["Invalid starting bid."]);
elseif 0 < buyout and buyout < bid then
self:Print(L["Buyout cannot be less than starting bid."]);
elseif GetMoney() < self:CalculateDeposit() then
self:Print(L["Not enough cash for deposit."]);
elseif numItems < stacks * size then
self:Print(L["Not enough items available."]);
elseif maxSize < size then
self:Print(L["Stack size too large."]);
elseif count ~= nil and stacks > 0 then
local created = 0;
-- Disable the auction creation button.
SellCreateAuctionButton:Disable();
-- Sell the main batch of items.
self:StartAuctions(bid, buyout, time, size, stacks, name, link);
-- We're done; clear the frame.
self:ClearSellFrame();
end
Selling = false;
else
self:Print(L["Auction creation is already in progress."]);
end
end
-- Start a coroutine to create auctions.
function AuctionLite:CreateAuctions()
self:StartCoroutine(function() AuctionLite:CreateAuctionsCore() end);
end
-------------------------------------------------------------------------------
-- Coroutine functions
-------------------------------------------------------------------------------
-- Yield until the number of items in the inventory drops below a threshold.
function AuctionLite:WaitForQuantity(link, qty)
self:WaitUntil(function()
local count = self:CountItems(link);
return (count <= qty);
end);
end
-- Yield until a multisell operation completes.
function AuctionLite:WaitForMultisell()
self:WaitUntil(function()
return MultisellDone;
end);
end
-- Yield until a condition is true.
function AuctionLite:WaitUntil(cond)
while not cond() do
coroutine.yield();
end
end
-- Start a coroutine to call the specified function.
function AuctionLite:StartCoroutine(fn)
if Coro == nil then
Coro = coroutine.create(fn);
AuctionLite:ResumeCoroutine();
end
end
-- Resume the stalled coroutine.
function AuctionLite:ResumeCoroutine()
if Coro ~= nil and coroutine.status(Coro) == "suspended" then
coroutine.resume(Coro)
if coroutine.status(Coro) == "dead" then
Coro = nil;
end
end
end
-------------------------------------------------------------------------------
-- Coroutine hooks
-------------------------------------------------------------------------------
function AuctionLite:BAG_UPDATE()
self:ResumeCoroutine();
end
function AuctionLite:AUCTION_MULTISELL_UPDATE(_, cur, total)
MultisellCreated = cur;
if cur == total then
MultisellDone = true;
self:ResumeCoroutine();
end
end
function AuctionLite:AUCTION_MULTISELL_FAILURE(_, cur, total)
MultisellDone = true;
MultisellError = true;
self:ResumeCoroutine();
end
-- Add the hooks needed for our coroutines.
function AuctionLite:HookCoroutines()
self:RegisterEvent("BAG_UPDATE");
self:RegisterEvent("AUCTION_MULTISELL_UPDATE");
self:RegisterEvent("AUCTION_MULTISELL_FAILURE");
end
-------------------------------------------------------------------------------
-- Miscellaneous
-------------------------------------------------------------------------------
-- Indicate whether we're creating auctions.
function AuctionLite:CreateInProgress()
return Selling;
end
-- Reset state. Useful for recovering from bugs.
function AuctionLite:ResetAuctionCreation()
Selling = false;
MultisellCreated = 0;
MultisellDone = false;
MultisellError = false;
Coro = nil;
end