Move ivert logic and trigger logic into Trigger

The base Trigger class is now responsible for inverting the trigger
state and also for signaling trigger activation to the target/indicator.

In addition the following non-function changes also occured:
 - The triggers moved into their own directory
 - The trigger code has been annotated to help lua-language-server
   deduce type information
 - AuraTrigger was moved into its own file

All these changes should make future development of other triggers easier
This commit is contained in:
2023-04-04 06:40:29 +02:00
parent d85a1c3579
commit 8c4cc405aa
5 changed files with 173 additions and 158 deletions

View File

@@ -9,7 +9,8 @@ main.lua
types/types.lua
types/object.lua
types/trigger.lua
types/triggers/trigger.lua
types/triggers/auratrigger.lua
types/statusbar.lua
types/auralist.lua
types/indicator.lua

View File

@@ -1,151 +0,0 @@
-- 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")
---
-- Trigger objects provide a link between indicators and some data source. They
-- can pass data from the data source into the trigger. This is just a
-- supertype for all indicators and should not be constructed on its own. It
-- has no functionality other than providing default implementations that do
-- nothing.
types.Trigger = types.CreateClass("Trigger")
local Trigger = types.Trigger
-- Initialize a new Trigger object
-- indicator:
-- The indicator that gets activated by this trigger.
function Trigger:Init(indicator)
self.indicator = indicator
end
-- Returns whether or not the trigger is active
function Trigger:IsActive()
return false
end
-- Reset the trigger to the default state. Deactivates the indicator if it is
-- active when Reset is called.
function Trigger:Reset()
end
---
-- AuraTrigger is a trigger that can be attached to AuraList as datasource
types.AuraTrigger = types.CreateClass("AuraTrigger", Trigger)
local AuraTrigger = types.AuraTrigger
--- Initialize a new AuraTrigger object
-- indicator
-- Indicator that gets controlled by this trigger.
-- spellId
-- Spell id to trigger on
-- own
-- Only trigger on auras by the player
-- requiredCount=1
-- Number of aura applications to activate trigger
-- invert=false
-- Whether to invert trigger activation
function AuraTrigger:Init(indicator, spellId, own, requiredCount, invert)
Trigger.Init(self, indicator)
self.spellId = spellId
self.requiredCount = requiredCount or 1
self.own = own
self.count = 0
self.invert = invert or false
end
--- See Trigger:Reset
function AuraTrigger:Reset()
local before = self:IsActive()
self.count = 0
local after = self:IsActive()
if not before and after then
self.indicator:Show()
elseif before and not after then
self.indicator:Hide()
end
end
--- Return true if the aura matches the trigger
-- aura:
-- Must be a valid UnitAuraInfo structure.
function AuraTrigger:IsMatching(aura)
if aura.spellId ~= aura.spellId then
return false
end
if self.own and aura.sourceUnit ~= "player" then
return false
end
return true
end
--- Inform the trigger about an added aura
-- aura:
-- Must be a valid UnitAuraInfo
function AuraTrigger:AddAura(aura)
if not self:IsMatching(aura) then
return
end
self.count = self.count + 1
-- Be mindful, this works only if count always changes by 1.
if self.count == self.requiredCount then
if self.invert then
self.indicator:Hide()
else
self.indicator:Show()
end
end
end
--- Inform the trigger about an updated aura
-- before:
-- Must be a valid UnitAuraInfo for the aura before the update
-- after:
-- Must be a valid UnitAuraInfo for the aura after the update
function AuraTrigger:UpdateAura(before, after)
--
end
--- Inform the trigger about an aura that got removed
-- aura:
-- Must be a valid UnitAuraInfo for the aura before it got removed
function AuraTrigger:RemoveAura(aura)
if not self:IsMatching(aura) then
return
end
self.count = self.count - 1
-- Be mindful, this works only if count always changes by 1.
if self.count == self.requiredCount - 1 then
if self.invert then
self.indicator:Show()
else
self.indicator:Hide()
end
end
end
--- Returns true if the trigger is active, false otherwise
function AuraTrigger:IsActive()
if self.invert then
return self.count < self.requiredCount
else
return self.count >= self.requiredCount
end
end

View File

@@ -0,0 +1,94 @@
-- 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
---AuraTrigger is a Trigger that can be attached to AuraList as datasource
---@class AuraTrigger: Trigger
---@field spellId number
---@field count number
---@field requiredCount number
local AuraTrigger = types.CreateClass("AuraTrigger", Trigger)
types.AuraTrigger = AuraTrigger
---@return AuraTrigger
function AuraTrigger.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 spellId number
---@param own boolean
---@param requiredCount number | nil
---@param invert boolean | nil
function AuraTrigger:Init(spellId, own, requiredCount, invert)
Trigger.Init(self, invert)
self.spellId = spellId
self.requiredCount = requiredCount or 1
self.own = own
self.count = 0
end
--- Reset the AuraTrigger to the default state
function AuraTrigger:Reset()
self.count = 0
self:SetState(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
return false
end
if self.own and aura.sourceUnit ~= "player" then
return false
end
return true
end
---Inform the trigger about an added aura
---@param aura UnitAuraInfo
function AuraTrigger:AddAura(aura)
if not self:IsMatching(aura) then
return
end
self.count = self.count + 1
self:SetState(self.count >= self.requiredCount)
end
---Inform the trigger about an updated aura
---@param before UnitAuraInfo
---@param after UnitAuraInfo
function AuraTrigger:UpdateAura(before, after)
--
end
---Inform the trigger about an aura that got removed
---@param aura UnitAuraInfo
function AuraTrigger:RemoveAura(aura)
if not self:IsMatching(aura) then
return
end
self.count = self.count - 1
self:SetState(self.count >= self.requiredCount)
end

View File

@@ -0,0 +1,67 @@
-- 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")
--- Triggers objects provide a link between indicators and some data source. They
-- can pass data from the data source into the indicator. This is a supertype for
-- all triggers and should not be constructed on its own.
---@class Trigger: Object
---@field active boolean
---@field invert boolean
local Trigger = types.CreateClass("Trigger")
types.Trigger = Trigger
--- Initialize a new Trigger object
---@param invert boolean|nil
function Trigger:Init(invert)
invert = invert or false
self.invert = invert
self.active = invert
end
--- Set the target of the Trigger.
-- The target will get notified every time the trigger changes state. If the trigger
-- is currently active when the target is set, it will get notified immediately.
---@param target Indicator
function Trigger:SetTarget(target)
self.indicator = target
end
---Set the state of the trigger. Will activate the indicator if needed.
---@param data table<string,any> | nil
---@param state boolean
function Trigger:SetState(state, data)
state = state ~= self.invert -- state xor inverted
if self.active ~= state then
if state then
self.indicator:Show(data)
else
self.indicator:Hide()
end
self.active = state
end
end
-- Reset the trigger to the default state. If this changes the activation of the
-- trigger then the target will be notified.
function Trigger:Reset()
self:SetState(false)
end

View File

@@ -19,10 +19,13 @@ local types = omif.GetModule("types")
local StatusBar = types.StatusBar
local AuraList = types.AuraList
local SquareIndicator = types.SquareIndicator
---@class AuraTrigger
local AuraTrigger = types.AuraTrigger
types.UnitFrame = types.CreateClass("UnitFrame")
local UnitFrame = types.UnitFrame
---@class UnitFrame
local UnitFrame = types.CreateClass("UnitFrame")
types.UnitFrame = UnitFrame
local colors = {
@@ -83,19 +86,20 @@ function UnitFrame:CreateTriggers(triggers)
for _, trigger in ipairs(triggers) do
local kind = trigger.kind
if kind == "AuraTrigger" then
self.auras:AddTrigger(
AuraTrigger:new(
self:CreateIndicator(trigger.indicator),
local indicator = self:CreateIndicator(trigger.indicator)
local at = AuraTrigger:new(
trigger.spellId,
trigger.own,
trigger.requiredCount,
trigger.invert
)
)
at:SetTarget(indicator)
self.auras:AddTrigger(at)
end
end
end
function UnitFrame:CreateIndicator(indicator)
local kind = indicator.kind
if kind == "SquareIndicator" then