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