------------------------------------------------------ -- DisenchantPredictor.lua ------------------------------------------------------ FDP_VERSION = "11200.1"; ------------------------------------------------------ -- constants local FDP_DUST = 1; local FDP_ESSENCE = 2; local FDP_SHARD = 3; -- Configuration FDP_Config = { }; FDP_Config.Tooltip = true; FDP_Config.Reagents = true; FDP_Config.Items = true; FDP_Config.Verbose = true; FDP_Config.AutoLoot = true; FDP_ItemIDs = { ["DUST_STRANGE"] = 10940; ["DUST_SOUL"] = 11083; ["DUST_VISION"] = 11137; ["DUST_DREAM"] = 11176; ["DUST_ILLUSION"] = 16204; ["ESSENCE_MAGIC_LESSER"] = 10938; ["ESSENCE_MAGIC_GREATER"] = 10939; ["ESSENCE_ASTRAL_LESSER"] = 10998; ["ESSENCE_ASTRAL_GREATER"] = 11082; ["ESSENCE_MYSTIC_LESSER"] = 11134; ["ESSENCE_MYSTIC_GREATER"] = 11135; ["ESSENCE_NETHER_LESSER"] = 11174; ["ESSENCE_NETHER_GREATER"] = 11175; ["ESSENCE_ETERNAL_LESSER"] = 16202; ["ESSENCE_ETERNAL_GREATER"] = 16203; ["SHARD_GLIMMER_SMALL"] = 10978; ["SHARD_GLIMMER_LARGE"] = 11084; ["SHARD_GLOWING_SMALL"] = 11138; ["SHARD_GLOWING_LARGE"] = 11139; ["SHARD_RADIANT_SMALL"] = 11177; ["SHARD_RADIANT_LARGE"] = 11178; ["SHARD_BRILLIANT_SMALL"] = 14343; ["SHARD_BRILLIANT_LARGE"] = 14344; ["NEXUS_CRYSTAL"] = 20725; } -- formula for dust by level: max(1, ceil((level - 10) / 10)) FDP_DustNames = { "DUST_STRANGE", -- 1-20 "DUST_SOUL", -- 21-30 "DUST_VISION", -- 31-40 "DUST_DREAM", -- 41-50 "DUST_ILLUSION", -- 51-60 } -- formula for essence by level: max(1, ceil((level - 5) / 5)) FDP_EssenceNames = { "ESSENCE_MAGIC_LESSER", -- 1-10 "ESSENCE_MAGIC_GREATER", -- 11-15 "ESSENCE_ASTRAL_LESSER", -- 16-20 "ESSENCE_ASTRAL_GREATER", -- 21-25 "ESSENCE_MYSTIC_LESSER", -- 26-30 "ESSENCE_MYSTIC_GREATER", -- 31-35 "ESSENCE_NETHER_LESSER", -- 36-40 "ESSENCE_NETHER_GREATER", -- 41-45 "ESSENCE_ETERNAL_LESSER", -- 46-50 "ESSENCE_ETERNAL_GREATER", -- 51-55 (51-60 is the same) "ESSENCE_ETERNAL_GREATER", -- 56-60 (51-60 is the same) } -- formula for shard by level: max(1, ceil((level - 15) / 5)) FDP_ShardNames = { "SHARD_GLIMMER_SMALL", -- 1-20 "SHARD_GLIMMER_LARGE", -- 21-25 "SHARD_GLOWING_SMALL", -- 26-30 "SHARD_GLOWING_LARGE", -- 31-35 "SHARD_RADIANT_SMALL", -- 36-40 "SHARD_RADIANT_LARGE", -- 41-45 "SHARD_BRILLIANT_SMALL", -- 46-50 "SHARD_BRILLIANT_LARGE", -- 51-55 (51-60 is the same) "SHARD_BRILLIANT_LARGE", -- 56-60 (51-60 is the same) } FDP_DustLevels = { "1-20", "21-30", "31-40", "41-50", "51-60", } FDP_EssenceLevels = { "1-10", "11-15", "16-20", "21-25", "26-30", "31-35", "36-40", "41-45", "46-50", "51-60", "51-60", } FDP_ShardLevels = { "1-20", "21-25", "26-30", "31-35", "36-40", "41-45", "46-50", "51-60", "51-60", } FDP_WeaponTypes = { "INVTYPE_2HWEAPON", "INVTYPE_WEAPON", "INVTYPE_WEAPONMAINHAND", "INVTYPE_WEAPONOFFHAND", "INVTYPE_RANGED" }; FDP_ArmorTypes = { "INVTYPE_BODY", "INVTYPE_CHEST", "INVTYPE_CLOAK", "INVTYPE_FEET", "INVTYPE_FINGER", "INVTYPE_HAND", "INVTYPE_HEAD", "INVTYPE_HOLDABLE", "INVTYPE_LEGS", "INVTYPE_NECK", "INVTYPE_RANGED", "INVTYPE_ROBE", "INVTYPE_SHIELD", "INVTYPE_SHOULDER", "INVTYPE_TABARD", "INVTYPE_TRINKET", "INVTYPE_WAIST", "INVTYPE_WRIST", }; FDP_COLOR_ARTIFACT = "ffffcc9d"; -- untested, extrapolated from ITEM_QUALITY_COLORS FDP_COLOR_LEGENDARY = "ffff8000"; -- untested, extrapolated from ITEM_QUALITY_COLORS FDP_COLOR_EPIC = "ffa335ee"; FDP_COLOR_RARE = "ff0070dd"; FDP_COLOR_UNCOMMON = "ff1eff00"; FDP_COLOR_COMMON = "ffffffff"; FDP_COLOR_POOR = "ff9d9d9d"; FDP_QUALITY_COLORS = { [0] = FDP_COLOR_POOR, [1] = FDP_COLOR_COMMON, [2] = FDP_COLOR_UNCOMMON, [3] = FDP_COLOR_RARE, [4] = FDP_COLOR_EPIC, [5] = FDP_COLOR_LEGENDARY, [6] = FDP_COLOR_ARTIFACT, }; local function FDP_Tooltip_Hook(frame, name, link) if ( FDP_Config.Tooltip and link ~= nil) then local _, _, itemID = string.find(link, "item:(%d+):%d+:%d+:%d+"); if (itemID == nil or tonumber(itemID) == nil) then return false; end itemID = tonumber(itemID); if (GFWTable.KeyOf(FDP_Exceptions, itemID)) then return false; end if (FDP_Config.Reagents) then if (FDP_TooltipForReagent(frame, itemID)) then return true; end end if (FDP_Config.Items) then local color, level, kind = FDP_ItemInfoForLink(link); if (level ~= nil and level > 0 and kind ~= nil) then local dustIndex, essenceIndex, shardIndex = FDP_DisenchantByLevel(level); local dustName, essenceName, shardName, crystalName; if (color == FDP_COLOR_EPIC and level > 50 ) then crystalName = FDP_DisplayName("NEXUS_CRYSTAL"); frame:AddLine(FDP_CAN_DIS_TO.." "..crystalName, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); return true; elseif (color == FDP_COLOR_RARE) then shardName = FDP_DisplayName(FDP_ShardNames[shardIndex]); if (level > 50) then crystalName = FDP_DisplayName("NEXUS_CRYSTAL"); if (FDP_Config.Verbose) then frame:AddLine(FDP_CAN_DIS_TO, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); frame:AddLine(" "..shardName.." "..FDP_MOST_LIKELY, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); frame:AddLine(" "..crystalName.." "..FDP_RARELY, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); else frame:AddLine(FDP_CAN_DIS_TO_SHORT, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); frame:AddDoubleLine(" ", shardName..crystalName); end else frame:AddLine(FDP_CAN_DIS_TO.." "..shardName, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); end return true; elseif (color == FDP_COLOR_UNCOMMON) then dustName = FDP_DisplayName(FDP_DustNames[dustIndex]); essenceName = FDP_DisplayName(FDP_EssenceNames[essenceIndex]); shardName = FDP_DisplayName(FDP_ShardNames[shardIndex]); if (FDP_Config.Verbose) then frame:AddLine(FDP_CAN_DIS_TO, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); frame:AddLine(" "..dustName.." "..FDP_MOST_LIKELY, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); if (kind == "WEAPON") then frame:AddLine(" "..essenceName.." "..FDP_JUST_LIKELY, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); else frame:AddLine(" "..essenceName.." "..FDP_OCCASIONALLY, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); end frame:AddLine(" "..shardName.." "..FDP_RARELY, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); else frame:AddDoubleLine(FDP_CAN_DIS_TO_SHORT, shardName, GFW_FONT_COLOR.r, GFW_FONT_COLOR.g, GFW_FONT_COLOR.b); frame:AddDoubleLine(" ", essenceName..dustName); end return true; end end end end return false; end function FDP_TooltipForReagent(frame, itemID) local identifier = GFWTable.KeyOf(FDP_ItemIDs, itemID); if (identifier == nil) then return false; -- not an itemID we care about end if (identifier == "NEXUS_CRYSTAL") then frame:AddLine(FDP_NEXUS_CAN_DIS_FROM_1, 0.7,0.7,0.7); frame:AddLine(FDP_NEXUS_CAN_DIS_FROM_2, 0.7,0.7,0.7); return true; end local kind, levelRange; local namesTables = {FDP_DustNames, FDP_EssenceNames, FDP_ShardNames}; local levelTables = {FDP_DustLevels, FDP_EssenceLevels, FDP_ShardLevels}; for tableID, aTable in namesTables do local index = GFWTable.KeyOf(aTable, identifier); if (index ~= nil) then levelRange = levelTables[tableID][index]; kind = tableID; break; end end if (kind ~= nil) then frame:AddLine(string.format(FDP_CAN_DIS_FROM_FORMAT, levelRange), 0.7,0.7,0.7); if (FDP_Config.Verbose) then if (kind == FDP_SHARD) then frame:AddLine(FDP_SHARD_VERBOSE, 0.7,0.7,0.7); elseif (kind == FDP_ESSENCE) then frame:AddLine(FDP_ESSENCE_VERBOSE, 0.7,0.7,0.7); elseif (kind == FDP_DUST) then frame:AddLine(FDP_DUST_VERBOSE, 0.7,0.7,0.7); end end return true; end end function FDP_OnLoad() -- Register Slash Commands SLASH_FDP1 = "/enchant"; SLASH_FDP2 = "/disenchant"; SLASH_FDP3 = "/ench"; SLASH_FDP4 = "/dis"; SLASH_FDP5 = "/de"; SLASH_FDP6 = "/dp"; SlashCmdList["FDP"] = function(msg) FDP_ChatCommandHandler(msg); end GFWTooltip_AddCallback("GFW_DisenchantPredictor", FDP_Tooltip_Hook); DisenchantPredictorFrame:RegisterEvent("LOOT_OPENED"); GFWUtils.Print("Fizzwidget Disenchant Predictor "..FDP_VERSION.." initialized!"); end local LootOpenedTime = 0; local MIN_TRY_AGAIN_TIME = 1; function FDP_OnEvent(event, arg1) if (event == "LOOT_OPENED") then if (GetTime() - LootOpenedTime < MIN_TRY_AGAIN_TIME) then return; -- UIParent likes to get lost in infinite recursion... end LootOpenedTime = GetTime(); if (FDP_Config.AutoLoot and LootFrame:IsVisible()) then for slot = 1, GetNumLootItems() do if (LootSlotIsCoin(slot)) then return; -- coins don't come from disenchanting. else local link = GetLootSlotLink(slot); if (link == nil) then return; end local _, _, itemID = string.find(link, "item:(%d+):%d+:%d+:%d+"); if (itemID == nil or tonumber(itemID) == nil) then return; end itemID = tonumber(itemID); local identifier = GFWTable.KeyOf(FDP_ItemIDs, itemID); if (identifier == nil) then return; -- if it's not one of our known disenchanted reagents, we probably didn't get here by disenchanting. end end end CloseLoot(); -- closing the loot window, if it's from disenchanting, automatically loots the items. end end end function FDP_ChatCommandHandler(msg) -- Print Help if ( msg == "help" ) or ( msg == "" ) then GFWUtils.Print("Fizzwidget Disenchant Predictor "..FDP_VERSION..":"); GFWUtils.Print("/enchant (or /ench or /disenchant or /dis or /de)"); GFWUtils.Print("- "..GFWUtils.Hilite("help").." - "..FDP_HELP_HELP); GFWUtils.Print("- "..GFWUtils.Hilite("status").." - "..FDP_HELP_STATUS); GFWUtils.Print("- "..GFWUtils.Hilite("reagents on").." | "..GFWUtils.Hilite("off").." - "..FDP_HELP_REAGENTS); GFWUtils.Print("- "..GFWUtils.Hilite("items on").." | "..GFWUtils.Hilite("off").." - "..FDP_HELP_ITEMS); GFWUtils.Print("- "..GFWUtils.Hilite("tooltip on").." | "..GFWUtils.Hilite("off").." - "..FDP_HELP_TOOLTIP); GFWUtils.Print("- "..GFWUtils.Hilite("verbose on").." | "..GFWUtils.Hilite("off").." - "..FDP_HELP_VERBOSE); GFWUtils.Print("- "..GFWUtils.Hilite("autoloot on").." | "..GFWUtils.Hilite("off").." - "..FDP_HELP_AUTOLOOT); GFWUtils.Print("- "..GFWUtils.Hilite(FDP_CMD_NUMBER).." - "..FDP_HELP_NUMBER); GFWUtils.Print("- "..GFWUtils.Hilite(FDP_CMD_LINK).." - "..FDP_HELP_LINK); return; end if (msg == "version") then GFWUtils.Print("Fizzwidget Disenchant Predictor "..FDP_VERSION); return; end if (msg == "reagents on") then FDP_Config.Reagents = true; FDP_Config.Tooltip = true; GFWUtils.Print(FDP_STATUS_REAGENTS_ON); return; end if (msg == "reagents off") then FDP_Config.Reagents = false; GFWUtils.Print(FDP_STATUS_REAGENTS_OFF); return; end if (msg == "items on") then FDP_Config.Items = true; FDP_Config.Tooltip = true; GFWUtils.Print(FDP_STATUS_ITEMS_ON); return; end if (msg == "items off") then FDP_Config.Items = false; GFWUtils.Print(FDP_STATUS_ITEMS_OFF); return; end if (msg == "tooltip on") then FDP_Config.Tooltip = true; GFWUtils.Print(FDP_STATUS_TOOLTIP_ON); return; end if (msg == "tooltip off") then FDP_Config.Tooltip = false; GFWUtils.Print(FDP_STATUS_TOOLTIP_OFF); return; end if (msg == "verbose on") then FDP_Config.Verbose = true; GFWUtils.Print(FDP_STATUS_VERBOSE_ON); return; end if (msg == "verbose off") then FDP_Config.Verbose = false; GFWUtils.Print(FDP_STATUS_VERBOSE_OFF); return; end if (msg == "autoloot on") then FDP_Config.AutoLoot = true; GFWUtils.Print(FDP_STATUS_AUTOLOOT_ON); return; end if (msg == "autoloot off") then FDP_Config.AutoLoot = false; GFWUtils.Print(FDP_STATUS_AUTOLOOT_OFF); return; end if ( msg == "status" ) then if ( FDP_Config.Tooltip and (FDP_Config.Items or FDP_Config.Reagents)) then if (FDP_Config.Items) then GFWUtils.Print(FDP_STATUS_ITEMS_ON); else GFWUtils.Print(FDP_STATUS_ITEMS_OFF); end if (FDP_Config.Reagents) then GFWUtils.Print(FDP_STATUS_REAGENTS_ON); if ( FDP_Config.Verbose ) then GFWUtils.Print(FDP_STATUS_VERBOSE_ON); else GFWUtils.Print(FDP_STATUS_VERBOSE_OFF); end else GFWUtils.Print(FDP_STATUS_REAGENTS_OFF); end else GFWUtils.Print(FDP_STATUS_TOOLTIP_OFF); end if ( FDP_Config.AutoLoot ) then GFWUtils.Print(FDP_STATUS_AUTOLOOT_ON); else GFWUtils.Print(FDP_STATUS_AUTOLOOT_OFF); end return; end if ( tonumber(msg) ~= nil ) then local level = tonumber(msg); if (level < 1 or level > 60) then GFWUtils.Print(FDP_ERROR_ITEMLEVEL); end local dustIndex, essenceIndex, shardIndex = FDP_DisenchantByLevel(level); GFWUtils.Print(string.format(FDP_ITEM_DIS_BY_LEVEL_FORMAT, GFWUtils.Hilite(level))); GFWUtils.Print(FDP_DisplayName(FDP_DustNames[dustIndex]).." "..FDP_DUST_BY_LEVEL_INFO); GFWUtils.Print(FDP_DisplayName(FDP_EssenceNames[essenceIndex]).." "..FDP_ESSENCE_BY_LEVEL_INFO); GFWUtils.Print(FDP_DisplayName(FDP_ShardNames[shardIndex]).." "..FDP_SHARD_BY_LEVEL_INFO); return; end local _, _, link = string.find(msg, "(.c%x+.Hitem:%d+:%d+:%d+:%d+.h%[[^]]+%].h.r)"); if (link ~= nil and link ~= "") then local _, _, itemID = string.find(link, "|c%x+|Hitem:(%d+):%d+:%d+:%d+|h%[.-%]|h|r"); if (itemID == nil or tonumber(itemID) == nil) then GFWUtils.Print(string.format(FDP_ERROR_ITEMID_FORMAT, link)); return; end itemID = tonumber(itemID); local identifier = GFWTable.KeyOf(FDP_ItemIDs, itemID); if (identifier == "NEXUS_CRYSTAL") then GFWUtils.Print(link..": "..FDP_NEXUS_CAN_DIS_FROM_1.." "..FDP_NEXUS_CAN_DIS_FROM_2); return; elseif (identifier ~= nil) then local kind, levelRange; local namesTables = {FDP_DustNames, FDP_EssenceNames, FDP_ShardNames}; local levelTables = {FDP_DustLevels, FDP_EssenceLevels, FDP_ShardLevels}; for tableID, aTable in namesTables do local index = GFWTable.KeyOf(aTable, identifier); if (index ~= nil) then levelRange = levelTables[tableID][index]; kind = tableID; break; end end if (kind ~= nil) then GFWUtils.Print(link..": "..string.format(FDP_CAN_DIS_FROM_FORMAT, levelRange)); if (FDP_Config.Verbose) then if (kind == FDP_SHARD) then GFWUtils.Print(FDP_SHARD_VERBOSE); elseif (kind == FDP_ESSENCE) then GFWUtils.Print(FDP_ESSENCE_VERBOSE); elseif (kind == FDP_DUST) then GFWUtils.Print(FDP_DUST_VERBOSE); end end return; end end if (GFWTable.KeyOf(FDP_Exceptions, itemID)) then GFWUtils.Print(string.format(FDP_CANT_DIS_EXCEPTION_FORMAT, link)); return; end local color, level, kind = FDP_ItemInfoForLink(link); local colorName; if (color ~= FDP_COLOR_UNCOMMON and color ~= FDP_COLOR_RARE and color ~= FDP_COLOR_EPIC) then GFWUtils.Print(string.format(FDP_CANT_DIS_QUALITY_FORMAT, link)); return; end if (level ~= nil and level > 0) then local dustIndex, essenceIndex, shardIndex = FDP_DisenchantByLevel(level); local dustName, essenceName, shardName, crystalName; if (color == FDP_COLOR_EPIC and kind ~= nil and level > 50) then crystalName = FDP_DisplayName("NEXUS_CRYSTAL"); GFWUtils.Print(link ..": "..FDP_CAN_DIS_TO.." ".. crystalName); return; elseif (color == FDP_COLOR_RARE and kind ~= nil) then shardName = FDP_DisplayName(FDP_ShardNames[shardIndex]); if (level > 50) then crystalName = FDP_DisplayName("NEXUS_CRYSTAL"); GFWUtils.Print(link ..": "..FDP_CAN_DIS_TO); GFWUtils.Print(" - "..shardName.." "..FDP_MOST_LIKELY); GFWUtils.Print(" - "..crystalName.." "..FDP_RARELY); else GFWUtils.Print(link ..": "..FDP_CAN_DIS_TO.." "..shardName); end return; elseif (color == FDP_COLOR_UNCOMMON and kind ~= nil) then dustName = FDP_DisplayName(FDP_DustNames[dustIndex]); essenceName = FDP_DisplayName(FDP_EssenceNames[essenceIndex]); shardName = FDP_DisplayName(FDP_ShardNames[shardIndex]); GFWUtils.Print(link ..": "..FDP_CAN_DIS_TO); GFWUtils.Print(" - "..dustName.." "..FDP_MOST_LIKELY); if (kind == "WEAPON") then GFWUtils.Print(" - "..essenceName.." "..FDP_JUST_LIKELY); else GFWUtils.Print(" - "..essenceName.." "..FDP_OCCASIONALLY); end GFWUtils.Print(" - "..shardName.." "..FDP_RARELY); return; end else if (kind == nil) then GFWUtils.Print(string.format(FDP_CANT_DIS_TYPE_FORMAT, link)); return; else if (color == FDP_COLOR_EPIC) then crystalName = FDP_DisplayName("NEXUS_CRYSTAL"); GFWUtils.Print(string.format(FDP_NOLEVEL_PURPLE_FORMAT, link, crystalName)); elseif (color == FDP_COLOR_RARE) then GFWUtils.Print(string.format(FDP_NOLEVEL_BLUE_FORMAT, link)); else -- must be green GFWUtils.Print(string.format(FDP_NOLEVEL_GREEN_FORMAT, link)); if (kind == "WEAPON") then GFWUtils.Print(FDP_GENERAL_WEAPON_RULE); else GFWUtils.Print(FDP_GENERAL_OTHER_RULE); end end return; end end GFWUtils.Print(string.format(FDP_BAIL_FORMAT, link)); return; end -- If we're this far, we probably have bad input. FDP_ChatCommandHandler("help"); end function FDP_DisenchantByLevel(level) local dustIndex = math.max(1, math.ceil((level - 10) / 10)); local essenceIndex = math.max(1, math.ceil((level - 5) / 5)); local shardIndex = math.max(1, math.ceil((level - 15) / 5)); return dustIndex, essenceIndex, shardIndex; end -- returns a link if possible, colored localized name otherwise. function FDP_DisplayName(identifier) local itemID = FDP_ItemIDs[identifier]; if (itemID == nil) then return getglobal(identifier); -- shouldn't happen anyways, right? end local colorCode; if (identifier == "NEXUS_CRYSTAL") then colorCode = FDP_COLOR_EPIC; else local namesTables = {FDP_DustNames, FDP_EssenceNames, FDP_ShardNames}; local kind; for tableID, aTable in namesTables do local index = GFWTable.KeyOf(aTable, identifier); if (index ~= nil) then kind = tableID; break; end end if (kind == FDP_SHARD) then colorCode = FDP_COLOR_RARE; elseif (kind == FDP_ESSENCE) then colorCode = FDP_COLOR_UNCOMMON; elseif (kind == FDP_DUST) then colorCode = FDP_COLOR_COMMON; end end local itemLink = "item:"..itemID..":0:0:0"; local localizedName = GetItemInfo(itemLink); if (localizedName) then return "|c"..colorCode.."|H"..itemLink.."|h["..localizedName.."]|h|r"; else localizedName = getglobal(identifier); return "|c"..colorCode..localizedName.."|r"; end end function FDP_ItemInfoForLink(itemLink) _, _, link = string.find(itemLink, "(item:%d+:%d+:%d+:%d+)"); if (link == nil or link == "") then return nil; end local name, link, quality, level, type, subType, stackCount, equipLoc, icon = GetItemInfo(link); local color = FDP_QUALITY_COLORS[quality]; local skill, kind; if (GFWTable.KeyOf(FDP_WeaponTypes, equipLoc)) then kind = "WEAPON"; end if (GFWTable.KeyOf(FDP_ArmorTypes, equipLoc)) then kind = "ARMOR"; end --[[ if (kind and level == 0) then skill = FDP_TooltipInfoForLink(link); end ]] return color, level, kind, skill; end function FDP_TooltipInfoForLink(link) FDPHiddenTooltip:ClearLines(); FDPHiddenTooltip:SetHyperlink(link); local level, skill, kind; if (FDP_ITEM_DURATION_DAYS == nil) then FDP_ITEM_DURATION_DAYS = GFWUtils.FormatToPattern(ITEM_DURATION_DAYS); end if (FDP_ITEM_DURATION_HOURS == nil) then FDP_ITEM_DURATION_HOURS = GFWUtils.FormatToPattern(ITEM_DURATION_HOURS); end if (FDP_ITEM_DURATION_MIN == nil) then FDP_ITEM_DURATION_MIN = GFWUtils.FormatToPattern(ITEM_DURATION_MIN); end if (FDP_ITEM_DURATION_SEC == nil) then FDP_ITEM_DURATION_SEC = GFWUtils.FormatToPattern(ITEM_DURATION_SEC); end if (FDP_ITEM_MIN_LEVEL == nil) then FDP_ITEM_MIN_LEVEL = GFWUtils.FormatToPattern(ITEM_MIN_LEVEL); end if (FDP_ITEM_MIN_SKILL == nil) then FDP_ITEM_MIN_SKILL = GFWUtils.FormatToPattern(ITEM_MIN_SKILL); end for lineNum = 1, FDPHiddenTooltip:NumLines() do local leftText = getglobal("FDPHiddenTooltipTextLeft"..lineNum):GetText(); if (string.find(leftText, FDP_ITEM_DURATION_DAYS) or string.find(leftText, FDP_ITEM_DURATION_HOURS) or string.find(leftText, FDP_ITEM_DURATION_MIN) or string.find(leftText, FDP_ITEM_DURATION_SEC)) then return nil; -- items with a duration can't be disenchanted even if we might otherwise think they can. end local _, _, skillName, skillString = string.find(leftText, FDP_ITEM_MIN_SKILL); if (levelString == nil and skillString ~= nil and tonumber(skillString) ~= nil) then if (lineNum < 4) then kind = "RECIPE"; -- if it's got a skill level on one of the first couple of lines and no armor slot or speed, it's very likely a recipe end if (skill ~= nil) then kind = "RECIPE"; -- if it lists a required skill level more than once, it's almost certainly a recipe end skill = tonumber(skillString); end end for lineNum = 1, FDPHiddenTooltip:NumLines() do -- for some reason ClearLines alone isn't clearing the right-side text getglobal("FDPHiddenTooltipTextLeft"..lineNum):SetText(nil); getglobal("FDPHiddenTooltipTextRight"..lineNum):SetText(nil); end --DevTools_Dump({skill=skill, level=level}); if (kind == "RECIPE") then return nil; -- if there's both a skill requirement and a level requirement, it's probably a recipe (which can't be DE'ed) end return skill; end ------------------------------------------------------ -- Runtime loading ------------------------------------------------------ FDP_OnLoad();