Skip to content

Aim

Needs the internal running. Declare needs_internal = true in script_info like the rest of this section. aim.can_reach also works without the internal.

A call stages a request and returns immediately; nothing fires inside the call. false is a normal answer: the built in aimbot owns the shot, the game is unfocused, or another script holds the window. aim.diag().last_reason says which, read immediately after the call.

aim.shoot(target, [opts])

aim.shoot(player_or_vec3 [, {bone = "head", button = "attack", backtrack = true,
                             silent = true, hold_ms = 0}]) -> boolean

Stages a corrected shot at a player or a world point and presses the button. Returns true when the press was queued.

OptionDefaultMeaning
bone"head"Bone to aim at
button"attack"Any button name: attack, ability1 to ability4, item1 to item4, melee, parry and the rest. An unknown name raises an error
backtracktrueAllow the shot to be judged against a recent position of the target. Only works when the user allows it; internal.backtrack_diag().allowed says whether
silenttruefalse keeps your own aim and only presses the button
hold_ms0Hold the button this long instead of tapping

With a player, the point is the bone led by the button's projectile speed: abilityN uses that ability's speed, attack uses the gun's. Hitscan is not led.

lua
local function fire(target, opts)
    local ok = aim.shoot(target, opts)
    if not ok then
        local d = aim.diag()
        last_reason = d and d.last_reason or "?"
    end
    return ok
end
lua
aim.shoot(target, { bone = "head",  button = "attack",          backtrack = true })
aim.shoot(target, { bone = "head",  button = "attack",          backtrack = true, silent = false })
aim.shoot(target, { bone = "chest", button = "ability" .. slot, backtrack = true })
aim.shoot(target, { bone = "head",  button = "attack", hold_ms = 40 })

aim.silent(pitch, yaw, [opts])

aim.silent(pitch, yaw [, {cmds = 1, always = false, distance = 1024,
                          target = player, bone = "head", button = "attack"}]) -> boolean

Arms an angle for the next shot without moving the crosshair and without pressing anything. Your own trigger, or input.tap("attack"), fires it. pitch and yaw use the same convention as camera.get_view_angles().

OptionDefaultMeaning
cmds1How many game ticks the angle stays armed, 1 to 16
alwaysfalseKeep the angle armed for the whole window even if nothing fires
distance1024Distance along the ray to the aimed point, 16 to 8192
targetnoneA player. The point becomes that player's led bone and distance is ignored
bone"head"Bone used with target
button"attack"Which projectile speed leads the point

Pass target = or the target's real distance. The default distance misses because the camera ray and the shot ray diverge with distance. With cmds = 1 the angle covers one tick, so call it again every tick while the target is in the cone.

Why a call returns false

  1. The internal is not running.
  2. TSUKI is shutting down.
  3. The built in aimbot owns the shot.
  4. The game window is not focused.
  5. The game cursor is visible (menu, shop, chat).
  6. Another script owns the silent window.
  7. The target is not alive.

The aimbot wins while it holds a lock, and the check is repeated at the last moment, so aim.shoot can return false even after aim.get_solution() showed owns_shot clear. Turn the aimbot off when testing a script.

One script at a time owns the silent window, for 375 ms from its last request. A script that unloads or errors drops its ownership and pending presses.

Timing

  • aim.shoot releases the press once the correction has been applied. If that takes more than 120 ms the press is dropped and last_reason reads press dropped: staged shot never published.
  • A press is also dropped when the button is unbound, the game lost focus, or the game cursor appeared.
  • A gun shot (button = "attack", no hold_ms) is corrected for 2 game ticks. Abilities, items, melee, and any call with hold_ms > 0 are corrected for the whole 375 ms window. aim.silent uses cmds as its tick budget.
  • When the budget runs out the correction stops. The shot still fires, along your own aim.
  • Tapping faster than the weapon's refire finds the gun on cooldown.

aim.can_reach(target, [bone], [detail])

aim.can_reach(player [, bone] [, detail]) -> {ok, why, leash [, lat, up, r]} | nil
aim.can_reach(vec3 [, _] [, detail])
aim.can_reach({x =, y =, z =} [, _] [, detail])
aim.can_reach(x, y, z [, detail])

Returns whether a silent shot at that point can be made from where you stand. Cheap; call it before staging. Works without the internal.

Bounds, in world units: lateral within 100, vertical within 80, radial under 170, and the game's own 150 unit leash from your pawn.

why is one of ok, no_camera, no_pawn, dead, target_dead, behind, lateral, up, radial, leash. A trailing true adds lat, up and r, the three distances. nil only for a player whose snapshot is missing; a dead target returns ok = false, why = "target_dead".

Write aim.can_reach(p, "head", true). A boolean where the bone goes raises an error.

lua
if not internal.is_loaded() then line("internal not loaded: nothing here can fire", WARN) end
local sol = aim.get_solution()
if sol and sol.owns_shot then line("the aimbot owns the shot: turn the aimbot off for these tests", WARN) end
local reach = target and aim.can_reach(target, "head") or nil
if reach and not reach.ok then line("cannot reach: " .. reach.why, WARN) end

aim.get_solution()

Returns what the built in aimbot decided this tick, or nil when the internal is not running.

Booleans: valid, key_held, target_pending, owns_shot, bt_allowed. Numbers: target_index, requested_tick, bt_depth, fov. Strings: mode (the configured aim mode) and source (script, aimbot or none). target is a player object when the index resolves. When valid is true the table also carries x, y, z, yaw, pitch and bone.

Poll owns_shot before calling aim.shoot.

aim.diag()

Counters for the script aim path. Never nil.

GroupKeys
Requestssilent, shots, presses, dropped, pending_presses
Refusalsrefused_aimbot, refused_input, refused_owner, refused_other, last_reason
Last shotlast_shot_req, last_shot_target, last_shot_bt_allowed
Ownershipowner (script index holding the window, -1 for none)
Reachreach_calls, reach_ok, reach_last_leash

last_reason is only meaningful immediately after a false return and can be the empty string.

Example

Arm the angle every tick while a target is in the cone, and let the player's own trigger fire:

lua
local target = best_in_fov(fov_deg, range_m, bone)
if not target then return end
local va = camera.get_view_angles()
local armed = aim.silent(va.x, va.y, { cmds = 1, target = target, bone = bone, button = "attack" })
if test_mode and armed and t - last_tap >= 0.7 then
    local ammo = me:get_ammo()
    if ammo and ammo < 2 then input.tap("reload"); last_tap = t + 1.5; return end
    if input.tap("attack") then taps = taps + 1 end
end

The full script is on Silent Aim on Your Shots. See also Input for the button names, Camera for camera.get_view_angles, and Targeting and Prediction for aim math that needs no internal.