local p=require((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\078\101\118\101\114\109\111\114\101"))local N=game:GetService("\067\111\110\116\101\120\116\065\099\116\105\111\110\083\101\114\118\105\099\101")local q=p("\083\105\103\110\097\108")local k=p("\077\097\105\100")local a=p("\069\110\097\098\108\101\100\077\105\120\105\110")local Y={}Y.__index=Y Y.ClassName="\066\097\115\101\065\099\116\105\111\110"a:Add(Y)function Y.new(p)assert(type(p)=="\116\097\098\108\101")local N=setmetatable({},Y)N._maid=k.new()N._name=p.Name or error("\078\111 \110\097\109\101")N._contextActionKey=("\037\115\095\067\111\110\116\101\120\116\065\099\116\105\111\110"):format(tostring(N._name))N._activateData=nil N.Activated=q.new()N._maid:GiveTask(N.Activated)N.Deactivated=q.new()N._maid:GiveTask(N.Deactivated)N.IsActivatedValue=Instance.new("\066\111\111\108\086\097\108\117\101")N.IsActivatedValue.Value=false N._maid:GiveTask(N.IsActivatedValue)N:InitEnabledMixin()N._maid:GiveTask(N.IsActivatedValue.Changed:Connect(function()N:_handleIsActiveValueChanged()end))N._maid:GiveTask(N.EnabledChanged:Connect(function(p)N:_handleEnabledChanged(p)end))N:_withActionData(p)return N end function Y._handleEnabledChanged(N,p)if not p then N:Deactivate()end N:_updateShortcuts()end function Y._handleIsActiveValueChanged(p)if p.IsActivatedValue.Value then local N=k.new()p._maid._actionMaid=N p.Activated:Fire(N,unpack(p._activateData))p._activateData=nil else p._maid._actionMaid=nil p.Deactivated:Fire()end end function Y.GetName(p)return p._name end function Y._withActionData(N,p)N._actionData=p or error("\078\111 \097\099\116\105\111\110\068\097\116\097")N:_updateShortcuts()return N end function Y._updateShortcuts(p)if not p._actionData then return end local q=p._actionData.Shortcuts if not(q and#q>0)then return end if p:IsEnabled()then N:BindAction(p._contextActionKey,function(N,q,k)if q==Enum.UserInputState.Begin then if p._actionData.CanActivateShortcutCallback then if not p._actionData.CanActivateShortcutCallback()then return end end p:ToggleActivate()end end,false,unpack(q))else N:UnbindAction(p._contextActionKey)end end function Y.GetData(p)return p._actionData end function Y.ToggleActivate(p,...)p._activateData={...}if p:IsEnabled()then p.IsActivatedValue.Value=not p.IsActivatedValue.Value else warn("\091\066\097\115\101\065\099\116\105\111\110\046\084\111\103\103\108\101\065\099\116\105\118\097\116\101\093 - \078\111\116 \097\099\116\105\118\097\116\105\110\103\044 \110\111\116 \101\110\097\098\108\101\100")p.IsActivatedValue.Value=false end end function Y.IsActive(p)return p.IsActivatedValue.Value end function Y.Deactivate(p)p.IsActivatedValue.Value=false end function Y.Activate(p,...)p._activateData={...}if p:IsEnabled()then p.IsActivatedValue.Value=true else warn(("\091\037\115\046\065\099\116\105\118\097\116\101\093 - \078\111\116 \097\099\116\105\118\097\116\105\110\103\046 \068\105\115\097\098\108\101\100\033"):format(p:GetName()))end end function Y.Destroy(p)p._maid:DoCleaning()setmetatable(p,nil)end return Y
--- BaseAction state for Actionmanager
-- @classmod BaseAction

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local ContextActionService = game:GetService("ContextActionService")

local Signal = require("Signal")
local Maid = require("Maid")
local EnabledMixin = require("EnabledMixin")

local BaseAction = {}
BaseAction.__index = BaseAction
BaseAction.ClassName = "BaseAction"

EnabledMixin:Add(BaseAction)

function BaseAction.new(actionData)
	assert(type(actionData) == "table")

	local self = setmetatable({}, BaseAction)

	self._maid = Maid.new()
	self._name = actionData.Name or error("No name")
	self._contextActionKey = ("%s_ContextAction"):format(tostring(self._name))
	self._activateData = nil -- Data to be fired with the Activated event

	self.Activated = Signal.new() -- :Fire(actionMaid, ... (activateData))
	self._maid:GiveTask(self.Activated)

	self.Deactivated = Signal.new() -- :Fire()
	self._maid:GiveTask(self.Deactivated)

	self.IsActivatedValue = Instance.new("BoolValue")
	self.IsActivatedValue.Value = false
	self._maid:GiveTask(self.IsActivatedValue)

	self:InitEnabledMixin()

	self._maid:GiveTask(self.IsActivatedValue.Changed:Connect(function()
		self:_handleIsActiveValueChanged()
	end))

	-- Prevent being activated when disabled
	self._maid:GiveTask(self.EnabledChanged:Connect(function(isEnabled)
		self:_handleEnabledChanged(isEnabled)
	end))

	self:_withActionData(actionData)


	return self
end

function BaseAction:_handleEnabledChanged(isEnabled)
	if not isEnabled then
		self:Deactivate()
	end

	self:_updateShortcuts()
end

function BaseAction:_handleIsActiveValueChanged()
	if self.IsActivatedValue.Value then
		local actionMaid = Maid.new()
		self._maid._actionMaid = actionMaid
		self.Activated:Fire(actionMaid, unpack(self._activateData))
		self._activateData = nil
	else
		self._maid._actionMaid = nil
		self.Deactivated:Fire()
	end
end

function BaseAction:GetName()
	return self._name
end

function BaseAction:_withActionData(actionData)
	self._actionData = actionData or error("No actionData")

	self:_updateShortcuts()

	return self
end

function BaseAction:_updateShortcuts()
	if not self._actionData then
		return
	end

	local shortcuts = self._actionData.Shortcuts
	if not (shortcuts and #shortcuts > 0) then
		return
	end

	if self:IsEnabled() then
		ContextActionService:BindAction(self._contextActionKey, function(actionName, userInputState, inputObject)
			if userInputState == Enum.UserInputState.Begin then
				if self._actionData.CanActivateShortcutCallback then
					if not self._actionData.CanActivateShortcutCallback() then
						return
					end
				end

				self:ToggleActivate()
			end
		end, false, unpack(shortcuts))
	else
		ContextActionService:UnbindAction(self._contextActionKey)
	end
end

function BaseAction:GetData()
	return self._actionData
end

function BaseAction:ToggleActivate(...)
	self._activateData = {...}

	if self:IsEnabled() then
		self.IsActivatedValue.Value = not (self.IsActivatedValue.Value)
	else
		warn("[BaseAction.ToggleActivate] - Not activating, not enabled")
		self.IsActivatedValue.Value = false
	end
end

function BaseAction:IsActive()
	return self.IsActivatedValue.Value
end

function BaseAction:Deactivate()
	self.IsActivatedValue.Value = false
end

function BaseAction:Activate(...)
	self._activateData = {...}

	if self:IsEnabled() then
		self.IsActivatedValue.Value = true
	else
		warn(("[%s.Activate] - Not activating. Disabled!"):format(self:GetName()))
	end
end

function BaseAction:Destroy()
	self._maid:DoCleaning()

	setmetatable(self, nil)
end

return BaseAction