Modules & Settings

Creating a module

local module = ui.category("visuals"):module("draw-square", "My ESP")
MethodWhat it does
ui.category(name)picks a GUI category: combat, movement, visuals, player, misc, scripts
category:module(icon, title[, description])registers a new module and returns it; description is readable via modules
module:callback(name, fn)lifecycle hooks: "enable", "disable"
module:event(name, fn)subscribes to a game event (list)
module:toggle()flips the module on/off
module:enabled()returns true while the module is enabled
module:set_enabled(bool)enables or disables the module
module.namethe module's name

One callback per event: a repeated module:event("tick", ...) replaces the previous one.

Icon names autocomplete in the editor — the full set lives in the generated library/icons.lua stub (see autocomplete).

Settings

Settings are created with module methods, appear in the GUI automatically and are saved to the config. The first argument is the name (also the GUI label).

local b = module:boolean("Flag", true)
local n = module:number("Speed", 1.0, 0.1, 10.0, 0.1, "x")
local r = module:range("Bounds", 20, 80, 0, 100, 1, "%")
local s = module:string("Message", "hello")
local k = module:key("Boost", "R")
local c = module:color("Color", 0xFF4FF2A6)
local sel = module:selection("Mode", nil, { "A", "B", "C" })
local multi = module:multi_selection("Targets", { "Players" }, { "Players", "Mobs" })
SignatureNotes
boolean(name, default)on/off switch
number(name, default, min, max[, step[, unit]])a slider; step defaults to 1, unit is a label like "ms"
range(name, default_min, default_max, min, max[, step[, unit]])two-handle slider; the value is a {min, max} table
string(name, default)text field
key(name[, default])key bind (like Item Helper); default is a key name or a table of up to 3 names
color(name, argb[, alpha])color picker, 0xAARRGGBB; alpha = false hides the alpha slider
selection(name, default, options)pick one option; default = nil means the first one
multi_selection(name, defaults, options[, allow_empty])pick several options; defaults = nil means the first one; the value is an array of strings

Working with values

n:get()          -- current value
n:set(5)         -- set (numbers are clamped to [min, max])
n:reset()        -- back to default
n.value          -- sugar for get/set
sel:set("B")     -- selection: by option name
r:get().min      -- range returns {min=, max=}
r:set({ min = 10, max = 90 })

Colors come back as unsigned numbers, so comparing against 0xAARRGGBB literals works directly.

Key binds

local k = module:key("Boost", "R")          -- or { "LCtrl", "R" }
module:event("tick", function()
    if k:pressed() then
        -- held right now (always false while a screen is open)
    end
end)
k:get()                  -- bound key names, e.g. { "R" }
k:set({ "LCtrl", "R" })  -- rebind from code

Key names match the GUI labels: letters/digits ("R"), "Space", "LShift", "LCtrl", "LAlt", "Enter", "Tab", "F1""F25", mouse buttons "MMB", "M4", "M5", etc. The bind is editable in the module's GUI panel like any other setting.

Other modules — the modules global

The modules global reads and controls every registered module — built-in ones included, not just those created by scripts.

modules.list()      -- all module names
modules.active()    -- names of the currently enabled modules
modules.binds()     -- all binds: { { module = "Flight", keys = { "R" }, type = "toggle" }, ... }

local flight = modules.get("Flight")    -- case-insensitive; nil when there is no such module
flight:enabled()                        -- true/false
flight:set_enabled(true)
flight:toggle()
flight:binds()                          -- { { keys = { "R" }, type = "toggle" }, ... }

flight.name, .title, .description and .category describe the module. Bind type is "toggle" or "hold"; key names match the GUI labels (see key binds).

Reading and overriding settings

ref:settings() lists the setting names in GUI order; ref:setting(name) (also case-insensitive) returns a handle with the usual :get() / :set(v) / :reset() and the .value sugar. Its type field says which value shape applies — the same shapes as the setting builders above:

typevalue
booleanboolean
numbernumber, clamped to the setting's range
range{ min = , max = } table
stringstring
keyarray of key names; also has :pressed()
color0xAARRGGBB number
selectionoption name
multi_selectionarray of option names
orderpermutation of the current key array
local speed = modules.get("Speed")
for _, name in ipairs(speed:settings()) do
    aesthetic.log(name .. " = " .. tostring(speed:setting(name):get()))
end
speed:setting("Mode"):set("Strafe")     -- unknown options/keys raise an error

Overrides go through the same path as the GUI: the module reacts immediately and the new value persists to the config.

Persistence

Setting values and the enabled state survive game restarts and script hot-reloads. They are keyed by the module and setting names — renaming loses the stored values.