Skip to content

Silent Aim on Your Shots ​

While an enemy head is within fov_deg of your crosshair and visible, every shot you fire is corrected onto it. The script only arms the angle, and you fire with your own trigger. With test_mode on, it also taps attack every 700 ms so a run can count its own hits.

What this shows ​

  • cmds = 1 is raised to 2. The aim point is fixed when you call, so aim.silent has to be called again every tick the target stays in the cone.
  • Pass target =. With a target, the aim point is that player's led bone. With only an angle, the aim point is distance units down the camera ray, and the default distance misses.
  • false means refused. This happens when the aimbot owns the shot, the game is unfocused, the cursor is up, or another script holds the window. aim.diag().last_reason tells you which one.
  • Hits come from p:get_hit_events. The sequence cursor keeps an event from being counted twice.

Script ​

lua
-- gun_psilent.lua
-- While an enemy head is inside fov_deg of the crosshair and visible, every shot you fire is
-- corrected onto it. You fire with your own trigger. The script only arms the angle, unless
-- test_mode is on. Settings (scripts/config/gun_psilent.json): fov_deg=6, bone="head", range_m=60.

script_info = {
    name        = "gun_psilent",
    author      = "tsuki",
    version     = "1.0",
    description = "Silent aim for the gun on your own shots (aim.silent example)",
    needs_internal = true,
}

local last_status, last_tap, taps, hits, hit_seq = -100, 0, 0, 0, 0

local function angle_between(a, b)
    local dot = a.x * b.x + a.y * b.y + a.z * b.z
    if dot > 1 then dot = 1 elseif dot < -1 then dot = -1 end
    return math.deg(math.acos(dot))
end

local function best_in_fov(fov_deg, range_m, bone)
    local cam, fwd = camera.get_position(), camera.get_forward()
    local best, ba = nil, fov_deg
    for _, p in ipairs(get_players() or {}) do
        if p:is_alive() and p:is_visible() then
            local d = p:get_distance()
            if d and d <= range_m then
                local h = p:get_bone_position(bone) or p:get_head_world()
                if h then
                    local v = vec3(h.x - cam.x, h.y - cam.y, h.z - cam.z):normalized()
                    local ang = angle_between(v, fwd)
                    if ang < ba then best, ba = p, ang end
                end
            end
        end
    end
    return best
end

function on_tick()
    local me = local_player()
    if not me or not me:is_alive() or not internal.is_loaded() then return end
    local fov_deg   = config.get_float("fov_deg", 6)
    local bone      = config.get_string("bone", "head")
    local range_m   = config.get_float("range_m", 60)
    local test_mode = config.get_bool("test_mode", false)
    local t = clock()

    -- count our hits on heroes
    local ev, latest = me:get_hit_events(hit_seq)
    if ev then
        for _, e in ipairs(ev) do if e.is_dealt and e.victim_class and e.victim_class ~= 0 then hits = hits + 1 end end
        if latest then hit_seq = latest end
    end
    if t - last_status >= 5 then
        last_status = t
        local d = aim.diag()
        print(string.format("[ex-gun] armed=%d taps=%d hero_hits=%d refused aimbot=%d input=%d last='%s'", d.silent, taps, hits, d.refused_aimbot, d.refused_input, d.last_reason or ""))
    end

    local target = best_in_fov(fov_deg, range_m, bone)
    if not target then return end
    -- re-arm every tick while the target stays in the cone
    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; last_tap = t end
    end
end

Notes ​

  • The script declares needs_internal = true because it uses the internal API. internal.is_loaded() at the top of on_tick checks that the internal is running.
  • Turn the built in aimbot off before testing. While it holds a lock, aim.silent returns false every tick and refused_aimbot climbs.
  • The status line prints every five seconds from aim.diag(). If armed climbs but hero_hits does not, the angle is being armed and the problem is elsewhere.
  • Only hero hits are counted (victim_class ~= 0).
  • The reload branch only runs under test_mode. A tap on an empty gun would count as a tap without firing.
  • The script has no settings table, so there is no menu for its values. It uses fov_deg = 6, bone = "head", range_m = 60 and test_mode = false unless C:\TSUKI\Deadlock\scripts\config\gun_psilent.json sets them. That file groups values by type: {"floats": {"fov_deg": 6, "range_m": 60}, "strings": {"bone": "head"}, "bools": {"test_mode": false}}.

See Aim for every option and refusal reason, Hit Events for the cursor, and Camera and Input for the external calls.