魔兽世界插件开发求助:无法在Tooltip显示物品升级成本
我正在开发一款魔兽世界(WoW)插件,目标是在物品Tooltip中显示其升级成本,但目前Tooltip上无任何相关内容显示。经排查,推测问题出在ItemLocation对象以及C_ItemUpgrade.GetItemUpgradeItemInfo(ItemLocation)函数上。目前调试还差2-3步就能获取所有相关信息,后续显示逻辑难度不大,现寻求WoW插件或Lua专家指点错误所在。
相关代码
-- 创建用于处理事件的框架 local frame = CreateFrame("Frame") -- 处理物品Tooltip显示及升级成本的函数 local function OnTooltipSetItem(tooltip) local name, link = tooltip:GetItem() if not link then return end -- 打印物品链接用于调试 print("物品链接:", link) -- 提取并打印物品ID local itemID = tonumber(string.match(link, "item:(%d+)")) if not itemID then print("提取ItemID失败") return end print("物品ID:", itemID) -- 尝试通过背包和槽位信息创建ItemLocation对象 local itemLocation for bag = 0, NUM_BAG_SLOTS do for slot = 1, C_Container.GetContainerNumSlots(bag) do local slotItemID = C_Container.GetContainerItemID(bag, slot) if slotItemID == itemID then itemLocation = ItemLocation:CreateFromBagAndSlot(bag, slot) break end end if itemLocation then break end end if itemLocation then if itemLocation:IsValid() then print("ItemLocation有效") local bag, slot = itemLocation:GetBagAndSlot() print("背包:", bag, "槽位:", slot) else print("ItemLocation无效") end else print("ItemLocation对象为nil") end -- 已装备物品的调试输出 if itemLocation and itemLocation:IsValid() then if itemLocation:GetType() == "BAG" then local bag, slot = itemLocation:GetBagAndSlot() print("背包:", bag, "槽位:", slot) elseif itemLocation:GetType() == "EQUIPMENT" then local equipmentSlot = itemLocation:GetEquipmentSlot() print("装备槽位:", equipmentSlot) end end -- 如果背包中未找到,检查已装备物品 if not itemLocation then for slot = 1, 19 do -- 19个装备槽位 local slotItemID = GetInventoryItemID("player", slot) if slotItemID == itemID then itemLocation = ItemLocation:CreateFromEquipmentSlot(slot) break end end end if not itemLocation then print("创建ItemLocation失败") return end -- ItemLocation的调试输出 print("ItemLocation状态:", itemLocation and itemLocation:IsValid() and "有效" or "无效") print("背包:", itemLocation and itemLocation:GetBagAndSlot() or "N/A") print("槽位:", itemLocation and itemLocation:GetBagAndSlot() or "N/A") -- 检查物品是否可升级 local isValid = C_ItemUpgrade.CanUpgradeItem(itemLocation) print("可升级:", isValid) if not isValid then return end -- 获取物品升级信息 local itemUpgradeInfo = C_ItemUpgrade.GetItemUpgradeItemInfo(itemLocation) if not itemUpgradeInfo then print("获取物品ID为", itemID, "的升级信息失败") print("ItemLocation状态:", itemLocation and itemLocation:IsValid() and "有效" or "无效") return end print("物品升级信息:", itemUpgradeInfo) -- 检查当前升级等级和最大升级等级 local currentUpgradeLevel = C_ItemUpgrade.GetItemUpgradeCurrentLevel(itemLocation) local maxUpgradeLevel = C_ItemUpgrade.GetItemUpgradeMaxLevel(itemLocation) print("当前升级等级:", currentUpgradeLevel) print("最大升级等级:", maxUpgradeLevel) -- 获取当前赛季 local currentSeason = C_ItemUpgrade.GetCurrentItemUpgradeSeason() print("当前赛季:", currentSeason) -- 获取赛季索引 local seasonIndex = itemUpgradeInfo.upgradeCostTypesForSeasonIndex and itemUpgradeInfo.upgradeCostTypesForSeasonIndex[currentSeason] print("赛季索引:", seasonIndex) -- 获取当前赛季的升级成本(如果有) local cost = itemUpgradeInfo.upgradeCostTypesForSeason and itemUpgradeInfo.upgradeCostTypesForSeason[seasonIndex] if cost then print("升级成本:", cost) tooltip:AddDoubleLine("升级成本:", GetCoinTextureString(cost), 1, 1, 1) else print("当前赛季无可用升级成本") end end -- 处理ADDON_LOADED事件的函数 local function OnAddonLoaded(self, event, addon) if addon == "UpgradeLion" then -- 注册Tooltip钩子 if TooltipDataProcessor then -- 适用于巨龙时代及以后版本 TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, OnTooltipSetItem) else -- 适用于更早版本 GameTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem) ItemRefTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem) end -- 注销ADDON_LOADED事件 self:UnregisterEvent("ADDON_LOADED") end end -- 注册ADDON_LOADED事件 frame:RegisterEvent("ADDON_LOADED") frame:SetScript("OnEvent", OnAddonLoaded)
问题排查与修复建议
1. ItemLocation创建顺序逻辑错误
你现在的代码在遍历背包后,先做了一轮有效性检查和输出,然后才去检查装备栏,但在背包遍历后如果没找到ItemLocation,后续的if not itemLocation then return会直接终止函数,导致装备栏的ItemLocation创建逻辑根本不会执行。
修复: 调整顺序,先完成背包+装备栏的ItemLocation创建,再统一做有效性判断:
-- 先遍历背包创建ItemLocation local itemLocation for bag = 0, NUM_BAG_SLOTS do for slot = 1, C_Container.GetContainerNumSlots(bag) do local slotItemID = C_Container.GetContainerItemID(bag, slot) if slotItemID == itemID then itemLocation = ItemLocation:CreateFromBagAndSlot(bag, slot) break end end if itemLocation then break end end -- 背包没找到,再遍历装备栏 if not itemLocation then -- 用枚举代替硬编码1-19,适配不同版本 for slot = Enum.InventorySlot.HeadSlot, Enum.InventorySlot.BackSlot do local slotItemID = GetInventoryItemID("player", slot) if slotItemID == itemID then itemLocation = ItemLocation:CreateFromEquipmentSlot(slot) break end end end -- 最后统一判断是否创建成功 if not itemLocation or not itemLocation:IsValid() then print("创建有效ItemLocation失败") return end
2. 新版本Tooltip钩子参数错误
巨龙时代及以后版本使用TooltipDataProcessor时,回调函数的参数是tooltip, data,而不是直接通过tooltip:GetItem()获取链接,这会导致新版本中无法正确拿到物品信息。
修复: 适配新版本的钩子逻辑:
if TooltipDataProcessor then TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, function(tooltip, data) local link = data and data.hyperlink if not link then return end -- 把原来OnTooltipSetItem里的逻辑移到这里,用link代替tooltip:GetItem()的返回值 local itemID = tonumber(string.match(link, "item:(%d+)")) -- ...后续逻辑... end) else -- 旧版本钩子保持不变 GameTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem) ItemRefTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem) end
3. 升级成本获取路径错误
你当前从itemUpgradeInfo中获取成本的逻辑不对,upgradeCostTypesForSeason和upgradeCostTypesForSeasonIndex的结构并非直接通过索引取值。建议用DevTools_Dump(itemUpgradeInfo)打印完整结构,确认正确的字段路径。通常升级成本是按等级存储的,比如itemUpgradeInfo.upgradeCostsByLevel[currentUpgradeLevel + 1](如果要升级到下一级)。
4. 冗余代码清理
代码中有多处重复的ItemLocation有效性检查和打印,建议合并成一次检查,避免逻辑混乱,减少不必要的调试输出。
内容的提问来源于stack exchange,提问作者Lazy Loafs

