forked from Bastion/Bastion
parent
a572688294
commit
031c68009c
@ -0,0 +1,141 @@ |
|||||||
|
---@type Tinkr, Bastion |
||||||
|
local Tinkr, 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 actorTable.condition and actorTable.condition() and not actorTable.sequencer:Finished() then |
||||||
|
actorTable.sequencer:Execute() |
||||||
|
return true |
||||||
|
end |
||||||
|
|
||||||
|
if not 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 actorTable.condition and actorTable.condition() then |
||||||
|
-- print("Bastion: APL:Execute: Executing sub APL " .. actorTable.apl.name) |
||||||
|
if actorTable.apl:Execute() then |
||||||
|
return true |
||||||
|
end |
||||||
|
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 |
||||||
|
|
||||||
|
return APLActor |
@ -0,0 +1,42 @@ |
|||||||
|
---@type Tinkr, Bastion |
||||||
|
local Tinkr, Bastion = ... |
||||||
|
|
||||||
|
-- Create an APL trait for the APL class |
||||||
|
---@class Bastion.APLTrait |
||||||
|
---@field cb fun(actor?: Bastion.APLActor.Table):boolean |
||||||
|
---@field lastcall number |
||||||
|
local APLTrait = {} |
||||||
|
APLTrait.__index = APLTrait |
||||||
|
|
||||||
|
-- Constructor |
||||||
|
---@param cb fun(actor?: Bastion.APLActor.Table):boolean |
||||||
|
---@return Bastion.APLTrait |
||||||
|
function APLTrait:New(cb) |
||||||
|
local self = setmetatable({}, APLTrait) |
||||||
|
|
||||||
|
self.cb = cb |
||||||
|
self.lastcall = 0 |
||||||
|
|
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
-- Evaulate the APL trait |
||||||
|
---@param actor? Bastion.APLActor.Table |
||||||
|
---@return boolean |
||||||
|
function APLTrait:Evaluate(actor) |
||||||
|
if GetTime() - self.lastcall > 0.1 then |
||||||
|
self.lastresult = self.cb(actor) |
||||||
|
self.lastcall = GetTime() |
||||||
|
return self.lastresult |
||||||
|
end |
||||||
|
|
||||||
|
return self.lastresult |
||||||
|
end |
||||||
|
|
||||||
|
-- tostring |
||||||
|
---@return string |
||||||
|
function APLTrait:__tostring() |
||||||
|
return "Bastion.__APLTrait" |
||||||
|
end |
||||||
|
|
||||||
|
return APLTrait |
@ -0,0 +1,69 @@ |
|||||||
|
---@type Tinkr, Bastion |
||||||
|
local Tinkr, Bastion = ... |
||||||
|
|
||||||
|
-- Create a notification class for the notifications list (takes icon and text) |
||||||
|
---@class Bastion.Notification |
||||||
|
---@field icon Texture |
||||||
|
---@field text FontString |
||||||
|
---@field frame Frame |
||||||
|
---@field addedAt number |
||||||
|
---@field duration number |
||||||
|
---@field list Bastion.NotificationList |
||||||
|
local Notification = { |
||||||
|
} |
||||||
|
Notification.__index = Notification |
||||||
|
|
||||||
|
-- Constructor |
||||||
|
---@param list Bastion.NotificationList |
||||||
|
---@param icon string |
||||||
|
---@param text string |
||||||
|
---@param duration number |
||||||
|
---@return Bastion.Notification |
||||||
|
function Notification:New(list, icon, text, duration) |
||||||
|
local self = setmetatable({}, Notification) |
||||||
|
|
||||||
|
if not duration then duration = 2 end |
||||||
|
|
||||||
|
-- Create a frame for the notification |
||||||
|
self.frame = CreateFrame("Frame", nil, list.frame) |
||||||
|
self.frame:SetSize(5, 5) |
||||||
|
self.frame:SetPoint("CENTER", list.frame, "CENTER", 0, 0) |
||||||
|
self.frame:SetFrameStrata("HIGH") |
||||||
|
|
||||||
|
-- Create a texture for the icon |
||||||
|
self.icon = self.frame:CreateTexture(nil, "ARTWORK") |
||||||
|
self.icon:SetSize(32, 32) |
||||||
|
self.icon:SetPoint("LEFT", self.frame, "LEFT", 0, 0) |
||||||
|
self.icon:SetTexture(icon) |
||||||
|
|
||||||
|
-- Create a fontstring for the text |
||||||
|
self.text = self.frame:CreateFontString(nil, "BACKGROUND", "NumberFontNormal") |
||||||
|
self.text:SetPoint("LEFT", self.frame, "LEFT", 32 + 16, 0) |
||||||
|
self.text:SetText(text) |
||||||
|
self.text:SetFont("Fonts\\OpenSans-Bold.ttf", 18, "") |
||||||
|
|
||||||
|
-- set the frame size to the size of the text + icon |
||||||
|
self.frame:SetSize(self.text:GetStringWidth() + 32 + 16, 32) |
||||||
|
|
||||||
|
self.addedAt = GetTime() |
||||||
|
self.duration = duration |
||||||
|
self.list = list |
||||||
|
|
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
-- Remove notification |
||||||
|
---@return nil |
||||||
|
function Notification:Remove() |
||||||
|
-- Fade out the notification frame and remove it after the fade |
||||||
|
UIFrameFadeOut(self.frame, 0.2, 1, 0) |
||||||
|
C_Timer.After(0.5, function() |
||||||
|
self.frame:Hide() |
||||||
|
self.frame:ClearAllPoints() |
||||||
|
self.frame:SetParent(nil) |
||||||
|
self.frame = nil |
||||||
|
self.list:Update() |
||||||
|
end) |
||||||
|
end |
||||||
|
|
||||||
|
return Notification |
@ -0,0 +1,92 @@ |
|||||||
|
---@type Tinkr, Bastion |
||||||
|
local Tinkr, Bastion = ... |
||||||
|
|
||||||
|
-- Create a NotificationList class |
||||||
|
|
||||||
|
---@class Bastion.NotificationList |
||||||
|
---@field frame Frame |
||||||
|
local NotificationList = { |
||||||
|
notifications = {} |
||||||
|
} |
||||||
|
NotificationList.__index = NotificationList |
||||||
|
|
||||||
|
-- Constructor |
||||||
|
---@return Bastion.NotificationList |
||||||
|
function NotificationList:New() |
||||||
|
local self = setmetatable({}, NotificationList) |
||||||
|
|
||||||
|
-- Create a frame for the notifications |
||||||
|
self.frame = CreateFrame("Frame", "BastionNotificationList", UIParent) |
||||||
|
self.frame:SetSize(600, 60) |
||||||
|
self.frame:SetPoint("TOP", UIParent, "TOP", 0, -100) |
||||||
|
self.frame:SetFrameStrata("HIGH") |
||||||
|
|
||||||
|
-- Remove notifications after 5 seconds |
||||||
|
C_Timer.NewTicker(0.1, function() |
||||||
|
for i, notification in ipairs(self.notifications) do |
||||||
|
if GetTime() - notification.addedAt > notification.duration then |
||||||
|
notification:Remove() |
||||||
|
table.remove(self.notifications, i) |
||||||
|
end |
||||||
|
end |
||||||
|
end) |
||||||
|
|
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
-- Add a notification to the list |
||||||
|
---@param icon string |
||||||
|
---@param text string |
||||||
|
---@param duration number |
||||||
|
---@return nil |
||||||
|
function NotificationList:AddNotification(icon, text, duration) |
||||||
|
-- Create a new notification |
||||||
|
local notification = Bastion.Notification:New(self, icon, text, duration) |
||||||
|
|
||||||
|
-- Add the notification to the list |
||||||
|
table.insert(self.notifications, notification) |
||||||
|
UIFrameFadeIn(notification.frame, 0.2, 0, 1) |
||||||
|
|
||||||
|
-- Update the notifications |
||||||
|
self:Update() |
||||||
|
end |
||||||
|
|
||||||
|
-- Update the notifications |
||||||
|
---@return nil |
||||||
|
function NotificationList:Update() |
||||||
|
-- Loop through the notifications |
||||||
|
for i, notification in ipairs(self.notifications) do |
||||||
|
-- Set the position of the notification |
||||||
|
notification.frame:SetPoint("CENTER", self.frame, "CENTER", 0, -42 * (i - 1)) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
-- Remove a notification from the list |
||||||
|
---@param notification Bastion.Notification |
||||||
|
---@return nil |
||||||
|
function NotificationList:RemoveNotification(notification) |
||||||
|
-- Loop through the notifications |
||||||
|
for i, v in ipairs(self.notifications) do |
||||||
|
-- Check if the notification is the one we want to remove |
||||||
|
if v == notification then |
||||||
|
-- Remove the notification from the list |
||||||
|
table.remove(self.notifications, i) |
||||||
|
notification:Remove() |
||||||
|
break |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
-- Remove all notifications from the list |
||||||
|
---@return nil |
||||||
|
function NotificationList:RemoveAllNotifications() |
||||||
|
-- Loop through the notifications |
||||||
|
for i, v in ipairs(self.notifications) do |
||||||
|
-- Remove the notification from the list |
||||||
|
table.remove(self.notifications, i) |
||||||
|
self.notifications[i]:Remove() |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
-- Remove all notifications |
||||||
|
return NotificationList |
@ -1,147 +0,0 @@ |
|||||||
-- Create a NotificationsList class |
|
||||||
|
|
||||||
---@class NotificationsList |
|
||||||
local NotificationsList = { |
|
||||||
notifications = {} |
|
||||||
} |
|
||||||
NotificationsList.__index = NotificationsList |
|
||||||
|
|
||||||
-- Constructor |
|
||||||
---@return NotificationsList |
|
||||||
function NotificationsList:New() |
|
||||||
local self = setmetatable({}, NotificationsList) |
|
||||||
|
|
||||||
-- Create a frame for the notifications |
|
||||||
self.frame = CreateFrame("Frame", "BastionNotificationsList", UIParent) |
|
||||||
self.frame:SetSize(600, 60) |
|
||||||
self.frame:SetPoint("TOP", UIParent, "TOP", 0, -100) |
|
||||||
self.frame:SetFrameStrata("HIGH") |
|
||||||
|
|
||||||
-- Remove notifications after 5 seconds |
|
||||||
C_Timer.NewTicker(0.1, function() |
|
||||||
for i, notification in ipairs(self.notifications) do |
|
||||||
if GetTime() - notification.addedAt > notification.duration then |
|
||||||
notification:Remove() |
|
||||||
table.remove(self.notifications, i) |
|
||||||
end |
|
||||||
end |
|
||||||
end) |
|
||||||
|
|
||||||
return self |
|
||||||
end |
|
||||||
|
|
||||||
-- Create a notification class for the notifications list (takes icon and text) |
|
||||||
---@class Notification |
|
||||||
local Notification = { |
|
||||||
} |
|
||||||
Notification.__index = Notification |
|
||||||
|
|
||||||
-- Constructor |
|
||||||
---@param list NotificationsList |
|
||||||
---@param icon string |
|
||||||
---@param text string |
|
||||||
---@param duration number |
|
||||||
---@return Notification |
|
||||||
function Notification:New(list, icon, text, duration) |
|
||||||
local self = setmetatable({}, Notification) |
|
||||||
|
|
||||||
if not duration then duration = 2 end |
|
||||||
|
|
||||||
-- Create a frame for the notification |
|
||||||
self.frame = CreateFrame("Frame", nil, list.frame) |
|
||||||
self.frame:SetSize(5, 5) |
|
||||||
self.frame:SetPoint("CENTER", list.frame, "CENTER", 0, 0) |
|
||||||
self.frame:SetFrameStrata("HIGH") |
|
||||||
|
|
||||||
-- Create a texture for the icon |
|
||||||
self.icon = self.frame:CreateTexture(nil, "ARTWORK") |
|
||||||
self.icon:SetSize(32, 32) |
|
||||||
self.icon:SetPoint("LEFT", self.frame, "LEFT", 0, 0) |
|
||||||
self.icon:SetTexture(icon) |
|
||||||
|
|
||||||
-- Create a fontstring for the text |
|
||||||
self.text = self.frame:CreateFontString(nil, "BACKGROUND", "NumberFontNormal") |
|
||||||
self.text:SetPoint("LEFT", self.frame, "LEFT", 32 + 16, 0) |
|
||||||
self.text:SetText(text) |
|
||||||
self.text:SetFont("Fonts\\OpenSans-Bold.ttf", 18) |
|
||||||
|
|
||||||
-- set the frame size to the size of the text + icon |
|
||||||
self.frame:SetSize(self.text:GetStringWidth() + 32 + 16, 32) |
|
||||||
|
|
||||||
self.addedAt = GetTime() |
|
||||||
self.duration = duration |
|
||||||
self.list = list |
|
||||||
|
|
||||||
return self |
|
||||||
end |
|
||||||
|
|
||||||
-- Remove notification |
|
||||||
---@return nil |
|
||||||
function Notification:Remove() |
|
||||||
-- Fade out the notification frame and remove it after the fade |
|
||||||
UIFrameFadeOut(self.frame, 0.2, 1, 0) |
|
||||||
C_Timer.After(0.5, function() |
|
||||||
self.frame:Hide() |
|
||||||
self.frame:ClearAllPoints() |
|
||||||
self.frame:SetParent(nil) |
|
||||||
self.frame = nil |
|
||||||
self.list:Update() |
|
||||||
end) |
|
||||||
end |
|
||||||
|
|
||||||
-- Add a notification to the list |
|
||||||
---@param icon string |
|
||||||
---@param text string |
|
||||||
---@param duration number |
|
||||||
---@return nil |
|
||||||
function NotificationsList:AddNotification(icon, text, duration) |
|
||||||
-- Create a new notification |
|
||||||
local notification = Notification:New(self, icon, text, duration) |
|
||||||
|
|
||||||
-- Add the notification to the list |
|
||||||
table.insert(self.notifications, notification) |
|
||||||
UIFrameFadeIn(notification.frame, 0.2, 0, 1) |
|
||||||
|
|
||||||
-- Update the notifications |
|
||||||
self:Update() |
|
||||||
end |
|
||||||
|
|
||||||
-- Update the notifications |
|
||||||
---@return nil |
|
||||||
function NotificationsList:Update() |
|
||||||
-- Loop through the notifications |
|
||||||
for i, notification in ipairs(self.notifications) do |
|
||||||
-- Set the position of the notification |
|
||||||
notification.frame:SetPoint("CENTER", self.frame, "CENTER", 0, -42 * (i - 1)) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Remove a notification from the list |
|
||||||
---@param notification Notification |
|
||||||
---@return nil |
|
||||||
function NotificationsList:RemoveNotification(notification) |
|
||||||
-- Loop through the notifications |
|
||||||
for i, v in ipairs(self.notifications) do |
|
||||||
-- Check if the notification is the one we want to remove |
|
||||||
if v == notification then |
|
||||||
-- Remove the notification from the list |
|
||||||
table.remove(self.notifications, i) |
|
||||||
notification:Remove() |
|
||||||
break |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Remove all notifications from the list |
|
||||||
---@return nil |
|
||||||
function NotificationsList:RemoveAllNotifications() |
|
||||||
-- Loop through the notifications |
|
||||||
for i, v in ipairs(self.notifications) do |
|
||||||
-- Remove the notification from the list |
|
||||||
table.remove(self.notifications, i) |
|
||||||
self.notifications[i]:Remove() |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Remove all notifications |
|
||||||
return NotificationsList, Notification |
|
Loading…
Reference in new issue