From eaebe470b9a279b445528918d8dc00ec4fccd32d Mon Sep 17 00:00:00 2001 From: omicron Date: Fri, 26 Jun 2026 01:25:10 +0200 Subject: [PATCH] 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 --- src/frames.lua | 61 ++++++++++++-------- src/types/auralist.lua | 32 ++++++++--- src/types/triggers/auratrigger.lua | 90 ++++++++++++++++++++++-------- 3 files changed, 127 insertions(+), 56 deletions(-) diff --git a/src/frames.lua b/src/frames.lua index ae9c1c2..8ef661c 100644 --- a/src/frames.lua +++ b/src/frames.lua @@ -31,6 +31,19 @@ local colors = { light_blue = { 0.7, 0.7, 1 }, } +---@param list number[] +---@return table +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 _, class = UnitClass("player") if class == "SHAMAN" then @@ -41,7 +54,7 @@ local function RangeConfig() } elseif class == "PRIEST" then return { - friendly = "Flash Heal", + friendly = "Heal", enemy = "Smite", fade = 0.2, } @@ -134,15 +147,15 @@ local function MouseConfig() button = "wheel-up", mods = {}, 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 { button = "mouse1", mods = { alt = true }, kind = "spell", data = "Power Word: Life" }, { button = "mouse2", mods = { alt = true }, kind = "spell", data = "Pain Suppression" }, { 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" }, -- Shift @@ -282,7 +295,7 @@ local function TriggerClassConfig() return { { kind = "AuraTrigger", - spellId = 32594, + spellIds = set({ 32594 }), own = true, -- Second Earth Shield on yourself indicator = { kind = "SquareIndicator", @@ -296,7 +309,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 29203, + spellIds = set({ 29203 }), own = true, -- Healing Way indicator = { kind = "SquareIndicator", @@ -310,7 +323,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 16237, + spellIds = set({ 16237 }), own = true, -- Ancestral Fortitude indicator = { kind = "SquareIndicator", @@ -338,7 +351,7 @@ local function TriggerClassConfig() return { { kind = "AuraTrigger", - spellId = 17, + spellIds = AURAS_PRIEST_PWS, own = true, -- Power Word: Shield indicator = { kind = "SquareIndicator", @@ -352,7 +365,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 33206, + spellIds = set({ 33206 }), own = true, -- Pain Suppression indicator = { kind = "SquareIndicator", @@ -367,7 +380,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 41635, + spellIds = set({ 41635 }), own = true, -- Prayer of Mending indicator = { kind = "SquareIndicator", @@ -381,7 +394,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 139, + spellIds = AURAS_PRIEST_RENEW, own = true, -- Renew indicator = { kind = "SquareIndicator", @@ -395,7 +408,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 194384, + spellIds = set({ 194384 }), own = true, -- Atonement indicator = { kind = "SquareIndicator", @@ -410,7 +423,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 10060, + spellIds = set({ 10060 }), own = true, -- Power Infusion indicator = { kind = "SquareIndicator", @@ -438,7 +451,7 @@ local function TriggerClassConfig() return { { kind = "AuraTrigger", - spellId = 287280, -- Glimmer of Light + spellIds = set({ 287280 }), -- Glimmer of Light own = true, indicator = { kind = "SquareIndicator", @@ -453,7 +466,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 25771, -- Forbearance + spellIds = set({ 25771 }), -- Forbearance indicator = { kind = "SquareIndicator", size = 17, @@ -467,7 +480,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 53563, -- Beacon of Light + spellIds = set({ 53563 }), -- Beacon of Light own = true, indicator = { kind = "SquareIndicator", @@ -480,7 +493,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 156910, -- Beacon of Faith + spellIds = set({ 156910 }), -- Beacon of Faith own = true, indicator = { kind = "SquareIndicator", @@ -493,7 +506,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 200025, -- Beacon of Virtue + spellIds = set({ 200025 }), -- Beacon of Virtue own = true, indicator = { kind = "SquareIndicator", @@ -506,7 +519,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 1044, -- Blessing of Freedom + spellIds = set({ 1044 }), -- Blessing of Freedom own = true, indicator = { kind = "SquareIndicator", @@ -520,7 +533,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 1111, -- Blessing of Spellwarding + spellIds = set({ 1111 }), -- Blessing of Spellwarding own = true, indicator = { kind = "SquareIndicator", @@ -534,7 +547,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 1022, -- Blessing of Protection + spellIds = set({ 1022 }), -- Blessing of Protection own = true, indicator = { kind = "SquareIndicator", @@ -548,7 +561,7 @@ local function TriggerClassConfig() }, { kind = "AuraTrigger", - spellId = 6940, -- Blessing of Saccrifice + spellIds = set({ 6940 }), -- Blessing of Saccrifice own = true, indicator = { kind = "SquareIndicator", @@ -596,7 +609,7 @@ local function MakeDebuffTrigger(slot, spellid, color, stacks) end return { kind = "AuraTrigger", - spellId = spellid, + spellIds = set({ spellid }), indicator = { kind = "SquareIndicator", size = 15, @@ -676,7 +689,7 @@ local function TriggerConfig() -- Some more debuffs in the bottom row table.insert(triggers, { kind = "AuraTrigger", - spellId = 240443, -- Bursting + spellIds = set({ 240443 }), -- Bursting indicator = { kind = "SquareIndicator", size = 17, diff --git a/src/types/auralist.lua b/src/types/auralist.lua index 5fea69b..74e7e6d 100644 --- a/src/types/auralist.lua +++ b/src/types/auralist.lua @@ -16,6 +16,8 @@ -- Omicron Frames. If not, see . local omi = select(2, ...) local types = omi.GetModule("types") +local AuraTrigger = types.AuraTrigger +local StatusTrigger = types.StatusTrigger --- AuraList keeps track of all the auras attached to a unitframe ---@class AuraList: Object @@ -180,21 +182,35 @@ function AuraList:Init(unitframe) self.triggersByStatus = {} end ----@param trigger AuraTrigger | StatusTrigger -function AuraList:AddTrigger(trigger) +---@param trigger StatusTrigger +function AuraList:AddStatusTrigger(trigger) table.insert(self.triggers, trigger) - local spellId = trigger.spellId local status = trigger.status - if spellId then + if self.triggersByStatus[status] == nil then + self.triggersByStatus[status] = {} + end + 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 - if self.triggersByStatus[status] == nil then - self.triggersByStatus[status] = {} - end - table.insert(self.triggersByStatus[status], trigger) + error("AddTrigger: trigger is neither an AuraTrigger nor a StatusTrigger") end end diff --git a/src/types/triggers/auratrigger.lua b/src/types/triggers/auratrigger.lua index cef6135..c5c725c 100644 --- a/src/types/triggers/auratrigger.lua +++ b/src/types/triggers/auratrigger.lua @@ -21,7 +21,7 @@ local Trigger = types.Trigger ---AuraTrigger is a Trigger that can be attached to AuraList as datasource ---@class AuraTrigger: Trigger ----@field spellId number +---@field spellIds table ---@field count number ---@field requiredCount number local AuraTrigger = types.CreateClass("AuraTrigger", Trigger) @@ -33,7 +33,8 @@ types.AuraTrigger = AuraTrigger ---@param config table ---@return AuraTrigger 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) return trigger end @@ -47,29 +48,33 @@ function AuraTrigger.new(cls, ...) end --- Initialize a new AuraTrigger object ----@param spellId number +---@param spellIds table ---@param own boolean ---@param requiredCount number | nil ---@param invert boolean | 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) - self.spellId = spellId + self.spellIds = spellIds + self.instanceData = {} self.requiredCount = requiredCount or 1 self.own = own self.count = 0 + self.bestAuraID = nil end --- Reset the AuraTrigger to the default state function AuraTrigger:Reset() self.count = 0 - self:SetState(self.count >= self.requiredCount, false) + self.bestAuraID = nil + table.wipe(self.instanceData) + self:SetStateAndData(self.count >= self.requiredCount, {}) end ---Check if a given aura matches this AuraTrigger ---@param aura UnitAuraInfo function AuraTrigger:IsMatching(aura) - if aura.spellId ~= aura.spellId then + if not self.spellIds[aura.spellId] then return false end if self.own and aura.sourceUnit ~= "player" then @@ -78,35 +83,68 @@ function AuraTrigger:IsMatching(aura) return true 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 ---@param aura UnitAuraInfo function AuraTrigger:AddAura(aura) if not self:IsMatching(aura) then return end + local aid = aura.auraInstanceID + self.instanceData[aid] = aura self.count = self.count + 1 - self:SetData({ - stacks = aura.applications, - duration = aura.duration, - expirationTime = aura.expirationTime, - icon = aura.icon, - }) - self:SetState(self.count >= self.requiredCount, false) + local newData = self:BestAuraData(nil) + self:SetStateAndData(self.count >= self.requiredCount, newData) end ---Inform the trigger about an updated aura ---@param before UnitAuraInfo ---@param after UnitAuraInfo function AuraTrigger:UpdateAura(before, after) - self:SetData({ - stacks = after.applications, - duration = after.duration, - expirationTime = after.expirationTime, - icon = after.icon, - }) - if self.active then - self.indicator:Update(self.data) + if not self:IsMatching(after) then + return end + local aid = after.auraInstanceID + self.instanceData[aid] = after + + local newData = self:BestAuraData(aid) + self:SetStateAndData(self.count >= self.requiredCount, newData) end ---Inform the trigger about an aura that got removed @@ -115,7 +153,11 @@ function AuraTrigger:RemoveAura(aura) if not self:IsMatching(aura) then return end + + local aid = aura.auraInstanceID + self.instanceData[aid] = nil 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