Add a new trigger type statustrigger

StatusTrigger will trigger if a status activates (or reaches a certain
activation # of auras). This is an abstraction provided by AuraList
which keeps track of which auras belong to which statuses.

Added type annotations to all touched files
This commit is contained in:
2023-04-04 16:45:43 +02:00
parent e55f139fca
commit d66989297c
4 changed files with 116 additions and 28 deletions

View File

@@ -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

View File

@@ -16,9 +16,9 @@
-- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.
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

View File

@@ -0,0 +1,53 @@
-- Copyright 2023 <omicron.me@protonmail.com>
--
-- 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 <https://www.gnu.org/licenses/>.
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

View File

@@ -16,13 +16,22 @@
-- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.
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