------------------------------------------------------------------------------- -- 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