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:
@@ -80,6 +80,8 @@ function HMGT:ApplyExternalKnownSpell(sourceName, playerName, spellId, class, co
|
||||
knownSpells = knownSpells,
|
||||
externalSource = source,
|
||||
}
|
||||
self:SetPlayerBridgeStatus(normalizedName, source)
|
||||
self:DebugScoped("verbose", "TrackerBridge", "Bridge known spell source=%s player=%s spellId=%s", tostring(source), tostring(normalizedName), tostring(sid))
|
||||
|
||||
if tonumber(cooldown) and tonumber(cooldown) > 0 then
|
||||
spellEntry._hmgtExternalBaseCd = tonumber(cooldown)
|
||||
@@ -128,6 +130,8 @@ function HMGT:ApplyExternalSpecInfo(sourceName, playerName, class, specId, talen
|
||||
knownSpells = knownSpells,
|
||||
externalSource = source,
|
||||
}
|
||||
self:SetPlayerBridgeStatus(normalizedName, source)
|
||||
self:DebugScoped("info", "TrackerBridge", "Bridge spec sync source=%s player=%s class=%s spec=%s", tostring(source), tostring(normalizedName), tostring(classToken), tostring(spec))
|
||||
|
||||
self:PruneAvailabilityStates(normalizedName, knownSpells)
|
||||
self:TriggerTrackerUpdate("trackers")
|
||||
@@ -154,6 +158,7 @@ function HMGT:ApplyExternalCooldown(sourceName, playerName, spellId, cooldown)
|
||||
|
||||
self:RegisterExternalAddonSource(source)
|
||||
self:ApplyExternalKnownSpell(source, normalizedName, sid, nil, cd)
|
||||
self:DebugScoped("info", "TrackerBridge", "Bridge cooldown source=%s player=%s spellId=%s cooldown=%.1f", tostring(source), tostring(normalizedName), tostring(sid), cd)
|
||||
self:HandleRemoteSpellCast(normalizedName, sid, GetServerTime(), nil, nil, nil, cd)
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -4,6 +4,91 @@ if not HMGT then return end
|
||||
|
||||
HMGT.TrackerCore = HMGT.TrackerCore or {}
|
||||
|
||||
HMGT.TRACKER_PRESET_DEFINITIONS = HMGT.TRACKER_PRESET_DEFINITIONS or {
|
||||
interruptTracker = {
|
||||
moduleName = "InterruptTracker",
|
||||
dbKey = "interruptTracker",
|
||||
trackerType = "normal",
|
||||
trackerKey = "interruptTracker",
|
||||
categories = { "interrupt" },
|
||||
defaultName = function(L)
|
||||
return (L and L["IT_NAME"]) or "Interrupts"
|
||||
end,
|
||||
},
|
||||
raidCooldownTracker = {
|
||||
moduleName = "RaidCooldownTracker",
|
||||
dbKey = "raidCooldownTracker",
|
||||
trackerType = "normal",
|
||||
trackerKey = "raidCooldownTracker",
|
||||
categories = { "lust", "defensive", "healing", "tank", "utility", "offensive", "cc", "interrupt" },
|
||||
defaultName = function(L)
|
||||
return (L and L["RCD_NAME"]) or "Raid Cooldowns"
|
||||
end,
|
||||
},
|
||||
groupCooldownTracker = {
|
||||
moduleName = "GroupCooldownTracker",
|
||||
dbKey = "groupCooldownTracker",
|
||||
trackerType = "group",
|
||||
trackerKey = "groupCooldownTracker",
|
||||
categories = { "tank", "defensive", "healing", "cc", "utility", "offensive", "lust", "interrupt" },
|
||||
includeSelfFrame = false,
|
||||
showChargesOnIcon = true,
|
||||
defaultName = function(L)
|
||||
return (L and L["GCD_NAME"]) or "Cooldowns"
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
function HMGT:GetTrackerPresetDefinitions()
|
||||
return self.TRACKER_PRESET_DEFINITIONS or {}
|
||||
end
|
||||
|
||||
function HMGT:GetTrackerPresetDefinition(key)
|
||||
local definitions = self:GetTrackerPresetDefinitions()
|
||||
return definitions and definitions[tostring(key or "")]
|
||||
end
|
||||
|
||||
function HMGT:GetTrackerPresetDefinitionByModule(moduleName)
|
||||
local target = tostring(moduleName or "")
|
||||
for _, definition in pairs(self:GetTrackerPresetDefinitions()) do
|
||||
if tostring(definition.moduleName or "") == target then
|
||||
return definition
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function HMGT:GetTrackerTypeOptions()
|
||||
local L = self.L
|
||||
return {
|
||||
normal = (L and L["OPT_TRACKER_TYPE_NORMAL"]) or "Normal tracker",
|
||||
group = (L and L["OPT_TRACKER_TYPE_GROUP"]) or "Group-based tracker",
|
||||
}
|
||||
end
|
||||
|
||||
function HMGT:BuildTrackerConfigFromPreset(presetKey, trackerId, overrides)
|
||||
local definition = self:GetTrackerPresetDefinition(presetKey)
|
||||
local config = overrides or {}
|
||||
if not definition then
|
||||
return self:CreateTrackerConfig(trackerId, config)
|
||||
end
|
||||
|
||||
local base = {
|
||||
name = type(definition.defaultName) == "function" and definition.defaultName(self.L) or tostring(definition.defaultName or ""),
|
||||
trackerType = definition.trackerType,
|
||||
trackerKey = definition.trackerKey,
|
||||
categories = definition.categories,
|
||||
includeSelfFrame = definition.includeSelfFrame,
|
||||
showChargesOnIcon = definition.showChargesOnIcon,
|
||||
}
|
||||
|
||||
for key, value in pairs(config) do
|
||||
base[key] = value
|
||||
end
|
||||
|
||||
return self:CreateTrackerConfig(trackerId, base)
|
||||
end
|
||||
|
||||
local function EntryNeedsVisualTicker(entry)
|
||||
if type(entry) ~= "table" then
|
||||
return false
|
||||
@@ -204,6 +289,93 @@ function HMGT:CollectTrackerEntries(tracker)
|
||||
return entries
|
||||
end
|
||||
|
||||
function HMGT:GetDemoEntries(trackerKey, database, settings)
|
||||
local pool = {}
|
||||
local poolByClass = {}
|
||||
for _, entry in ipairs(database or {}) do
|
||||
if settings.enabledSpells[entry.spellId] ~= false then
|
||||
pool[#pool + 1] = entry
|
||||
for _, classToken in ipairs(entry.classes or {}) do
|
||||
poolByClass[classToken] = poolByClass[classToken] or {}
|
||||
poolByClass[classToken][#poolByClass[classToken] + 1] = entry
|
||||
end
|
||||
end
|
||||
end
|
||||
if #pool == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local classKeys = {}
|
||||
for classToken in pairs(poolByClass) do
|
||||
classKeys[#classKeys + 1] = classToken
|
||||
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 _, entry in ipairs(pool) do
|
||||
spellIds[#spellIds + 1] = tostring(entry.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 cachedEntries = {}
|
||||
for index = 1, count do
|
||||
local classToken = classKeys[math.random(1, #classKeys)]
|
||||
local classPool = poolByClass[classToken]
|
||||
local spellEntry = (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(spellEntry)) or tonumber(spellEntry.cooldown) or 60
|
||||
)
|
||||
local offset = math.random() * math.min(duration * 0.85, duration - 0.1)
|
||||
cachedEntries[#cachedEntries + 1] = {
|
||||
playerName = names[((index - 1) % #names) + 1],
|
||||
class = classToken or ((spellEntry.classes and spellEntry.classes[1]) or "WARRIOR"),
|
||||
spellEntry = spellEntry,
|
||||
total = duration,
|
||||
cycleStart = now - offset,
|
||||
currentCharges = nil,
|
||||
maxCharges = nil,
|
||||
}
|
||||
end
|
||||
cache = {
|
||||
signature = signature,
|
||||
entries = cachedEntries,
|
||||
}
|
||||
self.demoModeData[trackerKey] = cache
|
||||
end
|
||||
|
||||
local entries = {}
|
||||
for _, entry in ipairs(cache.entries) do
|
||||
local total = math.max(1, tonumber(entry.total) or 1)
|
||||
local elapsed = math.max(0, now - (entry.cycleStart or now))
|
||||
local phase = math.fmod(elapsed, total)
|
||||
local remaining = total - phase
|
||||
if elapsed > 0 and phase < 0.05 then
|
||||
remaining = 0
|
||||
end
|
||||
entries[#entries + 1] = {
|
||||
playerName = entry.playerName,
|
||||
class = entry.class,
|
||||
spellEntry = entry.spellEntry,
|
||||
remaining = remaining,
|
||||
total = total,
|
||||
currentCharges = entry.currentCharges,
|
||||
maxCharges = entry.maxCharges,
|
||||
}
|
||||
end
|
||||
|
||||
return entries
|
||||
end
|
||||
|
||||
function HMGT:CollectTrackerTestEntries(tracker)
|
||||
local playerName = self:NormalizePlayerName(UnitName("player")) or "Player"
|
||||
local classToken = select(2, UnitClass("player"))
|
||||
@@ -385,7 +557,7 @@ function HMGT:TriggerTrackerUpdate(reason)
|
||||
if t0 and t1 then
|
||||
local mod = HMGT[name]
|
||||
local count = mod and mod.lastEntryCount or 0
|
||||
self:Debug("verbose", "UIUpdate %s took %.2fms entries=%s", tostring(name), t1 - t0, tostring(count))
|
||||
self:DebugScoped("verbose", "TrackerUI", "UIUpdate %s took %.2fms entries=%s", tostring(name), t1 - t0, tostring(count))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ function HMGT:RefreshOwnCooldownStateFromGame(spellId)
|
||||
if isLikelyGlobalCooldown or isSuspiciousShortRefresh then
|
||||
self:DebugScoped(
|
||||
"verbose",
|
||||
"TrackedSpells",
|
||||
"TrackerState",
|
||||
"Ignore suspicious refresh for %s: spellCD=%.3f gcd=%.3f existing=%.3f remaining=%.3f effective=%.3f",
|
||||
GetSpellDebugLabel and GetSpellDebugLabel(sid) or tostring(sid),
|
||||
cooldownDuration,
|
||||
|
||||
@@ -142,13 +142,26 @@ local function IsPartyAttachMode(tracker)
|
||||
end
|
||||
|
||||
local function IsGroupTracker(tracker)
|
||||
return type(tracker) == "table" and tracker.trackerType == "group"
|
||||
return HMGT.IsGroupTrackerConfig and HMGT:IsGroupTrackerConfig(tracker) or (type(tracker) == "table" and tracker.trackerType == "group")
|
||||
end
|
||||
|
||||
local TRACKER_TYPE_VALUES = {
|
||||
normal = L["OPT_TRACKER_TYPE_NORMAL"] or "Normal tracker",
|
||||
group = L["OPT_TRACKER_TYPE_GROUP"] or "Group-based tracker",
|
||||
}
|
||||
local function GetTrackerTypeValues()
|
||||
return HMGT.GetTrackerTypeOptions and HMGT:GetTrackerTypeOptions() or {
|
||||
normal = L["OPT_TRACKER_TYPE_NORMAL"] or "Normal tracker",
|
||||
group = L["OPT_TRACKER_TYPE_GROUP"] or "Group-based tracker",
|
||||
}
|
||||
end
|
||||
|
||||
local function GetPresetLabel(presetKey)
|
||||
local definition = HMGT.GetTrackerPresetDefinition and HMGT:GetTrackerPresetDefinition(presetKey) or nil
|
||||
if not definition then
|
||||
return tostring(presetKey or (L["OPT_TRACKER"] or "Tracker"))
|
||||
end
|
||||
if type(definition.defaultName) == "function" then
|
||||
return tostring(definition.defaultName(L))
|
||||
end
|
||||
return tostring(definition.defaultName or definition.moduleName or presetKey)
|
||||
end
|
||||
|
||||
local function GetTrackerVisibilitySummary(tracker)
|
||||
local parts = {}
|
||||
@@ -180,7 +193,7 @@ local function GetTrackerSummaryText(tracker)
|
||||
local display = tracker.showBar and (L["OPT_DISPLAY_BAR"] or "Progress bars") or (L["OPT_DISPLAY_ICON"] or "Icons")
|
||||
|
||||
return table.concat({
|
||||
string.format("|cffffd100%s|r: %s", L["OPT_TRACKER_TYPE"] or "Tracker type", TRACKER_TYPE_VALUES[tracker.trackerType or "normal"] or (L["OPT_TRACKER_TYPE_NORMAL"] or "Normal tracker")),
|
||||
string.format("|cffffd100%s|r: %s", L["OPT_TRACKER_TYPE"] or "Tracker type", GetTrackerTypeValues()[tracker.trackerType or "normal"] or (L["OPT_TRACKER_TYPE_NORMAL"] or "Normal tracker")),
|
||||
string.format("|cffffd100%s|r: %s", L["OPT_TRACKER_CATEGORIES"] or "Categories", GetTrackerCategoriesSummary(tracker)),
|
||||
string.format("|cffffd100%s|r: %s", L["OPT_STATUS_MODE"] or "Mode", modeLabel),
|
||||
string.format("|cffffd100%s|r: %s", L["OPT_STATUS_DISPLAY"] or "Display", display),
|
||||
@@ -814,7 +827,7 @@ local function BuildGlobalSpellBrowserArgs()
|
||||
end
|
||||
|
||||
local function BuildTrackerOverviewArgs()
|
||||
return {
|
||||
local args = {
|
||||
description = {
|
||||
type = "description",
|
||||
order = 1,
|
||||
@@ -833,22 +846,36 @@ local function BuildTrackerOverviewArgs()
|
||||
return string.format("%s\n\n%s (%d): %s", body, L["OPT_TRACKERS"] or "Tracker Bars", #trackers, table.concat(names, ", "))
|
||||
end,
|
||||
},
|
||||
addTracker = {
|
||||
}
|
||||
|
||||
local definitions = HMGT.GetTrackerPresetDefinitions and HMGT:GetTrackerPresetDefinitions() or {}
|
||||
local presetKeys = {}
|
||||
for presetKey in pairs(definitions) do
|
||||
presetKeys[#presetKeys + 1] = presetKey
|
||||
end
|
||||
table.sort(presetKeys, function(a, b)
|
||||
return GetPresetLabel(a) < GetPresetLabel(b)
|
||||
end)
|
||||
|
||||
for index, presetKey in ipairs(presetKeys) do
|
||||
args["addPreset_" .. presetKey] = {
|
||||
type = "execute",
|
||||
order = 2,
|
||||
order = 2 + index,
|
||||
width = "full",
|
||||
name = L["OPT_ADD_TRACKER"] or "Add tracker",
|
||||
name = function()
|
||||
return string.format("%s: %s", L["OPT_ADD_TRACKER"] or "Add tracker", GetPresetLabel(presetKey))
|
||||
end,
|
||||
func = function()
|
||||
local nextId = HMGT:GetNextTrackerId()
|
||||
local tracker = HMGT:CreateTrackerConfig(nextId, {
|
||||
name = string.format("%s %d", L["OPT_TRACKER"] or "Tracker", nextId),
|
||||
})
|
||||
local tracker = HMGT:BuildTrackerConfigFromPreset(presetKey, nextId)
|
||||
HMGT.db.profile.trackers = HMGT.db.profile.trackers or {}
|
||||
HMGT.db.profile.trackers[#HMGT.db.profile.trackers + 1] = tracker
|
||||
TriggerTrackerUpdate(true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
return args
|
||||
end
|
||||
|
||||
local function BuildTrackerGroup(trackerId, order)
|
||||
@@ -1008,7 +1035,7 @@ local function BuildTrackerGroup(trackerId, order)
|
||||
width = "full",
|
||||
name = L["OPT_TRACKER_TYPE"] or "Tracker type",
|
||||
desc = L["OPT_TRACKER_TYPE_DESC"] or "Choose whether this tracker uses one shared frame or separate frames per group member.",
|
||||
values = TRACKER_TYPE_VALUES,
|
||||
values = GetTrackerTypeValues,
|
||||
get = function()
|
||||
local tracker = s()
|
||||
return (tracker and tracker.trackerType) or "normal"
|
||||
|
||||
@@ -203,7 +203,7 @@ function HMGT:SendSpellStateSnapshot(snapshot, target, revision)
|
||||
|
||||
self:DebugScoped(
|
||||
"verbose",
|
||||
"TrackedSpells",
|
||||
"TrackerSync",
|
||||
"SendSpellStateSnapshot target=%s spell=%s kind=%s rev=%d a=%.3f b=%.3f c=%.3f d=%.3f",
|
||||
tostring(target and target ~= "" and target or "GROUP"),
|
||||
GetSpellDebugLabel and GetSpellDebugLabel(sid) or tostring(sid),
|
||||
@@ -307,7 +307,7 @@ function HMGT:BroadcastRepairSpellStates()
|
||||
if not self:IsEnabled() then return end
|
||||
local sent = self:SendOwnTrackedSpellStates()
|
||||
if sent > 0 then
|
||||
self:DebugScoped("verbose", "TrackedSpells", "RepairSpellStates sent=%d", sent)
|
||||
self:DebugScoped("verbose", "TrackerSync", "RepairSpellStates sent=%d", sent)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -407,7 +407,7 @@ function HMGT:BroadcastSpellCast(spellId, snapshot)
|
||||
chargeRemaining = math.max(0, tonumber(remaining) or 0)
|
||||
chargeDuration = math.max(0, tonumber(total) or 0)
|
||||
end
|
||||
self:DebugScoped("verbose", "TrackedSpells", "BroadcastSpellCast spell=%s serverTime=%s charges=%d/%d",
|
||||
self:DebugScoped("verbose", "TrackerSync", "BroadcastSpellCast spell=%s serverTime=%s charges=%d/%d",
|
||||
GetSpellDebugLabel and GetSpellDebugLabel(spellId) or tostring(spellId),
|
||||
tostring(GetServerTime()),
|
||||
cur,
|
||||
@@ -563,7 +563,7 @@ function HMGT:StoreRemotePlayerInfo(playerName, class, specIndex, talentHash, kn
|
||||
end
|
||||
self:DebugScoped(
|
||||
"info",
|
||||
"TrackedSpells",
|
||||
"TrackerSync",
|
||||
"Spielerinfo von %s: class=%s spec=%s bekannteSpells=%d",
|
||||
tostring(playerName),
|
||||
tostring(class),
|
||||
@@ -753,7 +753,7 @@ function HMGT:ApplyRemoteSpellState(playerName, spellId, kind, revision, a, b, c
|
||||
if changed then
|
||||
self:DebugScoped(
|
||||
"info",
|
||||
"TrackedSpells",
|
||||
"TrackerSync",
|
||||
"Sync von %s: %s -> %s (rev=%d)",
|
||||
tostring(normalizedName),
|
||||
GetSpellDebugLabel and GetSpellDebugLabel(sid) or tostring(sid),
|
||||
@@ -814,7 +814,7 @@ function HMGT:OnCommReceived(prefix, message, distribution, sender)
|
||||
if (tonumber(protocol) or 0) >= 5 then
|
||||
return
|
||||
end
|
||||
self:DebugScoped("verbose", "TrackedSpells", "Legacy cast von %s: %s ts=%s",
|
||||
self:DebugScoped("verbose", "TrackerSync", "Legacy cast von %s: %s ts=%s",
|
||||
tostring(senderName),
|
||||
GetSpellDebugLabel and GetSpellDebugLabel(spellId) or tostring(spellId),
|
||||
tostring(timestamp))
|
||||
@@ -892,7 +892,7 @@ function HMGT:OnCommReceived(prefix, message, distribution, sender)
|
||||
self:RememberPeerProtocolVersion(senderName, protocol)
|
||||
self:ClearRemoteSpellStateRevisions(senderName)
|
||||
self:StoreRemotePlayerInfo(senderName, class, specIndex, talentHash, knownSpellList)
|
||||
self:DebugScoped("info", "TrackedSpells", "Hello von %s: class=%s spec=%s spells=%s",
|
||||
self:DebugScoped("info", "TrackerSync", "Hello von %s: class=%s spec=%s spells=%s",
|
||||
tostring(senderName), tostring(class), tostring(specIndex), tostring(knownSpellList or ""))
|
||||
self:SendSyncResponse(sender)
|
||||
self:TriggerTrackerUpdate()
|
||||
@@ -1003,7 +1003,7 @@ function HMGT:OnCommReceived(prefix, message, distribution, sender)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:DebugScoped("info", "TrackedSpells", "SyncResponse von %s: cdsApplied=%d", tostring(senderName), applied)
|
||||
self:DebugScoped("info", "TrackerSync", "SyncResponse von %s: cdsApplied=%d", tostring(senderName), applied)
|
||||
end
|
||||
self:TriggerTrackerUpdate()
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user