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.
1856 lines
61 KiB
1856 lines
61 KiB
----Post 10.1----
|
|
|
|
local _, addon = ...
|
|
if addon.GetTooltipInfoVersion() ~= 2 then
|
|
return
|
|
end
|
|
|
|
local C_TooltipInfo = C_TooltipInfo;
|
|
local GetInfoByHyperlink = C_TooltipInfo.GetHyperlink;
|
|
local GetInfoByItemID = C_TooltipInfo.GetItemByID;
|
|
local GetInfoByBagItem = C_TooltipInfo.GetBagItem;
|
|
local GetInfoByInventoryItem = C_TooltipInfo.GetInventoryItem;
|
|
|
|
--C_TooltipInfo.GetInventoryItem("player", 13, true)
|
|
--TooltipDataLineType
|
|
local LINE_TYPE_SOCKET = 3;
|
|
local LINE_TYPE_TOY_EFFECT = Enum.TooltipDataLineType.ToyEffect;
|
|
local LINE_TYPE_TOY_DESC = Enum.TooltipDataLineType.ToyDescription;
|
|
|
|
local strtrim = strtrim;
|
|
local strsub = string.sub;
|
|
local gsub = string.gsub;
|
|
local match = string.match;
|
|
local find = string.find;
|
|
local format = string.format;
|
|
local split = string.split;
|
|
local tonumber = tonumber;
|
|
local type = type;
|
|
local select = select;
|
|
local tinsert = table.insert;
|
|
|
|
local floor = math.floor;
|
|
local max = math.max;
|
|
|
|
local _G = _G;
|
|
local L = Narci.L;
|
|
local NarciAPI = NarciAPI;
|
|
local TEXT_LOCALE = GetLocale();
|
|
|
|
local GetItemInfoInstant = GetItemInfoInstant;
|
|
local GetItemGem = GetItemGem;
|
|
local GetItemStats = GetItemStats;
|
|
local GetInventoryItemLink = GetInventoryItemLink;
|
|
local StripHyperlinks = StripHyperlinks; --Added in 10.1.0
|
|
|
|
local function IsArtifactRelic(item)
|
|
--an alternative to IsArtifactRelicItem()
|
|
local _, _, _, _, _, classID, subclassID = GetItemInfoInstant(item);
|
|
return classID == 3 and subclassID == 11
|
|
end
|
|
|
|
--[[
|
|
Enum.TooltipDataLineType
|
|
|
|
GameTooltip Color Scheme
|
|
1, 0.13, 0.13 --red
|
|
0, 1, 0 --green
|
|
1, 1, 1 --white
|
|
1, 0.5, 1 --pink transmog
|
|
0.5, 0.5, 0.5 --grey
|
|
|
|
ITEM_SET_LEGACY_INACTIVE_BONUS
|
|
ITEM_LEGACY_INACTIVE_EFFECTS
|
|
--]]
|
|
|
|
local function RoundColor(a)
|
|
return tonumber(format("%.2f", floor(a*100+0.5)*0.01 ))
|
|
end
|
|
|
|
local function IsTextColorColor(colorVal, r, g, b)
|
|
if not colorVal then return false end;
|
|
return (RoundColor(colorVal.r) == r) and (RoundColor(colorVal.g) == g) and (RoundColor(colorVal.b) == b)
|
|
end
|
|
|
|
local function IsTextColorRed(colorVal)
|
|
--1, 0.13, 0.13
|
|
if not colorVal then return false end;
|
|
local r, g, b = colorVal.r, colorVal.g, colorVal.b;
|
|
return (r > 0.99) and (g > 0.12 and g < 0.14) and (b > 0.12 and b < 0.14)
|
|
end
|
|
|
|
local function IsTextColorYellow(colorVal)
|
|
--1, 0.82, 0
|
|
if not colorVal then return false end;
|
|
local r, g, b = colorVal.r, colorVal.g, colorVal.b;
|
|
return (r > 0.99) and (g > 0.83 and g < 0.81) and (b < 0.01)
|
|
end
|
|
|
|
local function IsTextColorWhite(colorVal)
|
|
if not colorVal then return false end;
|
|
local r, g, b = colorVal.r, colorVal.g, colorVal.b;
|
|
return (r > 0.99) and (g > 0.99) and (b > 0.99)
|
|
end
|
|
|
|
local function IsTextColor50Grey(colorVal)
|
|
--0.5, 0.5, 0.5
|
|
if not colorVal then return false end;
|
|
local r, g, b = colorVal.r, colorVal.g, colorVal.b;
|
|
return (r > 0.49 and r < 0.51) and (g > 0.49 and g < 0.51) and (b > 0.49 and b < 0.51)
|
|
end
|
|
|
|
|
|
local function TrimColon(text)
|
|
return strtrim(text, "::");
|
|
end
|
|
|
|
local function TrimWhiteSpace(text)
|
|
return gsub(text, "%%s", "");
|
|
end
|
|
|
|
local function Pattern_WrapBrace(text)
|
|
return text and gsub(text, "([()()])", "%%%1");
|
|
end
|
|
|
|
local function Pattern_WrapSpace(text)
|
|
return text and gsub(text, "%%s", "%(%.%+%)");
|
|
end
|
|
|
|
local function Pattern_WrapNumber(text)
|
|
if not text then return end
|
|
text = gsub(text, "%%d", "%(%%d%)");
|
|
text = gsub(text, "%%d%+", "%(%%d%+%)");
|
|
return text
|
|
end
|
|
|
|
local LEFT_BRACE = "%(";
|
|
local RIGHT_BRACE = "%)";
|
|
|
|
|
|
local ON_USE = ITEM_SPELL_TRIGGER_ONUSE;
|
|
local ON_EQUIP = ITEM_SPELL_TRIGGER_ONEQUIP;
|
|
local ON_PROC = ITEM_SPELL_TRIGGER_ONPROC;
|
|
local ITEM_BONUS = L["Item Bonus"]; --Bonus: (used by Domination Shard) --ITEM_SOCKET_BONUS
|
|
local NO_COMMA_ON_USE = TrimColon(ON_USE);
|
|
local NO_COMMA_ON_EQUIP = TrimColon(ON_EQUIP);
|
|
local NO_COMMA_ON_PROC = TrimColon(ON_PROC);
|
|
local NO_COMMA_SET_BONUS = TrimColon(ITEM_BONUS);
|
|
local GEM_MIN_LEVEL = SOCKETING_ITEM_MIN_LEVEL_I; --Requires Item Level:
|
|
local GREY_FONT = "|cff959595";
|
|
local SOURCE_KNOWN = TRANSMOGRIFY_TOOLTIP_APPEARANCE_KNOWN;
|
|
local APPEARANCE_KNOWN = TRANSMOGRIFY_TOOLTIP_ITEM_UNKNOWN_APPEARANCE_KNOWN;
|
|
local APPEARANCE_UNKNOWN = TRANSMOGRIFY_TOOLTIP_APPEARANCE_UNKNOWN;
|
|
|
|
local TEXT_SPELL_RANGE = TrimWhiteSpace(SPELL_RANGE or "%s yd range");
|
|
local TEXT_SPELL_RANGE_UNLIMITED = SPELL_RANGE_UNLIMITED or "Unlimited range";
|
|
local TEXT_SPELL_RANGE_MELEE = MELEE_RANGE or "Melee Range";
|
|
local TEXT_SPELL_CAST_TIME_INSTANT = SPELL_CAST_TIME_INSTANT or "Instant";
|
|
local TEXT_SPELL_CAST_TIME_SEC = gsub(SPELL_CAST_TIME_SEC or "%.2g sec cast", "%%.2g", "");
|
|
local TEXT_SPELL_CAST_CHANNELED = SPELL_CAST_CHANNELED or "Channeled";
|
|
local TEXT_SPELL_PASSIVE = SPELL_PASSIVE or "Passive";
|
|
local TEXT_SPELL_COOLDOWN = L["Find Cooldown"];
|
|
local TEXT_SPELL_RECHARGE = L["Find Recharge"];
|
|
local TEXT_REPLACES_SPELL = TrimWhiteSpace(REPLACES_SPELL or "Replaces %s");
|
|
local TEXT_COSMETIC = ITEM_COSMETIC or "Cosmetic";
|
|
|
|
local SET_BONUS = TrimWhiteSpace(ITEM_SET_BONUS); --"Set: %s" --SET_BONUS_GRAY
|
|
local SOCKET_BONUS = TrimWhiteSpace(ITEM_SOCKET_BONUS); --Socket Bonus: %s
|
|
|
|
local PATTERN_COOLDOWN_TIME = "%((%d.+) Cooldown%)$";
|
|
local PATTERN_UPGRADE_LEVEL = gsub(ITEM_UPGRADE_TOOLTIP_FORMAT, "%%d+", "(%%d+)"); --Upgrade Level: %d/%d
|
|
local PATTERN_UPGRADE_STRING = gsub(ITEM_UPGRADE_TOOLTIP_FORMAT or "Upgrade Level: %d/%d", "%%d/%%d", "(.+)"); --Upgrade Level: %d/%d
|
|
local PATTERN_ITEM_SET_NAME = "(.+) %((%d+)/(%d+)%)"; --Pattern_WrapNumber( Pattern_WrapSpace( Pattern_WrapBrace( ITEM_SET_NAME) ) );
|
|
local PATTERN_CLASS_REQUIREMENT = Pattern_WrapSpace(ITEM_CLASSES_ALLOWED);
|
|
local PATTERN_AMMO_DPS = gsub(AMMO_DAMAGE_TEMPLATE, "%%s", "([%%d.]+)");
|
|
local PATTERN_PROFESSION_QUALITY = Pattern_WrapSpace(PROFESSIONS_CRAFTING_QUALITY or "Quality: %s");
|
|
local PATTERN_ITEM_LEVEL = ITEM_LEVEL or "Item Level";
|
|
local PATTERN_UPGRADE_TRACK_NAME = gsub(ITEM_UPGRADE_TOOLTIP_FORMAT_STRING or "Upgrade Level: %s %d/%d", "%%s", "(%%D+)");
|
|
|
|
local ITEM_UPGRADE_TRACK_LEVELS = {
|
|
--[TrackName] = maxItemLevel
|
|
};
|
|
|
|
local SOCKET_TYPE_TEXTURE = {
|
|
Yellow = "Yellow",
|
|
Red = "Red",
|
|
Blue = "Blue",
|
|
Hydraulic = "HYDRAULIC",
|
|
Cogwheel = "COGWHEEL",
|
|
Meta = "meta",
|
|
Prismatic = "prismatic",
|
|
PunchcardRed = "PunchcardRed",
|
|
PunchcardYellow = "PunchcardYellow",
|
|
PunchcardBlue = "PunchcardBlue",
|
|
Domination = "Domination",
|
|
Cypher = "META",
|
|
Tinker = "PunchcardRed",
|
|
};
|
|
|
|
do
|
|
if TEXT_LOCALE == "zhCN" then
|
|
LEFT_BRACE = "(";
|
|
RIGHT_BRACE = ")";
|
|
PATTERN_ITEM_SET_NAME = "(.+)((%d+)/(%d+))" --"%s(%d/%d)";
|
|
elseif TEXT_LOCALE == "zhTW" then
|
|
PATTERN_ITEM_SET_NAME = "(.+)%((%d+)/(%d+)%)"; --%s(%d/%d)
|
|
elseif TEXT_LOCALE == "deDE" then
|
|
PATTERN_ITEM_SET_NAME = "(.+) %((%d+)/(%d+)%)"; --"%1$s (%2$d/%3$d)"??
|
|
end
|
|
end
|
|
|
|
local function RemoveColorString(str)
|
|
if str then
|
|
return gsub(str, "|[cC][fF][fF][%w%s][%w%s][%w%s][%w%s][%w%s][%w%s](.*)|[rR]", "%1")
|
|
end
|
|
end
|
|
|
|
NarciAPI.RemoveColorString = RemoveColorString;
|
|
|
|
local function FormatItemLink(link)
|
|
return match(link, "(item:[%-?%d:]+)");
|
|
end
|
|
|
|
local function FormatString(text, removedText, keepFormat)
|
|
if not keepFormat then
|
|
text = strtrim(text, removedText);
|
|
text = TrimColon(text);
|
|
text = strtrim(text); --remove space
|
|
text = gsub(text, LEFT_BRACE, "\n\n"..GREY_FONT)
|
|
text = gsub(text, RIGHT_BRACE, "|r")
|
|
end
|
|
return text;
|
|
end
|
|
|
|
local function TrimCooldownText(text)
|
|
text = TrimColon(text);
|
|
local cooldownText = match(text, PATTERN_COOLDOWN_TIME);
|
|
text = gsub(text, LEFT_BRACE..".+"..RIGHT_BRACE.."$", "");
|
|
text = strtrim(text);
|
|
return text, cooldownText;
|
|
end
|
|
|
|
local function ReplacePureGreenText(text)
|
|
return gsub(text, "cFF.0FF.0", "cFF00E700");
|
|
end
|
|
|
|
--[[
|
|
local function GetLineText(lines, index)
|
|
if lines[index] and lines[index].args then
|
|
return lines[index].args[2].stringVal;
|
|
end
|
|
end
|
|
|
|
local function GetLineRightText(lines, index)
|
|
if lines[index] and lines[index].args and lines[index].args[4] then
|
|
return lines[index].args[4].stringVal;
|
|
end
|
|
end
|
|
--]]
|
|
|
|
local function GetLineText(lines, index)
|
|
--10.1.0
|
|
if lines[index] then
|
|
return lines[index].leftText;
|
|
end
|
|
end
|
|
|
|
local function GetLineRightText(lines, index)
|
|
if lines[index] then
|
|
return lines[index].rightText;
|
|
end
|
|
end
|
|
|
|
local function GetCraftingQualityFromText(text)
|
|
--escape sequence: "|A:Professions-Icon-Quality-Tier1-Small:26:26:0:-1|a"
|
|
local quality = match(text, "[Pp]rofessions%-[Ii]con%-[Qq]uality%-[Tt]ier(%d)", 1);
|
|
if quality then
|
|
return tonumber(quality)
|
|
end
|
|
end
|
|
|
|
local function ReformatCraftingQualityText(text, addTierTextToRight)
|
|
local quality = match(text, "[Qq]uality%-[Tt]ier(%d)", 1); --10.0.7: Changed to Professions-(Chat)Icon-Quality-Tier
|
|
if quality then
|
|
local tempText = gsub(text, "%s?|A[^|]+|a", "");
|
|
if tempText then
|
|
local color;
|
|
quality = tonumber(quality);
|
|
if quality == 1 then
|
|
color = "|cffd8b093";
|
|
elseif quality == 2 then
|
|
color = "|cffbbbbbb";
|
|
elseif quality == 3 then
|
|
color = "|cffdeb630";
|
|
elseif quality == 4 then
|
|
color = "|cff50c7a6";
|
|
elseif quality == 5 then
|
|
color = "|cffffa04c";
|
|
else
|
|
color = "|cffffffff";
|
|
end
|
|
|
|
if addTierTextToRight then
|
|
return tempText .." "..color.."T"..quality.."|r", true
|
|
else
|
|
return color.."T"..quality.."|r "..tempText, true
|
|
end
|
|
end
|
|
end
|
|
return text, quality ~= nil
|
|
end
|
|
|
|
local function CompleteColorString(str)
|
|
--Fixes some unclosured color string (no |r at the end)
|
|
--Not robust
|
|
if str then
|
|
if strsub(str, 1, 1) == "|" and strsub(str, -2, -2) ~= "|" then
|
|
str = str .. "|r"
|
|
end
|
|
end
|
|
|
|
return str
|
|
end
|
|
|
|
---- Advanced Tooltip Parser with callback ----
|
|
local TooltipUpdateFrame;
|
|
local IS_ITEM_CACHED = {};
|
|
local ON_TEXT_CHANGED_CALLBACK;
|
|
local PINNED_LINES, LAST_ITEM, LAST_TEXT;
|
|
|
|
local function OnTextChanged(object, text)
|
|
print(object.lineIndex);
|
|
print(text);
|
|
end
|
|
|
|
local function GetPinnedLineText()
|
|
if PINNED_LINES and LAST_ITEM then
|
|
local tooltipData;
|
|
if type(LAST_ITEM) == "number" then
|
|
tooltipData = GetInfoByItemID(LAST_ITEM);
|
|
else
|
|
tooltipData = GetInfoByHyperlink(LAST_ITEM);
|
|
end
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText;
|
|
local output;
|
|
|
|
for i = 1, #PINNED_LINES do
|
|
if PINNED_LINES[i] <= numLines then
|
|
lineText = GetLineText(lines, PINNED_LINES[i]);
|
|
if lineText and lineText ~= "" then
|
|
if output then
|
|
output = output.."\n"..lineText;
|
|
else
|
|
output = lineText;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if output ~= LAST_TEXT then
|
|
LAST_TEXT = output;
|
|
if ON_TEXT_CHANGED_CALLBACK then
|
|
ON_TEXT_CHANGED_CALLBACK(output);
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function TooltipUpdateFrame_OnUpdate(self, elapsed)
|
|
self.t = self.t + elapsed;
|
|
if self.t > 0.25 then
|
|
self.t = 0;
|
|
self.iteration = self.iteration + 1;
|
|
if self.iteration >= 3 then
|
|
self:SetScript("OnUpdate", nil);
|
|
end
|
|
GetPinnedLineText();
|
|
end
|
|
end
|
|
|
|
local function GetCachedItemTooltipTextByLine(item, line, callbackFunc)
|
|
if not TooltipUpdateFrame then
|
|
TooltipUpdateFrame = CreateFrame("Frame");
|
|
end
|
|
|
|
ON_TEXT_CHANGED_CALLBACK = callbackFunc;
|
|
|
|
local isCached;
|
|
if IS_ITEM_CACHED[item] then
|
|
isCached = true
|
|
else
|
|
IS_ITEM_CACHED[item] = true;
|
|
isCached = false
|
|
end
|
|
|
|
local tooltipData;
|
|
if type(item) == "number" then
|
|
tooltipData = GetInfoByItemID(item);
|
|
else
|
|
tooltipData = GetInfoByHyperlink(item);
|
|
end
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText;
|
|
|
|
if item ~= LAST_ITEM then
|
|
LAST_ITEM = item;
|
|
LAST_TEXT = nil;
|
|
TooltipUpdateFrame.t = 0;
|
|
TooltipUpdateFrame.iteration = 0;
|
|
TooltipUpdateFrame:SetScript("OnUpdate", TooltipUpdateFrame_OnUpdate);
|
|
end
|
|
|
|
if isCached then
|
|
if PINNED_LINES then
|
|
PINNED_LINES = nil;
|
|
end
|
|
end
|
|
|
|
|
|
if type(line) == "table" then
|
|
local output;
|
|
local _l;
|
|
for i = 1, #line do
|
|
_l = line[i];
|
|
if _l <= numLines then
|
|
lineText = GetLineText(lines, _l);
|
|
if lineText and lineText ~= "" then
|
|
lineText = CompleteColorString(lineText);
|
|
if output then
|
|
output = output.."\n"..lineText;
|
|
else
|
|
output = lineText;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if not isCached then
|
|
PINNED_LINES = line;
|
|
LAST_TEXT = output;
|
|
end
|
|
|
|
return output, isCached or (output ~= nil);
|
|
else
|
|
if line <= numLines then
|
|
lineText = RemoveColorString( GetLineText(lines, line) );
|
|
end
|
|
|
|
if not isCached then
|
|
PINNED_LINES = {line};
|
|
LAST_TEXT = lineText;
|
|
end
|
|
|
|
return lineText, isCached or (lineText ~= nil);
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetCachedItemTooltipTextByLine = GetCachedItemTooltipTextByLine;
|
|
-------------------------------------------------------------------
|
|
|
|
|
|
|
|
local function GetItemRankText(itemLink, statName)
|
|
--Items that can get upgraded
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local dataText = GetLineText(tooltipData.lines, 2);
|
|
if not dataText then return end;
|
|
|
|
local rank = match(dataText, "%d+", -2) or "";
|
|
if not rank then return end;
|
|
|
|
if statName then
|
|
local stats = GetItemStats(itemLink) or {};
|
|
return "|cff00ccff"..rank.."|r", stats[statName] or 0
|
|
else
|
|
return "|cff00ccff"..rank.."|r"
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetItemRankText = GetItemRankText;
|
|
|
|
|
|
local function GetItemTooltipTextByLine(item, lineIndex, keepColor)
|
|
--It's possible that item description hasn't been cached yet
|
|
--See TooltipParser.lua for more advanced functionalities
|
|
local tooltipData;
|
|
if type(item) == "number" then
|
|
tooltipData = GetInfoByItemID(item);
|
|
else
|
|
tooltipData = GetInfoByHyperlink(item);
|
|
end
|
|
|
|
if tooltipData and tooltipData.lines then
|
|
if keepColor then
|
|
return GetLineText(tooltipData.lines, lineIndex)
|
|
else
|
|
return RemoveColorString( GetLineText(tooltipData.lines, lineIndex) );
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetItemTooltipTextByLine = GetItemTooltipTextByLine;
|
|
|
|
|
|
local ITEM_ENCHANT_FORMAT = gsub(ENCHANTED_TOOLTIP_LINE, "%%s", "(.+)");
|
|
|
|
local function GetItemEnchantText(itemLink, colorized)
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
|
|
if numLines < 5 then return end;
|
|
|
|
local lineText;
|
|
local enchantText;
|
|
local enchantFormat = ITEM_ENCHANT_FORMAT;
|
|
|
|
for i = 5, numLines do
|
|
if lines[i][4] and lines[i][4].field == "enchantID" then
|
|
lineText = GetLineText(lines, i);
|
|
if lineText then
|
|
enchantText = match(lineText, enchantFormat);
|
|
if enchantText then
|
|
enchantText = strtrim(enchantText);
|
|
if enchantText ~= "" then
|
|
if colorized then
|
|
enchantText = "|cff5fbd6b"..enchantText.."|r";
|
|
end
|
|
enchantText = ReformatCraftingQualityText(enchantText);
|
|
return enchantText
|
|
end
|
|
end
|
|
end
|
|
return
|
|
else
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
local function GetEnchantTextByEnchantID(enchantID)
|
|
if enchantID then
|
|
--local itemLink = "item:2092:"..enchantID;
|
|
--return GetItemEnchantText(itemLink, false);
|
|
local tooltipData = GetInfoByHyperlink("item:2092:"..enchantID);
|
|
if not tooltipData then return nil, true end;
|
|
|
|
local enchantText = GetLineText(tooltipData.lines, 8); --DF:Moved to line #8
|
|
if enchantText and enchantText ~= "" then
|
|
--remove "Enchanted:"
|
|
local effect = match(enchantText, ITEM_ENCHANT_FORMAT);
|
|
if not effect then
|
|
effect = enchantText;
|
|
end
|
|
|
|
effect = ReformatCraftingQualityText(effect);
|
|
return effect, true
|
|
else
|
|
return nil, true
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetItemEnchantText = GetItemEnchantText;
|
|
NarciAPI.GetEnchantTextByEnchantID = GetEnchantTextByEnchantID;
|
|
|
|
|
|
local function GetEnchantTextByItemLink(itemLink, colorized, isRight)
|
|
if not itemLink then return end;
|
|
|
|
local enchantID = match(itemLink, "item:%d+:(%d+):");
|
|
|
|
if enchantID and enchantID ~= "" then
|
|
local tooltipData = GetInfoByHyperlink("item:2092:"..enchantID);
|
|
if not tooltipData then return nil, true end;
|
|
|
|
local enchantText = GetLineText(tooltipData.lines, 8);
|
|
if enchantText and enchantText ~= "" then
|
|
--remove "Enchanted:"
|
|
local effect = match(enchantText, ITEM_ENCHANT_FORMAT);
|
|
if not effect then
|
|
effect = enchantText;
|
|
end
|
|
if colorized then
|
|
effect = "|cff5fbd6b"..effect.."|r";
|
|
end
|
|
effect = ReformatCraftingQualityText(effect, isRight);
|
|
return effect, true
|
|
else
|
|
return nil, true
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetEnchantTextByItemLink = GetEnchantTextByItemLink;
|
|
|
|
|
|
local TEMP_ENCHANT_FORMAT = "([^+].+) %((%d+%D+)%)";
|
|
local FORMAT_COLON = ":";
|
|
if TEXT_LOCALE == "zhCN" then
|
|
FORMAT_COLON = ":";
|
|
TEMP_ENCHANT_FORMAT = "([^+].+)((%d+%D+)%)";
|
|
elseif TEXT_LOCALE == "zhTW" then
|
|
FORMAT_COLON = ":";
|
|
TEMP_ENCHANT_FORMAT = "([^+].+)%((%d+%D+)%)";
|
|
end
|
|
|
|
local function GetTemporaryItemBuff(location1, location2)
|
|
if not location1 then return; end
|
|
|
|
local tooltipData;
|
|
if location2 then
|
|
tooltipData = GetInfoByBagItem(location1, location2);
|
|
else
|
|
tooltipData = GetInfoByInventoryItem("player", location1, true);
|
|
end
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText;
|
|
local buffText, durationText;
|
|
for i = 5, numLines do
|
|
lineText = GetLineText(lines, i);
|
|
if lineText then
|
|
if not match(lineText, FORMAT_COLON) then
|
|
buffText, durationText = match(lineText, TEMP_ENCHANT_FORMAT);
|
|
if buffText and durationText then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--durationText: hours, hour, min, sec
|
|
--/dump string.match("Reinforced (15 sec)", ".+ %((%d+) sec%)")
|
|
return buffText, durationText
|
|
end
|
|
|
|
NarciAPI.GetTemporaryItemBuff = GetTemporaryItemBuff;
|
|
|
|
|
|
local function GetWeaponDamageAndSpeed(itemLink)
|
|
if not itemLink then return; end
|
|
local _, _, _, itemEquipLoc, _, classID, subclassID = GetItemInfoInstant(itemLink);
|
|
if classID ~= 2 then
|
|
return
|
|
end
|
|
itemEquipLoc = _G[itemEquipLoc];
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText, leftText, rightText;
|
|
|
|
for i = 3, numLines do
|
|
lineText = GetLineText(lines, i);
|
|
if lineText then
|
|
if lineText == itemEquipLoc then
|
|
local n = i + 1;
|
|
leftText = GetLineText(lines, n);
|
|
rightText = GetLineRightText(lines, n);
|
|
return leftText, rightText
|
|
end
|
|
else
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetWeaponDamageAndSpeed = GetWeaponDamageAndSpeed;
|
|
|
|
|
|
local function GetItemFlavorText(itemLink)
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText, text;
|
|
|
|
for i = numLines, numLines - 1, -1 do
|
|
lineText = GetLineText(lines, i);
|
|
if lineText then
|
|
if match(lineText, "^[\"“]") then
|
|
return text
|
|
end
|
|
else
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetItemFlavorText = GetItemFlavorText;
|
|
|
|
|
|
|
|
local function IsAppearanceKnown(itemLink)
|
|
--Need to correspond with C_TransmogCollection.PlayerHasTransmog
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText;
|
|
|
|
for i = numLines, numLines - 2, -1 do
|
|
lineText = GetLineText(lines, i);
|
|
if not lineText then
|
|
return false;
|
|
end
|
|
if lineText == SOURCE_KNOWN or lineText == APPEARANCE_KNOWN then
|
|
return true;
|
|
elseif lineText == APPEARANCE_UNKNOWN then
|
|
return false;
|
|
end
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
NarciAPI.IsAppearanceKnown = IsAppearanceKnown;
|
|
|
|
|
|
local function GetItemExtraEffect(itemLink, checkBonus, keepFormat)
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local fromLine = max(numLines - 6, 3);
|
|
local output = "";
|
|
local category, lineText;
|
|
|
|
for i = fromLine, numLines, 1 do
|
|
lineText = GetLineText(lines, i);
|
|
if not lineText then
|
|
break;
|
|
end
|
|
|
|
if find(lineText, ON_USE) then
|
|
lineText = FormatString(lineText, NO_COMMA_ON_USE, keepFormat);
|
|
if not category then category = NO_COMMA_ON_USE; end
|
|
output = output..lineText.."\n";
|
|
elseif find(lineText, ON_EQUIP) then
|
|
lineText = FormatString(lineText, NO_COMMA_ON_EQUIP, keepFormat);
|
|
if not category then category = NO_COMMA_ON_EQUIP; end
|
|
output = output..lineText.."\n";
|
|
elseif find(lineText, ON_PROC) then
|
|
lineText = FormatString(lineText, NO_COMMA_ON_PROC, keepFormat);
|
|
if not category then category = NO_COMMA_ON_PROC; end
|
|
output = output..lineText.."\n";
|
|
elseif checkBonus then
|
|
if find(lineText, ITEM_BONUS) then
|
|
lineText = FormatString(lineText, NO_COMMA_SET_BONUS, keepFormat);
|
|
if not category then category = NO_COMMA_SET_BONUS; end
|
|
output = output..lineText.."\n";
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
return category, output;
|
|
end
|
|
|
|
NarciAPI.GetItemExtraEffect = GetItemExtraEffect;
|
|
|
|
|
|
local SpecialGemData = {
|
|
--1 Movement Speed
|
|
--2 Health Regen
|
|
[173125] = 2, --Revitalizing Jewel Doublet
|
|
[173126] = 1, --Straddling Jewel Doublet
|
|
[25893] = 3, --Meta Chance to Increase Spell Cast Speed
|
|
[32410] = 4, --Meta Chance to Increase Melee/Ranged Attack Speed
|
|
};
|
|
|
|
local GEM_BONUS_CACHE = {};
|
|
|
|
local function GetGemBonusFromGem(gem)
|
|
--gem: Gem's itemID or hyperlink
|
|
if not gem then return; end
|
|
|
|
if GEM_BONUS_CACHE[gem] then
|
|
return GEM_BONUS_CACHE[gem][1], GEM_BONUS_CACHE[gem][2]
|
|
end
|
|
|
|
local tooltipData;
|
|
local itemID;
|
|
if type(gem) == "number" then
|
|
tooltipData = GetInfoByItemID(gem);
|
|
itemID = gem;
|
|
else
|
|
tooltipData = GetInfoByHyperlink(gem);
|
|
itemID = GetItemInfoInstant(gem);
|
|
end
|
|
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local bonusText;
|
|
local lineText;
|
|
local requiredItemLevel = 0;
|
|
|
|
local bonusID = SpecialGemData[itemID];
|
|
if bonusID then
|
|
if bonusID == 1 then
|
|
bonusText = STAT_MOVEMENT_SPEED;
|
|
elseif bonusID == 2 then
|
|
bonusText = ITEM_MOD_HEALTH_REGENERATION_SHORT;
|
|
elseif bonusID == 3 then
|
|
bonusText = GetSpellInfo(32837);
|
|
elseif bonusID == 4 then
|
|
bonusText = STAT_ATTACK_SPEED;
|
|
end
|
|
end
|
|
|
|
for i = 2, numLines do
|
|
lineText = GetLineText(lines, i);
|
|
if not lineText then
|
|
return;
|
|
end
|
|
|
|
if not bonusText then
|
|
if strsub(lineText, 1, 1) == "+" then
|
|
bonusText = lineText;
|
|
elseif find(lineText, ON_EQUIP) then
|
|
bonusText = FormatString(lineText, NO_COMMA_ON_EQUIP);
|
|
end
|
|
end
|
|
|
|
if find(lineText, GEM_MIN_LEVEL) then
|
|
requiredItemLevel = FormatString(lineText, GEM_MIN_LEVEL);
|
|
end
|
|
|
|
if requiredItemLevel and bonusText then break end;
|
|
end
|
|
|
|
requiredItemLevel = tonumber(requiredItemLevel);
|
|
|
|
if bonusText then
|
|
bonusText = ReformatCraftingQualityText(bonusText);
|
|
GEM_BONUS_CACHE[gem] = {bonusText, requiredItemLevel};
|
|
end
|
|
|
|
return bonusText, requiredItemLevel;
|
|
end
|
|
|
|
NarciAPI.GetGemBonus = GetGemBonusFromGem;
|
|
|
|
|
|
local function GetItemEquipEffect(itemLink)
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local fromLine = max(numLines - 4, 0);
|
|
local lineText;
|
|
local effects, effectType, effectText, cooldownText;
|
|
local numEffects;
|
|
|
|
for i = fromLine, numLines do
|
|
lineText = GetLineText(lines, i);
|
|
if not lineText then
|
|
break;
|
|
end
|
|
effectType = nil;
|
|
effectText = nil;
|
|
cooldownText = nil;
|
|
if find(lineText, ON_USE) then
|
|
effectText, cooldownText = TrimCooldownText( strtrim(lineText, NO_COMMA_ON_USE) );
|
|
effectType = "use";
|
|
elseif find(lineText, ON_EQUIP) then
|
|
effectText = RemoveColorString(lineText);
|
|
effectType = "equip";
|
|
elseif find(lineText, ON_PROC) then
|
|
effectText = lineText;
|
|
effectType = "proc";
|
|
elseif find(lineText, ITEM_BONUS) then
|
|
effectText = lineText;
|
|
effectType = "set";
|
|
end
|
|
if effectType then
|
|
if not effects then
|
|
effects = {};
|
|
numEffects = 0;
|
|
end
|
|
numEffects = numEffects + 1;
|
|
effects[numEffects] = {effectType, effectText, cooldownText};
|
|
end
|
|
end
|
|
return effects, numEffects;
|
|
end
|
|
|
|
NarciAPI.GetItemEquipEffect = GetItemEquipEffect;
|
|
|
|
|
|
local function GetItemUpgradeLevel(itemLink)
|
|
if not itemLink then return; end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText;
|
|
local currentLevel, maxLevel;
|
|
for i = 2, 3 do
|
|
lineText = GetLineText(lines, i);
|
|
if lineText then
|
|
currentLevel, maxLevel = match(lineText, PATTERN_UPGRADE_LEVEL);
|
|
if maxLevel then
|
|
return currentLevel, maxLevel
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetItemUpgradeLevel = GetItemUpgradeLevel;
|
|
|
|
|
|
local function GetCompleteItemData(tooltipData, itemLink)
|
|
--return a table of data obtained by scanning tooltip
|
|
--upgrade level (current/max), equipmentEffects(onEquip, onUse, onProc, bonus), socket info(socket1, socket2, socket3), enchant
|
|
--reset socket textures
|
|
if not (tooltipData and itemLink) then return end;
|
|
|
|
itemLink = FormatItemLink(itemLink);
|
|
|
|
local _, _, _, itemEquipLoc, _, classID, subclassID = GetItemInfoInstant(itemLink);
|
|
local matchWeapon;
|
|
if classID == 2 then
|
|
--Find Weapon damage and attack speed by matching the texts below equip location
|
|
itemEquipLoc = _G[itemEquipLoc];
|
|
matchWeapon = true;
|
|
end
|
|
|
|
local processed = {}; --process each line once
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local lineText;
|
|
local match1, match2;
|
|
local enchantText;
|
|
local effectText, effectType, numEffects, isActive, cooldownText;
|
|
local data, anyMatch;
|
|
local socketOrderID = 0;
|
|
local qualityFound;
|
|
local requestSubData;
|
|
|
|
for i = 2, numLines do
|
|
if not processed[i] then
|
|
lineText = GetLineText(lines, i);
|
|
if lineText then
|
|
anyMatch = nil;
|
|
if i == 2 then
|
|
--the second line is usually item level
|
|
--or a special item category: difficuty, Cypher Equipment
|
|
if not match(lineText, "%d$") then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.context = ReplacePureGreenText(lineText);
|
|
anyMatch = true;
|
|
end
|
|
else
|
|
if i < 5 and not match2 then
|
|
--upgrade level
|
|
match1 = match(lineText, PATTERN_UPGRADE_STRING);
|
|
if match1 then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.upgradeString = strtrim(match1);
|
|
anyMatch = true;
|
|
|
|
local trackName = match(lineText, PATTERN_UPGRADE_TRACK_NAME);
|
|
if trackName and ITEM_UPGRADE_TRACK_LEVELS[trackName] then
|
|
data.fullyUpgradedItemLevel = ITEM_UPGRADE_TRACK_LEVELS[trackName];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if i >= 4 and not anyMatch then
|
|
--effects
|
|
if find(lineText, ON_USE) then
|
|
effectText, cooldownText = TrimCooldownText( strtrim(lineText, NO_COMMA_ON_USE) );
|
|
effectType = "use";
|
|
elseif find(lineText, ON_EQUIP) then
|
|
effectText = RemoveColorString(lineText);
|
|
effectType = "equip";
|
|
elseif find(lineText, ON_PROC) then
|
|
effectText = lineText;
|
|
effectType = "proc";
|
|
elseif find(lineText, ITEM_BONUS) or find(lineText, SOCKET_BONUS) then
|
|
effectText = lineText;
|
|
effectType = "set";
|
|
elseif matchWeapon then
|
|
if lineText == itemEquipLoc then
|
|
matchWeapon = nil;
|
|
local leftText;
|
|
local rightText = GetLineRightText(lines, i);
|
|
if rightText then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.itemType = rightText;
|
|
end
|
|
local n = i + 1;
|
|
|
|
leftText = GetLineText(lines, n);
|
|
rightText = GetLineRightText(lines, n);
|
|
if leftText and rightText then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.weaponInfo = {leftText, rightText};
|
|
anyMatch = true;
|
|
end
|
|
end
|
|
else
|
|
--enchant
|
|
if not enchantText then
|
|
enchantText = match(lineText, ITEM_ENCHANT_FORMAT);
|
|
if enchantText then
|
|
enchantText = strtrim(enchantText);
|
|
if enchantText ~= "" then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
enchantText = ReformatCraftingQualityText(enchantText, true);
|
|
data.enchant = enchantText;
|
|
anyMatch = true;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if effectType then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
if not data.effects then
|
|
data.effects = {};
|
|
numEffects = 0;
|
|
end
|
|
|
|
local color = lines[i].leftColor; --IsTextColorRed(lines[i].args[3].colorVal
|
|
isActive = not (IsTextColorRed(color) or IsTextColor50Grey(color));
|
|
numEffects = numEffects + 1;
|
|
data.effects[numEffects] = {effectType, effectText, isActive, cooldownText};
|
|
effectType = nil;
|
|
effectText = nil;
|
|
cooldownText = nil;
|
|
isActive = nil;
|
|
anyMatch = true;
|
|
end
|
|
|
|
if not anyMatch then
|
|
--socket
|
|
if lines[i].type and (lines[i].type == LINE_TYPE_SOCKET) then --type:GemSocket/
|
|
if not data then
|
|
data = {};
|
|
end
|
|
if not data.socketInfo then
|
|
data.socketInfo = {};
|
|
end
|
|
local socketType = lines[i].stringVal;
|
|
local icon, gemName, gemLink, gemEffect;
|
|
if lines[i].gemIcon then
|
|
icon = lines[i].gemIcon;
|
|
end
|
|
socketOrderID = socketOrderID + 1;
|
|
gemName, gemLink = GetItemGem(itemLink, socketOrderID);
|
|
if gemLink then --has a gem
|
|
if not icon then
|
|
icon = select(5, GetItemInfoInstant(gemLink));
|
|
end
|
|
|
|
local isCraftedItem;
|
|
|
|
gemEffect = lines[i].leftText;
|
|
gemEffect = RemoveColorString(gemEffect);
|
|
gemEffect, isCraftedItem = ReformatCraftingQualityText(gemEffect, true);
|
|
|
|
if not isCraftedItem then
|
|
local bonusTextFromItem = GetGemBonusFromGem(gemLink);
|
|
if bonusTextFromItem and gemEffect then
|
|
if bonusTextFromItem ~= gemEffect then
|
|
gemEffect = CompleteColorString(gemEffect)
|
|
gemEffect = gemEffect.."\n"..bonusTextFromItem;
|
|
end
|
|
end
|
|
end
|
|
|
|
if not requestSubData then
|
|
if (not gemName or gemName == "") or (not gemEffect and gemEffect == "") then
|
|
requestSubData = true;
|
|
end
|
|
end
|
|
else
|
|
local textureKit = SOCKET_TYPE_TEXTURE[socketType] or "Prismatic";
|
|
icon = "Interface\\ItemSocketingFrame\\UI-EmptySocket-"..textureKit;
|
|
gemName = lines[i].leftText; --Empty X Socket
|
|
gemEffect = gemName;
|
|
end
|
|
data.socketInfo[socketOrderID] = {icon, gemName, gemLink, gemEffect};
|
|
end
|
|
end
|
|
end
|
|
if i >= numLines - 2 and not anyMatch then
|
|
--flavor texts, class restrictions
|
|
match1 = match(lineText, PATTERN_CLASS_REQUIREMENT);
|
|
if match1 then
|
|
isActive = IsTextColorWhite(lines[i].leftColor);
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.classesAllowed = {match1, isActive};
|
|
anyMatch = true;
|
|
elseif match(lineText, "^[\"“]") then
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.flavorText = lineText;
|
|
anyMatch = true;
|
|
end
|
|
end
|
|
--print(i.." "..tostring(anyMatch).." "..lineText)
|
|
if i > 8 and not anyMatch then
|
|
if not qualityFound then
|
|
match1 = match(lineText, PATTERN_PROFESSION_QUALITY);
|
|
if match1 then
|
|
PP = match1
|
|
qualityFound = true;
|
|
anyMatch = true;
|
|
if not data then
|
|
data = {};
|
|
end
|
|
data.craftingQuality = GetCraftingQualityFromText(match1);
|
|
end
|
|
end
|
|
|
|
--match item sets
|
|
if not anyMatch then
|
|
match1, match2, _ = match(lineText, PATTERN_ITEM_SET_NAME); --string.match("Test Set (1/9)", PATTERN_ITEM_SET_NAME)
|
|
if match1 and match2 and _ then
|
|
--found setName, numOwned, total
|
|
if not data then
|
|
data = {};
|
|
end
|
|
if not data.itemSet then
|
|
data.itemSet = {};
|
|
data.itemSet.itemNames = {};
|
|
data.itemSet.bonuses = {};
|
|
end
|
|
anyMatch = true;
|
|
local total = tonumber(_);
|
|
data.itemSet.rawName = lineText;
|
|
data.itemSet.name = match1;
|
|
data.itemSet.numOwned = tonumber(match2);
|
|
data.itemSet.total = total;
|
|
|
|
for j = 1 + i, total + i do
|
|
lineText = GetLineText(lines, j);
|
|
if lineText then
|
|
isActive = not IsTextColor50Grey(lines[j].leftColor);
|
|
--print(fontString:GetTextColor());
|
|
tinsert(data.itemSet.itemNames, {lineText, isActive});
|
|
processed[j] = true;
|
|
else
|
|
break
|
|
end
|
|
end
|
|
for j = i + total + 2, numLines do
|
|
lineText = GetLineText(lines, j);
|
|
if lineText then
|
|
if find(lineText, SET_BONUS, 1) then
|
|
--found set bonus
|
|
isActive = not IsTextColor50Grey(lines[j].leftColor);
|
|
tinsert(data.itemSet.bonuses, {lineText, isActive});
|
|
processed[j] = true;
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
return data, requestSubData
|
|
end
|
|
|
|
local function ClearTooltipTexture()
|
|
local tex;
|
|
for i = 1, 3 do
|
|
tex = _G["NarciVirtualTooltipTexture"..i];
|
|
if tex then
|
|
tex = tex:SetTexture(nil);
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
local function GetCompleteItemDataFromSlot(slotID, itemLink)
|
|
local tooltipData = GetInfoByInventoryItem("player", slotID, true);
|
|
if not itemLink then
|
|
itemLink = GetInventoryItemLink("player", slotID);
|
|
end
|
|
return GetCompleteItemData(tooltipData, itemLink);
|
|
end
|
|
|
|
local function GetCompleteItemDataByItemLink(itemLink)
|
|
if not itemLink then return end
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
return GetCompleteItemData(tooltipData, itemLink);
|
|
end
|
|
|
|
local function GetCompleteItemDataFromGameTooltip()
|
|
--for debug
|
|
return
|
|
end
|
|
|
|
NarciAPI.GetCompleteItemDataFromSlot = GetCompleteItemDataFromSlot;
|
|
NarciAPI.GetCompleteItemDataByItemLink = GetCompleteItemDataByItemLink;
|
|
NarciAPI.GetCompleteItemDataFromGameTooltip = GetCompleteItemDataFromGameTooltip;
|
|
|
|
|
|
--[[
|
|
EMPTY_SOCKET_BLUE = "Blue Socket"; 136256
|
|
EMPTY_SOCKET_COGWHEEL = "Cogwheel Socket"; 407324
|
|
EMPTY_SOCKET_CYPHER = "Crystallic Socket"; ???
|
|
EMPTY_SOCKET_DOMINATION = "Domination Socket"; 4095404
|
|
EMPTY_SOCKET_HYDRAULIC = "Sha-Touched"; 407325
|
|
EMPTY_SOCKET_META = "Meta Socket"; 136257
|
|
EMPTY_SOCKET_NO_COLOR = "Prismatic Socket"; 458977
|
|
EMPTY_SOCKET_PRISMATIC = "Prismatic Socket"; 458977
|
|
EMPTY_SOCKET_PUNCHCARDBLUE = "Blue Punchcard Socket"; 2958629
|
|
EMPTY_SOCKET_PUNCHCARDRED = "Red Punchcard Socket"; 2958630
|
|
EMPTY_SOCKET_PUNCHCARDYELLOW = "Yellow Punchcard Socket"; 2958631
|
|
EMPTY_SOCKET_RED = "Red Socket"; 136258
|
|
EMPTY_SOCKET_YELLOW = "Yellow Socket"; 136259
|
|
EMPTY_SOCKET_CYPHER = "Crystallic Socket"
|
|
|
|
RELIC_TOOLTIP_TYPE
|
|
--]]
|
|
|
|
--[[
|
|
local SocketTypes = {
|
|
--tooltip emtpy socket texture fileID
|
|
[136256] = "BLUE",
|
|
[136258] = "RED",
|
|
[136259] = "YELLOW",
|
|
[407324] = "COGWHEEL",
|
|
[4095404] = "DOMINATION",
|
|
[407325] = "HYDRAULIC",
|
|
[136257] = "CYPHER", --was META
|
|
[458977] = "PRISMATIC",
|
|
[2958629] = "PUNCHCARDBLUE",
|
|
[2958630] = "PUNCHCARDRED",
|
|
[2958631] = "PUNCHCARDYELLOW",
|
|
};
|
|
--]]
|
|
|
|
local IsSupportedSocket = {};
|
|
|
|
do
|
|
local postfixes = {
|
|
"BLUE", "COGWHEEL", "HYDRAULIC", "META", "PRISMATIC", "PUNCHCARDBLUE", "PUNCHCARDRED", "PUNCHCARDYELLOW",
|
|
"RED", "TINKER", "YELLOW", "PRIMORDIAL",
|
|
};
|
|
|
|
for _, name in pairs(postfixes) do
|
|
IsSupportedSocket[name] = true;
|
|
end
|
|
end
|
|
|
|
|
|
local function IsItemSocketable(itemLink, socketID)
|
|
if not itemLink then return; end
|
|
|
|
local gemName, gemLink = GetItemGem(itemLink, socketID or 1)
|
|
if gemLink then
|
|
if not IsArtifactRelic(gemLink) then
|
|
return gemName or "...", gemLink;
|
|
end
|
|
return
|
|
end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
|
|
for i = 4, numLines do --max 10
|
|
if lines[i] and lines[i].type and lines[i].type == LINE_TYPE_SOCKET then
|
|
return lines[i].leftText, nil
|
|
end
|
|
end
|
|
|
|
return nil, nil;
|
|
end
|
|
NarciAPI.IsItemSocketable = IsItemSocketable;
|
|
|
|
|
|
|
|
--[[
|
|
--Interface / SharedXML / Tooltip / TooltipDataRules.lua
|
|
|
|
function TooltipDataRules.GemSocket(tooltip, lineData)
|
|
local asset;
|
|
local gemIcon = lineData.gemIcon;
|
|
if gemIcon then
|
|
asset = gemIcon;
|
|
else
|
|
local socketType = lineData.socketType;
|
|
if socketType then
|
|
asset = string.format("Interface\\ItemSocketingFrame\\UI-EmptySocket-%s", socketType);
|
|
end
|
|
end
|
|
if asset then
|
|
tooltip:AddTexture(asset);
|
|
end
|
|
end
|
|
--]]
|
|
|
|
local function GetItemSocketInfo(itemLink)
|
|
--gemData = { {socketType, icon, gemLink(nillable) } }
|
|
|
|
if not itemLink then return end
|
|
|
|
local tooltipData = GetInfoByHyperlink(itemLink);
|
|
if not tooltipData then return end;
|
|
|
|
local icon;
|
|
local gemName, gemLink, socketType, socketName;
|
|
local socektInfo;
|
|
local gemOrderID = 0;
|
|
|
|
for i = 1, 3 do
|
|
gemName, gemLink = GetItemGem(itemLink, i);
|
|
if gemLink then
|
|
if not socektInfo then
|
|
socektInfo = {};
|
|
end
|
|
gemOrderID = i;
|
|
icon = select(5, GetItemInfoInstant(gemLink));
|
|
socektInfo[gemOrderID] = {gemName, icon, gemLink};
|
|
end
|
|
end
|
|
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local field;
|
|
|
|
gemOrderID = 0;
|
|
|
|
for i = 4, numLines do --max 10
|
|
if lines[i] and lines[i].type and lines[i].type == LINE_TYPE_SOCKET then
|
|
gemOrderID = gemOrderID + 1;
|
|
if not socektInfo then
|
|
socektInfo = {};
|
|
end
|
|
socketType = lines[i].socketType;
|
|
if not socektInfo[gemOrderID] then
|
|
socketName = lines[i].leftText;
|
|
socektInfo[gemOrderID] = {socketName, "Interface\\ItemSocketingFrame\\UI-EmptySocket-"..socketType, nil, socketType};
|
|
else
|
|
socektInfo[gemOrderID][4] = socketType;
|
|
end
|
|
end
|
|
end
|
|
|
|
return socektInfo
|
|
end
|
|
|
|
NarciAPI.GetItemSocketInfo = GetItemSocketInfo;
|
|
|
|
|
|
local function DoesItemHaveSockets(itemLink)
|
|
--determine if item really have sockets instead of relics
|
|
--can't determine socket order so:
|
|
--If the item have two or more types of socket, use ItemSocketingFrame-GetSocketTypes to get socket order
|
|
|
|
if not itemLink then return end
|
|
|
|
local stats = GetItemStats(itemLink);
|
|
|
|
if stats then
|
|
local numSocket = 0;
|
|
local subType, lastType;
|
|
local socketIsDiverse;
|
|
|
|
for name, count in pairs(stats) do
|
|
subType = match(name, "^EMPTY_SOCKET_(%a+)");
|
|
if IsSupportedSocket[subType] then
|
|
numSocket = numSocket + count;
|
|
if lastType then
|
|
socketIsDiverse = socketIsDiverse or (subType ~= lastType);
|
|
else
|
|
lastType = subType;
|
|
end
|
|
end
|
|
end
|
|
|
|
if numSocket > 0 then
|
|
return numSocket, socketIsDiverse, lastType
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.DoesItemHaveSockets = DoesItemHaveSockets;
|
|
|
|
--[[
|
|
GameTooltip:HookScript("OnTooltipSetItem", function(self)
|
|
local _, itemLink = self:GetItem();
|
|
DoesItemHaveSockets(itemLink);
|
|
end);
|
|
--]]
|
|
|
|
local function GetAmmoDps(itemID)
|
|
if not itemID then return end;
|
|
return 0
|
|
end
|
|
|
|
NarciAPI.GetAmmoDps = GetAmmoDps;
|
|
|
|
|
|
|
|
local function FormatSpellData(tooltipData, fromLine)
|
|
local lines = tooltipData.lines;
|
|
local numLines = #lines;
|
|
local leftText, rightText;
|
|
local anyMatch;
|
|
local data = {};
|
|
local rangeText, castText, cdText, costText, replaceSpell;
|
|
local isPassive;
|
|
fromLine = fromLine or 1;
|
|
local first2Lines = fromLine + 1;
|
|
|
|
--castText: instant, x sec cast, channel
|
|
--cdText: cooldown or recharge time
|
|
for i = fromLine, numLines do
|
|
anyMatch = false;
|
|
leftText = GetLineText(lines, i);
|
|
rightText = GetLineRightText(lines, i);
|
|
|
|
if i <= first2Lines then
|
|
if leftText then
|
|
if not rangeText then
|
|
if find(leftText, TEXT_SPELL_RANGE) or find(leftText, TEXT_SPELL_RANGE_MELEE) or find(leftText, TEXT_SPELL_RANGE_UNLIMITED) then
|
|
anyMatch = true;
|
|
rangeText = leftText;
|
|
data.rangeText = rangeText;
|
|
end
|
|
end
|
|
|
|
if not anyMatch and not castText then
|
|
if find(leftText, TEXT_SPELL_PASSIVE) then
|
|
isPassive = true;
|
|
anyMatch = true;
|
|
castText = leftText;
|
|
data.castText = castText;
|
|
elseif find(leftText, TEXT_SPELL_CAST_TIME_INSTANT) or find(leftText, TEXT_SPELL_CAST_TIME_SEC) or find(leftText, TEXT_SPELL_CAST_CHANNELED) then
|
|
anyMatch = true;
|
|
castText = leftText;
|
|
data.castText = castText;
|
|
end
|
|
end
|
|
|
|
if not anyMatch and not isPassive and not cdText then
|
|
if find(leftText, TEXT_SPELL_COOLDOWN) or find(leftText, TEXT_SPELL_RECHARGE) then
|
|
anyMatch = true;
|
|
cdText = leftText;
|
|
data.cdText = cdText;
|
|
end
|
|
end
|
|
|
|
if not anyMatch and find(leftText, "%d") then
|
|
anyMatch = true;
|
|
costText = gsub(leftText, "\n", " "); --!Druid: Energy + ComboPoint
|
|
data.costText = costText;
|
|
end
|
|
|
|
if not anyMatch and find(leftText, TEXT_REPLACES_SPELL) then
|
|
anyMatch = true;
|
|
replaceSpell = leftText;
|
|
data.replaceSpell = replaceSpell;
|
|
end
|
|
end
|
|
|
|
if rightText and not anyMatch then
|
|
if not rangeText then
|
|
if find(rightText, TEXT_SPELL_RANGE) or find(rightText, TEXT_SPELL_RANGE_MELEE) or find(rightText, TEXT_SPELL_RANGE_UNLIMITED) then
|
|
anyMatch = true;
|
|
rangeText = rightText;
|
|
data.rangeText = rangeText;
|
|
end
|
|
end
|
|
|
|
if not anyMatch and not castText then
|
|
if find(rightText, TEXT_SPELL_PASSIVE) then
|
|
isPassive = true;
|
|
anyMatch = true;
|
|
castText = rightText;
|
|
data.castText = castText;
|
|
elseif find(rightText, TEXT_SPELL_CAST_TIME_INSTANT) or find(rightText, TEXT_SPELL_CAST_TIME_SEC) or find(rightText, TEXT_SPELL_CAST_CHANNELED) then
|
|
anyMatch = true;
|
|
castText = rightText;
|
|
data.castText = castText;
|
|
end
|
|
end
|
|
|
|
if not anyMatch and not isPassive and not cdText then
|
|
if find(rightText, TEXT_SPELL_COOLDOWN) or find(rightText, TEXT_SPELL_RECHARGE) then
|
|
anyMatch = true;
|
|
cdText = rightText;
|
|
data.cdText = cdText;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if not anyMatch then
|
|
if leftText then
|
|
leftText = strtrim(leftText);
|
|
if leftText ~= "" then
|
|
if not data.descriptions then
|
|
data.descriptions = {};
|
|
end
|
|
tinsert(data.descriptions, leftText);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return data
|
|
end
|
|
|
|
local function GetTraitEntryTooltip(entryID, rank)
|
|
if not (entryID and rank) then return end;
|
|
|
|
local tooltipData = C_TooltipInfo.GetTraitEntry(entryID, rank);
|
|
if not tooltipData then return end;
|
|
|
|
return FormatSpellData(tooltipData)
|
|
end
|
|
|
|
NarciAPI.GetTraitEntryTooltip = GetTraitEntryTooltip;
|
|
|
|
|
|
local function GetPvpTalentTooltip(talentID, isInspecting, specGroupIndex, slotIndex)
|
|
if not (talentID and specGroupIndex and slotIndex) then return end;
|
|
|
|
local tooltipData = C_TooltipInfo.GetPvpTalent(talentID, isInspecting, specGroupIndex, slotIndex);
|
|
if not tooltipData then return end;
|
|
|
|
return FormatSpellData(tooltipData, 2)
|
|
end
|
|
|
|
NarciAPI.GetPvpTalentTooltip = GetPvpTalentTooltip;
|
|
|
|
|
|
local function GetBagItemSubText(bag, slot)
|
|
if not (bag and slot) then return end;
|
|
|
|
local tooltipData = GetInfoByBagItem(bag, slot);
|
|
if tooltipData then
|
|
return GetLineText(tooltipData.lines, 2) or ""
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetBagItemSubText = GetBagItemSubText;
|
|
|
|
|
|
local function GetCreatureName(creatureID)
|
|
if not creatureID then return end;
|
|
local tooltipData = GetInfoByHyperlink("unit:Creature-0-0-0-0-"..creatureID);
|
|
if tooltipData then
|
|
return GetLineText(tooltipData.lines, 1);
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetCreatureName = GetCreatureName;
|
|
|
|
local function GetDominationShardEffect(item)
|
|
if not item then return end;
|
|
|
|
local tooltipData;
|
|
if type(item) == "number" then
|
|
tooltipData = GetInfoByItemID(item);
|
|
else
|
|
tooltipData = GetInfoByHyperlink(item);
|
|
end
|
|
|
|
if tooltipData then
|
|
return GetLineText(tooltipData.lines, 5);
|
|
end
|
|
end
|
|
|
|
NarciAPI.GetDominationShardEffect = GetDominationShardEffect;
|
|
|
|
--[[
|
|
local function SurfaceItemArgs(item)
|
|
if not item then return end;
|
|
|
|
local tooltipData;
|
|
if type(item) == "number" then
|
|
tooltipData = GetInfoByItemID(item);
|
|
else
|
|
tooltipData = GetInfoByHyperlink(item);
|
|
end
|
|
|
|
if not tooltipData then return end;
|
|
|
|
local surfaceArgs = {};
|
|
|
|
for i, lineData in ipairs(tooltipData.lines) do
|
|
surfaceArgs[i] = {};
|
|
for j, arg in ipairs(lineData.args) do
|
|
surfaceArgs[i][arg.field] = arg.stringVal or arg.intVal or arg.floatVal or arg.boolVal or arg.colorVal or arg.guidVal;
|
|
end
|
|
end
|
|
|
|
return surfaceArgs
|
|
end
|
|
--]]
|
|
|
|
local ITEM_REQUIREMENT_INCLUDE_LINES = {
|
|
[21] = true, --Enum.TooltipDataLineType.RestrictedRaceClass
|
|
[22] = true, --Enum.TooltipDataLineType.RestrictedFaction
|
|
[23] = true, --Enum.TooltipDataLineType.RestrictedSkill
|
|
[24] = true, --Enum.TooltipDataLineType.RestrictedPvPMedal
|
|
[25] = true, --Enum.TooltipDataLineType.RestrictedReputation
|
|
--[26] = true, --Enum.TooltipDataLineType.RestrictedSpellKnown Already Known
|
|
[27] = true, --Enum.TooltipDataLineType.RestrictedLevel
|
|
[28] = true, --Enum.TooltipDataLineType.EquipSlot
|
|
};
|
|
|
|
|
|
local function GetItemRequirement(item)
|
|
if not item then return end;
|
|
|
|
local tooltipData;
|
|
|
|
if type(item) == "number" then
|
|
tooltipData = GetInfoByItemID(item);
|
|
else
|
|
tooltipData = GetInfoByHyperlink(item);
|
|
end
|
|
|
|
if not (tooltipData and tooltipData.lines) then return end;
|
|
|
|
--local surfaceArgs = SurfaceItemArgs(item);
|
|
|
|
local data = {};
|
|
local index = 0;
|
|
local leftText, rightText;
|
|
local lineTypeEquipSlot = 28; --Enum.TooltipDataLineType.EquipSlot
|
|
|
|
for i, arg in ipairs(tooltipData.lines) do
|
|
if ITEM_REQUIREMENT_INCLUDE_LINES[arg.type] then
|
|
leftText = arg.leftText;
|
|
if leftText then
|
|
--print(arg.type, leftText)
|
|
rightText = arg.rightText;
|
|
if arg.type == lineTypeEquipSlot and ( not (arg.isValidInvSlot and arg.isValidItemType) ) and rightText then
|
|
leftText = "|cffff2121"..leftText.."|r";
|
|
rightText = "|cffff2121"..rightText.."|r";
|
|
else
|
|
if arg.leftColor then
|
|
leftText = arg.leftColor:WrapTextInColorCode(leftText);
|
|
end
|
|
|
|
if rightText and arg.rightColor then
|
|
rightText = arg.leftColor:WrapTextInColorCode(rightText);
|
|
end
|
|
end
|
|
|
|
if rightText then
|
|
leftText = leftText .. " " .. rightText;
|
|
end
|
|
|
|
index = index + 1;
|
|
data[index] = leftText;
|
|
end
|
|
end
|
|
end
|
|
|
|
return data
|
|
end
|
|
|
|
NarciAPI.GetItemRequirement = GetItemRequirement;
|
|
|
|
|
|
|
|
local PrimordialStoneNames = {};
|
|
|
|
local function GetColorizedPrimordialStoneName(itemID)
|
|
--From PTR: color format |C0040C040Storm Infused Stone --|C00? No closure |r?
|
|
if PrimordialStoneNames[itemID] then
|
|
return PrimordialStoneNames[itemID]
|
|
end
|
|
|
|
local name = GetItemTooltipTextByLine(itemID, 6, true);
|
|
|
|
if name and name ~= "" then
|
|
PrimordialStoneNames[itemID] = name;
|
|
else
|
|
name = GetItemInfo(itemID);
|
|
end
|
|
|
|
return name
|
|
end
|
|
|
|
NarciAPI.GetColorizedPrimordialStoneName = GetColorizedPrimordialStoneName;
|
|
|
|
--[[
|
|
function Professions.GetIconForQuality(quality, small)
|
|
if small then
|
|
return ("Professions-Icon-Quality-Tier%d-Small"):format(quality);
|
|
end
|
|
return ("Professions-Icon-Quality-Tier%d"):format(quality);
|
|
end
|
|
|
|
function TestSetProfessionQuality(quality, small)
|
|
if not TT then
|
|
local f = CreateFrame("Frame");
|
|
TT = f:CreateTexture();
|
|
TT:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
|
|
end
|
|
|
|
local atlas;
|
|
if small then
|
|
atlas = ("Professions-Icon-Quality-Tier%d-Small"):format(quality);
|
|
else
|
|
atlas = ("Professions-Icon-Quality-Tier%d"):format(quality);
|
|
end
|
|
|
|
TT:SetAtlas(atlas, true);
|
|
|
|
C_TooltipInfo.GetHyperlink("item:202557::::::::70:261::4:1:3524:1:28:2648")
|
|
end
|
|
--]]
|
|
|
|
local function GetAvailableItemUpgradeTracks()
|
|
local bonusInfo = {
|
|
--{bonusID, maxItemLevel}
|
|
{9294, 398}, --Explorer
|
|
{9302, 411}, --Adventurer
|
|
{9313, 424}, --Veteran 1/8 --LFG
|
|
{9321, 437}, --Champion 1/8 --Normal
|
|
{9330, 441}, --Hero 1/5 --Heroic
|
|
{9380, 447}, --Myth 1/3 --Mythic added in 10.1.5
|
|
};
|
|
|
|
local tooltipData;
|
|
local trackName;
|
|
local upgradeText;
|
|
|
|
for _, info in ipairs(bonusInfo) do
|
|
tooltipData = C_TooltipInfo.GetHyperlink("item:2092::::::::::::1:"..info[1]);
|
|
if tooltipData and tooltipData.lines then
|
|
upgradeText = GetLineText(tooltipData.lines, 3);
|
|
if upgradeText and upgradeText ~= "" then
|
|
trackName = match(upgradeText, PATTERN_UPGRADE_TRACK_NAME);
|
|
if trackName then
|
|
ITEM_UPGRADE_TRACK_LEVELS[trackName] = info[2];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
GetAvailableItemUpgradeTracks();
|
|
C_Timer.After(8, GetAvailableItemUpgradeTracks);
|
|
|
|
|
|
local function Debug_PrintItemBonus(fromID)
|
|
local tooltipData, context;
|
|
local defaultText = _G.ITEM_BIND_ON_EQUIP or "Binds when equipped";
|
|
|
|
for bonusID = fromID, fromID + 500 do
|
|
tooltipData = C_TooltipInfo.GetHyperlink("item:2092::::::::::::1:"..bonusID);
|
|
if tooltipData and tooltipData.lines then
|
|
context = GetLineText(tooltipData.lines, 3);
|
|
if context and context ~= "" and context ~= defaultText then
|
|
print(bonusID, context);
|
|
end
|
|
else
|
|
print("Throttled");
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
NarciAPI.DebugPrintItemBonus = Debug_PrintItemBonus;
|
|
|
|
|
|
local function GetToyEffect(item)
|
|
local itemID;
|
|
if type(item) == "number" then
|
|
itemID = item;
|
|
else
|
|
itemID = GetItemInfoInstant(item);
|
|
end
|
|
|
|
local tooltipData = C_TooltipInfo.GetToyByItemID(itemID);
|
|
if not (tooltipData and tooltipData.lines) then return end;
|
|
|
|
local toyEffect, toyDescription;
|
|
|
|
for i, lineData in ipairs(tooltipData.lines) do
|
|
if lineData.leftText then
|
|
if lineData.type == LINE_TYPE_TOY_EFFECT then
|
|
toyEffect = StripHyperlinks(lineData.leftText);
|
|
toyEffect = lineData.leftColor:WrapTextInColorCode(toyEffect);
|
|
elseif lineData.type == LINE_TYPE_TOY_DESC then
|
|
toyDescription = StripHyperlinks(lineData.leftText);
|
|
toyDescription = lineData.leftColor:WrapTextInColorCode(toyDescription);
|
|
end
|
|
|
|
if toyEffect and toyDescription then break end;
|
|
end
|
|
end
|
|
|
|
return toyEffect, toyDescription
|
|
end
|
|
|
|
NarciAPI.GetToyEffect = GetToyEffect;
|