Added personal and realm bank implementations (#27)
* added personal and realm bank implementations * fix gathering from personal and realm banks * faster gathering from personal and realm banks * Fix Profession Multiselect on Gathering window * cleaner GetAscensionBankType function * craft queue update
This commit is contained in:
@@ -539,9 +539,13 @@ function GUI:CreateQueueFrame(parent)
|
||||
end
|
||||
|
||||
end
|
||||
-- Position tooltip next to the row, on left or right depending on screen position
|
||||
GameTooltip:SetOwner(self, "ANCHOR_NONE")
|
||||
-- GameTooltip:SetPoint("LEFT", self, "RIGHT")
|
||||
GameTooltip:SetPoint("LEFT", self, "LEFT")
|
||||
if self:GetRight() >= (GetScreenWidth() / 2) then
|
||||
GameTooltip:SetPoint("TOPRIGHT", self, "TOPLEFT", -5, 0)
|
||||
else
|
||||
GameTooltip:SetPoint("TOPLEFT", self, "TOPRIGHT", 5, 0)
|
||||
end
|
||||
GameTooltip:AddLine(TSM.db.realm.crafts[data.spellID].name .. " (x" .. data.numQueued .. ")")
|
||||
|
||||
local cost = TSM.Cost:GetCraftPrices(data.spellID)
|
||||
@@ -621,6 +625,8 @@ function GUI:CreateQueueFrame(parent)
|
||||
name = color .. inventory .. "/" .. need .. "|r " .. name
|
||||
GameTooltip:AddLine(name, 1, 1, 1)
|
||||
end
|
||||
GameTooltip:AddLine(" ")
|
||||
GameTooltip:AddLine("|cff00ff00Ctrl+Click|r to remove from queue", 0.7, 0.7, 0.7)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
@@ -644,6 +650,13 @@ function GUI:CreateQueueFrame(parent)
|
||||
TSM.db.realm.queueStatus.collapsed[data.profession] = not TSM.db.realm.queueStatus.collapsed[data.profession]
|
||||
end
|
||||
GUI:UpdateQueue()
|
||||
elseif data.spellID and IsControlKeyDown() then
|
||||
-- Ctrl+Left-Click: Remove item from queue
|
||||
local craft = TSM.db.realm.crafts[data.spellID]
|
||||
if craft then
|
||||
craft.queued = 0
|
||||
GUI:UpdateQueue()
|
||||
end
|
||||
elseif data.index then
|
||||
GUI:CastTradeSkill(data.index, min(data.canCraft, data.numQueued), data.velName)
|
||||
end
|
||||
@@ -739,20 +752,31 @@ function GUI:CreateQueueFrame(parent)
|
||||
btn:SetHeight(20)
|
||||
btn:SetText(L["Clear Queue"])
|
||||
btn:SetScript("OnClick", function()
|
||||
TSM.Queue:ClearQueue()
|
||||
GUI:UpdateQueue()
|
||||
if GUI.frame.gather:IsVisible() then
|
||||
GUI.frame.gather:Hide()
|
||||
end
|
||||
private.gather = {}
|
||||
GUI:UpdateGatherSelectionWindow()
|
||||
if GUI.gatheringFrame:IsShown() then
|
||||
GUI.gatheringFrame:Hide()
|
||||
TSM.db.realm.gathering.crafter = nil
|
||||
TSM.db.realm.gathering.neededMats = {}
|
||||
TSM.db.realm.gathering.gatheredMats = false
|
||||
TSM.db.realm.sourceStatus.collapsed = {}
|
||||
end
|
||||
StaticPopupDialogs["TSM_CRAFTING_CLEAR_QUEUE"] = StaticPopupDialogs["TSM_CRAFTING_CLEAR_QUEUE"] or {
|
||||
text = L["Are you sure you want to clear the entire queue?"],
|
||||
button1 = YES,
|
||||
button2 = CANCEL,
|
||||
timeout = 0,
|
||||
hideOnEscape = true,
|
||||
OnAccept = function()
|
||||
TSM.Queue:ClearQueue()
|
||||
GUI:UpdateQueue()
|
||||
if GUI.frame.gather:IsVisible() then
|
||||
GUI.frame.gather:Hide()
|
||||
end
|
||||
private.gather = {}
|
||||
GUI:UpdateGatherSelectionWindow()
|
||||
if GUI.gatheringFrame:IsShown() then
|
||||
GUI.gatheringFrame:Hide()
|
||||
TSM.db.realm.gathering.crafter = nil
|
||||
TSM.db.realm.gathering.neededMats = {}
|
||||
TSM.db.realm.gathering.gatheredMats = false
|
||||
TSM.db.realm.sourceStatus.collapsed = {}
|
||||
end
|
||||
end,
|
||||
preferredIndex = 3,
|
||||
}
|
||||
TSMAPI:ShowStaticPopupDialog("TSM_CRAFTING_CLEAR_QUEUE")
|
||||
end)
|
||||
frame.clearBtn = btn
|
||||
|
||||
@@ -2041,7 +2065,12 @@ function GUI:CreateGatheringSelectionFrame(parent)
|
||||
dropdown:SetMultiselect(true)
|
||||
dropdown:SetCallback("OnValueChanged", function(_, _, profession, value)
|
||||
private.gather.professions[profession] = value or nil
|
||||
GUI:UpdateGatherSelectionWindow()
|
||||
-- Only update the button state, don't rebuild the dropdown list
|
||||
if next(private.gather.professions) then
|
||||
frame.gatherButton:Enable()
|
||||
else
|
||||
frame.gatherButton:Disable()
|
||||
end
|
||||
end)
|
||||
frame.professionDropdown = dropdown
|
||||
|
||||
@@ -2622,8 +2651,19 @@ function GUI:GatheringEventHandler(event)
|
||||
if not GUI.gatheringFrame or not GUI.gatheringFrame:IsShown() then return end
|
||||
|
||||
if event == "GUILDBANKFRAME_OPENED" then
|
||||
private.currentSource = UnitName("player")
|
||||
private.currentTask = L["Visit Guild Bank"]
|
||||
-- Ascension WoW: Detect bank type based on first tab name
|
||||
local numTabs = GetNumGuildBankTabs()
|
||||
local firstTabName = numTabs > 0 and GetGuildBankTabInfo(1) or nil
|
||||
if firstTabName == "Personal Bank" then
|
||||
private.currentSource = UnitName("player")
|
||||
private.currentTask = L["Visit Personal Bank"]
|
||||
elseif firstTabName == "Realm Bank" then
|
||||
private.currentSource = L["Realm Bank"]
|
||||
private.currentTask = L["Visit Realm Bank"]
|
||||
else
|
||||
private.currentSource = UnitName("player")
|
||||
private.currentTask = L["Visit Guild Bank"]
|
||||
end
|
||||
elseif event == "GUILDBANKFRAME_CLOSED" then
|
||||
private.currentSource = nil
|
||||
private.currentTask = nil
|
||||
|
||||
@@ -34,7 +34,7 @@ function Gather:gatherItems(source, task)
|
||||
|
||||
if source == L["Vendor"] then
|
||||
Gather:BuyFromMerchant(items)
|
||||
elseif source == UnitName("player") and (task == L["Visit Bank"] or task == L["Visit Guild Bank"]) then
|
||||
elseif (source == UnitName("player") or source == L["Realm Bank"]) and (task == L["Visit Bank"] or task == L["Visit Guild Bank"] or task == L["Visit Personal Bank"] or task == L["Visit Realm Bank"]) then
|
||||
Gather:GatherBank(items)
|
||||
elseif source == UnitName("player") and task == L["Mail Items"] then
|
||||
Gather:MailItems(items)
|
||||
|
||||
@@ -1,340 +1,416 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Crafting --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_crafting --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
-- load the parent file (TSM) into a local variable and register this file as a module
|
||||
local TSM = select(2, ...)
|
||||
local Inventory = TSM:NewModule("Inventory", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Crafting") -- loads the localization table
|
||||
|
||||
|
||||
-- gets the number of an item in the current player's bags
|
||||
function Inventory:GetPlayerBagNum(itemString)
|
||||
if not itemString then return end
|
||||
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
return GetItemCount(itemString)
|
||||
else
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", UnitName("player")) or {}
|
||||
return bags and bags[itemString] or 0
|
||||
end
|
||||
end
|
||||
|
||||
function Inventory:GetTotals()
|
||||
local bagTotal, auctionTotal, otherTotal, total = {}, {}, {}, {}
|
||||
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
|
||||
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
|
||||
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {}
|
||||
for itemString, quantity in pairs(bags) do
|
||||
if player == UnitName("player") then
|
||||
bagTotal[itemString] = (bagTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
else
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
for itemString, quantity in pairs(bank) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
for itemString, quantity in pairs(mail) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
for itemString, quantity in pairs(auctions) do
|
||||
auctionTotal[itemString] = (auctionTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for itemString in pairs(TSMAPI.SOULBOUND_MATS) do
|
||||
local bagNum = GetItemCount(itemString)
|
||||
local bankNum = GetItemCount(itemString, true) - GetItemCount(itemString)
|
||||
bagTotal[itemString] = (bagTotal[itemString] or 0) + bagNum
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + bankNum
|
||||
total[itemString] = (total[itemString] or 0) + bagNum + bankNum
|
||||
end
|
||||
|
||||
-- add gbank counts of all non-ignored guilds
|
||||
for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do
|
||||
if not TSM.db.global.ignoreGuilds[guild] then
|
||||
local gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
|
||||
for itemString, quantity in pairs(gbank) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
return bagTotal, auctionTotal, otherTotal, total
|
||||
end
|
||||
|
||||
-- gets the total number of some item that they have
|
||||
function Inventory:GetTotalQuantity(itemString)
|
||||
if not itemString then return 0 end
|
||||
local count = 0
|
||||
|
||||
-- add bags/bank/mail/auction counts of all non-ignored characters (always including current character)
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
|
||||
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
|
||||
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {}
|
||||
count = count + (bags[itemString] or 0)
|
||||
count = count + (bank[itemString] or 0)
|
||||
count = count + (mail[itemString] or 0)
|
||||
count = count + (auctions[itemString] or 0)
|
||||
end
|
||||
end
|
||||
-- add gbank counts of all non-ignored guilds
|
||||
for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do
|
||||
if not TSM.db.global.ignoreGuilds[guild] then
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
|
||||
count = count + (bank[itemString] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
count = count + GetItemCount(itemString, true)
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function Inventory:GetItemSources(crafter, neededMats)
|
||||
if not neededMats then return end
|
||||
local sources = {}
|
||||
local gbank = {}
|
||||
local next = next
|
||||
local crafterBags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", crafter) or {}
|
||||
local crafterMail = TSMAPI:ModuleAPI("ItemTracker", "playermail", crafter) or {}
|
||||
local crafterBank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", crafter) or {}
|
||||
|
||||
-- add vendor items
|
||||
local task = {}
|
||||
local items = {}
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
if TSMAPI:GetVendorCost(itemString) then
|
||||
local vendorNeed = quantity - ((crafterBags[itemString] or 0) + (crafterMail[itemString] or 0) + (crafterBank[itemString] or 0))
|
||||
if vendorNeed > 0 then
|
||||
items[itemString] = vendorNeed
|
||||
end
|
||||
elseif TSMAPI.Conversions[itemString] and TSMAPI.InkConversions[itemString] then
|
||||
local tradeItem, data = next(TSMAPI.Conversions[itemString])
|
||||
if data.source == "vendortrade" then
|
||||
local num = floor(Inventory:GetTotalQuantity(tradeItem) * data.rate)
|
||||
if quantity > Inventory:GetTotalQuantity(itemString) and num >= (quantity - Inventory:GetTotalQuantity(itemString)) then
|
||||
items[itemString] = quantity - Inventory:GetTotalQuantity(itemString)
|
||||
neededMats[tradeItem] = (neededMats[tradeItem] or 0) + quantity / data.rate -- add the qty of IOD to needed mats
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if next(items) then
|
||||
tinsert(task, { taskType = L["Visit Vendor"], items = items })
|
||||
tinsert(sources, { sourceName = L["Vendor"], isCrafter = false, isVendor = true, isAH = false, tasks = task })
|
||||
end
|
||||
|
||||
-- double check if crafter already has all the items needed
|
||||
local shortItems = {}
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
local soulboundBagCount
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
soulboundBagCount = GetItemCount(itemString)
|
||||
end
|
||||
local need = max(quantity - (crafterBags[itemString] or soulboundBagCount or 0), 0)
|
||||
if need > 0 then
|
||||
shortItems[itemString] = need
|
||||
end
|
||||
end
|
||||
if not next(shortItems) then return end
|
||||
|
||||
-- add bags/bank/mail "tasks" for needed items of all non-ignored characters (always include crafter)
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == crafter or not TSM.db.global.ignoreCharacters[player] then
|
||||
local task = {}
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
|
||||
local guild = TSMAPI:ModuleAPI("ItemTracker", "playerguild", player) or {}
|
||||
local gbank = {}
|
||||
if guild and not TSM.db.global.ignoreGuilds[guild] then
|
||||
gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
|
||||
end
|
||||
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
|
||||
local bankItems = {}
|
||||
local gbankItems = {}
|
||||
local mailItems = {}
|
||||
local bagItems = {}
|
||||
|
||||
for itemString in pairs(neededMats) do
|
||||
local soulboundBagCount, soulboundBankCount
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
soulboundBagCount = GetItemCount(itemString)
|
||||
soulboundBankCount = GetItemCount(itemString, true) - soulboundBagCount
|
||||
end
|
||||
if (bank[itemString] or (soulboundBankCount and soulboundBankCount > 0)) and shortItems[itemString] then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
|
||||
bankItems[itemString] = bank[itemString] or soulboundBankCount
|
||||
end
|
||||
end
|
||||
if gbank[itemString] and shortItems[itemString] then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
|
||||
gbankItems[itemString] = gbank[itemString]
|
||||
end
|
||||
end
|
||||
if mail[itemString] and shortItems[itemString] then
|
||||
mailItems[itemString] = mail[itemString]
|
||||
end
|
||||
if bags[itemString] and shortItems[itemString] then
|
||||
if player ~= crafter then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) > 0 then
|
||||
bagItems[itemString] = bags[itemString]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- add mail tasks for destroyable items bought through shopping search (exclude items already added to mail tasks)
|
||||
for itemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do
|
||||
if mail[itemString] and not shortItems[itemString] then
|
||||
mailItems[itemString] = quantity
|
||||
end
|
||||
end
|
||||
|
||||
if next(bankItems) then
|
||||
tinsert(task, { taskType = L["Visit Bank"], items = bankItems })
|
||||
end
|
||||
if next(gbankItems) then
|
||||
tinsert(task, { taskType = L["Visit Guild Bank"], items = gbankItems })
|
||||
end
|
||||
if next(mailItems) then
|
||||
tinsert(task, { taskType = L["Collect Mail"], items = mailItems })
|
||||
end
|
||||
if next(bagItems) then
|
||||
tinsert(task, { taskType = L["Mail Items"], items = bagItems })
|
||||
end
|
||||
if next(task) then
|
||||
tinsert(sources, { sourceName = player, isCrafter = player == crafter, isVendor = false, isAH = false, tasks = task, isCurrent = (player == UnitName("player")) })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- add auction house tasks
|
||||
local auctionTask = {}
|
||||
local auctionItems = {}
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
if not TSMAPI.SOULBOUND_MATS[itemString] and not TSMAPI:GetVendorCost(itemString) then
|
||||
local need
|
||||
if TSM.Inventory.gatherItem == itemString and TSM.Inventory.gatherQuantity then
|
||||
need = TSM.Inventory.gatherQuantity
|
||||
else
|
||||
need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0)
|
||||
end
|
||||
if need > 0 then
|
||||
auctionItems[itemString] = need
|
||||
end
|
||||
end
|
||||
end
|
||||
if next(auctionItems) then
|
||||
tinsert(auctionTask, { taskType = L["Search for Mats"], items = auctionItems })
|
||||
tinsert(sources, { sourceName = L["Auction House"], isCrafter = false, isVendor = false, isAH = true, tasks = auctionTask })
|
||||
end
|
||||
|
||||
-- add destroying tasks
|
||||
local destroyingTask, millItems, prospectItems, transformItems, deItems = {}, {}, {}, {}, {}
|
||||
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
local need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0)
|
||||
-- conversion items
|
||||
for destroyItem, data in pairs(TSMAPI.Conversions[itemString] or {}) do
|
||||
if TSM.db.realm.gathering.destroyingMats[destroyItem] then
|
||||
if need > 0 then
|
||||
local destroyNeed
|
||||
if data.source == "mill" then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5)
|
||||
if destroyNeed > 0 then
|
||||
millItems[destroyItem] = (millItems[destroyItem] or 0) + destroyNeed
|
||||
end
|
||||
elseif data.source == "prospect" then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5)
|
||||
if destroyNeed > 0 then
|
||||
prospectItems[destroyItem] = (prospectItems[destroyItem] or 0) + destroyNeed
|
||||
end
|
||||
elseif data.source == "transform" then
|
||||
if data.rate == 1 / 3 then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 3)
|
||||
elseif data.rate == 1 / 10 then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 10)
|
||||
else
|
||||
destroyNeed = TSM.db.realm.gathering.destroyingMats[destroyItem]
|
||||
end
|
||||
if destroyNeed > 0 then
|
||||
transformItems[destroyItem] = (transformItems[destroyItem] or 0) + destroyNeed
|
||||
end
|
||||
end
|
||||
else
|
||||
TSM.db.realm.gathering.destroyingMats[destroyItem] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
-- disenchantable items
|
||||
if next(TSM.db.realm.gathering.destroyingMats) then
|
||||
for deItemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do
|
||||
if Inventory:IsDisenchantable(deItemString) then
|
||||
if need > 0 then
|
||||
deItems[deItemString] = quantity
|
||||
else
|
||||
TSM.db.realm.gathering.destroyingMats[deItemString] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(millItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Milling"], items = millItems })
|
||||
end
|
||||
if next(prospectItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Prospect"], items = prospectItems })
|
||||
end
|
||||
if next(transformItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Transform"], items = transformItems })
|
||||
end
|
||||
if next(deItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Disenchant"], items = deItems })
|
||||
end
|
||||
if next(destroyingTask) then
|
||||
tinsert(sources, { sourceName = L["Destroying"], isCrafter = false, isVendor = false, isAH = true, tasks = destroyingTask })
|
||||
end
|
||||
|
||||
|
||||
sort(sources, function(a, b)
|
||||
if a.isCurrent then return true end
|
||||
if b.isCurrent then return false end
|
||||
if a.isAH then return false end
|
||||
if b.isAH then return true end
|
||||
if a.isVendor then return false end
|
||||
if b.isVendor then return true end
|
||||
if a.isCrafter then return false end
|
||||
if b.isCrafter then return true end
|
||||
return a.sourceName < b.sourceName
|
||||
end)
|
||||
return sources
|
||||
end
|
||||
|
||||
function Inventory:IsDisenchantable(itemString)
|
||||
local _, link, quality, _, _, iType = TSMAPI:GetSafeItemInfo(itemString)
|
||||
local WEAPON, ARMOR = GetAuctionItemClasses()
|
||||
if itemString and not TSMAPI.DisenchantingData.notDisenchantable[itemString] and (iType == ARMOR or iType == WEAPON) then
|
||||
return true
|
||||
end
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster_Crafting --
|
||||
-- http://www.curse.com/addons/wow/tradeskillmaster_crafting --
|
||||
-- --
|
||||
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
|
||||
-- All Rights Reserved* - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
-- load the parent file (TSM) into a local variable and register this file as a module
|
||||
local TSM = select(2, ...)
|
||||
local Inventory = TSM:NewModule("Inventory", "AceEvent-3.0")
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Crafting") -- loads the localization table
|
||||
|
||||
|
||||
-- gets the number of an item in the current player's bags
|
||||
function Inventory:GetPlayerBagNum(itemString)
|
||||
if not itemString then return end
|
||||
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
return GetItemCount(itemString)
|
||||
else
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", UnitName("player")) or {}
|
||||
return bags and bags[itemString] or 0
|
||||
end
|
||||
end
|
||||
|
||||
function Inventory:GetTotals()
|
||||
local bagTotal, auctionTotal, otherTotal, total = {}, {}, {}, {}
|
||||
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
|
||||
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
|
||||
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {}
|
||||
for itemString, quantity in pairs(bags) do
|
||||
if player == UnitName("player") then
|
||||
bagTotal[itemString] = (bagTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
else
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
for itemString, quantity in pairs(bank) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
for itemString, quantity in pairs(mail) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
for itemString, quantity in pairs(auctions) do
|
||||
auctionTotal[itemString] = (auctionTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for itemString in pairs(TSMAPI.SOULBOUND_MATS) do
|
||||
local bagNum = GetItemCount(itemString)
|
||||
local bankNum = GetItemCount(itemString, true) - GetItemCount(itemString)
|
||||
bagTotal[itemString] = (bagTotal[itemString] or 0) + bagNum
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + bankNum
|
||||
total[itemString] = (total[itemString] or 0) + bagNum + bankNum
|
||||
end
|
||||
|
||||
-- add gbank counts of all non-ignored guilds
|
||||
for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do
|
||||
if not TSM.db.global.ignoreGuilds[guild] then
|
||||
local gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
|
||||
for itemString, quantity in pairs(gbank) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Ascension WoW: add personal bank counts for all non-ignored characters
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
|
||||
local personalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", player) or {}
|
||||
for itemString, quantity in pairs(personalBank) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Ascension WoW: add realm bank counts
|
||||
local realmBank = TSMAPI:ModuleAPI("ItemTracker", "realmbank") or {}
|
||||
for itemString, quantity in pairs(realmBank) do
|
||||
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
|
||||
total[itemString] = (total[itemString] or 0) + quantity
|
||||
end
|
||||
|
||||
return bagTotal, auctionTotal, otherTotal, total
|
||||
end
|
||||
|
||||
-- gets the total number of some item that they have
|
||||
function Inventory:GetTotalQuantity(itemString)
|
||||
if not itemString then return 0 end
|
||||
local count = 0
|
||||
|
||||
-- add bags/bank/mail/auction counts of all non-ignored characters (always including current character)
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
|
||||
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
|
||||
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {}
|
||||
count = count + (bags[itemString] or 0)
|
||||
count = count + (bank[itemString] or 0)
|
||||
count = count + (mail[itemString] or 0)
|
||||
count = count + (auctions[itemString] or 0)
|
||||
end
|
||||
end
|
||||
-- add gbank counts of all non-ignored guilds
|
||||
for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do
|
||||
if not TSM.db.global.ignoreGuilds[guild] then
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
|
||||
count = count + (bank[itemString] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Ascension WoW: add personal bank counts for all non-ignored characters
|
||||
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
|
||||
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
|
||||
local personalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", player) or {}
|
||||
count = count + (personalBank[itemString] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Ascension WoW: add realm bank count
|
||||
local realmBank = TSMAPI:ModuleAPI("ItemTracker", "realmbank") or {}
|
||||
count = count + (realmBank[itemString] or 0)
|
||||
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
count = count + GetItemCount(itemString, true)
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function Inventory:GetItemSources(crafter, neededMats)
|
||||
if not neededMats then return end
|
||||
local sources = {}
|
||||
local gbank = {}
|
||||
local next = next
|
||||
local crafterBags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", crafter) or {}
|
||||
local crafterMail = TSMAPI:ModuleAPI("ItemTracker", "playermail", crafter) or {}
|
||||
local crafterBank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", crafter) or {}
|
||||
-- Ascension WoW: crafter's personal bank
|
||||
local crafterPersonalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", crafter) or {}
|
||||
|
||||
-- add vendor items
|
||||
local task = {}
|
||||
local items = {}
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
if TSMAPI:GetVendorCost(itemString) then
|
||||
local vendorNeed = quantity - ((crafterBags[itemString] or 0) + (crafterMail[itemString] or 0) + (crafterBank[itemString] or 0) + (crafterPersonalBank[itemString] or 0))
|
||||
if vendorNeed > 0 then
|
||||
items[itemString] = vendorNeed
|
||||
end
|
||||
elseif TSMAPI.Conversions[itemString] and TSMAPI.InkConversions[itemString] then
|
||||
local tradeItem, data = next(TSMAPI.Conversions[itemString])
|
||||
if data.source == "vendortrade" then
|
||||
local num = floor(Inventory:GetTotalQuantity(tradeItem) * data.rate)
|
||||
if quantity > Inventory:GetTotalQuantity(itemString) and num >= (quantity - Inventory:GetTotalQuantity(itemString)) then
|
||||
items[itemString] = quantity - Inventory:GetTotalQuantity(itemString)
|
||||
neededMats[tradeItem] = (neededMats[tradeItem] or 0) + quantity / data.rate -- add the qty of IOD to needed mats
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if next(items) then
|
||||
tinsert(task, { taskType = L["Visit Vendor"], items = items })
|
||||
tinsert(sources, { sourceName = L["Vendor"], isCrafter = false, isVendor = true, isAH = false, tasks = task })
|
||||
end
|
||||
|
||||
-- double check if crafter already has all the items needed
|
||||
local shortItems = {}
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
local soulboundBagCount
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
soulboundBagCount = GetItemCount(itemString)
|
||||
end
|
||||
local inBags = crafterBags[itemString] or soulboundBagCount or 0
|
||||
local need = max(quantity - inBags, 0)
|
||||
if need > 0 then
|
||||
shortItems[itemString] = need
|
||||
end
|
||||
end
|
||||
if not next(shortItems) then
|
||||
return sources -- Return sources instead of nil so vendor items are not lost
|
||||
end
|
||||
|
||||
-- add bags/bank/mail "tasks" for needed items of all non-ignored characters (always include crafter)
|
||||
local playerList = TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}
|
||||
|
||||
for _, player in pairs(playerList) do
|
||||
if player == crafter or not TSM.db.global.ignoreCharacters[player] then
|
||||
local task = {}
|
||||
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
|
||||
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
|
||||
local guild = TSMAPI:ModuleAPI("ItemTracker", "playerguild", player) or {}
|
||||
local gbank = {}
|
||||
if guild and not TSM.db.global.ignoreGuilds[guild] then
|
||||
gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
|
||||
end
|
||||
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
|
||||
-- Ascension WoW: personal bank for this player
|
||||
local personalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", player) or {}
|
||||
local bankItems = {}
|
||||
local gbankItems = {}
|
||||
local mailItems = {}
|
||||
local bagItems = {}
|
||||
local personalBankItems = {}
|
||||
|
||||
for itemString in pairs(neededMats) do
|
||||
local soulboundBagCount, soulboundBankCount
|
||||
if TSMAPI.SOULBOUND_MATS[itemString] then
|
||||
soulboundBagCount = GetItemCount(itemString)
|
||||
soulboundBankCount = GetItemCount(itemString, true) - soulboundBagCount
|
||||
end
|
||||
if (bank[itemString] or (soulboundBankCount and soulboundBankCount > 0)) and shortItems[itemString] then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
|
||||
bankItems[itemString] = bank[itemString] or soulboundBankCount
|
||||
end
|
||||
end
|
||||
if gbank[itemString] and shortItems[itemString] then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
|
||||
gbankItems[itemString] = gbank[itemString]
|
||||
end
|
||||
end
|
||||
-- Ascension WoW: check personal bank
|
||||
if personalBank[itemString] and shortItems[itemString] then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
|
||||
personalBankItems[itemString] = personalBank[itemString]
|
||||
end
|
||||
end
|
||||
if mail[itemString] and shortItems[itemString] then
|
||||
mailItems[itemString] = mail[itemString]
|
||||
end
|
||||
if bags[itemString] and shortItems[itemString] then
|
||||
if player ~= crafter then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) > 0 then
|
||||
bagItems[itemString] = bags[itemString]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- add mail tasks for destroyable items bought through shopping search (exclude items already added to mail tasks)
|
||||
for itemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do
|
||||
if mail[itemString] and not shortItems[itemString] then
|
||||
mailItems[itemString] = quantity
|
||||
end
|
||||
end
|
||||
|
||||
if next(bankItems) then
|
||||
tinsert(task, { taskType = L["Visit Bank"], items = bankItems })
|
||||
end
|
||||
if next(gbankItems) then
|
||||
tinsert(task, { taskType = L["Visit Guild Bank"], items = gbankItems })
|
||||
end
|
||||
-- Ascension WoW: personal bank task
|
||||
if next(personalBankItems) then
|
||||
tinsert(task, { taskType = L["Visit Personal Bank"], items = personalBankItems })
|
||||
end
|
||||
if next(mailItems) then
|
||||
tinsert(task, { taskType = L["Collect Mail"], items = mailItems })
|
||||
end
|
||||
if next(bagItems) then
|
||||
tinsert(task, { taskType = L["Mail Items"], items = bagItems })
|
||||
end
|
||||
if next(task) then
|
||||
tinsert(sources, { sourceName = player, isCrafter = player == crafter, isVendor = false, isAH = false, tasks = task, isCurrent = (player == UnitName("player")) })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Ascension WoW: add realm bank as a separate source
|
||||
local realmBank = TSMAPI:ModuleAPI("ItemTracker", "realmbank") or {}
|
||||
local realmBankTask = {}
|
||||
local realmBankItems = {}
|
||||
for itemString in pairs(neededMats) do
|
||||
if realmBank[itemString] and shortItems[itemString] then
|
||||
if shortItems[itemString] - (crafterMail[itemString] or 0) > 0 then
|
||||
realmBankItems[itemString] = realmBank[itemString]
|
||||
end
|
||||
end
|
||||
end
|
||||
if next(realmBankItems) then
|
||||
tinsert(realmBankTask, { taskType = L["Visit Realm Bank"], items = realmBankItems })
|
||||
tinsert(sources, { sourceName = L["Realm Bank"], isCrafter = false, isVendor = false, isAH = false, tasks = realmBankTask, isCurrent = true })
|
||||
end
|
||||
|
||||
-- add auction house tasks
|
||||
local auctionTask = {}
|
||||
local auctionItems = {}
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
if not TSMAPI.SOULBOUND_MATS[itemString] and not TSMAPI:GetVendorCost(itemString) then
|
||||
local need
|
||||
if TSM.Inventory.gatherItem == itemString and TSM.Inventory.gatherQuantity then
|
||||
need = TSM.Inventory.gatherQuantity
|
||||
else
|
||||
need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0)
|
||||
end
|
||||
if need > 0 then
|
||||
auctionItems[itemString] = need
|
||||
end
|
||||
end
|
||||
end
|
||||
if next(auctionItems) then
|
||||
tinsert(auctionTask, { taskType = L["Search for Mats"], items = auctionItems })
|
||||
tinsert(sources, { sourceName = L["Auction House"], isCrafter = false, isVendor = false, isAH = true, tasks = auctionTask })
|
||||
end
|
||||
|
||||
-- add destroying tasks
|
||||
local destroyingTask, millItems, prospectItems, transformItems, deItems = {}, {}, {}, {}, {}
|
||||
|
||||
for itemString, quantity in pairs(neededMats) do
|
||||
local need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0)
|
||||
-- conversion items
|
||||
for destroyItem, data in pairs(TSMAPI.Conversions[itemString] or {}) do
|
||||
if TSM.db.realm.gathering.destroyingMats[destroyItem] then
|
||||
if need > 0 then
|
||||
local destroyNeed
|
||||
if data.source == "mill" then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5)
|
||||
if destroyNeed > 0 then
|
||||
millItems[destroyItem] = (millItems[destroyItem] or 0) + destroyNeed
|
||||
end
|
||||
elseif data.source == "prospect" then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5)
|
||||
if destroyNeed > 0 then
|
||||
prospectItems[destroyItem] = (prospectItems[destroyItem] or 0) + destroyNeed
|
||||
end
|
||||
elseif data.source == "transform" then
|
||||
if data.rate == 1 / 3 then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 3)
|
||||
elseif data.rate == 1 / 10 then
|
||||
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 10)
|
||||
else
|
||||
destroyNeed = TSM.db.realm.gathering.destroyingMats[destroyItem]
|
||||
end
|
||||
if destroyNeed > 0 then
|
||||
transformItems[destroyItem] = (transformItems[destroyItem] or 0) + destroyNeed
|
||||
end
|
||||
end
|
||||
else
|
||||
TSM.db.realm.gathering.destroyingMats[destroyItem] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
-- disenchantable items
|
||||
if next(TSM.db.realm.gathering.destroyingMats) then
|
||||
for deItemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do
|
||||
if Inventory:IsDisenchantable(deItemString) then
|
||||
if need > 0 then
|
||||
deItems[deItemString] = quantity
|
||||
else
|
||||
TSM.db.realm.gathering.destroyingMats[deItemString] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(millItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Milling"], items = millItems })
|
||||
end
|
||||
if next(prospectItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Prospect"], items = prospectItems })
|
||||
end
|
||||
if next(transformItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Transform"], items = transformItems })
|
||||
end
|
||||
if next(deItems) then
|
||||
tinsert(destroyingTask, { taskType = L["Disenchant"], items = deItems })
|
||||
end
|
||||
if next(destroyingTask) then
|
||||
tinsert(sources, { sourceName = L["Destroying"], isCrafter = false, isVendor = false, isAH = true, tasks = destroyingTask })
|
||||
end
|
||||
|
||||
|
||||
sort(sources, function(a, b)
|
||||
-- isCurrent sources come first
|
||||
if a.isCurrent ~= b.isCurrent then
|
||||
return a.isCurrent
|
||||
end
|
||||
-- AH sources come last
|
||||
if a.isAH ~= b.isAH then
|
||||
return b.isAH
|
||||
end
|
||||
-- Vendor sources come near last (before AH)
|
||||
if a.isVendor ~= b.isVendor then
|
||||
return b.isVendor
|
||||
end
|
||||
-- Crafter sources come after other players
|
||||
if a.isCrafter ~= b.isCrafter then
|
||||
return b.isCrafter
|
||||
end
|
||||
-- Alphabetical by name
|
||||
return a.sourceName < b.sourceName
|
||||
end)
|
||||
|
||||
return sources
|
||||
end
|
||||
|
||||
function Inventory:IsDisenchantable(itemString)
|
||||
local _, link, quality, _, _, iType = TSMAPI:GetSafeItemInfo(itemString)
|
||||
local WEAPON, ARMOR = GetAuctionItemClasses()
|
||||
if itemString and not TSMAPI.DisenchantingData.notDisenchantable[itemString] and (iType == ARMOR or iType == WEAPON) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user