Files
HailMaryGuildTools/Modules/Tracker/TrackerAvailability.lua
2026-04-24 23:43:55 +02:00

170 lines
5.9 KiB
Lua

local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
HMGT.TrackerAvailability = HMGT.TrackerAvailability or {}
local internals = HMGT.TrackerInternals or {}
local GetPlayerAuraApplications = internals.GetPlayerAuraApplications
local GetSpellCastCountInfo = internals.GetSpellCastCountInfo
function HMGT:GetOwnAvailabilityProgress(spellEntry)
local availability = self:GetAvailabilityConfig(spellEntry)
if not availability then
return nil, nil
end
local required = self:GetAvailabilityRequiredCount(spellEntry)
if required <= 0 then
return nil, nil
end
local current = 0
if availability.type == "auraStacks" then
current = GetPlayerAuraApplications and GetPlayerAuraApplications(availability.auraSpellId) or 0
if current <= 0 then
local fallbackSpellId = tonumber(availability.fallbackSpellCountId)
or tonumber(availability.progressSpellId)
or tonumber(spellEntry and spellEntry.spellId)
if fallbackSpellId and fallbackSpellId > 0 and GetSpellCastCountInfo then
current = GetSpellCastCountInfo(fallbackSpellId)
end
end
else
return nil, nil
end
current = math.max(0, math.min(required, tonumber(current) or 0))
return current, required
end
function HMGT:GetAvailabilityState(playerName, spellId)
local state = self:GetAvailabilityStateEntry(playerName, spellId)
if not state then
return nil, nil
end
return tonumber(state.current) or 0, tonumber(state.max) or 0
end
function HMGT:HasAvailabilityState(playerName, spellId)
local _, max = self:GetAvailabilityState(playerName, spellId)
return (tonumber(max) or 0) > 0
end
function HMGT:StoreAvailabilityState(playerName, spellId, current, max, spellEntry)
local normalizedName = self:NormalizePlayerName(playerName)
local sid = tonumber(spellId)
if not normalizedName or not sid or sid <= 0 then
return false
end
local maxCount = math.max(0, math.floor((tonumber(max) or 0) + 0.5))
if maxCount <= 0 then
return self:ClearAvailabilityState(normalizedName, sid)
end
local currentCount = math.max(0, math.min(maxCount, math.floor((tonumber(current) or 0) + 0.5)))
local previous = self:GetAvailabilityStateEntry(normalizedName, sid)
local changed = (not previous)
or (tonumber(previous.current) or -1) ~= currentCount
or (tonumber(previous.max) or -1) ~= maxCount
self:SetAvailabilityStateEntry(normalizedName, sid, {
current = currentCount,
max = maxCount,
spellEntry = spellEntry,
updatedAt = GetTime(),
})
return changed
end
function HMGT:RefreshOwnAvailabilitySpell(spellEntry)
if not self:IsAvailabilitySpell(spellEntry) then
return false
end
local playerName = self:NormalizePlayerName(UnitName("player"))
if not playerName then
return false
end
local current, max = self:GetOwnAvailabilityProgress(spellEntry)
if (tonumber(max) or 0) > 0 then
local pData = self.playerData[playerName]
if pData and type(pData.knownSpells) == "table" then
pData.knownSpells[tonumber(spellEntry.spellId)] = true
end
end
return self:StoreAvailabilityState(playerName, spellEntry.spellId, current, max, spellEntry)
end
function HMGT:RefreshOwnAvailabilityStates()
local playerName = self:NormalizePlayerName(UnitName("player"))
local pData = playerName and self.playerData[playerName]
if not pData or not pData.class or not pData.specIndex then
return false
end
local changed = false
local groupCooldowns = HMGT_SpellData.GetSpellsForSpec(pData.class, pData.specIndex, HMGT_SpellData.GroupCooldowns)
for _, spellEntry in ipairs(groupCooldowns or {}) do
if self:IsAvailabilitySpell(spellEntry) and self:RefreshOwnAvailabilitySpell(spellEntry) then
changed = true
end
end
if self:PruneAvailabilityStates(playerName, pData.knownSpells or {}) then
changed = true
end
return changed
end
function HMGT:RefreshAndPublishOwnAvailabilityStates()
local playerName = self:NormalizePlayerName(UnitName("player"))
local pData = playerName and self.playerData[playerName]
if not pData or not pData.class or not pData.specIndex then
return false
end
local changed = false
local groupCooldowns = HMGT_SpellData.GetSpellsForSpec(pData.class, pData.specIndex, HMGT_SpellData.GroupCooldowns)
for _, spellEntry in ipairs(groupCooldowns or {}) do
if self:IsAvailabilitySpell(spellEntry) and self:RefreshOwnAvailabilitySpell(spellEntry) then
self:PublishOwnSpellState(spellEntry.spellId, { sendLegacy = true })
changed = true
end
end
if self:PruneAvailabilityStates(playerName, pData.knownSpells or {}) then
changed = true
end
return changed
end
function HMGT:SendOwnAvailabilityStates(target)
local playerName = self:NormalizePlayerName(UnitName("player"))
local pData = playerName and self.playerData[playerName]
if not pData or not pData.class or not pData.specIndex then
return 0
end
self:RefreshOwnAvailabilityStates()
local sent = 0
local groupCooldowns = HMGT_SpellData.GetSpellsForSpec(pData.class, pData.specIndex, HMGT_SpellData.GroupCooldowns)
for _, spellEntry in ipairs(groupCooldowns or {}) do
if self:IsAvailabilitySpell(spellEntry) and self:IsTrackedSpellKnownForPlayer(playerName, spellEntry.spellId) then
local current, max = self:GetAvailabilityState(playerName, spellEntry.spellId)
if (tonumber(max) or 0) > 0 then
self:BroadcastAvailabilityState(spellEntry.spellId, current, max, target)
sent = sent + 1
end
end
end
return sent
end