LT Language Compiler for FiveM
npm install lt-script
nil errors before* you run the game.
netevent, addcmd, thread, and wait.
bash
Global installation (Recommended)
npm install -g lt-script
OR run directly via npx
npx lt-script build .
`
---
š Quick Start
Create a client.lt file:
`typescript
// Define a type for player data
interface PlayerData {
id: number,
name: string,
health: number
}
// Variables with types
let active: boolean = false
const MAX_HEALTH = 100
// FiveM Command
addcmd "heal" (source, args)
let amount = tonumber(args[1]) ?? MAX_HEALTH
SetEntityHealth(PlayerPedId(), amount)
print("Healed for ${amount}")
end
// Thread with loop
thread
print("System active")
loop (true)
wait 1000
if LocalPlayer.state?.isDead then
print("Player is dead!")
end
end
end
`
Compile it:
`bash
ltc build .
`
---
š Language Reference
$3
LT supports explicit typing with compile-time validation.
`typescript
// Mutable variables
let score: number = 0
var playerName: string = "John" // Type inferred if omitted
// Constants (Compiles to Lua 5.4 )
const MAX_PLAYERS = 32
// Available primitive types
let str: string = "hello"
let num: number = 42
let flag: boolean = true
let data: table = { key: "value" }
let pos: vector3 = <100.0, 200.0, 30.0>
let callback: function = () => print("hi")
// Arrays
let inventory: string[] = ["Apple", "Water"]
let numbers: number[] = [1, 2, 3]
`
$3
Define complex data structures for compile-time validation.
`typescript
// Interface - Object shape definition
interface VehicleConfig {
model: string,
price: number,
color: string
}
// Type Alias - Alternative syntax
type PlayerPos = { x: number, y: number, z: number }
// Usage with validation
const myCar: VehicleConfig = {
model: "sultan",
price: 50000,
color: "red"
}
// Arrays of interfaces
interface StoreConfig {
id: number,
position: vector3,
isOpen: boolean
}
const Stores: StoreConfig[] = [
{ id: 1, position: <100.0, 200.0, 30.0>, isOpen: true },
{ id: 2, position: <150.0, 250.0, 35.0>, isOpen: false }
]
`
> Note: Type validation ensures field types match. Assigning number to a vector3 field will cause a compile error.
$3
`typescript
// Standard function with typed parameters
func Add(a: number, b: number)
return a + b
end
// Default parameters
func Greet(name: string, prefix = "Hello")
print("${prefix}, ${name}!")
end
// Local function (Lua local function)
local function PrivateHelper()
return "internal"
end
// Arrow functions
let double = (x: number) => x * 2
let greet = (name) => print("Hello ${name}")
// Multi-line arrow
let process = (data) => {
let result = data * 2
return result
}
`
$3
#### If / Else
`typescript
// Note: 'then' keyword is required after condition
if health < 20 then
print("Low health!")
elseif health < 50 then
print("Medium health")
else
print("Full health")
end
`
#### Switch / Case
`typescript
let job = "police"
switch job
case "police", "ambulance"
print("Government worker")
case "mechanic"
print("Service worker")
default
print("Civilian")
end
`
#### Guard Clauses
Clean up nested if-statements with early returns.
`typescript
func RevivePlayer(player)
// Returns immediately if player is nil
guard player return
// Returns with custom logic if condition fails
guard player.isDead else
print("Player is already alive")
return
end
// Main logic
player.revive()
end
// Guard with return value
func GetPlayer(id)
let player = GetPlayerById(id)
guard player return nil
return player
end
`
#### For Loops
`typescript
// Numeric for (start, end)
for i = 1, 10 do
print(i)
end
// Numeric for with step (start, end, step)
for i = 0, 100, 5 do
print(i)
end
// Range for with step
for i in 1..10 by 2 do
print(i)
end
// For-in (pairs)
for key, value in pairs(myTable) do
print("${key}: ${value}")
end
// For-in (ipairs)
for index, item in ipairs(myArray) do
print("${index}: ${item}")
end
`
#### While Loop
`typescript
let count = 0
while count < 10 do
print(count)
count += 1
end
`
$3
#### Compound Assignment
`typescript
let x = 10
x += 5
x -= 3
x *= 2
x /= 4
x %= 3
`
#### Null Coalescing (??)
`typescript
let name = playerName ?? "Unknown"
let health = GetHealth() ?? 100
`
#### Optional Chaining (?.)
`typescript
let state = LocalPlayer.state?.isDead
let nested = obj?.deep?.value
let arrItem = arr?[0]
`
#### Ternary Operator
`typescript
let status = isDead ? "Dead" : "Alive"
let label = count > 0 ? "${count} items" : "Empty"
`
$3
`typescript
// Object Destructuring
let { x, y, z } = GetEntityCoords(ped)
let { name, health } = playerData
// Array Destructuring
let [first, second] = GetValues()
// Object Spread (tables only)
let base = { a: 1, b: 2 }
let extended = { ...base, c: 3 }
`
$3
Use ${expression} inside strings to embed values:
`typescript
let name = "John"
let age = 25
print("Hello, ${name}!")
print("You are ${age} years old")
print("Next year you'll be ${age + 1}")
// Complex expressions
let player = { health: 100 }
print("Health: ${player.health}")
`
$3
`typescript
// Vector3 (FiveM native)
let pos: vector3 = <100.0, 200.0, 30.0>
// Vector2
let screenPos: vector2 = <0.5, 0.5>
// Vector4 (includes heading)
let spawn: vector4 = <100.0, 200.0, 30.0, 90.0>
`
---
š® FiveM Features
$3
`typescript
// Create a thread (Citizen.CreateThread)
thread
print("Thread started")
loop (true)
wait 0 // Run every frame
// Game logic here
let ped = PlayerPedId()
let health = GetEntityHealth(ped)
if health < 50 then
print("Low health warning!")
end
end
end
`
$3
`typescript
// Wait in milliseconds
wait 1000 // Wait 1 second
wait 0 // Yield one frame
`
$3
`typescript
// Register + Handle network event (Client <-> Server)
netevent "bank:deposit" (amount)
print("Depositing ${amount}")
UpdateBankBalance(amount)
end
// Local event handler
event "onClientResourceStart" (resName)
guard resName == GetCurrentResourceName() return
print("Resource started!")
end
`
$3
`typescript
// Emit to server
emit "server:event:name" (arg1, arg2)
// Explicit emit variants
emitServer "myevent" (data)
emitClient "myevent" (targetPlayer, data)
`
$3
`typescript
// Register a command (RegisterCommand wrapper)
addcmd "teleport" (source, args)
let x = tonumber(args[1]) ?? 0
let y = tonumber(args[2]) ?? 0
let z = tonumber(args[3]) ?? 0
SetEntityCoords(PlayerPedId(), x, y, z)
print("Teleported to ${x}, ${y}, ${z}")
end
`
$3
`typescript
// Export a function
export "GetPlayerMoney" ()
return playerMoney
end
`
$3
`typescript
// Run once after delay
timeout 5000
print("5 seconds passed!")
end
// Run repeatedly
interval 1000
print("Every second")
end
`
$3
`typescript
try
RiskyOperation()
catch err
print("Error: ${err}")
end
`
---
ā” Complete Example: Store Robbery System
`typescript
// 1. Type Definition
interface StoreConfig {
id: number,
position: vector3,
reward: number,
isOpen: boolean
}
// 2. Configuration
const Stores: StoreConfig[] = [
{ id: 1, position: <120.5, -500.2, 30.0>, reward: 5000, isOpen: true },
{ id: 2, position: <250.0, 300.0, 25.0>, reward: 10000, isOpen: true }
]
let isRobbing = false
// 3. Main Game Loop
thread
loop (true)
wait 0
if isRobbing then
break
end
let ped = PlayerPedId()
let pos = GetEntityCoords(ped)
for _, store in ipairs(Stores) do
if not store.isOpen then
break
end
let distance = #(pos - store.position)
if distance < 2.0 then
ShowHelpText("Press ~INPUT_CONTEXT~ to rob")
if IsControlJustPressed(0, 38) then
StartRobbery(store)
end
end
end
end
end
// 4. Robbery Function
func StartRobbery(store: StoreConfig)
isRobbing = true
// Notify server
emit "robbery:start" (store.id)
// Play animation
TaskPlayAnim(PlayerPedId(), "anim_dict", "anim_name", 8.0, -8.0, -1, 0, 0, false, false, false)
wait 5000
ClearPedTasks(PlayerPedId())
isRobbing = false
print("Robbery complete! Reward: ${store.reward}")
end
// 5. Server Sync Handler
netevent "robbery:sync" (storeId, newState)
let store = Stores.find(s => s.id == storeId)
guard store return
store.isOpen = newState
let stateStr = newState ? "open" : "closed"
print("Store ${storeId} is now ${stateStr}")
end
`
---
š ļø CLI Reference
| Command | Usage | Description |
|:--------|:------|:------------|
| Build | ltc build ./ | Compiles all .lt files in the folder to .lua |
| Watch | ltc watch ./ | Watches for file changes and recompiles instantly |
| Version | ltc -v | Displays the current compiler version |
$3
LT automatically detects src/ folders:
`
my-resource/
āāā src/
ā āāā client.lt
ā āāā server.lt
āāā client.lua ā Generated
āāā server.lua ā Generated
``
Made with ā¤ļø for the FiveM Community by LaotScripts