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

410 lines
15 KiB
Lua

-- Modules/BuffEndingAnnouncer/BuffEndingAnnouncerOptions.lua
local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
local BEA = HMGT.BuffEndingAnnouncer
if not BEA then return end
if not HMGT_Config or not HMGT_Config.RegisterOptionsProvider then return end
local L = LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME, true) or {}
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0")
local beaOptionsGroup
local function GetSpellName(spellId)
local sid = tonumber(spellId)
if not sid or sid <= 0 then return nil end
if C_Spell and type(C_Spell.GetSpellName) == "function" then
local name = C_Spell.GetSpellName(sid)
if type(name) == "string" and name ~= "" then
return name
end
end
if type(GetSpellInfo) == "function" then
local name = GetSpellInfo(sid)
if type(name) == "string" and name ~= "" then
return name
end
end
return nil
end
local function GetSpellIcon(spellId)
local sid = tonumber(spellId)
if not sid or sid <= 0 then return nil end
if HMGT_SpellData and type(HMGT_SpellData.GetSpellIcon) == "function" then
return HMGT_SpellData.GetSpellIcon(sid)
end
if C_Spell and type(C_Spell.GetSpellTexture) == "function" then
return C_Spell.GetSpellTexture(sid)
end
local _, _, icon = GetSpellInfo(sid)
return icon
end
local function RefreshTrackedGroup()
if not beaOptionsGroup or type(beaOptionsGroup.args) ~= "table" then
return
end
local fresh = BEA:BuildOptionsGroup()
local currentTracked = beaOptionsGroup.args.tracked
local freshTracked = fresh and fresh.args and fresh.args.tracked
if type(currentTracked) == "table" and type(freshTracked) == "table" then
currentTracked.name = freshTracked.name
currentTracked.order = freshTracked.order
currentTracked.inline = freshTracked.inline
currentTracked.childGroups = freshTracked.childGroups
currentTracked.args = freshTracked.args
end
end
local function NotifyOptionsChanged(rebuild)
if rebuild ~= false then
RefreshTrackedGroup()
end
AceConfigRegistry:NotifyChange(ADDON_NAME)
end
local function GetFilterState()
HMGT._beaSpellFilter = HMGT._beaSpellFilter or {
search = "",
}
return HMGT._beaSpellFilter
end
local function NormalizeSearchText(value)
local text = tostring(value or ""):lower()
text = text:gsub("^%s+", "")
text = text:gsub("%s+$", "")
return text
end
local function GetDraft()
HMGT._beaDraft = HMGT._beaDraft or {}
return HMGT._beaDraft
end
local function GetTrackedBuffLabel(entry)
local spellId = tonumber(entry and entry.spellId) or 0
local spellName = tostring(entry and entry.name or GetSpellName(spellId) or ("Spell " .. spellId))
local icon = GetSpellIcon(spellId)
local threshold = tonumber(entry and entry.threshold) or tonumber(BEA:GetDefaultThreshold()) or 0
if icon and icon ~= "" then
return string.format("|T%s:16:16:0:0|t %s (%ss)", tostring(icon), spellName, threshold)
end
return string.format("%s (%ss)", spellName, threshold)
end
local function BuildTrackedBuffLeaf(entry)
local spellId = tonumber(entry and entry.spellId) or 0
return {
type = "group",
name = GetTrackedBuffLabel(entry),
args = {
header = {
type = "header",
order = 1,
name = GetTrackedBuffLabel(entry),
},
spellInfo = {
type = "description",
order = 2,
width = "full",
name = string.format(
"|cffffd100Spell ID|r: %d\n|cffffd100%s|r: %s",
spellId,
L["OPT_BEA_COL_SPELL"] or "Spellname",
tostring(entry and entry.name or GetSpellName(spellId) or ("Spell " .. spellId))
),
},
threshold = {
type = "range",
order = 3,
min = 1,
max = 60,
step = 1,
width = "full",
name = L["OPT_BEA_COL_THRESHOLD"] or "Threshold",
get = function()
local current = BEA:GetTrackedBuffEntries()
for _, candidate in ipairs(current) do
if tonumber(candidate.spellId) == spellId then
return tonumber(candidate.threshold) or BEA:GetDefaultThreshold()
end
end
return tonumber(BEA:GetDefaultThreshold()) or 5
end,
set = function(_, val)
BEA:SetTrackedBuffThreshold(spellId, val)
NotifyOptionsChanged()
end,
},
remove = {
type = "execute",
order = 4,
width = "full",
name = REMOVE or (L["OPT_BEA_REMOVE"] or "Remove buff"),
confirm = function()
return string.format("%s?", tostring(entry and entry.name or GetSpellName(spellId) or ("Spell " .. spellId)))
end,
func = function()
local ok, info = BEA:RemoveTrackedBuff(spellId)
if ok then
HMGT:Print(string.format(L["OPT_BEA_MSG_REMOVED"] or "HMGT: buff removed: %s", tostring(info or spellId)))
else
HMGT:Print(L["OPT_BEA_MSG_NOT_FOUND"] or "HMGT: buff not found")
end
NotifyOptionsChanged()
end,
},
},
}
end
local function IsTrackedBuffVisible(entry)
local spellId = tonumber(entry and entry.spellId) or 0
if spellId <= 0 then
return false
end
local search = NormalizeSearchText(GetFilterState().search)
if search == "" then
return true
end
local haystack = table.concat({
tostring(entry and entry.name or GetSpellName(spellId) or ""),
tostring(spellId),
}, " "):lower()
return haystack:find(search, 1, true) ~= nil
end
local function CountVisibleEntries(entries)
local count = 0
for _, entry in ipairs(entries or {}) do
if IsTrackedBuffVisible(entry) then
count = count + 1
end
end
return count
end
function BEA:BuildOptionsGroup()
local draft = GetDraft()
local entries = self:GetTrackedBuffEntries()
local group = {
type = "group",
name = L["BEA_NAME"] or "Buff Ending Announcer",
order = 3,
childGroups = "tree",
args = {
general = {
type = "group",
order = 1,
name = L["OPT_BEA_SECTION_GENERAL"] or "General",
args = {
enabled = {
type = "toggle",
order = 1,
width = "full",
name = L["OPT_BEA_ENABLED"] or "Enable buff ending announcer",
desc = L["OPT_BEA_ENABLED_DESC"] or "Announce tracked buff countdowns in /say",
get = function()
return self:GetSettings().enabled == true
end,
set = function(_, val)
self:GetSettings().enabled = val and true or false
if val then
self:Enable()
else
self:Disable()
end
end,
},
defaultThreshold = {
type = "range",
order = 2,
min = 1,
max = 60,
step = 1,
width = "full",
name = L["OPT_BEA_DEFAULT_THRESHOLD"] or "Default threshold (sec)",
desc = L["OPT_BEA_DEFAULT_THRESHOLD_DESC"] or "Used when you add a new tracked buff",
get = function()
return tonumber(self:GetDefaultThreshold()) or 5
end,
set = function(_, val)
self:GetSettings().announceAtSec = math.floor((tonumber(val) or 5) + 0.5)
self:Refresh()
end,
},
},
},
tracked = {
type = "group",
order = 2,
name = string.format(
"%s (%d)",
L["OPT_BEA_SECTION_BUFFS"] or "Tracked buffs",
#entries
),
args = {
header = {
type = "header",
order = 1,
name = L["OPT_SPELL_BROWSER"] or "Spell Browser",
},
summary = {
type = "description",
order = 2,
width = "full",
name = function()
local currentEntries = BEA:GetTrackedBuffEntries()
return string.format(
"%s\n\n|cffffd100%s|r: %d\n|cffffd100%s|r: %d",
L["OPT_SPELL_BROWSER_DESC"] or "Filter tracked spells by name or Spell ID and apply quick actions to the visible results.",
L["OPT_SPELLS_VISIBLE"] or "Visible spells",
CountVisibleEntries(currentEntries),
L["OPT_BEA_SECTION_BUFFS"] or "Tracked buffs",
#currentEntries
)
end,
},
search = {
type = "input",
order = 3,
width = "full",
name = L["OPT_FILTER_SEARCH"] or "Search",
desc = L["OPT_FILTER_SEARCH_DESC"] or "Search by spell name or Spell ID",
get = function()
return GetFilterState().search or ""
end,
set = function(_, val)
GetFilterState().search = val or ""
NotifyOptionsChanged(false)
end,
},
resetFilters = {
type = "execute",
order = 4,
width = "full",
name = L["OPT_FILTER_RESET"] or "Reset filters",
func = function()
GetFilterState().search = ""
NotifyOptionsChanged(false)
end,
},
addGroup = {
type = "group",
order = 5,
inline = true,
name = L["OPT_BEA_CURRENT"] or "Current tracked buffs",
args = {
addSpellId = {
type = "input",
order = 1,
width = 0.9,
name = L["OPT_BEA_ADD_ID"] or "Add Spell ID",
get = function()
return tostring(draft.addSpellId or "")
end,
set = function(_, val)
draft.addSpellId = val
end,
},
addThreshold = {
type = "range",
order = 2,
min = 1,
max = 60,
step = 1,
width = 1.1,
name = L["OPT_BEA_ADD_THRESHOLD"] or "Threshold",
desc = L["OPT_BEA_ADD_THRESHOLD_DESC"] or "Countdown start in seconds for this buff",
get = function()
return tonumber(draft.addThreshold) or tonumber(self:GetDefaultThreshold()) or 5
end,
set = function(_, val)
draft.addThreshold = tonumber(val) or self:GetDefaultThreshold()
end,
},
addSpell = {
type = "execute",
order = 3,
width = "full",
name = L["OPT_BEA_ADD"] or "Add buff",
func = function()
local sid = tonumber(draft.addSpellId)
local threshold = tonumber(draft.addThreshold) or self:GetDefaultThreshold()
local ok, info = self:AddTrackedBuff(sid, threshold)
if ok then
draft.addSpellId = ""
draft.addThreshold = tonumber(self:GetDefaultThreshold()) or 5
HMGT:Print(string.format(L["OPT_BEA_MSG_ADDED"] or "HMGT: buff added: %s", tostring(info or sid)))
else
HMGT:Print(L["OPT_BEA_MSG_INVALID"] or "HMGT: invalid buff spell ID")
end
NotifyOptionsChanged()
end,
},
},
},
},
},
},
}
if #entries == 0 then
group.args.tracked.args.empty = {
type = "description",
order = 10,
width = "full",
name = L["OPT_BEA_EMPTY"] or "No buffs configured.",
}
else
for index, entry in ipairs(entries) do
local key = "buff_" .. tostring(tonumber(entry.spellId) or index)
local leaf = BuildTrackedBuffLeaf(entry)
leaf.order = 10 + index
leaf.inline = true
leaf.name = " "
leaf.hidden = function()
return not IsTrackedBuffVisible(entry)
end
group.args.tracked.args[key] = leaf
end
group.args.tracked.args.noVisible = {
type = "description",
order = 1000,
width = "full",
hidden = function()
return CountVisibleEntries(BEA:GetTrackedBuffEntries()) > 0
end,
name = L["OPT_BEA_EMPTY"] or "No buffs configured.",
}
end
return group
end
function BEA:GetOptionsGroup()
if not beaOptionsGroup then
beaOptionsGroup = self:BuildOptionsGroup()
else
RefreshTrackedGroup()
end
return beaOptionsGroup
end
HMGT_Config:RegisterOptionsProvider("announcer.buffEndingAnnouncer", function()
return {
path = "announcer",
order = 3,
group = BEA:GetOptionsGroup(),
}
end)