Skip to content

Example Scripts

Minimal Script

A simple script that uses ability 2 on the closest target:

lua
name = "Example"
id = hero_id.abrams

function is_enabled()
    return config.get_bool("enabled") and input.is_key_held(VK.XBUTTON2)
end

function on_tick()
    local target = targeting.find_closest_by_fov(5.0, 50.0)
    if not target or not target:is_targetable() then return end

    local lp = local_player()
    if not lp then return end

    if lp:is_ability_ready(slot.ability2) then
        if snap_to_target(target, { bone = bone.spine_1 }) then
            press_ability(slot.ability2)
        end
    end
end

settings = {
    { key = "enabled", type = "bool", default = false, label = "Enabled" },
}

Combo Script

Combos use helpers like snap_to_target, sleep, wait_until_in_range, and press_ability together. on_tick() runs as a coroutine — when it returns, it will be restarted on the next tick.

lua
name = "Bebop"
id = hero_id.bebop

function is_enabled()
    return config.get_bool("enabled")
        and input.is_key_held(config.get_int("activation_key"))
end

function on_tick()
    local target = targeting.find_closest_by_fov(config.get_float("max_fov"), 70.0)
    if not target or not target:is_targetable() then return end

    local lp = local_player()
    if not lp then return end

    -- hook (ability 3)
    local hook = lp:get_ability(slot.ability3)
    if not hook or not hook.learned then return end
    if not lp:is_ability_ready(slot.ability3) then return end

    snap_to_target(target, { bone = bone.spine_1, projectile_velocity = 3100 })
    press_ability(slot.ability3)

    if not wait_for_cooling_down(slot.ability3, 5000) then return end
    if not wait_until_in_range(target, 4.0, 4000) then return end

    -- bomb (ability 2)
    local bomb = lp:get_ability(slot.ability2)
    if config.get_bool("bomb") and bomb and bomb.learned and lp:is_ability_ready(slot.ability2) then
        snap_to_target(target, { bone = bone.spine_1 })
        sleep(100)
        press_ability(slot.ability2)
        sleep(100)
        left_click()

        -- echo shard
        if config.get_bool("echoshard") and lp:has_item("upgrade_ability_power_shard") then
            input.press_key(item_slot_to_key(config.get_int("echoshard_slot")))
            sleep(100)

            if lp:is_ability_ready(slot.ability2) then
                snap_to_target(target, { bone = bone.spine_1 })
                sleep(100)
                press_ability(slot.ability2)
                sleep(100)
                left_click()
            end
        end
    end

    -- uppercut (ability 1)
    local uppercut = lp:get_ability(slot.ability1)
    if config.get_bool("uppercut") and uppercut and uppercut.learned and lp:is_ability_ready(slot.ability1) then
        snap_to_target(target, { bone = bone.spine_1 })
        sleep(100)
        press_ability(slot.ability1)
    end
end

settings = {
    { key = "enabled",        type = "bool",    default = false,       label = "Enabled" },
    { key = "activation_key", type = "keybind", default = VK.XBUTTON2, label = "Activation Key" },
    { key = "max_fov",        type = "float",   default = 5.0,         label = "Max FOV", min = 1.0, max = 15.0 },
    { key = "bomb",           type = "bool",    default = true,        label = "Bomb" },
    { key = "uppercut",       type = "bool",    default = true,        label = "Uppercut" },
    { key = "echoshard",      type = "bool",    default = false,       label = "Echo Shard" },
    { key = "echoshard_slot", type = "item_slot", default = 0,           label = "Echo Shard Slot", depends_on = "echoshard", depends_value = 1 },
}

Key Patterns

Activation with Hold Key

lua
function is_enabled()
    return config.get_bool("enabled")
        and input.is_key_held(config.get_int("hotkey"))
end

Activation Mode (Hold Key vs Always On)

lua
function is_enabled()
    if not config.get_bool("enabled") then return false end
    if config.get_bool("always_on") then return true end
    local key = config.get_int("activation_key")
    return key > 0 and input.is_key_held(key)
end

settings = {
    { key = "enabled",        type = "bool",    default = false,       label = "Enabled" },
    { key = "always_on",      type = "bool",    default = false,       label = "Always On" },
    { key = "activation_key", type = "keybind", default = VK.XBUTTON2, label = "Key", depends_on = "always_on", depends_value = 0 },
}

Low-Health Execute

Using find_closest_by_predicate and is_targetable:

lua
function on_tick()
    local lp = local_player()
    if not lp or not lp:is_ability_ready(slot.ability4) then return end

    local target = find_closest_by_predicate(function(e)
        return e:is_targetable() and e:get_health_percentage() < 20
    end, 30.0)

    if not target then return end

    if snap_to_target(target, { bone = bone.spine_1 }) then
        press_ability(slot.ability4)
    end
end

Cooldown Gating with Debounce

Prevent spamming an action with debounce:

lua
function on_tick()
    local target = targeting.find_closest_by_fov(5.0, 30.0)
    if not target or not target:is_targetable() then return end

    -- only fire every 2 seconds
    if debounce("combo", 2000) then
        press_ability(slot.ability1)
    end
end

Custom Mouse Movement

Raw vs smoothed mouse movement:

lua
function on_tick()
    local target = targeting.find_closest_by_fov(5.0, 50.0)
    if not target then return end

    local delta = targeting.compute_aim_delta(target, bone.head)
    if delta:empty() then return end

    -- raw instant flick
    input.move_mouse(delta)

    -- smoothed movement (speed 0.5)
    input.move_mouse(delta, 0.5)

    -- smoothed with detach factor
    input.move_mouse(delta, 0.5, 0.3)
end

Smoothness Compensation

When aiming with smoothing, the crosshair lags behind a moving target. Pass your speed value as the 4th argument to compute_aim_delta — it applies smoothness compensation automatically, predicting where the target will be by the time the smooth cursor catches up.

lua
function on_tick()
    local target = targeting.find_closest_by_fov(5.0, 50.0)
    if not target or not target:is_targetable() then return end

    local speed = config.get_float("smooth_speed")

    -- speed param enables smoothness compensation inside compute_aim_delta
    local delta = targeting.compute_aim_delta(target, bone.head, 0, speed)
    if delta:empty() then return end

    input.move_mouse(delta, speed)
end

The higher-level helpers (aim_at_target, lock_aim) handle this automatically.

Raw Mouse Movement Explained

input.move_mouse(delta) sends a raw mouse delta in pixel units — the game converts it to angle change using the mouse multiplier (0.044) and sensitivity. With no extra args it applies instantly in one frame. With a speed argument (0.01–1.0), it interpolates over multiple frames — lower values are smoother but slower to converge.

lua
function on_tick()
    local target = targeting.find_closest_by_fov(5.0, 50.0)
    if not target then return end

    local delta = targeting.compute_aim_delta(target, bone.head)
    if delta:empty() then return end

    -- raw: full delta applied this frame
    input.move_mouse(delta)

    -- smoothed: only a fraction applied per frame, call every tick
    -- input.move_mouse(delta, 0.3)

    -- smoothed with detach: stops early when close enough
    -- input.move_mouse(delta, 0.3, 0.5)
end

Aim at World Position

Use the vec3 overload of compute_aim_delta to aim at an arbitrary world point instead of a player bone:

lua
function on_tick()
    -- aim at a fixed world coordinate
    local pos = vec3(1200, -500, 300)
    local delta = targeting.compute_aim_delta(pos)
    if delta:empty() then return end

    input.move_mouse(delta, 0.5)
end

Camera and World-to-Screen

Access camera state and project world positions to screen coordinates:

lua
function on_tick()
    local angles = camera.get_view_angles()  -- vec2(pitch, yaw)
    local forward = camera.get_forward()      -- unit vec3
    local fov = camera.get_fov()
    local screen = camera.get_screen_size()   -- vec2(width, height)

    -- project a world position to screen
    local target = targeting.find_closest_by_fov(10.0, 50.0)
    if not target then return end

    local head = target:get_bone_position(bone.head)
    local screen_pos = camera.world_to_screen(head)
    if screen_pos then
        print("head on screen at: " .. tostring(screen_pos))
    end
end

Aim Test Script

Diagnostic script that prints aim state each tick — useful for tuning sensitivity and smoothness:

lua
name = "Aim Test"
id = hero_id.any

function is_enabled()
    return config.get_bool("enabled") and input.is_key_held(VK.XBUTTON2)
end

function on_tick()
    local target = targeting.find_closest_by_fov(10.0, 50.0)
    if not target or not target:is_targetable() then return end

    local fov = targeting.get_fov(target, bone.head)
    local delta = targeting.compute_aim_delta(target, bone.head)
    local angles = camera.get_view_angles()

    print(string.format("fov=%.2f delta=%s angles=%s", fov, tostring(delta), tostring(angles)))

    if fov > 0.5 then
        local speed = config.get_float("speed")
        input.move_mouse(delta, speed)
    end
end

settings = {
    { key = "enabled", type = "bool",  default = false, label = "Enabled" },
    { key = "speed",   type = "float", default = 0.5,   label = "Smooth Speed", min = 0.01, max = 1.0 },
}