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/object.lua
types/triggers/trigger.lua types/triggers/trigger.lua
types/triggers/auratrigger.lua types/triggers/auratrigger.lua
types/triggers/statustrigger.lua
types/statusbar.lua types/statusbar.lua
types/auralist.lua types/auralist.lua
types/indicators/indicator.lua types/indicators/indicator.lua

View File

@@ -16,9 +16,9 @@
-- 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
--- 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
local AuraList = types.CreateClass("AuraList") local AuraList = types.CreateClass("AuraList")
types.AuraList = AuraList types.AuraList = AuraList
@@ -67,9 +67,16 @@ local function ForEachAura(unit, fn)
ForEachAuraFiltered(unit, "HARMFUL", fn) ForEachAuraFiltered(unit, "HARMFUL", fn)
end end
--- Initialize AuraList
-- unitframe ---@return AuraList
-- The unitframe this list belongs to 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) function AuraList:Init(unitframe)
self.unitframe = unitframe self.unitframe = unitframe
self.unit = unitframe.unit self.unit = unitframe.unit
@@ -80,22 +87,29 @@ function AuraList:Init(unitframe)
self.triggers = {} self.triggers = {}
self.triggersBySpell = {} self.triggersBySpell = {}
self.triggersByStatus = {}
end end
--- Add an AuraTrigger to this AuraList ---@param trigger AuraTrigger | StatusTrigger
-- trigger
-- an AuraTrigger object
function AuraList:AddTrigger(trigger) function AuraList:AddTrigger(trigger)
table.insert(self.triggers, trigger) table.insert(self.triggers, trigger)
local spellId = trigger.spellId local spellId = trigger.spellId
local status = trigger.status
if spellId then
if self.triggersBySpell[spellId] == nil then if self.triggersBySpell[spellId] == nil then
self.triggersBySpell[spellId] = {} self.triggersBySpell[spellId] = {}
end end
table.insert(self.triggersBySpell[spellId], trigger) table.insert(self.triggersBySpell[spellId], trigger)
else
if self.triggersByStatus[status] == nil then
self.triggersByStatus[status] = {}
end
table.insert(self.triggersByStatus[status], trigger)
end
end end
---Reset the AuraList and do a full aura scan on the unit ---Reset the AuraList and do a full aura scan on the unit
-- This also resets all the triggers that are attached to this AuraList ---This also resets all the triggers that are attached to this AuraList
function AuraList:Reset() function AuraList:Reset()
self.auras = {} self.auras = {}
@@ -110,9 +124,7 @@ function AuraList:Reset()
end) end)
end end
--- Add an aura to the AuraList ---@param aura UnitAuraInfo
-- aura
-- A UnitAuraInfo table for a newly added aura
function AuraList:AddAura(aura) function AuraList:AddAura(aura)
local statusChanged = false local statusChanged = false
self.auras[aura.auraInstanceID] = aura self.auras[aura.auraInstanceID] = aura
@@ -126,6 +138,7 @@ function AuraList:AddAura(aura)
else else
count[status] = count[status] + 1 count[status] = count[status] + 1
end end
self:UpdateStatusTriggers(status)
end end
for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do
@@ -136,9 +149,20 @@ function AuraList:AddAura(aura)
return statusChanged return statusChanged
end end
--- Return a sequence table with all status names that match the given aura ---@param status string
-- aura function AuraList:UpdateStatusTriggers(status)
-- A UnitAuraInfo table 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) function AuraList:GetStatusForAura(aura)
local status = {} local status = {}
if aura.dispelName and aura.isHarmful then if aura.dispelName and aura.isHarmful then
@@ -152,9 +176,7 @@ function AuraList:GetStatusForAura(aura)
return status return status
end end
--- Add an aura to the AuraList ---@param aura UnitAuraInfo
-- aura
-- A UnitAuraInfo table for a newly added aura
function AuraList:UpdateAura(aura) function AuraList:UpdateAura(aura)
for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do
trigger:UpdateAura(self.auras[aura.auraInstanceId], aura) trigger:UpdateAura(self.auras[aura.auraInstanceId], aura)
@@ -162,9 +184,7 @@ function AuraList:UpdateAura(aura)
self.auras[aura.auraInstanceID] = aura self.auras[aura.auraInstanceID] = aura
end end
--- Remove an aura from the AuraList ---@param iid number
-- iid
-- The instance id for a removed aura
function AuraList:RemoveAura(iid) function AuraList:RemoveAura(iid)
local aura = self.auras[iid] local aura = self.auras[iid]
if aura == nil then if aura == nil then
@@ -184,6 +204,7 @@ function AuraList:RemoveAura(iid)
else else
count[status] = count[status] - 1 count[status] = count[status] - 1
end end
self:UpdateStatusTriggers(status)
end end
for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do for _, trigger in ipairs(self.triggersBySpell[aura.spellId] or {}) do
@@ -192,9 +213,7 @@ function AuraList:RemoveAura(iid)
return statusChanged return statusChanged
end end
--- Update an aura in the AuraList ---@param info UnitAuraInfo
-- info
-- The new UnitAuraInfo structure
function AuraList:Update(info) function AuraList:Update(info)
local GetAuraDataByAuraInstanceID = C_UnitAuras.GetAuraDataByAuraInstanceID local GetAuraDataByAuraInstanceID = C_UnitAuras.GetAuraDataByAuraInstanceID
local statusChanged = false 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/>. -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.
local omif = select(2, ...) local omif = select(2, ...)
local types = omif.GetModule("types") local types = omif.GetModule("types")
---@class StatusBar
local StatusBar = types.StatusBar local StatusBar = types.StatusBar
---@class AuraList
local AuraList = types.AuraList local AuraList = types.AuraList
---@class SquareIndicator
local SquareIndicator = types.SquareIndicator local SquareIndicator = types.SquareIndicator
---@class AuraTrigger ---@class AuraTrigger
local AuraTrigger = types.AuraTrigger local AuraTrigger = types.AuraTrigger
---@class StatusTrigger
local StatusTrigger = types.StatusTrigger
---@class UnitFrame ---@class UnitFrame
local UnitFrame = types.CreateClass("UnitFrame") local UnitFrame = types.CreateClass("UnitFrame")
types.UnitFrame = UnitFrame types.UnitFrame = UnitFrame
@@ -47,6 +56,8 @@ local colors = {
white = {1.0, 1.0, 1.0} white = {1.0, 1.0, 1.0}
} }
---@param unit string
---@param config table
function UnitFrame:Init(unit, config) function UnitFrame:Init(unit, config)
local width = config.size.width local width = config.size.width
local height = config.size.height local height = config.size.height
@@ -85,8 +96,8 @@ end
function UnitFrame:CreateTriggers(triggers) function UnitFrame:CreateTriggers(triggers)
for _, trigger in ipairs(triggers) do for _, trigger in ipairs(triggers) do
local kind = trigger.kind local kind = trigger.kind
if kind == "AuraTrigger" then
local indicator = self:CreateIndicator(trigger.indicator) local indicator = self:CreateIndicator(trigger.indicator)
if kind == "AuraTrigger" then
local at = AuraTrigger:new( local at = AuraTrigger:new(
trigger.spellId, trigger.spellId,
trigger.own, trigger.own,
@@ -95,6 +106,10 @@ function UnitFrame:CreateTriggers(triggers)
) )
at:SetTarget(indicator) at:SetTarget(indicator)
self.auras:AddTrigger(at) 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 end
end end