RLS Studios
ProjectsPatreonCommunityDocsAbout
Join Patreon
BeamNG Modding Docs

Guides

Reference

Server CommandsGE UtilitiesGame Engine MainNavigation GraphScreenshot CaptureServerServer ConnectionSpawnpoint ManagerSimulation TimeVehicle SpawningSuspension Frequency Tester
Gameplay AchievementGameplay CityDiscoverForce FieldGarage ModeMarker InteractionParking SystemGameplay Playmode MarkersGameplay PoliceGameplay RallyGameplay Rally LoopGameplay Raw POIsGameplay Skidpad TestSpeed Trap LeaderboardsSpeed Traps and CamerasGameplay StatisticsTaxi Ride SystemTraffic SystemVehicle PerformanceWalking
Locations DetectorMission ManagerMissionsMission Screen UIPOI TestProgressMission Start TriggerUnlocks

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

API ReferenceGE Extensionsgameplaymissions

Mission Start Trigger

Reference for `gameplay_missions_startTrigger`, which parses mission start triggers into location data and clusters nearby missions for the POI/marker system.

Reference for gameplay_missions_startTrigger, which parses mission start triggers into location data and clusters nearby missions for the POI/marker system.


Module Exports (M)

FunctionSignatureDescription
parseMission(mission) → locations, errParses a mission's startTrigger into a list of location objects
getMissionClusters(mergeRadius) → tableReturns clustered mission locations, cached by merge radius
defaultLocationCheck(location, level, playerPosition, mission) → boolProximity check: same level + within radius
defaultLocationDisplayMarker(location, playerPosition)Debug: draws cylinder marker at location
onAnyMissionChangedhookClears cluster cache when missions change

Start Trigger Types

TypeRequired FieldsDescription
levellevelMission available anywhere on specified level(s)
coordinateslevel, pos, radiusMission available at specific world position
leaguelevelLeague-based trigger (no location generated)
M.defaultLocationCheck(location, level, playerPosition, mission)-
M.defaultLocationDisplayMarker(location, playerPosition)-
M.getMissionClusters(mergeRadius)-
M.onAnyMissionChanged()-
M.parseMission(mission)-

Mission Clustering

Uses a quadtree for spatial clustering of coordinate-based mission triggers:

local function getMissionClusters(mergeRadius)
  -- 1. Collect all coordinate locations, grouped by level
  -- 2. Build quadtree per level
  -- 3. For each location, find overlapping neighbors
  -- 4. Merge overlapping locations into clusters
  -- 5. Cache result by mergeRadius
end

Merge Algorithm

local function merge(allClusters, cluster, mergeRadius)
  if #cluster == 1 then
    -- Single mission: use its position/radius directly
  else
    -- Multiple missions: compute weighted center
    -- 1. First pass: radius-weighted center
    -- 2. Second pass: distance-weighted center refinement
    -- 3. New radius = max(distance to any member + its radius) - 1
    -- All mission IDs collected into cluster
  end
end

Location Object Structure

{
  type = 'coordinates',
  level = "west_coast_usa",
  pos = vec3(...),
  rot = quat(...),
  radius = 3,
  check = defaultLocationCheck,
  displayMarker = defaultLocationDisplayMarker,
  missionIds = {"mission1", "mission2"},  -- for clusters
  clusterId = "mission1mission2"
}

How It Works

-- Parsing validates required fields before generating locations:
local function parseMission(mission)
  local trigger = mission.startTrigger
  -- Check required fields for the trigger type
  -- Call the appropriate trigger handler (level/coordinates/league)
  -- Return locations array or error string
end

-- Level triggers support string or array of level names:
local function levelTriggerList(trigger, locations)
  if type(trigger.level) == 'string' then
    -- Single level
  elseif type(trigger.level) == 'table' then
    -- Multiple levels
  end
end

Key Behaviors

  • Cluster cache is invalidated whenever onAnyMissionChanged fires
  • Quadtree uses quadtree.pointBBox() for spatial indexing
  • Locations are sorted by ID for deterministic clustering
  • mergeRadius of -1 (nil) means no clustering - each location uses its own radius
  • The league trigger type is a no-op - produces no locations (handled elsewhere)
  • Debug markers draw colored cylinders: red = out of range, green = in range and startable, gray = in range but not startable

See Also

  • missions/locationsDetector - Nearby Mission Location Detection - Related reference
  • missions/missionManager - Mission Lifecycle Manager - Related reference
  • missions/missionScreen - Mission UI Screen & Starting Options - Related reference
  • Gameplay Systems Guide - Guide

Progress

Reference for `gameplay_missions_progress`, the system that tracks mission attempts, aggregates progress, manages leaderboards, computes star rewards, and formats progress data for the UI.

Unlocks

Reference for `gameplay_missions_unlocks`, which evaluates start/visible conditions, manages unlock dependencies between missions, and computes mission ordering depth.

On this page

Module Exports (M)Start Trigger TypesMission ClusteringMerge AlgorithmLocation Object StructureHow It WorksKey BehaviorsSee Also