You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
8.3 KiB

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local TSM = select(2, ...) ---@type TSM
local TooltipScanning = TSM.Init("Service.TooltipScanning") ---@class Service.TooltipScanning
local Environment = TSM.Include("Environment")
local ItemInfo = TSM.Include("Service.ItemInfo")
local ItemString = TSM.Include("Util.ItemString")
local Container = TSM.Include("Util.Container")
local private = {
tooltip = nil
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function TooltipScanning.IsSoulbound(bag, slot)
local itemId = Container.GetItemId(bag, slot)
if not itemId then
-- No item in this slot
return true, false, false
elseif itemId == ItemString.ToId(ItemString.GetPetCage()) then
-- Battle pets are never soulbound
return true, false, false
end
local info = private.SetContainerItem(bag, slot)
if not Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) and private.tooltip:NumLines() < 1 then
-- The tooltip didn't fully load yet
return false, nil, nil
end
local recipeTargetItemName = nil
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) and info.hyperlink and ItemString.ToId(info.hyperlink) ~= itemId then
recipeTargetItemName = ItemInfo.GetName(info.hyperlink)
end
local isBOP, isBOA = false, false
for i, text in private.TooltipLineIterator(info) do
if recipeTargetItemName and strtrim(text) == recipeTargetItemName then
-- This is a recipe and we've reached the target item within the tooltip, so stop scanning so we don't get confused by soulbound info of the target item
break
end
if text == PROFESSIONS_MODIFIED_CRAFTING_REAGENT_BASIC then
break
elseif (text == ITEM_BIND_ON_PICKUP and i < 4) or text == ITEM_SOULBOUND or text == ITEM_BIND_QUEST then
isBOP = true
break
elseif (text == ITEM_ACCOUNTBOUND or text == ITEM_BIND_TO_ACCOUNT or text == ITEM_BIND_TO_BNETACCOUNT or text == ITEM_BNETACCOUNTBOUND) then
isBOA = true
break
end
end
return true, isBOP, isBOA
end
function TooltipScanning.HasUsedCharges(bag, slot)
assert(not Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO))
local itemId = Container.GetItemId(bag, slot)
if not itemId then
-- No item in this slot
return false
elseif itemId == ItemString.ToId(ItemString.GetPetCage()) then
-- Battle pets never have charges
return false
end
-- Check if the item has max charges
local info = private.SetItemId(itemId)
local maxCharges = private.ScanTooltipCharges(info)
if not maxCharges then
return false
end
-- Check if there are used charges on the container item
info = private.SetContainerItem(bag, slot)
if maxCharges and private.ScanTooltipCharges(info) ~= maxCharges then
return true
end
return false
end
function TooltipScanning.GetInboxMaxUnique(index, num)
num = num or 1
local speciesId, info = nil, nil
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
info = private.SetInboxItem(index, num)
speciesId = info.battlePetSpeciesID
else
speciesId = private.SetInboxItem(index, num)
end
if speciesId and speciesId > 0 then
-- No max for battle pets
return 0
end
for _, text in private.TooltipLineIterator(info) do
if text == PROFESSIONS_MODIFIED_CRAFTING_REAGENT_BASIC then
return 0
elseif text == ITEM_UNIQUE then
return 1
else
local match = strmatch(text, "^"..ITEM_UNIQUE.." %((%d+)%)$")
if match then
return tonumber(match)
end
end
end
return 0
end
function TooltipScanning.GetInboxBattlePetInfo(index, attachIndex)
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
local info = private.SetInboxItem(index, attachIndex)
return info.battlePetSpeciesID, info.battlePetLevel, info.battlePetBreedQuality
else
return private.SetInboxItem(index, attachIndex)
end
end
function TooltipScanning.GetBuildBankBattlePetInfo(tab, slot)
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
local info = private.SetGuildBankItem(tab, slot)
if not info then
return nil, nil, nil
end
return info.battlePetSpeciesID, info.battlePetLevel, info.battlePetBreedQuality
else
return private.SetGuildBankItem(tab, slot)
end
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.SetContainerItem(bag, slot)
private.PrepareTooltip()
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
local info = nil
if bag == BANK_CONTAINER then
info = C_TooltipInfo.GetInventoryItem("player", BankButtonIDToInvSlotID(slot), true)
elseif bag == REAGENTBANK_CONTAINER then
info = C_TooltipInfo.GetInventoryItem("player", ReagentBankButtonIDToInvSlotID(slot), true)
else
info = C_TooltipInfo.GetBagItem(bag, slot)
end
TooltipUtil.SurfaceArgs(info)
return info
else
if bag == BANK_CONTAINER then
private.tooltip:SetInventoryItem("player", BankButtonIDToInvSlotID(slot))
elseif bag == REAGENTBANK_CONTAINER then
private.tooltip:SetInventoryItem("player", ReagentBankButtonIDToInvSlotID(slot))
else
private.tooltip:SetBagItem(bag, slot)
end
end
end
function private.SetItemId(itemId)
private.PrepareTooltip()
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
local info = C_TooltipInfo.GetItemByID(itemId)
TooltipUtil.SurfaceArgs(info)
return info
else
private.tooltip:SetItemByID(itemId)
end
end
function private.SetInboxItem(index, attachIndex)
private.PrepareTooltip()
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
local info = C_TooltipInfo.GetInboxItem(index, attachIndex)
TooltipUtil.SurfaceArgs(info)
return info
else
return select(2, private.tooltip:SetInboxItem(index, attachIndex))
end
end
function private.SetGuildBankItem(tab, slot)
private.PrepareTooltip()
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
local info = C_TooltipInfo.GetGuildBankItem(tab, slot)
if not info then
return nil
end
TooltipUtil.SurfaceArgs(info)
return info
else
return private.tooltip:SetGuildBankItem(tab, slot)
end
end
function private.PrepareTooltip()
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
return
end
private.tooltip = private.tooltip or CreateFrame("GameTooltip", "TSMScanTooltip", UIParent, "GameTooltipTemplate")
private.tooltip:SetOwner(UIParent, "ANCHOR_NONE")
private.tooltip:ClearLines()
end
function private.ScanTooltipCharges(info)
for _, text in private.TooltipLineIterator(info) do
if text == PROFESSIONS_MODIFIED_CRAFTING_REAGENT_BASIC then
return false
end
local num = strmatch(text, "%d+")
local chargesStr = gsub(ITEM_SPELL_CHARGES, "%%d", "%%d+")
if strfind(chargesStr, ":") then
if num == 1 then
chargesStr = gsub(chargesStr, "\1244(.+):.+;", "%1")
else
chargesStr = gsub(chargesStr, "\1244.+:(.+);", "%1")
end
end
local maxCharges = strmatch(text, "^"..chargesStr.."$")
if maxCharges then
return maxCharges
end
end
return false
end
function private.TooltipLineIterator(info)
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
assert(info)
return private.TooltipLineIteratorHelper, info, 1
else
assert(not info)
return private.TooltipLineIteratorHelper, nil, 1
end
end
function private.TooltipLineIteratorHelper(info, index)
while true do
index = index + 1
local numLines = Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) and #info.lines or private.tooltip:NumLines()
if index > numLines then
return
end
local text = nil
if Environment.HasFeature(Environment.FEATURES.C_TOOLTIP_INFO) then
TooltipUtil.SurfaceArgs(info.lines[index])
text = info.lines[index].leftText
else
local tooltipText = _G["TSMScanTooltipTextLeft"..index]
text = strtrim(tooltipText and tooltipText:GetText() or "")
end
if text and text ~= "" then
return index, text
end
end
end