RLS Studios
ProjectsPatreonCommunityDocsAbout
Join Patreon
BeamNG Modding Docs

Guides

Reference

UI

Resources

BeamNG Game Engine Lua Cheat SheetGE Developer RecipesMCP Server Setup

// RLS.STUDIOS=true

Premium Mods for BeamNG.drive. Career systems, custom vehicles, and immersive gameplay experiences.

Index

HomeProjectsPatreon

Socials

DiscordPatreon (RLS)Patreon (Vehicles)

© 2026 RLS Studios. All rights reserved.

Modding since 2024

GE Developer Recipes

A comprehensive collection of 50+ practical solutions for common Game Engine (GE) development tasks. Each recipe is copy-paste ready with explanations.

A comprehensive collection of 50+ practical solutions for common Game Engine (GE) development tasks. Each recipe is copy-paste ready with explanations.


Table of Contents

  1. Extension Fundamentals
  2. Custom Missions
  3. Career Integration
  4. UI Popups & Notifications
  5. Flowgraph Scripting
  6. Vehicle Management
  7. World & Environment
  8. Traffic & AI
  9. Save & Persistence
  10. Utility Patterns

1. Extension Fundamentals

Recipe 1.1: Minimal GE Extension

local M = {}
local logTag = 'myMod'

local function onExtensionLoaded()
  log('I', logTag, 'Extension loaded')
end

M.onExtensionLoaded = onExtensionLoaded
return M

Recipe 1.2: Extension with Dependencies

local M = {}
M.dependencies = {'career_career', 'career_saveSystem', 'freeroam_facilities'}
-- Dependencies are loaded before this extension's hooks fire
return M

Recipe 1.3: Hot-Reload Extension During Development

-- Load an extension
extensions.load('gameplay_taxi')

-- Unload when done
extensions.unload('gameplay_taxi')

-- Hot-reload (unload + load) for rapid iteration
extensions.reload('gameplay_taxi')

Recipe 1.4: Persist Extension Across Level Changes

-- By default, extensions unload on level change
-- Use manual mode to persist
setExtensionUnloadMode("gameplay_taxi", "manual")
extensions.load("gameplay_taxi")

Recipe 1.5: Fire Custom Hook to All Extensions

-- Trigger a custom hook that any extension can listen to
extensions.hook("onMyCustomEvent", {data = 42, source = "myMod"})

-- In another extension, receive the event:
local function onMyCustomEvent(data)
  log('I', 'otherMod', 'Received event with data: ' .. dumps(data))
end
M.onMyCustomEvent = onMyCustomEvent

2. Custom Missions

Recipe 2.1: Start a Mission Programmatically

-- Start a mission by its ID
local missionId = "mission_timeTrial_01"
gameplay_missions_missionManager.start(missionId)

-- Start with attempt data
local attemptData = {
  vehicle = "etk800",
  difficulty = "hard"
}
gameplay_missions_missionManager.start(missionId, attemptData)

Recipe 2.2: Check Mission Status

-- Check if any mission is active
local activeMissionId = gameplay_missions_missionManager.getForegroundMissionId()
if activeMissionId then
  log('I', 'myMod', 'Active mission: ' .. activeMissionId)
else
  log('I', 'myMod', 'No mission active')
end

-- Get mission state
local state = gameplay_missions_missionManager.getMissionState()
-- state can be: "none", "started", "stopped", etc.

Recipe 2.3: Stop Current Mission

-- Stop the foreground mission
local missionId = gameplay_missions_missionManager.getForegroundMissionId()
if missionId then
  gameplay_missions_missionManager.stop(missionId)
end

Recipe 2.4: Create Mission Attempt Data

-- Structure for tracking a mission attempt
local attempt = {
  type = "passed",           -- "completed", "passed", "attempted", "abandoned", "failed"
  date = os.time(),
  humanDate = os.date("!%Y-%m-%dT%TZ"),
  data = { 
    points = 1500,
    time = 45.32,
    penalties = 0
  },
  unlockedStars = { 
    defaultStar0 = true, 
    bonusStar0 = true 
  }
}

-- Aggregate the attempt into progress
gameplay_missions_progress.aggregateAttempt(missionId, attempt, "default")

Recipe 2.5: Get Mission Progress

-- Get mission by ID
local mission = gameplay_missions_missions.getMissionById(missionId)

-- Check if mission is unlocked
local isUnlocked = gameplay_missions_unlocks.getSimpleUnlockedStatus(missionId)

-- Format save data for UI display
local uiData = gameplay_missions_progress.formatSaveDataForUi(missionId)

Recipe 2.6: Mission with Star Rewards

-- Define star rewards in mission configuration
local missionConfig = {
  careerSetup = {
    starRewards = {
      defaultStar0 = {
        { attributeKey = "money", rewardAmount = 500 },
        { attributeKey = "beamXP", rewardAmount = 10 },
      },
      bonusStar0 = {
        { attributeKey = "money", rewardAmount = 200 },
        { attributeKey = "voucher", rewardAmount = 1 },
      }
    }
  }
}

3. Career Integration

Recipe 3.1: Guard Code Behind Career Check

-- Always check if career is active before using career modules
if not career_career or not career_career.isActive() then 
  return 
end

-- Safe to use career modules here
local money = career_modules_playerAttributes.getAttributeValue("money")

Recipe 3.2: Pay Money from Player

-- Check if player has enough money first
local price = { money = { amount = 5000, canBeNegative = false } }
local currentMoney = career_modules_playerAttributes.getAttributeValue("money")

if currentMoney >= 5000 then
  career_modules_payment.pay(price, { label = "Purchased garage upgrade" })
  return true
else
  -- Show insufficient funds notification
  guihooks.trigger("toastrMsg", {
    type = "error",
    title = "Insufficient Funds",
    msg = "You need $5,000 for this purchase."
  })
  return false
end

Recipe 3.3: Reward Player

-- Give money/XP reward via addAttributes
local change = { money = 1500, beamXP = 50 }
local reason = { label = "Delivery completed" }
career_modules_playerAttributes.addAttributes(change, reason)

-- Show toast notification manually
guihooks.trigger("toastrMsg", {
  type = "success",
  title = "Reward!",
  msg = "You earned $1,500 and 50 XP"
})

Recipe 3.4: Read Player Attributes

-- Get various player attributes
local money = career_modules_playerAttributes.getAttributeValue("money")
local beamXP = career_modules_playerAttributes.getAttributeValue("beamXP")
local vouchers = career_modules_playerAttributes.getAttributeValue("voucher")

-- Check if player has specific amount
if money >= 10000 then
  -- Unlock premium feature
end

Recipe 3.5: Reputation Management

-- Add/update reputation data for an organization object
-- Note: addReputationToOrg takes an organization table, not a string
career_modules_reputation.addReputationToOrg(organizationTable)

-- Get value for a specific event type
local val = career_modules_reputation.getValueForEvent("returnLoanerDamaged")

-- Get label for a reputation level
local label = career_modules_reputation.getLabel(levelNumber)

Recipe 3.6: Career Save/Load Integration

-- Save custom data when career saves
local function onSaveCurrentSaveSlot(currentSavePath)
  local dirPath = currentSavePath .. "/career/myMod"
  if not FS:directoryExists(dirPath) then
    FS:directoryCreate(dirPath)
  end
  career_saveSystem.jsonWriteFileSafe(dirPath .. "/state.json", myState, true)
end
M.onSaveCurrentSaveSlot = onSaveCurrentSaveSlot

-- Load data when career modules activate
local function onCareerModulesActivated(alreadyInLevel)
  if not career_career.isActive() then return end
  local _, path = career_saveSystem.getCurrentSaveSlot()
  if not path then return end
  myState = jsonReadFile(path .. "/career/myMod/state.json") or {}
end
M.onCareerModulesActivated = onCareerModulesActivated

Recipe 3.7: Inventory Management

-- Get player's owned vehicles
local inventory = career_modules_inventory
local vehicles = inventory.getVehicles()

-- Get specific vehicle data
local vehicleData = inventory.getVehicle(inventoryId)

-- Spawn a vehicle from inventory
inventory.spawnVehicle(inventoryId)

-- Get current vehicle inventory ID
local currentId = inventory.getCurrentVehicleId()

Recipe 3.8: Trigger Manual Career Save

-- Force a career save (use sparingly)
career_saveSystem.saveCurrent()

-- With callback when complete
career_saveSystem.saveCurrent(function(success)
  if success then
    guihooks.trigger("toastrMsg", {
      type = "success",
      title = "Game Saved",
      msg = "Your progress has been saved."
    })
  end
end)

4. UI Popups & Notifications

Recipe 4.1: Toast Notification

-- Simple toast notification (non-blocking, auto-dismiss)
guihooks.trigger("toastrMsg", {
  type = "success",   -- "success", "error", "warning", "info"
  title = "Game Saved",
  msg = "Your progress has been saved."
})

-- Error toast
guihooks.trigger("toastrMsg", {
  type = "error",
  title = "Update Required",
  msg = "Please update to the latest version."
})

-- Warning with label (for grouping)
guihooks.trigger("toastrMsg", {
  type = "warning",
  label = "vehStored",
  title = "Vehicle stored",
  msg = "Damaged vehicles have been moved to storage."
})

Recipe 4.2: Full Notification Dialog

-- Full notification with more prominence
guihooks.trigger("Notification", {
  type = "info",      -- "info", "warning", "error", "success"
  title = "Mission Complete",
  message = "You have successfully delivered all packages."
})

Recipe 4.3: Confirmation Dialog

-- Show confirmation then execute callback
guihooks.trigger("ConfirmDialog", {
  title = "Are you sure?",
  message = "This will delete your save file permanently.",
  confirmLabel = "Delete",
  cancelLabel = "Cancel",
  onConfirm = "myExtension.confirmDelete()",
  onCancel = "myExtension.cancelDelete()"
})

-- Handler functions
local function confirmDelete()
  -- Perform deletion
  log('I', 'myMod', 'User confirmed deletion')
end
M.confirmDelete = confirmDelete

local function cancelDelete()
  -- Cleanup if needed
  log('I', 'myMod', 'User cancelled deletion')
end
M.cancelDelete = cancelDelete

Recipe 4.4: UI State Navigation

-- Navigate to a UI state
guihooks.trigger("ChangeState", {state = "play", params = {}})
guihooks.trigger("ChangeState", {state = "menu"})
guihooks.trigger("ChangeState", {state = "vehicleInventory"})
guihooks.trigger("ChangeState", {state = "purchase-garage"})

-- Open specific UI module
guihooks.trigger("MenuOpenModule", "vehicleselect")

-- Navigate back
guihooks.trigger("UINavigation", "back", 1)

-- Hide menu
guihooks.trigger("MenuHide")

Recipe 4.5: Send Data to UI

-- Send one-time data update
guihooks.trigger("vehicleInventoryData", {
  vehicles = getVehicleList(),
  balance = getMoney(),
  garageName = "Main Garage"
})

-- Simple message popup
guihooks.message("Purchase complete!", 5, "info")

Recipe 4.6: Stream High-Frequency Data

-- For telemetry or live dashboards
function M.onUpdate(dtReal, dtSim, dtRaw)
  guihooks.queueStream("myModSpeed", currentSpeed)
  guihooks.queueStream("myModFuel", fuelPercent)
  guihooks.queueStream("myModRPM", engineRPM)
  -- Streams are flushed automatically by main.lua's render loop
end

-- In UI: bngApi.engineLua('myMod.getStreamData()', callback)

Recipe 4.7: Screen Fade Effect

-- Fade to black over 0.5 seconds
ui_fadeScreen.start(0.5)

-- React to fade state changes
local function onScreenFadeState(state)
  if state == 1 then
    -- Fully black - do transition work
    performLevelTransition()
    ui_fadeScreen.stop(0.5)  -- Fade back in
  elseif state == 3 then
    -- Fully visible again - cleanup
    cleanupTransition()
  end
end
M.onScreenFadeState = onScreenFadeState

5. Flowgraph Scripting

Recipe 5.1: Access Flowgraph Module

-- Get a flowgraph module
local missionModule = self.mgr:getModule("mission")

-- Process vehicles at mission start
missionModule:processVehicles({ keepPlayer = true, keepTraffic = false })

-- Get original player vehicle ID
local origId = missionModule:getOriginalPlayerId()

-- Fire custom mission event
missionModule:missionHook("checkpointReached", { index = 3 })

Recipe 5.2: Create Custom Flowgraph Node

-- Template for custom node
local C = {}
C.name = "My Custom Node"
C.type = "node"
C.category = "Gameplay"

C.pinSchema = {
  {dir = "in", type = "flow", name = "flow", description = "Input flow"},
  {dir = "in", type = "number", name = "value", description = "Input value"},
  {dir = "out", type = "flow", name = "flow", description = "Output flow"},
  {dir = "out", type = "number", name = "result", description = "Result"}
}

function C:init()
  -- Initialize node state
  self.count = 0
end

function C:_executionStarted()
  -- Called when execution starts
  self.count = 0
end

function C:work(args)
  -- Process input and set output
  self.count = self.count + 1
  self.pinOut.result.value = self.pinIn.value.value * 2
  self.pinOut.flow.value = self.pinIn.flow.value
end

function C:_executionStopped()
  -- Cleanup when execution stops
end

return _flowgraph_createNode(C)

Recipe 5.3: Flowgraph Timer Node

-- Create a countdown timer node
local C = {}
C.name = "Countdown Timer"
C.type = "node"
C.category = "Logic"

C.pinSchema = {
  {dir = "in", type = "flow", name = "start", description = "Start timer"},
  {dir = "in", type = "number", name = "duration", default = 10, description = "Duration in seconds"},
  {dir = "out", type = "flow", name = "finished", description = "Timer finished"},
  {dir = "out", type = "number", name = "remaining", description = "Seconds remaining"}
}

function C:init()
  self.running = false
  self.endTime = 0
end

function C:work(args)
  if self.pinIn.start.value then
    self.running = true
    self.endTime = os.clock() + self.pinIn.duration.value
  end
  
  if self.running then
    local remaining = self.endTime - os.clock()
    self.pinOut.remaining.value = math.max(0, remaining)
    self.pinOut.finished.value = remaining <= 0
    
    if remaining <= 0 then
      self.running = false
    end
  end
end

return _flowgraph_createNode(C)

Recipe 5.4: Vehicle Visibility Control

-- Hide/show player vehicle in flowgraph
local missionModule = self.mgr:getModule("mission")

-- Hide player vehicle, freeze traffic
missionModule:processVehicles({ keepPlayer = false, keepTraffic = false })

-- Show player vehicle, unfreeze traffic  
missionModule:processVehicles({ keepPlayer = true, keepTraffic = true })

-- Prepare vehicle (headlights based on time of day)
missionModule:prepareVehicle(vehId)

Recipe 5.5: Flowgraph Variable Access

-- Get/set flowgraph variables
local value = self.mgr:getVariable("myVariable")
self.mgr:setVariable("myVariable", newValue)

-- Check if variable exists
local exists = self.mgr:hasVariable("myVariable")

-- Get all variables as table
local vars = self.mgr:getVariables()

6. Vehicle Management

Recipe 6.1: Get Player Vehicle

-- Get the player vehicle (index 0 = current player)
local veh = be:getPlayerVehicle(0)
if not veh then return end

local vehId = veh:getId()
local jbeamFile = veh:getJBeamFilename()

Recipe 6.2: Spawn Vehicle

-- spawn.spawnVehicle(model, partConfig, pos, rot, options)
local pos = vec3(0, 0, 100)
local rot = quat(0, 0, 0, 1)
local options = {
  licenseText = "AB-123-CD"
}
local veh = spawn.spawnVehicle("etk800", "vehicles/etk800/sport.pc", pos, rot, options)

-- Get spawned vehicle ID
local vehId = veh:getId()

Recipe 6.3: Send Command to Vehicle

-- Send Lua command to vehicle's VE context
local veh = be:getPlayerVehicle(0)
if veh then
  veh:queueLuaCommand("electrics.values.hazard = 1")
  veh:queueLuaCommand("extensions.load('myVeExtension')")
end

-- Send to vehicle by ID
be:getObjectByID(vehId):queueLuaCommand("electrics.set_motor_boost(1)")

Recipe 6.4: VE-to-GE Callback Pattern

-- In GE: spawn vehicle, then run VE code that calls back
veh:queueLuaCommand(string.format(
  "partCondition.initConditions(nil, %d, nil, %f) obj:queueGameEngineLua('myMod.onSpawnComplete(%d)')",
  mileage, visualCondition, vehId
))

-- Callback handler
local function onSpawnComplete(vehId)
  log('I', 'myMod', 'Vehicle ' .. vehId .. ' spawn complete')
end
M.onSpawnComplete = onSpawnComplete

Recipe 6.5: Iterate All Vehicles

-- Loop through all vehicles in scene
for i = 0, be:getObjectCount() - 1 do
  local veh = be:getObject(i)
  local id = veh:getId()
  local pos = veh:getPosition()
  -- Process each vehicle
end

-- Delete all vehicles (iterate backwards)
for i = be:getObjectCount() - 1, 0, -1 do
  be:getObject(i):delete()
end

-- Delete specific vehicle
veh:delete()

Recipe 6.6: Teleport Vehicle

local veh = be:getPlayerVehicle(0)
if veh then
  -- Set position
  veh:setPosition(Point3F(x, y, z))
  
  -- Set rotation
  veh:setRotation(QuatF(0, 0, 0, 1))
  
  -- Combined position + rotation
  veh:setPositionRotation(x, y, z, rx, ry, rz, rw)
  
  -- Reset physics (recommended after teleport)
  veh:reset()
end

7. World & Environment

Recipe 7.1: Time of Day Control

-- Set time via core_environment (0.0-1.0, where 0.5 = noon)
core_environment.setTimeOfDay({time = 0.5})

-- Or via scenetree TimeOfDay object
local tod = scenetree.findObject("TimeOfDay")
if tod then
  tod.time = 0.5
  tod.play = false  -- Stop day/night cycle
end

Recipe 7.2: Physics Control

-- Pause/resume via simTimeAuthority
simTimeAuthority.pause(true)
simTimeAuthority.pause(false)

-- Set physics speed factor
be:setPhysicsSpeedFactor(0.5)  -- Half speed
be:setPhysicsSpeedFactor(1.0)  -- Normal

Recipe 7.3: Scene Object Access

-- Find object by name
local obj = scenetree.findObject("myTrigger")
if obj then
  local pos = obj:getPosition()
  local className = obj:getClassName()
end

-- Hide/show object
obj:setHidden(true)
obj:setHidden(false)

-- Get object by ID
local obj = scenetree.findObjectById(id)

Recipe 7.4: Facility Access

-- Get all facilities of a type
local garages = freeroam_facilities.getFacilitiesByType("garage")
local gasStations = freeroam_facilities.getFacilitiesByType("gasStation")

-- Get specific facility
local garage = freeroam_facilities.getFacility("garage", garageId)

-- Get garage position and rotation
local pos, rot = freeroam_facilities.getGaragePosRot(garageId)

Recipe 7.5: Map/Level Info

-- Get current level identifier
local levelName = getCurrentLevelIdentifier()

-- Get map data
local mapData = map.getMap()
local mapName = map.getMapName()
local mapPath = map.getMapPath()

-- Access road nodes
local nodes = map.getMap().nodes
local nodePos = nodes["nodename"].pos

8. Traffic & AI

Recipe 8.1: Get Traffic Vehicles

-- Get list of all traffic vehicles
local trafficVehicles = gameplay_traffic.getTrafficList()

for _, tVeh in ipairs(trafficVehicles) do
  local id = tVeh.id
  local role = tVeh.role  -- "police", "civilian", etc.
  -- Process traffic vehicle
end

-- Get traffic data table
local trafficData = gameplay_traffic.getTrafficData()

Recipe 8.2: Set AI Role

-- Assign police role to traffic vehicle
local vehicle = gameplay_traffic.getTrafficData()[vehId]
if vehicle then
  vehicle:setRole("police")
end

-- Available roles: "police", "civilian", "ambulance", "fire", "highwayPatrol"

Recipe 8.3: AI Driving Commands

local obj = be:getObjectByID(vehId)

-- Drive in lane
obj:queueLuaCommand('ai.driveInLane("on")')

-- Set speed mode
obj:queueLuaCommand('ai.setSpeedMode("off")')  -- No speed limit
obj:queueLuaCommand('ai.setSpeedMode("limit")') -- Obey speed limits
obj:queueLuaCommand('ai.setSpeed(20)')  -- m/s

-- Set target
obj:queueLuaCommand(string.format('ai.setTarget(%f, %f, %f)', x, y, z))

Recipe 8.4: Spawn Traffic

-- Add traffic vehicle
gameplay_traffic.addTrafficVehicle(vehId)

-- Remove traffic vehicle
gameplay_traffic.removeTrafficVehicle(vehId)

-- Setup parked cars
gameplay_traffic.setupParkedCars(config)

9. Save & Persistence

Recipe 9.1: Read/Write JSON Settings

local settingsPath = 'settings/myMod/config.json'

local function loadSettings()
  return jsonReadFile(settingsPath) or { 
    volume = 1.0, 
    enabled = true,
    difficulty = "normal"
  }
end

local function saveSettings(data)
  if not FS:directoryExists('settings/myMod') then
    FS:directoryCreate('settings/myMod')
  end
  jsonWriteFile(settingsPath, data, true)
end

Recipe 9.2: Safe File Writing

-- Use safe write for critical save data
-- Writes to temp file first, then moves to prevent corruption

career_saveSystem.jsonWriteFileSafe(
  "path/to/data.json",  -- file path
  myTable,               -- data to save
  true                   -- pretty print
)

Recipe 9.3: File System Operations

-- Check existence
if FS:fileExists("/path/to/file.json") then ... end
if FS:directoryExists("/path/to/dir") then ... end

-- Create directory (recursive)
FS:directoryCreate("/path/to/deep/dir", true)

-- Find files
local luaFiles = FS:findFiles("/lua/ge/extensions/", "*.lua", -1, true, false)

-- Read/Write raw files
local content = readFile("/path/to/file.txt")
writeFile("/path/to/output.txt", content)

Recipe 9.4: Mission Progress Save Slot

-- Set save slot for mission progress
gameplay_missions_progress.setSaveSlot("career_slot1")

-- Get current slot
local slotName, savePath = gameplay_missions_progress.getSaveSlot()

10. Utility Patterns

Recipe 10.1: Input Action Filtering

-- Block specific editor actions
local blocked = {"editorToggle", "editorSafeModeToggle", "vehicleEditorToggle"}
core_input_actionFilter.setGroup("MY_MOD_BLOCK", blocked)

-- Enable blocking
core_input_actionFilter.addAction(0, "MY_MOD_BLOCK", true)

-- Disable blocking
core_input_actionFilter.addAction(0, "MY_MOD_BLOCK", false)

Recipe 10.2: Async Job System

-- Create non-blocking delayed work
core_jobsystem.create(function(job)
  job.sleep(3)  -- Wait 3 seconds
  log('I', 'myMod', 'Delayed work done')
  
  -- Can chain more work
  job.sleep(1)
  doMoreWork()
end)

Recipe 10.3: World Ready State

-- Run code when world is fully loaded
local function onWorldReadyState(state)
  if state == 2 then -- 2 = fully ready
    initializeMyMod()
  end
end
M.onWorldReadyState = onWorldReadyState

Recipe 10.4: Career Activation Hook

-- React to career activation/deactivation
local function onCareerActive(active)
  if active then
    startCareerFeatures()
  else
    cleanupCareerFeatures()
  end
end
M.onCareerActive = onCareerActive

Recipe 10.5: Vehicle Spawn Hook

-- React to vehicle spawn
local function onVehicleSpawned(objID, veh)
  veh:queueLuaCommand("extensions.load('myVeExtension')")
end
M.onVehicleSpawned = onVehicleSpawned

Recipe 10.6: Mod Deactivation Cleanup

-- Cleanup when mod is deactivated
local function onModDeactivated(modData)
  if modData.modname == "my_mod_name" then
    cleanup()
    saveState()
  end
end
M.onModDeactivated = onModDeactivated

Recipe 10.7: Throttled UI Updates

-- Don't update UI every frame - throttle to 10Hz
function M.onUpdate(dtReal, dtSim, dtRaw)
  if not M.isActive then return end
  
  M.uiTimer = (M.uiTimer or 0) + dtReal
  if M.uiTimer > 0.1 then  -- 10Hz update rate
    M.uiTimer = 0
    guihooks.trigger('MyModUpdate', M.getState())
  end
end

Recipe 10.8: State + UI Sync Pattern

-- Always keep UI in sync with state (No Ghost Values!)
local function setActive(active)
  M.isActive = active
  -- Immediately notify UI
  guihooks.trigger('MyModStateChanged', {active = M.isActive})
end

-- DON'T do this (creates ghost value):
-- M.isActive = true  -- UI doesn't know about this!

Quick Reference

CategoryRecipesKey Modules
Extensions5extensions
Missions6gameplay_missions_*
Career8career_modules_*, career_saveSystem
UI7guihooks, ui_fadeScreen
Flowgraph5_flowgraph_*
Vehicles6be, spawn
World5be, scenetree, map
Traffic4gameplay_traffic
Save/Persistence4FS, json*
Utilities8Various
Total58-

See Also

  • GE Cheat Sheet - 50+ common one-liners
  • GE TL;DR Architect - Extension lifecycle rules
  • GE SKILL.md - Complete GE documentation hub
  • VE Recipes - Vehicle Engine recipes

BeamNG Game Engine Lua Cheat Sheet

A collection of 50+ high-frequency one-liners and snippets for game engine-side scripting.

MCP Server Setup

Use BeamNG docs with AI coding tools like Cursor and Claude Desktop

On this page

Table of Contents1. Extension FundamentalsRecipe 1.1: Minimal GE ExtensionRecipe 1.2: Extension with DependenciesRecipe 1.3: Hot-Reload Extension During DevelopmentRecipe 1.4: Persist Extension Across Level ChangesRecipe 1.5: Fire Custom Hook to All Extensions2. Custom MissionsRecipe 2.1: Start a Mission ProgrammaticallyRecipe 2.2: Check Mission StatusRecipe 2.3: Stop Current MissionRecipe 2.4: Create Mission Attempt DataRecipe 2.5: Get Mission ProgressRecipe 2.6: Mission with Star Rewards3. Career IntegrationRecipe 3.1: Guard Code Behind Career CheckRecipe 3.2: Pay Money from PlayerRecipe 3.3: Reward PlayerRecipe 3.4: Read Player AttributesRecipe 3.5: Reputation ManagementRecipe 3.6: Career Save/Load IntegrationRecipe 3.7: Inventory ManagementRecipe 3.8: Trigger Manual Career Save4. UI Popups & NotificationsRecipe 4.1: Toast NotificationRecipe 4.2: Full Notification DialogRecipe 4.3: Confirmation DialogRecipe 4.4: UI State NavigationRecipe 4.5: Send Data to UIRecipe 4.6: Stream High-Frequency DataRecipe 4.7: Screen Fade Effect5. Flowgraph ScriptingRecipe 5.1: Access Flowgraph ModuleRecipe 5.2: Create Custom Flowgraph NodeRecipe 5.3: Flowgraph Timer NodeRecipe 5.4: Vehicle Visibility ControlRecipe 5.5: Flowgraph Variable Access6. Vehicle ManagementRecipe 6.1: Get Player VehicleRecipe 6.2: Spawn VehicleRecipe 6.3: Send Command to VehicleRecipe 6.4: VE-to-GE Callback PatternRecipe 6.5: Iterate All VehiclesRecipe 6.6: Teleport Vehicle7. World & EnvironmentRecipe 7.1: Time of Day ControlRecipe 7.2: Physics ControlRecipe 7.3: Scene Object AccessRecipe 7.4: Facility AccessRecipe 7.5: Map/Level Info8. Traffic & AIRecipe 8.1: Get Traffic VehiclesRecipe 8.2: Set AI RoleRecipe 8.3: AI Driving CommandsRecipe 8.4: Spawn Traffic9. Save & PersistenceRecipe 9.1: Read/Write JSON SettingsRecipe 9.2: Safe File WritingRecipe 9.3: File System OperationsRecipe 9.4: Mission Progress Save Slot10. Utility PatternsRecipe 10.1: Input Action FilteringRecipe 10.2: Async Job SystemRecipe 10.3: World Ready StateRecipe 10.4: Career Activation HookRecipe 10.5: Vehicle Spawn HookRecipe 10.6: Mod Deactivation CleanupRecipe 10.7: Throttled UI UpdatesRecipe 10.8: State + UI Sync PatternQuick ReferenceSee Also