Overview
Available in: Client Only
This module runs entirely on the client side. It handles the UI, inputs and visual effects.
OwlAction is a client-side wrapper around ContextActionService, built to replace scattered ContextActionService:BindAction(...) calls with declarative, named ActionMaps. Each ActionMap groups related inputs together, gets its own priority, and can be enabled or disabled as a unit a combat control scheme and a menu control scheme, for instance, living side by side without fighting over the same keys.
Creating an ActionMap
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Owl = require(ReplicatedStorage.OwlKnit.Owl)
local OwlAction = Owl.Util.Action
local CombatMap = OwlAction.CreateActionMap({
Name = "Combat",
Actions = {
Attack = { Enum.UserInputType.MouseButton1 },
Block = { Enum.KeyCode.F },
Dodge = { Enum.KeyCode.LeftShift, Enum.KeyCode.ButtonR2 },
},
Priority = Enum.ContextActionPriority.High.Value,
CreateTouchButtons = true,
Extensions = {},
})Each key in Actions is a name you choose; the value is a list of Enum.KeyCode or Enum.UserInputType entries that should trigger it list more than one to support multiple bindings for the same action, like Dodge above covering both keyboard and gamepad.
Binding callbacks
local unbind = CombatMap:Bind("Attack", function(state, inputObject)
if state == "Begin" then
performAttack()
end
end)
-- > // Later, to stop listening:
unbind()state is one of "Begin", "Change", or "End" the three phases ContextActionService already reports, normalized to plain strings. :Bind returns an unbind function rather than requiring you to track a connection object yourself; multiple callbacks can be bound to the same action and all of them fire on every dispatch.
Enabling and disabling
Creating an ActionMap doesn't make it active nothing is bound to ContextActionService until you call :Enable():
CombatMap:Enable()
-- ...
CombatMap:Disable()Only enabled ActionMaps consume input. This is the mechanism behind swapping control schemes cleanly disable a Menu ActionMap and enable a Combat one on the same keys and there's no overlap, no manual UnbindAction bookkeeping.
OwlAction.GetActive() returns every currently enabled ActionMap and OwlAction.DisableAll() tears all of them down at once handy for a hard reset, like opening a cutscene that should suspend every gameplay input at once.
Reading state directly
Sometimes you need to know if a key is held down right now without waiting for the next Begin/End event :GetState(actionName) polls the current input state directly:
if CombatMap:GetState("Dodge") then
-- > // Shift or the right trigger is currently held
endCleanup
CombatMap:Destroy()Disables the ActionMap, destroys its internal Trove and removes it from the registry after this, OwlAction.GetActionMap("Combat") returns nil.
Where to go next
- Extensions - observing an ActionMap's Enable/Disable lifecycle without modifying
CombatControlleritself.