New Release Version 2.0 #3

Merged
Torsten merged 8 commits from dev into main 2026-04-16 09:11:55 +00:00
20 changed files with 85 additions and 1463 deletions

View File

@@ -34,7 +34,7 @@ jobs:
zip -r "/tmp/HailMaryGuildTools-${{ gitea.ref_name }}.zip" HailMaryGuildTools
ls -lh "/tmp/HailMaryGuildTools-${{ gitea.ref_name }}.zip"
- name: Release anlegen oder vorhandene laden
- name: Release anlegen oder laden
run: |
set -e
TAG="${{ gitea.ref_name }}"

View File

@@ -41,26 +41,26 @@ jobs:
TAG="v$VERSION"
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "TAG=$TAG" >> "$GITHUB_ENV"
echo "Gefundene Version: $VERSION"
echo "Neues Tag wäre: $TAG"
echo "$TAG" > /tmp/release_tag.txt
- name: Tag nur erstellen, wenn noch nicht vorhanden
run: |
set -e
cd /tmp/repo
git fetch --tags
TAG=$(cat /tmp/release_tag.txt)
if git rev-parse "${TAG}" >/dev/null 2>&1; then
echo "Tag ${TAG} existiert bereits, nichts zu tun."
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Tag $TAG existiert bereits, nichts zu tun."
exit 0
fi
git config user.name "Gitea Actions"
git config user.email "actions@local"
git tag "${TAG}"
git push origin "${TAG}"
git tag "$TAG"
git push origin "$TAG"

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.git
.gitea
.vscode
*.txt
*.zip

View File

@@ -29,7 +29,7 @@
<!-- AceGUI -->
<Include file="Libs\AceGUI-3.0\AceGUI-3.0.xml"/>
<!-- AceConfig (depends on AceGUI via AceConfigDialog) -->
<!-- AceConfig -->
<Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml"/>
<!-- AceConsole -->

View File

@@ -1691,6 +1691,7 @@ function HMGT:MigrateProfileSettings()
NormalizeMapOverlaySettings(p.mapOverlay)
p.buffEndingAnnouncer = p.buffEndingAnnouncer or {}
NormalizeBuffEndingAnnouncerSettings(p.buffEndingAnnouncer)
p.personalAuras = nil
p.raidTimeline = p.raidTimeline or {}
NormalizeRaidTimelineSettings(p.raidTimeline)
p.notes = p.notes or {}

View File

@@ -4,8 +4,8 @@
## Title: Hail Mary Guild Tools
## Notes: Guild Tools for World of Warcraft
## Version: 1.3
## X-Stable-Version: 1.3
## X-Build-Version: 2.0-beta
## X-Stable-Version: 2.0.0
## X-Build-Version: 2.1.0-beta
## X-Release-Channel: beta
## SavedVariables: HailMaryGuildToolsDB
## OptionalDeps: Ace3, LibSharedMedia-3.0, LibDataBroker-1.1, LibDBIcon-1.0
@@ -41,9 +41,9 @@ Modules\Tracker\NormalTrackerFrames.lua
Modules\Tracker\GroupTrackerFrames.lua
Modules\Tracker\TrackerOptions.lua
# ────── BuffEndingAnnouncer ──────────────────────────────────────────
Modules\BuffEndingAnnouncer\BuffEndingAnnouncer.lua
Modules\BuffEndingAnnouncer\BuffEndingAnnouncerOptions.lua
# ────── AuraExpiry ───────────────────────────────────────────────────
Modules\AuraExpiry\AuraExpiry.lua
Modules\AuraExpiry\AuraExpiryOptions.lua
# ────── MapOverlay ───────────────────────────────────────────────────
Modules\MapOverlay\MapOverlayIconConfig.lua
@@ -56,4 +56,4 @@ Modules\RaidTimeline\RaidTimelineBossAbilityData.lua
Modules\RaidTimeline\RaidTimeline.lua
Modules\RaidTimeline\RaidTimelineBigWigs.lua
Modules\RaidTimeline\RaidTimelineDBM.lua
Modules\RaidTimeline\RaidTimelineOptions.lua
Modules\RaidTimeline\RaidTimelineOptions.lua

View File

@@ -1974,8 +1974,8 @@ function HMGT_Config:Initialize()
end
local buffEndingGroup = BuildNamedModuleGroup(
"announcer.buffEndingAnnouncer",
L["OPT_MODULE_BUFF_ENDING"] or "Buff Ending",
"announcer.auraExpiry",
L["OPT_MODULE_AURA_EXPIRY"] or L["OPT_MODULE_BUFF_ENDING"] or "Aura Expiry",
20
)
if buffEndingGroup then

View File

@@ -1,23 +0,0 @@
------------------------------------------------------------------------
r106 | nebula169 | 2024-08-23 12:53:29 +0000 (Fri, 23 Aug 2024) | 1 line
Changed paths:
M /trunk/LibGroupInSpecT-1.1.lua
Update talent string decoding for v2
------------------------------------------------------------------------
r105 | nebula169 | 2024-08-20 06:44:07 +0000 (Tue, 20 Aug 2024) | 2 lines
Changed paths:
M /trunk/LibGroupInSpecT-1.1.lua
- Handle heroic talents
- Remove tier/column
------------------------------------------------------------------------
r104 | nebula169 | 2024-07-25 01:08:28 +0000 (Thu, 25 Jul 2024) | 1 line
Changed paths:
M /trunk/LibGroupInSpecT-1.1.lua
M /trunk/LibGroupInSpecT-1.1.toc
D /trunk/embeds.xml
Update TOC for 11.0
------------------------------------------------------------------------

View File

@@ -1,240 +0,0 @@
--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 6
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
if not CallbackHandler then return end -- No upgrade needed
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-- Lua APIs
local tconcat = table.concat
local assert, error, loadstring = assert, error, loadstring
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: geterrorhandler
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local next, xpcall, eh = ...
local method, ARGS
local function call() method(ARGS) end
local function dispatch(handlers, ...)
local index
index, method = next(handlers)
if not method then return end
local OLD_ARGS = ARGS
ARGS = ...
repeat
xpcall(call, eh)
index, method = next(handlers, index)
until not method
ARGS = OLD_ARGS
end
return dispatch
]]
local ARGS, OLD_ARGS = {}, {}
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
--------------------------------------------------------------------------
-- CallbackHandler:New
--
-- target - target object to embed public APIs in
-- RegisterName - name of the callback registration API, default "RegisterCallback"
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
-- TODO: Remove this after beta has gone out
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
RegisterName = RegisterName or "RegisterCallback"
UnregisterName = UnregisterName or "UnregisterCallback"
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
UnregisterAllName = "UnregisterAllCallbacks"
end
-- we declare all objects and exported APIs inside this closure to quickly gain access
-- to e.g. function names, the "target" parameter, etc
-- Create the registry object
local events = setmetatable({}, meta)
local registry = { recurse=0, events=events }
-- registry:Fire() - fires the given event/message into the registry
function registry:Fire(eventname, ...)
if not rawget(events, eventname) or not next(events[eventname]) then return end
local oldrecurse = registry.recurse
registry.recurse = oldrecurse + 1
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
registry.recurse = oldrecurse
if registry.insertQueue and oldrecurse==0 then
-- Something in one of our callbacks wanted to register more callbacks; they got queued
for eventname,callbacks in pairs(registry.insertQueue) do
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
for self,func in pairs(callbacks) do
events[eventname][self] = func
-- fire OnUsed callback?
if first and registry.OnUsed then
registry.OnUsed(registry, target, eventname)
first = nil
end
end
end
registry.insertQueue = nil
end
end
-- Registration of a callback, handles:
-- self["method"], leads to self["method"](self, ...)
-- self with function ref, leads to functionref(...)
-- "addonId" (instead of self) with function ref, leads to functionref(...)
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
if type(eventname) ~= "string" then
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
end
method = method or eventname
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
if type(method) ~= "string" and type(method) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
end
local regfunc
if type(method) == "string" then
-- self["method"] calling style
if type(self) ~= "table" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
elseif self==target then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
elseif type(self[method]) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId" or self=thread
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(arg,...) end
else
regfunc = method
end
end
if events[eventname][self] or registry.recurse<1 then
-- if registry.recurse<1 then
-- we're overwriting an existing entry, or not currently recursing. just set it.
events[eventname][self] = regfunc
-- fire OnUsed callback?
if registry.OnUsed and first then
registry.OnUsed(registry, target, eventname)
end
else
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
registry.insertQueue[eventname][self] = regfunc
end
end
-- Unregister a callback
target[UnregisterName] = function(self, eventname)
if not self or self==target then
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
end
if type(eventname) ~= "string" then
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
end
if rawget(events, eventname) and events[eventname][self] then
events[eventname][self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(events[eventname]) then
registry.OnUnused(registry, target, eventname)
end
end
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
registry.insertQueue[eventname][self] = nil
end
end
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
if UnregisterAllName then
target[UnregisterAllName] = function(...)
if select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
for i=1,select("#",...) do
local self = select(i,...)
if registry.insertQueue then
for eventname, callbacks in pairs(registry.insertQueue) do
if callbacks[self] then
callbacks[self] = nil
end
end
end
for eventname, callbacks in pairs(events) do
if callbacks[self] then
callbacks[self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(callbacks) then
registry.OnUnused(registry, target, eventname)
end
end
end
end
end
end
return registry
end
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
-- try to upgrade old implicit embeds since the system is selfcontained and
-- relies on closures to work.

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +0,0 @@
## Interface: 110000, 110002
## Title: Lib: GroupInSpecT-1.1
## Notes: Keeps track of group members and keeps an up-to-date cache of their specialization and talents.
## Version: 1.5.1
## Author: Anyia of HordeYakka (Jubei'Thos)
## X-Category: Library
LibStub\LibStub.lua
CallbackHandler-1.0\CallbackHandler-1.0.lua
lib.xml

View File

@@ -1,51 +0,0 @@
-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local LibStub = _G[LIBSTUB_MAJOR]
-- Check to see is this version of the stub is obsolete
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
-- LibStub:NewLibrary(major, minor)
-- major (string) - the major version of the library
-- minor (string or number ) - the minor version of the library
--
-- returns nil if a newer or same version of the lib is already present
-- returns empty library object or old library object if upgrade is needed
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
-- LibStub:GetLibrary(major, [silent])
-- major (string) - the major version of the library
-- silent (boolean) - if true, library is optional, silently return nil if its not found
--
-- throws an error if the library can not be found (except silent is set)
-- returns the library object if found
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
-- LibStub:IterateLibraries()
--
-- Returns an iterator for the currently registered libraries
function LibStub:IterateLibraries()
return pairs(self.libs)
end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

View File

@@ -1,6 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="LibGroupInSpecT-1.1.lua"/>
</Ui>

View File

@@ -116,6 +116,7 @@ L["OPT_MAP_POI_REMOVE_INDEX"] = "Index entfernen"
L["OPT_MAP_POI_REMOVE"] = "POI entfernen"
L["OPT_MAP_POI_LIST"] = "Aktuelle POIs"
L["OPT_MAP_POI_EMPTY"] = "Keine POIs konfiguriert."
L["OPT_MAP_POI_SELECT_HINT"] = "Waehle links im Baum einen POI aus, um ihn zu bearbeiten."
L["OPT_MAP_POI_CURRENT_SET"] = "HMGT: aktuelle Position uebernommen"
L["OPT_MAP_POI_CURRENT_FAILED"] = "HMGT: aktuelle Position konnte nicht ermittelt werden"
L["OPT_MAP_POI_ADDED"] = "HMGT: POI hinzugefuegt"
@@ -129,7 +130,8 @@ L["OPT_SHOW_MINIMAP_ICON"] = "Minimap-Icon anzeigen"
L["OPT_COMMANDS"] = "Commands"
L["OPT_MODULES"] = "Modules"
L["OPT_MODULE_TRACKER"] = "Tracker"
L["OPT_MODULE_BUFF_ENDING"] = "Buff Ending"
L["OPT_MODULE_BUFF_ENDING"] = "Aura-Ablauf"
L["OPT_MODULE_AURA_EXPIRY"] = "Aura-Ablauf"
L["OPT_MODULE_MAP_OVERLAY"] = "Map Overlay"
-- ── Options: tracker shared ───────────────────────────────────
@@ -246,7 +248,6 @@ L["OPT_RT_ASSIGNMENT_LEAD_TIME"] = "Vorlaufzeit fuer Zuweisung"
L["OPT_RT_ASSIGNMENT_LEAD_TIME_DESC"] = "Wie viele Sekunden vor dem geplanten Einsatz der zugewiesene Spieler ausgewaehlt werden soll."
L["OPT_RT_ALERT_HEADER"] = "Hinweisfenster"
L["OPT_RT_UNLOCK"] = "Hinweisfenster entsperren"
L["OPT_RT_PREVIEW"] = "Vorschau anzeigen"
L["OPT_RT_ALERT_COLOR"] = "Textfarbe"
L["OPT_RT_ALERT_PREVIEW"] = "Gelassenheit in 5"
L["OPT_RT_DESC"] = "Lege hier Encounter-Timelines an und oeffne fuer die visuelle Planung den interaktiven Ace3-Timeline-Editor."
@@ -311,7 +312,6 @@ L["OPT_RT_INVALID_SPELL"] = "HMGT: ungueltige Spell-ID"
L["OPT_RT_TIMELINE_VIEWPORT"] = "Timeline-Fenster"
L["OPT_RT_TIMELINE_EMPTY_WINDOW"] = "Im aktuellen Zeitfenster sind keine Cooldowns."
L["OPT_RT_TIMELINE_EDITOR"] = "Interaktive Timeline"
L["OPT_RT_OPEN_EDITOR"] = "Timeline oeffnen"
L["OPT_RT_START_TEST"] = "Timeline-Test starten"
L["OPT_RT_STOP_TEST"] = "Test stoppen"
L["OPT_RT_TEST_HINT"] = "Laesst die Encounter-Timeline ausserhalb des Kampfes ablaufen, damit du Zuweisungen, Whisper und Debug-Ausgaben pruefen kannst."
@@ -341,11 +341,12 @@ L["GCD_TITLE"] = "|cff77dd77Gruppen-Cooldowns|r"
L["IT_NAME"] = "Interrupt Tracker"
L["RCD_NAME"] = "Raid Cooldown Tracker"
L["GCD_NAME"] = "Gruppen-Cooldown-Tracker"
L["BEA_NAME"] = "Buff-Ende-Ansager"
L["BEA_NAME"] = "Aura-Ablauf"
L["AE_NAME"] = "Aura-Ablauf"
L["AEM_NAME"] = "Auto-Gegner-Markierung"
L["OPT_BEA_ENABLED"] = "Buff-Ende-Ansager aktivieren"
L["OPT_BEA_ENABLED_DESC"] = "Sagt Countdown fuer verfolgte Buffs in /say an"
L["OPT_BEA_ENABLED"] = "Aura-Ablauf aktivieren"
L["OPT_BEA_ENABLED_DESC"] = "Sagt Countdowns fuer verfolgte Auren und Kanaele in /say an"
L["OPT_BEA_ANNOUNCE_AT"] = "Ansage ab (Sek.)"
L["OPT_BEA_ANNOUNCE_AT_DESC"] = "Startet die Countdown-Ansage, sobald die Restdauer darunter liegt"
L["OPT_BEA_DEFAULT_THRESHOLD"] = "Standard-Threshold (Sek.)"

View File

@@ -116,6 +116,7 @@ L["OPT_MAP_POI_REMOVE_INDEX"] = "Remove index"
L["OPT_MAP_POI_REMOVE"] = "Remove POI"
L["OPT_MAP_POI_LIST"] = "Current POIs"
L["OPT_MAP_POI_EMPTY"] = "No POIs configured."
L["OPT_MAP_POI_SELECT_HINT"] = "Select a POI in the tree on the left to edit it."
L["OPT_MAP_POI_CURRENT_SET"] = "HMGT: current position copied"
L["OPT_MAP_POI_CURRENT_FAILED"] = "HMGT: could not determine current position"
L["OPT_MAP_POI_ADDED"] = "HMGT: POI added"
@@ -129,7 +130,8 @@ L["OPT_SHOW_MINIMAP_ICON"] = "Show Minimap Icon"
L["OPT_COMMANDS"] = "Commands"
L["OPT_MODULES"] = "Modules"
L["OPT_MODULE_TRACKER"] = "Tracker"
L["OPT_MODULE_BUFF_ENDING"] = "Buff Ending"
L["OPT_MODULE_BUFF_ENDING"] = "Aura Expiry"
L["OPT_MODULE_AURA_EXPIRY"] = "Aura Expiry"
L["OPT_MODULE_MAP_OVERLAY"] = "Map Overlay"
-- ── Options: tracker shared ───────────────────────────────────
@@ -244,7 +246,6 @@ L["OPT_RT_ASSIGNMENT_LEAD_TIME"] = "Assignment lead time"
L["OPT_RT_ASSIGNMENT_LEAD_TIME_DESC"] = "How many seconds before the planned use the assigned player should be selected."
L["OPT_RT_ALERT_HEADER"] = "Alert frame"
L["OPT_RT_UNLOCK"] = "Unlock alert frame"
L["OPT_RT_PREVIEW"] = "Preview alert"
L["OPT_RT_ALERT_COLOR"] = "Text colour"
L["OPT_RT_ALERT_PREVIEW"] = "Tranquility in 5"
L["OPT_RT_DESC"] = "Create encounter timelines here and open the interactive Ace3 timeline editor for visual planning."
@@ -309,7 +310,6 @@ L["OPT_RT_INVALID_SPELL"] = "HMGT: invalid spell ID"
L["OPT_RT_TIMELINE_VIEWPORT"] = "Timeline window"
L["OPT_RT_TIMELINE_EMPTY_WINDOW"] = "No cooldowns in the current window."
L["OPT_RT_TIMELINE_EDITOR"] = "Interactive Timeline"
L["OPT_RT_OPEN_EDITOR"] = "Open timeline"
L["OPT_RT_START_TEST"] = "Start timeline test"
L["OPT_RT_STOP_TEST"] = "Stop test"
L["OPT_RT_TEST_HINT"] = "Runs the encounter timeline outside of combat so you can verify assignments, whispers and debug output."
@@ -341,11 +341,12 @@ L["GCD_TITLE"] = "|cff77dd77Group Cooldowns|r"
L["IT_NAME"] = "Interrupt Tracker"
L["RCD_NAME"] = "Raid Cooldown Tracker"
L["GCD_NAME"] = "Group Cooldown Tracker"
L["BEA_NAME"] = "Buff Ending Announcer"
L["BEA_NAME"] = "Aura Expiry"
L["AE_NAME"] = "Aura Expiry"
L["AEM_NAME"] = "Auto Enemy Marker"
L["OPT_BEA_ENABLED"] = "Enable buff ending announcer"
L["OPT_BEA_ENABLED_DESC"] = "Announce tracked buff countdowns in /say"
L["OPT_BEA_ENABLED"] = "Enable aura expiry"
L["OPT_BEA_ENABLED_DESC"] = "Announce countdowns for tracked auras and channels in /say"
L["OPT_BEA_ANNOUNCE_AT"] = "Announce from (sec)"
L["OPT_BEA_ANNOUNCE_AT_DESC"] = "Start countdown announcements when remaining buff duration is at or below this value"
L["OPT_BEA_DEFAULT_THRESHOLD"] = "Default threshold (sec)"

View File

@@ -1,4 +1,4 @@
-- Modules/BuffEndingAnnouncer/BuffEndingAnnouncer.lua
-- Modules/AuraExpiry/AuraExpiry.lua
-- Announces tracked buffs in SAY shortly before they expire.
local ADDON_NAME = "HailMaryGuildTools"
@@ -7,7 +7,8 @@ if not HMGT then return end
local L = LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME, true) or {}
local BEA = HMGT:NewModule("BuffEndingAnnouncer")
local BEA = HMGT:NewModule("AuraExpiry")
HMGT.AuraExpiry = BEA
HMGT.BuffEndingAnnouncer = BEA
BEA.runtimeEnabled = false
@@ -426,6 +427,7 @@ function BEA:StopRuntime()
end
function BEA:OnInitialize()
HMGT.AuraExpiry = self
HMGT.BuffEndingAnnouncer = self
end

View File

@@ -1,9 +1,9 @@
-- Modules/BuffEndingAnnouncer/BuffEndingAnnouncerOptions.lua
-- Modules/AuraExpiry/AuraExpiryOptions.lua
local ADDON_NAME = "HailMaryGuildTools"
local HMGT = LibStub("AceAddon-3.0"):GetAddon(ADDON_NAME)
if not HMGT then return end
local BEA = HMGT.BuffEndingAnnouncer
local BEA = HMGT.AuraExpiry or HMGT.BuffEndingAnnouncer
if not BEA then return end
if not HMGT_Config or not HMGT_Config.RegisterOptionsProvider then return end
@@ -197,7 +197,7 @@ function BEA:BuildOptionsGroup()
local group = {
type = "group",
name = L["BEA_NAME"] or "Buff Ending Announcer",
name = L["AE_NAME"] or L["BEA_NAME"] or "Aura Expiry",
order = 3,
childGroups = "tree",
args = {
@@ -400,7 +400,7 @@ function BEA:GetOptionsGroup()
return beaOptionsGroup
end
HMGT_Config:RegisterOptionsProvider("announcer.buffEndingAnnouncer", function()
HMGT_Config:RegisterOptionsProvider("announcer.auraExpiry", function()
return {
path = "announcer",
order = 3,

View File

@@ -881,9 +881,6 @@ function WorldMapPinMixin:OnLoad()
if self.SetScalingLimits then
self:SetScalingLimits(1, 1.0, 1.2)
end
if self.SetPassThroughButtons then
self:SetPassThroughButtons("")
end
end
function WorldMapPinMixin:OnAcquired(poi, settings, owner)

View File

@@ -8,6 +8,7 @@ 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 AceConfigDialog = LibStub("AceConfigDialog-3.0", true)
local LSM = LibStub("LibSharedMedia-3.0", true)
local FONT_OUTLINE_VALUES = {
@@ -43,6 +44,15 @@ local function Notify(rebuild)
AceConfigRegistry:NotifyChange(ADDON_NAME)
end
local function SelectRaidTimelineGeneral()
if not AceConfigDialog or type(AceConfigDialog.SelectGroup) ~= "function" then
return
end
pcall(function()
AceConfigDialog:SelectGroup(ADDON_NAME, "modules", "raidTimeline", "general")
end)
end
local function GetDrafts()
HMGT._raidTimelineDraft = HMGT._raidTimelineDraft or {
addEncounterId = "",
@@ -523,13 +533,9 @@ local function BuildEncounterDetailGroup(encounterId)
diffOrder = diffOrder + 0.01
end
args.openTimelineEditor = {
type = "execute", order = 7, width = "full", name = L["OPT_RT_OPEN_EDITOR"] or "Open timeline",
func = function() if RT.OpenTimelineEditor then RT:OpenTimelineEditor(encounterId) end end,
}
args.runTest = {
type = "execute",
order = 7.5,
order = 7,
width = "full",
name = function()
if RT:IsTestRunning(encounterId) then
@@ -549,19 +555,19 @@ local function BuildEncounterDetailGroup(encounterId)
}
args.testHint = {
type = "description",
order = 7.6,
order = 7.1,
width = "full",
name = L["OPT_RT_TEST_HINT"] or "Runs the encounter timeline outside of combat so you can verify assignments, whispers and debug output.",
}
args.editorHint = {
type = "description", order = 8, width = "full",
name = L["OPT_RT_TIMELINE_HINT"] or "Click the bar to add a cooldown. Drag markers horizontally to change the time. Mousewheel scrolls, Ctrl+Mousewheel zooms.",
}
args.encounterDelete = {
type = "execute", order = 9, width = "full", name = DELETE or "Delete",
type = "execute", order = 8, width = "full", name = DELETE or "Delete",
disabled = function() return not RT:IsLocalEditor() end,
confirm = function() return string.format(L["OPT_RT_DELETE_ENCOUNTER_CONFIRM"] or "Delete raid timeline for encounter %d?", tonumber(encounterId) or 0) end,
func = function() RT:RemoveEncounter(encounterId); Notify(true) end,
func = function()
RT:RemoveEncounter(encounterId)
Notify(true)
SelectRaidTimelineGeneral()
end,
}
args.entryBreak = { type = "description", order = 10, width = "full", name = " " }
@@ -569,7 +575,14 @@ local function BuildEncounterDetailGroup(encounterId)
args[key] = value
end
return { type = "group", name = GetBossTreeLabel(encounterId), args = args }
return {
type = "group",
name = GetBossTreeLabel(encounterId),
hidden = function()
return RT:GetEncounter(encounterId) == nil
end,
args = args,
}
end
local function BuildRaidTreeArgs()
@@ -679,34 +692,33 @@ function RT:GetOptionsGroup()
set = function(_, val)
RT:GetSettings().unlocked = val and true or false
RT:ApplyAlertStyle()
if val then RT:ShowPreview() end
if val then
RT:ShowPreview()
else
RT:HideAlert()
end
end,
},
preview = {
type = "toggle", order = 5, width = "double", name = L["OPT_RT_PREVIEW"] or "Preview alert",
get = function() return RT.previewAlertActive == true end,
set = function(_, val) if val then RT:ShowPreview() else RT:HideAlert() end end,
},
alertFont = {
type = "select", order = 6, width = 1.4, name = L["OPT_FONT"] or "Typeface",
type = "select", order = 5, width = 1.4, name = L["OPT_FONT"] or "Typeface",
dialogControl = "LSM30_Font",
values = AceGUIWidgetLSMlists and AceGUIWidgetLSMlists.font or (LSM and LSM:HashTable("font")) or {},
get = function() return RT:GetSettings().alertFont or "Friz Quadrata TT" end,
set = function(_, val) RT:GetSettings().alertFont = val; RT:ApplyAlertStyle() end,
},
alertFontSize = {
type = "range", order = 7, min = 10, max = 72, step = 1, width = 1.0, name = L["OPT_FONT_SIZE"] or "Font size",
type = "range", order = 6, min = 10, max = 72, step = 1, width = 1.0, name = L["OPT_FONT_SIZE"] or "Font size",
get = function() return tonumber(RT:GetSettings().alertFontSize) or 30 end,
set = function(_, val) RT:GetSettings().alertFontSize = math.floor((tonumber(val) or 30) + 0.5); RT:ApplyAlertStyle() end,
},
alertFontOutline = {
type = "select", order = 8, width = 1.0, name = L["OPT_FONT_OUTLINE"] or "Font outline",
type = "select", order = 7, width = 1.0, name = L["OPT_FONT_OUTLINE"] or "Font outline",
values = FONT_OUTLINE_VALUES,
get = function() return RT:GetSettings().alertFontOutline or "OUTLINE" end,
set = function(_, val) RT:GetSettings().alertFontOutline = val; RT:ApplyAlertStyle() end,
},
alertColor = {
type = "color", order = 9, width = 0.8, name = L["OPT_RT_ALERT_COLOR"] or "Text colour", hasAlpha = true,
type = "color", order = 8, width = 0.8, name = L["OPT_RT_ALERT_COLOR"] or "Text colour", hasAlpha = true,
get = function()
local color = RT:GetSettings().alertColor or {}
return color.r or 1, color.g or 0.82, color.b or 0.15, color.a or 1

View File

@@ -14,7 +14,7 @@ It combines cooldown tracking, encounter reminders, notes, and map utilities in
- Custom tracker system with individual tracker configs
- Interrupt, raid cooldown, and group cooldown tracking
- Per-tracker bar and icon layouts
- Buff Ending Announcer for selected buffs and channels
- Aura Expiry for selected buffs and channels
- Raid Timeline for encounter-based text reminders and raid cooldown assignments
- Notes window for raid or personal note management
- Map Overlay with custom world map POIs
@@ -28,7 +28,7 @@ It combines cooldown tracking, encounter reminders, notes, and map utilities in
The tracker system is the core feature of HMGT.
It supports multiple independent tracker bars with custom spell categories, display modes, growth directions, party-frame attachment, and demo/test modes.
### Buff Ending Announcer
### Aura Expiry
Tracks selected buffs and channel-based spells and warns before they expire.
@@ -83,8 +83,8 @@ Provides a dedicated notes window for raid notes, personal notes, and drafts.
Shared windows and developer tooling
- `Modules/Tracker/`
Tracker rendering, data, and options
- `Modules/BuffEndingAnnouncer/`
Buff ending module and options
- `Modules/AuraExpiry/`
Aura expiry module and options
- `Modules/MapOverlay/`
World map POIs, icon config, and options
- `Modules/RaidTimeline/`
@@ -113,4 +113,4 @@ Recent `2.0` highlights include:
- Improved party-frame attachment and upward bar layouts
- Persistent tracker category selections
- Tracker removal confirmation
- Improved bar coloring behavior
- Improved bar coloring behavior