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