Lua · AimSync Hardware

Lua Scripting API

Complete reference for the AimSync Lua scripting engine. Write custom scripts to control aim behavior, input, recoil, detection filtering, and more — all streamed live from the webmenu.

Getting Started

Lua scripts give you full programmatic control over AimSync's behavior. Scripts are written in Lua 5.4 and executed inside the AimSync hardware client.

Step 1 Write your script

Use the Lua Script Editor in the webmenu (Lua tab). Write or paste your code in the editor.

Step 2 Stream to AimSync

Click "Stream to AimSync". The script is sent to the server as a pending payload. Within ~2 seconds, the AimSync client picks it up and loads it live.

Step 3 Script executes

Your script's global code runs once on load. Then your callback functions (like on_tick, on_pre_aim, on_frame) are called automatically every frame or event.

How It Works

The Lua engine runs inside the same process as AimSync. Scripts have direct access to all internal systems via bound API tables.

-- Script lifecycle: -- 1. Global code executes once when script is loaded -- 2. Callback functions are called each frame/event -- 3. Loading a new script resets all overrides print("Script loaded! Weapon: " .. config.get_current_weapon()) function on_tick() -- Called every main loop iteration end

API Reference

All functions are organized into tables (namespaces). Call them as table.function().

Table   config

Read and write webmenu configuration values. Most weapon-specific functions accept an optional weapon parameter (1–8); defaults to the current weapon.

Getters

FunctionParametersReturnsDescription
get_aimbot_enabled()booleanWhether aimbot is enabled
get_confidence()integerConfidence slider value (0–100)
get_current_weapon()integerActive weapon preset (1–8)
get_fov_x([weapon])opt intintegerHorizontal FOV in pixels
get_fov_y([weapon])opt intintegerVertical FOV in pixels
get_smoothing_x1([weapon])opt intnumberSmoothing X for aimkey 1
get_smoothing_y1([weapon])opt intnumberSmoothing Y for aimkey 1
get_smoothing_x2([weapon])opt intnumberSmoothing X for aimkey 2
get_smoothing_y2([weapon])opt intnumberSmoothing Y for aimkey 2
get_acceleration_x1([weapon])opt intnumberAcceleration X for aimkey 1
get_acceleration_y1([weapon])opt intnumberAcceleration Y for aimkey 1
get_acceleration_x2([weapon])opt intnumberAcceleration X for aimkey 2
get_acceleration_y2([weapon])opt intnumberAcceleration Y for aimkey 2
get_aimbot_key([weapon])opt intintegerVirtual key code for aimkey 1
get_aimbot_key2([weapon])opt intintegerVirtual key code for aimkey 2
get_aimbot_mode([weapon])opt intintegerAim mode for aimkey 1
get_aimbot_mode2([weapon])opt intintegerAim mode for aimkey 2
get_aim_stop_key([weapon])opt intintegerKey code for aim stop
get_recoil_enabled()booleanWhether recoil control is on
get_recoil_x([weapon])opt intnumberRecoil X compensation value
get_recoil_y([weapon])opt intnumberRecoil Y compensation value
get_recoil_multiplier([weapon])opt intintegerRecoil pattern multiplier
get_triggerbot_enabled()booleanWhether triggerbot is enabled
get_triggerbot_key()integerTriggerbot activation key
get_triggerbot_first_delay_min()integerFirst shot delay minimum (ms)
get_triggerbot_first_delay_max()integerFirst shot delay maximum (ms)
get_triggerbot_next_delay_min()integerFollow-up shot delay min (ms)
get_triggerbot_next_delay_max()integerFollow-up shot delay max (ms)
get_triggerbot_positions()stringTriggerbot target positions
get_video_mode()string"capture_card" or "udp"
get_capture_device()stringCapture device name / ID

Setters

Write config values. Changes are applied immediately and synced to the webmenu. Weapon-specific setters default to the current weapon if weapon is omitted.

FunctionParametersReturnsDescription
set_aimbot_enabled(val)req booleanEnable or disable aimbot
set_confidence(val)req integerSet confidence slider value (0–100)
set_current_weapon(val)req integerSet active weapon preset (1–8)
set_recoil_enabled(val)req booleanEnable or disable recoil control
set_triggerbot_enabled(val)req booleanEnable or disable triggerbot
set_video_mode(val)req stringSet video mode: "capture_card" or "udp"
set_capture_device(val)req stringSet capture device name / ID
set_triggerbot_key(val)req integerSet triggerbot activation key
set_triggerbot_first_delay_min(val)req integerSet first shot delay minimum (ms)
set_triggerbot_first_delay_max(val)req integerSet first shot delay maximum (ms)
set_triggerbot_next_delay_min(val)req integerSet follow-up shot delay min (ms)
set_triggerbot_next_delay_max(val)req integerSet follow-up shot delay max (ms)
set_triggerbot_positions(val)req stringSet triggerbot target positions
set_recoil_key(val)req integerSet recoil activation key
set_recoil_stop_mode(val)req integerSet recoil stop mode
set_fov_x([weapon,] val)opt int, req intSet horizontal FOV in pixels
set_fov_y([weapon,] val)opt int, req intSet vertical FOV in pixels
set_smoothing_x1([weapon,] val)opt int, req numberSet smoothing X for aimkey 1
set_smoothing_y1([weapon,] val)opt int, req numberSet smoothing Y for aimkey 1
set_smoothing_x2([weapon,] val)opt int, req numberSet smoothing X for aimkey 2
set_smoothing_y2([weapon,] val)opt int, req numberSet smoothing Y for aimkey 2
set_acceleration_x1([weapon,] val)opt int, req numberSet acceleration X for aimkey 1
set_acceleration_y1([weapon,] val)opt int, req numberSet acceleration Y for aimkey 1
set_acceleration_x2([weapon,] val)opt int, req numberSet acceleration X for aimkey 2
set_acceleration_y2([weapon,] val)opt int, req numberSet acceleration Y for aimkey 2
set_aimbot_key([weapon,] val)opt int, req intSet virtual key code for aimkey 1
set_aimbot_key2([weapon,] val)opt int, req intSet virtual key code for aimkey 2
set_aim_stop_key([weapon,] val)opt int, req intSet key code for aim stop
set_aim_stop_mode([weapon,] val)opt int, req intSet aim stop mode
set_aimbot_mode([weapon,] val)opt int, req intSet aim mode for aimkey 1
set_aimbot_mode2([weapon,] val)opt int, req intSet aim mode for aimkey 2
set_recoil_x([weapon,] val)opt int, req numberSet recoil X compensation value
set_recoil_y([weapon,] val)opt int, req numberSet recoil Y compensation value
-- Disable aimbot and switch to weapon 2 config.set_aimbot_enabled(false) config.set_current_weapon(2) -- Set FOV for weapon 3 config.set_fov_x(3, 200) config.set_fov_y(3, 200) -- Set smoothing for current weapon config.set_smoothing_x1(0.5) config.set_smoothing_y1(0.5)

Table   pid

Control the PID controllers used for aim smoothing. Axis parameter: "x", "y", or "both".

FunctionParametersReturnsDescription
set_kp(axis, value)req string, numberSet proportional gain
set_ki(axis, value)req string, numberSet integral gain
set_kd(axis, value)req string, numberSet derivative gain
set_max_output(axis, value)req string, numberClamp maximum PID output
set_integral_limit(axis, value)req string, numberLimit integral accumulation
set_filter_alpha(axis, value)req string, numberDerivative low-pass filter (0–1)
set_derivative_on_measurement(axis, bool)req string, booleanUse D-on-measurement vs D-on-error
get_kp(axis)req stringnumberCurrent Kp value
get_ki(axis)req stringnumberCurrent Ki value
get_kd(axis)req stringnumberCurrent Kd value
get_max_output(axis)req stringnumberCurrent max output
get_integral_limit(axis)req stringnumberCurrent integral limit
reset(axis)req stringReset integral accumulator
-- Make aim snappier on both axes pid.set_kp("both", 0.8) pid.set_kd("both", 0.1) pid.set_max_output("both", 80.0)

Table   mouse

Direct hardware mouse control via the Makcu device. Button is an integer 0–4 matching MouseButton: LEFT = 0, RIGHT = 1, MIDDLE = 2, SIDE1 = 3, SIDE2 = 4.

FunctionParametersReturnsDescription
move(dx, dy)req int, intMove mouse by relative delta
down(button)req intPress and hold a mouse button
up(button)req intRelease a mouse button
click(button [, holdMs])req int, opt intClick (press + delay + release). Default hold: 30ms
is_pressed(button)req intbooleanCheck if button is currently held
-- Left-click with 50ms hold (LEFT = 0) mouse.click(0, 50) -- Check if right mouse is held (RIGHT = 1) if mouse.is_pressed(1) then print("ADS active") end

Table   recoil

Control the recoil compensation system.

FunctionParametersReturnsDescription
start()Begin recoil compensation pattern
stop()Stop recoil compensation
is_active()booleanWhether pattern is currently playing
is_finished()booleanWhether pattern has completed
set_fire_rate(rpm)req intSet fire rate in rounds per minute
set_micro_steps(n)req intInterpolation steps between points
set_screen_scale(scale)req numberScale factor for screen resolution
set_step_interval(ms)req intSet interval between recoil steps (ms)
load_pattern(steps [, scaleX [, scaleY]])req table, opt number, opt numberintegerLoad a recoil pattern from a Lua table. Each entry is {dx=N, dy=N} or {N, N}. Returns step count.
clear_pattern()Clear the loaded recoil pattern
get_step_count()integerNumber of steps in the loaded pattern
get_current_step()integerIndex of the currently executing step
-- Load a custom 5-step recoil pattern local pattern = { { dx = 0, dy = 2 }, { dx = 1, dy = 3 }, { dx = -1, dy = 4 }, { dx = 2, dy = 3 }, { dx = 0, dy = 2 }, } local count = recoil.load_pattern(pattern, 1.0, 1.0) print("Loaded " .. count .. " steps") recoil.set_step_interval(50) recoil.start() -- Check progress in on_tick function on_tick() if recoil.is_active() then print("Step " .. recoil.get_current_step() .. " / " .. recoil.get_step_count()) end end

Table   screen

Read screen and capture dimensions.

FunctionReturnsDescription
width()numberMonitor screen width
height()numberMonitor screen height
capture_width()integerCapture card resolution width
capture_height()integerCapture card resolution height
local cx = screen.width() / 2 local cy = screen.height() / 2 print("Screen center: " .. cx .. ", " .. cy)

Table   aim

Override aim behavior at runtime. These overrides persist until changed or until a new script is loaded (which resets them).

FunctionParametersDescription
set_enabled(bool|nil)req boolean or nilForce aimbot on/off. Pass nil to restore webmenu setting.
set_delta_scale(scaleX, scaleY)req number, numberMultiply aim deltas by these factors (1.0 = normal)
set_target_override(x, y)req number, numberForce aim target to specific screen coordinates
clear_target_override()Remove target override, return to normal targeting
-- Reduce aim speed by 50% aim.set_delta_scale(0.5, 0.5) -- Temporarily disable aimbot aim.set_enabled(false) -- Restore to webmenu setting aim.set_enabled(nil)

Table   detection

Filter which detections the aimbot processes.

FunctionParametersDescription
set_min_confidence(value|nil)req number or nilOverride minimum confidence threshold (0.0–1.0). Pass nil to use webmenu value.
filter_class(classId|nil)req int or nilOnly aim at a specific class ID. Pass nil to disable filter.
-- Only aim at class 0 (e.g., "head") with 60% min confidence detection.filter_class(0) detection.set_min_confidence(0.6) -- Clear filters detection.filter_class(nil) detection.set_min_confidence(nil)

Table   model

Query information about the currently loaded ONNX model.

FunctionReturnsDescription
get_name()stringFull path of the loaded model file
get_width()integerModel input width (e.g., 640)
get_height()integerModel input height (e.g., 640)
get_class_count()integerNumber of detection classes
get_class_names()tableArray of class name strings (1-indexed)
local names = model.get_class_names() for i, name in ipairs(names) do print("Class " .. i .. ": " .. name) end

Table   math2

Extended math utilities. Named math2 to avoid shadowing Lua's built-in math library.

FunctionParametersReturnsDescription
distance(x1, y1, x2, y2)req number ×4numberEuclidean distance between two points
lerp(a, b, t)req number ×3numberLinear interpolation: a + t*(b-a)
clamp(value, min, max)req number ×3numberClamp value to [min, max] range

Table   draw

Immediate-mode drawing API. Call these from on_frame or on_tick to render custom overlays on the detection preview window. Commands are rendered once per frame — call them every frame to persist.

FunctionParametersReturnsDescription
text(x, y, text [, r, g, b [, fontSize [, thickness]]])req num, num, string, opt int ×3, num, intDraw text on the detection preview. Default: white, 0.5 scale, 1px.
rect(x, y, w, h [, r, g, b [, thickness]])req num ×4, opt int ×3, intDraw rectangle outline. Default: green, 2px.
filled_rect(x, y, w, h [, r, g, b [, alpha]])req num ×4, opt int ×3, numDraw filled rectangle. alpha 0.0–1.0 for transparency.
circle(x, y, radius [, r, g, b [, thickness]])req num ×3, opt int ×3, intDraw circle outline. Default: green, 2px.
filled_circle(x, y, radius [, r, g, b])req num ×3, opt int ×3Draw filled circle.
line(x1, y1, x2, y2 [, r, g, b [, thickness]])req num ×4, opt int ×3, intDraw line segment. Default: green, 2px.
clear()Manually clear all pending draw commands.

Color Format

Colors use RGB values (0–255). If omitted, defaults are: text = white (255,255,255), shapes = green (0,255,0).

-- Draw a crosshair at screen center function on_frame(dets) local cx = screen.capture_width() / 2 local cy = screen.capture_height() / 2 -- Yellow crosshair lines draw.line(cx - 10, cy, cx + 10, cy, 255, 255, 0) draw.line(cx, cy - 10, cx, cy + 10, 255, 255, 0) -- Label each detection with a circle on the head for _, d in ipairs(dets) do draw.text(d.x, d.y - 10, d.label, 255, 0, 0, 0.4) draw.circle(d.x + d.width/2, d.y + d.height/5, 8, 255, 0, 255, 2) end -- Semi-transparent info bar draw.filled_rect(5, 5, 200, 25, 0, 0, 0, 0.5) draw.text(10, 22, "Detections: " .. #dets, 255, 255, 255, 0.45) end

Global   System Functions

Available at the top level — no table prefix needed.

FunctionParametersReturnsDescription
log(message)req stringWrite message to AimSync log file (prefixed [Lua])
print(...)any valuesPrint to console (overrides default Lua print)
sleep(ms)req intSleep for up to 5000ms. Caution: blocks the calling thread.
time()numberHigh-resolution monotonic time in seconds (steady_clock)
get_tick_count()integerMilliseconds since system boot (GetTickCount64)
-- Log a message and check elapsed time log("Script started") local start = time() sleep(100) print("Elapsed: " .. time() - start .. "s")

Callbacks

Define these functions in your script and they will be called automatically by the engine. All callbacks are optional — only define the ones you need.

Callback   on_pre_aim(ctx) → table

Called before aim movement is applied. Receives a context table and can return modified deltas.

Input Context Table

FieldTypeDescription
delta_xnumberCalculated horizontal aim delta
delta_ynumberCalculated vertical aim delta
target_xnumberTarget screen X coordinate
target_ynumberTarget screen Y coordinate
center_xnumberScreen center X
center_ynumberScreen center Y

Return Value

Return a table with delta_x and delta_y to override the aim deltas. Return nil to use default behavior.

function on_pre_aim(ctx) -- Add random jitter to look more human local jitter = 0.8 + math.random() * 0.4 return { delta_x = ctx.delta_x * jitter, delta_y = ctx.delta_y * jitter } end

Callback   on_post_aim(movedX, movedY)

Called after aim movement is sent to the device. Useful for logging or analytics.

ParameterTypeDescription
movedXnumberActual horizontal pixels moved
movedYnumberActual vertical pixels moved
function on_post_aim(mx, my) log("Moved: " .. mx .. ", " .. my) end

Callback   on_frame(detections)

Called every frame with all current detections. Receives a Lua array of detection tables.

Detection Table Fields

FieldTypeDescription
xnumberBounding box X position
ynumberBounding box Y position
widthnumberBounding box width
heightnumberBounding box height
class_idintegerDetection class index
confidencenumberDetection confidence (0.0–1.0)
labelstringHuman-readable class name
function on_frame(dets) for i, d in ipairs(dets) do print(string.format( "[%d] %s (%.0f%%) at %d,%d %dx%d", i, d.label, d.confidence * 100, d.x, d.y, d.width, d.height )) end end

Callback   on_triggerbot(inCrosshair) → boolean

Called when the triggerbot evaluates whether to fire. Return true/false to override, or nil to use default logic.

ParameterTypeDescription
inCrosshairbooleanWhether a target is in the crosshair zone
function on_triggerbot(inCrosshair) -- Only fire if right mouse is also held (ADS) if inCrosshair and mouse.is_pressed(1) then return true end return false end

Callback   on_tick()

Called once per main loop iteration — ideal for continuous input checks, state machines, or per-frame logic.

local frameCount = 0 function on_tick() frameCount = frameCount + 1 if frameCount % 300 == 0 then print("Tick #" .. frameCount .. " — weapon: " .. config.get_current_weapon()) end end

Callback   on_config_update()

Called every time the config polling thread refreshes settings from the webmenu (approximately every 2 seconds). Use it to react to config changes dynamically.

function on_config_update() local weapon = config.get_current_weapon() print("Config refreshed — weapon " .. weapon) end

Example Scripts

Ready-to-use scripts you can paste into the webmenu Lua editor.

Example Distance-Based Aim Scaling

Automatically adjusts aim speed based on how far the target is from center — slower when close, faster when far.

function on_pre_aim(ctx) local dist = math2.distance( ctx.center_x, ctx.center_y, ctx.target_x, ctx.target_y ) -- Close targets: slow down. Far targets: speed up. local scale = math2.clamp(dist / 200, 0.3, 1.5) return { delta_x = ctx.delta_x * scale, delta_y = ctx.delta_y * scale } end
Example Per-Weapon PID Tuning

Automatically adjusts PID gains when the weapon preset changes.

local PID_PRESETS = { [1] = { kp = 0.8, kd = 0.10, max = 60 }, -- AR [2] = { kp = 0.5, kd = 0.05, max = 30 }, -- Sniper [3] = { kp = 1.0, kd = 0.12, max = 80 }, -- SMG } local lastWeapon = 0 function on_config_update() local w = config.get_current_weapon() if w ~= lastWeapon then lastWeapon = w local p = PID_PRESETS[w] if p then pid.set_kp("both", p.kp) pid.set_kd("both", p.kd) pid.set_max_output("both", p.max) print("PID switched for weapon " .. w) end end end
Example Head-Only Detection Filter

Locks detection to head-only (class 0) with a higher confidence threshold.

-- Filter to head class only with 65% min confidence detection.filter_class(0) detection.set_min_confidence(0.65) print("HEAD ONLY mode active") function on_config_update() -- Re-apply filter on every config refresh detection.filter_class(0) detection.set_min_confidence(0.65) end
Example Detection Counter & Logger

Counts total detections per class and logs stats periodically.

local classCounts = {} local lastReport = time() function on_frame(dets) for _, d in ipairs(dets) do classCounts[d.label] = (classCounts[d.label] or 0) + 1 end end function on_tick() local now = time() if now - lastReport > 10 then lastReport = now print("=== Detection Stats ===") for label, count in pairs(classCounts) do print(" " .. label .. ": " .. count) end end end
Example Full Script — Adaptive Aim & Recoil

A complete script combining per-weapon PID tuning, distance-based aim scaling, ADS-only triggerbot, recoil control, detection logging, and auto-start recoil on fire.

-- ═══════════════════════════════════════════════ -- AimSync Full Script — Adaptive Aim & Recoil -- ═══════════════════════════════════════════════ -- Per-weapon PID presets local PID_PRESETS = { [1] = { kp = 0.80, ki = 0.01, kd = 0.10, max = 60 }, -- AR [2] = { kp = 0.50, ki = 0.00, kd = 0.05, max = 30 }, -- Sniper [3] = { kp = 1.00, ki = 0.02, kd = 0.12, max = 80 }, -- SMG [4] = { kp = 0.90, ki = 0.01, kd = 0.08, max = 70 }, -- LMG } -- State local lastWeapon = 0 local totalAimMoves = 0 local lastStatTime = time() local firing = false -- ─── Initialization ─────────────────────────── log("Full script loaded") print("Weapon: " .. config.get_current_weapon()) print("Model: " .. model.get_name() .. " (" .. model.get_class_count() .. " classes)") print("Screen: " .. screen.width() .. "x" .. screen.height()) -- ─── Apply PID for current weapon ───────────── local function applyPID(w) local p = PID_PRESETS[w] if not p then return end pid.set_kp("both", p.kp) pid.set_ki("both", p.ki) pid.set_kd("both", p.kd) pid.set_max_output("both", p.max) pid.reset("both") print("PID → weapon " .. w) end applyPID(config.get_current_weapon()) -- ─── on_config_update: weapon switch detection ─ function on_config_update() local w = config.get_current_weapon() if w ~= lastWeapon then lastWeapon = w applyPID(w) end end -- ─── on_pre_aim: distance-based scaling ──────── function on_pre_aim(ctx) local dist = math2.distance( ctx.center_x, ctx.center_y, ctx.target_x, ctx.target_y ) -- Slow near crosshair, faster at range local scale = math2.clamp(dist / 200, 0.3, 1.5) -- Slight human jitter local jitter = 0.95 + math.random() * 0.1 return { delta_x = ctx.delta_x * scale * jitter, delta_y = ctx.delta_y * scale * jitter } end -- ─── on_post_aim: track total movements ──────── function on_post_aim(mx, my) totalAimMoves = totalAimMoves + 1 end -- ─── on_triggerbot: ADS-only firing ──────────── function on_triggerbot(inCrosshair) local ads = mouse.is_pressed(1) if inCrosshair and ads then return true end return false end -- ─── on_tick: recoil + periodic stats ────────── function on_tick() -- Auto-start recoil when left mouse held local lmb = mouse.is_pressed(0) if lmb and not firing then recoil.start() firing = true elseif not lmb and firing then recoil.stop() firing = false end -- Print stats every 15 seconds local now = time() if now - lastStatTime > 15 then lastStatTime = now print("[Stats] Aim moves: " .. totalAimMoves) end end -- ─── on_frame: log high-confidence detections ── function on_frame(dets) for _, d in ipairs(dets) do if d.confidence > 0.85 then log(string.format( "%s %.0f%% at (%d,%d)", d.label, d.confidence * 100, d.x, d.y )) end end end

Safety & Limits

LimitValueDetails
Instruction Limit1,000,000Maximum VM instructions per hook call. Prevents infinite loops from freezing AimSync.
Sleep Maximum5000 mssleep() is capped at 5 seconds. Values outside 1–5000 are ignored.
Script ReloadAutomaticLoading a new script resets all overrides (aim, detection, delta scale, target) to defaults.
Thread SafetyRecursive mutexAll Lua calls are guarded by a recursive mutex. Callbacks run on different threads (main loop, aim worker, config thread) but never concurrently.
Error HandlingProtected callsAll callbacks use lua_pcall. Errors are printed and logged — they never crash AimSync.
AimSync Lua API Wiki © 2026