Skip to main content
events.On is load-time only. A callback error stops that script’s normal callbacks until it reloads. Unload handlers still run so the script can clean up. Multiple scripts can register for the same event; all callbacks fire in registration order. Callbacks are cleaned up automatically when the script is unloaded or disabled.

Built-in events

createmove

cmd is a CUserCmd. Writes are diffed back. Fires once per rendered frame. The same command may appear more than once above tickrate. Movement and button changes must be written on every call; use movement for persistent movement changes.

movement

Uses the same cmd as createmove. It fires for each new command and view-angle change. Use it for movement changes that should persist across repeated frames. Entity reads are pre-prediction state. createmove runs later and can overwrite these changes.

frame_stage

Fires several times per frame with the stage index.

unload

Fires when the script unloads. No arguments. Runs on the game’s main thread.

paint

Fires once per frame. Draw calls only work from here, see Renderer.

vote_setup

Fires when a vote starts, before the HUD shows it.

edgebug

Fires when hitting an edgebug.

jumpbug

Fires on the command the jump bug lands. No arguments.

pixelsurf

Fires once per command while pixel surfing, then once more with active = false when the surf ends.

Game events

Any CS2 game event can be registered by name. See CS2 Game Events for the full list of events and their keys.
The callback receives a game event object with typed getters: The event object is only valid inside the callback. Don’t store it. Player fields (userid, attacker, etc.) are player controller indices internally. Use e:GetPawn("userid") or e:GetController("userid") to get the entity directly. Names are case-sensitive. An unknown name registers successfully but never fires.

Button constants

Available on the events table for use with cmd.buttons:
cmd.buttons is the raw button bitfield, so any other bit can be passed as a plain number. Bits above 31 (IN_ZOOM is one) have no constant here because bit.bor is 32-bit and would truncate them; add them with + instead.