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"))
endActivation 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
endCooldown 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
endCustom 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)
endSmoothness 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)
endThe 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)
endAim 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)
endCamera 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
endAim 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 },
}