Script Settings ​
Two ways to add user-configurable options to your script:
settings = { ... }declaration (recommended for most scripts): declarative table at script load time. Auto-renders inline under your script in the menu, auto-persists to a per-script JSON config, auto-restores on next launch.ui.*widget API (for advanced or dynamic UIs): imperative widget creation with custom tabs, buttons with callbacks, and runtime-mutable layouts. See UI.
Neither is deprecated. Use settings for simple scripts where users just need a few toggles and sliders. Use ui.* when you need dynamic widgets, custom tabs, or button callbacks.
settings declaration ​
name = "My Script"
id = hero_id.any
settings = {
{ key = "enabled", type = "bool", default = true, label = "Enabled" },
{ key = "speed", type = "float", default = 1.0, min = 0.1, max = 10.0, label = "Speed" },
{ key = "count", type = "int", default = 5, min = 1, max = 20, label = "Count" },
{ key = "mode", type = "combo", default = 0, label = "Mode",
options = { "Off", "Conservative", "Aggressive" } },
{ key = "hotkey", type = "keybind", default = 0, label = "Hotkey" },
{ key = "slot", type = "item_slot", default = 0, label = "Item Slot" },
{ key = "font", type = "font", default = "", label = "Draw Font" },
{ key = "tint", type = "color", default = {r=255, g=80, b=80, a=255}, label = "Tint" },
}Each entry is a table with these keys:
| Key | Required | Description |
|---|---|---|
key | yes | Config key for persistence. Must be unique within the script |
type | yes | One of: bool, int, float, combo, keybind, item_slot, font, color |
default | yes | Default value when the user hasn't set one |
label | yes | Display label in the menu |
min, max | for int/float | Slider bounds |
options | for combo | Array of strings shown in the dropdown |
depends_on | optional | Key of another setting that controls this one's visibility |
depends_value | optional | Value the controlling setting must have for this one to show |
Setting types ​
| Type | Backing type | Notes |
|---|---|---|
bool | boolean | Renders as a checkbox |
int | integer | Renders as a slider; needs min and max |
float | number | Same as int but for fractional values |
combo | integer | Dropdown index (0-based); needs options array |
keybind | integer | VK code; renders as a "click to bind" picker |
item_slot | integer | Slot 0-7; renders as an ability-slot picker |
font | string | Font name; renders as a font picker with system font search |
color | RGBA table | {r, g, b, a} with components 0-255; renders as an inline swatch that opens a full RGBA picker on click. default must be a four-key table |
Conditional visibility ​
Hide a setting unless another one has a specific value:
settings = {
{ key = "auto_dispel", type = "bool", default = false, label = "Auto Dispel" },
{ key = "dispel_threshold", type = "float", default = 2.0,
min = 0.5, max = 5.0, label = "Threshold (seconds)",
depends_on = "auto_dispel", depends_value = 1 },
}depends_value = 1 for booleans means "controlling setting must be true." For combo, it's the option index (0-based).
config namespace ​
Read and write your script's persisted setting values at runtime.
| Function | Returns | Description |
|---|---|---|
config.get_bool(key, default) | boolean | Read a bool setting |
config.get_int(key, default) | integer | Read an int, combo, keybind, or item_slot |
config.get_float(key, default) | number | Read a float setting |
config.get_string(key, default) | string | Read a font (or any other string-typed) setting |
config.get_color(key) | RGBA table | Read a color setting; returns {r, g, b, a} with components 0-255 |
config.set_bool(key, value) | - | Write a boolean. Auto-saves to disk |
config.set_int(key, value) | - | Write an integer. Auto-saves to disk |
config.set_float(key, value) | - | Write a float. Auto-saves to disk |
config.set_string(key, value) | - | Write a string. Auto-saves to disk |
config.set_color(key, {r,g,b,a}) | - | Write a color. Auto-saves to disk |
Values persist per-script in a JSON file. All setting types, bool, int, float, combo, keybind, item_slot, font, and color, save to disk the moment the user changes them in the menu or a script writes them via config.set_*. No manual save call required.
Reading settings ​
function on_tick()
if not config.get_bool("enabled", true) then return end
local speed = config.get_float("speed", 1.0)
local mode = config.get_int("mode", 0)
local font = config.get_string("font", "")
-- ...
endThe default argument is used when the key isn't in the config yet (e.g. first launch before the user touches the menu). Match the default in config.get_* to the default you declared in settings to avoid surprises.
Writing settings ​
Useful for scripts that need to mutate their own settings in response to events:
function on_tick()
if input.is_key_pressed(0x70) then -- F1
local was = config.get_bool("enabled", true)
config.set_bool("enabled", not was)
toast(not was and "ON" or "OFF")
end
endPer-script isolation: writing enabled in Script A doesn't touch Script B's enabled. Each script has its own JSON file.
Color picker ​
The color type renders as an inline color swatch in the menu. Clicking it opens a full RGBA picker, hue ring, saturation/value square, alpha slider, and direct hex/RGB number entry. The picked value persists like every other setting.
The default value is a table with four numeric keys, each 0-255:
settings = {
{ key = "alert_color", label = "Alert Color", type = "color",
default = {r = 255, g = 0, b = 0, a = 255} },
}Read the current value with config.get_color. Write a new one with config.set_color:
local c = config.get_color("alert_color")
-- c.r, c.g, c.b, c.a, all 0-255
config.set_color("alert_color", {r = 0, g = 255, b = 0, a = 255})The returned RGBA table plugs directly into the Draw namespace via draw.color(c.r, c.g, c.b, c.a). Here's a complete script that uses a color picker to draw 3D boxes around enemies:
-- Color Picker Test
-- Draws 3D boxes on enemies using color picker
name = "Color Picker Test"
description = "3D box ESP with color picker"
settings = {
{ key = "box_color", label = "Box Color", type = "color", default = {r=255, g=50, b=50, a=255} },
}
function on_tick()
local c = config.get_color("box_color")
local col = draw.color(c.r, c.g, c.b, c.a)
for _, p in ipairs(get_players()) do
if p:is_enemy() and p:is_alive() then
local pos = p:get_position()
local head = p:get_head_world()
local height = head.z - pos.z + 14
local width = 30
draw.box3d(vec3(pos.x, pos.y, pos.z + height * 0.5), width, width, height, col, 1.5)
end
end
endChanging the swatch in the menu while the script is running updates the box color on the next tick. No reload, no restart.
Top-level globals ​
The full set of script-level globals you can declare:
| Global | Type | Description |
|---|---|---|
name | string | Display name shown in the scripts list |
description | string | Optional one-line tagline shown under the script name in the list |
id | integer | Hero gating. Use hero_id.any for "runs on any hero" |
settings | table | Setting declarations as above |
needs_all_particles | boolean | Set to true if you need ability/tower/environment particle events. Default false |
Plus the event callbacks (on_tick, on_kill, on_modifier_added, on_modifier_removed, on_ability_cast, on_item_used, on_particle_create, on_particle_destroy). See Events.