Skip to content

Script Structure ​

A Lua script is a .lua file in the scripts folder. No fields are strictly required. An empty file is a valid script. Define only what you need.

Your most basic script will probably look something like this:

lua
name = "Aim Assist"

function on_tick()
    if is_in_menu() then return end
    if not input.is_key_held(VK.XBUTTON2) then return end

    local target = targeting.find_closest_by_fov(15, 50)
    if target and target:is_alive() then
        snap_to_target(target, { bone = bone.chest })
    end
end

on_tick runs every ~4ms (the rate at which the cheat reads memory) and is what 90%+ of scripts will use as their main loop. It runs as a coroutine, return to start fresh next tick, or call coroutine.yield() to resume from the same line preserving all local state.

Event-only scripts ​

on_tick isn't required. If your script only needs to react to game events, kills, modifiers, ability casts, you can skip it entirely. This is a complete event-only script:

lua
name = "Kill Logger"

function on_kill(player)
    toast(player:hero_name() .. " died!", 2)
end

The full list of available event callbacks is in the table below.

Optional globals ​

FieldDefaultPurpose
namefilename (without .lua)Display name in menu
idhero_id.any (all heroes)Hero filter: hero_id.haze, etc.
description""Tagline shown in the menu
settingsnoneConfig table rendered in the menu
needs_all_particlesfalseReceive all particle events, not just ability-related ones

Optional callbacks ​

Define only the callbacks you need.

CallbackWhen it fires
on_tick()Every ~4ms, runs as a coroutine
is_enabled()Checked before every tick; return false to skip this tick
on_kill(player)A player dies
on_modifier_added(player, mod)A modifier is applied to any player
on_modifier_removed(player, mod)A modifier is removed from any player
on_ability_cast(player, info)An ability (slots 0-3) went on cooldown
on_item_used(player, info)An active item (slots 4-7) went on cooldown
on_particle_create(event)A particle system spawned
on_particle_destroy(event)A particle system destroyed

Parameter details for each callback are in the Events reference.

is_enabled() is checked every tick before resuming on_tick. If it returns false, the coroutine is paused at its current coroutine.yield(). Not killed. When is_enabled() returns true again, the script resumes from exactly where it left off, with all local state preserved. For long-running helpers like fire_and_hold, this means a mid-hold disable will pause the wait; on re-enable the hold continues, though wall-clock timing keeps advancing in the meantime so the remaining hold window may have partially or fully elapsed.

Reloading ​

Edits to a .lua file are picked up by toggling that script off then back on in the menu, equivalent to a Reload Scripts call but scoped to one script. The Lua state, in-flight coroutines, and custom UI tabs are torn down and rebuilt from scratch. Top-level local variables reset on the cycle; for state that should survive a deliberate toggle, persist it via Storage.

Next steps ​

  • Sandbox - which standard libraries are available and which aren't
  • Script Settings - declarative settings and the config namespace
  • Events - full reference for each callback
  • Globals - top-level functions like clock, toast, print
  • Player - everything you can ask about a player

Not affiliated with Valve Corporation.