Add multiple spell ids support to AuraTrigger

Before AuraTrigger only supported a single spell id but now multiple
spells can activate the same trigger.

Related changes:
- Change the glue between AuraList and AuraTrigger to match this new functionality.
- Update the default frame config
This commit is contained in:
omicron committed 2026-06-26 01:25:10 +02:00
1 parent 8be0732930
commit eaebe470b9
3 files changed
+128 -57

No files matched your search

+37 -24
View File
@@ -31,6 +31,19 @@ local colors = {
light_blue = { 0.7, 0.7, 1 }, light_blue = { 0.7, 0.7, 1 },
} }
---@param list number[]
---@return table<number, true>
local function set(list)
local s = {}
for _, v in ipairs(list) do
s[v] = true
end
return s
end
local AURAS_PRIEST_RENEW = set({ 139, 6074, 6075, 6076, 6077, 6078, 10927, 10928, 10929, 25315, 25221, 25222 })
local AURAS_PRIEST_PWS = set({ 17, 592, 600, 3747, 6065, 6066, 10898, 10899, 10900, 10901, 25217, 25218 })
local function RangeConfig() local function RangeConfig()
local _, class = UnitClass("player") local _, class = UnitClass("player")
if class == "SHAMAN" then if class == "SHAMAN" then
@@ -41,7 +54,7 @@ local function RangeConfig()
} }
elseif class == "PRIEST" then elseif class == "PRIEST" then
return { return {
friendly = "Flash Heal", friendly = "Heal",
enemy = "Smite", enemy = "Smite",
fade = 0.2, fade = 0.2,
} }
@@ -134,15 +147,15 @@ local function MouseConfig()
button = "wheel-up", button = "wheel-up",
mods = {}, mods = {},
kind = "macro", kind = "macro",
data = "/use [@UNIT,help]Flash Heal", data = "/use [@UNIT,help]Lesser Heal",
}, },
{ button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Renew" }, { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Heal" },
-- alt -- alt
{ button = "mouse1", mods = { alt = true }, kind = "spell", data = "Power Word: Life" }, { button = "mouse1", mods = { alt = true }, kind = "spell", data = "Power Word: Life" },
{ button = "mouse2", mods = { alt = true }, kind = "spell", data = "Pain Suppression" }, { button = "mouse2", mods = { alt = true }, kind = "spell", data = "Pain Suppression" },
{ button = "mouse3", mods = { alt = true }, kind = "spell", data = "Power Infusion" }, { button = "mouse3", mods = { alt = true }, kind = "spell", data = "Power Infusion" },
{ button = "wheel-up", mods = { alt = true }, kind = "spell", data = "Rapture" }, { button = "wheel-up", mods = { alt = true }, kind = "spell", data = "Renew" },
{ button = "wheel-down", mods = { alt = true }, kind = "spell", data = "Power Word: Shield" }, { button = "wheel-down", mods = { alt = true }, kind = "spell", data = "Power Word: Shield" },
-- Shift -- Shift
@@ -282,7 +295,7 @@ local function TriggerClassConfig()
return { return {
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 32594, spellIds = set({ 32594 }),
own = true, -- Second Earth Shield on yourself own = true, -- Second Earth Shield on yourself
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -296,7 +309,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 29203, spellIds = set({ 29203 }),
own = true, -- Healing Way own = true, -- Healing Way
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -310,7 +323,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 16237, spellIds = set({ 16237 }),
own = true, -- Ancestral Fortitude own = true, -- Ancestral Fortitude
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -338,7 +351,7 @@ local function TriggerClassConfig()
return { return {
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 17, spellIds = AURAS_PRIEST_PWS,
own = true, -- Power Word: Shield own = true, -- Power Word: Shield
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -352,7 +365,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 33206, spellIds = set({ 33206 }),
own = true, -- Pain Suppression own = true, -- Pain Suppression
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -367,7 +380,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 41635, spellIds = set({ 41635 }),
own = true, -- Prayer of Mending own = true, -- Prayer of Mending
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -381,7 +394,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 139, spellIds = AURAS_PRIEST_RENEW,
own = true, -- Renew own = true, -- Renew
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -395,7 +408,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 194384, spellIds = set({ 194384 }),
own = true, -- Atonement own = true, -- Atonement
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -410,7 +423,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 10060, spellIds = set({ 10060 }),
own = true, -- Power Infusion own = true, -- Power Infusion
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -438,7 +451,7 @@ local function TriggerClassConfig()
return { return {
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 287280, -- Glimmer of Light spellIds = set({ 287280 }), -- Glimmer of Light
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -453,7 +466,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 25771, -- Forbearance spellIds = set({ 25771 }), -- Forbearance
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
size = 17, size = 17,
@@ -467,7 +480,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 53563, -- Beacon of Light spellIds = set({ 53563 }), -- Beacon of Light
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -480,7 +493,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 156910, -- Beacon of Faith spellIds = set({ 156910 }), -- Beacon of Faith
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -493,7 +506,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 200025, -- Beacon of Virtue spellIds = set({ 200025 }), -- Beacon of Virtue
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -506,7 +519,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 1044, -- Blessing of Freedom spellIds = set({ 1044 }), -- Blessing of Freedom
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -520,7 +533,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 1111, -- Blessing of Spellwarding spellIds = set({ 1111 }), -- Blessing of Spellwarding
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -534,7 +547,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 1022, -- Blessing of Protection spellIds = set({ 1022 }), -- Blessing of Protection
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -548,7 +561,7 @@ local function TriggerClassConfig()
}, },
{ {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 6940, -- Blessing of Saccrifice spellIds = set({ 6940 }), -- Blessing of Saccrifice
own = true, own = true,
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
@@ -596,7 +609,7 @@ local function MakeDebuffTrigger(slot, spellid, color, stacks)
end end
return { return {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = spellid, spellIds = set({ spellid }),
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
size = 15, size = 15,
@@ -676,7 +689,7 @@ local function TriggerConfig()
-- Some more debuffs in the bottom row -- Some more debuffs in the bottom row
table.insert(triggers, { table.insert(triggers, {
kind = "AuraTrigger", kind = "AuraTrigger",
spellId = 240443, -- Bursting spellIds = set({ 240443 }), -- Bursting
indicator = { indicator = {
kind = "SquareIndicator", kind = "SquareIndicator",
size = 17, size = 17,
+25 -9
View File
@@ -16,6 +16,8 @@
-- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.
local omi = select(2, ...) local omi = select(2, ...)
local types = omi.GetModule("types") local types = omi.GetModule("types")
local AuraTrigger = types.AuraTrigger
local StatusTrigger = types.StatusTrigger
--- AuraList keeps track of all the auras attached to a unitframe --- AuraList keeps track of all the auras attached to a unitframe
---@class AuraList: Object ---@class AuraList: Object
@@ -180,21 +182,35 @@ function AuraList:Init(unitframe)
self.triggersByStatus = {} self.triggersByStatus = {}
end end
---@param trigger AuraTrigger | StatusTrigger ---@param trigger StatusTrigger
function AuraList:AddTrigger(trigger) function AuraList:AddStatusTrigger(trigger)
table.insert(self.triggers, trigger) table.insert(self.triggers, trigger)
local spellId = trigger.spellId
local status = trigger.status local status = trigger.status
if spellId then
if self.triggersBySpell[spellId] == nil then
self.triggersBySpell[spellId] = {}
end
table.insert(self.triggersBySpell[spellId], trigger)
else
if self.triggersByStatus[status] == nil then if self.triggersByStatus[status] == nil then
self.triggersByStatus[status] = {} self.triggersByStatus[status] = {}
end end
table.insert(self.triggersByStatus[status], trigger) table.insert(self.triggersByStatus[status], trigger)
end
---@param trigger AuraTrigger
function AuraList:AddAuraTrigger(trigger)
table.insert(self.triggers, trigger)
for spellId in pairs(trigger.spellIds) do
if self.triggersBySpell[spellId] == nil then
self.triggersBySpell[spellId] = {}
end
table.insert(self.triggersBySpell[spellId], trigger)
end
end
---@param trigger AuraTrigger | StatusTrigger
function AuraList:AddTrigger(trigger)
if trigger:IsInstanceOf(AuraTrigger) then
self:AddAuraTrigger(trigger)
elseif trigger:IsInstanceOf(StatusTrigger) then
self:AddStatusTrigger(trigger)
else
error("AddTrigger: trigger is neither an AuraTrigger nor a StatusTrigger")
end end
end end
+66 -24
View File
@@ -21,7 +21,7 @@ local Trigger = types.Trigger
---AuraTrigger is a Trigger that can be attached to AuraList as datasource ---AuraTrigger is a Trigger that can be attached to AuraList as datasource
---@class AuraTrigger: Trigger ---@class AuraTrigger: Trigger
---@field spellId number ---@field spellIds table<number, true>
---@field count number ---@field count number
---@field requiredCount number ---@field requiredCount number
local AuraTrigger = types.CreateClass("AuraTrigger", Trigger) local AuraTrigger = types.CreateClass("AuraTrigger", Trigger)
@@ -33,7 +33,8 @@ types.AuraTrigger = AuraTrigger
---@param config table ---@param config table
---@return AuraTrigger ---@return AuraTrigger
function AuraTrigger.CreateFromConfig(unit, config) function AuraTrigger.CreateFromConfig(unit, config)
local trigger = AuraTrigger:new(config.spellId, config.own, config.requiredCount, config.invert, config.defaultData) local trigger =
AuraTrigger:new(config.spellIds, config.own, config.requiredCount, config.invert, config.defaultData)
unit.auras:AddTrigger(trigger) unit.auras:AddTrigger(trigger)
return trigger return trigger
end end
@@ -47,29 +48,33 @@ function AuraTrigger.new(cls, ...)
end end
--- Initialize a new AuraTrigger object --- Initialize a new AuraTrigger object
---@param spellId number ---@param spellIds table<number, true>
---@param own boolean ---@param own boolean
---@param requiredCount number | nil ---@param requiredCount number | nil
---@param invert boolean | nil ---@param invert boolean | nil
---@param defaultData table | nil ---@param defaultData table | nil
function AuraTrigger:Init(spellId, own, requiredCount, invert, defaultData) function AuraTrigger:Init(spellIds, own, requiredCount, invert, defaultData)
Trigger.Init(self, invert, defaultData) Trigger.Init(self, invert, defaultData)
self.spellId = spellId self.spellIds = spellIds
self.instanceData = {}
self.requiredCount = requiredCount or 1 self.requiredCount = requiredCount or 1
self.own = own self.own = own
self.count = 0 self.count = 0
self.bestAuraID = nil
end end
--- Reset the AuraTrigger to the default state --- Reset the AuraTrigger to the default state
function AuraTrigger:Reset() function AuraTrigger:Reset()
self.count = 0 self.count = 0
self:SetState(self.count >= self.requiredCount, false) self.bestAuraID = nil
table.wipe(self.instanceData)
self:SetStateAndData(self.count >= self.requiredCount, {})
end end
---Check if a given aura matches this AuraTrigger ---Check if a given aura matches this AuraTrigger
---@param aura UnitAuraInfo ---@param aura UnitAuraInfo
function AuraTrigger:IsMatching(aura) function AuraTrigger:IsMatching(aura)
if aura.spellId ~= aura.spellId then if not self.spellIds[aura.spellId] then
return false return false
end end
if self.own and aura.sourceUnit ~= "player" then if self.own and aura.sourceUnit ~= "player" then
@@ -78,35 +83,68 @@ function AuraTrigger:IsMatching(aura)
return true return true
end end
-- Get the ID of the current best matching aura in AuraTrigger.instanceData
function AuraTrigger:BestAuraID()
local found = nil
for k, v in pairs(self.instanceData) do
if not found then
found = k
elseif v.expirationTime > self.instanceData[found].expirationTime then
found = k
end
end
return found
end
---Grab the best aura data and update the current recorded best aura
---It returns data if the current best aura is different from the previous
---@param updatedInstanceId number|nil the aura id that was recently updated
function AuraTrigger:BestAuraData(updatedInstanceId)
local bid = self:BestAuraID()
if bid == nil then
self.bestAuraID = nil
return nil
end
local data = nil
if bid ~= self.bestAuraID or (updatedInstanceId and bid == updatedInstanceId) then
local aura = self.instanceData[bid]
data = {
stacks = aura.applications,
duration = aura.duration,
expirationTime = aura.expirationTime,
icon = aura.icon,
}
self.bestAuraID = bid
end
return data
end
---Inform the trigger about an added aura ---Inform the trigger about an added aura
---@param aura UnitAuraInfo ---@param aura UnitAuraInfo
function AuraTrigger:AddAura(aura) function AuraTrigger:AddAura(aura)
if not self:IsMatching(aura) then if not self:IsMatching(aura) then
return return
end end
local aid = aura.auraInstanceID
self.instanceData[aid] = aura
self.count = self.count + 1 self.count = self.count + 1
self:SetData({ local newData = self:BestAuraData(nil)
stacks = aura.applications, self:SetStateAndData(self.count >= self.requiredCount, newData)
duration = aura.duration,
expirationTime = aura.expirationTime,
icon = aura.icon,
})
self:SetState(self.count >= self.requiredCount, false)
end end
---Inform the trigger about an updated aura ---Inform the trigger about an updated aura
---@param before UnitAuraInfo ---@param before UnitAuraInfo
---@param after UnitAuraInfo ---@param after UnitAuraInfo
function AuraTrigger:UpdateAura(before, after) function AuraTrigger:UpdateAura(before, after)
self:SetData({ if not self:IsMatching(after) then
stacks = after.applications, return
duration = after.duration,
expirationTime = after.expirationTime,
icon = after.icon,
})
if self.active then
self.indicator:Update(self.data)
end end
local aid = after.auraInstanceID
self.instanceData[aid] = after
local newData = self:BestAuraData(aid)
self:SetStateAndData(self.count >= self.requiredCount, newData)
end end
---Inform the trigger about an aura that got removed ---Inform the trigger about an aura that got removed
@@ -115,7 +153,11 @@ function AuraTrigger:RemoveAura(aura)
if not self:IsMatching(aura) then if not self:IsMatching(aura) then
return return
end end
local aid = aura.auraInstanceID
self.instanceData[aid] = nil
self.count = self.count - 1 self.count = self.count - 1
self:SetData({})
self:SetState(self.count >= self.requiredCount, false) local newData = self:BestAuraData(nil)
self:SetStateAndData(self.count >= self.requiredCount, newData)
end end