Lua SDK
Getting started
A script is a Lua file with two optional entry points and a settings card:
lua
menu.group("My Script") -- settings card title
menu.slider('fov', 'Aim FOV', 10, 300, 120, 'px')
menu.keybind('aimkey', 'Aim key', 'Mouse2')
function on_tick()
local me = util.me()
if not me then return end -- not in a match / dead
if not util.held(menu.get_str('aimkey')) then return end
local e = util.best_enemy({ fov = menu.get('fov'), bone = 'chest' })
if e then util.aim_at_bone(e, 'chest', 6) end
end
function on_draw()
draw.text_centered('active', screen.center_x(), 40, draw.color(80, 255, 80))
end
Lifecycle in one paragraph#
Create the script in the Scripts tab, optionally bind it to specific heroes, and enable it.
The loader compiles it once; whenever your current hero matches the binding, a private
sandbox activates and starts receiving on_tick() every engine tick and on_draw() every
render frame. Hero swap, disable, delete, or a script error tears the sandbox down (pending
taps are dropped so a dead script never keeps firing). Values declared with menu.* appear
in the menu and persist across sessions.
The rules that matter#
- Start every tick with
util.me()- outside a match everything else is empty anyway. - Entity tables are rebuilt every tick. Hold
e.id, not the table, across ticks (or useutil.sticky_enemy, which does it for you). - Aim moves in clamped steps and never teleports.
mouse.aimtakes one clamped 20-30 deg step per tick - call it every tick and let it converge over several ticks. Write your own smoothing only if you have to (util.aim_atcovers most cases). - Held means held this frame.
key.hold/mouse.downassert for the current frame only - call them every tick.key.tapfires a randomized 2-5 tick pulse. - Gate new API on
sdk.version()if you share scripts across builds.
Where to go next#
- Scripting model - tick/draw dispatch, budgets, faulting, sandbox limits.
- Input & aim - action names, tap/hold/block merge semantics, aim model.
- Menu & config - every
menu.*param type and its limits. - The reference pages, and the bundled scripts (see builtins.md) as working examples.
Last updated 2026-10-03