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:
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 |