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/APL/APL.lua

282 lines
7.2 KiB

-- Document with emmy lua: https://emmylua.github.io/
2 years ago
-- Create an APL trait for the APL class
---@class APLTrait
2 years ago
local APLTrait = {}
APLTrait.__index = APLTrait
-- Constructor
---@param cb fun():boolean
---@return APLTrait
2 years ago
function APLTrait:New(cb)
local self = setmetatable({}, APLTrait)
self.cb = cb
self.lastcall = 0
return self
end
-- Evaulate the APL trait
---@return boolean
2 years ago
function APLTrait:Evaluate()
if GetTime() - self.lastcall > 0.1 then
self.lastresult = self.cb()
self.lastcall = GetTime()
return self.lastresult
end
return self.lastresult
end
-- tostring
---@return string
2 years ago
function APLTrait:__tostring()
return "Bastion.__APLTrait"
end
-- Create an APL actor for the APL class
---@class APLActor
2 years ago
local APLActor = {}
APLActor.__index = APLActor
-- Constructor
---@param actor table
2 years ago
function APLActor:New(actor)
local self = setmetatable({}, APLActor)
self.actor = actor
self.traits = {}
return self
end
-- Add a trait to the APL actor
---@param ... APLTrait
---@return APLActor
2 years ago
function APLActor:AddTraits(...)
for _, trait in ipairs({ ... }) do
table.insert(self.traits, trait)
end
return self
end
-- Get the actor
---@return table
2 years ago
function APLActor:GetActor()
return self.actor
end
-- Evaulate the APL actor
---@return boolean
2 years ago
function APLActor:Evaluate()
for _, trait in ipairs(self.traits) do
if not trait:Evaluate() then
return false
end
end
return true
end
-- Execute
function APLActor:Execute()
2 years ago
-- If the actor is a sequencer we don't want to continue executing the APL if the sequencer is not finished
if self:GetActor().sequencer then
if self:GetActor().condition and self:GetActor().condition() and not self:GetActor().sequencer:Finished() then
print("Execute?")
self:GetActor().sequencer:Execute()
return true
end
if not self:GetActor().condition and not self:GetActor().sequencer:Finished() then
print("Execute?")
self:GetActor().sequencer:Execute()
return true
end
-- Check if the sequencer can be reset and reset it if it can
if self:GetActor().sequencer:ShouldReset() then
self:GetActor().sequencer:Reset()
end
end
2 years ago
if self:GetActor().apl then
if self:GetActor().condition and self:GetActor().condition() then
2 years ago
-- print("Bastion: APL:Execute: Executing sub APL " .. self:GetActor().apl.name)
self:GetActor().apl:Execute()
end
end
if self:GetActor().spell then
if self:GetActor().condition then
-- print("Bastion: APL:Execute: Condition for spell " .. self:GetActor().spell:GetName())
self:GetActor().spell:CastableIf(self:GetActor().castableFunc):Cast(self:GetActor().target,
self:GetActor().condition)
end
-- print("Bastion: APL:Execute: No condition for spell " .. self:GetActor().spell:GetName())
self:GetActor().spell:CastableIf(self:GetActor().castableFunc):Cast(self:GetActor().target)
end
if self:GetActor().item then
if self:GetActor().condition then
-- print("Bastion: APL:Execute: Condition for spell " .. self:GetActor().spell:GetName())
self:GetActor().item:UsableIf(self:GetActor().usableFunc):Use(self:GetActor().target,
self:GetActor().condition)
end
-- print("Bastion: APL:Execute: No condition for spell " .. self:GetActor().spell:GetName())
self:GetActor().item:UsableIf(self:GetActor().usableFunc):Use(self:GetActor().target)
end
if self:GetActor().action then
-- print("Bastion: APL:Execute: Executing action " .. self:GetActor().action)
self:GetActor().cb(self)
end
if self:GetActor().variable then
-- print("Bastion: APL:Execute: Setting variable " .. self:GetActor().variable)
self:GetActor()._apl.variables[self:GetActor().variable] = self:GetActor().cb(self:GetActor()._apl)
end
2 years ago
return false
2 years ago
end
-- has traits
---@return boolean
2 years ago
function APLActor:HasTraits()
return #self.traits > 0
end
-- tostring
---@return string
2 years ago
function APLActor:__tostring()
return "Bastion.__APLActor"
end
2 years ago
-- APL (Attack priority list) class
---@class APL
2 years ago
local APL = {}
APL.__index = APL
-- Constructor
---@param name string
---@return APL
2 years ago
function APL:New(name)
local self = setmetatable({}, APL)
self.apl = {}
self.variables = {}
self.name = name
return self
end
-- Add a variable to the APL
---@param name string
---@param value any
2 years ago
function APL:SetVariable(name, value)
self.variables[name] = value
end
-- Get and evaluate a variable
---@param name string
---@return boolean
2 years ago
function APL:GetVariable(name)
return self.variables[name]
end
-- Add variable
---@param name string
---@param cb fun(...):any
---@return APLActor
function APL:AddVariable(name, cb)
local actor = APLActor:New({ variable = name, cb = cb, _apl = self })
table.insert(self.apl, actor)
return actor
end
2 years ago
-- Add a manual action to the APL
---@param action string
---@param cb fun(...):any
---@return APLActor
2 years ago
function APL:AddAction(action, cb)
2 years ago
local actor = APLActor:New({ action = action, cb = cb })
table.insert(self.apl, actor)
return actor
2 years ago
end
-- Add a spell to the APL
---@param spell Spell
---@param condition fun(...):boolean
---@return APLActor
2 years ago
function APL:AddSpell(spell, condition)
local castableFunc = spell.CastableIfFunc
local target = spell:GetTarget()
2 years ago
local actor = APLActor:New({ spell = spell, condition = condition, castableFunc = castableFunc, target = target })
table.insert(self.apl, actor)
return actor
2 years ago
end
-- Add an item to the APL
---@param item Item
---@param condition fun(...):boolean
---@return APLActor
function APL:AddItem(item, condition)
local usableFunc = item.UsableIfFunc
local target = item:GetTarget()
2 years ago
local actor = APLActor:New({ item = item, condition = condition, usableFunc = usableFunc, target = target })
table.insert(self.apl, actor)
return actor
end
2 years ago
-- Add an APL to the APL (for sub APLs)
---@param apl APL
---@param condition fun(...):boolean
---@return APLActor
2 years ago
function APL:AddAPL(apl, condition)
if not condition then
error("Bastion: APL:AddAPL: No condition for APL " .. apl.name)
end
2 years ago
local actor = APLActor:New({ apl = apl, condition = condition })
table.insert(self.apl, actor)
return actor
2 years ago
end
-- Execute the APL
function APL:Execute()
for _, actor in ipairs(self.apl) do
2 years ago
if actor:HasTraits() and actor:Evaluate() then
2 years ago
if actor:Execute() then
print("BREAQK", actor)
break
end
2 years ago
else
2 years ago
if actor:Execute() then
print("BREAQK", actor)
break
end
2 years ago
end
end
end
2 years ago
-- Add a Sequencer to the APL
---@param sequencer Sequencer
---@param condition fun(...):boolean
---@return APLActor
function APL:AddSequence(sequencer, condition)
local actor = APLActor:New({ sequencer = sequencer, condition = condition })
table.insert(self.apl, actor)
return actor
end
2 years ago
-- tostring
---@return string
2 years ago
function APL:__tostring()
return "Bastion.__APL(" .. self.name .. ")"
end
2 years ago
return APL, APLActor, APLTrait