Commands
Needs the internal running and needs_internal = true in script_info. Without it cmd.clear, cmd.hold, cmd.press, cmd.cast and cmd.use_item return false.
cmd.clear(buttons [, ms]) -> bool take these buttons out of every command
cmd.hold(buttons [, ms]) -> bool hold these buttons
cmd.release(buttons) -> integer end your clear or hold early
cmd.press(buttons) -> bool one press
cmd.cast(slot) -> bool cast ability 1-4
cmd.use_item(slot) -> bool use item 1-4
cmd.mask() -> table | nil
cmd.reset() drop everything this script asked for
cmd.on_change(fn) fn(c) once per new command
cmd.diag() -> table | nilbuttons is a button name like "attack", or a list of them like { "attack", "attack2" }. The names are the same ones input.* uses: attack, attack2, jump, duck, reload, dash, ability1-ability4, item1-item4, melee, parry, and the rest on the Input page. An unknown name raises an error.
What it is for
input.* presses keys for you, but it can never take one away. If you are holding the left mouse button, nothing in input.* can stop that button from reaching the game. cmd.* can. It changes the command the game sends, after your real keys are in it. So a script can say "no attack right now" while you keep holding the button.
-- cleanse the moment a debuff lands, even while you are holding fire
local function should_cleanse(m)
return false -- your rule: check m.name against the debuffs you care about
end
function on_modifier_added(p, m)
if p:is_local() and should_cleanse(m) then
cmd.clear("attack", 150) -- no shooting for 150 ms
cmd.use_item(2) -- your cleanse item in slot 2
end
endThe modifier names to check come from your own logs. Debugging modifiers shows how to list them.
Every change is timed
A clear or a hold lasts ms milliseconds. Leave ms out and it lasts 100 ms. The longest is 5 seconds.
To keep one going, call it again. Calling it again makes it last longer, never shorter. For "while something is true", call it every tick while it is true:
function on_tick()
if i_am_channelling() then cmd.clear("attack") end -- asked again every tick, so it never runs out
endA clear can never get stuck. If your script stops asking, you get the button back when the time runs out, 100 ms by default. If it is turned off or errors, you get it back straight away. A short hitch in TSUKI does not let the button through early.
If TSUKI closes or crashes, your clears and holds stop within a quarter of a second. The game never keeps a button taken away after TSUKI is gone.
cmd.release(buttons) ends your clear and hold of those buttons straight away. cmd.reset() ends everything your script asked for.
Pressing and casting
cmd.press(buttons) presses once. cmd.cast(slot) casts ability 1 to 4 and cmd.use_item(slot) uses item 1 to 4.
These go through the game command, not your keyboard. They work with any keybinds and while a text box has focus, and they do not wait for Windows to deliver a keypress.
Timing
A change reaches the game a few milliseconds after you ask. It takes a little longer if the overlay's Refresh Rate is set low. It is not tied to one exact command. Use cmd.* for "stop shooting while I cast", not for "change exactly command 1234". It works the same at any frame rate.
If two scripts disagree
A clear beats a hold and a press. If one script clears attack and another holds it, attack is cleared.
cmd.mask() shows what is in force: { clear, hold, intents, mine = { clear, hold } }. clear and hold are button bit masks for every script together. mine has the same masks for your script only. Use input.bit(name) to test a bit:
local m = cmd.mask()
if m and (m.clear & input.bit("attack")) ~= 0 then
-- something is holding attack off right now
endcmd.on_change(fn)
Calls fn(c) once for each new game command, about 64 times a second. c has:
| Field | What it is |
|---|---|
cmd | The new command number |
prev | The one before |
skipped | Commands that went by between two calls. They are reported, not replayed |
held, pressed, released | Button bit masks, the same as input.buttons() |
cmd.on_change(nil) stops it.
Returns false when
- The internal is not running.
needs_internal = trueis missing fromscript_info.- 64 clears and holds are already live across every script.
A press is also dropped if it cannot reach the game within half a second, for example during a loading screen. It is never delivered late.
When a script is turned off
Everything a script asked for is removed when it is turned off or errors: its clears, holds, on_change, and anything else it owns. See on_disable.
Checking it worked
cmd.diag() shows what was applied, not what was asked for. The main fields:
| Field | What it is |
|---|---|
cmds_seen | Commands that went out while a clear, hold or press was live |
cmds_cleared | Commands where a cleared button was really there and was taken out |
presses_applied | Presses written into a command |
presses_dropped | Presses that were too late to send |
last_press_cmd | The command the last press went out on |
press_words | The last press as it went out: { held, pressed, released }, as button bit masks |
Clearing a button nobody is pressing leaves cmds_cleared at 0.
To check that a press went out as a full tap:
local d, b = cmd.diag(), input.bit("ability1")
if d and (d.press_words[2] & b) ~= 0 and (d.press_words[3] & b) ~= 0 then
-- pressed and released on the same command
endIf you were already holding the button, the press keeps it held, so pressed is set and released is not.
It costs nothing while no script is using it.