diff --git a/src/OmicronFrames.toc b/src/OmicronFrames.toc
index cbc7486..1b6d960 100644
--- a/src/OmicronFrames.toc
+++ b/src/OmicronFrames.toc
@@ -11,6 +11,7 @@ types/types.lua
types/object.lua
types/triggers/trigger.lua
types/triggers/auratrigger.lua
+types/triggers/statustrigger.lua
types/statusbar.lua
types/auralist.lua
types/indicators/indicator.lua
diff --git a/src/types/auralist.lua b/src/types/auralist.lua
index 67ac884..f5cb9b1 100644
--- a/src/types/auralist.lua
+++ b/src/types/auralist.lua
@@ -16,9 +16,9 @@
-- Omicron Frames. If not, see .
local omi = select(2, ...)
local types = omi.GetModule("types")
-local AuraTrigger = types.AuraTrigger
--- AuraList keeps track of all the auras attached to a unitframe
+---@class AuraList: Object
local AuraList = types.CreateClass("AuraList")
types.AuraList = AuraList
@@ -67,9 +67,16 @@ local function ForEachAura(unit, fn)
ForEachAuraFiltered(unit, "HARMFUL", fn)
end
---- Initialize AuraList
--- unitframe
--- The unitframe this list belongs to
+
+---@return AuraList
+function AuraList.new(cls, ...)
+ --- I really dislike duplicating this everywhere but it makes
+ --lua-language-server able to deduce the type of Object:new calls and that
+ --is honestly worth it
+ return types.Object.new(cls, ...)
+end
+
+---@param unitframe UnitFrame
function AuraList:Init(unitframe)
self.unitframe = unitframe
self.unit = unitframe.unit
@@ -80,22 +87,29 @@ function AuraList:Init(unitframe)
self.triggers = {}
self.triggersBySpell = {}
+ self.triggersByStatus = {}
end
---- Add an AuraTrigger to this AuraList
--- trigger
--- an AuraTrigger object
+---@param trigger AuraTrigger | StatusTrigger
function AuraList:AddTrigger(trigger)
table.insert(self.triggers, trigger)
local spellId = trigger.spellId
- if self.triggersBySpell[spellId] == nil then
- self.triggersBySpell[spellId] = {}
+ 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
+ self.triggersByStatus[status] = {}
+ end
+ table.insert(self.triggersByStatus[status], trigger)
end
- table.insert(self.triggersBySpell[spellId], trigger)
end
---- Reset the AuraList and do a full aura scan on the unit
--- This also resets all the triggers that are attached to this AuraList
+---Reset the AuraList and do a full aura scan on the unit
+---This also resets all the triggers that are attached to this AuraList
function AuraList:Reset()
self.auras = {}
@@ -110,9 +124,7 @@ function AuraList:Reset()
end)
end
---- Add an aura to the AuraList
--- aura
--- A UnitAuraInfo table for a newly added aura
+---@param aura UnitAuraInfo
function AuraList:AddAura(aura)
local statusChanged = false
self.auras[aura.auraInstanceID] = aura
@@ -126,6 +138,7 @@ function AuraList:AddAura(aura)
else
count[status] = count[status] + 1
end
+ self:UpdateStatusTriggers(status)
end
for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do
@@ -136,9 +149,20 @@ function AuraList:AddAura(aura)
return statusChanged
end
---- Return a sequence table with all status names that match the given aura
--- aura
--- A UnitAuraInfo table
+---@param status string
+function AuraList:UpdateStatusTriggers(status)
+ local triggers = self.triggersByStatus[status]
+ if not triggers then
+ return
+ end
+ local count = self.statusCount[status] or 0
+ for _, trigger in ipairs(triggers) do
+ trigger:UpdateStatus(count)
+ end
+end
+
+---@param aura UnitAuraInfo
+---@return string[] All status names associated with this aura
function AuraList:GetStatusForAura(aura)
local status = {}
if aura.dispelName and aura.isHarmful then
@@ -152,9 +176,7 @@ function AuraList:GetStatusForAura(aura)
return status
end
---- Add an aura to the AuraList
--- aura
--- A UnitAuraInfo table for a newly added aura
+---@param aura UnitAuraInfo
function AuraList:UpdateAura(aura)
for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do
trigger:UpdateAura(self.auras[aura.auraInstanceId], aura)
@@ -162,9 +184,7 @@ function AuraList:UpdateAura(aura)
self.auras[aura.auraInstanceID] = aura
end
---- Remove an aura from the AuraList
--- iid
--- The instance id for a removed aura
+---@param iid number
function AuraList:RemoveAura(iid)
local aura = self.auras[iid]
if aura == nil then
@@ -184,6 +204,7 @@ function AuraList:RemoveAura(iid)
else
count[status] = count[status] - 1
end
+ self:UpdateStatusTriggers(status)
end
for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do
@@ -192,9 +213,7 @@ function AuraList:RemoveAura(iid)
return statusChanged
end
---- Update an aura in the AuraList
--- info
--- The new UnitAuraInfo structure
+---@param info UnitAuraInfo
function AuraList:Update(info)
local GetAuraDataByAuraInstanceID = C_UnitAuras.GetAuraDataByAuraInstanceID
local statusChanged = false
diff --git a/src/types/triggers/statustrigger.lua b/src/types/triggers/statustrigger.lua
new file mode 100644
index 0000000..a537ca6
--- /dev/null
+++ b/src/types/triggers/statustrigger.lua
@@ -0,0 +1,53 @@
+-- Copyright 2023
+--
+-- This file is part of Omicron Frames
+--
+-- Omicron Frames is free software: you can redistribute it and/or modify it
+-- under the terms of the GNU General Public License as published by the Free
+-- Software Foundation, either version 3 of the License, or (at your option)
+-- any later version.
+--
+-- Omicron Frames is distributed in the hope that it will be useful, but
+-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+-- more details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- Omicron Frames. If not, see .
+local omi = select(2, ...)
+local types = omi.GetModule("types")
+---@class Trigger
+local Trigger = types.Trigger
+
+---StatusTrigger is a trigger that can be attached to AuraList as datasource
+---@class StatusTrigger: Trigger
+---@field status string
+local StatusTrigger = types.CreateClass("StatusTrigger", Trigger)
+types.StatusTrigger = StatusTrigger
+
+---@return StatusTrigger
+function StatusTrigger.new(cls, ...)
+ --- I really dislike duplicating this everywhere but it makes
+ --lua-language-server able to deduce the type of Object:new calls and that
+ --is honestly worth it
+ return types.Object.new(cls, ...)
+end
+
+--- Initialize a new AuraTrigger object
+---@param status string The kind of status to trigger on
+---@param requiredCount number | nil
+---@param invert boolean | nil
+function StatusTrigger:Init(status, requiredCount, invert)
+ Trigger.Init(self, invert)
+ self.status = status
+ self.requiredCount = requiredCount or 1
+ self.invert = invert or false
+ self.active = invert
+end
+
+--- Inform the trigger about a changed status
+-- status:
+-- Must be a valid UnitAuraInfo
+function StatusTrigger:UpdateStatus(count)
+ self:SetState(count >= self.requiredCount)
+end
diff --git a/src/types/unitframe.lua b/src/types/unitframe.lua
index 4e7cfcb..9c542bd 100644
--- a/src/types/unitframe.lua
+++ b/src/types/unitframe.lua
@@ -16,13 +16,22 @@
-- Omicron Frames. If not, see .
local omif = select(2, ...)
local types = omif.GetModule("types")
+
+---@class StatusBar
local StatusBar = types.StatusBar
+
+---@class AuraList
local AuraList = types.AuraList
+
+---@class SquareIndicator
local SquareIndicator = types.SquareIndicator
---@class AuraTrigger
local AuraTrigger = types.AuraTrigger
+---@class StatusTrigger
+local StatusTrigger = types.StatusTrigger
+
---@class UnitFrame
local UnitFrame = types.CreateClass("UnitFrame")
types.UnitFrame = UnitFrame
@@ -47,6 +56,8 @@ local colors = {
white = {1.0, 1.0, 1.0}
}
+---@param unit string
+---@param config table
function UnitFrame:Init(unit, config)
local width = config.size.width
local height = config.size.height
@@ -85,8 +96,8 @@ end
function UnitFrame:CreateTriggers(triggers)
for _, trigger in ipairs(triggers) do
local kind = trigger.kind
+ local indicator = self:CreateIndicator(trigger.indicator)
if kind == "AuraTrigger" then
- local indicator = self:CreateIndicator(trigger.indicator)
local at = AuraTrigger:new(
trigger.spellId,
trigger.own,
@@ -95,6 +106,10 @@ function UnitFrame:CreateTriggers(triggers)
)
at:SetTarget(indicator)
self.auras:AddTrigger(at)
+ elseif kind == "StatusTrigger" then
+ local st = StatusTrigger:new(trigger.status, trigger.requiredCount, trigger.invert)
+ st:SetTarget(indicator)
+ self.auras:AddTrigger(st)
end
end
end