Skip to content

Commit 17799bb

Browse files
committed
Exposed an API that other addons can use to find out if an item can be upgraded or catalysed for a new transmog appearance
1 parent d7ad5b6 commit 17799bb

File tree

3 files changed

+169
-40
lines changed

3 files changed

+169
-40
lines changed

TransmogUpgradeMaster.lua

Lines changed: 129 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ TransmogUpgradeMaster = TUM
66
--@debug@
77
_G.TUM = TUM
88
--@end-debug@
9+
ns.core = TUM
910

1011
--- @type TransmogUpgradeMasterData
1112
TUM.data = ns.data
@@ -167,6 +168,10 @@ end
167168

168169
local BONUS_ID_OFFSET = 13;
169170
function TUM:GetItemSeason(itemLink)
171+
if self:IsCurrentSeasonItem(itemLink) then
172+
return self.currentSeason;
173+
end
174+
170175
local _, data = LinkUtil.ExtractLink(itemLink);
171176
local parts = strsplittable(':', data);
172177
local numBonusIDs = tonumber(parts[BONUS_ID_OFFSET]) or 0;
@@ -234,25 +239,47 @@ function TUM:AddDebugLine(tooltip, text)
234239
tooltip:AddDoubleLine('<TUM Debug>', text, 1, 0.5, 0, 1, 1, 1)
235240
end
236241

237-
--- @param tooltip GameTooltip
238-
function TUM:HandleTooltip(tooltip)
239-
local itemLink = select(2, TooltipUtil.GetDisplayedItem(tooltip))
240-
if not itemLink then return end
242+
--- @param tbl table?
243+
---@param value any
244+
local function tryInsert(tbl, value)
245+
if tbl then
246+
table.insert(tbl, value)
247+
end
248+
end
249+
250+
--- @param itemLink string
251+
--- @param classID number? # defaults to the player's class
252+
--- @param debugLines string[]? # if provided, debug lines will be added to this table
253+
--- @return boolean? canCatalyse # whether the item can be catalysed; if false, the catalystAppearanceMissing return values will be nil
254+
--- @return boolean? canUpgrade # whether the item can be upgraded to the next tier; if false, the upgradeAppearanceMissing return values will be nil
255+
--- @return boolean? catalystAppearanceMissing # true if the item will teach a new appearance when catalysed
256+
--- @return boolean? catalystUpgradeAppearanceMissing # true if the item will teach a new appearance when catalysed AND upgraded to the next tier
257+
--- @return boolean? upgradeAppearanceMissing # true if the item will teach a new appearance when upgraded to the next tier
258+
function TUM:IsAppearanceMissing(itemLink, classID, debugLines)
259+
if not C_Item.IsItemDataCachedByID(itemLink) then
260+
tryInsert(debugLines, 'item data not cached')
261+
262+
return nil, nil, nil, nil, nil
263+
end
264+
local canCatalyse, canUpgradeToNextBreakpoint = false, false
265+
local catalystMissing, catalystUpgradeMissing, upgradeMissing = nil, nil, nil
241266

242267
local itemID = tonumber(itemLink:match("item:(%d+)"))
243-
if not itemID or not C_Item.IsDressableItemByID(itemID) then return end
244-
self:AddDebugLine(tooltip, 'itemID: ' .. tostring(itemID))
268+
if not itemID or not C_Item.IsDressableItemByID(itemID) then
269+
return canCatalyse, canUpgradeToNextBreakpoint, catalystMissing, catalystUpgradeMissing, upgradeMissing
270+
end
271+
tryInsert(debugLines, 'itemID: ' .. tostring(itemID))
245272

246273
local upgradeInfo = C_Item.GetItemUpgradeInfo(itemLink)
247274
local canUpgrade = upgradeInfo and self:IsCurrentSeasonItem(itemLink)
248275
local seasonID = self:GetItemSeason(itemLink)
276+
tryInsert(debugLines, 'seasonID: ' .. tostring(seasonID))
249277
if not upgradeInfo or not seasonID then
250-
self:AddDebugLine(tooltip, 'not upgradable or no seasonID')
251-
return
278+
tryInsert(debugLines, 'not upgradable or no seasonID')
279+
280+
return canCatalyse, canUpgradeToNextBreakpoint, catalystMissing, catalystUpgradeMissing, upgradeMissing
252281
end
253-
self:AddDebugLine(tooltip, 'seasonID: ' .. tostring(seasonID))
254282

255-
local canUpgradeToNextBreakpoint = false
256283
local currentTier = 0;
257284
if upgradeInfo then
258285
currentTier = TRACK_STRING_ID_TO_TIERS[upgradeInfo.trackStringID] or 0
@@ -270,12 +297,12 @@ function TUM:HandleTooltip(tooltip)
270297
currentTier = index
271298

272299
if currentTier == 0 then
273-
self:AddDebugLine(tooltip, 'no tier info found')
300+
tryInsert(debugLines, 'no tier info found')
274301

275-
return
302+
return canCatalyse, canUpgradeToNextBreakpoint, catalystMissing, catalystUpgradeMissing, upgradeMissing
276303
end
277304
end
278-
self:AddDebugLine(tooltip, 'currentTier: ' .. tostring(currentTier))
305+
tryInsert(debugLines, 'currentTier: ' .. tostring(currentTier))
279306

280307
local itemSlot = C_Item.GetItemInventoryTypeByID(itemLink)
281308
if itemSlot == Enum.InventoryType.IndexRobeType then
@@ -284,12 +311,12 @@ function TUM:HandleTooltip(tooltip)
284311
end
285312

286313
local _, sourceID = C_TransmogCollection.GetItemInfo(itemID)
287-
self:AddDebugLine(tooltip, 'sourceID: ' .. tostring(sourceID))
314+
tryInsert(debugLines, 'sourceID: ' .. tostring(sourceID))
288315

289316
local setIDs = sourceID and C_TransmogSets.GetSetsContainingSourceID(sourceID)
290317
local relatedSets
291318
if setIDs and #setIDs > 0 then
292-
self:AddDebugLine(tooltip, 'setIDs: ' .. table.concat(setIDs, ', '))
319+
tryInsert(debugLines, 'setIDs: ' .. table.concat(setIDs, ', '))
293320
for _, setID in ipairs(setIDs) do
294321
local setInfo = C_TransmogSets.GetSetInfo(setID)
295322

@@ -303,66 +330,128 @@ function TUM:HandleTooltip(tooltip)
303330
end
304331

305332
local isCatalysed = self:IsItemCatalysed(itemID)
306-
self:AddDebugLine(tooltip, 'isCatalysed: ' .. tostring(isCatalysed))
307-
local canCatalyse = not isCatalysed and self:IsCatalystSlot(itemSlot) and self:IsValidArmorTypeForPlayer(itemLink)
333+
tryInsert(debugLines, 'isCatalysed: ' .. tostring(isCatalysed))
334+
canCatalyse = not isCatalysed and self:IsCatalystSlot(itemSlot) and self:IsValidArmorTypeForClass(itemLink, classID)
308335
if canCatalyse then
309-
local playerSets = self:GetSetsForClass(playerClassID, seasonID)
336+
local playerSets = self:GetSetsForClass(classID, seasonID)
310337
if playerSets then
311-
local currentIsCollected = self:IsSetItemCollected(playerSets[currentTier], itemSlot)
312-
self:AddTooltipLine(tooltip, CATALYST_MARKUP .. " Catalyst appearance", currentIsCollected)
338+
catalystMissing = not self:IsSetItemCollected(playerSets[currentTier], itemSlot)
313339
if canUpgradeToNextBreakpoint then
314-
local nextIsCollected = self:IsSetItemCollected(playerSets[currentTier + 1], itemSlot)
315-
self:AddTooltipLine(tooltip, CATALYST_MARKUP .. " Catalyst & " .. UPGRADE_MARKUP .. " Upgrade appearance",
316-
nextIsCollected)
340+
catalystUpgradeMissing = not self:IsSetItemCollected(playerSets[currentTier + 1], itemSlot)
317341
end
318342
else
319-
local collected = self:IsCatalystItemCollected(seasonID, playerClassID, itemSlot, currentTier)
320-
if collected == nil then
321-
TUM:ShowLoadingTooltipIfLoading(tooltip)
322-
-- todo: add a 1-time error message that set info for current season+class couldn't be found
323-
else
324-
self:AddTooltipLine(tooltip, CATALYST_MARKUP .. " Catalyst appearance", collected)
343+
catalystMissing = not self:IsCatalystItemCollected(seasonID, classID, itemSlot, currentTier)
344+
if canUpgradeToNextBreakpoint then
345+
catalystUpgradeMissing = not self:IsCatalystItemCollected(seasonID, classID, itemSlot, currentTier + 1)
325346
end
326347
end
327348
else
328-
self:AddDebugLine(tooltip, 'can\'t catalyse or already catalysed')
349+
tryInsert(debugLines, 'can\'t catalyse or already catalysed')
329350
end
330351
if isCatalysed and relatedSets and canUpgradeToNextBreakpoint then
331352
local nextSetID = relatedSets[currentTier + 1]
332353
if nextSetID then
333-
local isCollected = self:IsSetItemCollected(nextSetID, itemSlot)
334-
self:AddTooltipLine(tooltip, UPGRADE_MARKUP .. " Upgrade appearance", isCollected)
354+
upgradeMissing = not self:IsSetItemCollected(nextSetID, itemSlot)
335355
end
336356
elseif canUpgradeToNextBreakpoint then
337357
local sourceIDs = self:GetSourceIDsForItemID(itemID)
338358
if sourceIDs and sourceIDs[currentTier + 1] then
339359
local nextSourceInfo = C_TransmogCollection.GetSourceInfo(sourceIDs[currentTier + 1])
340-
local isCollected = nextSourceInfo and nextSourceInfo.isCollected
341-
self:AddTooltipLine(tooltip, UPGRADE_MARKUP .. " Upgrade appearance", isCollected)
360+
upgradeMissing = not nextSourceInfo or not nextSourceInfo.isCollected
361+
end
362+
end
363+
364+
if self:IsCacheWarmedUp() then
365+
if canCatalyse then
366+
catalystMissing = catalystMissing or false
367+
if canUpgradeToNextBreakpoint then
368+
catalystUpgradeMissing = catalystUpgradeMissing or false
369+
end
370+
end
371+
if canUpgradeToNextBreakpoint then
372+
upgradeMissing = upgradeMissing or false
373+
end
374+
end
375+
376+
return canCatalyse, canUpgradeToNextBreakpoint, catalystMissing, catalystUpgradeMissing, upgradeMissing
377+
end
378+
379+
--- @param tooltip GameTooltip
380+
function TUM:HandleTooltip(tooltip)
381+
local itemLink = select(2, TooltipUtil.GetDisplayedItem(tooltip))
382+
if not itemLink then return end
383+
384+
local debugLines = {}
385+
local canCatalyse, canUpgrade,
386+
catalystMissing, catalystUpgradeMissing, upgradeMissing = self:IsAppearanceMissing(itemLink, nil, debugLines)
387+
388+
for _, line in ipairs(debugLines) do
389+
self:AddDebugLine(tooltip, line)
390+
end
391+
392+
if not canCatalyse and not canUpgrade then
393+
return
394+
end
395+
396+
local loadingTooltipShown = false
397+
if canCatalyse then
398+
if catalystMissing == nil then
399+
if not loadingTooltipShown then loadingTooltipShown = self:ShowLoadingTooltipIfLoading(tooltip) end
400+
else
401+
self:AddTooltipLine(tooltip, CATALYST_MARKUP .. ' Catalyst appearance', not catalystMissing)
402+
end
403+
if canUpgrade then
404+
if catalystUpgradeMissing == nil then
405+
if not loadingTooltipShown then loadingTooltipShown = self:ShowLoadingTooltipIfLoading(tooltip) end
406+
else
407+
self:AddTooltipLine(
408+
tooltip,
409+
CATALYST_MARKUP .. ' Catalyst & ' .. UPGRADE_MARKUP .. ' Upgrade appearance',
410+
not catalystUpgradeMissing
411+
)
412+
end
413+
end
414+
end
415+
if canUpgrade then
416+
if upgradeMissing == nil then
417+
if not loadingTooltipShown then loadingTooltipShown = self:ShowLoadingTooltipIfLoading(tooltip) end
342418
else
343-
TUM:ShowLoadingTooltipIfLoading(tooltip)
419+
self:AddTooltipLine(tooltip, UPGRADE_MARKUP .. ' Upgrade appearance', not upgradeMissing)
344420
end
345421
end
346422
end
347423

424+
--- @return boolean isCacheWarmedUp
425+
--- @return number progress # a number between 0 and 1, where 1 means caching has finished
426+
function TUM:IsCacheWarmedUp()
427+
if not self.itemSourceMapInitialized then
428+
return false, self.itemSourceMapProgress / self.itemSourceMapTotal
429+
end
430+
return true, 1
431+
end
432+
433+
--- @return boolean loading
348434
function TUM:ShowLoadingTooltipIfLoading(tooltip)
349-
if self.itemSourceMapInitialized then return end
350-
local progress = self.itemSourceMapProgress / self.itemSourceMapTotal * 100
351-
local text = string.format("TransmogUpgradeMaster is loading (%.0f%%)", progress)
435+
if self.itemSourceMapInitialized then return false end
436+
local _, progress = self:IsCacheWarmedUp()
437+
local text = string.format("TransmogUpgradeMaster is loading (%.0f%%)", progress * 100)
352438
tooltip:AddLine(text, nil, nil, nil, true)
439+
440+
return true
353441
end
354442

355443
function TUM:GetSourceIDsForItemID(itemID)
356444
return self.itemSourceIDs[itemID]
357445
end
358446

359447
--- @param itemLink string
448+
--- @param classID number? # defaults to the player's class
360449
--- @return boolean
361-
function TUM:IsValidArmorTypeForPlayer(itemLink)
450+
function TUM:IsValidArmorTypeForClass(itemLink, classID)
362451
local invType, _, itemClassID, itemSubClassID = select(4, C_Item.GetItemInfoInstant(itemLink))
363452

364453
return invType == "INVTYPE_CLOAK"
365-
or (itemClassID == Enum.ItemClass.Armor and itemSubClassID == classArmorTypeMap[playerClassID])
454+
or (itemClassID == Enum.ItemClass.Armor and itemSubClassID == classArmorTypeMap[classID or playerClassID])
366455
end
367456

368457
function TUM:IsCatalystSlot(slot)

TransmogUpgradeMaster.toc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@
2222
data.lua
2323
config.lua
2424
TransmogUpgradeMaster.lua
25+
26+
api.lua

api.lua

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
local _, ns = ...
2+
3+
--- @type TransmogUpgradeMaster
4+
local TUM = ns.TUM
5+
6+
--- The function signatures in this file will remain stable, though no guarantees are made.
7+
--- @class TransmogUpgradeMaster_API
8+
local api = {}
9+
10+
TransmogUpgradeMaster_API = api
11+
12+
--- Transmog data is cached on login, until the cache is fully warmed up, the other APIs may return nils instead of booleans
13+
--- @return boolean isCacheWarmedUp
14+
--- @return number progress # a number between 0 and 1, where 1 means caching has finished
15+
function api.IsCacheWarmedUp()
16+
return TUM:IsCacheWarmedUp()
17+
end
18+
19+
--- Check whether an item can teach new appearances when upgraded and/or catalysed
20+
---
21+
--- The "canCatalyse" and "canUpgrade" return values will be nil if the item is not cached
22+
--- It is up to you to ensure that the item gets cached, and then call this API again
23+
---
24+
--- The "appearance missing" return values will be nil if the item cannot be upgraded and/or catalysed, or if the required information is missing from the cache.
25+
--- It's possible for a only subset of "appearance missing" return values to be nil while the cache is loading
26+
---
27+
--- You can optionally pass a classID to specify the class for which you want to check the catalyst appearance. This is useful for BoE or warbound items.
28+
---
29+
--- @param itemLink string
30+
--- @param classID number? # defaults to the player's class
31+
--- @return boolean? canCatalyse # whether the item can be catalysed; if false, the catalystAppearanceMissing return values will be nil
32+
--- @return boolean? canUpgrade # whether the item can be upgraded to the next tier; if false, the upgradeAppearanceMissing return values will be nil
33+
--- @return boolean? catalystAppearanceMissing # true if the item will teach a new appearance when catalysed
34+
--- @return boolean? catalystUpgradeAppearanceMissing # true if the item will teach a new appearance when catalysed AND upgraded to the next tier
35+
--- @return boolean? upgradeAppearanceMissing # true if the item will teach a new appearance when upgraded to the next tier
36+
function api.IsAppearanceMissing(itemLink, classID)
37+
return TUM:IsAppearanceMissing(itemLink, classID)
38+
end

0 commit comments

Comments
 (0)