Skip to content

Script Structure

Required Globals

Every script must define these globals:

lua
name = "MyHero"              -- display name (string)
id = hero_id.abrams          -- which hero this script runs for

function is_enabled()
    return true              -- return true when the script should be active
end

function on_tick()
    -- your logic here
end

Settings Table

Define a settings table to expose configurable options in the UI:

lua
settings = {
    { key = "enabled",    type = "bool",      default = false,       label = "Enabled" },
    { key = "fov",        type = "float",     default = 5.0,         label = "Max FOV",  min = 1.0, max = 15.0 },
    { key = "delay",      type = "int",       default = 100,         label = "Delay ms", min = 0,   max = 1000 },
    { key = "hotkey",     type = "keybind",   default = VK.XBUTTON2, label = "Hotkey" },
    { key = "mode",       type = "combo",     default = 0,           label = "Mode", options = { "Hold Key", "Always On" } },
    { key = "slot",       type = "item_slot", default = 0,           label = "Item Slot" },

    -- Layout helpers
    { key = "sep1",       type = "separator" },
    { key = "info",       type = "label",     label = "Hold shift to activate", color = { 1, 0.85, 0.3, 1 } },
    { key = "sl1",        type = "sameline" },
}

TIP

settings defines the UI layout at load time. Use config (below) to read/write values at runtime. They are separate — settings is the definition, config is the API.

Entry Fields

FieldTypeDescription
keystringConfig key (required)
typestring"bool", "int", "float", "keybind", "combo", "item_slot", "separator", "label", or "sameline" (defaults to "bool")
defaultanyDefault value
labelstringDisplay name in UI (defaults to key)
min, maxnumberRange for int/float sliders
optionstableString list for "combo" type
colortableText color for "label" type as { r, g, b, a } (0-1 floats, defaults to white)
depends_onstring | string[]Key of another config entry, or a list of keys for multi-parent. The entry is visible only when every named dependency matches its depends_value and is itself visible (transitive).
depends_valueint | int[]Value(s) the parent(s) must equal, parallel to depends_on. For booleans, 1 = true, 0 = false. Defaults to 1 for each parent. A scalar broadcasts to all parents.

Entries with depends_on are visually indented under their parent automatically — one indent level per dependency-chain depth. No extra field is needed.

Config API

Read and write config values at runtime:

lua
config.get_bool("enabled")          -- returns bool
config.get_int("delay")             -- returns int
config.get_float("fov")             -- returns float
config.set_bool("enabled", false)   -- write back
config.set_int("delay", 200)
config.set_float("fov", 3.0)

Config is persisted per-script as JSON in the scripts directory.

Layout Types

Three types exist purely for UI layout and don't store any config values:

TypeDescription
"separator"Horizontal line with spacing above and below
"label"Static text. Use label for the text and color for an RGBA color table
"sameline"Places the next widget on the same line as the previous one
lua
settings = {
    { key = "enabled", type = "bool", label = "Enabled" },
    { key = "s1",      type = "separator" },
    { key = "warn",    type = "label", label = "Experimental feature!", color = { 1, 0.4, 0.4, 1 } },
    { key = "sl1",     type = "sameline" },
    { key = "debug",   type = "bool", label = "Debug" },
}

TIP

Layout types still require a unique key but the key is not stored in config.

Console Color Codes

The script console supports Minecraft-style color codes using § followed by a hex digit (0-f) or r to reset. Multiple colors can be used in a single print() call.

lua
print("§aHealth OK §r| §cDamage: §e42")
print("§6Gold: §f1500 §r| §9Mana: §b350")
CodeColorCodeColor
§0Black§8Dark Gray
§1Dark Blue§9Blue
§2Dark Green§aGreen
§3Dark Aqua§bAqua
§4Dark Red§cRed
§5Dark Purple§dLight Purple
§6Gold§eYellow
§7Gray§fWhite
§rReset

Lines without color codes use the default auto-detection (red for errors, yellow for warnings, gray for engine messages).

Keybind Names

keybinds.get(name) returns the user's live in-game virtual-key for an action, looked up by its raw Deadlock action name. The named helpers (keybinds.reload_key(), keybinds.ability1_key(), …) are shortcuts for the most common ones.

lua
local parry = keybinds.get("HeldItem")
local dash  = keybinds.get("Roll")
local ab1   = keybinds.get("Ability1")
local melee = keybinds.get("AbilityMelee")

Pre-seeded defaults

These are loaded at startup before the game's keybind file is read, so they always resolve even if Steam userdata is unavailable:

NameIn-game actionDefault key
ReloadReloadR
HeldItemParry / Heavy MeleeF
RollDashShift
MantleJumpSpace
Ability1Ability slot 11
Ability2Ability slot 22
Ability3Ability slot 33
Ability4Ability slot 44
Item1Item slot 1Z
Item2Item slot 2X
Item3Item slot 3C
Item4Item slot 4V

Other known action names

These are read from citadelkeys_personal.lst and are available once keybinds load from Steam. Names come straight from the game's keybind file.

NameIn-game action
AttackPrimary fire
Attack2Secondary fire / Zoom
AbilityMeleeQuick melee
CrouchCrouch
WalkSprint / Walk toggle
MoveForwardMove forward
MoveBackMove backward
MoveLeftStrafe left
MoveRightStrafe right
PingPing
PingWheelPing wheel
VoiceChatPush to talk
TextChatAll chat
TeamChatTeam chat
ScoreboardScoreboard
ShowMapFull map
ShopOpen shop
InteractUse / Interact
InspectHeroInspect hero
RecallRecall to base

TIP

This is not an exhaustive list. Any action present in your citadelkeys_personal.lst works — the file lives at Steam/userdata/<id>/1422450/remote/cfg/citadelkeys_personal.lst. Keybinds are refreshed from the game every 30 seconds while the cheat is running. keybinds.get returns 0 for an unbound or unknown name.