Bastion aims to serve as a highly performant, simplisitic, and expandable World of Warcraft data visualization framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Bastion/src/APLActor/APLActor.lua

136 lines
4.5 KiB

---@type Tinkr
local Tinkr,
---@class Bastion
Bastion = ...
---@class Bastion.APLActor.Table.Base
---@field type "spell" | "item" | "apl" | "sequencer" | "variable" | "action"
---@alias Bastion.APLActor.Table Bastion.APL.Actor.Spell.Table | Bastion.APL.Actor.Item.Table | Bastion.APL.Actor.APL.Table | Bastion.APL.Actor.Sequencer.Table | Bastion.APL.Actor.Variable.Table | Bastion.APL.Actor.Action.Table
-- Create an APL actor for the APL class
---@class Bastion.APLActor
---@field actor Bastion.APLActor.Table
---@field enabled boolean
---@field traits Bastion.APLTrait[]
---@field name string
local APLActor = {}
APLActor.__index = APLActor
-- Constructor
---@param actor Bastion.APLActor.Table
function APLActor:New(actor)
local self = setmetatable({}, APLActor)
if actor.type == "spell" then
local name = actor.spell:GetName() or "Unknown"
local id = actor.spell:GetID() or 0
self.name = string.format("[%s] `%s`<%s>", "spell", name, id)
elseif actor.type == "item" then
local name = actor.item:GetName() or "Unknown"
local id = actor.item:GetID() or 0
self.name = string.format("[%s] `%s`<%s>", "item", name, id)
elseif actor.type == "apl" then
self.name = string.format("[%s] `%s`", "apl", actor.apl.name)
elseif actor.type == "sequencer" then
self.name = string.format("[%s]", "sequencer")
elseif actor.type == "variable" then
self.name = string.format("[%s] `%s`", "variable", actor.variable)
elseif actor.type == "action" then
self.name = string.format("[%s] `%s`", "action", actor.action)
else
self.name = string.format("[%s] Unknown", actor.type)
end
self.actor = actor
self.enabled = true
self.traits = {}
return self
end
-- Add a trait to the APL actor
---@param ... Bastion.APLTrait
---@return Bastion.APLActor
function APLActor:AddTraits(...)
for _, trait in ipairs({ ... }) do
table.insert(self.traits, trait)
end
return self
end
-- Get the actor
---@return Bastion.APLActor.Table
function APLActor:GetActor()
return self.actor
end
-- Evaulate the APL actor
---@return boolean
function APLActor:Evaluate()
for _, trait in ipairs(self.traits) do
if not trait:Evaluate(self:GetActor()) then
return false
end
end
return true
end
-- Execute
function APLActor:Execute()
local actorTable = self:GetActor()
-- If the actor is a sequencer we don't want to continue executing the APL if the sequencer is not finished
if actorTable.type == "sequencer" then
---@cast actorTable Bastion.APL.Actor.Sequencer.Table
if (not actorTable.condition or actorTable.condition()) and not actorTable.sequencer:Finished() then
actorTable.sequencer:Execute()
return true
end
-- Check if the sequencer can be reset and reset it if it can
if actorTable.sequencer:ShouldReset() then
actorTable.sequencer:Reset()
end
end
if actorTable.type == "apl" then
---@cast actorTable Bastion.APL.Actor.APL.Table
if not actorTable.condition or actorTable.condition() then
-- print("Bastion: APL:Execute: Executing sub APL " .. actorTable.apl.name)
return actorTable.apl:Execute()
end
end
if actorTable.type == "spell" then
---@cast actorTable Bastion.APL.Actor.Spell.Table
return actorTable.spell:CastableIf(actorTable.castableFunc):OnCast(actorTable.onCastFunc):Cast(actorTable.target,
actorTable.condition)
end
if actorTable.type == "item" then
---@cast actorTable Bastion.APL.Actor.Item.Table
return actorTable.item:UsableIf(actorTable.usableFunc):Use(actorTable.target, actorTable.condition)
end
if self:GetActor().type == "action" then
---@cast actorTable Bastion.APL.Actor.Action.Table
-- print("Bastion: APL:Execute: Executing action " .. actorTable.action)
self:GetActor().cb()
end
if actorTable.type == "variable" then
---@cast actorTable Bastion.APL.Actor.Variable.Table
-- print("Bastion: APL:Execute: Setting variable " .. actorTable.variable)
actorTable._apl.variables[actorTable.variable] = actorTable.cb(actorTable._apl)
end
return false
end
-- has traits
---@return boolean
function APLActor:HasTraits()
return #self.traits > 0
end
-- tostring
---@return string
function APLActor:__tostring()
return string.format("Bastion.__APLActor(%s)", self.name)
end
Bastion.APLActor = APLActor