Getting Started
TSUKI includes a Lua 5.4 scripting environment. Scripts can read player data, control input, draw on screen, query the menu UI, and read game memory directly.
Installing a script
Scripts live in:
C:\TSUKI\Deadlock\scripts\Paste that path into the Run dialog (Win + R) or your File Explorer address bar to open the folder, then drop your .lua file inside.
Open the TSUKI menu, click Scripts in the sidebar, then press the Reload button at the top of the page if your new file doesn't appear yet.
A script's config lives inside C:\TSUKI\Deadlock\scripts\config\. Each script gets its own .json file.
Your first script
local greeted = false
function on_tick()
if local_player():is_alive() and not greeted then
toast("Hello from Lua!", 3)
greeted = true
end
endSave as hello.lua and enable it in the Scripts page, and you should see a single HUD toast.
Two APIs
Most of the API is served by TSUKI itself and works in every script.
A smaller set is served by the internal, an optional component that has to be running: resolved combat stats, resolved ability values, per hit damage events, line traces, entity fields by name, and scripted aim.
To use it, add one line to script_info:
script_info = {
name = "my script",
needs_internal = true,
}Everything else keeps working; the flag only adds. Without it the internal calls return nil and one line is written to C:\TSUKI\Deadlock\logs\tsuki.log.
internal.is_loaded() and internal.is_alive() tell you whether the internal is running.
Details: Internal API Reference.
Quick Example
Here's a Haze script that locks onto an enemy and throws a Sleep Dagger (ability 1) whenever mouse5 is pressed.
-- Haze Auto Dagger
-- Hold mouse5 -> snap to closest enemy -> fire Sleep Dagger
name = "Haze Auto Dagger"
id = hero_id.haze
settings = {
{ key = "fov", label = "FOV (degrees)", type = "float", default = 15.0, min = 1.0, max = 30.0 },
{ key = "max_range", label = "Max Range (m)", type = "float", default = 30.0, min = 5.0, max = 100.0 },
{ key = "fire_angle", label = "Fire Threshold (deg)", type = "float", default = 1.5, min = 0.3, max = 5.0 },
}
function on_tick()
local lp = local_player()
if not lp or not lp:is_alive() then return end
if not input.is_key_held(VK.XBUTTON2) then return end
if not lp:is_ability_ready(slot.ability1) then return end
local target = targeting.find_closest_by_fov(
config.get_float("fov"),
config.get_float("max_range")
)
if not target or not target:is_targetable() then return end
snap_to_target(target, { bone = bone.chest })
local angle = targeting.get_fov(target, bone.chest)
if angle and angle < config.get_float("fire_angle") then
press_ability(slot.ability1)
toast(string.format("Dagger → %s", target:hero_name() or "?"), 2)
end
endon_tick() runs ~250 times per second. It's called every ~4ms by default, the rate at which TSUKI reads memory. You can change it under General → Overlay → Reader Rate. Most features run on the same tick clock, so 250Hz is a sane default for most things.
Putting id = hero_id.haze at the top means this script only runs when you're on Haze.
A fuller version lives in Haze Auto Dagger. It uses fire_and_hold to hold the aim lock through Haze's throw windup so the dagger doesn't miss if the snap releases too early.
Where to go next
- Script Structure - script lifecycle, flags and event callbacks
- Game Keybinds - how scripts reach your real in-game keys
- API Reference - every namespace every script can use
- Internal API Reference - the feeds behind
needs_internal = true - Player - the largest reference page; covers everything on a player
- Examples - working scripts to learn from