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:
Kian Soltani
2026-02-16 16:12:24 +01:00
committed by GitHub
parent 8a6c8fd3a2
commit 4a03ece3d3
10 changed files with 688 additions and 387 deletions
+3 -1
View File
@@ -4,4 +4,6 @@
.install .install
.lua/* .lua/*
.vscode .vscode
.idea .idea
deploy.bat
claude.md
+24 -2
View File
@@ -14,9 +14,19 @@ local AceGUI = LibStub("AceGUI-3.0") -- load the AceGUI libraries
local lib = TSMAPI local lib = TSMAPI
local bankType local bankType
local ascensionBankType
local fullMoves, splitMoves, bagState = {}, {}, {} local fullMoves, splitMoves, bagState = {}, {}, {}
local callbackMsg = {} local callbackMsg = {}
local function GetAscensionBankType()
if GuildBankFrame and GuildBankFrame.IsPersonalBank then
return "personal"
elseif GuildBankFrame and GuildBankFrame.IsRealmBank then
return "realm"
end
return nil
end
-- this is a set of wrapper functions so that I can switch -- this is a set of wrapper functions so that I can switch
-- between guildbank and bank function easily (taken from warehousing) -- between guildbank and bank function easily (taken from warehousing)
@@ -42,6 +52,7 @@ function TSM:OnEnable()
TSM:RegisterEvent("GUILDBANKFRAME_OPENED", function(event) TSM:RegisterEvent("GUILDBANKFRAME_OPENED", function(event)
bankType = "guildbank" bankType = "guildbank"
ascensionBankType = GetAscensionBankType() -- Ascension WoW: detect personal/realm bank
end) end)
TSM:RegisterEvent("BANKFRAME_OPENED", function(event) TSM:RegisterEvent("BANKFRAME_OPENED", function(event)
@@ -50,6 +61,7 @@ function TSM:OnEnable()
TSM:RegisterEvent("GUILDBANKFRAME_CLOSED", function(event, addon) TSM:RegisterEvent("GUILDBANKFRAME_CLOSED", function(event, addon)
bankType = nil bankType = nil
ascensionBankType = nil -- Ascension WoW: reset
TSM:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED") TSM:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED")
end) end)
@@ -402,13 +414,23 @@ function TSM.generateMoves(includeSoulbound)
if next(fullMoves) ~= nil then if next(fullMoves) ~= nil then
if bankType == "guildbank" then if bankType == "guildbank" then
TSMAPI:CreateTimeDelay("moveItem", 0.05, TSM.moveItem, 0.35) -- Ascension WoW: Personal/Realm banks don't need slow delays like real guild banks
if ascensionBankType then
TSMAPI:CreateTimeDelay("moveItem", 0.05, TSM.moveItem, 0.05)
else
TSMAPI:CreateTimeDelay("moveItem", 0.05, TSM.moveItem, 0.35)
end
else else
TSMAPI:CreateTimeDelay("moveItem", 0.05, TSM.moveItem, 0.05) TSMAPI:CreateTimeDelay("moveItem", 0.05, TSM.moveItem, 0.05)
end end
elseif next(splitMoves) ~= nil then elseif next(splitMoves) ~= nil then
if bankType == "guildbank" then if bankType == "guildbank" then
TSMAPI:CreateTimeDelay("moveSplitItem", 0.05, TSM.moveSplitItem, 0.75) -- Ascension WoW: Personal/Realm banks don't need slow delays like real guild banks
if ascensionBankType then
TSMAPI:CreateTimeDelay("moveSplitItem", 0.05, TSM.moveSplitItem, 0.1)
else
TSMAPI:CreateTimeDelay("moveSplitItem", 0.05, TSM.moveSplitItem, 0.75)
end
else else
TSMAPI:CreateTimeDelay("moveSplitItem", 0.05, TSM.moveSplitItem, 0.4) TSMAPI:CreateTimeDelay("moveSplitItem", 0.05, TSM.moveSplitItem, 0.4)
end end
@@ -83,9 +83,9 @@ function Post:GetScanListAndSetup(GUIRef, options)
totalToPost, totalPosted, count = 0, 0, 0 totalToPost, totalPosted, count = 0, 0, 0
local tempList, scanList = {}, {} local tempList, scanList = {}, {}
Post:UpdateBagState() Post:UpdateBagState()
local function HasEnoughToPost(operation, itemString) local function HasEnoughToPost(operation, itemString)
local maxStackSize = select(8, TSMAPI:GetSafeItemInfo(itemString)) or 1 local maxStackSize = select(8, TSMAPI:GetSafeItemInfo(itemString)) or 1
local perAuction = min(maxStackSize, operation.stackSize) local perAuction = min(maxStackSize, operation.stackSize)
@@ -129,7 +129,7 @@ function Post:GetScanListAndSetup(GUIRef, options)
tinsert(scanList, itemString) tinsert(scanList, itemString)
end end
end end
TSMAPI:FireEvent("AUCTIONING:POST:START", {numItems=#scanList, isGroup=true}) TSMAPI:FireEvent("AUCTIONING:POST:START", {numItems=#scanList, isGroup=true})
return scanList return scanList
end end
@@ -21,6 +21,7 @@ L["<< Hide Queue"] = true
L["<None>"] = true L["<None>"] = true
L["AH"] = true L["AH"] = true
L["All"] = true L["All"] = true
L["Are you sure you want to clear the entire queue?"] = true
L["Are you sure you want to reset all material prices to the default value?"] = true L["Are you sure you want to reset all material prices to the default value?"] = true
L["Ask Later"] = true L["Ask Later"] = true
L["Auction House"] = true L["Auction House"] = true
@@ -168,6 +169,9 @@ L["Total"] = true
L["Vendor"] = true L["Vendor"] = true
L["Visit Bank"] = true L["Visit Bank"] = true
L["Visit Guild Bank"] = true L["Visit Guild Bank"] = true
L["Visit Personal Bank"] = true
L["Visit Realm Bank"] = true
L["Realm Bank"] = true
L["Visit Vendor"] = true L["Visit Vendor"] = true
L["Warning: The min restock quantity must be lower than the max restock quantity."] = true L["Warning: The min restock quantity must be lower than the max restock quantity."] = true
L["When you click on the \"Restock Queue\" button enough of each craft will be queued so that you have this maximum number on hand. For example, if you have 2 of item X on hand and you set this to 4, 2 more will be added to the craft queue."] = true L["When you click on the \"Restock Queue\" button enough of each craft will be queued so that you have this maximum number on hand. For example, if you have 2 of item X on hand and you set this to 4, 2 more will be added to the craft queue."] = true
@@ -539,9 +539,13 @@ function GUI:CreateQueueFrame(parent)
end end
end end
-- Position tooltip next to the row, on left or right depending on screen position
GameTooltip:SetOwner(self, "ANCHOR_NONE") GameTooltip:SetOwner(self, "ANCHOR_NONE")
-- GameTooltip:SetPoint("LEFT", self, "RIGHT") if self:GetRight() >= (GetScreenWidth() / 2) then
GameTooltip:SetPoint("LEFT", self, "LEFT") 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 .. ")") GameTooltip:AddLine(TSM.db.realm.crafts[data.spellID].name .. " (x" .. data.numQueued .. ")")
local cost = TSM.Cost:GetCraftPrices(data.spellID) local cost = TSM.Cost:GetCraftPrices(data.spellID)
@@ -621,6 +625,8 @@ function GUI:CreateQueueFrame(parent)
name = color .. inventory .. "/" .. need .. "|r " .. name name = color .. inventory .. "/" .. need .. "|r " .. name
GameTooltip:AddLine(name, 1, 1, 1) GameTooltip:AddLine(name, 1, 1, 1)
end end
GameTooltip:AddLine(" ")
GameTooltip:AddLine("|cff00ff00Ctrl+Click|r to remove from queue", 0.7, 0.7, 0.7)
GameTooltip:Show() GameTooltip:Show()
end end
@@ -644,6 +650,13 @@ function GUI:CreateQueueFrame(parent)
TSM.db.realm.queueStatus.collapsed[data.profession] = not TSM.db.realm.queueStatus.collapsed[data.profession] TSM.db.realm.queueStatus.collapsed[data.profession] = not TSM.db.realm.queueStatus.collapsed[data.profession]
end end
GUI:UpdateQueue() 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 elseif data.index then
GUI:CastTradeSkill(data.index, min(data.canCraft, data.numQueued), data.velName) GUI:CastTradeSkill(data.index, min(data.canCraft, data.numQueued), data.velName)
end end
@@ -739,20 +752,31 @@ function GUI:CreateQueueFrame(parent)
btn:SetHeight(20) btn:SetHeight(20)
btn:SetText(L["Clear Queue"]) btn:SetText(L["Clear Queue"])
btn:SetScript("OnClick", function() btn:SetScript("OnClick", function()
TSM.Queue:ClearQueue() StaticPopupDialogs["TSM_CRAFTING_CLEAR_QUEUE"] = StaticPopupDialogs["TSM_CRAFTING_CLEAR_QUEUE"] or {
GUI:UpdateQueue() text = L["Are you sure you want to clear the entire queue?"],
if GUI.frame.gather:IsVisible() then button1 = YES,
GUI.frame.gather:Hide() button2 = CANCEL,
end timeout = 0,
private.gather = {} hideOnEscape = true,
GUI:UpdateGatherSelectionWindow() OnAccept = function()
if GUI.gatheringFrame:IsShown() then TSM.Queue:ClearQueue()
GUI.gatheringFrame:Hide() GUI:UpdateQueue()
TSM.db.realm.gathering.crafter = nil if GUI.frame.gather:IsVisible() then
TSM.db.realm.gathering.neededMats = {} GUI.frame.gather:Hide()
TSM.db.realm.gathering.gatheredMats = false end
TSM.db.realm.sourceStatus.collapsed = {} private.gather = {}
end 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) end)
frame.clearBtn = btn frame.clearBtn = btn
@@ -2041,7 +2065,12 @@ function GUI:CreateGatheringSelectionFrame(parent)
dropdown:SetMultiselect(true) dropdown:SetMultiselect(true)
dropdown:SetCallback("OnValueChanged", function(_, _, profession, value) dropdown:SetCallback("OnValueChanged", function(_, _, profession, value)
private.gather.professions[profession] = value or nil 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) end)
frame.professionDropdown = dropdown frame.professionDropdown = dropdown
@@ -2622,8 +2651,19 @@ function GUI:GatheringEventHandler(event)
if not GUI.gatheringFrame or not GUI.gatheringFrame:IsShown() then return end if not GUI.gatheringFrame or not GUI.gatheringFrame:IsShown() then return end
if event == "GUILDBANKFRAME_OPENED" then if event == "GUILDBANKFRAME_OPENED" then
private.currentSource = UnitName("player") -- Ascension WoW: Detect bank type based on first tab name
private.currentTask = L["Visit Guild Bank"] 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 elseif event == "GUILDBANKFRAME_CLOSED" then
private.currentSource = nil private.currentSource = nil
private.currentTask = nil private.currentTask = nil
+1 -1
View File
@@ -34,7 +34,7 @@ function Gather:gatherItems(source, task)
if source == L["Vendor"] then if source == L["Vendor"] then
Gather:BuyFromMerchant(items) 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) Gather:GatherBank(items)
elseif source == UnitName("player") and task == L["Mail Items"] then elseif source == UnitName("player") and task == L["Mail Items"] then
Gather:MailItems(items) Gather:MailItems(items)
+415 -339
View File
@@ -1,340 +1,416 @@
-- ------------------------------------------------------------------------------ -- -- ------------------------------------------------------------------------------ --
-- TradeSkillMaster_Crafting -- -- TradeSkillMaster_Crafting --
-- http://www.curse.com/addons/wow/tradeskillmaster_crafting -- -- http://www.curse.com/addons/wow/tradeskillmaster_crafting --
-- -- -- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) -- -- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. -- -- 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 -- load the parent file (TSM) into a local variable and register this file as a module
local TSM = select(2, ...) local TSM = select(2, ...)
local Inventory = TSM:NewModule("Inventory", "AceEvent-3.0") local Inventory = TSM:NewModule("Inventory", "AceEvent-3.0")
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Crafting") -- loads the localization table 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 -- gets the number of an item in the current player's bags
function Inventory:GetPlayerBagNum(itemString) function Inventory:GetPlayerBagNum(itemString)
if not itemString then return end if not itemString then return end
if TSMAPI.SOULBOUND_MATS[itemString] then if TSMAPI.SOULBOUND_MATS[itemString] then
return GetItemCount(itemString) return GetItemCount(itemString)
else else
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", UnitName("player")) or {} local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", UnitName("player")) or {}
return bags and bags[itemString] or 0 return bags and bags[itemString] or 0
end end
end end
function Inventory:GetTotals() function Inventory:GetTotals()
local bagTotal, auctionTotal, otherTotal, total = {}, {}, {}, {} local bagTotal, auctionTotal, otherTotal, total = {}, {}, {}, {}
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {} local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {} local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {} local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {} local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {}
for itemString, quantity in pairs(bags) do for itemString, quantity in pairs(bags) do
if player == UnitName("player") then if player == UnitName("player") then
bagTotal[itemString] = (bagTotal[itemString] or 0) + quantity bagTotal[itemString] = (bagTotal[itemString] or 0) + quantity
total[itemString] = (total[itemString] or 0) + quantity total[itemString] = (total[itemString] or 0) + quantity
else else
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
total[itemString] = (total[itemString] or 0) + quantity total[itemString] = (total[itemString] or 0) + quantity
end end
end end
for itemString, quantity in pairs(bank) do for itemString, quantity in pairs(bank) do
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
total[itemString] = (total[itemString] or 0) + quantity total[itemString] = (total[itemString] or 0) + quantity
end end
for itemString, quantity in pairs(mail) do for itemString, quantity in pairs(mail) do
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
total[itemString] = (total[itemString] or 0) + quantity total[itemString] = (total[itemString] or 0) + quantity
end end
for itemString, quantity in pairs(auctions) do for itemString, quantity in pairs(auctions) do
auctionTotal[itemString] = (auctionTotal[itemString] or 0) + quantity auctionTotal[itemString] = (auctionTotal[itemString] or 0) + quantity
total[itemString] = (total[itemString] or 0) + quantity total[itemString] = (total[itemString] or 0) + quantity
end end
end end
end end
for itemString in pairs(TSMAPI.SOULBOUND_MATS) do for itemString in pairs(TSMAPI.SOULBOUND_MATS) do
local bagNum = GetItemCount(itemString) local bagNum = GetItemCount(itemString)
local bankNum = GetItemCount(itemString, true) - GetItemCount(itemString) local bankNum = GetItemCount(itemString, true) - GetItemCount(itemString)
bagTotal[itemString] = (bagTotal[itemString] or 0) + bagNum bagTotal[itemString] = (bagTotal[itemString] or 0) + bagNum
otherTotal[itemString] = (otherTotal[itemString] or 0) + bankNum otherTotal[itemString] = (otherTotal[itemString] or 0) + bankNum
total[itemString] = (total[itemString] or 0) + bagNum + bankNum total[itemString] = (total[itemString] or 0) + bagNum + bankNum
end end
-- add gbank counts of all non-ignored guilds -- add gbank counts of all non-ignored guilds
for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do
if not TSM.db.global.ignoreGuilds[guild] then if not TSM.db.global.ignoreGuilds[guild] then
local gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {} local gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
for itemString, quantity in pairs(gbank) do for itemString, quantity in pairs(gbank) do
otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
total[itemString] = (total[itemString] or 0) + quantity total[itemString] = (total[itemString] or 0) + quantity
end end
end end
end end
return bagTotal, auctionTotal, otherTotal, total -- Ascension WoW: add personal bank counts for all non-ignored characters
end for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
-- gets the total number of some item that they have local personalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", player) or {}
function Inventory:GetTotalQuantity(itemString) for itemString, quantity in pairs(personalBank) do
if not itemString then return 0 end otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
local count = 0 total[itemString] = (total[itemString] or 0) + quantity
end
-- add bags/bank/mail/auction counts of all non-ignored characters (always including current character) end
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do end
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {} -- Ascension WoW: add realm bank counts
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {} local realmBank = TSMAPI:ModuleAPI("ItemTracker", "realmbank") or {}
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {} for itemString, quantity in pairs(realmBank) do
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {} otherTotal[itemString] = (otherTotal[itemString] or 0) + quantity
count = count + (bags[itemString] or 0) total[itemString] = (total[itemString] or 0) + quantity
count = count + (bank[itemString] or 0) end
count = count + (mail[itemString] or 0)
count = count + (auctions[itemString] or 0) return bagTotal, auctionTotal, otherTotal, total
end end
end
-- add gbank counts of all non-ignored guilds -- gets the total number of some item that they have
for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do function Inventory:GetTotalQuantity(itemString)
if not TSM.db.global.ignoreGuilds[guild] then if not itemString then return 0 end
local bank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {} local count = 0
count = count + (bank[itemString] or 0)
end -- add bags/bank/mail/auction counts of all non-ignored characters (always including current character)
end for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
if TSMAPI.SOULBOUND_MATS[itemString] then local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
count = count + GetItemCount(itemString, true) local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
end local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
local auctions = TSMAPI:ModuleAPI("ItemTracker", "playerauctions", player) or {}
return count count = count + (bags[itemString] or 0)
end count = count + (bank[itemString] or 0)
count = count + (mail[itemString] or 0)
function Inventory:GetItemSources(crafter, neededMats) count = count + (auctions[itemString] or 0)
if not neededMats then return end end
local sources = {} end
local gbank = {} -- add gbank counts of all non-ignored guilds
local next = next for _, guild in pairs(TSMAPI:ModuleAPI("ItemTracker", "guildlist") or {}) do
local crafterBags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", crafter) or {} if not TSM.db.global.ignoreGuilds[guild] then
local crafterMail = TSMAPI:ModuleAPI("ItemTracker", "playermail", crafter) or {} local bank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
local crafterBank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", crafter) or {} count = count + (bank[itemString] or 0)
end
-- add vendor items end
local task = {}
local items = {} -- Ascension WoW: add personal bank counts for all non-ignored characters
for itemString, quantity in pairs(neededMats) do for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do
if TSMAPI:GetVendorCost(itemString) then if player == UnitName("player") or not TSM.db.global.ignoreCharacters[player] then
local vendorNeed = quantity - ((crafterBags[itemString] or 0) + (crafterMail[itemString] or 0) + (crafterBank[itemString] or 0)) local personalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", player) or {}
if vendorNeed > 0 then count = count + (personalBank[itemString] or 0)
items[itemString] = vendorNeed end
end end
elseif TSMAPI.Conversions[itemString] and TSMAPI.InkConversions[itemString] then
local tradeItem, data = next(TSMAPI.Conversions[itemString]) -- Ascension WoW: add realm bank count
if data.source == "vendortrade" then local realmBank = TSMAPI:ModuleAPI("ItemTracker", "realmbank") or {}
local num = floor(Inventory:GetTotalQuantity(tradeItem) * data.rate) count = count + (realmBank[itemString] or 0)
if quantity > Inventory:GetTotalQuantity(itemString) and num >= (quantity - Inventory:GetTotalQuantity(itemString)) then
items[itemString] = quantity - Inventory:GetTotalQuantity(itemString) if TSMAPI.SOULBOUND_MATS[itemString] then
neededMats[tradeItem] = (neededMats[tradeItem] or 0) + quantity / data.rate -- add the qty of IOD to needed mats count = count + GetItemCount(itemString, true)
end end
end
end return count
end end
if next(items) then
tinsert(task, { taskType = L["Visit Vendor"], items = items }) function Inventory:GetItemSources(crafter, neededMats)
tinsert(sources, { sourceName = L["Vendor"], isCrafter = false, isVendor = true, isAH = false, tasks = task }) if not neededMats then return end
end local sources = {}
local gbank = {}
-- double check if crafter already has all the items needed local next = next
local shortItems = {} local crafterBags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", crafter) or {}
for itemString, quantity in pairs(neededMats) do local crafterMail = TSMAPI:ModuleAPI("ItemTracker", "playermail", crafter) or {}
local soulboundBagCount local crafterBank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", crafter) or {}
if TSMAPI.SOULBOUND_MATS[itemString] then -- Ascension WoW: crafter's personal bank
soulboundBagCount = GetItemCount(itemString) local crafterPersonalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", crafter) or {}
end
local need = max(quantity - (crafterBags[itemString] or soulboundBagCount or 0), 0) -- add vendor items
if need > 0 then local task = {}
shortItems[itemString] = need local items = {}
end for itemString, quantity in pairs(neededMats) do
end if TSMAPI:GetVendorCost(itemString) then
if not next(shortItems) then return end local vendorNeed = quantity - ((crafterBags[itemString] or 0) + (crafterMail[itemString] or 0) + (crafterBank[itemString] or 0) + (crafterPersonalBank[itemString] or 0))
if vendorNeed > 0 then
-- add bags/bank/mail "tasks" for needed items of all non-ignored characters (always include crafter) items[itemString] = vendorNeed
for _, player in pairs(TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}) do end
if player == crafter or not TSM.db.global.ignoreCharacters[player] then elseif TSMAPI.Conversions[itemString] and TSMAPI.InkConversions[itemString] then
local task = {} local tradeItem, data = next(TSMAPI.Conversions[itemString])
local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {} if data.source == "vendortrade" then
local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {} local num = floor(Inventory:GetTotalQuantity(tradeItem) * data.rate)
local guild = TSMAPI:ModuleAPI("ItemTracker", "playerguild", player) or {} if quantity > Inventory:GetTotalQuantity(itemString) and num >= (quantity - Inventory:GetTotalQuantity(itemString)) then
local gbank = {} items[itemString] = quantity - Inventory:GetTotalQuantity(itemString)
if guild and not TSM.db.global.ignoreGuilds[guild] then neededMats[tradeItem] = (neededMats[tradeItem] or 0) + quantity / data.rate -- add the qty of IOD to needed mats
gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {} end
end end
local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {} end
local bankItems = {} end
local gbankItems = {} if next(items) then
local mailItems = {} tinsert(task, { taskType = L["Visit Vendor"], items = items })
local bagItems = {} tinsert(sources, { sourceName = L["Vendor"], isCrafter = false, isVendor = true, isAH = false, tasks = task })
end
for itemString in pairs(neededMats) do
local soulboundBagCount, soulboundBankCount -- double check if crafter already has all the items needed
if TSMAPI.SOULBOUND_MATS[itemString] then local shortItems = {}
soulboundBagCount = GetItemCount(itemString) for itemString, quantity in pairs(neededMats) do
soulboundBankCount = GetItemCount(itemString, true) - soulboundBagCount local soulboundBagCount
end if TSMAPI.SOULBOUND_MATS[itemString] then
if (bank[itemString] or (soulboundBankCount and soulboundBankCount > 0)) and shortItems[itemString] then soulboundBagCount = GetItemCount(itemString)
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then end
bankItems[itemString] = bank[itemString] or soulboundBankCount local inBags = crafterBags[itemString] or soulboundBagCount or 0
end local need = max(quantity - inBags, 0)
end if need > 0 then
if gbank[itemString] and shortItems[itemString] then shortItems[itemString] = need
if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then end
gbankItems[itemString] = gbank[itemString] end
end if not next(shortItems) then
end return sources -- Return sources instead of nil so vendor items are not lost
if mail[itemString] and shortItems[itemString] then end
mailItems[itemString] = mail[itemString]
end -- add bags/bank/mail "tasks" for needed items of all non-ignored characters (always include crafter)
if bags[itemString] and shortItems[itemString] then local playerList = TSMAPI:ModuleAPI("ItemTracker", "playerlist") or {}
if player ~= crafter then
if shortItems[itemString] - (crafterMail[itemString] or 0) > 0 then for _, player in pairs(playerList) do
bagItems[itemString] = bags[itemString] if player == crafter or not TSM.db.global.ignoreCharacters[player] then
end local task = {}
end local bags = TSMAPI:ModuleAPI("ItemTracker", "playerbags", player) or {}
end local bank = TSMAPI:ModuleAPI("ItemTracker", "playerbank", player) or {}
end local guild = TSMAPI:ModuleAPI("ItemTracker", "playerguild", player) or {}
-- add mail tasks for destroyable items bought through shopping search (exclude items already added to mail tasks) local gbank = {}
for itemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do if guild and not TSM.db.global.ignoreGuilds[guild] then
if mail[itemString] and not shortItems[itemString] then gbank = TSMAPI:ModuleAPI("ItemTracker", "guildbank", guild) or {}
mailItems[itemString] = quantity end
end local mail = TSMAPI:ModuleAPI("ItemTracker", "playermail", player) or {}
end -- Ascension WoW: personal bank for this player
local personalBank = TSMAPI:ModuleAPI("ItemTracker", "personalbank", player) or {}
if next(bankItems) then local bankItems = {}
tinsert(task, { taskType = L["Visit Bank"], items = bankItems }) local gbankItems = {}
end local mailItems = {}
if next(gbankItems) then local bagItems = {}
tinsert(task, { taskType = L["Visit Guild Bank"], items = gbankItems }) local personalBankItems = {}
end
if next(mailItems) then for itemString in pairs(neededMats) do
tinsert(task, { taskType = L["Collect Mail"], items = mailItems }) local soulboundBagCount, soulboundBankCount
end if TSMAPI.SOULBOUND_MATS[itemString] then
if next(bagItems) then soulboundBagCount = GetItemCount(itemString)
tinsert(task, { taskType = L["Mail Items"], items = bagItems }) soulboundBankCount = GetItemCount(itemString, true) - soulboundBagCount
end end
if next(task) then if (bank[itemString] or (soulboundBankCount and soulboundBankCount > 0)) and shortItems[itemString] then
tinsert(sources, { sourceName = player, isCrafter = player == crafter, isVendor = false, isAH = false, tasks = task, isCurrent = (player == UnitName("player")) }) if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
end bankItems[itemString] = bank[itemString] or soulboundBankCount
end end
end end
if gbank[itemString] and shortItems[itemString] then
-- add auction house tasks if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
local auctionTask = {} gbankItems[itemString] = gbank[itemString]
local auctionItems = {} end
for itemString, quantity in pairs(neededMats) do end
if not TSMAPI.SOULBOUND_MATS[itemString] and not TSMAPI:GetVendorCost(itemString) then -- Ascension WoW: check personal bank
local need if personalBank[itemString] and shortItems[itemString] then
if TSM.Inventory.gatherItem == itemString and TSM.Inventory.gatherQuantity then if shortItems[itemString] - (crafterMail[itemString] or 0) - (player ~= crafter and bags[itemString] or 0) > 0 then
need = TSM.Inventory.gatherQuantity personalBankItems[itemString] = personalBank[itemString]
else end
need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0) end
end if mail[itemString] and shortItems[itemString] then
if need > 0 then mailItems[itemString] = mail[itemString]
auctionItems[itemString] = need end
end if bags[itemString] and shortItems[itemString] then
end if player ~= crafter then
end if shortItems[itemString] - (crafterMail[itemString] or 0) > 0 then
if next(auctionItems) then bagItems[itemString] = bags[itemString]
tinsert(auctionTask, { taskType = L["Search for Mats"], items = auctionItems }) end
tinsert(sources, { sourceName = L["Auction House"], isCrafter = false, isVendor = false, isAH = true, tasks = auctionTask }) end
end end
end
-- add destroying tasks -- add mail tasks for destroyable items bought through shopping search (exclude items already added to mail tasks)
local destroyingTask, millItems, prospectItems, transformItems, deItems = {}, {}, {}, {}, {} for itemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do
if mail[itemString] and not shortItems[itemString] then
for itemString, quantity in pairs(neededMats) do mailItems[itemString] = quantity
local need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0) end
-- conversion items end
for destroyItem, data in pairs(TSMAPI.Conversions[itemString] or {}) do
if TSM.db.realm.gathering.destroyingMats[destroyItem] then if next(bankItems) then
if need > 0 then tinsert(task, { taskType = L["Visit Bank"], items = bankItems })
local destroyNeed end
if data.source == "mill" then if next(gbankItems) then
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5) tinsert(task, { taskType = L["Visit Guild Bank"], items = gbankItems })
if destroyNeed > 0 then end
millItems[destroyItem] = (millItems[destroyItem] or 0) + destroyNeed -- Ascension WoW: personal bank task
end if next(personalBankItems) then
elseif data.source == "prospect" then tinsert(task, { taskType = L["Visit Personal Bank"], items = personalBankItems })
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5) end
if destroyNeed > 0 then if next(mailItems) then
prospectItems[destroyItem] = (prospectItems[destroyItem] or 0) + destroyNeed tinsert(task, { taskType = L["Collect Mail"], items = mailItems })
end end
elseif data.source == "transform" then if next(bagItems) then
if data.rate == 1 / 3 then tinsert(task, { taskType = L["Mail Items"], items = bagItems })
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 3) end
elseif data.rate == 1 / 10 then if next(task) then
destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 10) tinsert(sources, { sourceName = player, isCrafter = player == crafter, isVendor = false, isAH = false, tasks = task, isCurrent = (player == UnitName("player")) })
else end
destroyNeed = TSM.db.realm.gathering.destroyingMats[destroyItem] end
end end
if destroyNeed > 0 then
transformItems[destroyItem] = (transformItems[destroyItem] or 0) + destroyNeed -- Ascension WoW: add realm bank as a separate source
end local realmBank = TSMAPI:ModuleAPI("ItemTracker", "realmbank") or {}
end local realmBankTask = {}
else local realmBankItems = {}
TSM.db.realm.gathering.destroyingMats[destroyItem] = nil for itemString in pairs(neededMats) do
end if realmBank[itemString] and shortItems[itemString] then
end if shortItems[itemString] - (crafterMail[itemString] or 0) > 0 then
end realmBankItems[itemString] = realmBank[itemString]
-- disenchantable items end
if next(TSM.db.realm.gathering.destroyingMats) then end
for deItemString, quantity in pairs(TSM.db.realm.gathering.destroyingMats) do end
if Inventory:IsDisenchantable(deItemString) then if next(realmBankItems) then
if need > 0 then tinsert(realmBankTask, { taskType = L["Visit Realm Bank"], items = realmBankItems })
deItems[deItemString] = quantity tinsert(sources, { sourceName = L["Realm Bank"], isCrafter = false, isVendor = false, isAH = false, tasks = realmBankTask, isCurrent = true })
else end
TSM.db.realm.gathering.destroyingMats[deItemString] = nil
end -- add auction house tasks
end local auctionTask = {}
end local auctionItems = {}
end for itemString, quantity in pairs(neededMats) do
end if not TSMAPI.SOULBOUND_MATS[itemString] and not TSMAPI:GetVendorCost(itemString) then
local need
if next(millItems) then if TSM.Inventory.gatherItem == itemString and TSM.Inventory.gatherQuantity then
tinsert(destroyingTask, { taskType = L["Milling"], items = millItems }) need = TSM.Inventory.gatherQuantity
end else
if next(prospectItems) then need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0)
tinsert(destroyingTask, { taskType = L["Prospect"], items = prospectItems }) end
end if need > 0 then
if next(transformItems) then auctionItems[itemString] = need
tinsert(destroyingTask, { taskType = L["Transform"], items = transformItems }) end
end end
if next(deItems) then end
tinsert(destroyingTask, { taskType = L["Disenchant"], items = deItems }) if next(auctionItems) then
end tinsert(auctionTask, { taskType = L["Search for Mats"], items = auctionItems })
if next(destroyingTask) then tinsert(sources, { sourceName = L["Auction House"], isCrafter = false, isVendor = false, isAH = true, tasks = auctionTask })
tinsert(sources, { sourceName = L["Destroying"], isCrafter = false, isVendor = false, isAH = true, tasks = destroyingTask }) end
end
-- add destroying tasks
local destroyingTask, millItems, prospectItems, transformItems, deItems = {}, {}, {}, {}, {}
sort(sources, function(a, b)
if a.isCurrent then return true end for itemString, quantity in pairs(neededMats) do
if b.isCurrent then return false end local need = max(quantity - (TSM.Inventory:GetTotalQuantity(itemString) or 0), 0)
if a.isAH then return false end -- conversion items
if b.isAH then return true end for destroyItem, data in pairs(TSMAPI.Conversions[itemString] or {}) do
if a.isVendor then return false end if TSM.db.realm.gathering.destroyingMats[destroyItem] then
if b.isVendor then return true end if need > 0 then
if a.isCrafter then return false end local destroyNeed
if b.isCrafter then return true end if data.source == "mill" then
return a.sourceName < b.sourceName destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5)
end) if destroyNeed > 0 then
return sources millItems[destroyItem] = (millItems[destroyItem] or 0) + destroyNeed
end end
elseif data.source == "prospect" then
function Inventory:IsDisenchantable(itemString) destroyNeed = floor(TSM.db.realm.gathering.destroyingMats[destroyItem] / 5)
local _, link, quality, _, _, iType = TSMAPI:GetSafeItemInfo(itemString) if destroyNeed > 0 then
local WEAPON, ARMOR = GetAuctionItemClasses() prospectItems[destroyItem] = (prospectItems[destroyItem] or 0) + destroyNeed
if itemString and not TSMAPI.DisenchantingData.notDisenchantable[itemString] and (iType == ARMOR or iType == WEAPON) then end
return true elseif data.source == "transform" then
end 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 end
@@ -14,9 +14,13 @@ local L = LibStub("AceLocale-3.0"):NewLocale("TradeSkillMaster_ItemTracker", "en
if not L then return end if not L then return end
L["%s (%s bags, %s bank, %s AH, %s mail)"] = true L["%s (%s bags, %s bank, %s AH, %s mail)"] = true
L["%s (%s bags, %s bank, %s AH, %s mail, %s personal)"] = true
L["%s in guild bank"] = true L["%s in guild bank"] = true
L["%s in realm bank"] = true
L["%s item(s) total"] = true L["%s item(s) total"] = true
L["(%s player, %s alts, %s guild banks, %s AH)"] = true L["(%s player, %s alts, %s guild banks, %s AH)"] = true
L["(%s player, %s alts, %s guild, %s AH, %s personal, %s realm)"] = true
L["Realm Bank"] = true
L["AH"] = true L["AH"] = true
L["Bags"] = true L["Bags"] = true
L["Bank"] = true L["Bank"] = true
+94 -16
View File
@@ -78,12 +78,32 @@ function Data:ThrottleEvent(event)
throttleFrames[event]:Show() throttleFrames[event]:Show()
end end
local BANK_TYPE_PERSONAL = "personal"
local BANK_TYPE_REALM = "realm"
local BANK_TYPE_GUILD = "guild"
local function GetCurrentBankType()
if GuildBankFrame and GuildBankFrame.IsPersonalBank then
return BANK_TYPE_PERSONAL
elseif GuildBankFrame and GuildBankFrame.IsRealmBank then
return BANK_TYPE_REALM
else
return BANK_TYPE_GUILD
end
end
-- Store the current bank type when opened (persists until next open)
local currentOpenBankType = nil
function Data:EventHandler(event, fire) function Data:EventHandler(event, fire)
if isScanning then return end if isScanning then return end
if fire ~= "FIRE" then if fire ~= "FIRE" then
Data:ThrottleEvent(event) Data:ThrottleEvent(event)
else else
if event == "GUILDBANKFRAME_OPENED" then if event == "GUILDBANKFRAME_OPENED" then
-- Detect and store the bank type
currentOpenBankType = GetCurrentBankType()
-- Query all tabs of the gbank to ensure all tabs will be scanned. -- Query all tabs of the gbank to ensure all tabs will be scanned.
local initialTab = GetCurrentGuildBankTab() local initialTab = GetCurrentGuildBankTab()
for tab = 1, GetNumGuildBankTabs() do for tab = 1, GetNumGuildBankTabs() do
@@ -93,7 +113,14 @@ function Data:EventHandler(event, fire)
end end
QueryGuildBankTab(initialTab) QueryGuildBankTab(initialTab)
elseif event == "GUILDBANKBAGSLOTS_CHANGED" then elseif event == "GUILDBANKBAGSLOTS_CHANGED" then
Data:GetGuildBankData() -- Route to the appropriate handler based on bank type
if currentOpenBankType == BANK_TYPE_PERSONAL then
Data:GetPersonalBankData()
elseif currentOpenBankType == BANK_TYPE_REALM then
Data:GetRealmBankData()
else
Data:GetGuildBankData()
end
elseif event == "AUCTION_OWNED_LIST_UPDATE" then elseif event == "AUCTION_OWNED_LIST_UPDATE" then
Data:ScanPlayerAuctions() Data:ScanPlayerAuctions()
end end
@@ -128,7 +155,32 @@ function Data:GetBankData(state)
TSM.Sync:BroadcastUpdateRequest() TSM.Sync:BroadcastUpdateRequest()
end end
-- scan the guild bank -- Helper function to scan all guild bank slots and return items table
local function ScanGuildBankSlots()
local items = {}
local numTabs = GetNumGuildBankTabs()
for tab = 1, numTabs do
local name, icon, isViewable, canDeposit, numWithdrawals = GetGuildBankTabInfo(tab)
-- Ascension WoW: For Personal/Realm banks, always scan (numWithdrawals check may not apply)
local canAccess = (numWithdrawals and numWithdrawals > 0) or IsGuildLeader(UnitName("player")) or (name == "Personal Bank") or (name == "Realm Bank")
if canAccess then
for slot = 1, MAX_GUILDBANK_SLOTS_PER_TAB or 98 do
local itemString = TSMAPI:GetItemString(GetGuildBankItemLink(tab, slot))
local baseItemString = TSMAPI:GetBaseItemString(GetGuildBankItemLink(tab, slot))
if itemString then
local quantity = select(2, GetGuildBankItemInfo(tab, slot))
items[itemString] = (items[itemString] or 0) + quantity
if itemString ~= baseItemString then
items[baseItemString] = (items[baseItemString] or 0) + quantity
end
end
end
end
end
return items
end
-- scan the guild bank (real guild bank only)
function Data:GetGuildBankData() function Data:GetGuildBankData()
if not TSM.CURRENT_GUILD then if not TSM.CURRENT_GUILD then
Data:StoreCurrentGuildInfo(true) Data:StoreCurrentGuildInfo(true)
@@ -136,27 +188,53 @@ function Data:GetGuildBankData()
end end
wipe(TSM.guilds[TSM.CURRENT_GUILD].items) wipe(TSM.guilds[TSM.CURRENT_GUILD].items)
for tab = 1, GetNumGuildBankTabs() do local items = ScanGuildBankSlots()
if select(5, GetGuildBankTabInfo(tab)) > 0 or IsGuildLeader(UnitName("player")) then for itemString, quantity in pairs(items) do
for slot = 1, MAX_GUILDBANK_SLOTS_PER_TAB or 98 do TSM.guilds[TSM.CURRENT_GUILD].items[itemString] = quantity
local itemString = TSMAPI:GetItemString(GetGuildBankItemLink(tab, slot))
local baseItemString = TSMAPI:GetBaseItemString(GetGuildBankItemLink(tab, slot))
if itemString then
local quantity = select(2, GetGuildBankItemInfo(tab, slot))
TSM.guilds[TSM.CURRENT_GUILD].items[itemString] = (TSM.guilds[TSM.CURRENT_GUILD].items[itemString] or 0) + quantity
if itemString ~= baseItemString then
TSM.guilds[TSM.CURRENT_GUILD].items[baseItemString] = (TSM.guilds[TSM.CURRENT_GUILD].items[baseItemString] or 0) + quantity
end
end
end
end
end end
if GuildBankFrame and GuildBankFrame:IsVisible() then if GuildBankFrame and GuildBankFrame:IsVisible() then
TSM.guilds[TSM.CURRENT_GUILD].lastUpdate = time() TSM.guilds[TSM.CURRENT_GUILD].lastUpdate = time()
end end
TSM.Sync:BroadcastUpdateRequest() TSM.Sync:BroadcastUpdateRequest()
end end
-- Ascension WoW: scan the personal bank (per character)
function Data:GetPersonalBankData()
-- Initialize personal bank for current player if needed
if not TSM.personalBanks[TSM.CURRENT_PLAYER] then
TSM.personalBanks[TSM.CURRENT_PLAYER] = { items = {}, lastUpdate = 0 }
end
wipe(TSM.personalBanks[TSM.CURRENT_PLAYER].items)
local items = ScanGuildBankSlots()
for itemString, quantity in pairs(items) do
TSM.personalBanks[TSM.CURRENT_PLAYER].items[itemString] = quantity
end
TSM.personalBanks[TSM.CURRENT_PLAYER].lastUpdate = time()
TSM.Sync:BroadcastUpdateRequest()
end
-- Ascension WoW: scan the realm bank (shared across realm)
function Data:GetRealmBankData()
-- Initialize realm bank if needed
if not TSM.realmBank.items then
TSM.realmBank.items = {}
end
wipe(TSM.realmBank.items)
local items = ScanGuildBankSlots()
for itemString, quantity in pairs(items) do
TSM.realmBank.items[itemString] = quantity
end
if GuildBankFrame and GuildBankFrame:IsVisible() then
TSM.realmBank.lastUpdate = time()
end
TSM.Sync:BroadcastUpdateRequest()
end
function Data:ScanPlayerAuctions() function Data:ScanPlayerAuctions()
wipe(TSM.characters[TSM.CURRENT_PLAYER].auctions) wipe(TSM.characters[TSM.CURRENT_PLAYER].auctions)
TSM.characters[TSM.CURRENT_PLAYER].auctions.time = time() TSM.characters[TSM.CURRENT_PLAYER].auctions.time = time()
@@ -13,7 +13,7 @@ local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_ItemTracker")
-- default values for the savedDB -- default values for the savedDB
local savedDBDefaults = { local savedDBDefaults = {
-- any global -- any global
global = { global = {
tooltip = "simple", tooltip = "simple",
}, },
@@ -23,6 +23,10 @@ local savedDBDefaults = {
characters = {}, characters = {},
guilds = {}, guilds = {},
ignoreGuilds = {}, ignoreGuilds = {},
-- Ascension WoW: Personal banks (per character, stored by character name)
personalBanks = {},
-- Ascension WoW: Realm bank (shared across all characters on realm)
realmBank = { items = {}, lastUpdate = 0 },
}, },
-- data that is stored per user profile -- data that is stored per user profile
@@ -47,6 +51,11 @@ local guildDefaults = {
items = {}, items = {},
lastUpdate = 0, lastUpdate = 0,
} }
-- Ascension WoW: Personal bank defaults (same structure as guild)
local personalBankDefaults = {
items = {},
lastUpdate = 0,
}
-- Called once the player has loaded into the game -- Called once the player has loaded into the game
-- Anything that needs to be done in order to initialize the addon should go here -- Anything that needs to be done in order to initialize the addon should go here
@@ -58,9 +67,12 @@ function TSM:OnInitialize()
-- load the saved variables table into TSM.db -- load the saved variables table into TSM.db
TSM.db = LibStub:GetLibrary("AceDB-3.0"):New("AscensionTSM_ItemTrackerDB", savedDBDefaults, true) TSM.db = LibStub:GetLibrary("AceDB-3.0"):New("AscensionTSM_ItemTrackerDB", savedDBDefaults, true)
TSM.characters = TSM.db.realm.characters TSM.characters = TSM.db.realm.characters
TSM.guilds = TSM.db.realm.guilds TSM.guilds = TSM.db.realm.guilds
-- Ascension WoW: Personal banks and realm bank
TSM.personalBanks = TSM.db.realm.personalBanks
TSM.realmBank = TSM.db.realm.realmBank
-- handle connected realms for characters -- handle connected realms for characters
local connectedRealms = TSMAPI.GetConnectedRealms and TSMAPI:GetConnectedRealms() or {} local connectedRealms = TSMAPI.GetConnectedRealms and TSMAPI:GetConnectedRealms() or {}
@@ -117,6 +129,11 @@ function TSM:OnInitialize()
for _, guildData in pairs(TSM.guilds) do for _, guildData in pairs(TSM.guilds) do
ClearItemIDs(guildData.items) ClearItemIDs(guildData.items)
end end
-- Ascension WoW: Clean up personal banks and realm bank
for _, personalBankData in pairs(TSM.personalBanks) do
ClearItemIDs(personalBankData.items)
end
ClearItemIDs(TSM.realmBank.items)
TSM.Data:Initialize() TSM.Data:Initialize()
TSM:UpdatePlayerLookup() TSM:UpdatePlayerLookup()
@@ -151,6 +168,11 @@ function TSM:RegisterModule()
{ key = "guildtotal", callback = "GetGuildTotal" }, { key = "guildtotal", callback = "GetGuildTotal" },
{ key = "playerguildtotal", callback = "GetPlayerGuildTotal" }, { key = "playerguildtotal", callback = "GetPlayerGuildTotal" },
{ key = "playerguild", callback = "GetPlayerGuild" }, { key = "playerguild", callback = "GetPlayerGuild" },
-- Ascension WoW: Personal banks and realm bank APIs
{ key = "personalbank", callback = "GetPersonalBank" },
{ key = "realmbank", callback = "GetRealmBank" },
{ key = "personalbankstotal", callback = "GetPersonalBanksTotal" },
{ key = "realmbanktotal", callback = "GetRealmBankTotal" },
} }
--TSM.sync = { callback = "Sync:Callback" } --TSM.sync = { callback = "Sync:Callback" }
TSM.tooltipOptions = { callback = "Config:LoadTooltipOptions" } TSM.tooltipOptions = { callback = "Config:LoadTooltipOptions" }
@@ -169,9 +191,18 @@ function TSM:GetTooltip(itemString)
local player, alts = TSM:GetPlayerTotal(itemString) local player, alts = TSM:GetPlayerTotal(itemString)
local guild = TSM:GetGuildTotal(itemString) local guild = TSM:GetGuildTotal(itemString)
local auctions = TSM:GetAuctionsTotal(itemString) local auctions = TSM:GetAuctionsTotal(itemString)
grandTotal = grandTotal + player + alts + guild + auctions -- Ascension WoW: Add personal banks and realm bank
local personalBanks = TSM:GetPersonalBanksTotal(itemString)
local realmBank = TSM:GetRealmBankTotal(itemString)
grandTotal = grandTotal + player + alts + guild + auctions + personalBanks + realmBank
if grandTotal > 0 then if grandTotal > 0 then
tinsert(text, { left = " " .. "ItemTracker:", right = format(L["(%s player, %s alts, %s guild banks, %s AH)"], "|cffffffff" .. player .. "|r", "|cffffffff" .. alts .. "|r", "|cffffffff" .. guild .. "|r", "|cffffffff" .. auctions .. "|r") }) tinsert(text, { left = " " .. "ItemTracker:", right = format(L["(%s player, %s alts, %s guild, %s AH, %s personal, %s realm)"],
"|cffffffff" .. player .. "|r",
"|cffffffff" .. alts .. "|r",
"|cffffffff" .. guild .. "|r",
"|cffffffff" .. auctions .. "|r",
"|cffffffff" .. personalBanks .. "|r",
"|cffffffff" .. realmBank .. "|r") })
end end
elseif TSM.db.global.tooltip == "full" then elseif TSM.db.global.tooltip == "full" then
for name, data in pairs(TSM.characters) do for name, data in pairs(TSM.characters) do
@@ -179,17 +210,26 @@ function TSM:GetTooltip(itemString)
local bank = data.bank[itemString] or 0 local bank = data.bank[itemString] or 0
local auctions = data.auctions[itemString] or 0 local auctions = data.auctions[itemString] or 0
local mail = data.mail[itemString] or 0 local mail = data.mail[itemString] or 0
local total = bags + bank + auctions + mail -- Ascension WoW: Add personal bank for this character
local personalBank = TSM.personalBanks[name] and TSM.personalBanks[name].items[itemString] or 0
local total = bags + bank + auctions + mail + personalBank
grandTotal = grandTotal + total grandTotal = grandTotal + total
local bagText = "|cffffffff" .. bags .. "|r" local bagText = "|cffffffff" .. bags .. "|r"
local bankText = "|cffffffff" .. bank .. "|r" local bankText = "|cffffffff" .. bank .. "|r"
local auctionText = "|cffffffff" .. auctions .. "|r" local auctionText = "|cffffffff" .. auctions .. "|r"
local mailText = "|cffffffff" .. mail .. "|r" local mailText = "|cffffffff" .. mail .. "|r"
local personalBankText = "|cffffffff" .. personalBank .. "|r"
local totalText = "|cffffffff" .. total .. "|r" local totalText = "|cffffffff" .. total .. "|r"
if total > 0 then if total > 0 then
tinsert(text, { left = format(" %s:", name), right = format(L["%s (%s bags, %s bank, %s AH, %s mail)"], "|cffffffff" .. totalText, "|cffffffff" .. bagText, "|cffffffff" .. bankText, "|cffffffff" .. auctionText, "|cffffffff" .. mailText) }) tinsert(text, { left = format(" %s:", name), right = format(L["%s (%s bags, %s bank, %s AH, %s mail, %s personal)"],
"|cffffffff" .. totalText,
"|cffffffff" .. bagText,
"|cffffffff" .. bankText,
"|cffffffff" .. auctionText,
"|cffffffff" .. mailText,
"|cffffffff" .. personalBankText) })
end end
end end
@@ -205,6 +245,14 @@ function TSM:GetTooltip(itemString)
end end
end end
end end
-- Ascension WoW: Show realm bank
local realmBank = TSM:GetRealmBankTotal(itemString)
if realmBank > 0 then
grandTotal = grandTotal + realmBank
local realmBankText = "|cffffffff" .. realmBank .. "|r"
tinsert(text, { left = " " .. L["Realm Bank"] .. ":", right = format(L["%s in realm bank"], realmBankText) })
end
end end
if #text > 0 then if #text > 0 then
@@ -343,4 +391,31 @@ function TSM:GetPlayerGuild(player)
player = TSM.playerLookup[player] or player player = TSM.playerLookup[player] or player
if not player or not TSM.characters[player] then return end if not player or not TSM.characters[player] then return end
return TSM.characters[player].guild return TSM.characters[player].guild
end
-- Ascension WoW: Get personal bank data for a player
function TSM:GetPersonalBank(player)
player = player or TSM.CURRENT_PLAYER
player = TSM.playerLookup[player] or player
if not player or not TSM.personalBanks[player] then return end
return TSM.personalBanks[player].items
end
-- Ascension WoW: Get realm bank data
function TSM:GetRealmBank()
return TSM.realmBank.items
end
-- Ascension WoW: Get total items across all personal banks
function TSM:GetPersonalBanksTotal(itemString)
local total = 0
for _, data in pairs(TSM.personalBanks) do
total = total + (data.items[itemString] or 0)
end
return total
end
-- Ascension WoW: Get realm bank total for an item
function TSM:GetRealmBankTotal(itemString)
return TSM.realmBank.items[itemString] or 0
end end