diff --git a/.pkgmeta b/.pkgmeta index 7ac6d6f..fac3c0f 100644 --- a/.pkgmeta +++ b/.pkgmeta @@ -10,6 +10,7 @@ externals: Libs/AceHook-3.0: https://repos.wowace.com/wow/ace3/trunk/AceHook-3.0 Libs/AceTimer-3.0: https://repos.wowace.com/wow/ace3/trunk/AceTimer-3.0 Libs/AceLocale-3.0: https://repos.wowace.com/wow/ace3/trunk/AceLocale-3.0 + Libs/AceBucket-3.0: https://repos.wowace.com/wow/ace3/trunk/AceBucket-3.0 enable-nolib-creation: yes diff --git a/.scripts/hardcode_string_check.py b/.scripts/hardcode_string_check.py index cf0f6fb..a34cd46 100644 --- a/.scripts/hardcode_string_check.py +++ b/.scripts/hardcode_string_check.py @@ -4,6 +4,8 @@ # Function to check if a file or directory should be ignored def should_ignore(path, ignore_files, ignore_dirs): + if os.path.basename(path) in ignore_dirs: + return True for dir in ignore_dirs: if path.startswith(f"./{dir}/"): return True @@ -65,8 +67,19 @@ def scan_directory(directory, ignore_files=None, ignore_dirs=None): def main(): - ignore_files = ["TestMode.lua"] - ignore_dirs = [".git", ".scripts", ".release", "locale"] + ignore_files = [] + ignore_dirs = [ + ".git", + ".github", + ".release", + ".scripts", + ".trunk", + ".venv", + "Icons", + "locale", + "luacov-html", + "spec", + ] # Scan the current directory issues = scan_directory(".", ignore_files, ignore_dirs) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 3121128..cdcbb9c 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -21,6 +21,9 @@ lint: - linters: [stylua] paths: - locale/** + - linters: [no-invalid-prints] + paths: + - spec/** enabled: - stylua@0.20.0 - actionlint@1.7.1 diff --git a/AddonScope.lua b/AddonScope.lua index dcee3cc..3d77bc1 100644 --- a/AddonScope.lua +++ b/AddonScope.lua @@ -3,8 +3,52 @@ G_RLF = {} local addonName = "RPGLootFeed" local dbName = addonName .. "DB" local localeName = addonName .. "Locale" + +local xpcall = xpcall + +local function errorhandler(err) + local suffix = "\n\n==== Addon Info " .. G_RLF.addonName .. " " .. G_RLF.addonVersion .. " ====\n\n" + suffix = suffix .. G_RLF.L["Issues"] .. "\n\n" + + return geterrorhandler()(err .. suffix) +end + +function G_RLF:fn(func, ...) + -- Borrowed from AceAddon-3.0 + if type(func) == "function" then + return xpcall(func, errorhandler, ...) + end +end + G_RLF.RLF = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0", "AceTimer-3.0") G_RLF.RLF:SetDefaultModuleState(true) +G_RLF.RLF:SetDefaultModulePrototype({ + getLogger = function(self) + return G_RLF.RLF:GetModule("Logger") + end, + fn = function(s, func, ...) + local function errorhandler(err) + local suffix = "\n\n==== Addon Info " .. G_RLF.addonName .. " " .. G_RLF.addonVersion .. " ====\n\n" + local status, trace = pcall(function() + return s:getLogger():Trace(s.moduleName) + end) + if status then + suffix = suffix .. "Log traces related to " .. s.moduleName .. "\n" + suffix = suffix .. "-------------------------------------------------\n" + suffix = suffix .. trace + suffix = suffix .. "-------------------------------------------------\n\n" + end + suffix = suffix .. G_RLF.L["Issues"] .. "\n\n" + + return geterrorhandler()(err .. suffix) + end + + -- Borrowed from AceAddon-3.0 + if type(func) == "function" then + return xpcall(func, errorhandler, ...) + end + end, +}) G_RLF.addonName = addonName G_RLF.dbName = dbName G_RLF.localeName = localeName @@ -20,19 +64,3 @@ G_RLF.DisableBossBanner = { function G_RLF:Print(...) G_RLF.RLF:Print(...) end - -local xpcall = xpcall - -local function errorhandler(err) - local suffix = "\n\n==== Addon Info " .. G_RLF.addonName .. " " .. G_RLF.addonVersion .. " ====\n\n" - suffix = suffix .. G_RLF.L["Issues"] .. "\n\n" - - return geterrorhandler()(err .. suffix) -end - -function G_RLF:fn(func, ...) - -- Borrowed from AceAddon-3.0 - if type(func) == "function" then - return xpcall(func, errorhandler, ...) - end -end diff --git a/Features/Currency.lua b/Features/Currency.lua index d400de5..12dabf1 100644 --- a/Features/Currency.lua +++ b/Features/Currency.lua @@ -1,5 +1,11 @@ local Currency = G_RLF.RLF:NewModule("Currency", "AceEvent-3.0") +local hiddenCurrencies + +local function isHiddenCurrency(id) + return hiddenCurrencies[id] == true +end + function Currency:OnInitialize() if G_RLF.db.global.currencyFeed then self:Enable() @@ -16,20 +22,51 @@ function Currency:OnEnable() self:RegisterEvent("CURRENCY_DISPLAY_UPDATE") end -function Currency:CURRENCY_DISPLAY_UPDATE(_, ...) +function Currency:CURRENCY_DISPLAY_UPDATE(eventName, ...) local currencyType, _quantity, quantityChange, _quantityGainSource, _quantityLostSource = ... + self:getLogger():Info(eventName, "WOWEVENT", self.moduleName, currencyType, eventName, quantityChange) + if currencyType == nil or not quantityChange or quantityChange <= 0 then + self:getLogger():Debug( + "Skip showing currency", + G_RLF.addonName, + self.moduleName, + currencyType, + "SKIP: Something was missing, don't display", + quantityChange + ) + return + end + + if isHiddenCurrency(currencyType) then + self:getLogger():Debug( + "Skip showing currency", + G_RLF.addonName, + self.moduleName, + currencyType, + "SKIP: This is a known hidden currencyType", + quantityChange + ) return end local info = C_CurrencyInfo.GetCurrencyInfo(currencyType) if info == nil or info.description == "" or info.iconFileID == nil then + self:getLogger():Debug( + "Skip showing currency", + G_RLF.addonName, + self.moduleName, + currencyType, + "SKIP: Description or icon was empty", + quantityChange + ) return end - G_RLF:fn(function() + self:fn(function() G_RLF.LootDisplay:ShowLoot( + self.moduleName, info.currencyID, C_CurrencyInfo.GetCurrencyLink(currencyType), info.iconFileID, @@ -38,4 +75,316 @@ function Currency:CURRENCY_DISPLAY_UPDATE(_, ...) end) end +hiddenCurrencies = { + [2918] = true, + [2919] = true, + [2899] = true, + [2793] = true, + [2902] = true, + [2897] = true, + [3045] = true, + [2912] = true, + [1822] = true, + [3066] = true, + [3040] = true, + [2785] = true, + [1810] = true, + [3002] = true, + [2795] = true, + [3041] = true, + [2901] = true, + [1191] = true, + [3054] = true, + [3068] = true, + [2034] = true, + [2789] = true, + [3003] = true, + [3050] = true, + [2035] = true, + [3004] = true, + [2813] = true, + [2786] = true, + [2026] = true, + [2792] = true, + [1728] = true, + [3051] = true, + [3047] = true, + [2794] = true, + [3052] = true, + [2787] = true, + [2033] = true, + [2024] = true, + [2788] = true, + [2900] = true, + [2023] = true, + [3065] = true, + [3057] = true, + [1889] = true, + [3086] = true, + [2791] = true, + [3071] = true, + [2029] = true, + [3042] = true, + [3046] = true, + [2898] = true, + [3059] = true, + [3061] = true, + [3048] = true, + [2027] = true, + [2167] = true, + [1744] = true, + [2706] = true, + [2030] = true, + [3064] = true, + [3067] = true, + [2790] = true, + [3058] = true, + [3043] = true, + [1703] = true, + [2709] = true, + [3063] = true, + [2025] = true, + [2921] = true, + [2904] = true, + [2903] = true, + [2533] = true, + [2166] = true, + [3070] = true, + [3049] = true, + [1171] = true, + [1877] = true, + [2715] = true, + [2796] = true, + [3069] = true, + [3060] = true, + [3075] = true, + [3013] = true, + [2814] = true, + [2707] = true, + [2267] = true, + [2153] = true, + [2805] = true, + [3074] = true, + [2920] = true, + [2652] = true, + [2819] = true, + [2106] = true, + [3023] = true, + [3073] = true, + [3083] = true, + [2922] = true, + [3053] = true, + [2808] = true, + [2649] = true, + [2028] = true, + [3044] = true, + [1891] = true, + [1907] = true, + [2171] = true, + [1579] = true, + [3062] = true, + [1838] = true, + [1559] = true, + [2109] = true, + [1747] = true, + [1982] = true, + [3077] = true, + [3079] = true, + [2000] = true, + [1745] = true, + [2031] = true, + [2410] = true, + [2036] = true, + [3080] = true, + [1757] = true, + [1880] = true, + [3085] = true, + [3099] = true, + [2408] = true, + [1325] = true, + [3005] = true, + [2169] = true, + [3009] = true, + [1878] = true, + [3010] = true, + [1593] = true, + [2278] = true, + [2866] = true, + [1807] = true, + [2908] = true, + [2874] = true, + [2420] = true, + [2172] = true, + [2645] = true, + [2149] = true, + [3094] = true, + [3076] = true, + [2710] = true, + [1750] = true, + [2413] = true, + [2419] = true, + [2780] = true, + [2810] = true, + [2151] = true, + [2152] = true, + [2708] = true, + [1347] = true, + [2910] = true, + [1501] = true, + [1752] = true, + [2170] = true, + [1540] = true, + [1722] = true, + [2021] = true, + [2094] = true, + [1541] = true, + [1804] = true, + [3088] = true, + [2402] = true, + [1746] = true, + [3103] = true, + [1598] = true, + [3115] = true, + [1837] = true, + [2087] = true, + [2002] = true, + [2784] = true, + [2653] = true, + [1594] = true, + [2150] = true, + [2906] = true, + [2409] = true, + [2165] = true, + [2872] = true, + [2858] = true, + [2088] = true, + [2862] = true, + [2173] = true, + [2108] = true, + [2175] = true, + [2244] = true, + [1595] = true, + [1805] = true, + [1324] = true, + [2856] = true, + [2873] = true, + [2909] = true, + [2717] = true, + [3081] = true, + [2861] = true, + [1842] = true, + [1884] = true, + [2275] = true, + [1592] = true, + [2277] = true, + [1794] = true, + [2148] = true, + [3000] = true, + [1596] = true, + [1806] = true, + [1848] = true, + [1903] = true, + [1597] = true, + [2266] = true, + [1808] = true, + [2871] = true, + [1748] = true, + [2268] = true, + [1852] = true, + [3078] = true, + [1997] = true, + [2716] = true, + [3007] = true, + [2911] = true, + [1506] = true, + [1714] = true, + [2876] = true, + [2878] = true, + [2913] = true, + [3082] = true, + [3084] = true, + [1738] = true, + [1769] = true, + [2231] = true, + [1742] = true, + [3026] = true, + [1847] = true, + [3001] = true, + [3027] = true, + [2854] = true, + [2907] = true, + [1599] = true, + [1349] = true, + [1600] = true, + [2269] = true, + [2411] = true, + [3006] = true, + [1853] = true, + [2270] = true, + [2412] = true, + [2271] = true, + [2859] = true, + [1840] = true, + [2800] = true, + [3011] = true, + [1883] = true, + [2107] = true, + [2865] = true, + [3025] = true, + [3087] = true, + [2279] = true, + [2867] = true, + [2264] = true, + [2280] = true, + [2265] = true, + [2869] = true, + [1849] = true, + [1850] = true, + [1749] = true, + [2857] = true, + [1350] = true, + [1705] = true, + [2875] = true, + [2272] = true, + [2718] = true, + [2860] = true, + [1758] = true, + [2273] = true, + [2774] = true, + [1723] = true, + [1841] = true, + [2274] = true, + [1762] = true, + [3022] = true, + [1887] = true, + [2276] = true, + [2864] = true, + [1888] = true, + [2811] = true, + [1740] = true, + [1845] = true, + [1846] = true, + [1902] = true, + [2868] = true, + [2853] = true, + [2870] = true, + [1947] = true, + [2855] = true, + [3104] = true, + [1851] = true, + [1986] = true, + [1839] = true, + [1761] = true, + [2863] = true, + [1763] = true, + [1843] = true, + [2174] = true, + [1739] = true, + [1844] = true, + [3024] = true, + [2655] = true, + [3072] = true, + [2799] = true, +} + return Currency diff --git a/Features/Experience.lua b/Features/Experience.lua index effe96b..24e15d4 100644 --- a/Features/Experience.lua +++ b/Features/Experience.lua @@ -24,21 +24,24 @@ function Xp:OnEnable() self:RegisterEvent("PLAYER_ENTERING_WORLD") self:RegisterEvent("PLAYER_XP_UPDATE") if currentXP == nil then - G_RLF:fn(initXpValues) + self:fn(initXpValues) end end -function Xp:PLAYER_ENTERING_WORLD() - G_RLF:fn(initXpValues) +function Xp:PLAYER_ENTERING_WORLD(eventName) + self:getLogger():Info(eventName, "WOWEVENT", self.moduleName) + self:fn(initXpValues) end -function Xp:PLAYER_XP_UPDATE(_, unitTarget) - G_RLF:fn(function() +function Xp:PLAYER_XP_UPDATE(eventName, unitTarget) + self:getLogger():Info(eventName, "WOWEVENT", self.moduleName, unitTarget) + self:fn(function() if unitTarget == "player" then local newLevel = UnitLevel(unitTarget) local newCurrentXP = UnitXP(unitTarget) local delta = 0 if newLevel == nil then + self:getLogger():Warn("Could not get player level", G_RLF.addonName, self.moduleName) return end currentLevel = currentLevel or newLevel @@ -51,7 +54,10 @@ function Xp:PLAYER_XP_UPDATE(_, unitTarget) currentLevel = newLevel currentMaxXP = UnitXPMax(unitTarget) if delta > 0 then - G_RLF.LootDisplay:ShowXP(delta) + G_RLF.LootDisplay:ShowLoot(self.moduleName, delta) + else + self:getLogger() + :Warn(eventName .. " fired but delta was not positive", G_RLF.addonName, self.moduleName) end end end) diff --git a/Features/ItemLoot.lua b/Features/ItemLoot.lua index 143d571..2d4fa84 100644 --- a/Features/ItemLoot.lua +++ b/Features/ItemLoot.lua @@ -23,6 +23,7 @@ local ItemLoot = G_RLF.RLF:NewModule("ItemLoot", "AceEvent-3.0") -- ["INVTYPE_RANGEDRIGHT"] = INVSLOT_RANGED, -- Ranged weapons -- } +local logger function ItemLoot:OnInitialize() if G_RLF.db.global.itemLootFeed then self:Enable() @@ -40,10 +41,11 @@ function ItemLoot:OnEnable() end local function showItemLoot(msg, itemLink) - local amount = msg:match("r ?x(%d+)") or 1 + local amount = tonumber(msg:match("r ?x(%d+)") or 1) local _, _, itemQuality, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, sellPrice, classID, subclassID, bindType, expansionID, setID, isCraftingReagent = C_Item.GetItemInfo(itemLink) if not G_RLF.db.global.itemQualityFilter[itemQuality] then + self:getLogger():Debug("Item Ignored by quality", G_RLF.addonName, "ItemLoot", "", msg, amount) return end local itemId = itemLink:match("Hitem:(%d+)") @@ -59,24 +61,28 @@ local function showItemLoot(msg, itemLink) -- end -- end - G_RLF.LootDisplay:ShowLoot(itemId, itemLink, itemTexture, amount) + G_RLF.LootDisplay:ShowLoot("ItemLoot", itemId, itemLink, itemTexture, amount) end -function ItemLoot:CHAT_MSG_LOOT(_, ...) +function ItemLoot:CHAT_MSG_LOOT(eventName, ...) local msg, _, _, _, _, _, _, _, _, _, _, guid = ... local raidLoot = msg:match("HlootHistory:") + self:getLogger():Info(eventName, "WOWEVENT", self.moduleName, nil, eventName .. " " .. msg) if raidLoot then -- Ignore this message as it's a raid loot message + self:getLogger():Debug("Raid Loot Ignored", "WOWEVENT", self.moduleName, "", msg) return end local me = guid == GetPlayerGuid() if not me then + self:getLogger():Debug("Group Member Loot Ignored", "WOWEVENT", self.moduleName, "", msg) return end + local itemLink = msg:match("|c%x+|Hitem:.-|h%[.-%]|h|r") if itemLink then - G_RLF:fn(showItemLoot, msg, itemLink) + self:fn(showItemLoot, msg, itemLink) end end diff --git a/Features/Money.lua b/Features/Money.lua index a13cf72..cc818cb 100644 --- a/Features/Money.lua +++ b/Features/Money.lua @@ -1,6 +1,5 @@ local Money = G_RLF.RLF:NewModule("Money", "AceEvent-3.0") -local oldMethod local startingMoney function Money:OnInitialize() @@ -12,55 +11,22 @@ function Money:OnInitialize() end function Money:OnDisable() - self:UnregisterEvent("LOOT_READY") - self:UnregisterEvent("CHAT_MSG_MONEY") + self:UnregisterEvent("PLAYER_MONEY") end function Money:OnEnable() - self:RegisterEvent("LOOT_READY") - self:RegisterEvent("CHAT_MSG_MONEY") -end - -function Money:LOOT_READY() - -- Get current money to calculate the delta later - startingMoney = GetMoney() -end - -local function showMoneyLoot(msg) - local amountInCopper - if startingMoney == nil then - -- Old method that doesn't work well with locales that are missing translation - amountInCopper = oldMethod(msg) - else - amountInCopper = GetMoney() - startingMoney - end + self:RegisterEvent("PLAYER_MONEY") startingMoney = GetMoney() - G_RLF.LootDisplay:ShowMoney(amountInCopper) end -function Money:CHAT_MSG_MONEY(_, msg) - G_RLF:fn(showMoneyLoot, msg) -end - -oldMethod = function(msg) - -- Initialize default values - local gold, silver, copper = 0, 0, 0 - - -- Patterns to match optional sections - local goldPattern = "(%d+) " .. G_RLF.L["Gold"] - local silverPattern = "(%d+) " .. G_RLF.L["Silver"] - local copperPattern = "(%d+) " .. G_RLF.L["Copper"] - - -- Find and convert matches to numbers if they exist - gold = tonumber(msg:match(goldPattern)) or gold - silver = tonumber(msg:match(silverPattern)) or silver - copper = tonumber(msg:match(copperPattern)) or copper - - local amountInCopper = (gold * 100 * 100) - amountInCopper = amountInCopper + (silver * 100) - amountInCopper = amountInCopper + copper - - return amountInCopper +function Money:PLAYER_MONEY(eventName) + self:getLogger():Info(eventName, "WOWEVENT", self.moduleName) + self:fn(function() + local newMoney = GetMoney() + local amountInCopper = newMoney - startingMoney + startingMoney = newMoney + G_RLF.LootDisplay:ShowLoot("Money", amountInCopper) + end) end return Money diff --git a/Features/Reputation.lua b/Features/Reputation.lua index 3913054..ad9a7f4 100644 --- a/Features/Reputation.lua +++ b/Features/Reputation.lua @@ -3,6 +3,7 @@ local Rep = G_RLF.RLF:NewModule("Reputation", "AceEvent-3.0", "AceTimer-3.0") local locale function Rep:OnInitialize() locale = GetLocale() + -- TODO: Move this to db defaults G_RLF.db.global.factionMaps = G_RLF.db.global.factionMaps or {} G_RLF.db.global.factionMaps[locale] = G_RLF.db.global.factionMaps[locale] or {} if G_RLF.db.global.repFeed then @@ -53,7 +54,12 @@ local function extractFactionAndRep(message, patterns) local postMatchStart, postMatchEnd = string.find(msgLoop, postPattern, midMatchEnd, true) if postMatchStart then local faction = msgLoop:sub(1, midMatchStart - 1) - local rep = msgLoop:sub(midMatchEnd + 1, postMatchStart - 1) + local rep + if midMatchEnd == postMatchStart then + rep = msgLoop:sub(midMatchEnd + 1) + else + rep = msgLoop:sub(midMatchEnd + 1, postMatchStart - 1) + end return faction, tonumber(rep) end end @@ -98,8 +104,9 @@ function Rep:OnEnable() self:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") end -function Rep:CHAT_MSG_COMBAT_FACTION_CHANGE(_, message) - G_RLF:fn(function() +function Rep:CHAT_MSG_COMBAT_FACTION_CHANGE(eventName, message) + self:getLogger():Info(eventName .. " " .. message, "WOWEVENT", self.moduleName) + return self:fn(function() local faction, repChange = extractFactionAndRep(message, increasePatterns) if not faction then faction, repChange = extractFactionAndRep(message, decreasePatterns) @@ -107,9 +114,21 @@ function Rep:CHAT_MSG_COMBAT_FACTION_CHANGE(_, message) repChange = -repChange end end + if not faction or not repChange then + self:getLogger():Error( + "Could not determine faction and/or rep change from message", + G_RLF.addonName, + self.moduleName, + faction, + nil, + repChange + ) + return + end local r, g, b, color if G_RLF.db.global.factionMaps[locale][faction] == nil then -- attempt to find the missing faction's ID + self:getLogger():Debug(faction .. " not cached for " .. locale, G_RLF.addonName, self.moduleName) buildFactionLocaleMap(faction) end @@ -125,15 +144,15 @@ function Rep:CHAT_MSG_COMBAT_FACTION_CHANGE(_, message) color = FACTION_BAR_COLORS[factionData.reaction] end end + else + self:getLogger():Warn(faction .. " is STILL not cached for " .. locale, G_RLF.addonName, self.moduleName) end if color then r, g, b = color.r, color.g, color.b end - if faction and repChange then - G_RLF.LootDisplay:ShowRep(repChange, faction, r, g, b) - end + G_RLF.LootDisplay:ShowLoot(self.moduleName, repChange, faction, r, g, b) end) end diff --git a/Logger.lua b/Logger.lua new file mode 100644 index 0000000..b8bbb34 --- /dev/null +++ b/Logger.lua @@ -0,0 +1,340 @@ +local Logger = G_RLF.RLF:NewModule("Logger", "AceEvent-3.0") +local gui = LibStub("AceGUI-3.0") + +local loggerName = G_RLF.addonName .. "Logger" +local defaults = { + sessionsLogged = 0, + logs = {}, +} + +local updateContent +local getLogger +local WOWEVENT = "WOWEVENT" + +local eventSource = { + [G_RLF.addonName] = true, + [WOWEVENT] = false, +} +local function OnEventSourceChange(_, _, k, v) + eventSource[k] = v + updateContent() +end + +local debug = "DEBUG" +local info = "INFO" +local warn = "WARN" +local error = "ERROR" +local eventLevel = { + [debug] = false, + [info] = true, + [warn] = true, + [error] = true, +} +local function OnEventLevelChange(_, _, k, v) + eventLevel[k] = v + updateContent() +end + +local ItemLoot = "ItemLoot" +local Currency = "Currency" +local Money = "Money" +local Reputation = "Reputation" +local Experience = "Experience" +local eventType = { + [ItemLoot] = true, + [Currency] = true, + [Money] = true, + [Reputation] = true, + [Experience] = true, +} +local function OnEventTypeChange(_, _, k, v) + eventType[k] = v + updateContent() +end + +local function OnClearLog() + local count = #getLogger() + for i = 0, count do + getLogger()[i] = nil + end + updateContent() +end + +local frame, contentBox +local function initializeFrame() + if not frame then + frame = gui:Create("Frame") + frame:SetTitle("Loot Log") + frame:EnableResize(false) + frame:SetCallback("OnClose", function(widget) + gui:Release(widget) + frame = nil + end) + frame:SetLayout("Flow") + + local filterBar = gui:Create("SimpleGroup") + filterBar:SetFullWidth(true) + filterBar:SetLayout("Flow") + frame:AddChild(filterBar) + + contentBox = gui:Create("MultiLineEditBox") + contentBox:SetLabel("Logs") + contentBox:DisableButton(true) + contentBox:SetFullWidth(true) + contentBox:SetNumLines(23) + frame:AddChild(contentBox) + + local logSources = gui:Create("Dropdown") + logSources:SetLabel("Log Sources") + logSources:SetMultiselect(true) + logSources:SetList({ + [G_RLF.addonName] = G_RLF.addonName, + [WOWEVENT] = WOWEVENT, + }, { + G_RLF.addonName, + WOWEVENT, + }) + logSources:SetCallback("OnValueChanged", OnEventSourceChange) + for k, v in pairs(eventSource) do + logSources:SetItemValue(k, v) + end + filterBar:AddChild(logSources) + + local logLevels = gui:Create("Dropdown") + logLevels:SetLabel("Log Levels") + logLevels:SetMultiselect(true) + logLevels:SetList({ + [debug] = debug, + [info] = info, + [warn] = warn, + [error] = error, + }) + logLevels:SetCallback("OnValueChanged", OnEventLevelChange) + for k, v in pairs(eventLevel) do + logLevels:SetItemValue(k, v) + end + filterBar:AddChild(logLevels) + + local logTypes = gui:Create("Dropdown") + logTypes:SetLabel("Log Types") + logTypes:SetMultiselect(true) + logTypes:SetList({ + [ItemLoot] = ItemLoot, + [Currency] = Currency, + [Money] = Money, + [Reputation] = Reputation, + [Experience] = Experience, + }) + logTypes:SetCallback("OnValueChanged", OnEventTypeChange) + for k, v in pairs(eventType) do + logTypes:SetItemValue(k, v) + end + filterBar:AddChild(logTypes) + + local clearButton = gui:Create("Button") + clearButton:SetText("Clear Current Log") + clearButton:SetCallback("OnClick", OnClearLog) + filterBar:AddChild(clearButton) + + frame:DoLayout() + end +end + +getLogger = function() + if G_RLF.db.global.logger ~= nil and G_RLF.db.global.logger.sessionsLogged > 0 then + return G_RLF.db.global.logger.logs[G_RLF.db.global.logger.sessionsLogged] + end +end + +function Logger:OnInitialize() + self:RegisterEvent("PLAYER_ENTERING_WORLD") +end + +function Logger:PLAYER_ENTERING_WORLD(_, isLogin, isReload) + if isLogin then + G_RLF.db.global.logger.sessionsLogged = (G_RLF.db.global.logger.sessionsLogged or 0) + 1 + G_RLF.db.global.logger.logs = G_RLF.db.global.logger.logs or {} + G_RLF.db.global.logger.logs[G_RLF.db.global.logger.sessionsLogged] = {} + while G_RLF.db.global.logger.sessionsLogged > 3 do + tremove(G_RLF.db.global.logger.logs, 1) + G_RLF.db.global.logger.sessionsLogged = G_RLF.db.global.logger.sessionsLogged - 1 + end + self:Debug("Logger is ready", G_RLF.addonName) + end +end + +local function getLevel(logEntry) + local level = logEntry.level + local levelColors = { + [debug] = "|cFF808080{D}|r", -- Gray for DEBUG + [info] = "|cFFADD8E6{I}|r", -- Light blue for INFO (ADD8E6 in hex) + [warn] = "|cFFFFD700{W}|r", -- Gold for WARN + [error] = "|cFFFF0000{E}|r", -- Red for ERROR + } + + -- Return the formatted level or an empty string if the level is not recognized + return levelColors[level] or "" +end + +local function getType(logEntry) + local type = logEntry.type + local typeColors = { + [ItemLoot] = "|cFF00FF00[ITEM]|r ", -- Green for item loot + [Currency] = "|cFFFFD700[CURR]|r ", -- Gold for currency + [Money] = "|cFFC0C0C0[GOLD]|r ", -- Silver/Gray for money + [Reputation] = "|cFF1E90FF[REPU]|r ", -- Blue for reputation + [Experience] = "|cFF9932CC[EXPR]|r ", -- Purple for experience + } + + -- Return an empty string for "General" and the corresponding value for others + return typeColors[type] or "" +end + +local function getSource(logEntry) + local source = logEntry.source + local sourceStrings = { + [G_RLF.addonName] = "(RLF)", + [WOWEVENT] = "(WOW)", + } + return sourceStrings[source] or "" +end + +local function getTimestamp(logEntry) + -- Extract the time portion from the timestamp using pattern matching + local timeOnly = logEntry.timestamp:match("%d%d:%d%d:%d%d") + + -- Return the formatted timestamp with dark gray color + return "|cFF808080" .. timeOnly .. "|r" +end + +local function getContent(logEntry) + if logEntry.content == "" then + return logEntry.message + end + return logEntry.content +end + +local function getAmount(logEntry) + if logEntry.amount == "" then + return "" + end + return format(" x%s", logEntry.amount) +end + +local function isUpdatedRow(logEntry) + if logEntry.new == false then + return " ~UPDATE~" + end + return "" +end + +local function getId(logEntry) + if logEntry.id == "" then + return "" + end + return format(" [%s]", logEntry.id) +end + +local function formatLogEntry(logEntry) + return format( + "[%s]%s%s%s:%s%s%s%s\n", + getTimestamp(logEntry), + getLevel(logEntry), + getSource(logEntry), + getType(logEntry), + getContent(logEntry), + getAmount(logEntry), + isUpdatedRow(logEntry), + getId(logEntry) + ) +end + +updateContent = function() + local text = "" + + local function addText(logEntry) + text = formatLogEntry(logEntry) .. text + end + + for i, logEntry in ipairs(getLogger()) do + if eventSource[logEntry.source] then + if eventLevel[logEntry.level] then + if eventType[logEntry.type] or logEntry.type == "General" then + addText(logEntry) + end + end + end + end + contentBox:SetText(text) +end + +local function addLogEntry(level, message, source, type, id, content, amount, isNew) + local entry = { + timestamp = date("%Y-%m-%d %H:%M:%S"), + level = level, + source = source or G_RLF.addonName, + type = type or "General", + id = id or "", + content = content or "", + amount = amount or "", + new = isNew, + message = message, + } + local logTable = getLogger() + if not logTable then + -- error("Log Table not ready") + return + end + table.insert(logTable, entry) + if frame and frame:IsShown() then + updateContent() + end +end + +function Logger:Debug(message, source, type, id, content, amount, isNew) + addLogEntry(debug, message, source, type, id, content, amount, isNew) +end + +function Logger:Info(message, source, type, id, content, amount, isNew) + addLogEntry(info, message, source, type, id, content, amount, isNew) +end + +function Logger:Warn(message, source, type, id, content, amount, isNew) + addLogEntry(warn, message, source, type, id, content, amount, isNew) +end + +function Logger:Error(message, source, type, id, content, amount, isNew) + addLogEntry(error, message, source, type, id, content, amount, isNew) +end + +function Logger:Trace(type, traceSize) + local trace = "" + traceSize = traceSize or 10 + local count = 0 + local logs = getLogger() + for i = #logs, 1, -1 do + if logs[i].type == type then + count = count + 1 + trace = trace .. formatLogEntry(logs[i]) + end + if count >= traceSize then + break + end + end + + return trace +end + +function Logger:Show() + if frame then + self:Hide() + else + initializeFrame() + updateContent() + frame:Show() + end +end + +function Logger:Hide() + frame:Hide() +end diff --git a/LootDisplay.lua b/LootDisplay.lua index 698d1ed..d14c2eb 100644 --- a/LootDisplay.lua +++ b/LootDisplay.lua @@ -1,9 +1,11 @@ -local LootDisplay = {} +local LootDisplay = G_RLF.RLF:NewModule("LootDisplay", "AceBucket-3.0", "AceEvent-3.0") local Masque = LibStub and LibStub("Masque", true) local iconGroup = Masque and Masque:Group(G_RLF.addonName) -- Private method declaration +local processRow +local processFromQueue local configureFeedFrame local applyRowStyles local doesRowExist @@ -18,9 +20,6 @@ local rowBackground local rowFadeOutAnimation local rowHighlightBorder local rowIcon -local rowMoneyIcon -local rowMoneyStyles -local rowMoneyText local rowStyles local configureTestArea local createArrowsTestArea @@ -46,6 +45,7 @@ local defaults = { rowBackgroundGradientEnd = { 0.1, 0.1, 0.1, 0 }, -- Default to dark grey with 0% opacity font = "GameFontNormalSmall", } +local defaultColor local config = nil local rows = G_RLF.list() local rowFramePool = {} @@ -54,7 +54,9 @@ local boundingBox = nil local tempFontString = nil -- Public methods -function LootDisplay:Initialize() +local logger + +function LootDisplay:OnInitialize() config = DynamicPropertyTable(G_RLF.db.global, defaults) configureFeedFrame() @@ -64,6 +66,7 @@ function LootDisplay:Initialize() tempFontString = UIParent:CreateFontString(nil, "ARTWORK") tempFontString:Hide() -- Prevent it from showing up + self:RegisterBucketMessage("RLF_LootDisplay_RowReturned", 0.2, processFromQueue) end function LootDisplay:SetBoundingBoxVisibility(show) @@ -107,168 +110,175 @@ function LootDisplay:UpdateFadeDelay() end end -function LootDisplay:ShowLoot(id, link, icon, amountLooted) - local key = tostring(id) -- Use ID as a unique key - - -- Check if the item or currency is already displayed - local row = getRow(key) - if row then - -- Update existing entry - row.amount = row.amount + amountLooted - row.highlightAnimation:Stop() - row.highlightAnimation:Play() - if row.fadeOutAnimation:IsPlaying() then - row.fadeOutAnimation:Stop() - row.fadeOutAnimation:Play() +function LootDisplay:ShowLoot(type, ...) + local key, textFn, isLink, icon, quantity, quality, r, g, b, a + isLink = false + local logType = type + if type == "Currency" or type == "ItemLoot" then + isLink = true + local t, k + k, t, icon, quantity = ... + key = tostring(k) + textFn = function(existingQuantity, truncatedLink) + if not truncatedLink then + return t + end + return truncatedLink .. " x" .. ((existingQuantity or 0) + quantity) end - else - row = leaseRow(key) - if row == nil then + if type == "Currency" then + quality = C_CurrencyInfo.GetCurrencyInfo(k).quality + end + elseif type == "Money" then + key = "MONEY_LOOT" + quantity = ... + if not quantity then return end - - -- Initialize row content - rowStyles(row) - if Masque and iconGroup then - local found = string.find(link, "item:") - if found then - row.icon:SetItem(link) - else - local quality = C_CurrencyInfo.GetCurrencyInfo(id).quality - row.icon:SetItemButtonTexture(icon) - row.icon:SetItemButtonQuality(quality, link) + textFn = function(existingCopper) + local sign = "" + local total = (existingCopper or 0) + quantity + if total < 0 then + sign = "-" end - else - row.icon:SetTexture(icon) - end - row.amount = amountLooted - local extraWidth = getTextWidth(" x" .. row.amount) - row.link = truncateItemLink(link, extraWidth) - row.fadeOutAnimation:Stop() - row.fadeOutAnimation:Play() - end - row.amountText:SetText(row.link .. " x" .. row.amount) - -- Add Tooltip - row.amountText:SetScript("OnEnter", function() - row.fadeOutAnimation:Stop() - row.highlightAnimation:Stop() - row.highlightBorder:SetAlpha(0) - if not G_RLF.db.global.tooltip then - return + return sign .. C_CurrencyInfo.GetCoinTextureString(math.abs(total)) end - if G_RLF.db.global.tooltipOnShift and not IsShiftKeyDown() then - return + elseif type == "Experience" then + key = "EXPERIENCE" + quantity = ... + r, g, b, a = 1, 0, 1, 0.8 + textFn = function(existingXP) + return "+" .. ((existingXP or 0) + quantity) .. " " .. G_RLF.L["XP"] end - local inCombat = UnitAffectingCombat("player") - if inCombat then - GameTooltip:Hide() - return + elseif type == "Reputation" then + local factionName, rL, gL, bL + quantity, factionName, rL, gL, bL = ... + r, g, b = rL or 0.5, gL or 0.5, bL or 1 + a = 1 + key = "REP_" .. factionName + textFn = function(existingRep) + local sign = "+" + local rep = (existingRep or 0) + quantity + if rep < 0 then + sign = "-" + end + return sign .. math.abs(rep) .. " " .. factionName end - GameTooltip:SetOwner(row.amountText, "ANCHOR_RIGHT") - GameTooltip:SetHyperlink(row.link) -- Use the item's link to show the tooltip - GameTooltip:Show() - end) - row.amountText:SetScript("OnLeave", function() - row.fadeOutAnimation:Play() - GameTooltip:Hide() - end) + else + self:getLogger():Error("Unknown type? " .. type, G_RLF.addonName, type) + end + processRow(key, textFn, icon, quantity, quality, r, g, b, a, logType) end -function LootDisplay:ShowMoney(copper) - local key = "MONEY_LOOT" -- Use ID as a unique key +local overflowQueue = {} +processRow = function(...) + local key, textFn, icon, quantity, quality, r, g, b, a, logType = ... + local isLink = not not icon + local new = true local text - if not copper or copper <= 0 then - return - end + local rD, gD, bD, aD = unpack(defaultColor or { 1, 1, 1, 1 }) - -- Check if the item or currency is already displayed local row = getRow(key) if row then -- Update existing entry - row.copper = row.copper + copper - row.highlightAnimation:Stop() - row.highlightAnimation:Play() + new = false + row.meta = { ... } + text = textFn(row.amount, row.link) + row.amount = row.amount + quantity + if not G_RLF.db.global.disableRowHighlight then + row.highlightAnimation:Stop() + row.highlightAnimation:Play() + end + if row.fadeOutAnimation:IsPlaying() then + row.fadeOutAnimation:Stop() + row.fadeOutAnimation:Play() + end else + -- New row row = leaseRow(key) if row == nil then + tinsert(overflowQueue, { ... }) return end - -- Initialize row content - rowMoneyStyles(row) - row.copper = copper + row.meta = { ... } + row.amount = quantity + rowStyles(row, icon) + if isLink then + local extraWidth = getTextWidth(" x" .. row.amount) + row.link = truncateItemLink(textFn(), extraWidth) + text = textFn(0, row.link) + + if icon then + if Masque and iconGroup then + if logType == "ItemLoot" then + row.icon:SetItem(row.link) + else + local quality = C_CurrencyInfo.GetCurrencyInfo(key).quality + row.icon:SetItemButtonTexture(icon) + row.icon:SetItemButtonQuality(quality, row.link) + end + else + row.icon:SetTexture(icon) + end + end + -- Add Tooltip + row.amountText:SetScript("OnEnter", function() + row.fadeOutAnimation:Stop() + row.highlightAnimation:Stop() + row.highlightBorder:SetAlpha(0) + if not G_RLF.db.global.tooltip then + return + end + if G_RLF.db.global.tooltipOnShift and not IsShiftKeyDown() then + return + end + local inCombat = UnitAffectingCombat("player") + if inCombat then + GameTooltip:Hide() + return + end + GameTooltip:SetOwner(row.amountText, "ANCHOR_RIGHT") + GameTooltip:SetHyperlink(row.link) -- Use the item's link to show the tooltip + GameTooltip:Show() + end) + row.amountText:SetScript("OnLeave", function() + row.fadeOutAnimation:Play() + GameTooltip:Hide() + end) + else + text = textFn() + end end - - text = C_CurrencyInfo.GetCoinTextureString(row.copper) row.amountText:SetText(text) - - row.fadeOutAnimation:Stop() - row.fadeOutAnimation:Play() -end - -function LootDisplay:ShowXP(experience) - local key = "EXPERIENCE" -- Use ID as a unique key - local text - - -- Check if the item or currency is already displayed - local row = getRow(key) - if row then - -- Update existing entry - row.experience = row.experience + experience - row.highlightAnimation:Stop() - row.highlightAnimation:Play() + if r == nil and g == nil and b == nil and row.amount ~= nil and row.amount < 0 then + r, g, b, a = 1, 0, 0, 0.8 else - row = leaseRow(key) - if row == nil then - return - end - - -- Initialize row content - rowMoneyStyles(row) - row.experience = experience + r, g, b, a = r or rD, g or gD, b or bD, a or aD end - - text = "+" .. row.experience .. " " .. G_RLF.L["XP"] - row.amountText:SetText(text) - row.amountText:SetTextColor(1, 0, 1, 0.8) - + row.amountText:SetTextColor(r, g, b, a) + local amountLogText = row.amount + if not new then + amountLogText = format("%s (+%s)", row.amount, quantity) + end + LootDisplay:getLogger():Info(logType .. " Shown", G_RLF.addonName, logType, key, text, amountLogText, new) row.fadeOutAnimation:Stop() row.fadeOutAnimation:Play() end -function LootDisplay:ShowRep(rep, factionName, r, g, b) - local key = "REP_" .. factionName -- Use ID as a unique key - local text - - -- Check if the item or currency is already displayed - local row = getRow(key) - if row then - -- Update existing entry - row.rep = row.rep + rep - row.highlightAnimation:Stop() - row.highlightAnimation:Play() - else - row = leaseRow(key) - if row == nil then - return +processFromQueue = function() + local snapshotQueueSize = #overflowQueue + if snapshotQueueSize > 0 then + -- error("Test") + local rowsToProcess = math.min(snapshotQueueSize, config.maxRows) + LootDisplay:getLogger():Debug("Processing " .. rowsToProcess .. " items from overflow queue", G_RLF.addonName) + for i = 1, math.min(snapshotQueueSize, config.maxRows) do + -- Get the first set of args from the queue + local args = tremove(overflowQueue, 1) -- Remove and return the first element + -- Call processRow with the unpacked arguments + processRow(unpack(args)) end - - -- Initialize row content - rowMoneyStyles(row) - row.rep = rep - end - local sign = "+" - if rep < 0 then - sign = "-" end - text = sign .. math.abs(row.rep) .. " " .. factionName - row.amountText:SetText(text) - local r, g, b = r or 0.5, g or 0.5, b or 1 - row.amountText:SetTextColor(r, g, b, 1) - - row.fadeOutAnimation:Stop() - row.fadeOutAnimation:Play() end function LootDisplay:HideLoot() @@ -353,48 +363,7 @@ rowIcon = function(row) row.icon:Show() end -rowMoneyIcon = function(row) - if row.icon == nil then - if Masque and iconGroup then - row.icon = CreateFrame("ItemButton", nil, row) - iconGroup:AddButton(row.icon) - else - row.icon = row:CreateTexture(nil, "ARTWORK") - end - else - row.icon:ClearAllPoints() - end - row.icon:SetSize(config.iconSize, config.iconSize) - local anchor = "LEFT" - local xOffset = config.iconSize / 4 - if G_RLF.db.global.leftAlign == false then - anchor = "RIGHT" - xOffset = xOffset * -1 - end - row.icon:SetPoint(anchor, xOffset, 0) - row.icon:Hide() -end - -local defaultColor -rowMoneyText = function(row) - if row.amountText == nil then - row.amountText = row:CreateFontString(nil, "ARTWORK") - if not defaultColor then - local r, g, b, a = row.amountText:GetTextColor() - defaultColor = { r, g, b, a } - end - else - row.amountText:ClearAllPoints() - end - local anchor = "LEFT" - if G_RLF.db.global.leftAlign == false then - anchor = "RIGHT" - end - row.amountText:SetFontObject(config.font) - row.amountText:SetPoint(anchor, row.icon, anchor, 0, 0) -end - -rowAmountText = function(row) +rowAmountText = function(row, icon) if row.amountText == nil then row.amountText = row:CreateFontString(nil, "ARTWORK") if not defaultColor then @@ -413,7 +382,11 @@ rowAmountText = function(row) xOffset = xOffset * -1 end row.amountText:SetFontObject(config.font) - row.amountText:SetPoint(anchor, row.icon, iconAnchor, xOffset, 0) + if icon then + row.amountText:SetPoint(anchor, row.icon, iconAnchor, xOffset, 0) + else + row.amountText:SetPoint(anchor, row.icon, anchor, 0, 0) + end end rowFadeOutAnimation = function(row) @@ -471,33 +444,21 @@ rowHighlightBorder = function(row) end end -rowMoneyStyles = function(row) +rowStyles = function(row, icon) row:SetSize(config.feedWidth, config.rowHeight) - - rowBackground(row) - rowMoneyIcon(row) - rowHighlightBorder(row) - rowMoneyText(row) - rowFadeOutAnimation(row) -end - -rowStyles = function(row) - row:SetSize(config.feedWidth, config.rowHeight) - rowBackground(row) rowIcon(row) + if not icon then + row.icon:Hide() + end rowHighlightBorder(row) - rowAmountText(row) + rowAmountText(row, icon) rowFadeOutAnimation(row) end -applyRowStyles = function(row) - if row.copper ~= nil or row.experience ~= nil or row.rep ~= nil then - rowMoneyStyles(row) - else - rowStyles(row) - end - if iconGroup then +applyRowStyles = function(row, icon) + rowStyles(row, icon) + if icon and iconGroup then iconGroup:ReSkin(row.icon) end end @@ -506,7 +467,12 @@ updateRowPositions = function() local index = 0 for row in rows:iterate() do if row:IsShown() then - applyRowStyles(row) + local icon + if row.meta then + local _, _, ic = unpack(row.meta) + icon = ic + end + applyRowStyles(row, icon) row:ClearAllPoints() local vertDir = "BOTTOM" local yOffset = index * (config.rowHeight + config.padding) @@ -585,13 +551,13 @@ local function createArrow(f, direction) arrow:SetRotation(0) elseif direction == "DOWN" then arrow:SetPoint("BOTTOM", f, "BOTTOM", 0, 20) - arrow:SetRotation(math.pi) -- Rotate 180 degrees + arrow:SetRotation(math.pi) elseif direction == "LEFT" then arrow:SetPoint("LEFT", f, "LEFT", 20, 0) - arrow:SetRotation(math.pi * 0.5) -- Rotate 270 degrees + arrow:SetRotation(math.pi * 0.5) elseif direction == "RIGHT" then arrow:SetPoint("RIGHT", f, "RIGHT", -20, 0) - arrow:SetRotation(math.pi * 1.5) -- Rotate 90 degrees + arrow:SetRotation(math.pi * 1.5) end arrow:Hide() @@ -657,10 +623,8 @@ leaseRow = function(key) row = tremove(rowFramePool) row:ClearAllPoints() row.amount = nil - row.copper = nil row.link = nil - row.experience = nil - row.rep = nil + row.meta = nil if row.highlightBorder then row.highlightBorder:SetAlpha(0) end @@ -700,4 +664,5 @@ end returnRow = function(row) row:Hide() tinsert(rowFramePool, row) + LootDisplay:SendMessage("RLF_LootDisplay_RowReturned") end diff --git a/RPGLootFeed.lua b/RPGLootFeed.lua index 6560684..dd433ad 100644 --- a/RPGLootFeed.lua +++ b/RPGLootFeed.lua @@ -1,12 +1,10 @@ local addonName = G_RLF.addonName local acd = LibStub("AceConfigDialog-3.0") RLF = G_RLF.RLF -G_RLF.L = LibStub("AceLocale-3.0"):GetLocale(G_RLF.localeName) function RLF:OnInitialize() G_RLF.db = LibStub("AceDB-3.0"):New(G_RLF.dbName, G_RLF.defaults, true) LibStub("AceConfig-3.0"):RegisterOptionsTable(addonName, G_RLF.options) - G_RLF.LootDisplay:Initialize() self:Hook(acd, "Open", "OnOptionsOpen") self:RegisterEvent("PLAYER_ENTERING_WORLD") self:RegisterChatCommand("rlf", "SlashCommand") @@ -30,6 +28,8 @@ function RLF:SlashCommand(msg, editBox) G_RLF.TestMode:ToggleTestMode() elseif msg == "clear" then G_RLF.LootDisplay:HideLoot() + elseif msg == "log" then + self:GetModule("Logger"):Show() else acd:Open(addonName) end diff --git a/RPGLootFeed.toc b/RPGLootFeed.toc index b1dbd89..ce2c1da 100644 --- a/RPGLootFeed.toc +++ b/RPGLootFeed.toc @@ -19,13 +19,12 @@ DoubleLinkedList.lua locale/locales.xml -Features/features.xml - BlizzOverrides/overrides.xml -RPGLootFeed.lua - config/config.xml +RPGLootFeed.lua +Logger.lua +Features/features.xml TestMode.lua LootDisplay.lua diff --git a/TestMode.lua b/TestMode.lua index 7427d84..a5d8335 100644 --- a/TestMode.lua +++ b/TestMode.lua @@ -1,5 +1,7 @@ TestMode = {} +local logger + local function idExistsInTable(id, table) for _, item in pairs(table) do if item.id == id then @@ -10,20 +12,7 @@ local function idExistsInTable(id, table) end -- Initial test items with color variables -local testItemIds = { - 50818, - 2589, - 2592, - 1515, - 730, - 19019, - 128507, - 132842, - 23538, - 11754, - 128827, - 219325, -} +local testItemIds = { 50818, 2589, 2592, 1515, 730, 19019, 128507, 132842, 23538, 11754, 128827, 219325 } local testItems = {} local function initializeTestItems() @@ -42,23 +31,7 @@ local function initializeTestItems() end end -local testCurrencyIds = { - 2245, - 1191, - 1828, - 1792, - 1755, - 1580, - 1273, - 1166, - 515, - 241, - 1813, - 2778, - 3089, - 1101, - 1704, -} +local testCurrencyIds = { 2245, 1191, 1828, 1792, 1755, 1580, 1273, 1166, 515, 241, 1813, 2778, 3089, 1101, 1704 } local testCurrencies = {} local function initializeTestCurrencies() @@ -77,6 +50,12 @@ local function initializeTestCurrencies() end end +local testFactions = { + "Undercity", + "Thunder Bluff", + "Orgrimmar", +} + local function generateRandomLoot() if #testItems ~= #testItemIds then initializeTestItems() @@ -86,25 +65,45 @@ local function generateRandomLoot() initializeTestCurrencies() end -- Randomly decide whether to generate an item or currency - local rng = math.random() - if rng < 0.8 then - -- Generate random item - local item = testItems[math.random(#testItems)] - local amountLooted = math.random(1, 5) - G_RLF.LootDisplay:ShowLoot(item.id, item.link, item.icon, amountLooted) - if rng < 0.1 then + local numberOfRowsToGenerate = math.random(1, 5) + for i = 1, numberOfRowsToGenerate do + local rng = math.random() + + if rng >= 0.8 then + local experienceGained = math.random(100, 10000) + G_RLF.LootDisplay:ShowLoot("Experience", experienceGained) + end + + if rng <= 0.2 then local copper = math.random(1, 100000000) - G_RLF.LootDisplay:ShowMoney(copper) + G_RLF.LootDisplay:ShowLoot("Money", copper) + end + + -- 50% chance to show items + if rng > 0.2 and rng <= 0.7 then + local item = testItems[math.random(#testItems)] + local amountLooted = math.random(1, 5) + G_RLF.LootDisplay:ShowLoot("ItemLoot", item.id, item.link, item.icon, amountLooted) + + -- 15% chance to show currency + elseif rng > 0.7 and rng <= 0.85 then + local currency = testCurrencies[math.random(#testCurrencies)] + local amountLooted = math.random(1, 500) + G_RLF.LootDisplay:ShowLoot("Currency", currency.id, currency.link, currency.icon, amountLooted) + + -- 10% chance to show reputation (least frequent) + elseif rng > 0.85 then + local reputationGained = math.random(10, 100) + local factionName = testFactions[math.random(#testFactions)] + G_RLF.LootDisplay:ShowLoot("Reputation", reputationGained, factionName) end - else - -- Generate random currency - local currency = testCurrencies[math.random(#testCurrencies)] - local amountLooted = math.random(1, 500) - G_RLF.LootDisplay:ShowLoot(currency.id, currency.link, currency.icon, amountLooted) end end function TestMode:ToggleTestMode() + if not logger then + logger = G_RLF.RLF:GetModule("Logger") + end if self.testMode then -- Stop test mode self.testMode = false @@ -113,10 +112,12 @@ function TestMode:ToggleTestMode() self.testTimer = nil end G_RLF:Print(G_RLF.L["Test Mode Disabled"]) + logger:Debug("Test Mode Disabled", G_RLF.addonName) else -- Start test mode self.testMode = true G_RLF:Print(G_RLF.L["Test Mode Enabled"]) + logger:Debug("Test Mode Enabled", G_RLF.addonName) self.testTimer = C_Timer.NewTicker(1.5, function() G_RLF:fn(generateRandomLoot) end) diff --git a/config/ConfigOptions.lua b/config/ConfigOptions.lua index b682cab..3f0b8ef 100644 --- a/config/ConfigOptions.lua +++ b/config/ConfigOptions.lua @@ -2,7 +2,12 @@ local ConfigOptions = {} G_RLF.defaults = { profile = {}, - global = {}, + global = { + logger = { + sessionsLogged = 0, + logs = {}, + }, + }, } G_RLF.options = { diff --git a/config/Sizing.lua b/config/Sizing.lua index 9304b3c..f5689b5 100644 --- a/config/Sizing.lua +++ b/config/Sizing.lua @@ -27,8 +27,9 @@ G_RLF.options.args.sizing = { type = "range", name = G_RLF.L["Maximum Rows to Display"], desc = G_RLF.L["MaxRowsDesc"], - min = 10, - max = 1000, + min = 1, + softMin = 3, + max = 20, step = 1, bigStep = 5, get = "GetMaxRows", diff --git a/config/Styling.lua b/config/Styling.lua index 0922226..91ea041 100644 --- a/config/Styling.lua +++ b/config/Styling.lua @@ -4,6 +4,7 @@ G_RLF.defaults.global.leftAlign = true G_RLF.defaults.global.growUp = true G_RLF.defaults.global.rowBackgroundGradientStart = { 0.1, 0.1, 0.1, 0.8 } -- Default to dark grey with 80% opacity G_RLF.defaults.global.rowBackgroundGradientEnd = { 0.1, 0.1, 0.1, 0 } -- Default to dark grey with 0% opacity +G_RLF.defaults.global.disableRowHighlight = false G_RLF.defaults.global.font = "GameFontNormalSmall" G_RLF.options.args.styles = { @@ -49,6 +50,15 @@ G_RLF.options.args.styles = { set = "SetGradientEndColor", order = 4, }, + rowHighlight = { + type = "toggle", + name = G_RLF.L["Disable Row Highlight"], + desc = G_RLF.L["DisableRowHighlightDesc"], + width = "double", + get = "GetRowHighlight", + set = "SetRowHighlight", + order = 5, + }, font = { type = "select", name = G_RLF.L["Font"], @@ -57,7 +67,7 @@ G_RLF.options.args.styles = { values = "GetFonts", get = "GetRowFont", set = "SetRowFont", - order = 5, + order = 6, }, }, } @@ -117,6 +127,14 @@ function Styling:SetGrowUp(info, value) G_RLF.LootDisplay:UpdateRowPositions() end +function Styling:GetRowHighlight(info, value) + return G_RLF.db.global.disableRowHighlight +end + +function Styling:SetRowHighlight(info, value) + G_RLF.db.global.disableRowHighlight = value +end + function Styling:SetRowFont(info, value) G_RLF.db.global.font = value G_RLF.LootDisplay:UpdateRowStyles() diff --git a/embeds.xml b/embeds.xml index ef3512a..95aa53d 100644 --- a/embeds.xml +++ b/embeds.xml @@ -10,4 +10,5 @@ + diff --git a/locale/enUS.lua b/locale/enUS.lua index 286c0e2..1bea837 100644 --- a/locale/enUS.lua +++ b/locale/enUS.lua @@ -120,6 +120,8 @@ L["Background Gradient Start"] = true L["GradientStartDesc"] = "The start color of the row background gradient." L["Background Gradient End"] = true L["GradientEndDesc"] = "The end color of the row background gradient." +L["Disable Row Highlight"] = true +L["DisableRowHighlightDesc"] = "If checked, don't highlight a row when you loot the same item again and the quanity is updated." L["Font"] = true L["FontDesc"] = "The font object for the loot text." diff --git a/locale/locales.xml b/locale/locales.xml index 1b717fb..4d381a3 100644 --- a/locale/locales.xml +++ b/locale/locales.xml @@ -15,4 +15,5 @@