delted old debug window, added new version notice window, added new features to tracker module, updated locales, and updated main addon files.
This commit is contained in:
@@ -288,16 +288,20 @@ HMGT.powerTracking = {
|
||||
}
|
||||
HMGT.pendingSpellPowerCosts = {}
|
||||
HMGT.demoModeData = {}
|
||||
HMGT.peerVersions = {}
|
||||
HMGT.versionWarnings = {}
|
||||
HMGT.versionWhisperWarnings = {}
|
||||
HMGT.playerStatus = {}
|
||||
HMGT.debugBuffer = {}
|
||||
HMGT.debugBufferMax = 500
|
||||
HMGT.enabledDebugScopes = {
|
||||
General = true,
|
||||
Debug = true,
|
||||
Comm = true,
|
||||
TrackedSpells = true,
|
||||
TrackerCore = true,
|
||||
TrackerSync = true,
|
||||
TrackerUI = true,
|
||||
TrackerBridge = true,
|
||||
TrackerState = true,
|
||||
PowerSpend = true,
|
||||
}
|
||||
HMGT.pendingReliableMessages = HMGT.pendingReliableMessages or {}
|
||||
@@ -311,7 +315,11 @@ local DEBUG_SCOPE_LABELS = {
|
||||
General = "General",
|
||||
Debug = "Debug",
|
||||
Comm = "Communication",
|
||||
TrackedSpells = "Tracked Spells",
|
||||
TrackerCore = "Tracker Core",
|
||||
TrackerSync = "Tracker Sync",
|
||||
TrackerUI = "Tracker UI",
|
||||
TrackerBridge = "Tracker Bridge",
|
||||
TrackerState = "Tracker State",
|
||||
PowerSpend = "Power Spend",
|
||||
RaidTimeline = "Raid Timeline",
|
||||
Notes = "Notes",
|
||||
@@ -340,8 +348,12 @@ end
|
||||
|
||||
function HMGT:GetTrackerDebugScope(tracker)
|
||||
local trackerName = nil
|
||||
local trackerId = nil
|
||||
local trackerType = nil
|
||||
if type(tracker) == "table" then
|
||||
trackerName = tracker.name
|
||||
trackerId = tonumber(tracker.id)
|
||||
trackerType = tracker.trackerType
|
||||
if (not trackerName or trackerName == "") and tracker.id then
|
||||
trackerName = string.format("Tracker %s", tostring(tracker.id))
|
||||
end
|
||||
@@ -353,7 +365,106 @@ function HMGT:GetTrackerDebugScope(tracker)
|
||||
if trackerName == "" then
|
||||
trackerName = "Tracker"
|
||||
end
|
||||
return "Tracker: " .. trackerName
|
||||
local prefix = "Tracker"
|
||||
if trackerType == "group" then
|
||||
prefix = "Tracker Group"
|
||||
elseif trackerType == "normal" then
|
||||
prefix = "Tracker Normal"
|
||||
end
|
||||
if trackerId then
|
||||
return string.format("%s #%d: %s", prefix, trackerId, trackerName)
|
||||
end
|
||||
return prefix .. ": " .. trackerName
|
||||
end
|
||||
|
||||
function HMGT:GetPlayerStatus(playerName, create)
|
||||
local normalizedName = self:NormalizePlayerName(playerName)
|
||||
if not normalizedName or normalizedName == "" then
|
||||
return nil
|
||||
end
|
||||
self.playerStatus = self.playerStatus or {}
|
||||
if create then
|
||||
self.playerStatus[normalizedName] = self.playerStatus[normalizedName] or {}
|
||||
end
|
||||
return self.playerStatus[normalizedName]
|
||||
end
|
||||
|
||||
function HMGT:SetPlayerVersionStatus(playerName, version, protocol, sourceTag)
|
||||
local status = self:GetPlayerStatus(playerName, true)
|
||||
if not status then
|
||||
return nil
|
||||
end
|
||||
if version and version ~= "" then
|
||||
status.version = tostring(version)
|
||||
end
|
||||
if tonumber(protocol) then
|
||||
status.protocol = tonumber(protocol)
|
||||
end
|
||||
if sourceTag and sourceTag ~= "" then
|
||||
status.versionSource = tostring(sourceTag)
|
||||
end
|
||||
status.mode = "hmgt"
|
||||
return status
|
||||
end
|
||||
|
||||
function HMGT:SetPlayerBridgeStatus(playerName, sourceName)
|
||||
local source = tostring(sourceName or "")
|
||||
if source == "" then
|
||||
return nil
|
||||
end
|
||||
local status = self:GetPlayerStatus(playerName, true)
|
||||
if not status then
|
||||
return nil
|
||||
end
|
||||
status.bridgeSource = source
|
||||
if not status.version or status.version == "" then
|
||||
status.mode = "bridge"
|
||||
end
|
||||
return status
|
||||
end
|
||||
|
||||
function HMGT:GetPlayerAddonStatus(playerName)
|
||||
local status = self:GetPlayerStatus(playerName, false)
|
||||
if not status then
|
||||
return {
|
||||
mode = "missing",
|
||||
version = nil,
|
||||
protocol = 0,
|
||||
bridgeSource = nil,
|
||||
}
|
||||
end
|
||||
|
||||
local version = status.version
|
||||
local protocol = tonumber(status.protocol) or 0
|
||||
local bridgeSource = status.bridgeSource
|
||||
local mode = status.mode
|
||||
|
||||
if version and version ~= "" then
|
||||
mode = "hmgt"
|
||||
elseif bridgeSource and bridgeSource ~= "" then
|
||||
mode = "bridge"
|
||||
else
|
||||
mode = "missing"
|
||||
end
|
||||
|
||||
return {
|
||||
mode = mode,
|
||||
version = version,
|
||||
protocol = protocol,
|
||||
bridgeSource = bridgeSource,
|
||||
}
|
||||
end
|
||||
|
||||
function HMGT:ClearPlayerStatus(playerName)
|
||||
local normalizedName = self:NormalizePlayerName(playerName)
|
||||
if not normalizedName or not self.playerStatus then
|
||||
return false
|
||||
end
|
||||
if self.playerStatus[normalizedName] then
|
||||
self.playerStatus[normalizedName] = nil
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function HMGT:GetStaticDebugScopeOptions()
|
||||
@@ -456,6 +567,10 @@ function HMGT:IsReliableCommType(msgType)
|
||||
end
|
||||
|
||||
function HMGT:GetPeerProtocolVersion(playerName)
|
||||
local status = self:GetPlayerStatus(playerName, false)
|
||||
if status and tonumber(status.protocol) then
|
||||
return tonumber(status.protocol) or 0
|
||||
end
|
||||
local normalizedName = self:NormalizePlayerName(playerName)
|
||||
local peerProtocols = self.peerProtocols or {}
|
||||
return tonumber(normalizedName and peerProtocols[normalizedName]) or 0
|
||||
@@ -469,6 +584,7 @@ function HMGT:RememberPeerProtocolVersion(playerName, protocol)
|
||||
end
|
||||
self.peerProtocols = self.peerProtocols or {}
|
||||
self.peerProtocols[normalizedName] = numeric
|
||||
self:SetPlayerVersionStatus(normalizedName, nil, numeric, nil)
|
||||
end
|
||||
|
||||
local function ParseVersionTokens(version)
|
||||
@@ -747,7 +863,32 @@ function HMGT:SendDirectMessage(payload, target, prio)
|
||||
end
|
||||
|
||||
function HMGT:DebugScoped(level, scope, fmt, ...)
|
||||
return
|
||||
local normalizedLevel = tostring(level or "info"):lower()
|
||||
if not DEBUG_LEVELS[normalizedLevel] then
|
||||
normalizedLevel = "info"
|
||||
end
|
||||
|
||||
local normalizedScope = tostring(scope or "General"):match("^%s*(.-)%s*$")
|
||||
if normalizedScope == "" then
|
||||
normalizedScope = "General"
|
||||
end
|
||||
|
||||
local ok, message = pcall(string.format, tostring(fmt or ""), ...)
|
||||
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)
|
||||
end
|
||||
|
||||
if self.debugWindow and self.debugWindow.IsShown and self.debugWindow:IsShown() and self.RefreshDebugWindow then
|
||||
self:RefreshDebugWindow()
|
||||
end
|
||||
end
|
||||
|
||||
function HMGT:Debug(fmt, ...)
|
||||
@@ -764,7 +905,7 @@ end
|
||||
|
||||
function HMGT:RegisterPeerVersion(playerName, version, protocol, sourceTag)
|
||||
if not playerName then return end
|
||||
self.peerVersions[playerName] = version
|
||||
self:SetPlayerVersionStatus(playerName, version, protocol, sourceTag)
|
||||
self:RememberPeerProtocolVersion(playerName, protocol)
|
||||
if self.versionNoticeWindow and self.versionNoticeWindow.IsShown and self.versionNoticeWindow:IsShown() and self.RefreshVersionNoticeWindow then
|
||||
self:RefreshVersionNoticeWindow()
|
||||
@@ -798,7 +939,7 @@ function HMGT:RegisterPeerVersion(playerName, version, protocol, sourceTag)
|
||||
tostring(playerName), table.concat(details, " | "))
|
||||
self:Print("|cffff5555HMGT|r " .. text)
|
||||
self:ShowVersionMismatchPopup(playerName, table.concat(details, " | "), sourceTag)
|
||||
self:Debug("info", "Version mismatch %s via=%s %s", tostring(playerName), tostring(sourceTag or "?"), table.concat(details, " | "))
|
||||
self:DebugScoped("info", "TrackerCore", "Version mismatch %s via=%s %s", tostring(playerName), tostring(sourceTag or "?"), table.concat(details, " | "))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1091,7 +1232,7 @@ function HMGT:LogTrackedSpellCast(playerName, spellEntry, details)
|
||||
|
||||
self:DebugScoped(
|
||||
"verbose",
|
||||
"TrackedSpells",
|
||||
"TrackerCore",
|
||||
"%s -> %s von %s, %s",
|
||||
GetTrackedSpellCategoryLabel(spellEntry),
|
||||
GetSpellDebugLabel(spellEntry.spellId),
|
||||
@@ -1699,22 +1840,9 @@ function HMGT:MigrateProfileSettings()
|
||||
|
||||
if #p.trackers == 0 and p.trackerModelVersion ~= TRACKER_MODEL_VERSION then
|
||||
p.trackers = {
|
||||
self:CreateTrackerConfig(1, CopyTrackerFields({
|
||||
name = L["IT_NAME"] or "Interrupts",
|
||||
trackerType = "normal",
|
||||
categories = { "interrupt" },
|
||||
}, p.interruptTracker or {})),
|
||||
self:CreateTrackerConfig(2, CopyTrackerFields({
|
||||
name = L["RCD_NAME"] or "Raid Cooldowns",
|
||||
trackerType = "normal",
|
||||
categories = { "raid" },
|
||||
}, p.raidCooldownTracker or {})),
|
||||
self:CreateTrackerConfig(3, CopyTrackerFields({
|
||||
name = L["GCD_NAME"] or "Cooldowns",
|
||||
trackerType = "group",
|
||||
categories = { "defensive", "offensive", "tank", "healing", "utility", "cc", "lust" },
|
||||
showChargesOnIcon = true,
|
||||
}, p.groupCooldownTracker or {})),
|
||||
self:BuildTrackerConfigFromPreset("interruptTracker", 1, CopyTrackerFields({}, p.interruptTracker or {})),
|
||||
self:BuildTrackerConfigFromPreset("raidCooldownTracker", 2, CopyTrackerFields({}, p.raidCooldownTracker or {})),
|
||||
self:BuildTrackerConfigFromPreset("groupCooldownTracker", 3, CopyTrackerFields({}, p.groupCooldownTracker or {})),
|
||||
}
|
||||
end
|
||||
|
||||
@@ -1732,11 +1860,7 @@ function HMGT:MigrateProfileSettings()
|
||||
end
|
||||
end
|
||||
if #normalizedTrackers == 0 then
|
||||
normalizedTrackers[1] = self:CreateTrackerConfig(1, {
|
||||
name = L["IT_NAME"] or "Interrupts",
|
||||
trackerType = "normal",
|
||||
categories = { "interrupt" },
|
||||
})
|
||||
normalizedTrackers[1] = self:BuildTrackerConfigFromPreset("interruptTracker", 1)
|
||||
end
|
||||
p.trackers = normalizedTrackers
|
||||
p.trackerModelVersion = TRACKER_MODEL_VERSION
|
||||
@@ -2648,7 +2772,7 @@ function HMGT:OnGroupRosterUpdate()
|
||||
if not validPlayers[name] then
|
||||
self.playerData[name] = nil
|
||||
self:ClearTrackerStateForPlayer(name)
|
||||
self.peerVersions[name] = nil
|
||||
self:ClearPlayerStatus(name)
|
||||
self.versionWarnings[name] = nil
|
||||
if self.peerProtocols then
|
||||
self.peerProtocols[name] = nil
|
||||
@@ -3040,127 +3164,6 @@ function HMGT:TestMode()
|
||||
self:Print(L["TEST_MODE_ACTIVE"])
|
||||
end
|
||||
|
||||
function HMGT:GetDemoEntries(trackerKey, database, settings)
|
||||
local pool = {}
|
||||
local poolByClass = {}
|
||||
for _, entry in ipairs(database) do
|
||||
if settings.enabledSpells[entry.spellId] ~= false then
|
||||
pool[#pool + 1] = entry
|
||||
for _, cls in ipairs(entry.classes or {}) do
|
||||
poolByClass[cls] = poolByClass[cls] or {}
|
||||
poolByClass[cls][#poolByClass[cls] + 1] = entry
|
||||
end
|
||||
end
|
||||
end
|
||||
if #pool == 0 then return {} end
|
||||
|
||||
local classKeys = {}
|
||||
for cls in pairs(poolByClass) do
|
||||
classKeys[#classKeys + 1] = cls
|
||||
end
|
||||
if #classKeys == 0 then classKeys[1] = "WARRIOR" end
|
||||
|
||||
local count = settings.showBar and math.min(8, #pool) or math.min(12, #pool)
|
||||
local names = { "Alice", "Bob", "Clara", "Duke", "Elli", "Fynn", "Gina", "Hektor", "Ivo", "Jana", "Kira", "Lio" }
|
||||
|
||||
local spellIds = {}
|
||||
for _, e in ipairs(pool) do spellIds[#spellIds + 1] = tostring(e.spellId) end
|
||||
table.sort(spellIds)
|
||||
local signature = table.concat(spellIds, ",") .. "|" .. tostring(settings.showBar and 1 or 0) .. "|" .. tostring(count)
|
||||
|
||||
local now = GetTime()
|
||||
local cache = self.demoModeData[trackerKey]
|
||||
if (not cache) or (cache.signature ~= signature) or (not cache.entries) or (#cache.entries ~= count) then
|
||||
local entries = {}
|
||||
for i = 1, count do
|
||||
local cls = classKeys[math.random(1, #classKeys)]
|
||||
local classPool = poolByClass[cls]
|
||||
local spell = (classPool and classPool[math.random(1, #classPool)]) or pool[math.random(1, #pool)]
|
||||
local duration = math.max(
|
||||
1,
|
||||
tonumber(HMGT_SpellData.GetBaseCooldown and HMGT_SpellData.GetBaseCooldown(spell)) or tonumber(spell.cooldown) or 60
|
||||
)
|
||||
local playerName = names[((i - 1) % #names) + 1]
|
||||
-- start offset so demo entries do not all tick in sync
|
||||
local offset = math.random() * math.min(duration * 0.85, duration - 0.1)
|
||||
entries[#entries + 1] = {
|
||||
playerName = playerName,
|
||||
class = cls or ((spell.classes and spell.classes[1]) or "WARRIOR"),
|
||||
spellEntry = spell,
|
||||
total = duration,
|
||||
cycleStart = now - offset,
|
||||
currentCharges = nil,
|
||||
maxCharges = nil,
|
||||
}
|
||||
end
|
||||
cache = { signature = signature, entries = entries }
|
||||
self.demoModeData[trackerKey] = cache
|
||||
end
|
||||
|
||||
local out = {}
|
||||
for _, e in ipairs(cache.entries) do
|
||||
local total = math.max(1, tonumber(e.total) or 1)
|
||||
local elapsed = math.max(0, now - (e.cycleStart or now))
|
||||
local phase = math.fmod(elapsed, total)
|
||||
local rem = total - phase
|
||||
-- show zero briefly at cycle boundary, then restart immediately
|
||||
if elapsed > 0 and phase < 0.05 then rem = 0 end
|
||||
out[#out + 1] = {
|
||||
playerName = e.playerName,
|
||||
class = e.class,
|
||||
spellEntry = e.spellEntry,
|
||||
remaining = rem,
|
||||
total = total,
|
||||
currentCharges = e.currentCharges,
|
||||
maxCharges = e.maxCharges,
|
||||
}
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
function HMGT:GetOwnTestEntries(database, settings, cooldownInfoOpts)
|
||||
local entries = {}
|
||||
local enabledSpells = settings and settings.enabledSpells or {}
|
||||
local playerName = self:NormalizePlayerName(UnitName("player")) or "Player"
|
||||
local classToken = select(2, UnitClass("player"))
|
||||
if not classToken then
|
||||
return entries, playerName
|
||||
end
|
||||
|
||||
local specIdx = GetSpecialization()
|
||||
local lookupSpec = (specIdx and specIdx > 0) and specIdx or 0
|
||||
local talents = (self.playerData[playerName] and self.playerData[playerName].talents) or {}
|
||||
local spells = HMGT_SpellData.GetSpellsForSpec(classToken, lookupSpec, database or {})
|
||||
|
||||
for _, spellEntry in ipairs(spells) do
|
||||
if enabledSpells[spellEntry.spellId] ~= false then
|
||||
local remaining, total, curCharges, maxCharges = self:GetCooldownInfo(playerName, spellEntry.spellId, cooldownInfoOpts)
|
||||
local effectiveCd = HMGT_SpellData.GetEffectiveCooldown(spellEntry, talents)
|
||||
local isAvailabilitySpell = self:IsAvailabilitySpell(spellEntry)
|
||||
local spellKnown = self:IsTrackedSpellKnownForPlayer(playerName, spellEntry.spellId)
|
||||
local hasPartialCharges = (tonumber(maxCharges) or 0) > 0
|
||||
and (tonumber(curCharges) or tonumber(maxCharges) or 0) < (tonumber(maxCharges) or 0)
|
||||
local hasActiveCd = ((remaining or 0) > 0) or hasPartialCharges
|
||||
local hasAvailabilityState = isAvailabilitySpell and self:HasAvailabilityState(playerName, spellEntry.spellId)
|
||||
|
||||
if spellKnown or hasActiveCd or hasAvailabilityState then
|
||||
entries[#entries + 1] = {
|
||||
playerName = playerName,
|
||||
class = classToken,
|
||||
spellEntry = spellEntry,
|
||||
remaining = remaining,
|
||||
total = total > 0 and total or effectiveCd,
|
||||
currentCharges = curCharges,
|
||||
maxCharges = maxCharges,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return entries, playerName
|
||||
end
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════
|
||||
-- HILFSFUNKTIONEN
|
||||
-- ═══════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user