Globals ​
Top-level functions and small namespaces (storage) callable from any script. These don't need a prefix beyond the namespace name.
Player Access ​
| Function | Returns | Description |
|---|---|---|
local_player() | player | The local player object |
get_players() | table | All enemy players. Teammates are always available via get_teammates() |
get_all_players() | table | All players including local |
get_teammates() | table | Teammate players only |
local me = local_player()
for _, p in ipairs(get_players()) do
if p:is_enemy() and p:is_alive() then
-- ...
end
endTime ​
| Function | Returns | Description |
|---|---|---|
clock() | number | High-resolution time in seconds. Use for deltatime and debouncing |
game_time() | number | In-game simulation time |
clock() is wall-clock time monotonic seconds since the engine started. game_time() advances with the match clock and freezes when the game is paused.
Output ​
| Function | Returns | Description |
|---|---|---|
print(...) | - | Output to app console and Windows console. Auto-prefixed with [Lua:script_name] |
toast(text, [duration], [style]) | - | Centered HUD toast. Optional per-call styling. See below |
notify(text, [duration], [color]) | - | Persistent notification. Default duration 3.0, color white |
play_sound(filename) | - | Play a .wav from %APPDATA%/TsukiProject/Deadlock/sounds/ |
toast("ready")
notify("warning", 5.0)
play_sound("alert.wav")toast(text, [duration], [style]) ​
A centered HUD toast notification.
duration, seconds to display. Pass0to use the global default from menu settings.style, optional table with per-call overrides. Any key omitted falls back to the global defaults configured in the menu:
| Key | Type | Notes |
|---|---|---|
bg | {r, g, b, a} | Background fill |
text | {r, g, b, a} | Text color |
outline | {r, g, b, a} | Outline / drop-shadow color |
scale | number | Size multiplier (1.0 = default) |
Toasts deduplicate by text only. If the same string is currently showing or already queued, the call is dropped on the floor, even if you passed a different style table. This means it's safe to fire toast("X") inside on_tick without flooding the screen; a tick-rate spam of the same message renders the original once.
toast("Hit", 2, {bg = draw.color(255,0,0)}) -- shows
toast("Hit", 2, {bg = draw.color(0,255,0)}) -- DEDUPED (same text)
toast("Hit!", 2) -- shows (different text)Different toasts with different text aren't deduplicated against each other, only repeats of the same string are suppressed, so a stream of "Hit X", "Hit Y", "Hit Z" all appear. The queue holds at most 5 pending toasts at a time.
toast("Target locked", 2, {
bg = {r = 40, g = 15, b = 50, a = 220},
text = {r = 200, g = 140, b = 255},
scale = 1.2
})Here's a complete demo script that shows the common style presets, wire each button to a different look and click through them to see how the parameters interact:
-- Toast Style Demo
-- Click buttons to see different toast styles
name = "Toast Style Demo"
description = "Showcases custom toast styling"
ui.new_tab("toast_demo", "Toast Demo")
ui.button("toast_demo", "styles", "Default Toast", function()
toast("Default style, uses your global settings", 3)
end)
ui.button("toast_demo", "styles", "Success (Green)", function()
toast("Parry successful!", 3, {
bg = {r=20, g=60, b=20, a=220},
text = {r=100, g=255, b=100},
outline = {r=80, g=200, b=80, a=120},
})
end)
ui.button("toast_demo", "styles", "Danger (Red)", function()
toast("LOW HP, retreat!", 4, {
bg = {r=80, g=10, b=10, a=230},
text = {r=255, g=80, b=80},
outline = {r=255, g=60, b=60, a=150},
scale = 1.3,
})
end)
ui.button("toast_demo", "styles", "Info (Blue)", function()
toast("Cooldown ready", 2, {
bg = {r=15, g=25, b=60, a=220},
text = {r=120, g=180, b=255},
outline = {r=80, g=140, b=220, a=100},
})
end)
ui.button("toast_demo", "styles", "Big Gold", function()
toast("ULTRA KILL!", 5, {
bg = {r=40, g=30, b=5, a=240},
text = {r=255, g=215, b=0},
outline = {r=255, g=180, b=0, a=160},
scale = 1.8,
})
end)Input shortcuts ​
| Function | Returns | Description |
|---|---|---|
slot_to_key(slot) | integer | VK code bound to the given ability/item slot. See Game Keybinds |
left_click() | - | Simulate a left mouse click |
right_click() | - | Simulate a right mouse click |
For finer-grained input control (key down, key up, mouse movement), see the Input namespace.
Game state ​
is_in_menu() ​
Returns true when the game cursor is visible, meaning the player is in a menu, shop, scoreboard, or settings screen.
if is_in_menu() then return endAll input actions (key presses, mouse movement) from Lua scripts are automatically blocked while in menu. You don't need to check is_in_menu() for safety, it's handled internally. Use this to skip expensive logic like targeting when the player isn't actively playing.
is_game_focused() ​
Returns true when the game window is in the foreground (active and focused).
if not is_game_focused() then return endUse this to skip logic when the player has alt-tabbed or is in another window. Unlike is_in_menu(), this detects when the game itself isn't the active window.
Tsuki Config ​
Read and write the cheat's own settings (values your user has configured in the menu like ESP toggles or aimbot FOV). Use this when you want a script to react to or override existing menu settings.
| Function | Returns | Description |
|---|---|---|
tsuki.get_bool(key, default) | boolean | Read a boolean setting |
tsuki.get_int(key, default) | integer | Read an integer setting |
tsuki.get_float(key, default) | number | Read a float setting |
tsuki.set_bool(key, value) | - | Write a boolean setting |
tsuki.set_int(key, value) | - | Write an integer setting |
tsuki.set_float(key, value) | - | Write a float setting |
-- React to the user's configured aimbot FOV
local fov = tsuki.get_float("aimbot_fov", 3.0)
local target = targeting.find_closest_by_fov(fov, 30.0)
-- Temporarily override a setting and restore it
local prev = tsuki.get_bool("show_teammate_esp", false)
tsuki.set_bool("show_teammate_esp", false)
-- ... do something ...
tsuki.set_bool("show_teammate_esp", prev)Setting keys match the IDs the cheat uses internally. The tsuki.* namespace is mainly useful when you know specific keys; for new script-defined settings, use the UI namespace instead. That gives you a labeled widget AND state without needing to know any internal keys.
Storage ​
Persistent key-value storage scoped per script. Values survive script reloads, game restarts, and PC restarts. Each script gets its own isolated storage backed by a JSON file in the scripts directory, keys from script A are invisible to script B.
| Function | Returns | Description |
|---|---|---|
storage.set(key, value) | - | Save a value under a key. Passing nil as the value deletes the key. |
storage.get(key) | any | nil | Load a saved value, or nil if not set |
storage.keys() | table | List of saved keys for this script |
Values can be strings, numbers (integer or float), booleans, or nil. Tables aren't auto-serialized, encode/decode manually with json.encode / json.decode if you need structured data. Writes flush to disk on change.
-- Track cumulative kills across game sessions
function on_kill(player)
if not player:is_enemy() then return end
local total = (storage.get("total_kills") or 0) + 1
storage.set("total_kills", total)
print("Total kills: " .. total)
end
-- Store a structured value as JSON
storage.set("loadout", json.encode({ slot1 = "burst_fire", slot2 = "trooper_bounty" }))
local loadout = json.decode(storage.get("loadout") or "{}")
-- Delete a key
storage.set("old_data", nil)