Learn how to use Lua scripts in DCS World missions with triggers, script files, DCS APIs, scheduling, debugging and multiplayer caveats.
Use Lua in a DCS World mission by adding a Mission Editor trigger, then choosing DO SCRIPT for short code or DO SCRIPT FILE for a .lua file. Run loaders at mission start, call DCS's mission-scripting API, and check dcs.log for errors. File-based scripts are embedded in the saved .miz mission.
How do I add a Lua script to a DCS mission?
The safest setup is to load a separate Lua file through a MISSION START trigger and initialise it immediately afterwards.
- Create the script: save a plain-text file such as
mission_logic.lua, preferably as UTF-8 without unusual formatting or typographic quotation marks. - Give it a namespace: avoid scattering generic global names through the mission. A simple starting pattern is
MyMission = MyMission or {}; function MyMission.start() trigger.action.outText('Mission script loaded', 10) end. - Add a trigger: in the Mission Editor, create a
MISSION STARTtrigger with no required condition. Add aDO SCRIPT FILEaction and select the Lua file. Our Mission Editor trigger and flag guide explains the surrounding interface and trigger logic. - Call the initialiser: add a second action in the same trigger, after the file action, using
DO SCRIPTwithMyMission.start(). Top-level code in the file runs while it loads, but an explicit start function makes load order clearer. - Save and test the mission: DCS packages the selected script into the saved
.miz. If the source file changes later, refresh or reselect it in the file action and save the mission again; an existing mission package does not automatically acquire every external edit.
For one or two commands, entering code directly in DO SCRIPT is quicker. Use a file once the script has functions, event handlers or enough logic to need proper editing and version control.
Which DCS trigger should run the script?
Use MISSION START for libraries and setup, ONCE for a single conditional action, and SWITCHED CONDITION when the same condition may become true again.
| Trigger or action | Best use | Main caveat |
|---|---|---|
MISSION START | Loading files, defining functions and registering event handlers | Some mission objects or dependent systems may need a short scheduled delay before use |
ONCE | Running code the first time a condition is met | It will not run again if the condition later resets |
SWITCHED CONDITION | Repeating an action each time a condition changes from false to true | The script must tolerate being called more than once |
CONTINUOUS ACTION | Logic that genuinely must repeat while a condition remains true | Easy to create duplicate handlers, repeated messages or unnecessary processing |
DO SCRIPT FILE | Libraries and substantial mission logic | The embedded copy must be refreshed after source changes |
Load dependencies before files that call them. When ordering matters, put the file actions and initialisation call in one trigger in the required sequence rather than relying on several separate start triggers.
How does Lua control a DCS World mission?
DCS exposes mission objects, events, triggers and timers through its own Lua API.
trigger.actiondisplays messages, sets flags and performs supported mission actions.trigger.miscreads user flags and information such as trigger zones.Group,Unit,Airbaseandcoalitionfind and inspect simulation objects.timerschedules functions without using a constantly firing trigger.world.addEventHandlerreceives events such as births, take-offs, landings, hits and deaths.env.info,env.warningandenv.errorwrite diagnostic entries to the DCS log.
Write for the Lua runtime embedded in DCS rather than assuming newer standalone Lua features or third-party modules are present. Object and group names are case-sensitive, and a lookup such as Group.getByName('CAP-1') can return nil if the name is wrong or the object no longer exists.
How do scripts communicate with Mission Editor triggers?
User flags provide the simplest bridge between Lua code and ordinary Mission Editor conditions.
Set a flag from Lua with trigger.action.setUserFlag('101', 1), then use a flag condition in the editor to activate another group or trigger a message. Read it in Lua with trigger.misc.getUserFlag('101'). This keeps routine activation logic visible to mission authors instead of burying the entire mission inside one script.
Zones, flags, messages and aircraft events can also be combined into interactive instruction logic; our guide to building custom simulator lessons with DCS triggers covers that design pattern.
How do I run Lua code later or respond to events?
Use timer.scheduleFunction for delayed or repeated work and world.addEventHandler for simulation events.
A scheduled function receives its argument and scheduled mission time. Returning another absolute mission time schedules its next run; returning nothing stops it. For example: local function tick(arg, time) env.info('Mission tick'); return time + 10 end; timer.scheduleFunction(tick, nil, timer.getTime() + 1).
An event handler is a table containing an onEvent function registered with world.addEventHandler. Check the event ID before accessing its fields because not every event has an initiator, target or weapon. Register each handler only once unless duplicate callbacks are deliberate.
Where should DCS mission Lua files go?
A mission Lua source file can live anywhere convenient while authoring because DO SCRIPT FILE embeds the selected copy into the .miz package.
It does not need to be placed in the DCS installation, the Mods directory or Saved Games\DCS\Scripts. Those locations serve different types of modifications and integrations. An embedded mission script also travels with the mission to a multiplayer server, so players do not install it separately.
Mission scripts run in a restricted environment. File-system and operating-system facilities such as io, lfs or arbitrary module loading may be unavailable or sanitised. We do not recommend weakening that sandbox by editing core DCS files: it creates a security risk, can be reverted by updates and makes the mission dependent on a specially configured host.
Why is my DCS Lua script not working?
Most DCS Lua failures come from syntax errors, stale embedded files, incorrect object names or code running before its dependencies are ready.
- Check the log: use a distinctive line such as
env.info('[MYMISSION] script loaded'), then inspectSaved Games\DCS\Logs\dcs.login the active DCS profile. Search for your prefix,ERROR SCRIPTINGor the reported Lua line. - Guard object lookups: an “attempt to index a nil value” error often means a group name is misspelt, the unit has been destroyed or the object is not available at that point.
- Confirm load order: “attempt to call global … (a nil value)” usually means the file defining that function failed or loaded after the caller.
- Refresh the embedded file: saving the external
.luaalone may leave the mission using its earlier packaged copy. - Return the next timer time: a scheduled callback runs only once unless it returns the absolute mission time for its next invocation.
- Avoid duplicate registration: a switched or continuous trigger can add the same world event handler repeatedly, causing every event to be processed several times.
- Delay object-dependent setup: if code fails only at mission start, schedule that portion shortly after mission time begins rather than delaying the entire library load.
When an established script library stops after a DCS update, test a minimal mission without unrelated add-ons, inspect the first Lua error rather than the later cascade, and follow our DCS Lua and mod compatibility checks.
Do DCS mission scripts work in multiplayer and save data?
Mission Lua works in single-player and multiplayer, but multiplayer mission logic runs under the host or dedicated server's authoritative mission environment.
Use DCS message functions intended for all players, a coalition or a group when presenting output; do not assume code can access arbitrary files on each client's computer. Embedded scripts require no separate client installation, although every module, map and asset used by the mission still follows DCS's normal ownership and server rules.
Lua globals and user flags last only for that running mission instance. Restarting or reloading the mission resets them, while normal disk writing is blocked by the sandbox. If the real requirement is a campaign state that survives sessions, use a deliberate persistence design rather than treating an in-memory Lua table as a save file; our explanation of DCS mission progress and persistence options covers those limits.