From 4cf2cc74dae4914934c90b0cf0f144380b30a87f Mon Sep 17 00:00:00 2001 From: Anonomit Date: Sun, 29 Sep 2024 23:46:55 -0400 Subject: [PATCH] Refactor debug --- Config/OptionsTables.lua | 124 +++++++++++++------------ Init/Init.lua | 179 +++++++++++++++++++++++++++++------- Locale/_LocaleAutomatic.lua | 29 ++++-- Operations/RewordLine.lua | 2 +- Stats/Stats.lua | 82 ++++++++++------- 5 files changed, 284 insertions(+), 132 deletions(-) diff --git a/Config/OptionsTables.lua b/Config/OptionsTables.lua index 9a0b3fb..c2ca772 100644 --- a/Config/OptionsTables.lua +++ b/Config/OptionsTables.lua @@ -66,10 +66,16 @@ end) local function GetFormattedStatText(number, stat) local StatInfo = Addon.statsInfo[stat] local hidden = Addon:GetOption("hide", stat) - local text = StatInfo:GetDefaultForm(number) + local defaultForm = StatInfo:GetDefaultForm(number) + Addon:Assertf(defaultForm, "Failed GetDefaultForm with stat %s. number: %s", stat, tostring(number)) + local text if Addon:GetOption("allow", "reword") and Addon:GetOption("doReword", stat) then - text = StatInfo:ConvertToNormalForm(text) - text = strGsub(StatInfo:Reword(text, text), "%+(%-)", "%1") + local normalForm = StatInfo:ConvertToNormalForm(defaultForm) + Addon:Assertf(normalForm, "Failed ConvertToNormalForm with stat %s. defaultForm: %s", stat, defaultForm) + text = strGsub(StatInfo:Reword(normalForm, normalForm), "%+(%-)", "%1") + Addon:Assertf(text, "Failed Reword with stat %s. normalForm: %s", stat, normalForm) + else + text = defaultForm end local color = StatInfo.tooltipColor if hidden then @@ -2125,6 +2131,29 @@ end + +-- ██████╗ ██████╗ ██████╗ ███████╗██╗██╗ ███████╗ ██████╗ ██████╗ ████████╗██╗ ██████╗ ███╗ ██╗███████╗ +-- ██╔══██╗██╔══██╗██╔═══██╗██╔════╝██║██║ ██╔════╝ ██╔═══██╗██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝ +-- ██████╔╝██████╔╝██║ ██║█████╗ ██║██║ █████╗ ██║ ██║██████╔╝ ██║ ██║██║ ██║██╔██╗ ██║███████╗ +-- ██╔═══╝ ██╔══██╗██║ ██║██╔══╝ ██║██║ ██╔══╝ ██║ ██║██╔═══╝ ██║ ██║██║ ██║██║╚██╗██║╚════██║ +-- ██║ ██║ ██║╚██████╔╝██║ ██║███████╗███████╗ ╚██████╔╝██║ ██║ ██║╚██████╔╝██║ ╚████║███████║ +-- ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ + +local function MakeProfileOptions(opts, categoryName) + local self = Addon + local GUI = self.GUI + + local profileOptions = self.AceDBOptions:GetOptionsTable(self:GetDB()) + profileOptions.order = GUI:Order() + opts.args[categoryName] = profileOptions + + return opts +end + + + + + -- ██████╗ ███████╗██████╗ ██╗ ██╗ ██████╗ ██████╗ ██████╗ ████████╗██╗ ██████╗ ███╗ ██╗███████╗ -- ██╔══██╗██╔════╝██╔══██╗██║ ██║██╔════╝ ██╔═══██╗██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝ -- ██║ ██║█████╗ ██████╔╝██║ ██║██║ ███╗ ██║ ██║██████╔╝ ██║ ██║██║ ██║██╔██╗ ██║███████╗ @@ -2160,38 +2189,53 @@ local function MakeDebugOptions(opts, categoryName) end end - -- Debug View + -- Debug Output do - local opts = GUI:CreateGroup(opts, GUI:Order(), "View") + local opts = GUI:CreateGroup(opts, GUI:Order(), "Output") local disabled = not self:GetGlobalOption"debug" do local opts = GUI:CreateGroupBox(opts, "Suppress All") - GUI:CreateToggle(opts, {"debugView", "suppressAll"}, self.L["Hide"], nil, disabled).width = 2 + GUI:CreateToggle(opts, {"debugOutput", "suppressAll"}, self.debugPrefix .. " " .. self.L["Hide messages like this one."], nil, disabled).width = 2 end do - local opts = GUI:CreateGroupBox(opts, "Tooltips") + local opts = GUI:CreateGroupBox(opts, "Message Types") - local disabled = disabled or self:GetGlobalOption("debugView", "suppressAll") + local disabled = disabled or self:GetGlobalOption("debugOutput", "suppressAll") for i, data in ipairs{ - {"tooltipLineNumbers", "Tooltip Line Numbers"}, - {"paddingConversionSuccesses", "Padding Conversion Successes"}, - {"paddingConversionFailures", "Padding Conversion Failures"}, + {"tooltipMethodHook", "Tooltip Method Hook"}, + {"tooltipOnSetItemHook", "Tooltip tooltipOnSetItem Hook"}, + {"tooltipHookFail", "Tooltip Hook Failure"}, + {"tooltipHookMarked", "Tooltip Hook Marked"}, + {"initialTooltipData", "Initial Tooltip Data"}, + {"finalTooltipData", "Final Tooltip Data"}, + {"constructorCreated", "Constructor Created"}, + {"constructorCached", "Constructor Cached"}, + {"constructorWiped", "Constructor Wiped"}, + {"constructorValidationFail", "Constructor Validation Failure"}, + {"constructorLineMove", "Constructor Moving Line"}, + {"paddingDecisions", "Padding Decisions"}, + {"optionSet", "Option Set"}, + {"cvarSet", "CVar Set"}, + {"InterfaceOptionsFrameFix", "Interface Options Patch"}, + {"throttlingStarted", "Throttling Started"}, } do if i ~= 1 then GUI:CreateNewline(opts) end - GUI:CreateToggle(opts, {"debugView", data[1]}, data[2], nil, disabled).width = 2 + GUI:CreateToggle(opts, {"debugOutput", data[1]}, format("%d: %s", i, data[2]), nil, disabled).width = 2 end end do local opts = GUI:CreateGroupBox(opts, "Scanner Tooltips") + local disabled = disabled or self:GetGlobalOption("debugOutput", "suppressAll") + for i, data in ipairs{ {"tooltip_GameTooltip", "GameTooltip"}, {"tooltip_ItemRefTooltip", "ItemRefTooltip"}, @@ -2201,58 +2245,43 @@ local function MakeDebugOptions(opts, categoryName) if i ~= 1 then GUI:CreateNewline(opts) end - GUI:CreateToggle(opts, {"debugView", data[1]}, data[2]).width = 2 + GUI:CreateToggle(opts, {"debugOutput", data[1]}, data[2], nil, disabled).width = 2 end end end - -- Debug Output + -- Debug View do - local opts = GUI:CreateGroup(opts, GUI:Order(), "Output") + local opts = GUI:CreateGroup(opts, GUI:Order(), "View") local disabled = not self:GetGlobalOption"debug" do local opts = GUI:CreateGroupBox(opts, "Suppress All") - GUI:CreateToggle(opts, {"debugOutput", "suppressAll"}, self.debugPrefix .. " " .. self.L["Hide messages like this one."], nil, disabled).width = 2 + GUI:CreateToggle(opts, {"debugView", "suppressAll"}, self.L["Hide"], nil, disabled).width = 2 end do - local opts = GUI:CreateGroupBox(opts, "Message Types") + local opts = GUI:CreateGroupBox(opts, "Tooltips") - local disabled = disabled or self:GetGlobalOption("debugOutput", "suppressAll") + local disabled = disabled or self:GetGlobalOption("debugView", "suppressAll") for i, data in ipairs{ - {"tooltipMethodHook", "Tooltip Method Hook"}, - {"tooltipOnSetItemHook", "Tooltip tooltipOnSetItem Hook"}, - {"tooltipHookFail", "Tooltip Hook Failure"}, - {"tooltipHookMarked", "Tooltip Hook Marked"}, - {"initialTooltipData", "Initial Tooltip Data"}, - {"finalTooltipData", "Final Tooltip Data"}, - {"constructorCreated", "Constructor Created"}, - {"constructorCached", "Constructor Cached"}, - {"constructorWiped", "Constructor Wiped"}, - {"constructorValidationFail", "Constructor Validation Failure"}, - {"constructorLineMove", "Constructor Moving Line"}, - {"paddingDecisions", "Padding Decisions"}, - {"optionSet", "Option Set"}, - {"cvarSet", "CVar Set"}, - {"InterfaceOptionsFrameFix", "Interface Options Patch"}, - {"throttlingStarted", "Throttling Started"}, + {"tooltipLineNumbers", "Tooltip Line Numbers"}, + {"paddingConversionSuccesses", "Padding Conversion Successes"}, + {"paddingConversionFailures", "Padding Conversion Failures"}, } do if i ~= 1 then GUI:CreateNewline(opts) end - GUI:CreateToggle(opts, {"debugOutput", data[1]}, data[2], nil, disabled).width = 2 + GUI:CreateToggle(opts, {"debugView", data[1]}, data[2], nil, disabled).width = 2 end end do local opts = GUI:CreateGroupBox(opts, "Scanner Tooltips") - local disabled = disabled or self:GetGlobalOption("debugOutput", "suppressAll") - for i, data in ipairs{ {"tooltip_GameTooltip", "GameTooltip"}, {"tooltip_ItemRefTooltip", "ItemRefTooltip"}, @@ -2262,7 +2291,7 @@ local function MakeDebugOptions(opts, categoryName) if i ~= 1 then GUI:CreateNewline(opts) end - GUI:CreateToggle(opts, {"debugOutput", data[1]}, data[2], nil, disabled).width = 2 + GUI:CreateToggle(opts, {"debugView", data[1]}, data[2]).width = 2 end end end @@ -2363,25 +2392,6 @@ local function MakeDebugOptions(opts, categoryName) end --- ██████╗ ██████╗ ██████╗ ███████╗██╗██╗ ███████╗ ██████╗ ██████╗ ████████╗██╗ ██████╗ ███╗ ██╗███████╗ --- ██╔══██╗██╔══██╗██╔═══██╗██╔════╝██║██║ ██╔════╝ ██╔═══██╗██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝ --- ██████╔╝██████╔╝██║ ██║█████╗ ██║██║ █████╗ ██║ ██║██████╔╝ ██║ ██║██║ ██║██╔██╗ ██║███████╗ --- ██╔═══╝ ██╔══██╗██║ ██║██╔══╝ ██║██║ ██╔══╝ ██║ ██║██╔═══╝ ██║ ██║██║ ██║██║╚██╗██║╚════██║ --- ██║ ██║ ██║╚██████╔╝██║ ██║███████╗███████╗ ╚██████╔╝██║ ██║ ██║╚██████╔╝██║ ╚████║███████║ --- ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ - -local function MakeProfileOptions(opts, categoryName) - local self = Addon - local GUI = self.GUI - - local profileOptions = self.AceDBOptions:GetOptionsTable(self:GetDB()) - profileOptions.order = GUI:Order() - opts.args[categoryName] = profileOptions - - return opts -end - - -- █████╗ ██████╗ ██████╗ ██████╗ ███╗ ██╗ ██████╗ ██████╗ ████████╗██╗ ██████╗ ███╗ ██╗███████╗ diff --git a/Init/Init.lua b/Init/Init.lua index 6eb7fef..70c1d86 100644 --- a/Init/Init.lua +++ b/Init/Init.lua @@ -196,12 +196,23 @@ do end return nop end + -- calls func in protected mode. errors are announced and then passed to errFunc. errFunc errors silently. non-blocking. function Addon:xpcall(func, errFunc) return xpcall(func, GetErrorHandler(errFunc)) end + -- calls func in protected mode. errors passed to errFunc if it exists. errFunc errors silently. non-blocking. function Addon:xpcallSilent(func, errFunc) - return xpcall(func, nop) + return xpcall(func, errFunc or nop) end + -- calls func in protected mode. errors passed to errFunc. non-blocking, unless errFunc errors. + function Addon:pcall(func, errFunc) + local t = {pcall(func)} + if not t[1] then + errFunc(unpack(t, 2)) + end + return unpack(t, 2) + end + -- Creates a non-blocking error. function Addon:Throw(...) if Addon:IsDebugEnabled() and ShouldShowLuaErrors() then geterrorhandler()(...) @@ -212,6 +223,7 @@ do local count = select("#", ...) self:xpcall(function() self:Throw(format(unpack(args, 1, count))) end) end + -- Creates a non-blocking error if bool is falsy. function Addon:ThrowAssert(bool, ...) if bool then return bool end if Addon:IsDebugEnabled() and ShouldShowLuaErrors() then @@ -226,6 +238,7 @@ do self:xpcall(function() self:Throw(format(unpack(args, 1, count))) end) return false end + -- Creates a blocking error. function Addon:Error(str) error(str, 2) end @@ -238,6 +251,7 @@ do function Addon:ErrorfLevel(lvl, ...) error(format(...), lvl + 1) end + -- Creates a blocking error if bool is falsy. function Addon:Assert(bool, str) if not bool then error(str, 2) @@ -325,6 +339,27 @@ end -- ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝╚══════╝ do + local function DeepCopy(orig, seen) + local new + if type(orig) == "table" then + if seen[orig] then + new = seen[orig] + else + new = {} + seen[orig] = copy + for k, v in next, orig, nil do + new[DeepCopy(k, seen)] = DeepCopy(v, seen) + end + setmetatable(new, DeepCopy(getmetatable(orig), seen)) + end + else + new = orig + end + return new + end + function Addon:Copy(val) + return DeepCopy(val, {}) + end function Addon:TableConcat(tbl, separator) local t = {} @@ -894,28 +929,6 @@ end -- ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ do - local function DeepCopy(orig, seen) - local new - if type(orig) == "table" then - if seen[orig] then - new = seen[orig] - else - new = {} - seen[orig] = copy - for k, v in next, orig, nil do - new[DeepCopy(k, seen)] = DeepCopy(v, seen) - end - setmetatable(new, DeepCopy(getmetatable(orig), seen)) - end - else - new = orig - end - return new - end - function Addon:Copy(val) - return DeepCopy(val, {}) - end - local onOptionSetHandlers = {} function Addon:RegisterOptionSetHandler(func) tinsert(onOptionSetHandlers, func) @@ -968,9 +981,10 @@ do for _, dbSection in ipairs(dbTypes) do local typeKey, typeName = unpack(dbSection, 1, 2) - local GetOptionQuiet = format("Get%s%sOptionQuiet", dbName, typeName) - local GetOption = format("Get%s%sOption", dbName, typeName) - local GetDefaultOption = format("Get%s%sOption", defaultName, typeName) + local GetOption = format("Get%s%sOption", dbName, typeName) + local GetOptionQuiet = format("Get%s%sOptionQuiet", dbName, typeName) + local GetDefaultOption = format("Get%s%sOption", defaultName, typeName) + local GetDefaultOptionQuiet = format("Get%s%sOptionQuiet", defaultName, typeName) Addon[GetOptionQuiet] = function(self, ...) assert(self[dbKey], format("Attempted to access database before initialization: %s", Addon:TableConcat({dbKey, typeKey, ...}, " > "))) @@ -1187,7 +1201,7 @@ do Addon:DebugIfOutput("optionsOpenedPost", "Options opened (Post)") end) Addon:RegisterOptionsClosePostCallback(function() - Addon:DebugIfOutput("optionsOpenedPost", "Options closed (Post)") + Addon:DebugIfOutput("optionsClosedPost", "Options closed (Post)") end) @@ -1299,6 +1313,25 @@ do local ResetFunction = function(keys) local funcName = format("Reset%sOptionConfig", dbType) return function(info, val) Addon[funcName](Addon, unpack(keys)) end end local GetColorFunction = function(keys) local funcName = format("Get%sOption", dbType) return function(info) return Addon:ConvertColorToBlizzard(Addon[funcName](Addon, unpack(keys))) end end local SetColorFunction = function(keys) local funcName = format("Set%sOption", dbType) return function(info, r, g, b) Addon[funcName](Addon, Addon:ConvertColorFromBlizzard(r, g, b), unpack(keys)) end end + + + local MultiGetFunction = function(keys) + local funcName = format("Get%sOption", dbType) + return function(info, key) + local path = Addon:Copy(keys) + path[#path+1] = key + return Addon[funcName](Addon, unpack(path)) + end + end + + local MultiSetFunction = function(keys) + local funcName = format("Set%sOptionConfig", dbType) + return function(info, key, val) + local path = Addon:Copy(keys) + path[#path+1] = key + Addon[funcName](Addon, val, unpack(path)) + end + end -- options window needs to redraw if color changes function GUI:SetDBType(typ) @@ -1370,13 +1403,11 @@ do option.sorting = sorting return option end - function GUI:CreateDropdown(...) local option = self:CreateSelect(...) option.style = "dropdown" return option end - function GUI:CreateRadio(...) local option = self:CreateSelect(...) option.style = "radio" @@ -1385,7 +1416,14 @@ do function GUI:CreateMultiSelect(opts, keys, name, desc, values, disabled) local option = self:CreateEntry(opts, keys, name, desc, "multiselect", disabled) - option.values = values + option.values = values + option.get = MultiGetFunction(keys) + option.set = MultiSetFunction(keys) + return option + end + function GUI:CreateMultiDropdown(...) + local option = self:CreateMultiSelect(...) + option.dialogControl = "Dropdown" return option end @@ -1468,21 +1506,26 @@ do end local function HookCloseConfig() - local hookedKey = "hooked" .. ADDON_NAME + local hookedKey = ADDON_NAME .. "_OPEN" local frame = Addon:GetConfigWindow() Addon:ThrowAssert(frame, "Can't find frame to hook options menu close") - if frame[hookedKey] then return end + local alreadyHooked = frame[hookedKey] ~= nil + frame[hookedKey] = true + + if alreadyHooked then return end frame:HookScript('OnHide', function(self) local currentFrame = Addon:GetConfigWindow() if not currentFrame or self ~= currentFrame then - Addon:RunOptionsClosePostCallbacks() + if self[hookedKey] then + Addon:RunOptionsClosePostCallbacks() + self[hookedKey] = false + end end end) - frame[hookedKey] = true end function Addon:GetConfigWindow() @@ -1532,6 +1575,74 @@ do Panel.default = function() self:ResetProfile(blizzardOptions) end return Panel end + + + do + Addon.staticPopups = {} + + local function MakeName(name) + return ADDON_NAME .. "_" .. tostring(name) + end + + + function Addon:InitPopup(name, popupData) + local key = MakeName(name) + self:Assertf(not StaticPopupDialogs[key], "StaticPopup with name '%s' already exists", key) + + self.staticPopups[name] = true + StaticPopupDialogs[key] = popupData + end + + function Addon:ShowPopup(name, data, ...) + local key = MakeName(name) + self:Assertf(StaticPopupDialogs[key], "StaticPopup with name '%s' doesn't exist", key) + self:Assertf(self.staticPopups[name], "StaticPopup with name '%s' isn't owned by %s", key, ADDON_NAME) + + local textAdditions = {...} + StaticPopup_Show(key, textAdditions[1], textAdditions[2], data) + if #textAdditions > 2 then + self:EditPopupText(name, ...) + end + end + + function Addon:HidePopup(name) + local key = MakeName(name) + self:Assertf(StaticPopupDialogs[key], "StaticPopup with name '%s' doesn't exist", key) + self:Assertf(self.staticPopups[name], "StaticPopup with name '%s' isn't owned by %s", key, ADDON_NAME) + + StaticPopup_Hide(key) + end + + function Addon:IsPopupShown(name) + return self:GetPopupData(name) and true or false + end + + function Addon:GetPopupData(name) + local key = MakeName(name) + self:Assertf(StaticPopupDialogs[key], "StaticPopup with name '%s' doesn't exist", key) + self:Assertf(self.staticPopups[name], "StaticPopup with name '%s' isn't owned by %s", key, ADDON_NAME) + + local frameName, data = StaticPopup_Visible(key) + if not data then return end + + return data.data + end + + function Addon:EditPopupText(name, ...) + local key = MakeName(name) + self:Assertf(StaticPopupDialogs[key], "StaticPopup with name '%s' doesn't exist", key) + self:Assertf(self.staticPopups[name], "StaticPopup with name '%s' isn't owned by %s", key, ADDON_NAME) + + local frameName = StaticPopup_Visible(key) + if frameName then + local textFrameName = frameName .. "Text" + local textFrame = _G[textFrameName] + self:Assertf(textFrame, "StaticPopup text frame with name '%s' isn't open", textFrameName) + + textFrame:SetFormattedText(StaticPopupDialogs[key].text, ...) + end + end + end end diff --git a/Locale/_LocaleAutomatic.lua b/Locale/_LocaleAutomatic.lua index 4bd9820..5adf135 100644 --- a/Locale/_LocaleAutomatic.lua +++ b/Locale/_LocaleAutomatic.lua @@ -18,6 +18,21 @@ local tostring = tostring local locale = GetLocale() +--[[ +L["key"] = value + +value should be a string, but can also be a function that returns a string + +value could also be a list of strings or functions that return strings. the first truthy value will be used + a nil element will throw an error and continue to the next element + a false element will fail silently and continue to the next element + +a value of nil will throw an error and fail +a value of false will fail silently + +accessing a key with no value will throw an error and return the key +]] + local actual = {} local L = setmetatable({}, { @@ -49,19 +64,22 @@ local L = setmetatable({}, { else Addon:Warnf(ADDON_NAME..": Automatic translation #%d failed for '%s'", i, tostring(key)) end - else + elseif val[i] ~= false then Addon:Warnf(ADDON_NAME..": Automatic translation #%d failed for '%s'", i, tostring(key)) end end elseif type(val) == "function" then -- use the function return value unless it errors + if not Addon:xpcallSilent(val, function(err) Addon:Throwf("%s: Automatic translation error for '%s' : %s", ADDON_NAME, tostring(key), err) end) then + return + end local success, result = Addon:xpcall(val) if not success then Addon:Throwf("%s: Automatic translation error for '%s'", ADDON_NAME, tostring(key)) return end - actual[key] = result - else + self[key] = result + elseif val ~= false then actual[key] = val end end, @@ -143,7 +161,6 @@ L["Short Name"] = COMMUNITIES_SETTINGS_SHORT_NAME_LABEL L["Show Item Level"] = SHOW_ITEM_LEVEL L["Category"] = CATEGORY L["Weapon Damage"] = DAMAGE_TOOLTIP -L["Bonus Damage"] = BONUS_DAMAGE L["Speed"] = SPEED L["Damage Per Second"] = ITEM_MOD_DAMAGE_PER_SECOND_SHORT L["Trade"] = TRADE @@ -493,8 +510,8 @@ L["Improves spell hit rating by %s."] = ITEM_MOD_HIT_SPELL_RATING L["Critical Strike Rating (Spell)"] = ITEM_MOD_CRIT_SPELL_RATING_SHORT L["Improves spell critical strike rating by %s."] = ITEM_MOD_CRIT_SPELL_RATING -L["Haste Rating (Spell)"] = {ITEM_MOD_HASTE_SPELL_RATING_SHORT, function() return strGsub(ITEM_MOD_CRIT_SPELL_RATING_SHORT, Addon:CoverSpecialCharacters(ITEM_MOD_CRIT_RATING_SHORT), Addon:CoverSpecialCharacters(ITEM_MOD_HASTE_RATING_SHORT)) end} -L["Improves spell haste rating by %s."] = {ITEM_MOD_HASTE_SPELL_RATING, function() return strGsub(ITEM_MOD_CRIT_SPELL_RATING, Addon:CoverSpecialCharacters(ITEM_MOD_CRIT_RATING), Addon:CoverSpecialCharacters(ITEM_MOD_HASTE_RATING)) end} +L["Haste Rating (Spell)"] = {ITEM_MOD_HASTE_SPELL_RATING_SHORT or false, function() return strGsub(ITEM_MOD_CRIT_SPELL_RATING_SHORT, Addon:CoverSpecialCharacters(ITEM_MOD_CRIT_RATING_SHORT), Addon:CoverSpecialCharacters(ITEM_MOD_HASTE_RATING_SHORT)) end} +L["Improves spell haste rating by %s."] = {ITEM_MOD_HASTE_SPELL_RATING or false, function() return strGsub(ITEM_MOD_CRIT_SPELL_RATING, Addon:CoverSpecialCharacters(ITEM_MOD_CRIT_RATING), Addon:CoverSpecialCharacters(ITEM_MOD_HASTE_RATING)) end} L["Health Regeneration"] = ITEM_MOD_HEALTH_REGENERATION_SHORT L["Restores %s health per 5 sec."] = ITEM_MOD_HEALTH_REGEN diff --git a/Operations/RewordLine.lua b/Operations/RewordLine.lua index 61a727b..d52c992 100644 --- a/Operations/RewordLine.lua +++ b/Operations/RewordLine.lua @@ -228,7 +228,7 @@ function Addon:RewordLine(tooltip, line, tooltipData) end end - if Addon:GetDebugView"tooltipLineNumbers" then + if Addon:GetDebugView"tooltipLineNumbers" and not line.fake then text = format("[%d] ", line.i) .. text end diff --git a/Stats/Stats.lua b/Stats/Stats.lua index a4778dd..63a951a 100644 --- a/Stats/Stats.lua +++ b/Stats/Stats.lua @@ -211,7 +211,7 @@ do tinsert(statsData, {1, {true, true, true, true}, "Spell Power", self.L["Spell Power"], self.L["Increases spell power by %s."], self.colors.GREEN, self.colors.LILAC_GEODE}) - tinsert(statsData, {0, {true, true, nil , true}, "Healing", self.L["Bonus Healing"], self.L["Increases healing done by magical spells and effects by up to %s."], self.colors.GREEN, self.colors.LIGHT_CYAN}) + tinsert(statsData, {0, {true, true, nil , true}, "Healing", self.L["Bonus Healing"], self.L["Increases healing done by magical spells and effects by up to %s."], self.colors.GREEN, self.colors.LIGHT_CYAN}) tinsert(statsData, {1, {true, true, nil, nil}, "Spell Damage" , self.L["Bonus Damage"], self.L["Increases damage done by magical spells and effects by up to %s."], self.colors.GREEN, self.colors.KISSES}) for i, stat in ipairs{"Arcane Damage", "Fire Damage", "Nature Damage", "Frost Damage", "Shadow Damage", "Holy Damage"} do @@ -317,10 +317,15 @@ do end function StatInfo:Reword(text, normalForm) - if Addon:GetOption("allow", "reword") and Addon:GetOption("doReword", stat) then - text = ConvertToAliasForm(ApplyMod(text, normalForm)) - end - return text + return Addon:pcall(function() + if Addon:GetOption("allow", "reword") and Addon:GetOption("doReword", stat) then + text = ConvertToAliasForm(ApplyMod(text, normalForm)) + end + return text + end, + function(err) + Addon:Errorf("Problem with stat %s: %s", stat, err) + end) end local function HasNumber(match1, match2) @@ -332,39 +337,48 @@ do end function StatInfo:ConvertToNormalForm(text) - text = strLower(text) - local match1, match2 = strMatch(text, Addon:ReversePattern(tooltipPatternLower)) - if match1 then - if HasNumber(match1, match2) then return format(normalFormPattern, match1, match2) end - end - local match1, match2 = strMatch(text, strLower(normalFormCaptureLower)) - if match1 then - if HasNumber(match1, match2) then return format(normalFormPattern, match1, match2) end - end - local match1, match2 = strMatch(text, strLower(normalFormLooseCaptureLower)) - if match1 then - if HasNumber(match1, match2) then return format(normalFormPattern, match1, match2) end - end - for _, rule in ipairs(Addon:GetExtraStatCapture(stat) or {}) do - local matches = rule.OUTPUT and {rule.OUTPUT(strMatch(text, rule.INPUT))} or {strMatch(text, rule.INPUT)} - if #matches > 0 then - if HasNumber(matches[1], matches[2]) then return format(normalFormPattern, matches[1], matches[2]) end + return Addon:pcall(function() + text = strLower(text) + local match1, match2 = strMatch(text, Addon:ReversePattern(tooltipPatternLower)) + if match1 then + if HasNumber(match1, match2) then return format(normalFormPattern, match1, match2) end end - end - return nil + local match1, match2 = strMatch(text, strLower(normalFormCaptureLower)) + if match1 then + if HasNumber(match1, match2) then return format(normalFormPattern, match1, match2) end + end + local match1, match2 = strMatch(text, strLower(normalFormLooseCaptureLower)) + if match1 then + if HasNumber(match1, match2) then return format(normalFormPattern, match1, match2) end + end + for _, rule in ipairs(Addon:GetExtraStatCapture(stat) or {}) do + local matches = rule.OUTPUT and {rule.OUTPUT(strMatch(text, rule.INPUT))} or {strMatch(text, rule.INPUT)} + if #matches > 0 then + if HasNumber(matches[1], matches[2]) then return format(normalFormPattern, matches[1], matches[2]) end + end + end + end, + function(err) + Addon:Errorf("Problem with stat %s: %s", stat, err) + end) end function StatInfo:GetDefaultForm(number) - local percent = strFind(number, "%%$") - number = Addon:ToNumber(number) - local strNumber - if isBaseStat and not isFakeBaseStat then - strNumber = tostring(number) - else - strNumber = Addon:ToFormattedNumber(number, nil, Addon.L["."], Addon.L[","], false, false) - end - strNumber = strNumber .. (percent and "%" or "") - return format(tooltipPattern2, isBaseStat and (number < 0 and "" or "+") or strNumber, isBaseStat and strNumber or nil) + return Addon:pcall(function() + local percent = strFind(number, "%%$") + number = Addon:ToNumber(number) + local strNumber + if isBaseStat and not isFakeBaseStat then + strNumber = tostring(number) + else + strNumber = Addon:ToFormattedNumber(number, nil, Addon.L["."], Addon.L[","], false, false) + end + strNumber = strNumber .. (percent and "%" or "") + return format(tooltipPattern2, isBaseStat and (number < 0 and "" or "+") or strNumber, isBaseStat and strNumber or nil) + end, + function(err) + Addon:Errorf("Problem with stat %s: %s", stat, err) + end) end function StatInfo:GetNormalName()