diff --git a/Core/DevTools.lua b/Core/DevTools.lua index 5df2382..fce4776 100644 --- a/Core/DevTools.lua +++ b/Core/DevTools.lua @@ -5,7 +5,7 @@ if not HMGT then return end local L = HMGT.L or LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME) HMGT.devToolsBuffer = HMGT.devToolsBuffer or {} -HMGT.devToolsBufferMax = HMGT.devToolsBufferMax or 300 +HMGT.devToolsBufferMax = HMGT.devToolsBufferMax or 500 local DEVTOOLS_SCOPE_ALL = "ALL" local DEVTOOLS_SCOPE_LABELS = { @@ -20,7 +20,8 @@ local DEVTOOLS_SCOPE_LABELS = { local DEVTOOLS_LEVELS = { error = 1, - trace = 2, + info = 2, + verbose = 3, } local function TrimText(value) @@ -76,8 +77,10 @@ function HMGT:GetDevToolsSettings() profile.devTools = type(profile.devTools) == "table" and profile.devTools or {} local settings = profile.devTools settings.enabled = settings.enabled == true - if settings.level ~= "error" and settings.level ~= "trace" then - settings.level = "error" + if settings.level == "trace" then + settings.level = "verbose" + elseif settings.level ~= "error" and settings.level ~= "info" and settings.level ~= "verbose" then + settings.level = "info" end if type(settings.scope) ~= "string" or settings.scope == "" then settings.scope = DEVTOOLS_SCOPE_ALL @@ -94,24 +97,25 @@ function HMGT:IsDevToolsEnabled() end function HMGT:GetDevToolsLevelOptions() - return { - error = L["OPT_DEVTOOLS_LEVEL_ERROR"] or "Errors", - trace = L["OPT_DEVTOOLS_LEVEL_TRACE"] or "Trace", - } + return self:GetDebugLevelOptions() end function HMGT:GetConfiguredDevToolsLevel() - return self:GetDevToolsSettings().level or "error" + return self:GetConfiguredDebugLevel() end function HMGT:ShouldIncludeDevToolsLevel(level) local configured = self:GetConfiguredDevToolsLevel() - return (DEVTOOLS_LEVELS[tostring(level or "error")] or DEVTOOLS_LEVELS.error) - <= (DEVTOOLS_LEVELS[configured] or DEVTOOLS_LEVELS.error) + local normalizedLevel = tostring(level or "info") + if normalizedLevel == "trace" then + normalizedLevel = "verbose" + end + return (DEVTOOLS_LEVELS[normalizedLevel] or DEVTOOLS_LEVELS.info) + <= (DEVTOOLS_LEVELS[configured] or DEVTOOLS_LEVELS.info) end function HMGT:GetDevToolsScopeOptions() - local values = { + local values = self:GetDebugScopeOptions() or { [DEVTOOLS_SCOPE_ALL] = L["OPT_DEVTOOLS_SCOPE_ALL"] or "All scopes", } for scope, label in pairs(DEVTOOLS_SCOPE_LABELS) do @@ -128,8 +132,11 @@ end function HMGT:FormatDevToolsEntry(entry) local stamp = tostring(entry and entry.stamp or date("%H:%M:%S")) - local level = string.upper(tostring(entry and entry.level or "error")) + local level = string.upper(tostring(entry and entry.level or "info")) local scope = tostring(entry and entry.scope or "System") + if entry and entry.kind == "debug" then + return string.format("%s [%s][%s] %s", stamp, level, scope, tostring(entry.message or "")) + end local eventName = tostring(entry and entry.event or "") local payload = TrimText(entry and entry.payload or "") if payload ~= "" then @@ -164,8 +171,10 @@ function HMGT:RecordDevEvent(level, scope, eventName, payload) end local normalizedLevel = tostring(level or "error") - if normalizedLevel ~= "error" and normalizedLevel ~= "trace" then - normalizedLevel = "trace" + if normalizedLevel == "trace" then + normalizedLevel = "verbose" + elseif normalizedLevel ~= "error" and normalizedLevel ~= "info" and normalizedLevel ~= "verbose" then + normalizedLevel = "verbose" end if not self:ShouldIncludeDevToolsLevel(normalizedLevel) then return @@ -182,6 +191,7 @@ function HMGT:RecordDevEvent(level, scope, eventName, payload) scope = normalizedScope, event = TrimText(eventName or "event"), payload = EncodePayloadValue(payload, 0), + kind = "event", } table.insert(self.devToolsBuffer, entry) @@ -194,6 +204,40 @@ function HMGT:RecordDevEvent(level, scope, eventName, payload) end end +function HMGT:RecordDebugEntry(level, scope, message) + if not self:IsDevToolsEnabled() then + return + end + + local normalizedLevel = tostring(level or "info") + if normalizedLevel == "trace" then + normalizedLevel = "verbose" + elseif normalizedLevel ~= "error" and normalizedLevel ~= "info" and normalizedLevel ~= "verbose" then + normalizedLevel = "info" + end + + local normalizedScope = TrimText(scope or "General") + if normalizedScope == "" then + normalizedScope = "General" + end + + self.devToolsBuffer = self.devToolsBuffer or {} + self.devToolsBuffer[#self.devToolsBuffer + 1] = { + stamp = date("%H:%M:%S"), + level = normalizedLevel, + scope = normalizedScope, + message = TrimText(message or ""), + kind = "debug", + } + while #self.devToolsBuffer > (tonumber(self.devToolsBufferMax) or 500) do + table.remove(self.devToolsBuffer, 1) + end + + if self.devToolsWindow and self.devToolsWindow:IsShown() and self.RefreshDevToolsWindow then + self:RefreshDevToolsWindow() + end +end + function HMGT:DevError(scope, eventName, payload) self:RecordDevEvent("error", scope, eventName, payload) end diff --git a/Core/DevToolsWindow.lua b/Core/DevToolsWindow.lua index 610a35e..58a3d5a 100644 --- a/Core/DevToolsWindow.lua +++ b/Core/DevToolsWindow.lua @@ -7,7 +7,7 @@ local AceGUI = LibStub("AceGUI-3.0", true) if not AceGUI then return end local function GetOrderedLevels() - return { "error", "trace" } + return { "error", "info", "verbose" } end local function GetOrderedScopes() @@ -78,8 +78,8 @@ function HMGT:EnsureDevToolsWindow() local settings = self:GetDevToolsSettings() local window = self:CreateAceWindow("devTools", { - title = L["DEVTOOLS_WINDOW_TITLE"] or "HMGT Developer Tools", - statusText = L["DEVTOOLS_WINDOW_HINT"] or "Structured developer events for the current session", + title = L["DEVTOOLS_WINDOW_TITLE"] or "HMGT Debug Console", + statusText = L["DEVTOOLS_WINDOW_HINT"] or "Debug and developer events for the current session", statusTable = settings.window, width = settings.window.width or 920, height = settings.window.height or 420, @@ -93,7 +93,7 @@ function HMGT:EnsureDevToolsWindow() local content = window:GetContent() local clearButton = AceGUI:Create("Button") - clearButton:SetText(L["OPT_DEVTOOLS_CLEAR"] or "Clear developer log") + clearButton:SetText(L["OPT_DEVTOOLS_CLEAR"] or L["OPT_DEBUG_CLEAR"] or "Clear log") clearButton:SetWidth(140) clearButton:SetCallback("OnClick", function() HMGT:ClearDevToolsLog() @@ -176,11 +176,11 @@ function HMGT:RefreshDevToolsWindow() end local levelOptions = self:GetDevToolsLevelOptions() - SetFilterButtonText(window.levelFilter, L["OPT_DEVTOOLS_LEVEL"] or "Capture level", levelOptions[self:GetConfiguredDevToolsLevel()]) + SetFilterButtonText(window.levelFilter, L["OPT_DEBUG_LEVEL"] or L["OPT_DEVTOOLS_LEVEL"] or "Level", levelOptions[self:GetConfiguredDevToolsLevel()]) local scopeValues = self:GetDevToolsScopeOptions() local currentScope = self:GetDevToolsSettings().scope or "ALL" - SetFilterButtonText(window.scopeFilter, L["OPT_DEVTOOLS_SCOPE"] or "Scope", scopeValues[currentScope] or currentScope) + SetFilterButtonText(window.scopeFilter, L["OPT_DEBUG_SCOPE"] or L["OPT_DEVTOOLS_SCOPE"] or "Module", scopeValues[currentScope] or currentScope) local text = table.concat(self:GetFilteredDevToolsLines(), "\n") window.logWidget:SetText(text) diff --git a/HailMaryGuildTools.lua b/HailMaryGuildTools.lua index 1c62c4d..e422c33 100644 --- a/HailMaryGuildTools.lua +++ b/HailMaryGuildTools.lua @@ -89,11 +89,9 @@ HMGT.MSG_RAID_TIMELINE_TEST = MSG_RAID_TIMELINE_TEST -- ── Standardwerte ───────────────────────────────────────────── local defaults = { profile = { - debug = false, - debugLevel = "info", devTools = { enabled = false, - level = "error", + level = "info", scope = "ALL", window = { width = 920, @@ -102,131 +100,6 @@ local defaults = { }, }, syncRemoteCharges = true, - interruptTracker = { - enabled = true, - demoMode = false, - testMode = false, - showBar = true, - showSpellTooltip = true, - locked = false, - posX = 200, - posY = -200, - anchorTo = "UIParent", - anchorCustom = "", - anchorPoint = "TOPLEFT", - anchorRelPoint= "TOPLEFT", - anchorX = 200, - anchorY = -200, - width = 250, - barHeight = 20, - barSpacing = 2, - barTexture = "Blizzard", - borderEnabled = false, - borderColor = { r = 1, g = 1, b = 1, a = 1 }, - iconSize = 32, - iconSpacing = 2, - iconCols = 6, - iconOverlay = "sweep", -- "sweep" | "timer" - textAnchor = "below", -- "onIcon" | "above" | "below" - fontSize = 12, - font = "Friz Quadrata TT", - fontOutline = "OUTLINE", - growDirection = "DOWN", - showInSolo = true, - showInGroup = true, - showInRaid = true, - enabledSpells = {}, - showPlayerName= true, - colorByClass = true, - showChargesOnIcon = false, - showOnlyReady = false, - readySoonSec = 0, - }, - raidCooldownTracker = { - enabled = true, - demoMode = false, - testMode = false, - showBar = true, - showSpellTooltip = true, - locked = false, - posX = 500, - posY = -200, - anchorTo = "UIParent", - anchorCustom = "", - anchorPoint = "TOPLEFT", - anchorRelPoint= "TOPLEFT", - anchorX = 500, - anchorY = -200, - width = 250, - barHeight = 20, - barSpacing = 2, - barTexture = "Blizzard", - borderEnabled = false, - borderColor = { r = 1, g = 1, b = 1, a = 1 }, - iconSize = 32, - iconSpacing = 2, - iconCols = 6, - iconOverlay = "sweep", -- "sweep" | "timer" - textAnchor = "below", -- "onIcon" | "above" | "below" - fontSize = 12, - font = "Friz Quadrata TT", - fontOutline = "OUTLINE", - growDirection = "DOWN", - showInSolo = true, - showInGroup = true, - showInRaid = true, - enabledSpells = {}, - showPlayerName= true, - colorByClass = true, - showChargesOnIcon = false, - showOnlyReady = false, - readySoonSec = 0, - }, - groupCooldownTracker = { - enabled = true, - demoMode = false, - testMode = false, - showBar = true, - showSpellTooltip = true, - locked = false, - attachToPartyFrame = false, - partyAttachSide = "RIGHT", - partyAttachOffsetX = 8, - partyAttachOffsetY = 0, - posX = 800, - posY = -200, - anchorTo = "UIParent", - anchorCustom = "", - anchorPoint = "TOPLEFT", - anchorRelPoint= "TOPLEFT", - anchorX = 800, - anchorY = -200, - width = 250, - barHeight = 20, - barSpacing = 2, - barTexture = "Blizzard", - borderEnabled = false, - borderColor = { r = 1, g = 1, b = 1, a = 1 }, - iconSize = 32, - iconSpacing = 2, - iconCols = 6, - iconOverlay = "sweep", - textAnchor = "below", - fontSize = 12, - font = "Friz Quadrata TT", - fontOutline = "OUTLINE", - growDirection = "DOWN", - showInSolo = false, - showInGroup = true, - showInRaid = false, - enabledSpells = {}, - showPlayerName= true, - colorByClass = true, - showChargesOnIcon = true, - showOnlyReady = false, - readySoonSec = 0, - includeSelfFrame = false, - }, trackers = {}, buffEndingAnnouncer = { enabled = true, @@ -291,8 +164,8 @@ HMGT.demoModeData = {} HMGT.versionWarnings = {} HMGT.versionWhisperWarnings = {} HMGT.playerStatus = {} -HMGT.debugBuffer = {} -HMGT.debugBufferMax = 500 +HMGT.devToolsBuffer = HMGT.devToolsBuffer or {} +HMGT.devToolsBufferMax = HMGT.devToolsBufferMax or 500 HMGT.enabledDebugScopes = { General = true, Debug = true, @@ -332,7 +205,8 @@ local DEBUG_LEVELS = { function HMGT:IsDebugScopeEnabled(scope) local normalizedScope = tostring(scope or "General") - local selectedScope = self.db and self.db.profile and self.db.profile.debugScope or DEBUG_SCOPE_ALL + local settings = self.GetDevToolsSettings and self:GetDevToolsSettings() or nil + local selectedScope = settings and settings.scope or DEBUG_SCOPE_ALL if selectedScope and selectedScope ~= DEBUG_SCOPE_ALL and normalizedScope ~= selectedScope then return false end @@ -496,7 +370,11 @@ function HMGT:GetDebugLevelOptions() end function HMGT:GetConfiguredDebugLevel() - local configured = self.db and self.db.profile and self.db.profile.debugLevel or "info" + local settings = self.GetDevToolsSettings and self:GetDevToolsSettings() or nil + local configured = settings and settings.level or "info" + if configured == "trace" then + configured = "verbose" + end if DEBUG_LEVELS[configured] then return configured end @@ -524,9 +402,8 @@ function HMGT:GetDebugScopeOptions() for scope in pairs(self.enabledDebugScopes or {}) do addScope(scope) end - for _, line in ipairs(self.debugBuffer or {}) do - local scope = tostring(line):match("^%d%d:%d%d:%d%d %[[^%]]+%]%[([^%]]+)%]") - addScope(scope) + for _, entry in ipairs(self.devToolsBuffer or {}) do + addScope(entry and entry.scope) end local names = {} @@ -541,15 +418,19 @@ function HMGT:GetDebugScopeOptions() end function HMGT:GetFilteredDebugBuffer() - local selectedLevel = self:GetConfiguredDebugLevel() - local selectedScope = self.db and self.db.profile and self.db.profile.debugScope or DEBUG_SCOPE_ALL local filtered = {} - for _, line in ipairs(self.debugBuffer or {}) do - local level, scope = tostring(line):match("^%d%d:%d%d:%d%d %[([^%]]+)%]%[([^%]]+)%]") - local normalizedLevel = tostring(level or "INFO"):lower() + local settings = self.GetDevToolsSettings and self:GetDevToolsSettings() or nil + local selectedScope = settings and settings.scope or DEBUG_SCOPE_ALL + for _, entry in ipairs(self.devToolsBuffer or {}) do + local scope = tostring(entry and entry.scope or "General") + local level = tostring(entry and entry.level or "info") local scopeMatches = (not selectedScope or selectedScope == DEBUG_SCOPE_ALL or scope == selectedScope) - if scopeMatches and self:ShouldIncludeDebugLine(normalizedLevel) then - filtered[#filtered + 1] = line + if scopeMatches and self:ShouldIncludeDebugLine(level) then + if self.FormatDevToolsEntry then + filtered[#filtered + 1] = self:FormatDevToolsEntry(entry) + else + filtered[#filtered + 1] = tostring(entry and entry.message or "") + end end end return filtered @@ -877,17 +758,22 @@ function HMGT:DebugScoped(level, scope, fmt, ...) if not ok then message = tostring(fmt or "") end - local line = string.format("%s [%s][%s] %s", date("%H:%M:%S"), string.upper(normalizedLevel), normalizedScope, tostring(message or "")) - - self.debugBuffer = self.debugBuffer or {} - self.debugBuffer[#self.debugBuffer + 1] = line - local maxLines = tonumber(self.debugBufferMax) or 500 - while #self.debugBuffer > maxLines do - table.remove(self.debugBuffer, 1) + if self.RecordDebugEntry then + self:RecordDebugEntry(normalizedLevel, normalizedScope, tostring(message or "")) + return end - if self.debugWindow and self.debugWindow.IsShown and self.debugWindow:IsShown() and self.RefreshDebugWindow then - self:RefreshDebugWindow() + self.devToolsBuffer = self.devToolsBuffer or {} + self.devToolsBuffer[#self.devToolsBuffer + 1] = { + stamp = date("%H:%M:%S"), + level = normalizedLevel, + scope = normalizedScope, + message = tostring(message or ""), + kind = "debug", + } + local maxLines = tonumber(self.devToolsBufferMax) or 500 + while #self.devToolsBuffer > maxLines do + table.remove(self.devToolsBuffer, 1) end end @@ -1797,52 +1683,53 @@ end function HMGT:MigrateProfileSettings() local p = self.db and self.db.profile if not p then return end - p.debug = false - if p.debugLevel ~= "error" and p.debugLevel ~= "info" and p.debugLevel ~= "verbose" then - p.debugLevel = "info" - end - if type(p.debugScope) ~= "string" or p.debugScope == "" then - p.debugScope = DEBUG_SCOPE_ALL - end + local oldDebugEnabled = p.debug == true + local oldDebugLevel = p.debugLevel + local oldDebugScope = p.debugScope p.devTools = type(p.devTools) == "table" and p.devTools or {} - p.devTools.enabled = p.devTools.enabled == true - if p.devTools.level ~= "error" and p.devTools.level ~= "trace" then - p.devTools.level = "error" + p.devTools.enabled = p.devTools.enabled == true or oldDebugEnabled + if p.devTools.level == "trace" then + p.devTools.level = "verbose" + elseif p.devTools.level ~= "error" and p.devTools.level ~= "info" and p.devTools.level ~= "verbose" then + p.devTools.level = (oldDebugLevel == "error" or oldDebugLevel == "info" or oldDebugLevel == "verbose") + and oldDebugLevel + or "info" end if type(p.devTools.scope) ~= "string" or p.devTools.scope == "" then - p.devTools.scope = "ALL" + p.devTools.scope = (type(oldDebugScope) == "string" and oldDebugScope ~= "") and oldDebugScope or "ALL" end p.devTools.window = type(p.devTools.window) == "table" and p.devTools.window or {} p.devTools.window.width = math.max(720, tonumber(p.devTools.window.width) or 920) p.devTools.window.height = math.max(260, tonumber(p.devTools.window.height) or 420) p.devTools.window.minimized = p.devTools.window.minimized == true + p.debug = nil + p.debugLevel = nil + p.debugScope = nil p.syncRemoteCharges = true - if p.interruptTracker then - NormalizeBorderSettings(p.interruptTracker) - NormalizeAnchorSettings(p.interruptTracker) - NormalizeTrackerLayout(p.interruptTracker, false, true) - end - if p.raidCooldownTracker then - NormalizeBorderSettings(p.raidCooldownTracker) - NormalizeAnchorSettings(p.raidCooldownTracker) - NormalizeTrackerLayout(p.raidCooldownTracker, false, true) - end - if p.groupCooldownTracker then - NormalizeBorderSettings(p.groupCooldownTracker) - NormalizeAnchorSettings(p.groupCooldownTracker) - NormalizeTrackerLayout(p.groupCooldownTracker, true, true) - end - if type(p.trackers) ~= "table" then p.trackers = {} end if #p.trackers == 0 and p.trackerModelVersion ~= TRACKER_MODEL_VERSION then + local legacyInterrupt = type(p.interruptTracker) == "table" and p.interruptTracker or {} + local legacyRaid = type(p.raidCooldownTracker) == "table" and p.raidCooldownTracker or {} + local legacyGroup = type(p.groupCooldownTracker) == "table" and p.groupCooldownTracker or {} + + NormalizeBorderSettings(legacyInterrupt) + NormalizeAnchorSettings(legacyInterrupt) + NormalizeTrackerLayout(legacyInterrupt, false, true) + NormalizeBorderSettings(legacyRaid) + NormalizeAnchorSettings(legacyRaid) + NormalizeTrackerLayout(legacyRaid, false, true) + NormalizeBorderSettings(legacyGroup) + NormalizeAnchorSettings(legacyGroup) + NormalizeTrackerLayout(legacyGroup, true, true) + p.trackers = { - self:BuildTrackerConfigFromPreset("interruptTracker", 1, CopyTrackerFields({}, p.interruptTracker or {})), - self:BuildTrackerConfigFromPreset("raidCooldownTracker", 2, CopyTrackerFields({}, p.raidCooldownTracker or {})), - self:BuildTrackerConfigFromPreset("groupCooldownTracker", 3, CopyTrackerFields({}, p.groupCooldownTracker or {})), + self:BuildTrackerConfigFromPreset("interruptTracker", 1, CopyTrackerFields({}, legacyInterrupt)), + self:BuildTrackerConfigFromPreset("raidCooldownTracker", 2, CopyTrackerFields({}, legacyRaid)), + self:BuildTrackerConfigFromPreset("groupCooldownTracker", 3, CopyTrackerFields({}, legacyGroup)), } end @@ -1864,6 +1751,9 @@ function HMGT:MigrateProfileSettings() end p.trackers = normalizedTrackers p.trackerModelVersion = TRACKER_MODEL_VERSION + p.interruptTracker = nil + p.raidCooldownTracker = nil + p.groupCooldownTracker = nil p.mapOverlay = p.mapOverlay or {} NormalizeMapOverlaySettings(p.mapOverlay) @@ -2820,7 +2710,7 @@ end --- Gibt true zurück wenn ein Tracker laut seinen Einstellungen --- im aktuellen Gruppen-Kontext angezeigt werden soll. ---- @param settings table db.profile.interruptTracker / raidCooldownTracker +--- @param settings table tracker config from db.profile.trackers function HMGT:IsVisibleForCurrentGroup(settings) if not settings.enabled then return false end @@ -3056,6 +2946,116 @@ function HMGT:CreateLegacyMinimapButton() end end +local function CountTableEntries(tbl) + local count = 0 + for _ in pairs(tbl or {}) do + count = count + 1 + end + return count +end + +function HMGT:GetHealthStatusLines() + local lines = {} + lines[#lines + 1] = "HMGT status" + lines[#lines + 1] = string.format( + "Version: addon=%s build=%s channel=%s protocol=%s", + tostring(self.ADDON_VERSION or "dev"), + tostring(self.BUILD_VERSION or self.ADDON_VERSION or "dev"), + tostring(self.RELEASE_CHANNEL or "stable"), + tostring(self.PROTOCOL_VERSION or "?") + ) + + local groupType = "solo" + local groupMembers = 1 + if IsInRaid() then + groupType = "raid" + groupMembers = GetNumGroupMembers() + elseif IsInGroup() then + groupType = "party" + groupMembers = GetNumGroupMembers() + end + lines[#lines + 1] = string.format("Group: type=%s members=%d", groupType, tonumber(groupMembers) or 1) + + local trackers = self:GetTrackerConfigs() + local enabledTrackers = 0 + local normalTrackers = 0 + local groupTrackers = 0 + for _, tracker in ipairs(trackers) do + if tracker.enabled ~= false then + enabledTrackers = enabledTrackers + 1 + end + if self:IsGroupTrackerConfig(tracker) then + groupTrackers = groupTrackers + 1 + else + normalTrackers = normalTrackers + 1 + end + end + lines[#lines + 1] = string.format( + "Trackers: total=%d enabled=%d normal=%d group=%d model=%s", + #trackers, + enabledTrackers, + normalTrackers, + groupTrackers, + tostring(self.db and self.db.profile and self.db.profile.trackerModelVersion or "?") + ) + + local profile = self.db and self.db.profile or {} + local legacyCount = 0 + if profile.interruptTracker ~= nil then legacyCount = legacyCount + 1 end + if profile.raidCooldownTracker ~= nil then legacyCount = legacyCount + 1 end + if profile.groupCooldownTracker ~= nil then legacyCount = legacyCount + 1 end + lines[#lines + 1] = string.format("Legacy profile keys: %d", legacyCount) + + local devSettings = self.GetDevToolsSettings and self:GetDevToolsSettings() or {} + lines[#lines + 1] = string.format( + "Debug: enabled=%s level=%s scope=%s lines=%d", + tostring(devSettings.enabled == true), + tostring(devSettings.level or "info"), + tostring(devSettings.scope or "ALL"), + #(self.devToolsBuffer or {}) + ) + + local activeCooldownPlayers = CountTableEntries(self.activeCDs) + local playerDataCount = CountTableEntries(self.playerData) + lines[#lines + 1] = string.format( + "Tracker state: players=%d cooldownPlayers=%d pendingReliable=%d", + playerDataCount, + activeCooldownPlayers, + CountTableEntries(self.pendingReliableMessages) + ) + + local modules = { + Tracker = self.TrackerManager ~= nil, + AuraExpiry = self.AuraExpiry ~= nil, + MapOverlay = self.MapOverlay ~= nil, + RaidTimeline = self.RaidTimeline ~= nil, + Notes = self.Notes ~= nil, + } + local moduleParts = {} + for name, loaded in pairs(modules) do + moduleParts[#moduleParts + 1] = string.format("%s=%s", name, loaded and "loaded" or "missing") + end + table.sort(moduleParts) + lines[#lines + 1] = "Modules: " .. table.concat(moduleParts, ", ") + + local bridge = _G.HMGT_Bridge + lines[#lines + 1] = string.format("Bridge: %s", bridge and "loaded" or "not loaded") + if bridge and type(bridge.GetStatusLines) == "function" then + local statusLines = bridge:GetStatusLines() + for index = 1, math.min(3, #(statusLines or {})) do + lines[#lines + 1] = "Bridge " .. tostring(index) .. ": " .. tostring(statusLines[index]) + end + end + + return lines +end + +function HMGT:PrintHealthStatus() + for _, line in ipairs(self:GetHealthStatusLines()) do + self:Print(line) + end +end + function HMGT:SlashCommand(input) input = input:trim():lower() if input == "lock" then @@ -3092,6 +3092,8 @@ function HMGT:SlashCommand(input) else self:Print("HMGT Bridge is not loaded.") end + elseif input == "status" then + self:PrintHealthStatus() elseif input == "debug" then if self.ToggleDevToolsWindow then self:ToggleDevToolsWindow() diff --git a/HailMaryGuildToolsOptions.lua b/HailMaryGuildToolsOptions.lua index 8bc2d50..948bbef 100644 --- a/HailMaryGuildToolsOptions.lua +++ b/HailMaryGuildToolsOptions.lua @@ -1835,6 +1835,88 @@ function HMGT_Config:Initialize() end end, }, + devToolsEnabled = { + type = "toggle", + order = 2, + width = "full", + name = L["OPT_DEVTOOLS_MODE"] or L["OPT_DEBUG_MODE"] or "Debug console", + desc = L["OPT_DEVTOOLS_MODE_DESC"] or L["OPT_DEBUG_MODE_DESC"] or "Enable the debug console.", + get = function() + return HMGT.GetDevToolsSettings and HMGT:GetDevToolsSettings().enabled == true + end, + set = function(_, value) + if not HMGT.GetDevToolsSettings then + return + end + HMGT:GetDevToolsSettings().enabled = value == true + if HMGT.UpdateDevToolsWindowVisibility then + HMGT:UpdateDevToolsWindowVisibility() + end + end, + }, + debugLevel = { + type = "select", + order = 3, + width = "full", + name = L["OPT_DEBUG_LEVEL"] or "Debug level", + values = function() + return HMGT.GetDebugLevelOptions and HMGT:GetDebugLevelOptions() or {} + end, + get = function() + return HMGT.GetConfiguredDebugLevel and HMGT:GetConfiguredDebugLevel() or "info" + end, + set = function(_, value) + if HMGT.GetDevToolsSettings then + HMGT:GetDevToolsSettings().level = value or "info" + end + if HMGT.RefreshDevToolsWindow then + HMGT:RefreshDevToolsWindow() + end + end, + }, + debugScope = { + type = "select", + order = 4, + width = "full", + name = L["OPT_DEBUG_SCOPE"] or "Module filter", + values = function() + return HMGT.GetDebugScopeOptions and HMGT:GetDebugScopeOptions() or {} + end, + get = function() + local settings = HMGT.GetDevToolsSettings and HMGT:GetDevToolsSettings() or {} + return settings.scope or "ALL" + end, + set = function(_, value) + if HMGT.GetDevToolsSettings then + HMGT:GetDevToolsSettings().scope = value or "ALL" + end + if HMGT.RefreshDevToolsWindow then + HMGT:RefreshDevToolsWindow() + end + end, + }, + openDebug = { + type = "execute", + order = 5, + width = "half", + name = L["OPT_DEVTOOLS_OPEN"] or L["OPT_DEBUG_OPEN"] or "Open debug console", + func = function() + if HMGT.OpenDevToolsWindow then + HMGT:OpenDevToolsWindow() + end + end, + }, + clearDebug = { + type = "execute", + order = 6, + width = "half", + name = L["OPT_DEVTOOLS_CLEAR"] or L["OPT_DEBUG_CLEAR"] or "Clear debug log", + func = function() + if HMGT.ClearDevToolsLog then + HMGT:ClearDevToolsLog() + end + end, + }, }, }, commands = { @@ -1850,6 +1932,7 @@ function HMGT_Config:Initialize() name = table.concat({ "|cffffd100/hmgt|r", "|cffffd100/hmgt debug|r", + "|cffffd100/hmgt status|r", "|cffffd100/hmgt version|r", }, "\n"), }, diff --git a/Locales/deDE.lua b/Locales/deDE.lua index 5679e7f..6a6d0a8 100644 --- a/Locales/deDE.lua +++ b/Locales/deDE.lua @@ -64,15 +64,15 @@ L["OPT_DEBUG_CLEAR"] = "Debug-Log leeren" L["OPT_DEBUG_SELECT_ALL"] = "Alles markieren" L["DEBUG_WINDOW_TITLE"] = "HMGT Debug-Konsole" L["DEBUG_WINDOW_HINT"] = "Mit dem Mausrad scrollen, Strg+A markiert alles, Strg+C kopiert markierten Text" -L["OPT_DEVTOOLS_MODE"] = "Entwicklerwerkzeuge" -L["OPT_DEVTOOLS_MODE_DESC"] = "Aktiviert die strukturierte Entwickler-Konsole." -L["OPT_DEVTOOLS_LEVEL"] = "Erfassungsstufe" +L["OPT_DEVTOOLS_MODE"] = "Debug-Konsole" +L["OPT_DEVTOOLS_MODE_DESC"] = "Aktiviert das gemeinsame Debug- und Entwickler-Log." +L["OPT_DEVTOOLS_LEVEL"] = "Debug-Stufe" L["OPT_DEVTOOLS_LEVEL_ERROR"] = "Fehler" -L["OPT_DEVTOOLS_LEVEL_TRACE"] = "Trace" -L["OPT_DEVTOOLS_SCOPE"] = "Scope-Filter" -L["OPT_DEVTOOLS_SCOPE_ALL"] = "Alle Scopes" -L["OPT_DEVTOOLS_OPEN"] = "Entwickler-Konsole oeffnen" -L["OPT_DEVTOOLS_CLEAR"] = "Entwickler-Log leeren" +L["OPT_DEVTOOLS_LEVEL_TRACE"] = "Ausfuehrlich" +L["OPT_DEVTOOLS_SCOPE"] = "Modulfilter" +L["OPT_DEVTOOLS_SCOPE_ALL"] = "Alle Module" +L["OPT_DEVTOOLS_OPEN"] = "Debug-Konsole oeffnen" +L["OPT_DEVTOOLS_CLEAR"] = "Debug-Log leeren" L["OPT_DEVTOOLS_SELECT_ALL"] = "Alles markieren" L["OPT_DEVTOOLS_DISABLED"] = "HMGT: Entwicklerwerkzeuge sind nicht aktiviert." L["DEVTOOLS_WINDOW_TITLE"] = "HMGT Entwicklerwerkzeuge" diff --git a/Locales/enUS.lua b/Locales/enUS.lua index 068ce49..cad8f90 100644 --- a/Locales/enUS.lua +++ b/Locales/enUS.lua @@ -64,15 +64,15 @@ L["OPT_DEBUG_CLEAR"] = "Clear debug log" L["OPT_DEBUG_SELECT_ALL"] = "Select all" L["DEBUG_WINDOW_TITLE"] = "HMGT Debug Console" L["DEBUG_WINDOW_HINT"] = "Mouse wheel scrolls, Ctrl+A selects all, Ctrl+C copies selected text" -L["OPT_DEVTOOLS_MODE"] = "Developer tools" -L["OPT_DEVTOOLS_MODE_DESC"] = "Enable the structured developer event console." -L["OPT_DEVTOOLS_LEVEL"] = "Capture level" +L["OPT_DEVTOOLS_MODE"] = "Debug console" +L["OPT_DEVTOOLS_MODE_DESC"] = "Enable the shared debug and developer log." +L["OPT_DEVTOOLS_LEVEL"] = "Debug level" L["OPT_DEVTOOLS_LEVEL_ERROR"] = "Errors" -L["OPT_DEVTOOLS_LEVEL_TRACE"] = "Trace" -L["OPT_DEVTOOLS_SCOPE"] = "Scope filter" -L["OPT_DEVTOOLS_SCOPE_ALL"] = "All scopes" -L["OPT_DEVTOOLS_OPEN"] = "Open developer console" -L["OPT_DEVTOOLS_CLEAR"] = "Clear developer log" +L["OPT_DEVTOOLS_LEVEL_TRACE"] = "Verbose" +L["OPT_DEVTOOLS_SCOPE"] = "Module filter" +L["OPT_DEVTOOLS_SCOPE_ALL"] = "All modules" +L["OPT_DEVTOOLS_OPEN"] = "Open debug console" +L["OPT_DEVTOOLS_CLEAR"] = "Clear debug log" L["OPT_DEVTOOLS_SELECT_ALL"] = "Select all" L["OPT_DEVTOOLS_DISABLED"] = "HMGT: developer tools are not enabled." L["DEVTOOLS_WINDOW_TITLE"] = "HMGT Developer Tools" diff --git a/Modules/Tracker/GroupCooldownTracker/GroupCooldownTracker.lua b/Modules/Tracker/GroupCooldownTracker/GroupCooldownTracker.lua index dd91d9c..db5ad93 100644 --- a/Modules/Tracker/GroupCooldownTracker/GroupCooldownTracker.lua +++ b/Modules/Tracker/GroupCooldownTracker/GroupCooldownTracker.lua @@ -23,8 +23,12 @@ function module:GetDefinition() end function module:GetSettings() - local profile = HMGT.db and HMGT.db.profile - return profile and profile[self.definition.dbKey] or nil + for _, tracker in ipairs(HMGT:GetTrackerConfigs()) do + if tracker.trackerKey == self.definition.trackerKey then + return tracker + end + end + return nil end function module:Enable() diff --git a/Modules/Tracker/InterruptTracker/InterruptTracker.lua b/Modules/Tracker/InterruptTracker/InterruptTracker.lua index e9d3eea..81ff4b4 100644 --- a/Modules/Tracker/InterruptTracker/InterruptTracker.lua +++ b/Modules/Tracker/InterruptTracker/InterruptTracker.lua @@ -23,8 +23,12 @@ function module:GetDefinition() end function module:GetSettings() - local profile = HMGT.db and HMGT.db.profile - return profile and profile[self.definition.dbKey] or nil + for _, tracker in ipairs(HMGT:GetTrackerConfigs()) do + if tracker.trackerKey == self.definition.trackerKey then + return tracker + end + end + return nil end function module:Enable() diff --git a/Modules/Tracker/RaidcooldownTracker/RaidcooldownTracker.lua b/Modules/Tracker/RaidcooldownTracker/RaidcooldownTracker.lua index 7191632..4929241 100644 --- a/Modules/Tracker/RaidcooldownTracker/RaidcooldownTracker.lua +++ b/Modules/Tracker/RaidcooldownTracker/RaidcooldownTracker.lua @@ -23,8 +23,12 @@ function module:GetDefinition() end function module:GetSettings() - local profile = HMGT.db and HMGT.db.profile - return profile and profile[self.definition.dbKey] or nil + for _, tracker in ipairs(HMGT:GetTrackerConfigs()) do + if tracker.trackerKey == self.definition.trackerKey then + return tracker + end + end + return nil end function module:Enable() diff --git a/readme.md b/readme.md index 579c838..538809b 100644 --- a/readme.md +++ b/readme.md @@ -16,7 +16,6 @@ It combines cooldown tracking, encounter reminders, notes, and map utilities in - Per-tracker bar and icon layouts - Aura Expiry for selected buffs and channels - Raid Timeline for encounter-based text reminders and raid cooldown assignments -- Notes window for raid or personal note management - Map Overlay with custom world map POIs - Version mismatch detection inside groups and raids - Blizzard AddOn options integration with Ace3-based module configuration @@ -63,6 +62,8 @@ Provides a dedicated notes window for raid notes, personal notes, and drafts. Opens the developer tools window - `/hmgt dev` Alias for the developer tools window +- `/hmgt status` + Prints a compact addon health check - `/hmgt version` Opens the version window when developer tools are enabled