Event callback parameters
Subscribe with samp.events.on. Every callback receives one event table.
Common envelope
Every event contains:
| Field | Type | Meaning |
|---|---|---|
name | string | Exact event name. |
sequence | integer | Monotonic dispatch sequence within the runtime. All subscribers to one dispatch see the same value. |
timestamp | integer | Monotonic event timestamp in milliseconds; not wall-clock time. |
sessionId | integer | Session associated with the event. |
playerGeneration | integer | Local-player generation associated with the event. |
Payload tables are valid for the callback only. Copy primitive values if a task needs them later. Unless marked mutable, changing a field has no host effect.
Lifecycle, frame, and UI events
| Event | Additional fields | Notes |
|---|---|---|
plugin.loaded | none | Dispatched after the entry file loads; subscribe during entry evaluation to receive it. |
plugin.unloading | none | Dispatched before the plugin's subscriptions, tasks, and effects are released. |
session.started | none | A new runtime session began. |
session.ended | none | Current session ended. |
game.ready | none | Game services became ready. |
server.connected | none | Multiplayer connection completed. |
server.disconnected | none | Connection ended. |
player.spawned | none | Acquire new player/resources here. |
player.died | none | Previous player-generation resources must be considered stale. |
game.frame | deltaSeconds: number | Per-frame managed callback. Keep work bounded. |
draw.hud | deltaSeconds, screenWidth, screenHeight: number | Only phase in which samp.draw is available. |
ui.menu_opened | none | This plugin's menu became visible; requires ui.menu. |
ui.menu_closed | none | This plugin's menu was closed; requires ui.menu. |
ui.control_changed | pluginId, pageId, controlId, valueType, value | switch → boolean; slider/number_input → normalized number; choice-like controls and list → string; button/confirm_button → action/click; group → action/toggle. Filter by page and control ID. |
ui.control_changed is emitted only for interactive controls. section, text, divider, and progress are display-only. multi_choice sends the value of the option that was toggled, while text_input and color_picker send their value after the user presses Apply. A list sends the selected item value as a string.
Local-player events
| Event | Permission | Payload |
|---|---|---|
player.health_changed | game.player.read | previousHealth: number, health: number. |
player.vehicle_entered | game.vehicle.read | vehicleId: integer, passenger: boolean. |
player.vehicle_left | game.vehicle.read | vehicleId: integer, passenger: boolean. |
player.interior_changed | game.state.read | previousInterior: integer, interior: integer. |
player.weapon_changed | game.player.read | previousWeapon: integer, weapon: integer. |
player.aiming_changed | game.player.read | previousAiming: boolean, aiming: boolean. |
player.motion_changed | game.player.read | previousActivity, activity, previousMoveState, moveState, onGround, inAir. |
player.vehicle_collision | game.vehicle.read | vehicleId, otherType (vehicle, player, or world), optional otherId, impact, speed, position. |
player.skin_changed | game.player.read | previousSkin: integer, skin: integer. |
player.animation_changed | game.player.read | previousAnimation: integer, animation: integer. |
player.task_changed | game.player.read | previousCategory, category, previousType, previousName, type, name. |
world.time_changed | game.state.read | previousHour, previousMinute, hour, minute. |
world.weather_changed | game.state.read | previousWeather, previousHoldTime, weather, holdTime. |
vehicle.health_changed | game.vehicle.read | vehicle ID and previous/current health. |
vehicle.state_changed | game.vehicle.read | vehicleId, previousModel, model, optional previousHeading/heading, and before/after engine, lights, and siren booleans. |
player.damage_before
Requires game.player.write. Additional fields:
| Field | Type | Mutability |
|---|---|---|
damage | number | Writable, finite 0..100000; set 0 to suppress damage. |
weaponType | integer | Read-only input. |
bodyPart | integer | Read-only input. |
sourceType | "player", "actor", or "entity" | Read-only input. |
sourcePlayerId | integer | Present only for a known player source. |
sourceActorId | integer | Present only for a known actor source. |
Handlers run by priority and each sees the accepted result of earlier handlers. Invalid replacements are ignored. The callback cannot yield.
Dispatch and lifecycle rules
Notifications from the game, network, and Android UI enter a bounded queue of 256 immutable snapshots and are delivered on the next game-thread frame; the network observation share is capped at 96 items and ordinary notifications at 224 items so lifecycle events retain capacity. When a queue is full, new notifications are dropped and the network thread never waits for Lua.
Player availability and generation are synchronized independently of that queue. State-change events are sampled at most once per frame after lifecycle events and before game.frame and draw.hud. A direct vehicle switch emits player.vehicle_left before player.vehicle_entered. Initial observation after spawn, reconnect, or runtime enable establishes a baseline and does not invent historical change events. Handles from an old generation must be reacquired even when an event was queued before the generation changed.
Chat events
| Event | Permission | Payload |
|---|---|---|
chat.message_received | chat.read | playerId: integer, playerName: string, message: string, localPlayer: boolean. |
chat.server_message_received | chat.read | message: string, color: integer (ARGB). |
chat.bubble_received | chat.read | playerId: integer, message: string, color: integer, drawDistance: number, durationMs: integer. |
chat.message_sending
Requires chat.intercept. message: string and cancelled: boolean are writable. The replacement must be valid UTF-8, non-empty, at most 4,096 bytes, contain no NUL/CR/LF, and must not begin with /.
command.executing
Requires command.intercept. command: string and cancelled: boolean are writable. The replacement has the same 4,096-byte and line restrictions, must start with /, and must contain at least one character after it.
Cancellation is sticky for both events: once true, later handlers cannot set it back to false. Mutable interception callbacks cannot yield.
Checkpoint events
checkpoint.entered and checkpoint.left require game.state.read.
| Field | Type | Meaning |
|---|---|---|
kind | "normal" or "race" | Checkpoint kind. |
position | Vector3 | Checkpoint position. |
size | Vector3 | Present for box-shaped checkpoints. |
radius | number | Present for radius-shaped checkpoints. |
raceType | integer | Present together with radius. |
Touch, camera, and network events
input.touch
Requires ui.input and is dispatched synchronously before touch input is passed to the game. The payload contains:
| Field | Meaning |
|---|---|
action | down, move, up, or cancel. |
pointerId | Pointer identity, valid only for the current gesture sequence. |
x, y | Current screen-pixel coordinates. |
width, height | Display dimensions in pixels. |
normalizedX, normalizedY | Coordinates clamped to 0..1. |
cancelled | Writable; starts false. |
Set writable cancelled = true, or return false, to consume the gesture. Cancellation remains in effect for later events in the same pointer sequence.
camera.mode_changed
Requires game.state.read and contains previousMode and mode. The event is read-only and reports a camera mode change; it does not grant camera control.
Network observation and interception
The following events contain bounded, read-only packet metadata and a binary payload prefix:
| Event | Permission | Additional payload |
|---|---|---|
network.packet_received | network.inspect | packet ID, source index, byte/bit lengths, payload. |
network.rpc_received | network.inspect | RPC ID, source index, byte/bit lengths, payload. |
network.packet_sending | network.inspect | outgoing packet metadata and payload. |
network.rpc_sending | network.inspect | outgoing RPC metadata and payload. |
network.packet_before_send | network.intercept | same metadata plus writable cancelled. |
network.rpc_before_send | network.intercept | same metadata plus writable cancelled. |
Network payloads are Lua binary strings capped at 4,096 bytes; byteLength and bitLength retain the original lengths and truncated indicates a prefix. Observation is asynchronous and cannot replace or mutate payloads. Before-send interception is synchronous and best-effort: if the runtime cannot obtain its game-thread lock safely, the packet is allowed through and the runtime records a bypass. It is not an absolute firewall.
Server entity events
entity.streamed_in and entity.streamed_out require game.entity.read. Both contain:
| Field | Type |
|---|---|
entityType | player, vehicle, object, actor, pickup, or text_label |
entityId | integer |
streamGeneration | positive integer |
On streamed_in, pass all three fields to samp.entity.get. On streamed_out, an existing Handle for that identity is stale.
pickup.collected
Requires game.entity.read. The event contains pickupId, model, type, and position for the collected pickup. It is a notification only; it does not provide a mutable pickup Handle.
Dialog events
dialog.shown
Requires dialog.read.
| Field | Type | Meaning |
|---|---|---|
dialogId | integer | 0..32767. |
styleId | integer | Numeric style 0..5. |
style | string | message, input, list, password, tablist, or tablist_headers. |
title | string | Dialog title. |
message | string | Dialog body/list data. |
primaryButton | string | Primary button label. |
secondaryButton | string | Secondary button label; may be empty. |
All strings are UTF-8. title and each button are at most 1,024 bytes; message is at most 16 KiB.
dialog.responding
Requires dialog.intercept. Fields accepted: boolean, listItem: integer (-1..65534), input: string (valid UTF-8, maximum 4,096 bytes, no NUL/CR/LF), and cancelled: boolean are writable. dialogId is read-only. Cancellation is sticky, invalid replacements are ignored, and the callback cannot yield.
TextDraw events
All TextDraw identities combine textdrawId (0..3071) and textdrawGeneration (positive integer).
| Event | Permission | Additional payload |
|---|---|---|
textdraw.shown | textdraw.read | identity, styleId: integer, text: string, selectable: boolean, x: number, y: number. |
textdraw.hidden | textdraw.read | identity. |
textdraw.text_changed | textdraw.read | identity, text: string. |
textdraw.clicking | textdraw.intercept | identity, writable cancelled: boolean. |
Text may contain at most 4,096 bytes in an event. Click cancellation is sticky; the interception callback cannot yield.