feat: Add Personal Auras module for tracking debuffs on the player

- Introduced a new module for Personal Auras that allows players to track selected debuffs on themselves in a movable frame.
- Implemented functionality to manage tracked debuffs, including adding and removing spells.
- Added options for configuring the appearance and behavior of the Personal Auras frame.
- Updated the readme to include information about the new Personal Auras feature.
This commit is contained in:
Torsten Brendgen
2026-04-12 00:04:34 +02:00
parent 01eeae9603
commit 391e581d32
11 changed files with 1034 additions and 5 deletions

View File

@@ -0,0 +1,308 @@
local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
local PA = HMGT.PersonalAuras
if not PA 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", true)
local optionsGroup
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)
if HMGT_SpellData and type(HMGT_SpellData.GetSpellIcon) == "function" then
local icon = HMGT_SpellData.GetSpellIcon(tonumber(spellId) or 0)
if icon and icon ~= "" then
return icon
end
end
if C_Spell and type(C_Spell.GetSpellTexture) == "function" then
local icon = C_Spell.GetSpellTexture(tonumber(spellId) or 0)
if icon and icon ~= "" then
return icon
end
end
return 136243
end
local function GetDraft()
HMGT._personalAurasDraft = HMGT._personalAurasDraft or {}
return HMGT._personalAurasDraft
end
local function NotifyOptionsChanged()
if optionsGroup then
local fresh = PA:BuildOptionsGroup()
if type(fresh) == "table" and type(fresh.args) == "table" then
optionsGroup.args = fresh.args
optionsGroup.childGroups = fresh.childGroups
end
end
if AceConfigRegistry and type(AceConfigRegistry.NotifyChange) == "function" then
AceConfigRegistry:NotifyChange(ADDON_NAME)
end
end
local function BuildTrackedLeaf(entry)
local spellId = tonumber(entry and entry.spellId) or 0
return {
type = "group",
name = tostring(entry and entry.name or ("Spell " .. tostring(spellId))),
args = {
header = {
type = "header",
order = 1,
name = function()
local icon = GetSpellIcon(spellId)
local name = tostring(GetSpellName(spellId) or ("Spell " .. tostring(spellId)))
return string.format("|T%s:16:16:0:0|t %s", tostring(icon), name)
end,
},
details = {
type = "description",
order = 2,
width = "full",
name = function()
local isActive = false
for _, activeEntry in ipairs(PA:GetActiveDebuffEntries()) do
if tonumber(activeEntry.spellId) == spellId then
isActive = true
break
end
end
return string.format(
"|cffffd100Spell ID|r: %d\n|cffffd100%s|r: %s",
spellId,
L["OPT_PA_ACTIVE"] or "Active",
isActive and (YES or "Yes") or (NO or "No")
)
end,
},
remove = {
type = "execute",
order = 3,
width = "full",
name = L["OPT_PA_REMOVE"] or "Remove debuff",
func = function()
local ok, info = PA:RemoveTrackedDebuff(spellId)
if ok then
HMGT:Print(string.format(L["OPT_PA_MSG_REMOVED"] or "HMGT: debuff removed: %s", tostring(info or spellId)))
else
HMGT:Print(L["OPT_PA_MSG_NOT_FOUND"] or "HMGT: debuff not found")
end
NotifyOptionsChanged()
end,
},
},
}
end
function PA:BuildOptionsGroup()
local draft = GetDraft()
local entries = self:GetTrackedEntries()
local group = {
type = "group",
name = L["PA_NAME"] or "Personal Auras",
order = 4,
childGroups = "tree",
args = {
general = {
type = "group",
order = 1,
name = L["OPT_PA_SECTION_GENERAL"] or "General",
args = {
enabled = {
type = "toggle",
order = 1,
width = "full",
name = L["OPT_PA_ENABLED"] or "Enable personal auras",
desc = L["OPT_PA_ENABLED_DESC"] or "Show tracked debuffs on your current player in a movable frame",
get = function()
return self:GetSettings().enabled == true
end,
set = function(_, val)
self:GetSettings().enabled = val and true or false
self:Refresh()
end,
},
unlocked = {
type = "toggle",
order = 2,
width = "full",
name = L["OPT_PA_UNLOCK"] or "Unlock frame",
desc = L["OPT_PA_UNLOCK_DESC"] or "Show the frame placeholder and allow it to be moved",
get = function()
return self:GetSettings().unlocked == true
end,
set = function(_, val)
self:GetSettings().unlocked = val and true or false
self:Refresh()
end,
},
width = {
type = "range",
order = 3,
min = 160,
max = 420,
step = 1,
width = "full",
name = L["OPT_PA_WIDTH"] or "Frame width",
get = function()
return tonumber(self:GetSettings().width) or 260
end,
set = function(_, val)
self:GetSettings().width = math.floor((tonumber(val) or 260) + 0.5)
self:Refresh()
end,
},
rowHeight = {
type = "range",
order = 4,
min = 18,
max = 42,
step = 1,
width = "full",
name = L["OPT_PA_ROW_HEIGHT"] or "Row height",
get = function()
return tonumber(self:GetSettings().rowHeight) or 24
end,
set = function(_, val)
self:GetSettings().rowHeight = math.floor((tonumber(val) or 24) + 0.5)
self:Refresh()
end,
},
iconSize = {
type = "range",
order = 5,
min = 14,
max = 32,
step = 1,
width = "full",
name = L["OPT_PA_ICON_SIZE"] or "Icon size",
get = function()
return tonumber(self:GetSettings().iconSize) or 20
end,
set = function(_, val)
self:GetSettings().iconSize = math.floor((tonumber(val) or 20) + 0.5)
self:Refresh()
end,
},
fontSize = {
type = "range",
order = 6,
min = 8,
max = 24,
step = 1,
width = "full",
name = L["OPT_PA_FONT_SIZE"] or "Font size",
get = function()
return tonumber(self:GetSettings().fontSize) or 12
end,
set = function(_, val)
self:GetSettings().fontSize = math.floor((tonumber(val) or 12) + 0.5)
self:Refresh()
end,
},
},
},
tracked = {
type = "group",
order = 2,
name = string.format(
"%s (%d)",
L["OPT_PA_SECTION_DEBUFFS"] or "Tracked debuffs",
#entries
),
args = {
addSpellId = {
type = "input",
order = 1,
width = "full",
name = L["OPT_PA_ADD_ID"] or "Add Spell ID",
get = function()
return tostring(draft.spellId or "")
end,
set = function(_, value)
draft.spellId = tostring(value or "")
end,
},
add = {
type = "execute",
order = 2,
width = "full",
name = L["OPT_PA_ADD"] or "Add debuff",
func = function()
local sid = tonumber(draft.spellId)
local ok, info = self:AddTrackedDebuff(sid)
if ok then
HMGT:Print(string.format(L["OPT_PA_MSG_ADDED"] or "HMGT: debuff added: %s", tostring(info or sid)))
draft.spellId = ""
NotifyOptionsChanged()
else
HMGT:Print(L["OPT_PA_MSG_INVALID"] or "HMGT: invalid debuff spell ID")
end
end,
},
},
},
},
}
if #entries == 0 then
group.args.tracked.args.empty = {
type = "description",
order = 10,
width = "full",
name = L["OPT_PA_EMPTY"] or "No debuffs configured.",
}
else
for index, entry in ipairs(entries) do
local spellId = tonumber(entry.spellId) or index
group.args.tracked.args["debuff_" .. tostring(spellId)] = {
type = "group",
order = 10 + index,
name = function()
return string.format("|T%s:16:16:0:0|t %s", tostring(entry.icon or GetSpellIcon(spellId)), tostring(entry.name or GetSpellName(spellId) or ("Spell " .. tostring(spellId))))
end,
inline = true,
args = BuildTrackedLeaf(entry).args,
}
end
end
return group
end
function PA:GetOptionsGroup()
if not optionsGroup then
optionsGroup = self:BuildOptionsGroup()
end
return optionsGroup
end
HMGT_Config:RegisterOptionsProvider("personalAuras", function()
return {
path = "personalAuras",
order = 4,
group = PA:GetOptionsGroup(),
}
end)