Skip to content

Events & Keyboard Controls

Learn how to run code continuously and detect player keyboard presses.


Running code every frame

Thread.Create()

A thread is how a mod runs code continuously. It is the heart of every mod, and the loader resumes it on every frame, around 60 times per second. This is where you check for key presses, draw HUD elements, or update game values.

Thread.Create(function()
    while true do
        -- This code runs constantly while playing
        Thread.Wait(0) -- hand control back until the next frame
    end
end)

Thread.Wait(ms) suspends the thread and resumes it later, without blocking the game or the other threads. Thread.Wait(0) simply waits for the next frame, which is what you want for per-frame code.

onUnload()

Called when your mod is stopped or reloaded. Use it to clean up objects, delete spawned cars, or save settings:

function onUnload()
    Log.Print("Mod stopped!")
end

Waiting between iterations

When you do not need to run on every single frame, wait longer. The thread sleeps, and costs nothing while it does.

Thread.Create(function()
    while true do
        SetCharHealth(GetPlayerChar(GetPlayerId()), 200)
        Thread.Wait(1000) -- once per second
    end
end)

This is the pattern ScriptHookDotNet mods are written against, so ported code keeps its structure.

Function Effect
Thread.Create(fn, ...) Starts a thread, returns an id. Extra arguments are passed to fn.
Thread.Wait(ms) Suspends the current thread. Thread.Wait(0) resumes on the next frame.
Thread.Stop(id) Stops a thread, returns true if it was still alive.
Thread.Count() Number of live threads.

Two things worth knowing:

  • An error inside a thread kills only that thread. It is logged, the thread is dropped, and the other threads keep running.
  • Thread.Wait() counts real time, not game time. A paused game wakes nothing, and every expired delay fires at once when you resume.

Wait() alone does not exist

GTA IV has a native called WAIT, so the bare global Wait belongs to the game, not to the scheduler. Always write Thread.Wait(ms). The native stays reachable through Native.Call("WAIT", ...).


Detecting Keyboard Keys (Input.IsKeyDown)

To check if a key is pressed, use Input.IsKeyDown(key_code).

Thread.Create(function()
    while true do
        if Input.IsKeyDown(0x73) then -- F4
            Log.Print("F4 was pressed!")
        end
        Thread.Wait(0)
    end
end)

Common Keyboard Key Codes Reference

Here are the most useful Windows Virtual-Key (VK) codes to copy and paste:

Key Hex Code Decimal Description
F1 0x70 112 Function Key 1
F2 0x71 113 Function Key 2
F3 0x72 114 Function Key 3
F4 0x73 115 Function Key 4 (Trainer standard)
F5 0x74 116 Function Key 5
F6 0x75 117 Reserved (Built-in In-Game Editor)
F7 0x76 118 Function Key 7
F8 0x77 119 Function Key 8
F9 0x78 120 Function Key 9
Shift 0x10 16 Left or Right Shift
Ctrl 0x11 17 Left or Right Control
Alt 0x12 18 Alt Key
Space 0x20 32 Spacebar
Enter 0x0D 13 Return / Enter
Escape 0x1B 27 Escape
Tab 0x09 9 Tab Key
Arrow Up 0x26 38 Up Arrow
Arrow Down 0x28 40 Down Arrow
Arrow Left 0x25 37 Left Arrow
Arrow Right 0x27 39 Right Arrow
E Key 0x45 69 Letter E
T Key 0x54 84 Letter T
X Key 0x58 88 Letter X
Z Key 0x5A 90 Letter Z
0 to 9 0x30 - 0x39 48 - 57 Top number row (0-9)
Numpad 0-9 0x60 - 0x69 96 - 105 Numeric Keypad