Files
HailMaryGuildTools/Modules/RaidTimeline/RaidTimelineBigWigs.lua
Torsten Brendgen fc5a8aa361 initial commit
2026-04-10 21:30:31 +02:00

203 lines
7.7 KiB
Lua

local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
local RT = HMGT.RaidTimeline
if not RT then return end
local function TrimText(value)
local text = tostring(value or "")
text = string.gsub(text, "^%s+", "")
text = string.gsub(text, "%s+$", "")
return text
end
local function StripBarDisplayText(value)
local text = tostring(value or "")
text = string.gsub(text, "|T.-|t", "")
text = string.gsub(text, "|c%x%x%x%x%x%x%x%x", "")
text = string.gsub(text, "|r", "")
return TrimText(text)
end
local function NormalizeBossAbilityBarName(value)
local text = TrimText(value)
if text == "" then
return ""
end
text = string.gsub(text, "%s*%(%d+%)%s*$", "")
text = string.gsub(text, "%s*%([Cc]ount%)%s*$", "")
text = string.gsub(text, "^%s*%[([A-Za-z])%]%s*", "%1 ")
text = string.gsub(text, "%s*%[([A-Za-z])%]%s*$", " (%1)")
text = string.gsub(text, "%s*%(([A-Za-z])%)%s*$", " (%1)")
text = string.lower(text)
return TrimText(text)
end
local function EnsureBigWigsBridge()
if RT._bigWigsBridgeRegistered == true then
return true
end
if type(BigWigsLoader) ~= "table" or type(BigWigsLoader.RegisterMessage) ~= "function" then
return false
end
RT._bigWigsObservedBars = RT._bigWigsObservedBars or setmetatable({}, { __mode = "k" })
RT._bigWigsReceiver = RT._bigWigsReceiver or {}
function RT._bigWigsReceiver:OnBigWigsBarCreated(_, plugin, bar, module, key, text, time)
RT._bigWigsObservedBars[bar] = {
plugin = plugin,
module = module,
key = key,
createdText = tostring(text or ""),
duration = tonumber(time) or 0,
}
end
function RT._bigWigsReceiver:OnBigWigsStopBar(_, plugin, module, text)
local targetText = StripBarDisplayText(text)
for bar, info in pairs(RT._bigWigsObservedBars) do
local currentText = ""
if type(bar) == "table" and type(bar.GetText) == "function" then
currentText = StripBarDisplayText(bar:GetText())
end
if (info and info.plugin == plugin or not info or not info.plugin)
and (currentText == targetText or StripBarDisplayText(info and info.createdText) == targetText) then
RT._bigWigsObservedBars[bar] = nil
end
end
end
BigWigsLoader.RegisterMessage(RT._bigWigsReceiver, "BigWigs_BarCreated", "OnBigWigsBarCreated")
BigWigsLoader.RegisterMessage(RT._bigWigsReceiver, "BigWigs_StopBar", "OnBigWigsStopBar")
RT._bigWigsBridgeRegistered = true
return true
end
function RT:GetObservedBigWigsBars()
local observed = {}
if not EnsureBigWigsBridge() then
return observed
end
for bar, info in pairs(self._bigWigsObservedBars or {}) do
local rawText = nil
if type(bar) == "table" and type(bar.GetText) == "function" then
rawText = bar:GetText()
end
rawText = StripBarDisplayText(rawText or (info and info.createdText) or "")
local remaining = math.max(0, tonumber(bar and bar.remaining) or 0)
if rawText ~= "" and remaining > 0 then
observed[#observed + 1] = {
rawText = rawText,
normalizedName = NormalizeBossAbilityBarName(rawText),
count = tonumber(string.match(rawText, "%((%d+)%)%s*$")) or 1,
seconds = remaining,
key = info and info.key or nil,
}
else
self._bigWigsObservedBars[bar] = nil
end
end
return observed
end
function RT:ProbeBossAbilityEntry(entryIndex, entry)
if not self:IsLocalEditor() or not self.activeEncounterId or self:GetTriggerType(entry) ~= "bossAbility" then
return
end
local desiredRawName = TrimText(entry and entry.bossAbilityBarName or "")
local desiredName = NormalizeBossAbilityBarName(desiredRawName)
local desiredSelector = self:NormalizeCastCountSelector(entry and entry.castCount)
local desiredSelectorText = self:FormatCastCountSelector(desiredSelector)
if desiredName == "" then
self:LogBossAbilityProbe(
entryIndex,
entry,
"missing-bar-name",
"RaidTimeline BigWigs probe encounter=%s slot=%s skipped=missing-bar-name",
tostring(self.activeEncounterId),
tostring(entryIndex)
)
return
end
local bars = self:GetObservedBigWigsBars()
if #bars == 0 then
self:LogBossAbilityProbe(
entryIndex,
entry,
"no-bars",
"RaidTimeline BigWigs probe encounter=%s slot=%s target=%s normalized=%s selector=%s foundBar=false bars=0",
tostring(self.activeEncounterId),
tostring(entryIndex),
tostring(desiredRawName),
tostring(desiredName),
tostring(desiredSelectorText)
)
return
end
local seenNames = {}
local foundName = false
for _, observed in ipairs(bars) do
seenNames[#seenNames + 1] = string.format("%s{key=%s}[%d]=%.1fs", tostring(observed.rawText), tostring(observed.key), tonumber(observed.count) or 1, tonumber(observed.seconds) or 0)
if observed.normalizedName == desiredName then
foundName = true
if self:DoesCastCountSelectorMatch(desiredSelector, observed.count) then
self:LogBossAbilityProbe(
entryIndex,
entry,
string.format("match:%s:%s:%d", desiredName, tostring(desiredSelector), tonumber(observed.count) or 1),
"RaidTimeline BigWigs probe encounter=%s slot=%s target=%s normalized=%s selector=%s foundBar=true countMatch=true observed=%s key=%s observedCount=%d remaining=%.1f",
tostring(self.activeEncounterId),
tostring(entryIndex),
tostring(desiredRawName),
tostring(desiredName),
tostring(desiredSelectorText),
tostring(observed.rawText),
tostring(observed.key),
tonumber(observed.count) or 1,
tonumber(observed.seconds) or 0
)
self:TryDispatchBossAbilityEntry(entryIndex, entry, observed.count, observed.seconds)
return
end
self:LogBossAbilityProbe(
entryIndex,
entry,
string.format("count-mismatch:%s:%d", desiredName, observed.count),
"RaidTimeline BigWigs probe encounter=%s slot=%s target=%s normalized=%s selector=%s foundBar=true countMatch=false observed=%s key=%s observedCount=%d remaining=%.1f",
tostring(self.activeEncounterId),
tostring(entryIndex),
tostring(desiredRawName),
tostring(desiredName),
tostring(desiredSelectorText),
tostring(observed.rawText),
tostring(observed.key),
tonumber(observed.count) or 1,
tonumber(observed.seconds) or 0
)
end
end
if not foundName then
self:LogBossAbilityProbe(
entryIndex,
entry,
string.format("name-miss:%s", desiredName),
"RaidTimeline BigWigs probe encounter=%s slot=%s target=%s normalized=%s selector=%s foundBar=false bars=%s",
tostring(self.activeEncounterId),
tostring(entryIndex),
tostring(desiredRawName),
tostring(desiredName),
tostring(desiredSelectorText),
table.concat(seenNames, ", ")
)
end
end