|
|
|
|
@ -436,6 +436,102 @@ function private:StartAutoLooting(mode)
|
|
|
|
|
private:AutoLoot() |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function CanLootItem(itemString, quantity) |
|
|
|
|
if not itemString or not quantity then return false end |
|
|
|
|
local maxStack = select(8, TSMAPI:GetSafeItemInfo(itemString)) |
|
|
|
|
local hasPartial = false |
|
|
|
|
local hasEmpty = false |
|
|
|
|
local totalFreeSlots = 0 |
|
|
|
|
|
|
|
|
|
for bag = 0, NUM_BAG_SLOTS do |
|
|
|
|
if TSMAPI:ItemWillGoInBag(itemString, bag) then |
|
|
|
|
totalFreeSlots = totalFreeSlots + (GetContainerNumFreeSlots(bag) or 0) |
|
|
|
|
for slot = 1, GetContainerNumSlots(bag) do |
|
|
|
|
local iLink = GetContainerItemLink(bag, slot) |
|
|
|
|
if iLink then |
|
|
|
|
if TSMAPI:GetItemString(iLink) == itemString and maxStack then |
|
|
|
|
local stackSize = select(2, GetContainerItemInfo(bag, slot)) |
|
|
|
|
if stackSize and (maxStack - stackSize) >= quantity then |
|
|
|
|
hasPartial = true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
hasEmpty = true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if hasPartial then |
|
|
|
|
return true |
|
|
|
|
end |
|
|
|
|
if not hasEmpty then |
|
|
|
|
return false |
|
|
|
|
end |
|
|
|
|
if TSM.db.global.keepMailSpace and TSM.db.global.keepMailSpace > 0 then |
|
|
|
|
return (totalFreeSlots - 1) >= TSM.db.global.keepMailSpace |
|
|
|
|
end |
|
|
|
|
return true |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function HasFittableStack(itemString, needed) |
|
|
|
|
if not itemString or not needed or needed <= 0 then return false end |
|
|
|
|
for i = 1, GetInboxNumItems() do |
|
|
|
|
local _, _, _, _, _, cod, _, hasItem = GetInboxHeaderInfo(i) |
|
|
|
|
if hasItem and hasItem > 0 and (not cod or cod == 0) then |
|
|
|
|
for j = 1, hasItem do |
|
|
|
|
local itemLink = GetInboxItemLink(i, j) |
|
|
|
|
if itemLink and TSMAPI:GetItemString(itemLink) == itemString then |
|
|
|
|
local quantity = select(3, GetInboxItem(i, j)) or 0 |
|
|
|
|
if quantity > 0 and quantity <= needed then |
|
|
|
|
return true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
return false |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function Inbox:CollectItems(items, callback) |
|
|
|
|
if not items or not next(items) then return end |
|
|
|
|
if not MailFrame or not MailFrame:IsShown() then return end |
|
|
|
|
|
|
|
|
|
local remaining = CopyTable(items) |
|
|
|
|
local collected = false |
|
|
|
|
for i = GetInboxNumItems(), 1, -1 do |
|
|
|
|
local _, _, _, _, _, cod, _, hasItem = GetInboxHeaderInfo(i) |
|
|
|
|
if hasItem and hasItem > 0 and (not cod or cod == 0) then |
|
|
|
|
for j = hasItem, 1, -1 do |
|
|
|
|
local itemLink = GetInboxItemLink(i, j) |
|
|
|
|
local itemString = itemLink and TSMAPI:GetItemString(itemLink) |
|
|
|
|
local need = itemString and remaining[itemString] |
|
|
|
|
if need and need > 0 then |
|
|
|
|
local quantity = select(3, GetInboxItem(i, j)) or 0 |
|
|
|
|
if quantity > 0 and (quantity <= need or not HasFittableStack(itemString, need)) then |
|
|
|
|
if CanLootItem(itemString, quantity) then |
|
|
|
|
TakeInboxItem(i, j) |
|
|
|
|
remaining[itemString] = max(need - quantity, 0) |
|
|
|
|
collected = true |
|
|
|
|
elseif callback then |
|
|
|
|
callback(L["Cannot finish auto looting, inventory is full or too many unique items."]) |
|
|
|
|
return |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- Keep looting as new mail indexes shift, while preserving 1 free slot. |
|
|
|
|
if collected then |
|
|
|
|
TSMAPI:CreateTimeDelay("craftingGatherMailLoop", 0.4, function() |
|
|
|
|
Inbox:CollectItems(remaining, callback) |
|
|
|
|
end) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function private:AutoLoot() |
|
|
|
|
TSMAPI:CancelFrame("mailSkipDelay") |
|
|
|
|
|
|
|
|
|
|