Skip to content

Internal API Reference

Most of the Lua API is served by TSUKI itself and works in every script. The functions in this section are served by the internal, an optional component that has to be running. When it is not running they return nil and your script keeps going.

To use them, add needs_internal = true to your script_info:

lua
script_info = {
    name           = "my_script",
    needs_internal = true,
}

Everything else in the API keeps working as before. The flag only adds.

What the flag gates

Without needs_internal = true these return nil and write one line to C:\TSUKI\Deadlock\logs\tsuki.log naming the script and the function (once per function, not once per call):

  • p:get_stats()
  • p:get_ability_value(slot, name)
  • p:get_hit_events([since_seq])
  • p:get_hit_stats()
  • p:get_property(name)
  • entities.row:get(name)
  • trace.line(from, to [, opts])
  • trace.get(id)
  • hud.class_count(name)

The script still loads, shows in the menu and ticks. Nothing errors. The log line does not reach the in-app console, so a missing flag looks like a function that returns nil forever.

aim.* needs the internal running but does not check the flag. Declare it anyway if you use them.

Is the internal running

FunctionReturns
internal.is_loaded()true when the internal is present
internal.is_alive()true when it is present and responding (its heartbeat moved in the last second)
internal.version()Build number, 0 when nothing is loaded

Any script can call these. Gate on is_alive before trusting numbers; is_loaded stays true for a component that is present but stuck.

lua
function on_tick()
    local me = local_player()
    if not me or not me:is_alive() or not internal.is_loaded() then return end
    -- ...
end

Or fall back instead of stopping:

lua
local dmg = fallback
if internal.is_loaded() then
    local st = me:get_stats()
    if st and st.bullet_damage and st.bullet_damage > 0 then dmg = st.bullet_damage end
end

When a call returns nil

Every feed returns nil rather than a placeholder. Never 0, never a table of zeros. Check in this order:

  1. internal.is_alive() is false.
  2. needs_internal = true is missing from script_info. Look for the line in tsuki.log.
  3. Nothing asked recently. The stat feed only runs while some script called p:get_stats() in the last 2 seconds. The ability value, property and trace feeds only work on names you have asked for.
  4. A cap is full: 24 ability value pairs, 32 property pairs, 32 traces, shared by every loaded script.
  5. It is the first call for a new request. The first call registers it and returns nil; the value lands on a later tick.

aim.silent and aim.shoot return false instead of nil when the internal is absent.

Refresh rates

FeedRefresh
Stats100 ms
Ability values250 ms
Entity properties250 ms
Traces50 ms
Hit eventsOn each hit

Checking a name from a script

tsuki.api() returns every registered name with its host (external or internal) and needs_internal flag. tsuki.api_info(name) returns one entry or nil. The name must match exactly, prefix included: "p:get_stats", not "get_stats".

lua
local i = tsuki.api_info("p:get_stats")
-- i.host = "internal", i.needs_internal = true

Pages

PageCovers
Statsp:get_stats(): resolved resists, shields, barrier, and your own weapon numbers
Ability Valuesp:get_ability_value(slot, name): the resolved number the tooltip shows
Hit Eventsp:get_hit_events() and p:get_hit_stats(): per hit damage events and a running tally
Entity Propertiesp:get_property(name) and row:get(name): read a game field by name
Tracestrace.line() and trace.get(): what a line hits
Aimaim.silent, aim.shoot, aim.can_reach, aim.get_solution, aim.diag
HUDhud.class_count(name): how many interface panels carry a class, for reading the game's own cast indicator

Everything else is in the API Reference.