Open Beta dcs-mcp 0.9.18 is out. See what’s new in the changelog. Join the Discord →
Reference

Capabilities

Every tool in dcs-mcp — all 171 of them, generated straight from the server's own tool definitions, so this reference is always current. Names are the exact tool names Claude calls; you never type them yourself, but knowing the surface tells you what you can ask for.

Positions: every position-taking tool accepts either geographic lat/lon or theater-native x/y — use whichever you have. Sessions: tools operate on an open mission via the mission_id returned by open_miz.

Mission authoring & structure15 tools

Create, open, save, and inspect missions. Session-based: open_miz hands back a mission ID that every other tool takes, and save_miz writes the real .miz atomically.

Create a new blank mission on the given terrain.

Details · 1 parameters (1 required)
WHAT GOES IN IS THE USER'S. What they did not ask for stays at the Mission Editor's default: a flight AI, unarmed, with waypoint 0 only; no briefing, goals or triggers. Offer the rest in your reply, or ask when the choice would change what they get. mission_authoring_guide lists the questions to check. terrain is case-insensitive. Examples: 'Caucasus', 'PersianGulf', 'Syria', 'MarianaIslands', 'Nevada', 'Normandy', 'TheChannel', 'SinaiMap', 'Kola', 'Afghanistan', 'GermanyCW', 'Iraq'.
ParameterTypeDescription
terrainstringrequired

Open an existing .miz file and return a session handle.

Details · 1 parameters (1 required)
The session ID returned here is required by every other tool in this server. Sessions live in memory until close_miz is called or the server exits -- save_miz does NOT close the session. path: absolute path, or a bare filename ("strike.miz") which is looked up in the user's DCS Missions folder. %USERPROFILE% and other environment variables are expanded. Do NOT guess a path: if you do not know where the mission is, pass the bare filename and the error will name the folder and list what is actually in it. As the Mission Editor's load, it keeps the triggers and goals as the file has them, a condition, action or goal rule naming something not in the mission included. validate names each one; save_miz removes each, as the editor's save does, and lists it under `repaired`. `repaired` here lists what the open filled in.
ParameterTypeDescription
pathstringrequired

Save the session to disk.

Details · 2 parameters (1 required)
Atomic write (temp file + rename). If path is omitted, saves back to the path it was opened from. Required for new_miz sessions (no source path). path: absolute path, or a bare filename ("strike.miz") which is written to the user's DCS Missions folder so it appears in the Mission Editor's open dialog. %USERPROFILE% and other environment variables are expanded. The response reports the folder actually written to, and the Missions folder -- use those rather than asking the user where their missions live. As the Mission Editor's save, it removes from the triggers and goals a condition, action or goal rule naming something not in the mission, an OR that ends a trigger's conditions as the save begins, and a trigger left with no actions or with only OR conditions; `repaired` lists each, when there are any. The removals can leave a trigger's conditions, or a goal's rules, ending in OR, as the editor's save does, and the next save removes it; or leave a trigger with no conditions, which the editor keeps and which then fires unconditionally. `warnings` names each such trigger or goal, when there are any.
ParameterTypeDescription
mission_idstringrequired
pathstring | nulloptional

Drop the session from memory.

Details · 1 parameters (1 required)
Unsaved changes are lost.
ParameterTypeDescription
mission_idstringrequired

List all currently open sessions.

Get summary info about a session (theater, time, group counts).

Details · 1 parameters (1 required)
ParameterTypeDescription
mission_idstringrequired

Return a high-level summary of the mission.

Details · 1 parameters (1 required)
Useful as a first call when opening an unfamiliar .miz -- gives an overview of who/what is present without listing every group. Returns: theater -- terrain class name (e.g. "Caucasus") start_time -- ISO 8601 datetime, NO timezone. Mission local time as DCS stores it; the .miz format carries no zone, so none is invented here briefing -- {description, blue_task, red_task} (first 200 chars each) groups -- {blue: {plane, helicopter, vehicle, ship, static}, red: {...}, neutral: {...}} (counts per category) zones -- number of trigger zones triggers -- number of trigger rules weather -- {name, visibility_m, wind_ground_ms, wind_ground_dir, clouds_preset, clouds_density, fog, dust}
ParameterTypeDescription
mission_idstringrequired

Comprehensive read-only mission analysis with 25 checks.

Details · 3 parameters (1 required)
Checks performed: 1-3 Trigger condition cross-refs (missing group / unit / zone IDs) 4 Trigger action cross-refs (missing groups, units, zones, resources) 5 Goal condition cross-refs 6 Trigger sanity (conditions-less trigger fires unconditionally) 7 Vehicle group terrain slope (uses slope_threshold_deg) 8 Vehicle group surface type (water check) 9 Terrain data availability 10 Flight group route: no waypoints 11 Flight group route: single waypoint only (info -- as the Mission Editor places a flight) 12 Flight group route: takeoff/landing missing airdrome_id 13 AI-only mission (no player or client slots; info) 14 Empty mission 15 Duplicate group IDs 16 Waypoint lock-state invalid -- ED's three route-lock rules (no ETA-locked anchor; OR a waypoint with both ETA_locked=False and speed_locked=False and no ETA-locked brackets; OR every speed locked between two consecutive ETA-locked waypoints; DCS ME rejects the save in all three) 16b Time anchor unreachable (the locked-speed legs between two ETA-locked waypoints already consume the interval; DCS writes a negative speed and a backwards arrival time) 16c Derived speed above the airframe maximum (warning; a solved speed the aircraft cannot hold, so it arrives late) 17 Flight with no meaningful tasking (takeoff->land anchors only; info) 18 Ground-start flight with no Landing waypoint (no RTB point) 19 Flight with empty pylons on all units (info; tankers/AWACS exempt) 20 AI flight with a real route but no attack/engagement tasking (info; tankers/AWACS exempt) 21 Mission has no briefing description set (info) 22 Refueling type mismatch: boom-receptacle or probe-equipped aircraft present but no compatible tanker type (info) 23 Tanker/AWACS comms collision: two support aircraft share the same primary radio frequency (info) 24 Ground-group route surface: a vehicle group's waypoint sits over water, or a leg crosses water between two dry waypoints (warning; ground groups only -- flights/ships exempt; warn-not-block so amphibious crossings/bridges still save; uses the installed terrain data, skips with an info note if the theater is not installed) 25 Flight led by a human pilot (its first unit is a Client or Player) with waypoints above the terrain (info). For a human pilot a waypoint is a navigation reference rather than a flight command, so one off the deck shows in the cockpit as hanging in mid-air. Covers hand-built routes and flights whose crew was changed after the route was written; silent where the theater has no terrain data. detail: "summary" returns only issues + stats. "full" additionally includes decoded trigger list, group list, and goal list. slope_threshold_deg: slope (in degrees) above which a vehicle group placement is flagged (default 10.0, matching the Phase 9 placement tools). Trigger indices in issues messages and in the full-mode triggers list are 0-based, matching add_trigger / modify_trigger / delete_trigger. Returns dict: verdict "clean" | "warnings" | "errors" | "empty_mission" theater theater name string detail echo of the detail parameter issues list of {severity, check, message} stats {group_count, unit_count, groups_by_category, trigger_count, zone_count, goal_count, resource_count} (full only): triggers list of {trigger_index, decoded} (0-based index) groups list of {id, name, category, coalition, unit_count} goals list of {side, index, score, conditions}
ParameterTypeDescription
mission_idstringrequired
detailstringoptionalDefault: "summary".
slope_threshold_degnumberoptionalDefault: 10.0.

Run basic sanity checks against the mission.

Details · 1 parameters (1 required)
Returns {ok: bool, warnings: [...], errors: [...], group_count, unit_count, farp_services: [...]}. FARP SERVICES OUT OF REACH -- a REPORT of what each FARP provides, not a verdict on it. DCS serves a FARP from every unit of its side within 150 m of the pad, whichever FARP it was built for, so a truck between two FARPs serves both -- that is DCS's rule, not a limit of this tool. Most services have two providers, a vehicle and a FARP static, and EITHER ONE within 150 m provides the service -- flown for fuel: the Fuel Depot static alone, or the tanker alone. A service is reported when NONE of its providers is within 150 m while one that could provide it sits beyond (attributed to the nearest pad of its side within 500 m): a tanker at 200 m, with no Fuel Depot, gave no fuel. It is reported PER SERVICE: a FARP can have fuel and no rearm. A FARP with only some services is a valid choice; the finding says what it provides, and what to move if that is not what was meant. Each finding is in `farp_services` as {check, severity, farp, coalition, service, units: [{name, type, distance_m}], message}, and its message is in `warnings`. A warning does not change `ok`. Not reported: a service that was never provided -- no unit for it anywhere near the pad. See farp_services.py for why. A FARP HOLDING MORE AIRCRAFT THAN IT HAS PADS is an error: DCS parks one aircraft per pad, and a Client slot left without one cannot be flown. The 4-pad FARP has four pads; a single pad or an invisible FARP, one. A CLIENT OR PLAYER GROUP ON A FREQUENCY ITS FREQUENCY BOX MARKS INVALID is an error: the Mission Editor will not save a mission with one ("Invalid frequency"). It checks a group whose first aircraft is Client or Player, against that aircraft type's bands. WAREHOUSE AIRCRAFT DCS WILL NOT LOAD. DCS needs a wsType on every warehouse aircraft entry. open_miz fills in the ones it can, as the Mission Editor does; an entry it cannot -- a type DCS does not ship, or one under the wrong category -- is named in `warnings`, since that aircraft is not in the warehouse when the mission runs. WHAT NAMES SOMETHING THAT IS NOT IN THE MISSION is in `warnings`: a waypoint linked to a unit that is gone, a task naming a group or unit that is gone, and a trigger zone attached to a unit that is gone. delete_group clears what the editor clears; a file made elsewhere can still carry these. WHAT save_miz WILL REMOVE FROM THE TRIGGERS AND GOALS is in `warnings`, by the save's own test: a trigger condition or action, or a goal rule, naming a group, unit, trigger zone, file, triggered action, template or drawing that is not there, or one this DCS's Mission Editor does not define; a goal's last OR; and a trigger it removes whole. open_miz keeps the triggers and goals as the file has them, as the Mission Editor's load does, so a file can carry these. save_miz removes them, as the editor's save does, and lists them under `repaired`. A TRIGGER WHOSE CONDITIONS END IN OR, which is not valid Lua, is in `warnings`; the next save_miz removes that OR. A GOAL HOLDING AN OR RULE is in `warnings`: the Mission Editor's goals panel cannot make one. A goal's index is its place among its side's goals, from 0, as get_goal takes it. TRIGGER ZONES SHARING A NAME are in `warnings`: the Mission Editor renames all but the first when it opens the file, so what finds a zone by that name finds only one. The zone tools refuse a taken name; a file made elsewhere can still carry these.
ParameterTypeDescription
mission_idstringrequired

Return a staged checklist of questions for authoring a complete DCS mission.

Details
Intended to be consulted at the start of and during a mission-building task. Advisory only -- nothing here blocks, enforces, or prevents saving. Takes no arguments; returns pure static content. Returns a dict with: purpose -- what the guide is for how_to_use -- short instruction for working through the stages stages -- ordered list of {stage, title, questions} objects; each question has "q" (the question) and "why" (the failure mode if skipped) notes -- cross-cutting reminders

Build a companion _diag.miz with an F10 diagnostic overlay.

Details · 2 parameters (1 required)
Reads the open source mission, runs mission_report findings analysis, and writes a separate .miz file with diagnostic drawings on the F10 map. The source mission (mission_id) is NOT modified. All drawings go on the standard Author layer. DCS supports exactly five layer names {Red, Blue, Neutral, Common, Author}; custom-named layers cause the Mission Editor to crash on load. Category is indicated by drawing name prefix and color: GRP:/GRP_LBL: -- group markers, coalition-colored ROUTE:/WP:/WP_LBL: -- route polylines and waypoint markers PROB:/PROB_LBL: -- issue markers (red=error, amber=warning) ZONE:/ZONE_LBL:/TRIG_SUMMARY -- trigger zones and text summary output_path: where to write the diag .miz. If omitted, derived from the source path as <dir>/<basename>_diag.miz. A bare filename goes to the DCS Missions folder; %USERPROFILE% and other variables are expanded. The response names the folder written to. Required if the source mission has never been saved. Issues with no map position are NOT drawn; they appear in the return value "notes" list so they are not silently lost. Returns: output_path path to the written diag .miz source_path source mission path (None if never saved) drawing_layer standard layer name all drawings were placed on drawing_count total drawings added findings_summary {verdict, error_count, warning_count} notes list of informational strings
ParameterTypeDescription
mission_idstringrequired
output_pathstring | nulloptional

Read an arbitrary value from the mission dict by dotted path.

Details · 2 parameters (2 required)
Example paths: coalition.blue.country[0].plane.group[3] weather.clouds.density forcedOptions Returns the raw value (dict / list / scalar) at that path. A valid path that resolves to a falsy value (0, false, "", {}, []) returns that value normally; failures (missing key, out-of-range index, wrong index type) raise ValueError with the full path, the failing component, the failure type, and -- for the common [0] case -- a hint that DCS Lua tables are 1-indexed. A trigger or goal entry from an opened file that names a condition or action this DCS's Mission Editor does not define is shown as the file holds it; its compiled string is the file's own, or left out when the file has none (save_miz removes such an entry, as the Mission Editor does). A read under trig, trigrules, goals or result then returns {"value": <the value>, "warnings": [...]}, naming each such entry.
ParameterTypeDescription
mission_idstringrequired
pathstringrequired

Write a value to the mission dict at the given dotted path.

Details · 3 parameters (3 required)
Supported top-level sections: weather -- clouds, wind, fog, visibility, dust, etc. forcedOptions -- cockpit indicators, G-effects, etc. triggers -- trigger zones (zones sub-key) groundControl -- ground control roles goals -- mission goals/conditions The path must start with one of those section names, e.g.: weather.enable_fog weather.clouds.density forcedOptions.cockpitStatusGreenMessages NOT supported (use typed tools instead): coalition.* -> list_groups / move_group / set_payload / etc. date / start_time / map -> not exposed here Values are JSON-typed: pass numbers as numbers, booleans as booleans, null as null. Text is read as JSON first, so "5" is written 5 and "true" true. null -- or the text "null" -- writes the key as nil, which Lua reads as no key at all: it does not write an empty or zero value. Two keys cannot be held as nil, weather.halo.preset and forcedOptions.labels: null is refused there and nothing is written. A read-back check reports if the write did not take effect (e.g., preset interference) -- and a path the section does not keep at all, or a key inside an object value that it does not keep, is REFUSED, with the section left as it was: there is nowhere to hold it, so it could never be saved. Errors are reported with the full path, the failing component, and the failure type. A reload failure (a value whose shape the mission loader rejects) is wrapped with type name, message, and traceback so the originating problem is legible. On an opened file holding a trigger or goal entry this DCS's Mission Editor does not define (validate names each), a write under goals is refused, naming such an entry, when the entry carries no compiled Lua of its own; when it carries its own, the write is made, but a write to an undefined goal entry itself is refused. A write anywhere else is made as on any other file (save_miz removes the entry, as the Mission Editor does).
ParameterTypeDescription
mission_idstringrequired
pathstringrequired
valueanyrequired

What the mission enforces on its players -- the Mission Editor's

Details · 1 parameters (1 required)
MISSION OPTIONS panel. An option the mission ENFORCES applies to everyone who flies it, whatever their own DCS settings. One it does not enforce is left to each player. Returns: enforced {option: {value, choice}} -- `choice` is the editor's word for the value of a list option left_to_the_player the options this mission does not enforce other_keys_in_the_file anything else the mission's forcedOptions table holds, as stored. Present only when there is something. f10_view_is_extended present, and true, only when the F10 view is the editor's Extended. f10_view_roles with Extended: {role: {view, value, layers}} for its six roles, in the editor's order. `layers` is {kind: {side: true or false}} -- whether that role sees that side's units of that kind on the F10 map. The options and what each takes are listed under set_mission_options.
ParameterTypeDescription
mission_idstringrequired

Enforce Mission Options on everyone who flies the mission, or stop

Details · 3 parameters (1 required)
enforcing them -- the Mission Editor's MISSION OPTIONS panel. options: {option: value}. A value ENFORCES the option at that value. null STOPS enforcing it and leaves it to each player's own setting. Options you do not name stay as they are. Every name and value is checked first: if one is wrong, nothing is changed. ON OR OFF (true or false): crash_auto_recovery, external_views, simplified_flight_model, immortal, unlimited_fuel, unlimited_weapons, easy_communication, radio_assists, unrestricted_satnav, padlock, wake_turbulence, random_system_failures, g_warm_up_in_the_air, mini_hud, cockpit_visual_recon_mode, f10_map_user_marks, cockpit_status_bar, battle_damage_assessment, supercarrier_deck_crew, supercarrier_1mc ONE OF A LIST (the editor's word for it, in any case): f10_view Map Only, My A/C, Fog of War, Allies Only, All, Extended labels FULL, ABBREVIATED, SYMBOL ONLY, DOT NEUTRAL, NO LABELS spotting_dots OFF, AUTO, 1 pixel, 2 pixels g_effects None, REDUCED, REALISTIC civ_traffic OFF, LOW, MEDIUM, HIGH A NUMBER: birds 0 to 1000 in steps of 10, as the editor's slider moves ENFORCING "OFF" IS NOT THE SAME AS NOT ENFORCING. unlimited_fuel=false makes fuel limited for everyone; unlimited_fuel=null lets each player keep their own setting. THE EXTENDED F10 VIEW gives each of six roles its own view and its own choice of which units it sees. f10_view="Extended" chooses it; a mission that did not have it starts with every role on All, seeing everything, as in the Mission Editor. f10_view_roles then sets the roles: f10_view_roles: {role: {view, layers}} -- either or both, for any of pilot, jtac_operator, tactical_cmdr, observer, spectator, airboss_lso. view Map Only, My A/C, Fog of War, Allies Only or All layers {kind: {side: true or false}} -- true shows that side's units of that kind to the role, false hides them. Kinds: planes, helicopters, ground, naval, weapons. Sides: allies, enemies, neutral. A role or a layer you do not name stays as it is. Example, pilots on Fog of War who do not see enemy aircraft: {"pilot": {"view": "Fog of War", "layers": {"planes": {"enemies": false}, "helicopters": {"enemies": false}}}} f10_view_roles is refused unless the F10 view is Extended, or is set to it in the same call. Choosing any other f10_view removes the roles' settings, as the Mission Editor does. The layers are stored for every view; the editor greys them out for Map Only and My A/C, and all but the allies for Allies Only. Returns what get_mission_options returns, and `changed`: the options this call changed.
ParameterTypeDescription
mission_idstringrequired
optionsobject | nulloptional
f10_view_rolesobject | nulloptional

Groups & units20 tools

Planes, helicopters, ships, ground vehicles, and static objects — add, modify, clone, move, delete, and query them anywhere in the mission.

Add a new ship group to the mission.

Details · 15 parameters (6 required)
coalition: "blue" | "red" | "neutral" country: DCS country name -- must exist in the mission ship_type: DCS type string, e.g. "PERRY", "TICONDEROG", "KUZNECOW" Use list_unit_types(category="ship") to find valid ids. name: group name (must be unique in the mission) position: spawn position -- {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. count: number of ships in the group (1-inf) heading: initial heading in degrees (0 = north; default 0) terrain_check: refuse placement on dry land (default true). Every hull in the group is checked, not just the first. Pass false to override -- e.g. a quayside berth the 100 m terrain grid classifies as land. speed_knots: speed in knots on the first waypoint (default 0, as the Mission Editor places a ship). The next waypoint you add takes the editor's 50 km/h after a stopped start; add further waypoints via add_waypoint or set_route. skill: "average" (default) | "good" | "high" | "excellent" | "random" Returns {group_id, name, unit_ids, unit_names, lat, lon}.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
ship_typestringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
countintegeroptionalDefault: 1.
headingintegeroptionalDefault: 0.
speed_knotsnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "average".
terrain_checkbooleanoptionalDefault: true.
hiddenboolean | nulloptional
hidden_on_plannerboolean | nulloptional
hidden_on_mfdboolean | nulloptional
late_activationboolean | nulloptional

Add a new ground vehicle group to the mission.

Details · 19 parameters (6 required)
coalition: "blue" | "red" | "neutral" country: DCS country name -- must exist in the mission vehicle_type: DCS type string, e.g. "M-1 Abrams", "ZSU-23-4 Shilka" Use list_unit_types(category="vehicle") to find valid ids. "Train" places a train -- see A TRAIN, below. name: group name (must be unique in the mission) position: spawn position -- {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. clear_trees: an AIR-DEFENCE or radar group always clears the trees at its footprint, and false is refused for one. Any other group clears only when asked: true. A clear places one trigger zone around the group, with a trees-only RemoveSceneObjects action for it in the mission's "Tree clearing" trigger. (Ruled 16 Sep 2026.) count: number of vehicles (1-inf, DCS handles large groups) heading: initial heading in degrees (0 = north, 90 = east; default 0) formation: "line" (default) | "star" | "rectangle" | "scattered" | "vee" "line" is what DCS's Mission Editor does when a group's unit count is raised: a column, each vehicle 40 m behind the one before along `heading`. The Mission Editor has no other ground formation; the other four are this server's own spacing (20 m) and are not DCS features. A vehicle other than the first that lands on water is moved to the nearest land, as the Mission Editor does, and "units_moved_to_land" says which; the first on water is refused unless the type can be on water. Both only with terrain_check on: terrain_check=false skips the water rules as well as the slope check. move_formation: "offroad" (default) | "onroad" "onroad" makes AI follow roads; "offroad" cuts cross-country. WHEN THE PERSON ASKS FOR A ROAD MOVE, pass "onroad": every waypoint added afterwards keeps that action (as the Mission Editor does), so the whole route travels by road. It sets the ACTION only. DCS moves an On Road group onto its own road network when the mission runs, and the Mission Editor does the same when the mission is saved there, drawing the road route as it does. So the group does not have to be on a road; placing it and its waypoints near the road you want helps it take that one. This server has no road network: sample_terrain reports a ROAD surface class, but that is a coarse 100 m mask, not ED's roads. skill: "average" (default) | "good" | "high" | "excellent" | "random" terrain_check: validate slope at the spawn point and under every vehicle (default true). Raises ValueError if any slope exceeds slope_threshold_deg. Pass false to skip (e.g. for wrecks or deliberate steep placement). slope_threshold_deg: slope limit in degrees for terrain_check (default 10). Returns {group_id, name, unit_ids, unit_names, lat, lon, units_moved_to_land, flags_applied (the group checkboxes set, e.g. hidden, late_activation)} plus a "terrain" key when terrain_check=True. The "tree_clear" key carries the wired clear ({zone_id, zone_name, radius, trigger_index}) or null when no clear happened. Route starts with one waypoint at the spawn position. Add further waypoints via add_waypoint or set_route. A TRAIN. vehicle_type="Train" with wagons=[...] places a train: one unit, whatever its length, so count stays 1. `wagons` is its cars in order from the front, each a railway-car type -- list_unit_types(category="train") lists the locomotives and the wagons. Every train in DCS's own missions leads with a locomotive. Its waypoints are all "On Railroads"; add_waypoint adds them. It starts at 20 km/h, as in the Mission Editor, and a new waypoint takes the speed of the one before it unless you give one. formation, move_formation, clear_trees and the terrain check do not apply to a train. DCS PUTS A TRAIN ON THE RAILS ITSELF when the mission runs: on the railway nearest each waypoint, HOWEVER FAR THAT IS. This server has no railway data. It cannot tell you where the rails are, nor whether two waypoints are joined by rail -- and a train placed away from a railway is moved to one, with nothing in the file to show it. Give positions on a railway you know. Afghanistan and the two Mariana Islands maps have no railway, and a train is refused there. A train's reply carries `train`: its wagons and this caution; it has no terrain, tree_clear or units_moved_to_land.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
vehicle_typestringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
clear_treesboolean | nulloptional
countintegeroptionalDefault: 1.
headingintegeroptionalDefault: 0.
formationstringoptionalDefault: "line".
move_formationstringoptionalDefault: "offroad".
skillstringoptionalDefault: "average".
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
hiddenboolean | nulloptional
hidden_on_plannerboolean | nulloptional
hidden_on_mfdboolean | nulloptional
late_activationboolean | nulloptional
wagonsstring[] | nulloptional

Place a Mission Editor group template by name: one of DCS's own, or

Details · 11 parameters (5 required)
one you saved in the editor. list_templates lists them. It is placed as the Mission Editor places one: as one group, with the template's origin on `position` -- its first unit, in every template DCS ships -- and every unit where the template puts it from there, turned by `heading`. template: the template's name, as list_templates gives it. One you saved under the name of one of DCS's own, and different from it, is "<name>-copy", as in the editor's own list. coalition: "blue" | "red" name: group name (must be unique in the mission) position: {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. country: the country the group is placed under. Omitted => the country the template was saved for, as in the editor, which lists a template only under its own country. That country must be on `coalition` in the mission. A country that does not field one of the template's types is refused, as for any group. heading: degrees to turn the whole template by (default 0: as saved) skill: "average" | "good" | "high" | "excellent" | "random" for every unit. Omitted => each unit's own from the template. clear_trees: for a template of ground vehicles, as add_vehicle_group's: one with an air-defence or radar unit always clears the trees around it; any other only when asked (true). terrain_check: refuse a ground unit on water, or a ship on land, and check the slope under a ground template (default true). slope_threshold_deg: slope limit in degrees (default 10). A template saved from a vehicle or a ship group is placed. One saved from a plane or helicopter group is refused: an aircraft group needs an airfield or an air start, an altitude and a task, which a template does not hold. Returns {group_id, name, category ("vehicle" | "ship"), unit_count, unit_ids, unit_names, template {name, kind, source ("shipped" | "yours"), country, unit_count}, country, country_note, footprint_m, lat, lon}, plus "terrain" when terrain_check is on, and "tree_clear" (ground) or "waypoint0" (ships). country_note says when the group was placed under a country other than the template's; null otherwise. Waypoint 0 is at `position`, at 20 km/h, as the editor sets it for a template; add the route with add_waypoint or set_route.
ParameterTypeDescription
mission_idstringrequired
templatestringrequired
coalitionstringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
countrystring | nulloptional
headingnumberoptionalDefault: 0.0.
skillstring | nulloptional
clear_treesboolean | nulloptional
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.

List the Mission Editor's group templates: DCS's own, and the ones you

Details · 2 parameters (0 required)
saved in the editor. add_template_group places one by name. kind: "vehicle" | "ship" | "plane" | "helicopter" -- only templates saved from that kind of group. Omitted => all. country: only templates saved for this country. Omitted => all. Returns: templates one entry per template, by name: name what to give add_template_group's `template` kind the kind of group it was saved from placeable true for a vehicle or ship template; add_template_group does not place an aircraft template source "shipped" (DCS's own) or "yours" country the country it was saved for; the editor lists a template only under that country unit_count units each type in it, with how many: [{type, count}] count, shipped_count, yours_count files {shipped, yours}: the two files read, or null where there is none. Yours is Saved Games\DCS\MissionEditor\ templates.lua, where the editor saves them. skipped_unknown_units how many templates were left out, from either file, because a unit type in them is not one this install knows -- the editor leaves them out too reason only when no template could be read, and why A template you saved under the name of one of DCS's own, and different from it, is listed as "<name>-copy", as in the editor's own list.
ParameterTypeDescription
kindstring | nulloptional
countrystring | nulloptional

Add a static object (building, FARP, vehicle wreck, ship, etc.).

Details · 11 parameters (4 required)
country: DCS country string, e.g. "Russia", "USA", "Germany". Must already exist in the mission. static_type: DCS type id string -- use list_unit_types(category="static") to find valid ids. Also accepts plane/heli/vehicle/ship type ids for wrecks (the category is taken from the type). A heliport (FARP, SINGLE_HELIPAD, Invisible FARP, FARP_SINGLE_01, Oil rig, Gas platform) gets a radio, AM, returned under "radio": a frequency unique in the mission, and a callsign unique while one of DCS's ten heliport callsigns is free -- past ten, it shares callsign 1, with a warning. A heliport or a warehouse static (Warehouse, Tank, .Ammunition depot ...) gets a warehouse, as in the Mission Editor; change it with set_warehouse_properties. position: {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. heading: facing direction in degrees (0 = north, 90 = east) name: name for the static group/unit -- unique in the mission; a name another group has is refused. Defaults to static_type with the new group id appended (the first free -N if another group has that). dead: start the object already dead/destroyed (default false) terrain_check: validate the placement surface (default true). Which rule applies depends on what you are placing: a SHIP type id must be on water, and everything else must be on land with a slope within slope_threshold_deg. Pass false to skip (a deliberate cliff-face placement, or a quayside berth the 100 m grid calls land). slope_threshold_deg: slope limit in degrees for terrain_check (default 10). Returns the new group id, unit id, name, and position, plus a "terrain" key when terrain_check=True.
ParameterTypeDescription
mission_idstringrequired
countrystringrequired
static_typestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
namestring | nulloptional
deadbooleanoptionalDefault: false.
effect_presetinteger | nulloptional
effect_transparencynumber | nulloptional
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.

Append one or more units (a "wingman") to an EXISTING group.

Details · 12 parameters (2 required)
Mirrors the DCS ME's one-click "add unit": clones the group's LAST unit verbatim (type, skill, livery, payload, radio preset blocks, frequency, heading, flags) and changes only what must differ -- a fresh mission-wide unit id, an incremented name, and a deconflicted placement (plus, for aircraft, an incremented callsign and tail number). The route, group-level task, and group frequency are group-level and are NOT touched. A DIFFERENT TYPE, FOR GROUND AND NAVAL GROUPS: pass `unit_type` to add a unit that is NOT a copy of the last one -- a Ticonderoga into a carrier group, an ammo truck into a convoy. Omit it and the clone behaviour above is unchanged, which is what the editor's own one-click add does. Applies to plane, helicopter, vehicle, and ship groups. Static groups are not supported (use add_static). group_id: the group to grow (from list_groups / add_*_group). count: how many units to add (default 1). Each is deconflicted against the previous one. Optional per-unit overrides (omitted => cloned / auto): parking_ids: pin specific parking crossroad_idx values for airbase aircraft (one per added unit, in order); else free spots are auto-allocated. Loud error if a pinned spot is taken or invalid. position: override placement (ground vehicle / ship / air-start aircraft) -- {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}. Not valid for airbase aircraft (parking drives the position). skill: per-unit skill (same vocabulary as the create tools; "Client"/"Player" on any aircraft, as the Mission Editor allows; warned about on one no player can fly). payload: {pylon_number: clsid} for aircraft (validated; rejects invalid assignments). Omitted => cloned from the source. livery: livery id for the added unit(s); "" reverts to default. callsign: display callsign name for added aircraft (western callsign nations only; ignored with a warning for numeric-callsign nations). name: explicit unit name; only valid with count=1, and refused if another unit in the mission has it. terrain_check: refuse a placement the surface will not take (default true). A SHIP is refused on dry land; a VEHICLE is refused on water, shallow water included. Checked at the position the unit ACTUALLY lands on, which is not the group's -- a naval group spans kilometres and a trailing hull can beach while the lead floats. Aircraft are not surface-checked: parking and air starts are not a surface question. Pass false for a quayside berth the 100 m grid calls land, which is a real case rather than a hypothetical. unit_type: a DIFFERENT type for the added unit(s) -- vehicle and ship groups only. Omitted => the last unit's type is cloned. All `count` units get this type. WHY VEHICLE AND SHIP ONLY, AND IT IS ED'S ANSWER RATHER THAN A PREFERENCE. In DCS's own shipped missions, many vehicle and ship groups hold more than one type, and no plane or helicopter group ever does. ED mixes types freely on the ground and at sea -- one of its own ship groups is PERRY + TICONDEROG + Arleigh Burke, which is a carrier screen -- and NEVER in a flight. A flight is one airframe: group size limits, parking allocation, payload and callsign numbering all assume it. So a `unit_type` on a plane or helicopter group is refused and the refusal says what to do instead. A UNIT OF ANOTHER CATEGORY IS NOT REFUSED, IT IS UNREACHABLE. The mission format nests groups under country.<category>.group, so a group IS its category; there is no field in which a ship group could hold an aircraft. The type is validated against the group's own catalogue, which makes a cross-category request a wrong-catalogue error rather than a rule we invented. Aircraft spawned on a FARP/carrier pad (pad_group_id) are rejected: deck/pad spot placement cannot be verified offline. Add a separate flight with one of the sixteen task tools (pad_group_id=...). Returns {group_id, group_category, added_unit_ids, added_unit_names, allocated_parking, positions, callsigns (aircraft), total_unit_count, warnings}.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
countintegeroptionalDefault: 1.
parking_idsinteger[] | nulloptional
positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
skillstring | nulloptional
payloadobject | nulloptional
liverystring | nulloptional
callsignstring | nulloptional
namestring | nulloptional
unit_typestring | nulloptional
terrain_checkbooleanoptionalDefault: true.

Duplicate a group the way the Mission Editor's copy and paste does.

Details · 4 parameters (2 required)
What the clone gets, as ED's paste gives it: - new group and unit ids, and names: the source's name with its trailing -N replaced by the first free -N ("Aerial-1" -> "Aerial-2"), units "<group>-1", "<group>-2"...; new_name overrides the group's - aircraft: new tail numbers and callsigns, a Player slot becomes a Client slot, and datalink / voice-callsign / IFF ids re-derived - message subtitles and sounds get their own dictionary and resource keys; EPLRS a new id; a task naming a unit of the source group names the unit at the same place in the clone - a flight starting at an airfield, on a FARP pad or on a ship's deck: its first waypoint placed again, as the paste places it -- the ground's height there, and 150 km/h for a helicopter or 500 km/h for a plane -- not a changed altitude or speed copied from the source. Its landings keep theirs. - a warehouse static or a heliport: a warehouse of its own, the editor's default (everything unlimited, no suppliers) -- not its source's warehouse settings. Change it with set_warehouse_properties. - a FARP or heliport: its source's frequency and callsign, unchanged, as the paste leaves them; `warnings` says so. WHERE IT GOES: - a flight parked at an airfield takes free stands that fit at the SAME airfield (refused if there are too few); a runway start stays on its runway; a carrier-deck or FARP-pad start stays on its ship or pad. These cannot take offset_position. - anything else: offset_position places the lead unit there, or the clone goes 500 m east of the source. DCS's y is east. - refused, nothing changed, if a ship would be on land, a vehicle in water, or a ground-starting helicopter on steep or wet ground. A FLIGHT ON A FARP takes free pads of its own, one aircraft per pad, as the editor numbers them; refused, nothing cloned, if the FARP has too few free. Returns {group_id, name, coalition, category, unit_ids}, plus `parking` for a parked flight, `start` for an anchored one, `tree_clear` (the zone that clears an air-defence group's trees, else null), and `warnings` when something could not be done as ED does it, or a copied heliport shares its source's radio.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
new_namestring | nulloptional
offset_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,

Delete a group and all its units, plus anything auto-created with it.

Details · 2 parameters (2 required)
To base a flight at another airfield, carrier or FARP, don't delete and rebuild it: modify_waypoint on waypoint 0 with airdrome_id or pad_group_id moves it there, keeping its tasks, payload and group id. Placing a ground site can auto-create a tree-clearing trigger zone, with a RemoveSceneObjects action for it in the mission's "Tree clearing" trigger. Until 0.9.8 deleting the group left both behind: a zone named treeclear_<group> clearing forest for a site that was no longer there. A FARP built with create_farp takes the support trucks and statics built with it: they are deleted too, and listed in removed_with_farp. Only those, as create_farp recorded them -- never another group near the FARP -- and only in the session that built them: a FARP read from a file has no such record, and deleting it removes the pad alone, as the Mission Editor does. WHAT POINTED AT IT IS CLEARED, as the Mission Editor clears it: - another group's waypoint on one of its units -- a start or a landing on a deleted ship or FARP pad -- becomes a Turning Point with no link, pad or airfield; a static standing on a deleted ship is no longer tied to it - other groups' tasks stop naming it: Embarking and Disembarking, AttachTrailer, RecoveryTanker, ParatroopersDrop, a cargo plane's unit; a beacon, ICLS or Link 4 action on one of its units is removed - trigger conditions and actions, and goal rules, naming it or one of its units are removed, and a trigger left with no actions, or with only OR conditions, is removed with them. A trigger left with no conditions is kept, as the editor keeps it, and then fires unconditionally - a trigger zone attached to one of its units stays where it is, no longer attached What the editor leaves, this leaves too: an Escort, Follow or attack task aimed at it, and any other task holding its id. They are listed in references_left; change or remove them. Returns: deleted_group_id, name tree_clear - {zone_id, zone_name, trigger_index, trigger_removed}: the zone was removed and its action taken out of that trigger; trigger_removed is true when it was the trigger's last action and the trigger went too. Null if the group had none renumbered - TRUE when removing a trigger shifted the index of later triggers, i.e. the removed one was not last. Any trigger_index you are holding from an earlier call is then stale. Same hazard delete_trigger reports, for the same reason. warehouse - what went with it, as in the Mission Editor: warehouses_removed (the unit ids of a FARP's or ship's own warehouse), supplier_links_removed (other warehouses and airfields it supplied), and dynamic_templates_unlinked (aircraft entries that used the group as a dynamic-spawn template). removed_with_farp - the groups create_farp built with this FARP that went with it, each {group_id, name}; [] for any other group. unlinked_waypoints - the waypoints made Turning Points, each {group_id, name, waypoint_index, was_type} statics_unlinked - the statics no longer tied to a deleted ship, each {group_id, name} tasks_changed - each {group, where, task, field}: field is the one cleared, or "removed" for an action taken out triggers_changed - {conditions_removed, actions_removed, triggers_removed}: a removed condition or action is {trigger_index, comment, predicate}, a removed trigger {trigger_index, comment}; trigger_index is the trigger's index before this call goal_rules_removed - each {goal_index, side, predicate} zones_unlinked - each {zone_id, name} unit_links_removed - units of an opened file whose links to a deleted unit (linksSources, linksConsumers) were removed, each {unit_id, field} references_left - what still names it, one sentence each warnings - a trigger whose conditions now end in OR, a goal whose rules now end in OR, and a trigger left with no conditions, which fires unconditionally
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired

Apply a partial update to a group.

Details · 11 parameters (2 required)
Pass only the fields to change. Supported fields (all optional): name, hidden, late_activation, frequency, modulation, start_time, hidden_on_planner, hidden_on_mfd, uncontrolled. For anything outside this set use set_raw_lua. FREQUENCY AND MODULATION GO WHERE DCS READS THEM, which depends on the kind of group -- one call, and the same meaning for all of them: plane / helicopter the group ship every unit in the group (DCS stores hertz; pass MHz here as everywhere else) FARP / helipad the pad unit's heliport radio vehicle, or any other static REFUSED, and nothing is changed: ED never writes a frequency on those, so there is nothing for DCS to read. frequency is in MHz; modulation is 0 = AM, 1 = FM. The response's `radio` says what was written, and `written_to` says where. A plane or helicopter group's frequency is set as set_intra_flight_frequency sets it, as the Mission Editor's group box does: the group's modulation as the editor sets it, and each Client or Player aircraft's radio channels connected to it, listed in `channels_written`. A modulation given beside it is applied after, as choosing it in the editor's modulation box would, and the channels are written again at it. A modulation given alone does the same at the frequency the group already holds; on a group with no frequency yet, it sets the modulation only. A plane or helicopter group's frequency is checked as the Mission Editor checks a group's frequency box, against the bands of the type's own radio as ED's data gives them (its HumanRadio): a frequency outside them is written as asked, with a warning in `warnings` that the editor shows it as invalid. On a Client or Player group (one whose first aircraft is Client or Player) it is refused instead, and nothing is changed: the editor will not save a mission with it. Where the editor does not let the box be edited for a type, nothing is said, as the editor says nothing. The Mission Editor's group panel has six checkboxes. Five map to fields here: hidden -- Hidden On Map hidden_on_planner -- Hidden On Planner (briefing map) hidden_on_mfd -- Hidden On MFD (in-cockpit displays) uncontrolled -- Uncontrolled: aircraft spawn cold and inert until a START command. AIRCRAFT ONLY -- planes and helicopters. Setting it on a vehicle, ship or static group raises, because DCS has no such concept there and a silent no-op would look like it worked. late_activation -- Late Activation The sixth, Game Master Only, is NOT settable here: the server's group has no field for it. Called with no fields, this is a no-op that returns the group_id and an empty updated list without mutating the group.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
namestring | nulloptional
hiddenboolean | nulloptional
late_activationboolean | nulloptional
frequencynumber | nulloptional
modulationinteger | nulloptional
start_timeinteger | nulloptional
hidden_on_plannerboolean | nulloptional
hidden_on_mfdboolean | nulloptional
uncontrolledboolean | nulloptional

Apply a partial update to a unit's state fields.

Details · 12 parameters (2 required)
Pass only the fields to change. Supported fields (all optional): fuel -- internal fuel in kg. Use get_unit to read the current value. A new aircraft starts with the Mission Editor's fuel for its type: a full tank for most, a share for a few -- the Su-33 and C-130 half, the Su-27 59%, the P-51D 68% (the creating tool's reply says how much). Multiply by a fraction for partial fuel: 70% = fuel * 0.7. From 0 to the airframe's full internal tank (ED's MaxFuelWeight), the Mission Editor's range; above it is refused, naming it. flare -- flare count, from 0 to the airframe's own maximum (ED's charge total over the flare's charge size), the Mission Editor's range; above it is refused, naming it. chaff -- chaff count, the same, by the chaff's charge size. The top of flare and chaff is not checked for an airframe this server holds no countermeasure figures for (65 types: A-20G, B-17G, Bf-109K-4, C-101CC, C-101EB, C-47, Christen Eagle II, F-100D, F-117A, F-5E, F-86F Sabre, F-86F_FC, F4U-1D, F4U-1D_CW, Falcon_Gyrocopter, FW-190A8, FW-190D9, Hawk, I-16, Ju-88A4, Ka-27, KC-135, KJ-2000, L-39C, L-39ZA, La-7, MB-339A, MB-339APAN, MiG-15bis, MiG-15bis_FC, MiG-19P, MiG-25PD, MiG-25RBT, MiG-31, Mirage-F1AD, Mirage-F1AZ, Mirage-F1B, Mirage-F1BD, Mirage-F1BQ, Mirage-F1C, Mirage-F1C-200, Mirage-F1CG, Mirage-F1CJ, Mirage-F1CK, Mirage-F1CR, Mirage-F1CT, Mirage-F1CZ, Mirage-F1DDA, Mirage-F1ED, Mirage-F1EDA, Mirage-F1EQ, MosquitoFBMkVI, MQ-9 Reaper, P-47D-30, P-47D-30bl1, P-47D-40, P-51D, P-51D-30-NA, RQ-1A Predator, SpitfireLFMkIX, SpitfireLFMkIXCW, TF-51D, WingLoong-I, Yak-40 and Yak-52), nor chaff on the Ka-50, Ka-50_3, Mi-24V, Mi-26, Mi-8MT, SA342L, SA342M, SA342Minigun, SA342Mistral and UH-1H, whose chaff charge size ED gives as 0; those take any count from 0 up. gun -- gun ammo percentage (0-100; default 100) ammo_type -- gun ammunition belt, a 1-BASED INDEX into the airframe's own list. DCS stores the index, not the name: an F-16C writes 5 for "SAPHEI ... PGU", which is also ED's declared default for it. The list is PER AIRFRAME -- an F/A-18C's 1 and an F-16C's 5 are different belts -- and is ED's own, from the Mission Editor's unit table (a community mod's from its own files), so a value outside the airframe's range is refused WITH the list. Airframes DCS gives no list for accept any value unchecked, because refusing on a list we could not read would be our rule, not DCS's. skill -- "Average" | "Good" | "High" | "Excellent" | "Random" for AI, or "Client" for a human slot. Case-insensitive on input; stored as canonical PascalCase. "Player" is accepted as an alias and normalized to "Client". "Client" requires a flying unit (Plane / Helicopter), on any airframe, as the Mission Editor allows -- on one no player can fly in DCS, `warnings` says a player who takes it is put in spectator mode; the transition also populates the unit's radio preset block. The reverse transition (Client -> AI) clears the radio block so the .miz matches what the ME writes for AI slots. Making a group's first aircraft Client is refused while the group holds a frequency its type's frequency box marks invalid: the Mission Editor will not save a mission with that on a Client group. Set a valid frequency first. livery_id -- livery string (use list_liveries to find IDs; empty string resets to default). An aircraft's id this DCS install does not have for its type is written as given, with a `livery_not_installed` warning; a ground unit's or ship's id is written as given, unchecked. name -- unit name (must be globally unique in the mission) heading -- facing direction in degrees (0 = north) onboard_num -- an aircraft's board number, the number painted on it. Written exactly as given, as the Mission Editor writes what is typed: "060" stays "060", and a number given as 60 is written "60". Any text is taken, and two aircraft may share one, as in the editor. Planes and helicopters only. A STATIC OBJECT'S UNIT takes name, heading and livery_id only, as the Mission Editor's static panel edits them; any other field is refused. A static aircraft's livery is checked as an aircraft's, any other static's is not. Not supported here: pylons (use set_payload), position (use move_group). skill is validated BEFORE any field is applied, so a bad skill value leaves the unit untouched. Called with no fields, this is a no-op that returns the unit/group ids and an empty updated list. Returns {unit_id, group_id, updated: [field, ...]} plus the new values for each changed field.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
fuelnumber | nulloptional
flareinteger | nulloptional
chaffinteger | nulloptional
guninteger | nulloptional
ammo_typeinteger | nulloptional
skillstring | nulloptional
livery_idstring | nulloptional
namestring | nulloptional
headinginteger | nulloptional
onboard_numstring | integer | nulloptional

Move a group to a new position, as dragging it in the Mission

Details · 4 parameters (3 required)
Editor does. The group's units move together (their formation is kept) and its waypoint 0 moves with them. ITS OTHER WAYPOINTS STAY WHERE THEY ARE, as in the editor: a convoy keeps its objective, a carrier keeps its track and now sails to it from the new position. The response counts them under route_kept; move one with modify_waypoint. If rotate_to_heading is given (degrees), every unit is turned to face that heading. A SHIP OR FARP TAKES WHAT IS LINKED TO IT. A flight that starts on the moved carrier or FARP pad, or lands on it, is linked to it: its aircraft and those waypoints move with it -- and only those. Its racetracks, IPs and targets stay where they are. The response counts the flights under linked_flights_moved. A FARP MOVES WITH ITS WORKING SET. Moving a FARP pad also moves every group on the pad's side -- vehicles and statics -- that lies entirely within 150 m of the pad centre, by the same offset, because DCS serves a FARP only from units inside that radius. They are listed in `moved_with_farp` (empty for any other group). A group partly outside the radius, another FARP pad, and the other side's units stay where they are. A FLIGHT THAT STARTS AT AN AIRFIELD, OR ON A SHIP OR PAD, IS NOT MOVED BY POSITION: its position is its stand, runway or deck. It is refused, naming where it starts; to start it somewhere else, name the new place with modify_waypoint on waypoint 0 (airdrome_id, or pad_group_id). A flight that starts in the air or from the ground moves to the position given. Refused, nothing moved, where the editor would not place it: a ship on land, a vehicle in water, or a ground start on steep or wet ground.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
rotate_to_headingnumber | nulloptional

Return full detail for a single group: units, route, tasks, etc.

Details · 2 parameters (2 required)
Returns the group as the .miz stores it (its Lua structure). Useful when you need fields not surfaced by list_groups. AIRCRAFT GROUPS ALSO CARRY `_crewing` -- who flies this group, in the same shape the creation tools return. The leading underscore marks it as OURS rather than the file's, the same convention get_unit uses for `_group_id` and `_group_name`: everything else in this dict is the group as the file stores it, and this is not. It is computed from the units, so it tracks a conversion made after creation -- modify_unit(unit_id, skill="Client") on a unit here will show as crewed_by "human" the next time this is called. Vehicle, ship and static groups do not carry it: they cannot be crewed, and a block saying "AI" about a tank platoon reports a choice nobody made.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired

Return full detail for a single unit, including its parent group's id.

Details · 2 parameters (2 required)
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired

List groups in a mission, optionally filtered.

Details · 4 parameters (1 required)
coalition: 'blue' | 'red' | 'neutral' country: country name (e.g. 'USA', 'Russia') -- case-insensitive category: 'plane' | 'helicopter' | 'vehicle' | 'ship' | 'static'
ParameterTypeDescription
mission_idstringrequired
coalition"blue" | "red" | "neutral" | nulloptional
countrystring | nulloptional
category"plane" | "helicopter" | "vehicle" | "ship" | "static" | nulloptional

Find groups whose name contains the given substring (case-insensitive).

Details · 2 parameters (2 required)
Handy when you remember 'Huey' but not the exact name.
ParameterTypeDescription
mission_idstringrequired
name_substringstringrequired

Find groups within radius_m metres of a lat/lon point.

Details · 6 parameters (4 required)
Returns groups sorted by distance (nearest first). Each entry includes all fields from list_groups plus distance_m. coalition / category: optional filters (same as list_groups). radius_m: search radius in metres (e.g. 50000 for 50 km).
ParameterTypeDescription
mission_idstringrequired
latnumberrequired
lonnumberrequired
radius_mnumberrequired
coalition"blue" | "red" | "neutral" | nulloptional
category"plane" | "helicopter" | "vehicle" | "ship" | "static" | nulloptional

List all unit types available for the given category.

Details · 1 parameters (1 required)
category: 'plane' | 'helicopter' | 'vehicle' | 'ship' | 'static' | 'train' Returns a list of {id, name} dicts. The 'id' field is the DCS type string -- use it in set_payload, add_group, etc. 'name' is a more human-readable label where available (often the same as id). Country filtering is not implemented; this returns every type in ED's catalogue regardless of country availability -- EXCEPT the aircraft every flight builder refuses because no country in DCS fields them: 'F-14A' (use 'F-14A-135-GR-Early'), 'F-4E' (use 'F-4E-45MC') and 'SH-3W' (no fielded successor). They are omitted, not listed. Railway cars (locomotives and wagons) are not listed under 'vehicle': DCS moves them only as part of a train. category='train' lists them, each with `kind`, "locomotive" or "wagon" -- the cars add_vehicle_group(vehicle_type="Train", wagons=[...]) takes. A type a community mod adds -- read from your mod export -- also carries `mod`, the mod's name, and `mod_version`. A mission using one needs that mod installed to fly. default_task: the group task the Mission Editor gives this aircraft when it is placed -- the builder to use for a flight the user named without a task. human_cockpit: whether a player can fly this aircraft in DCS. A Client slot can be made on any aircraft, as the Mission Editor allows; on one with human_cockpit false, a player who takes it is put in spectator mode -- build it if the user asks, and tell them.
ParameterTypeDescription
categorystringrequired

This is the toolset path to choose a SPECIFIC callsign.

Details · 5 parameters (3 required)
The task tools and the macros otherwise assign a clean rotating default (Texaco -> Arco -> Shell for tankers, etc.); use this to override. name: the callsign name. It must be one the Mission Editor offers this country for this aircraft: the general names (Enfield, Springfield ... Pontiac) and the aircraft's own (Viper for an F-16, Hornet for an F/A-18, Texaco for a KC-135, and so on). Case-insensitive on input; stored as the editor spells it. A name it does not offer is refused, with the list. Countries whose flights take numbered callsigns in the editor (Russia and others) are refused. Where DCS gives no list for the aircraft, tanker and AWACS airframes take their role names and any other name is accepted with a warning. flight: flight number -- the first visible digit (e.g. the "2" in "Shell 2-1"). Callsign field [2]. first_unit: the lead unit's number -- the second visible digit (the "1" in "Shell 2-1"). Increments by one per unit across the group (lead = first_unit, wingman = first_unit + 1, ...). Callsign field [3]. So set_group_callsign(name="Shell", flight=2, first_unit=1) on a 2-ship produces "Shell21" (lead) and "Shell22" (wingman). Does NOT modify the pilot name or the group name -- those are independent fields. Returns: { "group_id": int, "callsign_name": str, # canonical, case-corrected "flight": int, "first_unit": int, "units_updated": int, "previous_callsign": dict, # lead unit's prior block (snapshot) "warnings": list[str], }
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
namestringrequired
flightintegeroptionalDefault: 1.
first_unitintegeroptionalDefault: 1.

Assign a country to a coalition, moving it if it is elsewhere.

Details · 3 parameters (3 required)
This is what the DCS Mission Editor's "assign countries to coalitions" screen does. Which countries sit on which side is a property of the mission, not a global constant: a mission opened from a file takes its roster from that file, so it can differ from the defaults. Read get_mission_info().mission.country_roster to see the current layout. country: DCS country name, case-insensitive (e.g. "Ukraine", "USA"). coalition: "blue" | "red" | "neutral". A new mission starts with the roster DCS's Mission Editor gives one: ED's default countries on blue and red (or the user's own defaults, if they saved some in the editor), and every other country on neutral -- Iraq, Afghanistan, Egypt, Insurgents among them. Move one to blue or red here before placing units for it. A mission opened from a file can leave some countries on no side at all; they are listed in get_mission_info().mission.country_roster.assignable, and assigning one here brings it into the mission. Returns added_to_mission=True when it did, and previous_coalition=None, since it was on no side rather than moved from one. Units move with the country -- they belong to it. Moving a country with groups moves those groups to the new side. Moving a country to "neutral" takes it out of play: neutral countries cannot own units, matching DCS itself (the Mission Editor omits them from the unit Country list). Write tools will then refuse to place units for it until it is assigned back to blue or red. Airbases are NOT changed. Airbase ownership belongs to a coalition, not to a country, so moving a country never seizes or surrenders an airbase -- that stays a deliberate act. diverged_airbases lists the airbases the other side holds after the move, for information: a flight may be based at any airfield, whichever side owns it, as in the Mission Editor. A FARP THE COUNTRY OWNS STOPS SERVICING AIRCRAFT, and the move is allowed anyway with a warning naming each one. A FARP's refuel, rearm, ground power, repair and ATC come from SPECIFIC VEHICLE TYPES parked within 150 m, and the required types are different per side -- blue wants an M978 and an M 818 and an M1043, red an ATMZ-5 and a Ural-4320T and a Ural-4320 APA-5D and an SKP-11. The pad, and the vehicles the country owns, move with it and stay exactly where they were, so the FARP still LOOKS complete: it is the roster that no longer matches the side. There is no reassignment that fixes it, because the vehicles themselves are the wrong ones -- delete the FARP and build it again with create_farp for the new coalition. A FARP is SEVERAL GROUPS: the pad, its support group ("<name> Support") and one group per role static ("<name> <static type> <n>"). delete_group on the pad removes the others too when create_farp built it in this session; for a FARP read from a file, delete each of them before rebuilding under the same name -- the rebuild is refused on their names. Reported in farps_now_unserviceable, which reports each as {group_id, name, farp_type, type_id} -- farp_type is the string create_farp takes, so it can go straight back into the rebuild; type_id is what the file holds, and the two differ for SingleHeliPad and InvisibleFARP. A FARP'S SUPPORT VEHICLES CAN BELONG TO ANOTHER COUNTRY: create_farp puts them under CJTF of the FARP's side when the FARP's country does not field every type. Moving the country that owns them stops a FARP it does not own from servicing aircraft: the vehicles leave the FARP's side and stay where they are. That is warned too, naming each FARP, and listed in farps_now_unserviceable with lost_by "support" (a FARP that lost its pad's country has lost_by "pad"). The fix is to move that country back. Returns {country, previous_coalition, coalition, moved, units_moved, diverged_airbases, farps_now_unserviceable, warnings}. moved is False when the country was already on that coalition (the call is idempotent, not an error).
ParameterTypeDescription
mission_idstringrequired
countrystringrequired
coalitionstringrequired

Change which coalition owns an airbase.

Details · 3 parameters (3 required)
It changes ownership only; aircraft already based there are not moved or re-flagged. A flight may be based at any airfield, whichever side owns it, as in the Mission Editor: a neutral one becomes the flight's side, and the other side's is left as it is. Change an airbase's side only when the user asks for it. airdrome_id: from list_airfields, which also reports current ownership. coalition: "blue" | "red" | "neutral" Returns airdrome_id, name, coalition, previous_coalition, and changed (false when it already belonged to that coalition -- a no-op, not an error).
ParameterTypeDescription
mission_idstringrequired
airdrome_idintegerrequired
coalitionstringrequired

Flights & AI behaviors17 tools

One call per mission role: CAP racetracks, CAS, SEAD, escorts, intercepts, sweeps, strikes, anti-ship, AFAC, recon, AWACS orbits, tankers and transports. Each builds the group and its first waypoint with the tasking DCS offers that airframe, and refuses the ones it does not.

Create a flight whose DCS group task is CAP -- combat air patrol.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step` in the response. REFUSES AN AIRFRAME DCS DOES NOT OFFER CAP FOR. About half the airframes carry it, and exactly one rotary type: the OH-58D. THE OH-58D BUILDS, AND ITS AUTO-INSERTED CAP ACTION IS DROPPED AND REPORTED. The editor offers a rotary CAP and then marks the action it inserts for it `1. CAP -a -!` in red, because the helicopter enroute list permits ENGAGE_TARGETS and not CAP. A person sees the red and deletes it; this does the same and says so. Ruled 30 Aug 2026 -- emulate what a competent person using the editor would end up with, not the editor's raw output. THERE ARE NO ORBIT POSITIONS, AND THE OLD PAIR WAS CIRCULAR. The orbit looked like a task parameter because the caller supplied two points -- but the caller supplied two points because the signature demanded them. ED's CAP action is an ENROUTE EngageTargets with targetTypes {Air} and NO GEOMETRY AT ALL. A race-track is ONE thing a CAP flight might fly; a ten-waypoint sweep over an area is another, and the old signature could not express it. Build the orbit with add_waypoint plus add_task, or any other route the tasking calls for. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is CAS -- close air support.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step` in the response, which names the call and the one call to avoid. REFUSES AN AIRFRAME DCS DOES NOT OFFER CAS FOR, and names what it does offer. There is no substitution: the tool IS the task, so an airframe DCS does not offer the CAS group task for cannot be given this tool. A UH-1H, an A-10C and a Ka-50 are all offered CAS; an E-3A is not. THAT IS A STATEMENT ABOUT WHAT THE EDITOR OFFERS, NOT ABOUT WHAT THE AIRCRAFT CAN DO. The wording used to say an airframe "cannot carry CAS", which reads as a capability claim and is the inference the shared block below exists to stop -- a group task selects default auto-actions and does not restrict anything in the mission. THERE IS NO target_position, AND THAT IS THE POINT. ED's CAS action is an ENROUTE EngageTargets with targetTypes {Helicopters, Ground Units, Light armed ships} and NO GEOMETRY AT ALL -- 'enroute' means it applies wherever the route goes. A single target coordinate was one use case encoded as if it were the task, and it made a CAS flight over a wide area inexpressible. WAYPOINT 0 IS BUILT AS THE EDITOR BUILDS IT, from ED's own autoActions table, and every action is checked against ED's permitted-action table before it is attached. A plane gets the full CAS signature -- the CAS engage task plus reaction-on-threat, radar usage, formation, prohibit jettison, radio usage and waypoint-pass reporting, plus EPLRS and formation side swap. A HELICOPTER GETS TWO ACTIONS, because ED has no helicopter entry in that table and rotary falls through to a much sparser shared list. That asymmetry is ED's, not ours. airdrome_id: the airfield to spawn at. Omit it for an AIR start, which then needs spawn_position; spawn_altitude_m and spawn_speed_kmh default to ED's own -- an air-started group's waypoint 0 IS its position, altitude and speed. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is SEAD -- suppress air defence.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step` in the response. REFUSES EVERY HELICOPTER, and that is not a category rule -- it is layer 1 answering. DCS gives SEAD to a minority of airframes and to no rotary one. DCS's action tables will happily describe a rotary SEAD group; no rotary airframe can be given the task, so those rows are unreachable. THERE IS NO target_position, AND FOR SEAD THAT IS THE CLEAREST CASE OF THE FOUR. ED's SEAD action is an ENROUTE_TASK -- EngageTargets with key='SEAD' and targetTypes {Air Defence}, and NO position, NO zone, NO radius. 'Enroute' means it applies ALONG THE ROUTE, wherever the route goes: a SEAD flight engages the air defences it meets. A single target coordinate made "fly this route and engage whatever you find" inexpressible, which is exactly the flight a SEAD tasking describes. Waypoint 0 is built as the editor builds it, from ED's own autoActions, with every action checked against ED's permitted-action table by ActionId and against the airframe's own capabilities. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Escort, protecting another flight.

Details · 17 parameters (6 required)
BUILDS THE GROUP AND WAYPOINT 0, carrying the escort task -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step` in the response. REFUSES AN AIRFRAME DCS DOES NOT OFFER ESCORT FOR, and names what it does carry. Most airframes carry it. escorted_group_id: THE ONE THING THE TASK CANNOT BE EXPRESSED WITHOUT. The plane or helicopter group to protect. It must already exist and must be the SAME CATEGORY -- the Mission Editor only offers same-category targets, so helicopters escort helicopters and planes escort planes, and the cross-category case is refused. engagement_distance_m: how far the escort will break off to engage. A parameter of the Escort task itself (ED's action template, me_action_db.lua). Default 60000, ED's own. From 0 to 250000 m, the Mission Editor's range. WHERE THE ESCORT TASK GOES IS MEASURED, NOT CHOSEN. A group with no route has one waypoint, so the editor puts the escort task on waypoint 0, last in the list, auto=false -- confirmed in a hand-built ME mission for an F-15C and an AH-64D alike. That is also where ED's corpus most often puts it: on the route's LAST waypoint, and with one waypoint those are the same place. IT STAYS THERE WHEN YOU ADD ROUTE WAYPOINTS; moving it would be our opinion, not ED's. THE TARGET CAN GO STALE, which a coordinate cannot. The escort task holds the escorted group's NUMERIC id. If that group is deleted later the escort task still names it, as the Mission Editor leaves it: delete_group lists it in references_left and validate warns about it. The response reports `escorted_group` so a caller can re-check it. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
escorted_group_idintegerrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
engagement_distance_mintegeroptionalDefault: 60000.
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Intercept.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. REFUSES EVERY HELICOPTER -- layer 1 answering, not a rule of ours. DCS gives Intercept to about half the airframes and to no rotary one. INTERCEPT IS NOT A FLAVOUR OF CAP, AND CHOOSING BETWEEN THEM MATTERS. DCS distinguishes them by what the ROUTE may carry: CAP enroute: CAP, EngageTargets, EngageTargetsInZone, EngageGroup, EngageUnit -- a STANDING engagement. Waypoints may carry BARCAP. Intercept enroute: NOTHING. No engage action of any kind is a permitted enroute task. Waypoints may instead carry AttackGroup and AttackUnit. So CAP holds an area and shoots what enters it; AN INTERCEPT FLIGHT HAS NO STANDING ENGAGEMENT AND IS POINTED AT A NAMED TARGET. That is ground-controlled interception, and DCS models it by REMOVING the enroute engage rather than by adding anything. If you want a fighter that patrols and reacts on its own, use create_cap_flight_v2 -- this tool will build a flight that ignores everything until you task it. WAYPOINT 0 IS CAP'S LIST MINUS THE CAP ACTION: prohibit air-to-ground, missile attack policy, prohibit waypoint-pass report, radio usage on contact, EPLRS and formation side swap. No task action. A helicopter would get EPLRS alone, but no helicopter reaches this tool. NO WAYPOINT TASK IS ADDED, and that is the corpus's answer rather than a default. Many of ED's Intercept groups carry no waypoint task at all, and every task that does appear -- AttackGroup or AttackUnit -- names a groupId or unitId that does not exist when this tool runs. Nearly all of those sit on waypoint 0, WHICH IS NOT A PLACEMENT RULE. They are AIR STARTS, where waypoint 0 is the first navigation point rather than a parking spot. Measured with no exceptions either way: no Intercept group in ED's corpus puts a task on a GROUND-STARTED waypoint 0. TO POINT IT AT SOMETHING, add a waypoint and then add_task with AttackGroup (params: group_id) or AttackUnit (params: unit_id). Those are what ED's own intercepts use, and they need a target that exists. FOR A TRIGGER-ACTIVATED INTERCEPT -- the alert-five pattern the old macro built in one call -- compose four: 1. this tool -> group_id 2. add_triggered_action(group_id, "StartCommand") -> task_index 3. modify_group(group_id, uncontrolled=True) 4. add_trigger("continuous", conditions=[{"type": "PartOfCoalitionInZone", "params": {"coalitionlist": "red", "zone_id": <zone>, "unit_type": "AIRPLANE"}}], actions=[{"type": "AITaskPush", "params": {"group_id": <group_id>, "task_index": <task_index>}}]) Measured: that writes the macro's trigger with two differences. The macro's condition had unit_type "ALL"; this example narrows it to "AIRPLANE", which the macro could not. And the macro's trigger had the comment "intercept trigger" and a colorItem. Pass "unit_type": "ALL" for the macro's condition. uncontrolled means the aircraft waits on the ramp with engines off; modify_group(late_activation=True) is the DIFFERENT DCS field where the group does not exist at all until activated. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Fighter Sweep.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. REFUSES EVERY HELICOPTER, and like SEAD that is layer 1 answering rather than a category rule of ours: DCS gives Fighter Sweep to about half the airframes and to no rotary one. THERE ARE NO ORBIT OR PATROL PARAMETERS. ED's FIGHTER_SWEEP action is an ENROUTE EngageTargets with key='FighterSweep' and targetTypes {Planes} -- no geometry at all. A sweep is a route, and the route is add_waypoint's job. HOW THIS DIFFERS FROM CAP, since the two are easy to confuse: CAP engages {Air}, which is planes AND helicopters, while a sweep engages {Planes} only -- and ED's description says enemy fighters are the priority targets. Both values are read from ED's table, not chosen. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Ground Attack.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. Most airframes carry it, helicopters among them, so most requests build and the refusal names what the airframe does carry. WAYPOINT 0 CARRIES NO TASK ACTION, and that is ED's own table rather than an omission: their auto list for a plane Ground Attack is six options plus EPLRS, and for a helicopter it is EPLRS alone. NOR IS A TASK ADDED ANYWHERE ELSE, and that is the corpus's answer. In ED's own missions most Ground Attack groups carry NO waypoint task at all. Every task that does appear -- Bombing, Strafing, AttackMapObject -- carries a target position we have not been given. SO ATTACK SOMETHING SPECIFIC WITH add_task once the route exists: Bombing or AttackMapObject for a point, AttackGroup or AttackUnit for a target that moves. The group task tells DCS what kind of flight this is; the waypoint task tells it what to hit. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Pinpoint Strike.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. REFUSES EVERY HELICOPTER, and that is layer 1 answering rather than a category rule of ours: DCS gives Pinpoint Strike to a minority of airframes and to no rotary one. WAYPOINT 0 CARRIES NO TASK ACTION -- ED's auto list is six options plus EPLRS -- and no task is added anywhere else. Most of ED's Pinpoint Strike groups carry no waypoint task at all, and every Bombing task they do carry has a target position we have not been given. HOW THIS DIFFERS FROM GROUND ATTACK: the two have IDENTICAL waypoint-0 auto lists and identical corpus behaviour. What differs is the group task DCS records, which is what the AI and the briefing read. Pinpoint Strike is the narrower tasking -- a specific structure rather than an area -- but that difference lives in the target you give it with add_task, not in anything this tool writes. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Runway Attack.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. REFUSES EVERY HELICOPTER -- layer 1 again. DCS gives Runway Attack to about half the airframes and to no rotary one. WAYPOINT 0 CARRIES NO TASK ACTION -- six options plus EPLRS -- and no task is added anywhere else. THE CORPUS CANNOT SUPPORT A RULE HERE AND THAT IS SAID RATHER THAN GLOSSED. ED ships only a handful of Runway Attack groups. All of them carry a waypoint task, which in any other task would be a strong signal; from so few it is not evidence of anything. The "no task" answer rests on the other three scans and on the target problem, not on this one. THE ACTUAL RUNWAY TASK IS BombingRunway AND IT NEEDS AN AIRFIELD. Add it with add_task once the route exists -- it takes a runwayId, which is a target this tool has not been given and would have to invent. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Antiship Strike.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. Most airframes carry it, helicopters among them -- the WIDEST of the three tools added alongside it, not the narrowest. THERE IS NO TARGET PARAMETER. ED's ANTI_SHIP action is an ENROUTE task -- EngageTargets with key='AntiShip' and targetTypes {Ships} -- and it carries no position, no group id and no zone. An antiship flight engages the shipping it meets along whatever route it flies. Give it a route with add_waypoint, and attack a NAMED vessel with add_task (AttackGroup / AttackUnit) if that is what the tasking calls for. A plane gets the full signature -- the antiship engage task plus reaction-on-threat, radar usage, formation, prohibit jettison and radio usage, plus EPLRS and formation side swap. A HELICOPTER GETS TWO ACTIONS, because ED has no helicopter entry in that table and rotary falls through to a sparser shared list. That asymmetry is ED's. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is AFAC -- airborne forward air control.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. Most airframes carry AFAC, helicopters among them, so most requests build. The refusal names what the airframe does carry. THE FAC ACTION IS GATED ON THE COUNTRY, NOT THE AIRFRAME, AND THIS IS THE ONLY GROUP TASK WHERE THAT HAPPENS. ED's own entry reads `verifyGroupCapability = isWesternCountry` (me_action_db.lua:2128), and isWesternCountry is a TEN-COUNTRY EXCLUSION LIST in me_utilities.lua: Russia, Ukraine, Insurgents, Abkhazia, South Ossetia, China, Belarus, USSR, Yugoslavia, GDR. SO A NON-WESTERN AFAC FLIGHT IS BUILT AND ITS FAC ACTION IS DROPPED, exactly as the editor does. The group keeps its AFAC group task and its other automatic actions; what it loses is the ability to designate targets. The drop is reported in `waypoint0.dropped_airframe_cannot` naming the COUNTRY, because a flight that silently cannot do the one thing it was created for is the worst kind of quiet failure. A Su-25T under Georgia and the same aircraft under Russia are therefore different flights. No per-airframe check could have found that, which is why the gate is applied per action rather than once. FAC TAKES NO PARAMETERS, and that is ED's design rather than a gap: "make the lead aircraft a FAC and let it choose targets by its own". Most FAC tasks in ED's own missions carry no params at all; the rest are designers who filled in a callsign and radio by hand. Do that with add_task if you want it. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Reconnaissance.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. A minority of airframes carry it, a few helicopters among them -- the narrowest of the four added alongside it, though still too many for the refusal to list them. WAYPOINT 0 CARRIES THE SPARSEST AUTO LIST OF ANY GROUP TASK: for a plane it is EPLRS and formation side swap, and for a helicopter it is EPLRS alone. No options beyond that, and no task action. A RECONNAISSANCE FLIGHT IS A ROUTE, and that is what the corpus says. Most of ED's Reconnaissance groups carry no waypoint task at all -- they simply fly somewhere and look. Those that do are almost all orbits, some wrapped in a controlled task. SO IF YOU WANT IT TO LOITER, add a waypoint and put an Orbit on it with add_task. Nine of ED's orbits here are exactly that. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is AWACS -- airborne early warning.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. ALMOST EVERY AIRFRAME IS REFUSED, and that is DCS's answer rather than ours: only the A-50, E-2C, E-3A and KJ-2000 carry AWACS. The refusal names them, because a short list is more use than a description. THE ORBIT IS NOT A PARAMETER HERE. ED's AWACS action is an ENROUTE task with no geometry at all; an orbit is one thing an AWACS might fly and a barrier patrol is another. Build the route with add_waypoint and add_task, which is also the only way to get a ten-waypoint track. count: 2 works. The tool this replaces defaulted to one; that limitation is not inherited. airdrome_id: omit for an AIR start, which then needs spawn_position; spawn_altitude_m and spawn_speed_kmh default to ED's own. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Refueling -- an air tanker.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. ALMOST EVERY AIRFRAME IS REFUSED. Only the A6E, C-130J-30, IL-78M, KC-135, KC130, KC135MPRS and S-3B Tanker carry Refueling, and the refusal names them. THE TACAN BEACON IS BUILT AND TAKES NO PARAMETERS FROM YOU, because the editor asks for none. ED's own template supplies all eight fields (me_action_db.lua:2563) and its fill_TACAN adjusts two of them for a tanker: channel 1X, callsign TKR, 962.0 MHz, AA off -- "tankers are supposed to have a normal TACAN station onboard, not Air-to-Air TACAN" in ED's own comment. These are ED's values and this tool takes no TACAN parameters, so EVERY tanker it builds is on 1X/TKR -- a second tanker in the same mission shares the first's channel, and the crews cannot tell the two apart by TACAN. **To give one a different channel, change this beacon; do not add a second.** modify_task(waypoint_index=0, task_index=<the ActivateBeacon's index in get_route>, params={"channel": N}) edits it in place and keeps the rest of ED's beacon. When the user wants a different channel, list_tacan_beacons shows the theater's own, to avoid. THE BEACON IS DROPPED, AND SAID SO, FOR A TANKER THAT HAS NO TACAN. The IL-78M has none; it is reported in `waypoint0.dropped_airframe_cannot` rather than vanishing. The A6E has only an air-to-air TACAN, and the Mission Editor does not add a beacon to it by itself; this tool does -- an air-to-air beacon on 1X / TKR, as the editor's own TACAN rule makes it for that aircraft. count: 2 works. The tool this replaces defaulted to one; that limitation is not inherited. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight whose DCS group task is Transport.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. THIS IS THE MOST COMMON GROUP TASK DCS SHIPS, ahead of CAS and Nothing. It is also the only task split about evenly between planes and helicopters -- and the two categories get DIFFERENT capabilities. FEW AIRFRAMES CARRY IT, more than half of them rotary. Airlifters and helicopters, plus a few oddities: the Christen Eagle II and the MB-339 carry Transport, the C-17A and IL-76MD obviously do, and no fast jet does. The refusal names what the airframe does carry. WAYPOINT 0 IS THE PLAINEST OF ANY TOOL HERE and has four outcomes: fixed-wing formation side swap ALONE -- no Transport-capable plane has EPLRS rotary with EPLRS EPLRS alone rotary without EPLRS NOTHING AT ALL, and still valid No task action in either category. That is ED's table, and it is why a transport flight is defined almost entirely by where it goes. A TRANSPORT FLIGHT IS A ROUTE, MORE SO THAN ANY OTHER TASK. Almost all of ED's Transport groups carry no waypoint task at all -- the highest proportion of the sixteen. TROOP LIFT IS HELICOPTER-ONLY, AND THAT IS DCS'S RULE. Embarking and Disembarking are not offered to a plane at any waypoint. A C-17A can carry cargo; it cannot load troops. What each category may carry: plane CargoTransportationPlane, CargoUnloadPlane, Aerobatics, Follow, NoTask, Orbit, Refueling helicopter CargoTransportation, Embarking, Disembarking, ExternalCargoLoad, ExternalCargoUnLoad, Land, Follow, NoTask, Orbit (plus the two plane forms) TO LIFT TROOPS, USE make_troop_transport RATHER THAN COMPOSING IT YOURSELF. It is not a convenience wrapper -- it encodes four things about DCS that raw add_task calls will get wrong, each verified in sim and each corroborated against ED's own missions: * the lift is THREE-SIDED, not four. Embarking + Disembarking on the helicopter, EmbarkToTransport on the troops, AND NO TROOP-SIDE DisembarkFromTransport. ED never writes that task in its own missions, and a lift built with it does not work. * groupsForEmbarking wants 1-BASED INDEX KEYS {1: gid}, as ED's own missions write it -- not {gid: gid}. * distribution must be {lead_unit_id: {index: gid}} with distributionFlag present and False. * THE GEOMETRY IS LOAD-BEARING. Troops teleport to their wait point on spawn, and a helicopter told to land on that exact coordinate BALKS. The lift must land clear of them but inside their embark radius -- which is what landing_offset_m is for. Compose it by hand only if you need something that tool cannot do, and expect to rediscover the four points above if you do. TO CARRY CARGO, add_task(heli, "CargoTransportation", {cargo_id}), naming a static cargo object that already exists. EVERY TRANSPORT WAYPOINT ACTION DCS OFFERS CAN BE WRITTEN -- eleven of eleven for a helicopter, eight of eight for a plane. Five could not be before 0.9.11, and the response still reports what DCS offers this airframe under `waypoint_actions.offered_by_dcs`. FIXED-WING CARGO works on a C-17A or IL-76MD route: add_task(plane, "CargoTransportationPlane") on the FIRST waypoint -- ED's own gate refuses it anywhere else -- and "CargoUnloadPlane" where the load should come off. SLING LOADS: "ExternalCargoLoad" and "ExternalCargoUnLoad" are reachable, though ED's own CH-47F sling-load training mission uses CargoTransportation and neither External action appears anywhere in their 789 shipped missions. NoTask is the editor's "nothing selected" placeholder. A waypoint with no task is what you get by not calling add_task, and ED never writes the marker in its own missions -- it is reachable for completeness, not because you need it. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Create a flight with NO combat tasking -- DCS group task 'Nothing'.

Details · 15 parameters (5 required)
BUILDS THE GROUP AND WAYPOINT 0 -- what the Mission Editor places. The route is the user's to describe: add_waypoint adds it. See `next_step`. REACH FOR THIS WHENEVER THE FLIGHT'S JOB IS TO FLY, NOT TO FIGHT. 'Nothing' is DCS's name and it is a poor one: it does not mean an inert or broken group, it means a group whose behaviour is defined ENTIRELY BY ITS ROUTE AND ITS WAYPOINT TASKS rather than by a standing combat role. Use it for: * a ferry or repositioning flight, or any A-to-B transit; * an airliner, bizjet or light aircraft populating the sky; * a Client slot the user said they will fly, where they decide what to do; * a target drone, or aircraft placed as scenery to be shot at; * a scripted flight driven by triggers, where a group task would fight the script; * ANY flight where you want precise control and no AI initiative. A FLIGHT THE USER ONLY NAMED. The Mission Editor places it with the airframe's default task -- list_unit_types gives each type's default_task -- so use that task's tool. Use this one when the user wants no task, or for the cases above. IT ACCEPTS EVERY AIRFRAME, AND IT IS THE ONLY TOOL HERE THAT DOES. There is no layer-1 refusal: an E-3A, a Ka-50, a Christen Eagle II and an F-16C are all valid. That is not a gap in the check -- it is ED's own rule. 'Nothing' appears in no airframe's task list, yet every airframe may be given it, because it is DCS's GLOBAL default task and their load-time validator exempts the global default from the reset it applies to every other airframe/task mismatch (me_mission.lua:829). Every other tool refuses; this one cannot. WAYPOINT 0 CARRIES NO TASK ACTION AND ALMOST NO OPTIONS, which is the point rather than an omission. ED's auto list for 'Nothing' is formation side swap plus EPLRS for a plane, and EPLRS alone for a helicopter -- so what you actually get is: plane, EPLRS-capable side swap + EPLRS plane, not EPLRS-capable side swap alone helicopter, EPLRS-capable EPLRS alone helicopter, not NOTHING AT ALL, and the group is still valid No reaction-on-threat, no radar usage, no engage task. The rotary asymmetry is ED's table, not ours, and the response lists exactly what was attached and what the airframe could not take. IT IS ONE OF THE THREE COMMONEST GROUP TASKS EAGLE DYNAMICS SHIPS, behind only Transport and CAS, and mostly on planes. It is the ordinary choice for a flight that is part of the scenery rather than part of the fight. TO MAKE IT DO SOMETHING, GIVE IT A ROUTE. add_waypoint for where it goes, then add_task for what it does when it gets there. 'Nothing' still permits waypoint tasks -- ED's availableActions has its own entry for it -- so an orbit, a landing or a scripted action all work. The group task only says the AI has no standing agenda of its own. THIS IS ONE OF THREE ACTS AND IT IS THE FIRST. The Mission Editor separates them and so do these tools: 1. THIS CALL places the group. UNARMED, and with no route. 2. set_payload OR arms it. apply_loadout_from_library(role=...) apply_loadout_... fits a named loadout; list_role_loadouts and list_weapons show what the airframe can take. 3. add_waypoint routes it. Then add_task for what it does when it gets there. A FLIGHT FROM THIS CALL HAS NO WEAPONS AND NO ROUTE, as the Mission Editor places one. Make calls 2 and 3 for what the user described -- the weapons they named, the route they gave. What they did not describe stays as placed: offer it in your reply, or ask when the choice would change what they get. The response reports `armament`, `fuel` and `next_step` so you can say what the flight has -- `fuel` is the Mission Editor's starting fuel for the type: a full tank for most, a share for a few (the Su-33 half). WHERE THE FLIGHT STANDS -- three surfaces, and exactly one of them. Placing a group is giving it a position, so all three live here: airdrome_id a runway or apron, at any airfield: a neutral one becomes the flight's side (airbase_claimed), and the other side's is left as it is, as in the Mission Editor. parking_ids pins specific spots (parking_id values from list_parking_spots); omit it and DCS allocates. pad_group_id a CARRIER DECK or FARP PAD of the flight's own side -- pass the ship or static group's id. pad_unit_id picks a particular ship or pad within it; omit it and the carrier is found by type. Not valid with start_type='runway'. On a FARP each aircraft takes a pad of its own, numbered as the editor numbers them (the 4-pad FARP has four, a single pad or an invisible FARP one), reported under spawn.pad.pads; a flight the free pads cannot hold is refused. spawn_position an air start. spawn_altitude_m and spawn_speed_kmh are both OPTIONAL and both default to ED's own: altitude 2000 m plane / 500 m rotary, speed from getCruiseSpeed for this airframe -- read from its declaration, or for a core type compiled into the engine, from the table this server ships of DCS's own values. Only a type in neither (a mod's, say) is refused and asked for spawn_speed_kmh. What was applied is reported under spawn.cruise_speed. Passing more than one refuses, and nothing is built. THE REST ARE THE SERVER'S USUAL GROUP PARAMETERS: name is the group name, aircraft_type the DCS type id, coalition and country place it, count is how many airframes (default 1, as the Mission Editor places a group), and start_type is 'cold', 'hot' or 'runway' for a ground start ('warm' is accepted for 'hot'). skill IS THE STORED DCS TOKEN AND DEFAULTS TO THE EDITOR'S OWN. 'Average', 'Good', 'High', 'Excellent', 'Random', 'Client', 'Player'. The default is 'High' -- measured: that is what the Mission Editor gives a freshly placed group, and the panel DISPLAYS it as 'Veteran'. Pass the token, never the label. 'Client' makes a human slot on any aircraft, as the Mission Editor allows. On a type no player can fly in DCS -- a B-52H, say -- the slot is written and `warnings` says so: a player who takes it is put in spectator mode. The response's `crewing` block says who ends up flying either way. LEAVE THE DEFAULT UNLESS THE USER SAYS THEY WILL FLY IT. A flight asked for without saying who flies it is AI, as the Mission Editor places it; if the user might want to fly it, offer a Client slot in your reply rather than making one. DO NOT INFER THE MISSION FROM THE WEAPONS. A loadout is a coarse signal. If the user asks for an aircraft carrying particular stores, arm it and leave the task alone -- do not decide the flight is CAS because it carries Mavericks, or SEAD because it carries HARMs. NEVER RE-TASK AN EXISTING FLIGHT. Advise instead. If arming or routing a flight suggests a different task would suit it better, say so in your reply and let the user decide. Changing the group task is theirs to ask for. WHAT A GROUP TASK ACTUALLY MEANS, so the above follows rather than being a rule to remember: it determines which auto-actions the group receives by default, and nothing more. It does not restrict what the aircraft can do in the mission. It has real force only for AI -- a client flies whatever they like regardless. Even an AI CAP flight is not precluded from engaging ground targets. The one thing that genuinely constrains that is the explicit Restrict Air-Ground Attack option, because a user set it. ADJUSTING IS CHEAP. There is no need to delete and rebuild. modify_waypoint, modify_task, remove_task and set_payload change what is already there. Building a flight again to change one value wastes the user's work and loses anything they set in between. READ THE RESPONSE. Every call reports what it did, what it defaulted, and anything it could not do -- corrected speeds, unarmed aircraft, refused parameters, content it could not preserve. Those fields exist to be read and passed on to the user, not to sit unmentioned. WHAT THIS TOOL RETURNS IS REVIEWABLE, NOT RECOMMENDED. Values it chose on the user's behalf are stated so they can be changed, not offered as the right answer.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
aircraft_typestringrequired
coalitionstringrequired
countrystringrequired
airdrome_idinteger | nulloptional
countintegeroptionalDefault: 1.
start_typestringoptionalDefault: "cold".
spawn_positionPosition | nulloptionalA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
spawn_altitude_mnumber | nulloptional
spawn_speed_kmhnumber | nulloptional
skillstringoptionalThe DCS skill token. Default 'High' -- AI, as the Mission Editor places a flight. 'Client' only when the user says they will fly this flight; otherwise leave the default and offer a Client slot in your reply. Default: "High".
parking_idsinteger[] | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Wire a complete, in-game-FUNCTIONAL helicopter troop lift (Fix 3).

Details · 10 parameters (5 required)
Redesigned from two ME ground-truth missions confirmed flying in sim. A troop lift is two-sided: the transport helicopter carries an Embarking (pickup) then a Disembarking (dropoff) task; each troop group carries an EmbarkToTransport (board) task. Disembark is HELI-SIDE ONLY -- there is no troop-side DisembarkFromTransport in a working AI lift. The geometry is load-bearing: the heli must land CLEAR of the troops (not on top of them) while both stay within the troops' embark radius. The troops teleport to their wait point on spawn; if the heli's landing spot is the same coordinate it balks. So this composer places the heli's pickup waypoint + Embarking point `landing_offset_m` away from `pickup_position` (toward the dropoff), within `pickup_radius`. It APPENDS a pickup and a dropoff waypoint to the heli's route (at real transit speed -- a 0-speed waypoint never flies), so the author only supplies the two positions. transport_group_id: the lifting helicopter group (must be a helicopter). troop_group_ids: the ground troops to lift (each must be a vehicle group; place them at `pickup_position` before calling). pickup_position: where the TROOPS wait (their EmbarkToTransport point). dropoff_position: where the lift unloads (the heli's Disembarking point). pickup_radius: troops' embark radius in metres (EmbarkToTransport zoneRadius, default 200). `landing_offset_m` must be less. landing_offset_m: how far the heli lands from the troops (default 100; must be < pickup_radius so troops can reach it). Offset is toward the dropoff. board_specific_unit: if true, the troops board this transport's airframe TYPE specifically (the ME's "specific transport" form -- selectedType, e.g. "UH-1H"), so a multi-type mission does not cross-load. Default false = board any transport. transit_speed_kmh: heli transit speed for the appended waypoints (default: as the Mission Editor fills a new waypoint -- the lift's last waypoint's speed). transit_altitude_m: altitude of the appended pickup/dropoff waypoints (default: the heli's last waypoint altitude, or 100 m). RAISED TO TERRAIN HEIGHT if it would put either waypoint under the ground -- exactly, with no clearance added, because the heli LANDS at both. The change is reported in `altitude_corrections`. Returns a summary of the appended waypoints and wired tasks, plus the four route findings the three route writers carry -- speed_advisories, speed_corrections, altitude_corrections, altitude_advisories -- present even when empty.
ParameterTypeDescription
mission_idstringrequired
transport_group_idintegerrequired
troop_group_idsinteger[]required
pickup_positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
dropoff_positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
pickup_radiusintegeroptionalDefault: 200.
landing_offset_mintegeroptionalDefault: 100.
board_specific_unitbooleanoptionalDefault: false.
transit_speed_kmhnumber | nulloptional
transit_altitude_mnumber | nulloptional

Routes, waypoints & tasks9 tools

Full route control: add, modify and remove waypoints, replace whole routes, set a time on target, and attach, edit, disable or remove the DCS tasks and options at any waypoint.

Insert a waypoint into a group's route.

Details · 14 parameters (3 required)
Flat parameters matching the house convention (add_vehicle_group / add_ship_group): position is a structured Position, the rest are flat optional scalars. (set_route, which replaces a whole route, still takes a LIST of WaypointSpec objects -- a list cannot be flattened.) position: {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. altitude_m: waypoint altitude in metres, for a flight. A VEHICLE'S OR SHIP'S WAYPOINT IS WRITTEN AT THE GROUND HEIGHT THERE, as the Mission Editor writes it; an altitude given for one is not used, and altitude_advisories says so. A FLIGHT WHOSE LEAD IS FLOWN BY A PERSON (its first unit is a Client or Player) TAKES GROUND LEVEL UNLESS THE PERSON ASKED FOR AN ALTITUDE. Their waypoints are navigation and designation references, and DCS designates at the waypoint's own altitude -- a steerpoint above the ground designates a point in the air rather than the target under it. altitude_m=0 (or omitted) writes terrain height exactly for such a flight; a value above the ground is written as asked and reported in altitude_advisories every time. A flight led by an AI is an AI flight, whoever else is in it -- the lead flies these altitudes -- and AI flights are unchanged: a below-terrain altitude is raised to terrain + 100 m. The Mission Editor's box takes 0-40000 m and, for an aircraft, no more than its type's ceiling; this server does not hold the ceilings, so only the 0-40000 m is checked, for every type. speed_kmh: waypoint speed in km/h. If omitted on a FLYING group, takes the route's established cruise -- its most recent non-zero speed at a waypoint in the air (takeoff and landing waypoints are skipped) -- or, when there is none, the Mission Editor's cruise speed for the airframe (ED's getCruiseSpeed), then 0.8 of the airframe's maximum, and only then a category cruise (200 km/h helicopter / 600 km/h plane). The response's default_speed says which. A vehicle or ship waypoint takes the previous waypoint's speed, as the Mission Editor gives it -- the first leg after a stopped start 20 km/h (vehicle) or 50 km/h (ship). A speed above an aircraft's maximum is written as asked and warned. A vehicle's or ship's speed is not checked against a maximum, which this server does not hold; speed_advisories says so. type: DCS waypoint type string -- "Turning Point" (default), "Fly Over Point", "TakeOffParking" (cold start), "TakeOffParkingHot" (hot start), "TakeOff" (runway start), "Land" -- also accepts the aliases "From Parking Area", "From Parking Area Hot", "From Runway", "Landing". Ground/ship: "On Road", "Off Road". An unknown type raises listing the valid set. A TRAIN'S WAYPOINTS ARE ALL "On Railroads": that is what a new one gets, and any other type is refused -- as "On Railroads" is for any other group. DCS puts a train on the railway nearest each waypoint, however far that is; this server has no railway data. A VEHICLE GROUP'S NEW WAYPOINT KEEPS THE ROUTE'S CURRENT ACTION when no type is given, as the Mission Editor does: a column already On Road stays On Road. Ask for a road move once and every waypoint after it follows. "On Road" sets the action only. DCS moves the group onto its own road network when the mission runs, and the Mission Editor does the same when the mission is saved there. A waypoint does not have to be on a road; near the road you want helps the group take that one. This server has no road network of its own (sample_terrain reports a ROAD surface class, but it is a coarse 100 m mask, not ED's roads). name: optional waypoint label. airdrome_id: required for takeoff/landing waypoint types (raises if omitted for one). Use list_airfields to find a valid id. A LANDING IS PUT WHERE THE MISSION EDITOR PUTS IT: on the airfield's reference point at the ground height, whatever position you pass (the response's airfield says so). A landing at a neutral airfield makes it the flight's side (airbase_claimed), as in the editor; the other side's airfield is left as it is. pad_group_id: recover on a SHIP or FARP of the flight's own side instead of an airfield -- the group_id of a ship group (carrier, LHA) or static group (FARP, helipad). Only valid with type="Land", and mutually exclusive with airdrome_id. The pad unit inside the group is located BY TYPE, and the waypoint is SNAPPED onto it (the Mission Editor snaps when you select Landing; the file format does not, so any position you pass is overwritten and the response says so). Altitude and speed take DCS's own defaults for the pad kind -- sea level / 500 km/h for a ship, terrain height / 150 km/h for a FARP -- unless you pass speed_kmh yourself. To DEPART from a deck, pass pad_group_id to one of the sixteen task tools instead; a spawn is a property of the group. pad_unit_id: which unit of pad_group_id to land on. Only needed when the group holds more than one pad-capable unit, which raises rather than picking -- a carrier strike group has several for a helicopter, because escorts take helicopters (but no planes). alt_type: 'BARO' (default) is height above SEA LEVEL; 'RADIO' is height above the ground below the aircraft, capped by DCS at 1200 m and valid on aircraft only. Neither this tool nor modify_waypoint could set it before 6 Sep 2026 -- both hard-coded BARO. speed_locked: default true, meaning the speed you give governs the leg and the arrival time follows. FALSE hands the speed to DCS, which solves for the value that meets the next locked arrival time -- so it is only valid when a later waypoint has one, and a route without that is refused rather than built. ETA: TIME ON TARGET, seconds after the mission start time. Supplying it MAKES this waypoint a time anchor; there is no separate lock flag, because in DCS a locked arrival time IS the input the editor solves speeds against and a lock with no time is half an instruction. Pair it with speed_locked=False on the SAME call -- usually on this waypoint, so its own leg is the one solved -- or the route has two fixed times with nothing between them to solve for, which DCS rejects. index: 0-based insertion position. The waypoint currently at this index (and all following) will be shifted back by one. Examples for a 2-waypoint route [TakeOff(0), Land(1)]: index=1 -> inserts before Land -> [TakeOff, NEW, Land] index=-1 -> same as index=1 on any route length (always inserts before the last waypoint) index=None / omitted -> inserts before the terminal Landing/LandingReFuAr waypoint if one exists, preserving it as the last waypoint. If the route has no terminal landing waypoint the new waypoint is appended at the end. Indices >= route length append at the end. INSERTING RENUMBERS, as the Mission Editor does: every SwitchWaypoint and "stop at waypoint" condition on the group's own waypoints that names a later waypoint moves up by one, so it still names the same waypoint; listed under references_renumbered. What the editor does not renumber -- a SwitchWaypoint in the group's triggered actions or inside a conditional task, and another group's escort or follow that runs to one of this group's waypoints -- is left as it is and named in warnings. Returns the new waypoint dict plus updated route length, and a "warnings" list: for a GROUND (vehicle) group, a new waypoint placed over water (warn-only -- the same baked-.dat surface check as mission_report check 24; amphibious/bridge crossings are legitimate); for a ship, a new waypoint on land (warn-only, as the grid cannot see a quay); for a flight, a speed above the airframe's maximum, written as asked; for a vehicle or ship given a speed, that it was not checked against a maximum; and the references an insert could not renumber (above). Empty when none applies.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
altitude_mnumber | nulloptional
speed_kmhnumber | nulloptional
typestring | nulloptional
namestring | nulloptional
airdrome_idinteger | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional
indexinteger | nulloptional
alt_typestring | nulloptional
speed_lockedboolean | nulloptional
ETAnumber | nulloptional

Apply a partial update to a single waypoint in a group's route.

Details · 14 parameters (3 required)
waypoint_index: 0-based index into the route (use get_route to see current indices). type -- waypoint type string (same values as add_waypoint; an unknown type raises listing the valid set) name -- display name for the waypoint altitude_m -- altitude in metres (BARO). A vehicle's or ship's waypoint is written at the ground height there, as the Mission Editor writes it, and altitude_advisories says so. A FLIGHT WHOSE LEAD IS FLOWN BY A PERSON (its first unit is a Client or Player) takes ground level unless the person asked for an altitude: DCS designates at a waypoint's own altitude, so a steerpoint above the ground designates a point in the air rather than the target under it. 0 writes terrain height exactly for such a flight; anything above the ground is written as asked and reported in altitude_advisories. AI is unchanged (below terrain is raised to terrain + 100 m). The first waypoint of a flight that starts in the air is where the aircraft is: it is treated as an AI flight's, whoever leads. The Mission Editor's box takes 0-40000 m and, for an aircraft, no more than its type's ceiling; this server does not hold the ceilings, so only the 0-40000 m is checked, for every type. speed_kmh -- airspeed / ground speed in km/h. Above an aircraft's maximum it is written as asked and warned. A vehicle's or ship's speed is not checked against a maximum, which this server does not hold; speed_advisories says so. ETA -- TIME ON TARGET, seconds after the mission start. Supplying it makes this waypoint a time anchor and DCS solves the speeds before it to meet the time. On a waypoint that is not already an anchor, pair it with speed_locked=False so there is something to solve; on one that already is, ETA alone RETIMES it and the solved speeds move. Refused on waypoint 0, whose arrival time is the group's start_time -- use modify_group for that. An unreachable time is refused rather than written. ETA_locked -- bool. Setting it TRUE is refused: the flag without a time is half an instruction, because in DCS a locked arrival time IS the input. Pass ETA instead. Setting it FALSE is refused on the route's only anchor (the ME rejects a route with no locked time) and allowed on any other -- which is the repair path for a route that arrived carrying a second anchor. speed_locked -- bool. Refused on waypoint 0, which has no leg into it to derive a speed from (me_route.lua:454), and refused anywhere the resulting route would have an unlocked speed with no later time anchor to solve it against -- DCS rejects that on save. alt_type -- 'BARO' (above sea level) or 'RADIO' (above the ground below the aircraft, capped at 1200 m, aircraft only). Settable on neither tool before 6 Sep 2026. airdrome_id -- int; required for takeoff/landing waypoint types (raises if the effective type is takeoff/landing and the waypoint has no airdrome_id, new or pre-existing). On a landing, the waypoint moves onto the airfield as add_waypoint places one, keeping its tasks; a neutral airfield becomes the flight's side (airbase_claimed). pad_group_id -- int; start on (waypoint 0) or land on (a Land waypoint) a ship or FARP of the flight's own side instead of an airfield. On a landing the waypoint is snapped onto it and keeps its tasks, as add_waypoint's pad landing does. pad_unit_id picks the unit when the group has more than one that can take the aircraft. MOVING WHERE A FLIGHT STARTS. On waypoint 0 of a flight that starts at an airfield, or on a ship or pad, airdrome_id or pad_group_id MOVES THE FLIGHT THERE, as a first placement there would put it: a parking or hot start takes free stands that fit every aircraft (one aircraft per FARP pad), a runway start stands on the runway, and the aircraft and waypoint 0 move with it. All or nothing: refused, nothing changed, where there is not room. The start type is kept unless you give type. As for a new flight, a neutral airfield becomes the flight's side (airbase_claimed), the other side's airfield is left as it is, as in the editor, and the other side's ship or FARP is refused. This is how to move such a flight -- move_group does not, because its position is its stand, runway or deck. Not supported here: tasks (use add_task), position (delete + re-add via add_waypoint). Called with no fields, this is a no-op that returns the waypoint's current state without mutating it. Returns the updated waypoint dict.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypoint_indexintegerrequired
typestring | nulloptional
namestring | nulloptional
altitude_mnumber | nulloptional
speed_kmhnumber | nulloptional
ETA_lockedboolean | nulloptional
speed_lockedboolean | nulloptional
airdrome_idinteger | nulloptional
alt_typestring | nulloptional
ETAnumber | nulloptional
pad_group_idinteger | nulloptional
pad_unit_idinteger | nulloptional

Remove one waypoint from a group's route, as the Mission Editor's

Details · 3 parameters (3 required)
DEL does. Every other waypoint, and its tasks, stays as it was. waypoint_index is 0-based, as get_route numbers the waypoints. Waypoint 0 cannot be removed: it is where the group comes into existence, and the editor does not remove it either. To change where a group starts, use move_group, or modify_waypoint on waypoint 0. WHAT GOES WITH IT, as in the editor: the waypoint's own tasks and actions; a ScriptFile or TransmitMessage file one of them used, unless something else names the file; and, if it carried the group's EmbarkToTransport, the group's place in other groups' embarking, disembarking and paradrop tasks (listed under groups_changed). WHAT IS RENUMBERED, as in the editor: every SwitchWaypoint on the group's waypoints and every "stop at waypoint" condition that names a later waypoint moves down by one, so it still names the same waypoint; a switch left going from a waypoint to itself is removed; a stop condition on the removed last waypoint is cleared. Listed under references_renumbered. WHAT IS NOT, as the editor does not: a SwitchWaypoint in the group's triggered actions or inside a conditional task, and another group's escort or follow that runs to one of this group's waypoints. Each one that now names a different waypoint is named in warnings. waypoint_index SHIFTS: every waypoint after the removed one is now one lower. Removing several means removing from the highest index down, or re-reading get_route between calls.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypoint_indexintegerrequired

Return the current route for a group.

Details · 2 parameters (2 required)
Returns: { "group_id": int, "waypoint_count": int, "waypoints": [ {index, type, name, position, altitude_m, speed_kmh, eta, eta_locked, airdrome_id, ...}, ... ] }
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired

Replace a group's entire route.

Details · 3 parameters (3 required)
Clears the existing route and rebuilds it from the given waypoints. Each waypoint is a WaypointSpec: { position: {lat_lon: ...}, {xy: ...}, or flat {lat, lon} or {x, y}, altitude_m?, speed_kmh?, type?, name?, airdrome_id? } A FLIGHT WHOSE LEAD IS FLOWN BY A PERSON (its first unit is a Client or Player) TAKES GROUND LEVEL AT EVERY WAYPOINT unless the person asked for an altitude. Their waypoints are navigation and designation references, and DCS designates at the waypoint's own altitude -- a steerpoint above the ground designates a point in the air rather than the target under it. altitude_m 0 (or omitted) writes terrain height exactly for such a flight; a value above the ground is written as asked and reported in altitude_advisories for every waypoint it applies to. A flight led by an AI is an AI flight, whoever else is in it -- the lead flies these altitudes -- and AI flights are unchanged: a below-terrain altitude is raised to terrain + 100 m. The Mission Editor's box takes 0-40000 m and, for an aircraft, no more than its type's ceiling; this server does not hold the ceilings, so only the 0-40000 m is checked, for every type. THE FIRST WAYPOINT OF A FLIGHT THAT STARTS IN THE AIR IS NOT ONE OF THESE, whoever leads: it is where the aircraft is, not a point it navigates to. With no altitude it takes the Mission Editor's (2,000 m for a plane, 500 m for a helicopter, or the ground's height where that is higher), and the rule above that puts a person's waypoints on the ground never applies to it. (Deliberate asymmetry: add_waypoint takes flat scalars because it adds a single waypoint; set_route takes a LIST of specs because a list of waypoints cannot be flattened into one call. Same per-waypoint validation -- unknown type / missing airdrome_id raise in both.) For flying groups the first waypoint is the start position -- use type "TakeOffParking" (cold), "TakeOffParkingHot" (hot), or "TakeOff" (runway), plus airdrome_id. Subsequent waypoints use "Turning Point". For ground/ship groups "Turning Point" works for all waypoints, except a train's: its waypoints are all "On Railroads", which a waypoint with no type becomes and any other type is refused. A train starts at 20 km/h, as in the Mission Editor, and a waypoint with no speed takes the speed of the one before. A landing is placed as add_waypoint places it; airbases_claimed lists any neutral airfield a landing claimed. [!] AUTO-TASK WARNING: many aircraft groups carry the editor's automatic tasks at the first waypoint (an EPLRS WrappedAction, and sometimes other enroute tasks). set_route clears those along with the route. If the rebuilt mission behaves unexpectedly (no datalink, wrong AI behaviour), re-add the needed tasks via add_task after set_route. At least one waypoint is required. The first waypoint is auto-locked (ETA_locked=true) when the supplied spec contains no time anchor, so the route is accepted by the DCS Mission Editor (which requires at least one ETA-locked waypoint per group). The return value reports this via "eta_auto_locked", and each waypoint dict in "route" carries its own "ETA_locked"/"speed_locked". Returns the new route as a list of waypoint dicts, plus a "warnings" list. For a GROUND (vehicle) group, each new waypoint over water adds a warn-only entry (placement still succeeds -- same baked-.dat check as mission_report check 24); for a ship, each new waypoint on land. Empty for flights and theaters with no terrain data installed. A speed above an aircraft's maximum is written as asked and warned, in warnings and speed_advisories. A vehicle's or ship's speed is not checked against a maximum, which this server does not hold; speed_advisories says so for the waypoints given one.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypointsWaypointSpec[]required

Add a task to a waypoint in a group's route.

Details · 6 parameters (4 required)
waypoint_index: 0-based index into the group's route points. enabled: False writes the task in a switched-OFF state -- DCS loads it and does not run it. Used to stage an alternative a designer can turn on in the editor. To switch off a task that already exists (including one DCS generated from the group's task), read get_route's per-waypoint `tasks` list and call set_task_enabled. A key in params given as null is not given: the task is built as if it were left out, and the response lists it under null_params_ignored -- inside a ControlledTask's inner_params too, as inner_params.<name>. task_type and params: "Orbit" -- hold pattern altitude_m (default the Mission Editor's: the altitude of the waypoint the action is on, or of waypoint 0 for a triggered action, with the ground there added for a RADIO one; 4000 where this server does not know the ground there), speed_kmh (default the Mission Editor's: half the aircraft's top speed, at most 500 km/h; 600 for a type whose top speed this server does not hold) pattern? -- "Race-Track", "Circle" or "Anchored". DCS's three, and an unknown value raises rather than being coerced. OMIT IT AND THE EDITOR'S OWN RULE CHOOSES: Race-Track when a waypoint follows this one, Circle when none does. A race-track has two ends -- the orbit waypoint and the next -- so DCS does not offer the pattern with nothing after it (me_action_edit_panel.lua:985), and ED's own missions never write such an orbit. Asking for one anyway is written and WARNED, not refused. The response reports `orbit_pattern`: the value used and whether it came from you or from the editor's rule. "Barcap" -- orbit on a combat air patrol, in the Mission Editor's own names: speed? (m/s; default the Mission Editor's, as Orbit's; none for a type whose top speed this server does not hold), altitude? (default the Mission Editor's, as Orbit's; none where this server does not know the ground there), pattern? "AttackGroup" -- attack a specific group group_id -- target group id, validated against the mission; omit it for none, the Mission Editor's NOTHING. weapon_type (optional int -- omit it and the editor's own choice for this attacker and target is used, e.g. 9663676414 for an aircraft attacking a vehicle; e.g. 2032=Bombs, 30720=Rockets, 264241152=AAM) group_attack (optional bool, default false) -- if true, every aircraft in the attacking group attacks the target "EngageGroup" -- engage a specific group group_id? (omit it for none, the Mission Editor's NOTHING), visible (bool, default false) "Hold" -- hold current position template_id? -- the template the group holds in, as the Mission Editor's Hold panel offers it: a name from list_templates, one of an opened file's own custom formations, or "default". Omitted, none is chosen, as the editor writes it. "GoToWaypoint" -- jump to another waypoint to_index (required, 1-based waypoint number of this group's route), from_index? (the number of the waypoint this action is on, 1-based, as the Mission Editor sets it: written so when omitted, any other refused; a triggered action takes none) "EPLRS" -- enable datalink group_id (optional) -- the datalink NETWORK number, not a group: defaults to the EPLRS number already on this route, otherwise the lowest one unused on this side "SetFrequency" -- set radio frequency frequency_mhz (default 131, the Mission Editor's), modulation ("AM" | "FM", default "AM"), power (default 10) "RunScript" -- run an inline Lua script script (Lua string). A script whose Lua doesn't compile is refused with Lua's own message, checked with DCS's own Lua and never run. If DCS's Lua can't be loaded, the script is taken unchecked, with a lua_not_checked warning. "ROE" -- rules of engagement option value: 0=WeaponFree, 1=OpenFireWeaponFree, 2=OpenFire, 3=ReturnFire, 4=WeaponHold, or ED's own names (WEAPON_FREE, ...). Aircraft are offered all five (default 2, OpenFire); ground units and ships 0, 3 and 4 (default 0). "ReactionOnThreat" -- threat reaction option value: 0=NoReaction, 1=PassiveDefence, 2=EvadeFire, 3=BypassAndEscape, 4=AllowAbortMission (default), 5=HorizontalAAAEvadeFire, or ED's own names. "AlarmState" -- ground units and ships only value: 0=Auto (default), 1=Green, 2=Red "OptRTBOnBingoFuel" -- return to base when bingo fuel is reached value: false = no RTB, true = RTB or air-refuel (default), 2 = RTB, ignoring air refuelling "OptRTBOnOutOfAmmo" -- return to base when out of the given weapon(s) value: weapon-type code (default 4294967295=All). Common codes: 0=NoWeapon, 4294967295=All, 805306368=Cannon, 2032=Bombs, 30720=Rockets, 268402688=Missiles, 264241152=AAM, 4161536=ASM, 131072=ATGM, 32768=ARM, 65536=Antiship, 268402702=Guided, 805339120=Unguided (one named code; OR-combined custom masks not supported here) "OptRadarUsing" -- radar emission policy value: 0=NeverUse, 1=UseForAttackOnly, 2=UseForSearchIfRequired (default), 3=UseForContinuousSearch "OptECMUsing" -- ECM emission policy value: 0=NeverUse, 1=UseIfOnlyLockByRadar (default), 2=UseIfDetectedLockByRadar, 3=AlwaysUse -- Restrict-class options (all bool, default false -- the editor adds them unticked; pass true to restrict) -- "OptRestrictAirToAirAttack" -- forbid air-to-air attacks value (bool, default false) "OptRestrictAirToGround" -- forbid air-to-ground attacks value (bool, default false) "OptRestrictAfterburner" -- forbid afterburner use value (bool, default false) "OptRestrictJettison" -- forbid stores jettison value (bool, default false) "OptJettisonEmptyTanks" -- jettison empty fuel tanks value (bool, default false) "OptRestrictTargets" -- restrict engageable target categories value: 0=AllUnits (default), 1=AirUnitsOnly, 2=GroundUnitsOnly -- Defensive / emission options -- "OptChaffFlareUsing" -- chaff/flare usage policy value: 0=NeverUse, 1=UseAgainstFiredMissile, 2=UseWhenFlyingInSAMWEZ (default), 3=UseWhenFlyingNearEnemies "OptDisparseUnderFire" -- ground units disperse when fired upon, for this long value: time in seconds (0 to 250000, default 600) ("DisperseUnderFire" is also accepted) "OptRadioSilence" -- enforce radio silence value (bool, default false) "OptNoReportWaypointPass" -- suppress waypoint-pass radio reports value (bool, default false) -- Engagement / weapons options -- "OptEngageAirWeapons" -- ground units and ships engage incoming air weapons (the editor offers it to vehicles and ships, not aircraft) value (bool, default true) "OptAAMissileAttackRange" -- air-to-air missile firing range discipline value: 0=MaxRange, 1=NoEscRange, 2=HalfWayRMaxNoEsc, 3=TargetThreatEst (default), 4=RandomRange "OptInterceptionRange" -- ED's "aircraft intercept range" (the editor offers it to vehicles and ships, not aircraft) value: 0 to 100 (default 100) -- Radio-usage options: which target types the AI calls out over the radio -- a REPORT filter, not an engage filter. value is one type or a list of them from the Mission Editor's Radio usage panel (e.g. "Planes" or ["Planes", "UAVs"]); "none" or [] ticks nothing. Default "All". -- "OptRadioUsageContact" -- types reported on initial contact "OptRadioUsageEngage" -- types reported when engaging "OptRadioUsageKill" -- types reported on a kill "OptFormation" -- set the group's flight formation (flying groups only) formation (required string; the variant/side/size is part of the name, case/underscore/space-insensitive). Valid: Fixed-wing: LineAbreast/Trail/Wedge/EchelonRight/EchelonLeft/ FingerFour/SpreadFour each x {Close, Open, GroupClose}; WW2_BomberElement{Close,Open}, WW2_BomberElementHeightSeperation, WW2_FighterVic{Close,Open}, ModernBomberFormation{Close,Open}. Rotary (helicopter): RotaryWedge, RotaryColumn, RotaryEchelonRight/Left {Small,Medium,Large}, RotaryFrontRight/Left {Small,Medium}. Unknown formation -> error listing the full set. Applying to a non-flying (vehicle/ship/static) group -> error. "Invisible" -- set unit invisible to AI value (bool, default true) "Immortal" -- set unit immortal value (bool, default true) "ActivateBeacon" -- emit a TACAN beacon (any group the Mission Editor offers it to: a unit with TACAN or air-to-air TACAN) tacan_channel (e.g. "42Y") OR channel (int) + band ("X"/"Y", default "X") tacan_callsign (3-letter ident, default "TKR") aa (bool -- omit it and the unit decides, as in the editor: false for a tanker, a ship or a vehicle, true for other aircraft) bearing (bool, default true) unit_id -- OMIT IT and the group's lead unit is used. Pass one to aim the beacon at a specific aircraft or ship. **unit_id: 0 is the editor's "Nothing" -- the beacon attaches to no unit and WILL NOT TRANSMIT.** It is accepted, and warned about, because ED's own missions occasionally name a unit outside the group. NOTE: frequency and beacon system are computed from the unit, channel, band and AA, as the editor computes them; do not pass Hz. "ActivateICLS" -- carrier ICLS beacon channel (int, default 1) name (str, optional) -- the ship's callsign, as ED writes it on about half its own ICLS actions. Omit it and none is written. unit_id -- omit for the group's lead. 0 means NO UNIT and the system will not transmit; accepted with a warning. "ActivateLink4" -- Link-4 datalink beacon frequency_mhz (default 336) -- 225.0 to 399.9, written in tenths of a MHz as the Mission Editor writes it: 251.55 is written 251.5, and the reply says so. name (str, optional) -- the ship's callsign, as for ICLS. unit_id -- omit for the group's lead. 0 means NO UNIT and the system will not transmit; accepted with a warning. "ActivateACLS" -- automatic carrier landing system unit_id -- omit for the group's lead. 0 means NO UNIT and the system will not transmit; accepted with a warning. "DeActivateBeacon" / "DeActivateLink4" / "DeActivateACLS" turn the corresponding beacon off (no params). Natural as a triggered action (see add_triggered_action). Returns {group_id, waypoint_index, added_task, task_index, task_count, enabled, warnings} -- NOT the waypoint. `task_index` is where the new task landed, which is what set_task_enabled and the removal path need; call get_route if you want the waypoint with its full tasks list. EVERY ACTION THE MISSION EDITOR OFFERS -- generated from DCS's own action table when the server starts, never typed out, so it follows a DCS update. Which of these a given group may have depends on its group task and its units, exactly as in the editor's ADD dropdown; a refusal names that group's own list. Names below are what task_type takes. Parameters are listed for actions not described above; a parameter marked * names a target -- a unit, group or zone. An action with targets is written only with one of them, given or filled in as the Mission Editor's panel fills it; a refusal names what is missing. PERFORM TASK (34): Aerobatics -- maneuvers_sequency AttachTrailer -- unit_id_tractor*, unit_id_trailer*, on_start_mission AttackGroup AttackMapObject AttackUnit Barcap Bombing BombingRunway CargoTransportation CargoTransportationPlane -- group_id, unit_id_transport, unit_id, x, y CargoUnloadPlane -- group_id, unit_id CarpetBombing DetachTrailer -- unit_id_tractor*, x, y Disembarking Embarking EmbarkToTransport EscortTaskAction ExternalCargoLoad -- group_id*, unit_id*, unit_id_transport* ExternalCargoUnLoad -- group_id*, unit_id_transport*, zone_id* FAC_AttackGroup FireAtPoint Follow GoToWaypoint GroundEscort -- last_wpt_index_flag, last_wpt_index, engagement_dist_max, target_types, group_id, unit_id Hold Land NoTask Orbit RecoveryTanker Refueling ShipHoldPoint Strafing TossAttack -- weapon_type, desired_angle, attack_qty, attack_type, altitude, altitude_enabled, direction, direction_enabled, expend, group_attack, speed, timing, x, y WWIIFollowBigFormation START ENROUTE TASK (15): AntiShip -- target_types, priority AWACS CAP -- target_types, priority CAS -- target_types, priority EngageGroup EngageTargets EngageTargetsInZone EngageUnit EWR -- callname, callsign, number FAC FAC_EngageGroup FighterSweep -- target_types, priority NoTask SEAD -- target_types, priority Tanker PERFORM COMMAND (30): ActivateACLS ActivateBeacon ActivateGCI -- unit_id*, channel, radius, x, y ActivateICLS ActivateJammer -- gps_spoofing, glonass_spoofing, radio_jamming, jamming_start, jamming_end, x, y ActivateLink4 ActivateRSBN -- channel, callsign DeactivateACLS DeactivateBeacon DeactivateGCI DeactivateICLS DeactivateJammer DeactivateLink4 DeactivateRSBN EPLRS LoadingShip -- cargo, unit_id NoAction RunScript RunScriptFile SetCallsign -- callname, callsign, number, callname_flag SetFrequency SetFrequencyForUnitCommand SetImmortal SetInvisible SetUnlimitedFuelCommand SmokeCommand StartCommand StopTransmission SwitchWaypoint TransmitMessage SET OPTION (34): ALARM_STATE ALLOW_FORMATION_SIDE_SWAP ALLOW_LINE_UP_RW ALT_RESTRICTION_MAX ALT_RESTRICTION_MIN DISENGAGE_AND_RTB EVASION_OF_ARM FORCED_ATTACK LANDING_OPTIONS OptAAMissileAttackRange OptChaffFlareUsing OptDisparseUnderFire OptECMUsing OptEngageAirWeapons OptFormation OptInterceptionRange OPTION_SET_COLUMN_INTERVAL OptJettisonEmptyTanks OptNoReportWaypointPass OptRadarUsing OptRadioSilence OptRadioUsageContact OptRadioUsageEngage OptRadioUsageKill OptRestrictAfterburner OptRestrictAirToAirAttack OptRestrictAirToGround OptRestrictJettison OptRestrictTargets OptRTBOnBingoFuel OptRTBOnOutOfAmmo PREFER_VERTICAL REACTION_ON_THREAT ROE
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypoint_indexintegerrequired
task_typestringrequired
paramsobject | nulloptional
enabledbooleanoptionalDefault: true.

Change an existing waypoint task's parameters in place.

Details · 6 parameters (4 required)
THE CASE THIS EXISTS FOR is a tanker's TACAN. The group-task tools write ED's own beacon on channel 1X and take no TACAN parameters, because the editor asks for none -- and until now there was no way to change it. `add_task` only ADDS, so a different channel meant TWO beacons on waypoint 0. MEASURED IN THE MISSION EDITOR 7 Sep 2026: an auto TACAN was edited from 1X to 11X, the edit survived save and reopen, and the action REMAINED FLAGGED `-a`. So editing an auto action is a state the editor produces, and it does not promote the action out of the auto set. DURABILITY. See `note` in the response -- an edit is durable in the file and is destroyed by a group task, unit type, country or coalition change in the editor. THE TASK IS REBUILT, NOT PATCHED, and that is deliberate: `params` goes through the same construction `add_task` uses, so an edit gets the same validation, the same TACAN unit binding and the same warnings -- a RunScript or RunScriptFile whose Lua doesn't compile is refused with Lua's own message, checked with DCS's own Lua and never run, as in add_task. It does NOT apply the editor's offer check: it can only edit a task already in the file, and refusing there would make a mission less editable than the editor makes it. Patching fields in place would have been a second, laxer write path onto the same tasks -- which is the shape every recent pass has found a defect in. **params CHANGES ONLY WHAT IT NAMES.** Every parameter you do not pass keeps the value the task already has -- change a tanker's TACAN channel and its callsign, bearing and air-to-air setting stay as they were. A value that follows from what you changed updates with it: a TACAN frequency follows its channel, and an attack moved to a new target keeps its weapon only while the editor offers that weapon against the new target. Otherwise it takes the editor's default, as the editor does. For a ControlledTask, `inner_params` works the same way: name only what changes in the wrapped task. If anything else changes anyway, the response's `warnings` names each field under `changed_without_being_asked`. The task's TYPE cannot change -- remove it and add the one you want. THE FILE'S NAMES ARE ACCEPTED TOO. A parameter may be named as get_route shows the stored task (attackQty, groupAttack ...) as well as by this tool's names; its value is read as the file holds it -- except where the file's name is also this tool's: `direction` is read in degrees, as this tool takes it, though the file holds radians. A switch such as attackQtyLimit or altitudeEnabled follows its value -- it is on when the value is given -- so it is accepted when it agrees with the rest of the edit and refused when it contradicts it. Named false on its own, a switch TURNS ITS SETTING OFF, keeping the stored value, as unticking it in the Mission Editor does: altitudeEnabled=false drops the attack altitude, directionEnabled=false the attack direction, maxDistEnabled=false an Engage Targets' distance. The same holds inside a ControlledTask's inner_params. A PARAMETER GIVEN AS null IS NOT NAMED: its current value is kept, and the response lists it under null_params_ignored -- inside inner_params too, listed as inner_params.<name>. A null never turns a setting off -- name its switch false. Preserved across the rebuild: the `auto` flag, the task's `number`, and its enabled state unless you pass `enabled`. task_index is the `index` field from get_route's per-waypoint `tasks` list. Indices do NOT shift -- this replaces in place. Returns the task before and after.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypoint_indexintegerrequired
task_indexintegerrequired
paramsobject | nulloptional
enabledboolean | nulloptional

Delete a waypoint task outright.

Details · 4 parameters (4 required)
Works on ED's auto actions too. NOT THE SAME AS set_task_enabled(enabled=False). A disabled task is still written to the file and shows in the editor as an unticked entry; this one is gone. Both are states the editor produces and a designer can tell them apart, so pick deliberately. AUTO ACTIONS CAN BE REMOVED, and that is measured rather than assumed. MEASURED IN THE MISSION EDITOR 7 Sep 2026: deleting `No Report on Waypoint Pass -a` from a CAP flight's waypoint 0 was accepted, survived save and reopen, and stayed gone. The `-a` flag marks where an action came from; it does not protect it. DURABILITY -- read this before relying on a removal. See `note` in the response -- an edit is durable in the file and is destroyed by a group task, unit type, country or coalition change in the editor. THE RENUMBERING IS THE EDITOR'S. Every task after the removed one has its `number` decremented, which is exactly what me_route.lua's updateAutoActions_ does when it removes an auto task. Skipping it leaves a gap in the sequence DCS writes. **task_index SHIFTS after a removal.** Everything below the removed entry moves up one. Removing several means re-reading get_route between calls, or removing from the highest index downwards. task_index is the `index` field from get_route's per-waypoint `tasks` list. A SCRIPT FILE OR MESSAGE SOUND GOES WITH ITS TASK, as the Mission Editor removes it: a ScriptFile or TransmitMessage task's file is removed from the mission when nothing else names it, and kept, and listed under files_kept, when something does. Returns what was removed, the resulting task count, and files_removed / files_kept.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypoint_indexintegerrequired
task_indexintegerrequired

Switch a waypoint task ON or OFF without removing it.

Details · 5 parameters (5 required)
THE CONSTRUCTION THIS EXISTS FOR is "engage only inside this zone", which was previously inexpressible through these tools. DCS gives a CAP or CAS flight a blanket `EngageTargets` derived from its group task, and that task engages everything in reach. Adding an `EngageTargetsInZone` alongside it does NOT narrow the flight -- the blanket task is still running, so the aircraft still leaves the zone to chase contacts. The designer's move is to DISABLE the blanket task and add the zoned one. 349 of DCS's own flights are built exactly that way, and 110 of its missions disable an EngageTargets somewhere. route = get_route(...) # find it in wp["tasks"] set_task_enabled(..., task_index=N, enabled=False) add_task(..., task_type="EngageTargetsInZone", params={...}) A disabled task is WRITTEN to the file and loaded by DCS; it simply does not run, and it shows in the editor as an unticked entry. This is not the same as deleting it, and the difference is visible to anyone who opens the mission. task_index is the `index` field from get_route's per-waypoint `tasks` list -- a position in the waypoint's full task list, not in the filtered view, so the number you read is the number you write. Returns the task's before/after state. Turning a task to the state it is already in is not an error and reports changed=False.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
waypoint_indexintegerrequired
task_indexintegerrequired
enabledbooleanrequired

Air defense & military sites12 tools

The site catalog: complete, correctly laid-out SAM sites for the SA-series, Patriot, Hawk, NASAMS and Rapier, plus EWR radars and FARPs. Each is built from the Mission Editor's own template and clears the trees around it.

Spawn an SA-2 S-75 Dvina (NATO: Guideline) SAM site.

Details · 12 parameters (5 required)
Composition (Mission Editor template, 15 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: 1 x SNR_75V -- Fan Song fire-control radar, centre 6 x S_75M_Volhov -- launchers ringing the radar 1 x p-19 s-125 sr -- Flat Face early-warning radar 2 x ZIL-131 KUNG -- guidance/support vans 1 x Ural-4320 APA-5D -- ground power 2 x ATMZ-5 -- fuel 2 x Ural-4320T -- transport All units are placed in ONE group, which is what makes the site function as an integrated system in DCS. heading: degrees the site faces (threat direction). 0=north. spacing_factor: scales all inter-unit distances (default 1.0). launcher_count: leave unset for the full Mission Editor composition. Setting it forces dcs-mcp's own simplified layout with that many launchers (1-6), because the ME template has a fixed unit list. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {radar, early_warning, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain" when terrain_check=True. composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
launcher_countinteger | nulloptional
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn an SA-3 S-125 Neva (NATO: Goa) SAM site.

Details · 12 parameters (5 required)
Composition (Mission Editor template, 12 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: Low Blow tracking radar, Flat Face search radar, 4 x 5p73 launchers, plus power and transport. All in ONE group. launcher_count: leave unset for the full Mission Editor composition. Setting it (1-6) forces dcs-mcp's own simplified layout, because the ME template has a fixed unit list. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {search_radar, tracking_radar, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
launcher_countinteger | nulloptional
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn an SA-5 S-200 (NATO: Gammon) long-range SAM site.

Details · 12 parameters (5 required)
Composition (Mission Editor template, 12 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: Square Pair tracking radar, search radar, S-200 launchers, plus support. All in ONE group. launcher_count: leave unset for the full Mission Editor composition. Setting it (1-6) forces dcs-mcp's own simplified layout, because the ME template has a fixed unit list. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {search_radar, tracking_radar, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
launcher_countinteger | nulloptional
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn an SA-6 Kub (NATO: Gainful) SAM site.

Details · 12 parameters (5 required)
Composition (Mission Editor template, 11 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: 1 x Kub 1S91 str SURN radar, 4 x Kub 2P25 ln TELARs, plus fuel, power and transport. All in ONE group, which is what makes the site engage. heading: degrees the site faces (threat direction). 0=north. spacing_factor: scales inter-unit distances (default 1.0). with_supply: force dcs-mcp's own simplified layout plus a Ural-375. The Mission Editor composition already includes support vehicles, so this is only needed to reproduce the pre-0.9.6 site. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {radar, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain" when terrain_check=True. composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
with_supplybooleanoptionalDefault: false.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn an SA-10 S-300PS (NATO: Grumble) SAM site.

Details · 11 parameters (5 required)
Composition (Mission Editor template, 18 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: Big Bird search radar, 40B6M tracking radar, 54K6 command post, launch vehicles and trailers, plus support. All in ONE group. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {search_radar, tracking_radar, command_post, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn an SA-11 Buk (NATO: Gadfly) SAM site.

Details · 11 parameters (5 required)
Composition (Mission Editor template, 12 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: Snow Drift search radar, 9S470M1 command post, TELARs, plus support. All in ONE group. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {search_radar, command, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn a MIM-104 Patriot SAM site.

Details · 11 parameters (5 required)
Composition (Mission Editor template, 20 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: STR radar, ECS, AMG, EPP, command post and launchers, plus support. All in ONE group. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {radar, ecs, amg, epp, command_post, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn a MIM-23 Hawk SAM site.

Details · 11 parameters (5 required)
Composition (Mission Editor template, 11 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: search radar, CWAR, tracking radar, platoon command post and launchers. All in ONE group. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {search_radar, cwar, tracking_radar, pcp, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn a NASAMS SAM site.

Details · 11 parameters (5 required)
Composition (Mission Editor template, 7 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: MPQ64F1 Sentinel radar, command post and launchers, plus support. All in ONE group. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {radar, command_post, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn a Rapier SAM site (UK SHORAD).

Details · 12 parameters (5 required)
Composition (Mission Editor template, 11 units) -- read from YOUR DCS install at runtime, so this is what you get WHEN DCS IS INSTALLED. Without it you get dcs-mcp's own simplified layout with a different unit count; the response's composition.source says which one you actually got: Blindfire radar, optical tracker, launchers, plus support. All in ONE group. launcher_count: leave unset for the full Mission Editor composition. Setting it (1-4) forces dcs-mcp's own simplified layout, because the ME template has a fixed unit list. terrain_check: validate slope over the site footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {blindfire_radar, optical_tracker, launchers: [...], support: [...]}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain". composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, chosen_by, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. chosen_by SAYS WHICH OF ED'S TEMPLATES WAS BUILT. "country": ED ships its own template of this system for the country you named, and that is the one built -- its units may not be the list above; unit_count and components say what was built. Where ED ships more than one for that country, the system's usual one is built, and that is "country" too; the others are reached by name. "default": ED ships none for that country, so the system's usual template was built. "name": the one you asked for in `template`. Absent when the layout is ours. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is THREE QUARTERS of the site radius and is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action. template: use a DIFFERENT Mission Editor template by name, including ONE YOU SAVED YOURSELF. Omitted => ED's template of this system for the country you named where it ships one, else the system's usual one; composition.chosen_by says which. A template you saved in the editor under a SHIPPED name, and different from ED's, is loaded as '<name>-copy' -- ED's own precedence, and what the editor's picker shows. An unknown name is refused and says how many templates are loaded from which file.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "high".
spacing_factornumberoptionalDefault: 1.0.
launcher_countinteger | nulloptional
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.
templatestring | nulloptional

Spawn a standalone Early Warning Radar (EWR) site.

Details · 12 parameters (5 required)
radar_type: one of '55G6 EWR' (Soviet Tall King -- default) '1L13 EWR' (Soviet Box Spring) 'Dog Ear radar' (Soviet; short range, often used with SA-6) 'p-19 s-125 sr' (Soviet P-19 Flat Face) 'P14_SR' (Tall King -- SA-5 search radar; standalone EWR-capable) 'FPS-117' (AN/FPS-117 long-range EWR -- NATO) 'FPS-117 Dome' (AN/FPS-117 in a radome -- NATO long-range EWR) (The 'FPS-117 ECS' variant is the equipment control shelter, not a standalone radar -- detection_range 0 in the catalog -- so it is not offered here, same reason 'Patriot ECS' is not an EWR. Use add_vehicle_group for it directly if ever needed.) For a single EWR with no guard, add_vehicle_group(vehicle_type=<radar_id>) is the simpler path; this macro adds value primarily via with_guard and the role-keyed return shape. For DCS's GCI station (KRU), the one unit that carries ActivateGCI, place GCI_station_MiG29 with add_vehicle_group. with_guard=True adds a ZSU-23-4 Shilka point defence vehicle, in the SAME group as the radar so the position reads as one object in triggers, consistent with every other site builder. DCS ships no Mission Editor template for a standalone EWR, so this builder uses dcs-mcp's own composition and layout. terrain_check: validate slope over the footprint (default true). slope_threshold_deg: slope limit in degrees (default 10). Returns: {site_name, group_id, group_ids, unit_count, unit_ids, components: {radar, guard (optional)}, composition, footprint_m, site_country, site_country_note, lat, lon} plus "terrain" key when terrain_check=True. composition SAYS WHOSE LAYOUT YOU GOT, and it is a fact about the mission rather than bookkeeping. Where DCS ships a Mission Editor template for this system the site is built from ED's own template; where it does not, it is built from dcs-mcp's simplified composition. The two are NOT interchangeable -- unit count and footprint can differ substantially, in either direction -- and this call's actual numbers are in unit_count and footprint_m beside it. {source, template, unit_count}, plus {reason} when the layout is ours. source is "dcs_mission_editor" or "builtin"; template names the ME template or is null. REASON IS PRESENT IF AND ONLY IF source is "builtin", so its presence alone answers "did I get ED's layout?" -- absent means yes. site_country IS THE COUNTRY THE SITE WAS BUILT UNDER. When the country you asked for does not field every unit of the layout in DCS, the whole site (one group) is built under CJTF of that side, which fields every type -- nothing is dropped or swapped -- and site_country_note says which units and why; null otherwise. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER. An air-defence site dropped into a forest is hidden by it, so one trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them. {zone_id, zone_name, radius, trigger_index}. radius is 100 m for the radar alone, and THREE QUARTERS of the site radius with its guard (with_guard); it is NOT footprint_m: the zone is a SEED, not a boundary. DCS removes every scenery tile the zone touches, entirely, so the ground cleared is several times the zone. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. The KEY is always present: this tool clears the site's trees ALWAYS (ruled 16 Sep 2026). THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT -- our terrain data has no tree layer, so a wooded site cannot be detected, only cleared, and trees block a site's radars and launchers. There is no parameter to turn it off; to keep the trees, delete the tree_clear zone afterwards with delete_zone, which takes its action out of the trigger -- and the trigger with its last action.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
radar_typestringoptionalDefault: "55G6 EWR".
headingnumberoptionalDefault: 0.0.
skillstringoptionalDefault: "average".
spacing_factornumberoptionalDefault: 1.0.
with_guardbooleanoptionalDefault: false.
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.

Place an OPERATIONAL, FUNCTIONAL FARP in one call.

Details · 12 parameters (5 required)
*** COALITION IS THE ONE CHOICE YOU CANNOT CHANGE AFTERWARDS. *** It selects the SERVICE VEHICLES, and the two sides need different ones. There is no tool that converts a FARP from blue to red: moving its country with set_country_coalition takes the pad and the vehicles across intact and leaves a site that looks complete and services nothing (that tool warns, and the warning names the FARPs). The fix is always delete and rebuild: delete_group on the pad (group_id) also removes the support group and the statics this call built with it. A FARP read from a file has no such record -- delete its pad, its support group and each static by their own ids. So pick the side first. Creates the actual FARP heliport pad (a static group in the Heliports category), an unlimited warehouse, and ALWAYS the coalition's required ground-support vehicle set within 150 m of the pad centre, plus the matching role statics -- a pad a helicopter can spawn on (via a task tool's pad_group_id) AND one that actually rearms/refuels/repairs/powers/ATCs in-game. THIS CALL PLACES A WORKING FARP AND STOPS. What it builds varies in one way only -- THE PAD TYPE. Everything else is fixed by the coalition: the pad, the service roster and its statics, the unlimited warehouse, a radio identity of its own, and the tree clearing described below. The other parameters say where it goes, what it is called, how its crews are skilled, or pin its radio; none of them adds or removes anything from the site. ANYTHING BEYOND THE WORKING SET IS A SEPARATE, SPECIFIC REQUEST, made after this call: add_vehicle_group air defence, or any other group add_static lighting, extra structures, set dressing placed relative to the FARP -- "put an Avenger 500 m north of the FARP" is the shape. If the user asked for a defended or a lit FARP, make those calls too, with the types they named; if they named none, offer a choice or ask. SERVICE MODEL (a DCS engine rule): a FARP provides a service only while something that provides it is alive within 150 m of centre -- its vehicle or, for every service but power, the matching FARP static. Either is enough: flown for fuel, where the Fuel Depot static alone and the tanker alone each refuelled, and a tanker at 200 m with no depot did not. This call places both. Blue: M978 (refuel), M 818 (rearm+power+repair), M1043 HMMWV (ATC/comms). Red: ATMZ-5 (refuel), Ural-4320T (rearm and repair), Ural-4320 APA-5D (power), SKP-11 (ATC/comms). Blue ATC is the M1043, flown and confirmed for ATC and comms on 10 Sep 2026. (The manual names the M1025, type `Hummer`, which is also placeable; the M1043 stays because it is the one proven in the sim.) SERVICE GOES BY DISTANCE, NOT BY OWNERSHIP. DCS serves a FARP from every unit of its side within 150 m of its centre, whichever FARP the unit was built for. Two FARPs closer than about 300 m share: a vehicle within 150 m of both serves both. That is DCS's rule, not a limit of this tool -- and validate reads overlapping FARPs the same way. THE 4-PAD FARP ("FARP") IS A LEVEL MAT 259 m SQUARE, laid near the height of the higher ground under it. A mission's statics stand on the mat, but its vehicles stand on the terrain -- under the mat wherever the ground is lower. So its support trucks stand in a line just off the mat's pad-free edge, 137 m out (inside the 150 m service radius), and its statics on the mat, 80 m out. Its terrain block reports mat_height_range_m, how much the ground under the mat varies, and warns above 3 m: the mat then floats over the lower ground, and the higher ground and brush show through it. coalition: "blue" | "red". It SELECTS THE ROSTER above, so there is no neutral FARP -- there is no neutral roster, and a neutral country owns no units. country: a DCS country in that coalition. name: unique group name (collision raises). position: pad centre -- {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. farp_type: "SingleHeliPad" (default, one working pad), "FARP" (4-pad), or "InvisibleFARP". Unknown -> loud error listing the valid set. heading: pad heading in degrees (default 0). frequency_mhz: FARP ATC radio frequency in MHz. Omit it and each FARP gets its own, starting at 127.5 -- the most common FARP frequency in DCS's shipped missions -- and stepping 0.05, the granularity every VHF airfield ATC frequency across all eleven theaters sits on. Unique across the whole loaded mission, not just this call. callsign_id: which of DCS's ten heliport callsigns (1-10). Omit it and the lowest one not already used ANYWHERE in this mission is assigned. The Mission Editor gives EVERY FARP the same frequency and the same callsign, so two FARPs in one mission are indistinguishable on the radio. Both are now unique. Either can still be set explicitly, and an explicit duplicate is allowed with a warning rather than refused. The two ceilings differ: callsigns run out at ten and frequencies do not. Past the tenth FARP the callsign repeats while the frequency keeps stepping, and the response says which limit was hit. NOT checked: the assigned frequency against the map's airfield ATC frequencies, and 127.5 is already one of them. Much less harmful than a TACAN collision -- radio range is short and you tune deliberately rather than having an aircraft lock it automatically -- but it is unchecked. THE WAREHOUSE IS ALWAYS UNLIMITED -- fuel, munitions and aircraft. Rearming and refuelling draw on it, so it is part of the working set and not an option. It is WRITTEN EXPLICITLY rather than left to the library's default, so a value the FARP depends on does not rest on one. To limit or stock it, change it afterwards with set_warehouse_properties or set_warehouse_inventory. THE SUPPORT ROSTER AND ITS STATICS ARE ALWAYS PLACED -- every required group and static for the coalition, and nothing more. terrain_check / slope_threshold_deg: slope guard at the pad centre. The FARP is referenced two ways (there is no separate airdrome-space id -- FARPs do not appear in list_airfields): use the returned group_id for a task tool with pad_group_id=... to spawn helis on the pad, and the returned farp_unit_id for get_warehouse / set_warehouse_properties / add_warehouse_supplier. Returns: {group_id, farp_unit_id, name, type, coalition, lat, lon, heading, frequency_mhz, warehouse:{unlimited flags}, support_vehicles:[], statics:[], tree_clear} plus "terrain" when terrain_check, and "warnings" when the FARP shares a callsign or frequency with another. SIDE EFFECT -- THIS TOOL ADDS A ZONE TO THE MISSION, AND AN ACTION TO ITS "Tree clearing" TRIGGER, ALWAYS. One trigger zone is placed over the site, and the mission's one "Tree clearing" trigger -- a TriggerStart, made by the first site that needs it -- gets an a_remove_scene_objects action, trees only, on it. A caller that counts zones or reads triggers will find objects it did not create; "tree_clear" is how it accounts for them: {zone_id, zone_name, radius, trigger_index}. trigger_index is that trigger's, the same for every site, and 0-BASED; the saved mission numbers trigrules from 1. THE SITE IS CLEARED BECAUSE WE CANNOT TELL WHETHER IT NEEDS IT. The terrain data this server reads has no tree layer -- it reports LAND and buildings, and nothing about trees, at every point sampled -- so a wooded site cannot be detected, only cleared. And trees at a FARP are not a question of service: a FARP is where helicopters land and take off, and a tree there is an obstruction. There is no parameter to turn it off. To keep the trees -- concealment -- take the clear back afterwards with delete_zone(zone_id=tree_clear.zone_id), which takes its action out of the "Tree clearing" trigger -- and the trigger with its last action.
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
countrystringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
farp_typestringoptionalDefault: "SingleHeliPad".
headingnumberoptionalDefault: 0.0.
frequency_mhznumber | nulloptional
callsign_idinteger | nulloptional
skillstringoptionalDefault: "average".
terrain_checkbooleanoptionalDefault: true.
slope_threshold_degnumberoptionalDefault: 10.0.

Triggers, zones & goals17 tools

Mission logic: triggers and triggered actions, circular and polygon zones, zone membership tests, and scored mission goals.

Add a mission trigger (conditions + actions).

Details · 5 parameters (2 required)
trigger_type: "once" | "continuous" | "start" - "once" fires once when all conditions are true - "continuous" fires every frame while conditions are true - "start" fires once at mission start (ignores conditions) conditions: list of {type, params} dicts (all must be true for trigger to fire). group params accept "group_id" or "group"; unit params accept "unit_name", "unit_id" or "unit"; a moving zone's unit accepts "zone_unit_name" or "zone_unit_id". Every unit, group and zone must exist in the mission -- an unknown one is refused. Required params raise ValueError if missing. A flag (flag, flag2) is a name or a number, written as text, as the Mission Editor writes flags. A number field takes a number within the Mission Editor's range for it; text, or true or false, is refused. Time: seconds are ELAPSED MISSION TIME, counted from mission start. They are NOT clock time and NOT offset from the mission's start_time, so a mission starting at 12:00 with TimeAfter 600 fires at 12:10. {"type": "TimeAfter", "params": {"seconds": 60}} {"type": "TimeBefore", "params": {"seconds": 120}} {"type": "TimeSinceFlag", "params": {"flag": 1, "seconds": 30}} Flags: {"type": "FlagIsTrue", "params": {"flag": 1}} {"type": "FlagIsFalse", "params": {"flag": 1}} {"type": "FlagEquals", "params": {"flag": 1, "value": 5}} {"type": "FlagIsLess", "params": {"flag": 1, "value": 5}} {"type": "FlagIsMore", "params": {"flag": 1, "value": 5}} {"type": "FlagEqualsFlag", "params": {"flag": 1, "flag2": 2}} {"type": "FlagIsLessThanFlag","params": {"flag": 1, "flag2": 2}} Group/unit life: {"type": "GroupDead", "params": {"group_id": 42}} {"type": "GroupAlive", "params": {"group_id": 42}} {"type": "GroupLifeLess", "params": {"group_id": 42, "percent": 50}} {"type": "UnitAlive", "params": {"unit_id": 91}} {"type": "UnitDead", "params": {"unit_id": 91}} {"type": "UnitDamaged", "params": {"unit_id": 91}} {"type": "UnitLifeLess", "params": {"unit_id": 91, "percent": 50}} Group-zone: {"type": "PartOfGroupInZone", "params": {"group_id": 42, "zone_id": 1}} {"type": "AllOfGroupInZone", "params": {"group_id": 42, "zone_id": 1}} {"type": "AllOfGroupOutsideZone", "params": {"group_id": 42, "zone_id": 1}} {"type": "PartOfGroupOutsideZone","params": {"group_id": 42, "zone_id": 1}} Unit-zone: {"type": "UnitInZone", "params": {"unit_id": 91, "zone_id": 1}} {"type": "UnitOutsideZone", "params": {"unit_id": 91, "zone_id": 1}} {"type": "UnitInMovingZone", "params": {"unit_id": 91, "zone_id": 200, "zone_unit_id": 5}} {"type": "UnitOutsideMovingZone", "params": {"unit_id": 91, "zone_id": 200, "zone_unit_id": 5}} Coalition-zone (coalitionlist: "red"|"blue"|"neutral", as the Mission Editor offers; unit_type: "ALL"|"AIRPLANE"|"HELICOPTER"|"NAVAL"|"GROUND", the Mission Editor's five, default "ALL", in any case ("airplane" is AIRPLANE). "Plane", "Vehicle" and "Ship", in any case, are taken as AIRPLANE, GROUND and NAVAL; anything else is refused): {"type": "AllOfCoalitionInZone", "params": {"coalitionlist": "blue", "zone_id": 1}} {"type": "AllOfCoalitionOutsideZone", "params": {"coalitionlist": "red", "zone_id": 1}} {"type": "PartOfCoalitionInZone", "params": {"coalitionlist": "red", "zone_id": 1, "unit_type": "AIRPLANE"}} {"type": "PartOfCoalitionOutsideZone","params": {"coalitionlist": "blue", "zone_id": 1}} Unit altitude/speed/attitude: {"type": "UnitAltitudeHigher", "params": {"unit_id": 91, "altitude": 3000}} {"type": "UnitAltitudeLower", "params": {"unit_id": 91, "altitude": 3000}} {"type": "UnitAltitudeHigherAGL", "params": {"unit_id": 91, "altitude": 100}} {"type": "UnitAltitudeLowerAGL", "params": {"unit_id": 91, "altitude": 100}} {"type": "UnitSpeedHigher", "params": {"unit_id": 91, "speed": 200}} {"type": "UnitSpeedLower", "params": {"unit_id": 91, "speed": 200}} {"type": "UnitVerticalSpeedWithin", "params": {"unit_id": 91, "min_speed": -10, "max_speed": 10}} {"type": "UnitBankWithin", "params": {"unit_id": 91, "min_bank": -30, "max_bank": 30}} {"type": "UnitPitchWithin", "params": {"unit_id": 91, "min_pitch": -10, "max_pitch": 10}} {"type": "UnitHeadingWithin", "params": {"unit_id": 91, "min_heading": 0, "max_heading": 90}} Weapons/cargo in zone: {"type": "BombInZone", "params": {"zone_id": 1}} {"type": "MissileInZone", "params": {"zone_id": 1}} {"type": "SignalFlareInZone", "params": {"zone_id": 1, "color": 0}} {"type": "CargoUnhookedInZone", "params": {"cargo_id": 5, "zone_id": 1}} Airbase/helipad ownership: {"type": "CoalitionHasAirdrome","params": {"coalitionlist": "blue", "airdrome_id": 22}} {"type": "CoalitionHasHelipad", "params": {"coalitionlist": "blue", "helipad_id": 99}} Map/scoring: {"type": "MapObjectIsDead", "params": {"zone_id": 1}} {"type": "MissionScoreHigher", "params": {"coalitionlist": "blue", "score": 100}} {"type": "MissionScoreLower", "params": {"coalitionlist": "red", "score": 50}} {"type": "PlayerScoreLess", "params": {"scores": 50}} {"type": "PlayerScoreMore", "params": {"scores": 200}} Misc: {"type": "Random", "params": {"percent": 50}} {"type": "Or", "params": {}} Cockpit-state (training missions; no unit param -- cockpit-wide): {"type": "ArgumentInRange", "params": {"argument": 5, "min_value": 0.0, "max_value": 1.0}} {"type": "IndicationTextEqual", "params": {"indicator_id": 1, "element_name": "foo", "element_value": "bar"}} {"type": "CockpitHighlightVisible", "params": {"highlight_id": 1}} {"type": "CockpitParamEqual", "params": {"parameter": "param_name", "value": "1"}} {"type": "CockpitParamEqualToAnother","params": {"parameter": "p1", "parameter2": "p2"}} {"type": "CockpitParamInRange", "params": {"parameter": "p1", "min_value": 0.0, "max_value": 1.0}} actions: list of {type, params} dicts executed when trigger fires: {"type": "MessageToAll", "params": {"text": "...", "seconds": 10}} {"type": "MessageToBlue", "params": {"text": "...", "seconds": 10}} {"type": "MessageToRed", "params": {"text": "...", "seconds": 10}} Every message action also takes clearview (bool) and start_delay (seconds before it shows, default 0). A yes/no parameter (clearview, readonly, loop, mic_effects) takes true or false; anything else is refused. squelch_effects takes only true: the Mission Editor compiles false as squelch's default, on, so false is refused. {"type": "SetFlag", "params": {"flag": 1}} {"type": "ClearFlag", "params": {"flag": 1}} {"type": "IncreaseFlag", "params": {"flag": 1, "value": 1}} {"type": "DecreaseFlag", "params": {"flag": 1, "value": 1}} {"type": "SetFlagValue", "params": {"flag": 1, "value": 42}} {"type": "DoScript", "params": {"script": "trigger.action.outText(...)"}} {"type": "ActivateGroup", "params": {"group_id": 42}} {"type": "DeactivateGroup", "params": {"group_id": 42}} {"type": "Explosion", "params": {"zone": "ZoneName" | <zoneId int>, "altitude": 1, "volume": 1000}} {"type": "SetFlagRandom", "params": {"flag": 1, "min_value": 0, "max_value": 100}} F10 map markers (marker_id: the mark's id, a whole number 1-100 -- left out, 10, the Mission Editor's seed, which it gives every new mark; zone_id: int zone id): {"type": "MarkToAll", "params": {"marker_id": 1, "zone_id": 1, "text": "...", "comment": "...", "readonly": true}} {"type": "MarkToCoalition", "params": {"marker_id": 1, "zone_id": 1, "coalition": "blue", "text": "...", "comment": "..."}} {"type": "MarkToGroup", "params": {"marker_id": 1, "zone_id": 1, "group_id": 42, "text": "..."}} Radio menu (radiotext: display label, flag: set when item clicked, value: flag value): {"type": "AddRadioItem", "params": {"radiotext": "Call CAS", "flag": 5, "value": 1}} {"type": "AddRadioItemForCoalition", "params": {"coalition": "blue", "radiotext": "Call CAS", "flag": 5, "value": 1}} {"type": "AddRadioItemForGroup", "params": {"group_id": 42, "radiotext": "Rejoin", "flag": 6, "value": 1}} {"type": "RemoveRadioItem", "params": {"radiotext": "Call CAS"}} {"type": "RemoveRadioItemForCoalition","params": {"coalition": "blue", "radiotext": "Call CAS"}} {"type": "RemoveRadioItemForGroup", "params": {"group_id": 42, "radiotext": "Rejoin"}} Embedded media and scripts -- sounds, pictures, Lua files. All of these take resource_key: embed the file first with add_resource(filepath), which returns "ResKey_Action_N", then pass that key here. Picture actions share the same optional display parameters: seconds (default 10), clearview, start_delay, horz_alignment ("left"|"center"|"right"), vert_alignment ("top"|"center"|"bottom"), size, size_units. {"type": "SoundToAll", "params": {"resource_key": "ResKey_Action_5"}} {"type": "SoundToCoalition", "params": {"coalitionlist": "blue", "resource_key": "ResKey_Action_5"}} {"type": "SoundToCountry", "params": {"country": "USA", "resource_key": "ResKey_Action_5"}} {"type": "SoundToGroup", "params": {"group_id": 42, "resource_key": "ResKey_Action_5"}} {"type": "SoundToUnit", "params": {"unit_name": "Enfield 1-1", "resource_key": "ResKey_Action_5"}} {"type": "PictureToAll", "params": {"resource_key": "ResKey_Action_6", "seconds": 30}} {"type": "PictureToCoalition", "params": {"coalitionlist": "blue", "resource_key": "ResKey_Action_6", "seconds": 30}} {"type": "PictureToCountry", "params": {"country": "USA", "resource_key": "ResKey_Action_6"}} {"type": "PictureToGroup", "params": {"group_id": 42, "resource_key": "ResKey_Action_6"}} {"type": "PictureToUnit", "params": {"unit_id": 7, "resource_key": "ResKey_Action_6"}} {"type": "DoScriptFile", "params": {"resource_key": "ResKey_Action_7"}} {"type": "RadioTransmission", "params": {"resource_key": "ResKey_Action_8", "frequency_mhz": 124.0, "modulation": "AM", "power": 100, "loop": false, "name": "ATIS", "zone_id": 1}} RadioTransmission REQUIRES zone_id: the transmitter stands in that zone and DCS transmits from its position -- with no zone, no one hears it (verified in-sim). SoundToUnit takes unit_name or unit_id (DCS stores the id; a name is resolved to it), as do PictureToUnit and MessageToUnit. Every sound action also takes start_delay (seconds before it plays, default 0). group_id/group, unit_id/unit and coalitionlist/coalition are each accepted as either spelling -- supply one of the pair, not both. Cockpit element highlight (training missions -- the mechanism ED's own startup tutorials use). highlight_id is a HANDLE you choose: CockpitRemoveHighlight clears the highlight with the same id, so the two go in pairs. element_name is PER-AIRCRAFT and is passed straight through -- it is not validated against any list, because the names differ by module (the AH-64D uses "pnt_57"-style names, the UH-1H uses "PHASE-SWITCHER-PTR"), and a list would reject a legitimate element the day a new module ships. Read the names out of a shipped training mission for the aircraft you are targeting. size_of_box defaults to 0, which is what ED writes in almost every shipped mission. ITS EFFECT IS UNVERIFIED -- the only non-zero values are 0.05s in the UH-1H startup tutorial and nobody here has flown the difference, so do not infer units or semantics from that. {"type": "CockpitHighlight", "params": {"highlight_id": 1, "element_name": "pnt_57", "size_of_box": 0}} {"type": "CockpitRemoveHighlight", "params": {"highlight_id": 1}} CockpitHighlightPosition highlights a POINT IN COCKPIT SPACE instead of a named element -- use it when the thing you want to draw attention to has no element name. Same handle: CockpitRemoveHighlight with the matching highlight_id clears it. A coordinate left out takes the Mission Editor's seed for a new action: x 1, y 0, z 0. In ED's own shipped blocks in_cockpit_position_x is almost always 1, y ranges -0.92 to 0.03 and z ranges -0.42 to 0.55 -- so x varies little and y/z are where the aiming happens. The box is a cube: size_of_box_x/y/z are usually 0.1 (sometimes 0.15), and default to 0.1 here. Unlike the element form's size_of_box, these carry a real range in shipped content rather than sitting at a single value. {"type": "CockpitHighlightPosition", "params": {"highlight_id": 2, "in_cockpit_position_x": 1, "in_cockpit_position_y": -0.62, "in_cockpit_position_z": 0.15, "size_of_box_x": 0.1, "size_of_box_y": 0.1, "size_of_box_z": 0.1}} Mission flow: {"type": "EndMission", "params": {"winner": "blue", "text": "Mission complete!"}} {"type": "LoadMission", "params": {"file": "missions/next.miz"}} AI control (group_id actions use int group id; unit actions take unit_name or unit_id -- DCS stores the id, and a name is resolved to it): {"type": "GroupAIOff", "params": {"group_id": 42}} {"type": "GroupAIOn", "params": {"group_id": 42}} {"type": "GroupStop", "params": {"group_id": 42}} {"type": "GroupResume", "params": {"group_id": 42}} {"type": "UnitAIOff", "params": {"unit_name": "Enfield 1-1"}} {"type": "UnitAIOn", "params": {"unit_name": "Enfield 1-1"}} {"type": "UnitEmissionOff", "params": {"unit_name": "SAM-1"}} {"type": "UnitEmissionOn", "params": {"unit_name": "SAM-1"}} {"type": "AITaskPush", "params": {"group_id": 42, "task_index": 1}} {"type": "AITaskSet", "params": {"group_id": 42, "task_index": 1}} Targeted messages: {"type": "MessageToCoalition", "params": {"coalition": "blue", "text": "...", "seconds": 10}} {"type": "MessageToCountry", "params": {"country": "USA", "text": "...", "seconds": 10}} {"type": "MessageToGroup", "params": {"group_id": 42, "text": "...", "seconds": 10}} {"type": "MessageToUnit", "params": {"unit_id": 91, "text": "...", "seconds": 10, "start_delay": 0}} Effects. For the zone-effect actions below (Explosion above, ExplodeWPMarker, IlluminatingBomb, SignalFlare, SceneryDestructionZone, ZoneIncrementResize) 'zone' accepts a zone NAME or an integer zoneId; the named zone must exist (it is resolved to its integer zoneId, which is what DCS stores). A unit is given as unit_name or unit_id: DCS stores the unit's ID, so a name is resolved to it and must exist: {"type": "ExplodeUnit", "params": {"unit_name": "SAM-1", "volume": 1000}} {"type": "ExplodeWPMarker", "params": {"zone": "ZoneName", "altitude": 1, "color": 0, "name": "marker"}} {"type": "ExplodeWPMarkerOnUnit","params": {"unit_name": "SAM-1", "color": 0}} {"type": "IlluminatingBomb", "params": {"zone": "ZoneName" | <zoneId int>, "altitude": 1}} {"type": "SignalFlare", "params": {"zone": "ZoneName" | <zoneId int>, "altitude": 1, "color": 0, "bearing": 0}} {"type": "SignalFlareOnUnit", "params": {"unit_name": "SAM-1", "color": 0, "bearing": 0}} Cargo / scenery: {"type": "SetInternalCargo", "params": {"cargo_mass": 500}} {"type": "FallInTemplate", "params": {"group_id": 42, "template": "template_name"}} {"type": "SceneryDestructionZone","params": {"zone": "ZoneName" | <zoneId int>, "destruction_level": 100}} {"type": "ZoneIncrementResize", "params": {"zone": "ZoneName" | <zoneId int>, "meters": 1000}} Returns the index of the new trigger in the trigger list and a summary. A parameter given as null inside a condition or action is not given: it is built as if left out, and the response lists it under null_params_ignored.
ParameterTypeDescription
mission_idstringrequired
trigger_typestringrequired
conditionsobject[] | nulloptional
actionsobject[] | nulloptional
commentstringoptional

Partially update an existing trigger by its 0-based index.

Details · 6 parameters (2 required)
trigger_index: 0-based index as returned by add_trigger. Must be in range. trigger_type: If provided, changes the trigger subclass ("once" / "continuous" / "start"). Conditions and actions are preserved unless also provided. comment: If provided, replaces the trigger comment. Otherwise preserved. conditions: If provided, FULLY REPLACES the existing condition list with the new list (same {type, params} format as add_trigger). Pass [] to clear all conditions. actions: If provided, FULLY REPLACES the existing action list with the new list. Pass [] to clear all actions. All fields are optional -- calling with only trigger_index is a no-op that returns the trigger's current state (useful for inspection). Validation is identical to add_trigger: unknown types and missing required params raise ValueError before any mutation occurs. Returns the same shape as add_trigger. A parameter given as null inside a condition or action is not given: it is built as if left out, and the response lists it under null_params_ignored.
ParameterTypeDescription
mission_idstringrequired
trigger_indexintegerrequired
trigger_typestring | nulloptional
commentstring | nulloptional
conditionsobject[] | nulloptional
actionsobject[] | nulloptional

Remove a trigger by its 0-based index.

Details · 2 parameters (2 required)
trigger_index: 0-based index as returned by add_trigger. Must be in range. WARNING: Deleting a trigger shifts all higher-indexed triggers down by one. If you need to delete multiple triggers, delete from highest index to lowest to avoid index confusion, or call get_raw_lua('trigrules') after each deletion to refresh your view of current indices. Returns metadata about the deleted trigger plus a renumbered flag that is True when any downstream triggers shifted (i.e. deleted trigger was not last).
ParameterTypeDescription
mission_idstringrequired
trigger_indexintegerrequired

Add a group-level triggered action (DCS "Triggered Actions").

Details · 4 parameters (3 required)
Companion to add_task. Where add_task writes to a waypoint's task list (the task fires automatically when the group reaches that waypoint), add_triggered_action writes to the group's own task list (group.tasks[N]). A triggered action does NOT fire on its own -- it sits dormant until a trigger invokes it via an AITaskPush or AITaskSet action (see add_trigger), keyed by the 1-based task_index this tool returns. There is no waypoint_index parameter -- the action is attached to the group, not a route point. task_type and params are IDENTICAL to add_task -- the same actions, the same param shape and validation for each. See add_task's docstring for the per-type param reference, and the catalogue at the end of add_task's description for every action the Mission Editor offers. That catalogue is generated at startup from the editor's own action table on your DCS install, so it is the complete and current list. A RunScript or RunScriptFile whose Lua doesn't compile is refused with Lua's own message, checked with DCS's own Lua and never run. If DCS's Lua can't be loaded, the script is taken unchecked, with a lua_not_checked warning. Which types are NATURAL as triggered actions (commands / options you toggle on a trigger): SetFrequency, RunScript, EPLRS, ROE, ReactionOnThreat, AlarmState, OptRTBOnBingoFuel, OptRTBOnOutOfAmmo, OptRadarUsing, OptECMUsing, and the rest of the Opt* family (restrict-class, chaff/flare, radio usage, interception range, etc. -- see add_task for the full list), Invisible, Immortal, and the beacon family (ActivateBeacon / ActivateICLS / ActivateLink4 / ActivateACLS and their DeActivate counterparts -- e.g. switch a tanker's TACAN off when it leaves station). Which are UNUSUAL here (their natural home is a waypoint; this tool refuses at group level what the editor does not offer there): Orbit, AttackGroup, EngageGroup, EngageTargets, Hold, GoToWaypoint. GoToWaypoint in particular references route waypoint indices and is rarely meaningful as a triggered action -- allowed, but think twice. Only flying, vehicle, and ship groups have a triggered-action list. Static objects do not -- calling this on a static raises. Returns: { "group_id": int, "task_index": int, # 1-based position in group.tasks; pass this # to add_trigger's AITaskPush / AITaskSet # actions as "task_index" to invoke it "task_count": int, # total triggered actions now on the group "added_task": dict, # the written task (same shape as add_task's # "added_task") } A key in params given as null is not given: the action is built as if it were left out, and the response lists it under null_params_ignored -- inside a ControlledTask's inner_params too, as inner_params.<name>.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
task_typestringrequired
paramsobject | nulloptional

Add a circular trigger zone to the mission.

Details · 6 parameters (3 required)
position: {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}, as the replies give positions -- exactly one form. radius_m: zone radius in metres (default 3000, as the Mission Editor starts a zone) hidden: whether the zone is hidden in the ME (default false) color: optional RGBA dict {1: r, 2: g, 3: b, 4: a} with values 0.0-1.0. Defaults to white with 15% opacity if omitted. A name another zone has is refused: the Mission Editor renames a second zone of one name when it opens the file. Returns the new zone's id, name, radius, and position.
ParameterTypeDescription
mission_idstringrequired
namestringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
radius_mnumberoptionalDefault: 3000.0.
hiddenbooleanoptionalDefault: false.
colorobject | nulloptional

Add a polygon (quad) trigger zone to the mission.

Details · 6 parameters (3 required)
Polygons in DCS are exactly 4-vertex quads, concave or convex. Self-intersecting (bowtie) quads are rejected as malformed, and so is a quad that encloses no area (its points on one spot or one line), which no unit could ever be inside. A name another zone has is refused: the Mission Editor renames a second zone of one name when it opens the file. vertices: list of exactly 4 positions, each {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}. Vertex order is preserved; centroid is computed automatically. This tool's own reply gives each vertex and the centroid both ways (lat, lon, x and y): pass one of them. hidden: whether the zone is hidden in the ME (default false) color: optional RGBA dict {1: r, 2: g, 3: b, 4: a} with values 0.0-1.0. Defaults to white with 15% opacity if omitted. properties: optional dict of user metadata {key: value}. Defaults to {}. Keys and values must be JSON-safe (strings, numbers, booleans, null); an object or a list as a value is refused. Each value is written as text, as the Mission Editor's zone panel holds it: a number as its digits (5 and 5.0 both "5"), true and false as "true" and "false". A number is written in its shortest exact digits with no exponent (1e-7 as "0.0000001"), and null as "", the panel's empty value. Returns the new zone's id, name, shape, type, vertices and centroid (each lat, lon, x and y), color, and properties. Raises ValueError if: - vertices count != 4 - any vertex is unparseable (invalid Position) - quad is self-intersecting (bowtie) - quad encloses less than 1 square metre - another zone has the name
ParameterTypeDescription
mission_idstringrequired
namestringrequired
verticesPosition[]required
hiddenbooleanoptionalDefault: false.
colorobject | nulloptional
propertiesobject | nulloptional

Modify an existing trigger zone's mutable attributes.

Details · 8 parameters (2 required)
Identified by zone_id (stable; never changes). Shape is immutable -- passing radius to a polygon zone or vertices to a circle zone is an error. To change shape, delete and re-create the zone. Parameters (all optional; only provided fields are applied): name: new name. Rename triggers a safety scan: DCS references a zone by its integer zoneId, which a rename does not touch, but a file written by an older tool can hold a zone NAME as a string. If any reference the current name, the rename is refused with a clear error naming the references. hidden: new hidden flag. color: RGBA dict {1: r, 2: g, 3: b, 4: a} with values 0.0-1.0. Fully replaces the existing color. properties: clean {key: value} dict. FULLY REPLACES the zone's property set -- to remove a property, omit it from the new dict. To merge, read current properties via list_zones, modify, then pass the full set back. Stored on-disk in DCS/ME's 1-indexed {key,value} table form (matches add_polygon_zone behaviour). Each value is written as text, as the Mission Editor's zone panel holds it: a number as its digits (5 and 5.0 both "5"), true and false as "true" and "false". A number is written in its shortest exact digits with no exponent (1e-7 as "0.0000001"), and null as "", the panel's empty value. Not given, the zone's properties stay as they are, as the file has them. radius: new radius in metres (CIRCLE ZONES ONLY). vertices: list of exactly 4 Positions (POLYGON ZONES ONLY). Same geometry validation as add_polygon_zone -- bowtie and no area rejected, concave accepted. The centroid is recomputed automatically. A name another zone has is refused: the Mission Editor renames a second zone of one name when it opens the file. A refusal changes nothing, whichever parameter it names. zone_id is never changed. Returns the modified zone in the same shape as list_zones.
ParameterTypeDescription
mission_idstringrequired
zone_idintegerrequired
namestring | nulloptional
hiddenboolean | nulloptional
colorobject | nulloptional
propertiesobject | nulloptional
radiusnumber | nulloptional
verticesPosition[] | nulloptional

Delete a trigger zone by zone_id.

Details · 3 parameters (2 required)
Safety: scans every construct that can reference a zone -- every trigger condition, every trigger action, every goal condition, and every CargoTransportation task -- for both integer-id references (zone == zone_id: how DCS stores every trigger zone reference) AND string-name references (zone == the zone's current name, found only in files written by older tools). The scan keys on the stored value's type (int vs str), so it stays correct whichever form a file holds. Behaviour: - If the zone is unreferenced, it is deleted cleanly. - If references exist and force=False (default), the deletion is refused with a clear error listing every referencing construct. - If force=True, the deletion proceeds and every now-orphaned reference is returned in the result so the damage is visible. zoneId is allocated monotonically and is stable across deletes -- removing a zone does NOT renumber any other zone, and a later zone never takes a deleted zone's id. Trigger references to OTHER zones remain valid. Returns: {deleted: {id, name, shape, ...}, references_orphaned: [...]}
ParameterTypeDescription
mission_idstringrequired
zone_idintegerrequired
forcebooleanoptionalDefault: false.

List all trigger zones in the mission, with full details.

Details · 1 parameters (1 required)
Returns for each zone: id, name, position, hidden (existing fields) type (int: 0=circle, 2=polygon), shape (str: "circle" or "polygon") radius (float, as the file holds it -- a polygon's too, 3000 as the Mission Editor writes one) color (RGBA dict {1: r, 2: g, 3: b, 4: a}, values 0.0-1.0) properties (user metadata dict {key: value}; {} if none) vertices (list of {x, y, lat, lon} points for polygons; null for circles)
ParameterTypeDescription
mission_idstringrequired

Check if a point is inside an existing trigger zone, circular or quad.

Details · 3 parameters (3 required)
zone_id must refer to an existing zone in the mission (use list_zones to find zone IDs and their radii). distance_to_center_m is always returned so callers can see how close to the zone edge a point is, regardless of inside/outside. A QUAD ZONE (zone_kind "quad", added 15 Sep 2026 -- they were refused) is inside when the point lies within its four corners, concave or not; distance_to_center_m is to the zone's centre and zone_radius_m is null.
ParameterTypeDescription
mission_idstringrequired
pointPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
zone_idintegerrequired

Batch check: which of a list of points fall inside a trigger zone?

Details · 3 parameters (3 required)
Maximum 100 points per call; raises ValueError if exceeded. Returns per-point results plus summary flags (all_inside, any_inside, inside_count) for quick branching without iterating the results list. Use case: "are any of this flight's waypoints inside the AO zone?" Circular and quad zones are both answered (zone_kind says which; a quad's zone_radius_m is null). Quads were refused until 15 Sep 2026.
ParameterTypeDescription
mission_idstringrequired
pointsPosition[]required
zone_idintegerrequired

Add a scored mission goal to a coalition's objectives.

Details · 5 parameters (3 required)
side: "red", "blue", or "offline" (case-insensitive). The offline side is scored independently of coalitions -- useful for unconditional bonuses, trainer objectives, or single-player campaign scoring. rules: list of condition dicts -- SAME shape as add_trigger's conditions parameter. Every condition type supported by add_trigger works here verbatim, except Or, which is refused: the Mission Editor's goals panel offers no OR, and joins a goal's rules with AND. All rules must evaluate true simultaneously for the goal to fire. Empty list is valid -- creates a placeholder goal that never fires. score: points awarded when all rules evaluate true, a whole number from -100 to 100 (the Mission Editor's range). Negative values are valid; DCS supports scoring penalties. comment: human-readable label shown in the Mission Editor goals panel. Returns the new goal's 0-based index within its side's list. A parameter given as null inside a rule is not given: it is built as if left out, and the response lists it under null_params_ignored.
ParameterTypeDescription
mission_idstringrequired
sidestringrequired
rulesobject[]required
scoreintegeroptionalDefault: 100.
commentstringoptional

Partially update a goal's fields, or move it to a different coalition side.

Details · 7 parameters (3 required)
side: the goal's CURRENT side ("red", "blue", or "offline", case-insensitive). goal_index: 0-based index within the current side's list. Optional update fields (omit any field to leave it unchanged): score: replace the goal's point value, a whole number from -100 to 100 (negative values are valid). comment: replace the human-readable label. rules: FULL replacement of the condition list -- same shape as add_goal's rules parameter. Partial patches are not supported; supply the complete desired list or omit to keep existing rules. new_side: MOVE the goal to a different coalition side. The goal is removed from its current position and appended to the end of the destination side's list. The original goal_index is no longer valid after a move; moved_to_index in the return reports the new location. Calling with no update fields is a no-op that returns the goal's current state (useful for inspection -- matches modify_trigger behaviour). Probe-before-mutate: if rules validation fails, the original goal is left completely untouched. All validation runs before any field is modified. A parameter given as null inside a rule is not given: it is built as if left out, and the response lists it under null_params_ignored.
ParameterTypeDescription
mission_idstringrequired
sidestringrequired
goal_indexintegerrequired
new_sidestring | nulloptional
scoreinteger | nulloptional
commentstring | nulloptional
rulesobject[] | nulloptional

Remove a goal from a side's objective list.

Details · 3 parameters (3 required)
side: "red", "blue", or "offline" (case-insensitive). goal_index: 0-based position within the side's goal list. Per-side renumbering: after deletion, all goals with a higher index on the SAME side shift down by 1. Goals on other sides are not affected. When deleting multiple goals from the same side, go highest-to-lowest to avoid index confusion (mirrors delete_trigger). renumbered: true if any goal on this side shifted (i.e. the deleted goal was not the last entry).
ParameterTypeDescription
mission_idstringrequired
sidestringrequired
goal_indexintegerrequired

Inspect a specific goal in full detail, including all condition rules.

Details · 3 parameters (3 required)
side: "red", "blue", or "offline" (case-insensitive). goal_index: 0-based position within the side's goal list. Use list_goals to see current indices. Returns side, goal_index, score, comment, rule_count, and the full rules list with each rule's predicate and params dict.
ParameterTypeDescription
mission_idstringrequired
sidestringrequired
goal_indexintegerrequired

List mission goals, optionally filtered to one coalition side.

Details · 2 parameters (1 required)
side: "red", "blue", or "offline" (case-insensitive). If omitted, all three sides are returned grouped under their side key. Each entry includes score, comment, and rule_count. Use get_goal for full rule detail on a specific goal.
ParameterTypeDescription
mission_idstringrequired
sidestring | nulloptional

Create a "destroy N% of these groups" scored goal via a flag counter.

Details · 10 parameters (3 required)
DCS has no native "destroy X% of coalition" goal condition. This builds the standard ME-debuggable pattern: one triggerOnce per target group ({GroupDead} -> {IncreaseFlag +1}) feeding a shared counter flag, plus a goal {FlagIsMore flag, value=K-1} that fires when >= K groups are dead, K = ceil(percent/100 * N). side: who is SCORED by the goal -- "red" | "blue" | "offline". This is distinct from whose groups must die (that is the target below). percent: float in (0, 100]. Fraction of target groups that must die. Target selection -- provide EXACTLY ONE mode: - Enumerate: target_coalition ("red"|"blue"|"neutral"), optionally narrowed by categories (a list of "plane"|"helicopter"|"vehicle"| "ship"|"static"; default all). Counts all matching groups. - Explicit: group_ids = [ids...]. Counts exactly those groups (duplicates are de-duplicated). target_coalition/categories must be unset in this mode. counter_flag: optional int. Omitted -> an unused flag is auto-picked. Provided -> must not already be referenced by any trigger/goal (raises, naming where it is used). score: points awarded when the goal fires (default 100), a whole number from -100 to 100 (the Mission Editor's range). comment: optional goal label (a descriptive default is generated). count_by: "unit" (default) or "group" -- what the percentage is OF. "unit" counts every unit in every target group, one {UnitDead} -> {IncreaseFlag +1} trigger each. This is the default because a SAM site is ONE group: counting groups would make ceil(pct/100 * 1) == 1 for every percentage from 1 to 100, so "destroy 25%" and "destroy 100%" would mean the same thing. "group" keeps the per-group basis ({GroupDead}, a 4-ship counts as one). Use it when the question really is about whole objects -- "destroy 2 of these 4 convoys". Each trigger is tagged "attrition[<flag>]: <name> dead" so the scaffold is identifiable for inspection or removal. Note that count_by="unit" emits one trigger per unit, so a mission with several full SAM sites will produce a lot of them; that is the price of a meaningful percentage, and they are all tagged. IMPORTANT -- build-time snapshot: N (the target count) and the threshold are fixed at call time. Run this AFTER all target groups are placed. Adding or deleting targets afterward makes the threshold stale and can orphan a trigger (mission_report checks 1-5 will flag it). Re-running creates a second independent scaffold (no dedupe across calls). Returns: {goal_index, side, score, counter_flag, percent, count_by, n_target_groups, target_groups: [{group_id, name}], trigger_indices: [...]} plus, when count_by="unit": n_target_units (N), threshold_units (K) plus, when count_by="group": threshold_groups (K)
ParameterTypeDescription
mission_idstringrequired
sidestringrequired
percentnumberrequired
target_coalitionstring | nulloptional
categoriesstring[] | nulloptional
group_idsinteger[] | nulloptional
counter_flaginteger | nulloptional
scoreintegeroptionalDefault: 100.
commentstring | nulloptional
count_bystringoptionalDefault: "unit".

F10 map drawings14 tools

Everything the F10 map can show: circles, lines, polygons, ovals, oblongs, rectangles, arrows, icons, and text boxes — organized into layers.

Draw an arrow on the F10 map.

Details · 12 parameters (5 required)
tail: the arrow's anchor / origin (tail end, not the tip). angle_deg: direction the arrow points, clockwise from north (0 = north, 90 = east, 180 = south, 270 = west). length_m: shaft length in meters (must be > 0). fill: arrowhead fill color. Defaults to solid red (same as outline). Note: the default fill is solid, not transparent. Use case: ingress arrows, attack vectors, threat-axis indicators, SEAD run-in direction.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
tailPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
angle_degnumberrequired
length_mnumberrequired
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
namestringoptionalDefault: "Arrow".

Draw a filled circle on the F10 map.

Details · 11 parameters (4 required)
center: center of the circle -- {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}. radius_m: radius in meters (must be > 0). color: outline color {r,g,b,a}. Defaults to solid red. fill: fill color {r,g,b,a}. Defaults to transparent red (a=60). Use fill={r:0,g:0,b:0,a:0} for a fully transparent (outline-only) circle. Use case: SAM engagement envelope, trigger zone visualization, area-of-effect, safe/no-fly zone radius.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
centerPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
radius_mnumberrequired
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
namestringoptionalDefault: "Circle".

Draw a filled arbitrary polygon on the F10 map.

Details · 11 parameters (4 required)
anchor: first vertex (also the drawing's anchor position). points: remaining vertices in order. Must have >= 2 entries so the polygon has >= 3 vertices total. The polygon is automatically closed (last vertex joins back to anchor). Use case: arbitrary AO shapes, irregular exclusion zones, complex kill-box polygons.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
anchorPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
pointsPosition[]required
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
namestringoptionalDefault: "Polygon".

Place a NATO unit-symbol icon on the F10 map.

Details · 8 parameters (4 required)
icon: one of the icons the Mission Editor's drawing panel offers, by its file name; each is followed here by the editor's name for it: P91000001.png Armor; P91000002.png IFV; P91000003.png Recon; P91000004.png Mechanized; P91000005.png Supply; P91000006.png Armored Artillery; P91000007.png Rocket Artillery; Field_Artillery.png Field Artillery; P91000035.png Friendly Ground Unit; P91000208.png Mobile Rocket LN; P91000212.png Engineers; P910000065.png Airborne Troops; P91000203.png Antitank; P91000204.png Mobile Antitank; P91000009.png Air Defence SAM; P91000010.png Air Defense SRD; P91000011.png Air Defense Single LN; P91000012.png Air Defense Dual LN; P91000013.png Air Defense Multiple LN; P91000014.png Surface to Air Missile; P91000028.png Electronic Warfare Jammer; P91000015.png Direct Fire Gun; P91000018.png Short Range SAM; P91000036.png Air Defence SR; P91000045.png Air Defence Control Station; P91000023.png Unmanned Aircraft; P91000024.png Fighter Aircraft; P91000025.png Attack Aircraft; P91000026.png Recon Aircraft; P91000027.png Bomber Aircraft; P91000029.png Cargo Aircraft; P91000056.png AWACS; P91000058.png Light Aircraft; P91000059.png Interceptor Aircraft; P91000060.png Tanker Aircraft; Aircraft_civilian.png Civilian Aircraft; P91000020.png Utility Helicopter; P91000021.png Attack Helicopter; P91000062.png Anti-Sub Helicopter; P91000096.png Recon Helicopter; P91000038.png Submarine; P91000039.png Warship; P91000051.png Carrier; P91000052.png Assualt Ship; P91000053.png Destroyer; P91000054.png Frigate; P91000057.png Merchant Ship; P91000211.png Civilian Ship; P91000108.png Railway; P91000109.png Waypoint; P91000207.png Fuel Supply; P91000040.png Arrow; P91000072.png Airbase Building. -- OR -- the editor's name for one, in any case ("Armor", "air defence sam"). -- OR -- one of these 8 names, each for the file shown: "MechanizedInfantryWithFightingVehicle" P91000002.png, "Recce" P91000003.png, "MechanizedInfantry" P91000004.png, "Logistics" P91000005.png, "MechanizedArtillery" P91000006.png, "MechanizedRocketArtillery" P91000007.png, "AirDefense" P91000009.png, "SearchRadar" P91000010.png. "Mechanized" is refused: this tool took it for P91000001.png, the editor's Armor, and the editor's Mechanized is P91000004.png -- give the file name, or "Armor". Any other is refused: the editor offers no other. scale: size multiplier (must be > 0; 1.0 = default size). color: tint color. Defaults to solid red. Use case: off-map threat markers, friendly unit position symbols, FARP and airfield markers, key landmark indicators.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
iconstringrequired
scalenumberoptionalDefault: 1.0.
colorobject | nulloptional
color_namestring | nulloptional
namestringoptionalDefault: "Icon".

Draw a smooth freeform curve through a series of points on the F10 map.

Details · 10 parameters (4 required)
DCS renders this as a Bezier-like smoothed curve rather than hard straight segments. Visually similar to line_segments for <= 3 points but smoothed for longer paths. anchor: first control point; also the drawing's anchor. points: remaining control points (>= 1 entry required). closed: if True, the curve loops back to anchor. Use case: river outlines, coastlines, natural-looking route curves, engagement-zone boundaries that shouldn't look rigid.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
anchorPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
pointsPosition[]required
colorobject | nulloptional
color_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
closedbooleanoptionalDefault: false.
namestringoptionalDefault: "Line".

Draw a straight line between two points on the F10 map.

Details · 9 parameters (4 required)
layer: "Red", "Blue", "Neutral", "Common", or "Author". start, end: endpoints, each {lat_lon: {lat, lon}}, {xy: {x, y}}, or flat {lat, lon} or {x, y}. color: {r, g, b, a} with 0-255 values. Defaults to solid red. color_name: convenience shorthand -- one of "red", "blue", "green", "yellow", "orange", "white", "black", "magenta", "cyan". If both color and color_name are given, color wins. line_thickness: pixel width (default 8). line_style: "solid" (default), "dot", "dash", "dotdash", "cross", "square", "triangle", "wirefence", "dot2", "solid2", "strongpoint", "boundry1" through "boundry5". name: label in the ME drawing list. Use case: range fans, boundary lines, route legs.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
startPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
endPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
colorobject | nulloptional
color_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
namestringoptionalDefault: "Line".

Draw a multi-segment polyline (connected straight segments) on the F10 map.

Details · 10 parameters (4 required)
anchor: first vertex; also the drawing's map anchor. points: remaining vertices in order. Must have >= 1 entry (so the polyline has at least 2 vertices total). closed: if True, the last vertex is connected back to anchor, producing a closed outline with no fill. For a filled closed shape use add_drawing_freeform_polygon instead. Use case: multi-leg route overlay, range boundary outline, perimeter.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
anchorPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
pointsPosition[]required
colorobject | nulloptional
color_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
closedbooleanoptionalDefault: false.
namestringoptionalDefault: "Line".

Draw a capsule (oblong) shape -- a corridor with two rounded ends.

Details · 13 parameters (5 required)
p1, p2: the two centerline endpoints. The corridor runs from p1 to p2. radius_m: radius of the rounded caps AND half the corridor width (must be > 0). resolution: number of polygon segments per rounded cap (default 20; must be >= 3). Higher = smoother caps. NOTE: anchor_position in the return is the computed first outline vertex (not p1), as the file stores the shape. Use case: navigation corridors, approach lanes, fly-zone tubes, safe-transit paths.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
p1PositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
p2PositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
radius_mnumberrequired
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
line_thicknessintegeroptionalDefault: 4.
line_stylestringoptionalDefault: "solid".
resolutionintegeroptionalDefault: 20.
namestringoptionalDefault: "Oblong".

Draw a filled oval (ellipse) on the F10 map.

Details · 13 parameters (5 required)
center: center point. radius_a_m: semi-major axis in meters (must be > 0). radius_b_m: semi-minor axis in meters (must be > 0). angle_deg: rotation of the major axis clockwise from north (0 = major axis points north, 90 = east). Use case: SAM seeker cone footprint, asymmetric AO, elongated threat envelope.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
centerPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
radius_a_mnumberrequired
radius_b_mnumberrequired
angle_degnumberoptionalDefault: 0.0.
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
namestringoptionalDefault: "Oval".

Draw a filled rectangle on the F10 map.

Details · 13 parameters (5 required)
center: center of the rectangle. width_m: width in meters (must be > 0). height_m: height in meters (must be > 0). angle_deg: rotation clockwise from north (0 = sides run N/S and E/W, 45 = diamond orientation). Use case: kill boxes, training range boundaries, airspace blocks.
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
centerPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
width_mnumberrequired
height_mnumberrequired
angle_degnumberoptionalDefault: 0.0.
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
line_thicknessintegeroptionalDefault: 8.
line_stylestringoptionalDefault: "solid".
namestringoptionalDefault: "Rectangle".

Place a text label with optional background box on the F10 map.

Details · 13 parameters (4 required)
text: the label content (must not be empty). color: text color. Defaults to solid red. fill: box background color. Defaults to transparent red (a=60). Use fill={r:0,g:0,b:0,a:0} for no background. font_size: point size (must be > 0; default 20). font: "DejaVuLGCSansCondensed.ttf", the font the Mission Editor writes on every text box; it offers no other, and any other is refused. border_thickness: box border width in pixels (default 2). angle_deg: text rotation clockwise from north (default 0 = normal). Use case: "PRIMARY TARGET", "IP ALPHA", "BULLSEYE", "DANGER -- SA-6 THREAT RING 24NM".
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
positionPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
textstringrequired
colorobject | nulloptional
color_namestring | nulloptional
fillobject | nulloptional
fill_namestring | nulloptional
font_sizeintegeroptionalDefault: 20.
fontstringoptionalDefault: "DejaVuLGCSansCondensed.ttf".
border_thicknessintegeroptionalDefault: 2.
angle_degnumberoptionalDefault: 0.0.
namestringoptionalDefault: "TextBox".

List all F10 map drawings, optionally filtered to one layer.

Details · 2 parameters (1 required)
layer: one of "Red", "Blue", "Neutral", "Common", "Author". If None, all five layers are returned. Returns "layers" mapping each layer name to a list of drawing summaries with index, primitive_type, name, and anchor_position. Use the index with remove_drawing to delete a specific drawing. total_drawing_count covers all returned layers combined.
ParameterTypeDescription
mission_idstringrequired
layerstring | nulloptional

Remove one drawing from a layer by 0-based index.

Details · 3 parameters (3 required)
After removal, drawings at higher indices shift down by 1. Call list_drawings to confirm current indices before removing. renumbered: True if any remaining drawings shifted (i.e. the removed drawing was not the last one).
ParameterTypeDescription
mission_idstringrequired
layerstringrequired
drawing_indexintegerrequired

Remove all drawings from one layer.

Details · 2 parameters (2 required)
Other layers are unaffected. layer must be one of: "Red", "Blue", "Neutral", "Common", "Author". drawings_removed is 0 if the layer was already empty (no error).
ParameterTypeDescription
mission_idstringrequired
layerstringrequired

Warehouses & logistics6 tools

Airfield and unit warehouses: inventories, supplier chains, and warehouse properties for dynamic-cargo and logistics play.

List all warehouse-capable locations in the mission.

Details · 2 parameters (1 required)
Returns an overview of every airport and any pre-existing unit warehouses (FARPs, carrier ships, etc.). No new entries are synthesized. Args: mission_id: Active session ID from open_miz. coalition: Optional filter: 'red', 'blue', or 'neutral' (case-insensitive). Pass None to list all coalitions. Returns: { "airport_count": int, "unit_warehouse_count": int, "airports": [ { "airdrome_id": int, "name": str, "coalition": str, "unlimited_fuel": bool, "unlimited_munitions": bool, "unlimited_aircrafts": bool } ], "unit_warehouses": [ { "unit_id": int, "name": str, "coalition": str, "unlimited_fuel": bool, "unlimited_munitions": bool, "unlimited_aircrafts": bool } ] }
ParameterTypeDescription
mission_idstringrequired
coalitionstring | nulloptional

Get full warehouse details for one airdrome or unit (FARP / carrier).

Details · 3 parameters (1 required)
Provide exactly one of airdrome_id or unit_id. If a unit_id is given and the unit has no warehouse entry yet, a default entry is synthesised in memory (not saved). The 'synthesized' flag in the response will be True in that case. Returns: { "warehouse_kind": "airport" | "unit", "airdrome_id": int | null, "unit_id": int | null, "name": str, "synthesized": bool, "warehouse": { ...all Warehouse fields... } }
ParameterTypeDescription
mission_idstringrequired
airdrome_idinteger | nulloptional
unit_idinteger | nulloptional

Limit a warehouse's aircraft and/or weapons, as the Mission Editor does.

Details · 6 parameters (1 required)
aircrafts: { "planes": {"F-16C_50": {"initialAmount": 12}, ...}, "helicopters": {"UH-1H": {"initialAmount": 4}, ...} } Two categories, "planes" and "helicopters", each aircraft by its DCS type name (as list_unit_types gives it). Give initialAmount; each entry is written as the Mission Editor writes it -- initialAmount, wsType, unlimited=false, linkDynTempl=0 -- with the aircraft's wsType filled in, because DCS does not load an aircraft entry without one. An aircraft the warehouse already lists keeps its own fields apart from those you give. A type DCS does not ship, or one under the wrong category, is refused and nothing is changed. A LIMITED WAREHOUSE HOLDS ONLY WHAT IT LISTS, so, as the Mission Editor does, every type you do not name is listed too: a type the warehouse already lists keeps its entry, and every other type is listed at 100. Set a type's initialAmount to 0 to keep it out, or give others_amount=0 to list only what you name. The response's notes say what was listed. others_amount: every aircraft type and weapon you do not name -- those the warehouse already lists included -- is listed at this amount instead. others_amount=0 limits the warehouse to exactly what you name. It applies to whichever of aircrafts and weapons you give. weapons: { "AIM-120C": {"initialAmount": 20}, "4.4.7.7": {"initialAmount": 10}, ... } A warehouse weapon is its number (wsType), four numbers; the file carries no name. Give a weapon by the name the Mission Editor's warehouse dialog gives it, or by its number as "a.b.c.d"; an entry keyed 1, 2, ... must carry its wsType, as get_warehouse shows them. An entry without a proper number stocks nothing, so it is refused. A name DCS gives more than one weapon is refused, naming their numbers. A name an earlier DCS gave a weapon is refused, naming the one it has now. As with aircraft, every weapon you do not name is listed, as the Mission Editor lists it: at 100 when the warehouse listed no weapons, and at 0 when it already listed some, as the editor does when it opens the mission. The weapons listed, and the names taken, are those DCS 2.9.31 lists in a warehouse; a mod's weapon, or one added in a later DCS version, is given by its number. If you pass 'aircrafts' and unlimited_aircrafts is currently True, the unlimited flag is automatically cleared and a warning is returned. Same for weapons / unlimited_munitions. A LIMITED WAREHOUSE SUPPLIES SCRIPTED AI TOO. With unlimited_aircrafts false, AI that a script spawns at the airfield takes its aircraft from this stock -- a user saw one spawn take a type from 50 to 49 -- so a warehouse stocked only for players can leave scripted AI with nothing to spawn. Reported by a user; not measured here. All initialAmount values must be >= 0. Returns full warehouse state plus 'warnings' and 'notes' (lists of str).
ParameterTypeDescription
mission_idstringrequired
airdrome_idinteger | nulloptional
unit_idinteger | nulloptional
aircraftsobject | nulloptional
weaponsobject | nulloptional
others_amountinteger | nulloptional

Partially update scalar properties of an airdrome or unit warehouse.

Details · 20 parameters (1 required)
Only fields that are provided (not None) are changed. All other fields retain their current values. Provide exactly one of airdrome_id or unit_id. Validation ranges, the Mission Editor's resource manager's: operating_level_air/fuel/equipment: 0-100 gasoline_init/methanol_mixture_init/diesel_init/jet_init: 0-5000 periodicity, size: 0-1000 speed: 0-277.777 (m/s) A value outside its range is refused, naming the range. Returns full warehouse state plus 'changed_fields: list[str]'.
ParameterTypeDescription
mission_idstringrequired
airdrome_idinteger | nulloptional
unit_idinteger | nulloptional
coalitionstring | nulloptional
sizeinteger | nulloptional
speednumber | nulloptional
periodicityinteger | nulloptional
unlimited_munitionsboolean | nulloptional
unlimited_aircraftsboolean | nulloptional
unlimited_fuelboolean | nulloptional
operating_level_airinteger | nulloptional
operating_level_fuelinteger | nulloptional
operating_level_equipmentinteger | nulloptional
gasoline_initnumber | nulloptional
methanol_mixture_initnumber | nulloptional
diesel_initnumber | nulloptional
jet_initnumber | nulloptional
dynamic_spawnboolean | nulloptional
dynamic_cargoboolean | nulloptional
allow_hot_startboolean | nulloptional

Add a supply-graph edge to a warehouse's suppliers list.

Details · 5 parameters (1 required)
Provide exactly one of airdrome_id/unit_id (the warehouse to edit) and exactly one of supplier_airdrome_id/supplier_unit_id (the supplier to add). The suppliers dict shape used by DCS: { 1: {"Id": <int>, "type": "airports"|"warehouses"}, ... } "airports" means the supplier is an airdrome; "warehouses" means it is a unit warehouse (FARP / carrier). Adding a duplicate supplier (same Id and type) is silently ignored. Returns full warehouse state plus 'added: bool'.
ParameterTypeDescription
mission_idstringrequired
airdrome_idinteger | nulloptional
unit_idinteger | nulloptional
supplier_airdrome_idinteger | nulloptional
supplier_unit_idinteger | nulloptional

Remove a supply-graph edge from a warehouse's suppliers list.

Details · 5 parameters (1 required)
Provide exactly one of airdrome_id/unit_id (the warehouse to edit) and exactly one of supplier_airdrome_id/supplier_unit_id (the supplier to remove). Raises ValueError if the specified supplier is not present. Returns full warehouse state plus 'removed: bool'.
ParameterTypeDescription
mission_idstringrequired
airdrome_idinteger | nulloptional
unit_idinteger | nulloptional
supplier_airdrome_idinteger | nulloptional
supplier_unit_idinteger | nulloptional

Terrain & analysis13 tools

Bare-earth terrain intelligence from DCS's own data: elevation sampling, profiles, zonal statistics, line-of-sight, viewsheds, water checks, scenery obstruction, and clear-spot search.

Sample the installed terrain data at a geographic coordinate: surface subtype + elevation.

Details · 2 parameters (2 required)
Reads DCS's own baked 100 m grid (land.getSurfaceType + land.getHeight), so the answer is authoritative and consistent with mission_report and the placement tools. There is NO coarse-dataset fallback (GSHHG has neither elevation nor surface subtype), so an uninstalled theater, an unknown theater, or an out-of-grid point returns available:false with a reason -- never a guess. elevation_m is the BILINEAR-interpolated continuous ground height (the same basis as check_slope / get_elevation), while surface_type is the NEAREST cell's class -- different spatial bases, by design. surface_type uses DCS's real class names: LAND, SHALLOW_WATER, WATER, ROAD, RUNWAY (note SHALLOW_WATER, not "SHALLOW"). is_water is True for WATER or SHALLOW_WATER -- the same single-sourced convention is_water and mission_report use, so this tool can never contradict them. Args: position: {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float}. xy-form is rejected: theater xy is meaningless without a Mission terrain reference (same contract as is_water). theater: the theater name, as list_theaters gives it (e.g. "Caucasus"). REQUIRED -- unlike is_water there is no fallback, so it must be explicit. Returns (available): {available: True, surface_type: str, surface_code: int, elevation_m: float (signed), is_water: bool, x_m: float, y_m: float, source: "dat"} Returns (unavailable): {available: False, reason: "<theater> not installed" | "point outside terrain grid" | "unknown theater ..."} Raises: ValueError if position is in xy form, lacks a latitude and longitude, or carries both.
ParameterTypeDescription
positionGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired

Sample baked terrain (surface subtype + elevation) for many points in one call.

Details · 2 parameters (2 required)
Per-point version of sample_terrain. Each result carries its OWN available/reason: an in-grid point resolves while an out-of-grid point in the same batch returns available:false, both in one call (mirrors is_water_batch's per-point shape). See sample_terrain for the spatial-basis note (elevation bilinear / surface nearest-cell) and the no-fallback contract. Args: points: List of positions, each {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float}. Max 500 per call. xy-form is rejected. theater: the theater name, as list_theaters gives it (e.g. "Caucasus"). REQUIRED. Returns: {results: [<sample_terrain result>, ...]} -- same order as input. Raises: ValueError if a point is in xy form, lacks a latitude and longitude, or carries both; the error identifies which index in the batch failed.
ParameterTypeDescription
pointsGeoPosition[]required
theaterstringrequired

Elevation + surface profile along a straight path between two points.

Details · 5 parameters (3 required)
A pure readout of what the terrain data shows the path crosses from start to end -- no modeling choices (no Earth curvature, no observer/target height; those belong to a line-of-sight tool). Useful for route planning, finding a lowest corridor, and "what do I cross between A and B". Reads DCS's baked 100 m grid (same source as sample_terrain / is_water), walking it vectorized in theater-XY: both endpoints are projected once, then the path is sampled in numpy -- so the per-sample answers AGREE with sample_terrain by construction (bilinear elevation, nearest surface). There is no GSHHG fallback; below-sea elevations clamp to 0. Args: start, end: each {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy rejected, same as sample_terrain -- theater xy needs a Mission terrain ref). theater: the theater name, as list_theaters gives it (e.g. "Caucasus"). REQUIRED -- there is no fallback, so an uninstalled or unknown theater returns available:false. step_m: nominal sample spacing in meters (default 100 = native resolution). Statistics are always computed on the full native walk. max_samples: cap on the samples returned in the payload (default 256). If the native walk exceeds this, evenly-spaced samples are returned and coarsened:true is set -- the SUMMARY still reflects the full native-resolution walk. Returns (available): {available: True, theater, start:{lat,lon}, end:{lat,lon}, total_distance_m, step_m, native_sample_count, sample_count, coarsened: bool, reported_step_m, samples: [{dist_m, lat, lon, elevation_m, surface_type, is_water, in_grid}, ...], summary: {min_elevation_m, max_elevation_m, max_elevation_at:{dist_m,lat,lon}, mean_elevation_m, crosses_water, water_segments:[{from_dist_m,to_dist_m}], surface_composition:{<NAME>:count, ...}, any_out_of_grid}} Off-grid samples carry in_grid:false with null elevation/surface and count into summary.any_out_of_grid (per-sample honesty); a fully-off- grid theater-baked path stays available:true with null elevation stats. Returns (unavailable -- no walk possible): {available: False, reason: "<theater> not installed" | "unknown theater ..."} Raises: ValueError if a Position is xy-form / missing a latitude and longitude / both, if step_m <= 0, or if max_samples < 2.
ParameterTypeDescription
startGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
endGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
step_mnumberoptionalDefault: 100.0.
max_samplesintegeroptionalDefault: 256.

Zonal terrain statistics over a circular area (the area read).

Details · 3 parameters (3 required)
The third spatial primitive alongside sample_terrain (point) and terrain_profile (line): summarizes the terrain data within radius_m of a center -- elevation min/max/mean/std (std = a ruggedness proxy), relief, highest/lowest point, and surface composition. LZ/FARP suitability and SAM siting compose this. Reads RAW per-cell values (the cells as baked), NOT bilinear -- zonal stats describe cells, not an interpolated surface. This agrees with sample_terrain by construction: bilinear AT a cell center returns that cell's node value, so a raw cell == sample_terrain's elevation at that cell center (to projection rounding). Surface classification uses the single-sourced is_water_surface convention. Args: center: {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy rejected, same as sample_terrain). theater: the theater name, as list_theaters gives it. REQUIRED (no fallback). radius_m: disc radius in meters, > 0 and <= 100000 (a bound that keeps the cell count sane; a 100 km radius is already a ~2001x2001 box). Returns (available): {available: True, theater, center:{lat,lon,ground_elevation_m}, radius_m, cells_in_grid, cells_total, partial_coverage: bool, elevation:{min_m,max_m,mean_m,std_m}, relief_m, highest_point:{lat,lon,elevation_m}, lowest_point:{lat,lon,elevation_m}, surface_composition:{<NAME>:count,...}, surface_fractions:{<NAME>:fraction,...}, water_fraction} Stats are over IN-GRID disc cells only; partial_coverage flags a disc that overlaps the grid edge (honest -- nothing past the edge invented). Returns (unavailable): {available: False, reason} for an not installed/unknown theater or an off-grid center. Raises: ValueError on xy-form center, radius_m <= 0, or radius_m above the cap.
ParameterTypeDescription
centerGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
radius_mnumberrequired

Find the nearest road to a point, from the installed terrain data.

Details · 3 parameters (2 required)
WHAT THIS IS, AND WHAT IT IS NOT. The terrain data gives every 100 m cell of the map a class, and ROAD is one of them. This returns the centre of the nearest cell classed ROAD. It is NOT the Mission Editor's road network. The data was taken by asking DCS for the surface at one point in each cell, so a road is in it only where that point fell on the road: most of a road's length is not, and on every map more than half the ROAD cells (56 to 87 in a hundred) have no ROAD cell beside them. The point returned is on a road, but a nearer road -- or a nearer stretch of the same one -- may not be in the data at all, and can be hundreds of metres closer. Use it to find a point on a road near the one you give, or to place something by a road. It does not make a vehicle follow the road: that is the waypoint type "On Road". Args: position: {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy form is rejected, as for sample_terrain). theater: theater name, as list_theaters gives it. max_radius_m: how far to look, in metres. Default 5000; at most 50000. Returns: {available: true, found, lat, lon, distance_m, cell_m, searched_radius_m, road_cells_within_radius} found false means no cell within the radius is classed ROAD -- lat, lon and distance_m are then absent. road_cells_within_radius is how many are: a handful, far away, is a road you may not want. {available: false, reason} when the theater is unknown, its terrain data is not installed, or the point is outside the map.
ParameterTypeDescription
positionGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
max_radius_mnumberoptionalDefault: 5000.0.

Bare-earth terrain-masked line of sight between two points.

Details · 9 parameters (3 required)
Answers: can an observer at A see a target at B over the BARE-EARTH terrain between them (no buildings, trees, or objects -- terrain masking, not full in-sim LOS), accounting for Earth curvature and atmospheric refraction? Built on the proven walk_path primitive (same projection + reads as sample_terrain / terrain_profile, so elevations agree by construction). Height semantics -- each endpoint takes height_m + height_ref: - "agl": height above the terrain at that point (eye_msl = ground + h). - "msl": absolute height above sea level (eye_msl = h), no lower than the ground at that point. Defaults are 0 m AGL / 0 m AGL (pure ground-to-ground intervisibility). Canonical tactical use: observer = radar antenna AGL (e.g. 15 m), target = aircraft altitude MSL (e.g. 9144 m). Both endpoints MUST be in-grid; an off-grid endpoint or theater with no terrain data installed -> available:false (cannot model terrain we cannot read). Model (over interior samples; endpoints are the eyes, excluded): R_eff = k_factor * 6371000 (k=4/3 standard atmosphere) bulge(s) = s*(D-s) / (2*R_eff) los_msl(s) = observer_eye + (target_eye - observer_eye)*(s/D) clear iff min(los_msl(s) - (terrain(s) + bulge(s))) >= 0 Args: observer, target: each {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy rejected). theater: the theater name, as list_theaters gives it (e.g. "Caucasus"). REQUIRED. observer_height_m / observer_height_ref: observer eye height + frame. target_height_m / target_height_ref: target height + frame. k_factor: refraction factor (default 4/3; 1.0 = geometric horizon). step_m: walk spacing (default 100 = native resolution). Returns (available, determinate): {available: True, theater, observer:{...,ground_elevation_m,eye_msl_m}, target:{...}, total_distance_m, k_factor, earth_radius_eff_m, step_m, samples_evaluated, clear: bool, min_clearance_m (signed), controlling_point:{dist_m,lat,lon,terrain_elevation_m,clearance_m}, los_indeterminate: False, any_out_of_grid: False, note: "bare-earth terrain masking; excludes buildings, trees, and objects"} Returns (indeterminate -- interior runs off-grid): clear: None, los_indeterminate: True, any_out_of_grid: True, + reason. (Never reports clear over terrain it cannot read.) Returns (unavailable): {available: False, reason} for an not installed/unknown theater or an off-grid endpoint. Raises: ValueError on xy-form Position, an invalid height_ref, a height below the ground (below 0 with its ref 'agl', or below the ground's height at its point with its ref 'msl', the refusal naming that height), step_m <= 0, or k_factor <= 0.
ParameterTypeDescription
observerGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
targetGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
observer_height_mnumberoptionalDefault: 0.0.
observer_height_refstringoptionalDefault: "agl".
target_height_mnumberoptionalDefault: 0.0.
target_height_refstringoptionalDefault: "agl".
k_factornumberoptionalDefault: 1.3333333333333333.
step_mnumberoptionalDefault: 100.0.

Terrain-masked coverage footprint of an emitter against a target altitude.

Details · 10 parameters (4 required)
From an emitter at center C (antenna height), against a target at altitude A, out to max_range_m: sweeps n_azimuths radials and reports, per azimuth, where the target is VISIBLE vs MASKED by BARE-EARTH terrain (plus Earth curvature + refraction). Turns a range ring into a real terrain-masked coverage diagram. HONEST LABEL: this is bare-earth terrain masking + a curvature horizon -- NOT radar power, RCS, beam pattern, or atmospheric attenuation. It says where line of sight exists, not where a real radar would detect. Composes the proven walk_path + viewshed sweep (provably equivalent to check_los at every sample). One walk + one cumulative-max pass per radial. Args: center: the emitter, {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy rejected). theater: the theater name, as list_theaters gives it. REQUIRED. target_altitude_m: target height (see target_altitude_ref). max_range_m: sweep each radial to this ground range. antenna_height_m / antenna_height_ref: emitter eye height + frame ("agl" = ground + h, typical radar; "msl" = absolute). Default 15 AGL. target_altitude_ref: "msl" = fixed altitude aircraft (default); "agl" = terrain-following. n_azimuths: radials, evenly spaced (default 72 = every 5 deg; max 360). Azimuth 0 = North, sweeping clockwise. k_factor: refraction factor (default 4/3; 1.0 = geometric). step_m: walk spacing (default 100 = native resolution). Returns (available): {available: True, theater, center:{lat,lon,ground_elevation_m, antenna_msl_m}, target:{altitude_m,ref}, max_range_m, n_azimuths, k_factor, step_m, azimuths:[{azimuth_deg, max_visible_range_m, visible_segments:[{from_m,to_m}], masked: bool, indeterminate_beyond_m: float|null}, ...], summary:{azimuths_total, azimuths_full_coverage, azimuths_with_masking, azimuths_indeterminate, min_visible_range_m, mean_visible_range_m, max_visible_range_m, fully_clear: bool, any_indeterminate: bool}} Per-azimuth segments + scalars only (no per-step arrays). A radial that leaves the grid at range g carries indeterminate_beyond_m=g; nothing is reported visible beyond g (unknown != visible), distinct from masked. Returns (unavailable): {available: False, reason} for an not installed/unknown theater or an off-grid center. Raises: ValueError on xy-form center, invalid height refs, n_azimuths out of [1,360], a height below the ground (antenna_height_m or target_altitude_m below 0 with its ref 'agl'; 0 is at the ground; antenna_height_m below the ground's height at the center with its ref 'msl', the refusal naming that height), or a range, k_factor or step that is not above 0.
ParameterTypeDescription
centerGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
target_altitude_mnumberrequired
max_range_mnumberrequired
antenna_height_mnumberoptionalDefault: 15.0.
antenna_height_refstringoptionalDefault: "agl".
target_altitude_refstringoptionalDefault: "msl".
n_azimuthsintegeroptionalDefault: 72.
k_factornumberoptionalDefault: 1.3333333333333333.
step_mnumberoptionalDefault: 100.0.

Check whether a geographic coordinate is over water.

Details · 2 parameters (1 required)
Two data sources, reported via the "source" field: - source="dat": when a theater is named and its 100 m surface grid (DCS's own land.getSurfaceType) is installed and covers the point. Authoritative and accurate near coastlines -- consistent with mission_report and the placement tools. WATER and SHALLOW both count as water. - source="gshhg": the coarse GSHHG coastline dataset (via global-land-mask) plus Black Sea / Caspian override polygons. Used when NO theater is named, or when a point falls outside an installed theater's grid. A few-km coastline resolution -- near-shore answers can be wrong (over-reports land). Naming a theater whose terrain data is NOT installed returns {available: false, reason} rather than a coarse guess, matching sample_terrain, check_los and the other terrain tools. Naming a theater is a claim about which map you are on; answering it from a dataset that is least reliable at coastlines -- where shore units, ships and FARPs get placed -- would look authoritative and be wrong. Args: position: {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float}. The water/land lookup is pure geography and meaningless against theater-relative xy coordinates; xy-form positions are rejected. (Same contract as is_water_batch.) theater: optional theater name, as list_theaters gives it (e.g. "Caucasus"). Omit it to get the coarse global answer; name it to get the authoritative one, or an explicit unavailable if that theater's data is not installed. Returns: {is_water: bool, source: "dat" | "gshhg"} or {available: false, reason} when a named theater has no data. Raises: ValueError if position is in xy form, lacks a latitude and longitude, or carries both.
ParameterTypeDescription
positionGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstring | nulloptional

Check water/land classification for multiple points in one call.

Details · 2 parameters (1 required)
Each point is a latitude and longitude, nested or flat (see points). An xy-form point in the batch is rejected with a clear error. Water/land is answered from the installed terrain data surface grid when a theater is named and can answer (source="dat", accurate near coasts), else from the coarse GSHHG path (source="gshhg"). The source is reported PER POINT: a point inside the terrain data grid resolves via the .dat while an out-of-bounds point in the same batch falls back to GSHHG, so the two can differ within one call. As with is_water, naming a theater whose terrain data is NOT installed returns {available: false, reason} for the whole call rather than a batch of coarse guesses. Bulk placement is the likelier route to a wrong shoreline answer, so the batch must not be the lenient one. Args: points: List of positions, each {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float}. Max 500 per call. theater: optional theater name, as list_theaters gives it (e.g. "Caucasus"). Omitted => GSHHG for every point (the original behaviour). Returns: {results: [{is_water: bool, source: "dat"|"gshhg"}, ...]} -- same order as input. (Return shape changed from a bare [bool, ...] list to per-point objects when the source flag was added.) Or {available: false, reason} when a named theater has no data. Raises: ValueError if a point is in xy form, lacks a latitude and longitude, or carries both forms; the error identifies which index in the batch failed.
ParameterTypeDescription
pointsGeoPosition[]required
theaterstring | nulloptional

Search outward for the nearest cell clear of map structures.

Details · 5 parameters (2 required)
The scenery counterpart to find_land_near: spiral concentric rings (250 m steps) from the point to the nearest cell whose obstruction level is at most *max_level*. Useful when a spawn lands on/in a building. Reads the scenery sidecar only -- no fallback. Args: position: {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy rejected). theater: the theater name, as list_theaters gives it. REQUIRED. search_radius_m: give up after this distance (default 2000). max_level: highest acceptable obstruction -- "clear" (0 structures, default), "light" (<=4), or "heavy" (any). Where the map's terrain pack has per-unit structure data, a spot must also be clear of every structure's measured reach plus 5 m (with footprint_m, across the whole footprint), the check placements make -- for max_level "clear" and "light"; "heavy" accepts any spot. Returns (available): {available: True, found: bool, lat, lon, distance_m, structure_count, level}. If the origin already satisfies max_level, found is True with distance_m 0 at the input point. If nothing qualifies within the radius, found is False (lat/lon = input, distance_m 0). Returns (unavailable): {available: False, reason} for an theater with no terrain data installed, absent sidecar, or an off-grid origin. Raises: ValueError on xy-form Position, an invalid max_level, or a sidecar co-registration mismatch.
ParameterTypeDescription
positionGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
search_radius_mnumberoptionalDefault: 2000.0.
max_levelstringoptionalDefault: "clear".
footprint_mnumberoptionalDefault: 0.0.

Search outward from a point to find the nearest land.

Details · 4 parameters (2 required)
Useful when a spawn coordinate has accidentally landed in the sea. Samples concentric rings at 250 m intervals; angular resolution scales so the worst-case gap between samples is ~10 % of the ring radius. Land/water at each sample is classified from the installed terrain data when a theater is named and can answer (accurate near coasts), else from GSHHG. The "source" of the returned answer is reported. Args: lat: Starting latitude. lon: Starting longitude. max_radius_m: Give up after this distance in metres (default 2000). theater: optional theater name, as list_theaters gives it (e.g. "Caucasus"). When given and baked, samples are classified via the .dat; the answer near coasts is far more accurate, so smaller max_radius_m suffices than on the GSHHG path. Returns: {found: bool, lat: float, lon: float, distance_m: float, source: "dat" | "gshhg"} distance_m is always <= max_radius_m (strictly enforced via haversine). If found is False, lat/lon equal the input and distance_m is 0. source reflects the dataset that classified the accepted land sample (or, when not found, the path used for the search). Note: on the GSHHG path coastline resolution is a few km, so sub-km offshore points may need max_radius_m > 2000.
ParameterTypeDescription
latnumberrequired
lonnumberrequired
max_radius_mnumberoptionalDefault: 2000.0.
theaterstring | nulloptional

Check whether a coordinate sits on a cell with map structures (buildings).

Details · 3 parameters (2 required)
Reads the scenery sidecar (<theater>_scenery.dat) -- a per-cell count of terrain structures (buildings/bridges/towers), co-registered to the terrain grid and harvested in-sim (see tools/bake_scenery). Lets placement avoid clipping units into buildings. Bare structures only -- NOT trees (engine-managed vegetation, not enumerable; use clear_scene_objects_in_zone to clear those at runtime). Graded level from the cell's structure count: "clear" (0), "light" (1-4, scattered), "heavy" (>=5, dense built-up). obstructed = count > 0; the level lets a caller choose strictness. Args: position: {"lat_lon": {"lat": float, "lon": float}} or flat {"lat": float, "lon": float} (xy rejected, same as sample_terrain). theater: the theater name, as list_theaters gives it. REQUIRED. Returns (available): {available: True, theater, structure_count: int, obstructed: bool, level: "clear"|"light"|"heavy", x_m, y_m} Returns (unavailable): {available: False, reason} for an theater with no terrain data installed, an absent scenery sidecar ("no scenery data for <theater>"), or a point out of grid. Raises: ValueError on xy-form Position, or a co-registration mismatch between the sidecar and the terrain .dat (loud -- a bad sidecar is worse than none).
ParameterTypeDescription
positionGeoPositionrequiredA point by latitude and longitude ONLY: {"lat_lon": {"lat": ...,
theaterstringrequired
footprint_mnumberoptionalDefault: 0.0.

Remove trees and/or static scenery objects inside a trigger zone at mission start.

Details · 4 parameters (2 required)
Creates a TriggerStart (fires once, no conditions, at mission start) that carries a RemoveSceneObjects action targeting the named zone. IMPORTANT - tile quantization caveat: DCS applies RemoveSceneObjects at tile granularity (roughly 100 m). Objects near the zone boundary may be cleared even if they lie slightly outside the zone circle, and objects just inside the boundary in an adjacent tile may be missed. Place the zone center and radius with this in mind; for precise clearance add ~100 m to the desired radius. zone_id: Integer id of an existing trigger zone (as returned by list_zones or add_zone). The zone name is resolved internally -- you do not need to pass the name. objects_mask: Which objects to remove. One of: "trees_only" - vegetation only (safe; no structural damage) "objects_only" - man-made objects only (buildings, statics) "all" - trees AND man-made objects Default: "trees_only" comment: Optional label for the trigger rule as it appears in the ME trigger list. Defaults to "clear_<mask>_<zone_name>". Returns: trigger_index - 0-based position in the trigger list trigger_type - predicate string (always "TriggerStart") comment - the comment actually stored on the rule zone_id - the zone id that was resolved zone_name - the zone name passed to RemoveSceneObjects objects_mask - the normalised mask key ("trees_only" / "objects_only" / "all") objects_mask_value - raw DCS enum integer (0=ALL, 1=TREES_ONLY, 2=OBJECTS_ONLY)
ParameterTypeDescription
mission_idstringrequired
zone_idintegerrequired
objects_maskstringoptionalDefault: "trees_only".
commentstringoptional

Theater & airfield data6 tools

What the map gives you to work with: theaters, airfields, runways, helipads, and parking spots.

List the theaters this release supports.

Details
Returns one {name, terrain_data_installed} entry per theater. `name` is the name to use with new_miz. `terrain_data_installed` says whether the theater's terrain pack is on this machine; with it, elevation, water and line-of-sight queries work there. Every theater listed here is built from ED's own data for that map. A pack that is not installed comes from the dcs-mcp Terrain Manager -- new_miz says how.

List all airfields/airports in the mission's theater.

Details · 1 parameters (1 required)
Returns [{id, name, coalition, lat, lon, parking_total, runways, atc, atc_status, tacan, tacan_status}] for every airport in the terrain. The id field is the airdrome_id you pass to a task tool, add_waypoint (Landing/TakeOff types), etc. coalition is "blue" | "red" | "neutral" -- who owns the field in THIS mission. A flight may be based at any airfield, whichever side owns it, as in the Mission Editor; set_airbase_coalition changes an airfield's side when the user asks for it. atc - {hf, vhf_low, vhf_high, uhf} in HERTZ, or null. ONLY the bands DCS actually gives are present: 26 of Persian Gulf's 27 airfields list VHF_HI alone, and one lists UHF alone. A missing band means DCS has none, not zero -- never treat an absent key as 0 Hz. tacan - {channel, callsign} or null. Most airfields have none: 14 of Iraq's 20, 20 of Afghanistan's 26. No mode is reported, because DCS records none for airfield TACANs. atc_status / tacan_status say WHICH KIND of null you are looking at, and the distinction is the point: "available" a value is present "none_in_dcs" we read DCS's own data and it supplies none here. A fact about the airfield. Do not go looking. "unknown" we could not read DCS's own data for this theater: DCS is not installed (or not found) here, this map itself is not installed in DCS, or DCS's own file for it is not in a form dcs-mcp can read. dcs-mcp's terrain pack does not supply this, and the Terrain Manager will not change it. A question we cannot answer, NOT an absence. Never tell the user such an airfield has no ATC or no TACAN; dcs_install_report says what is missing. For choosing a carrier or tanker TACAN channel use list_tacan_beacons, which covers every beacon in the theater rather than only those attributable to an airfield. Helipad-only sites (FARPs etc.) are not included here -- they show up in list_parking_spots filtered to helicopter=True slots.
ParameterTypeDescription
mission_idstringrequired

List runways at an airfield.

Details · 2 parameters (2 required)
Returns [{name, heading, id, main}] for each runway. heading is in degrees; name is the runway designator e.g. "22-04".
ParameterTypeDescription
mission_idstringrequired
airdrome_idintegerrequired

List helipad parking spots at an airfield.

Details · 2 parameters (2 required)
Returns slots that helicopters can use (helicopter=True). Many airfields have heli spots mixed in with fixed-wing ramps; this filters to just those. Each entry: {parking_id, slot_name, free, large, lat, lon}
ParameterTypeDescription
mission_idstringrequired
airdrome_idintegerrequired

List parking slots at an airfield.

Details · 3 parameters (2 required)
airdrome_id: from list_airfields aircraft_type: optional, and RECOMMENDED -- if provided, returns only slots that are free AND physically fit that aircraft, using DCS's own rule (length, width and height, plus the helicopter/aeroplane split). If omitted, returns ALL slots and you must check the dimensions yourself. Each slot: {parking_id (crossroad_idx), slot_name, free, airplanes, helicopter, large, shelter, length_m, width_m, height_m, lat, lon} SIZE IS THE BINDING CONSTRAINT, not the flags. A spot can be aeroplane-capable, not large and not sheltered, and still be far too small: Bagram's M03 is 21.0 x 15.0 m, and an A-10C is 17.53 m wide, so it does not fit. Many of Bagram's spots are too small for an A-10. Compare length_m/width_m/height_m against the aircraft's own dimensions, or just pass aircraft_type and let this tool do it. `large` is NOT a size summary -- it is False on every slot of every shipped terrain, so it tells you nothing. Use the dimensions. parking_id is the identifier; slot_name is only a printed label and is NOT always unique. Bagram has two spots named D09 (one 21x15, one 41x41) and Syria's Ramat David has seven named 63. Always place by parking_id, and quote slot_name to the user for recognition only. If you request a parking_id that the aircraft does not fit, DCS silently moves it somewhere else, and the mission will not match what you asked for. Pass parking_id values to a task tool's parking_ids to override auto-allocation.
ParameterTypeDescription
mission_idstringrequired
airdrome_idintegerrequired
aircraft_typestring | nulloptional

TACAN channels already in use by this theater's own navigation beacons.

Details · 1 parameters (1 required)
Consult this BEFORE choosing a TACAN channel for a carrier or a tanker -- both are add_task("ActivateBeacon", ...) on the group's waypoint 0, and modify_task for a beacon a tool placed itself. A channel that collides with a map beacon fails IN FLIGHT -- the aircraft locks the wrong station -- rather than failing at build time, so it cannot be caught by validate or by loading the mission. THIS IS WHY NOTHING HERE DEFAULTS A CHANNEL. ED's own editor picks 1X for a new beacon regardless of what the mission already uses -- measured twice, on a second carrier and on a second tanker. DCS's own missions key a carrier's TACAN to its hull number (CVN-71 -> 71, CVN-73 -> 73), which looks like a safe rule and is not: Iraq's own beacons occupy channel 72 and Afghanistan's occupy 75. Returns: available - False if the DCS install or the theater's beacon table could not be read; `reason` says which. The mission is still buildable, you just get no collision check. theater - the theater inspected beacons - [{channel, mode, callsign, name}] sorted by channel. mode is "X", "Y", or null. reason - why the list is empty or unavailable, else null mode is null for most beacons: DCS omits the frequency field the mode would be derived from, on almost every beacon across the supported theaters. Treat a null-mode beacon as occupying BOTH modes -- a carrier on 73Y does not collide with a map beacon on 73X, but if the mode is unknown you cannot rely on that. Read live from the DCS installation, so it reflects the user's actual version rather than anything baked into this release.
ParameterTypeDescription
mission_idstringrequired

Payloads, liveries & loadouts9 tools

Arm and dress aircraft: pylon-level payloads, curated role loadouts from the library, weapons catalogs, and liveries.

Set the weapons load for an aircraft unit, with validation

Details · 5 parameters (3 required)
and post-write coverage reporting. pylons: {pylon_number: CLSID}, or {pylon_number: {"CLSID": ..., "settings": {...}}} to set the store's own settings as well (fuzing, laser code, appearance). Use list_weapons(unit_type) to discover valid pylon numbers and CLSIDs for an airframe. force: if True, write the payload even if validation fails. The rejected assignments are returned under "validation_warnings" so deviations are visible, not silent. Default False rejects the call without writing anything when validation fails. restricted: {pylon_number: [CLSID, ...]} -- stores a player may NOT select for that pylon. {} clears every restriction; omitting it leaves them as they are. A STORE'S SETTINGS ARE CHECKED, with the pylon number and the CLSID. Each store has its own settings -- fuzes, arm and function delays, a laser code -- and list_weapon_settings(clsid) lists them: every setting's key, what it may hold and its default, as the mission file holds them. A key the store does not have, or a value its setting does not allow -- not on its list, outside its range or between its steps, or any but the default where the editor holds it fixed -- fails validation, and the message names the store's own settings. USE THE KEYS, NOT THE MISSION EDITOR'S LABELS: "Tail Fuze Well" is NFP_fuze_type_tail and "Laser Designator PRF Code" is laser_code. A delay belongs to the fuze fitted and is keyed by it (01_prfx_arm_delay_ctrl_FMU139CB_LD is the FMU-139's arm delay), so give a fuze and its own delays together. "Instantaneous" is a function delay of 0, not a fuze. Settings you give are written as given, and a key you leave out of them is not added. A store placed with no settings at all is saved with the store's default settings, as the Mission Editor gives a store it places, and `settings_written` names those keys too. A store this build's DCS data does not have -- a community mod's, say, or one of the few of DCS's own the data missed -- cannot be checked: its settings are written as given, and `settings_not_checked` says so. The settings a mission already carries are never checked or changed by this. THE EDITOR'S PYLON RULES. Stores are placed in the order given, as the Mission Editor places a store picked for one pylon, and DCS's own loading rules apply as they do there: a store that needs another on a second station puts it there (unless one it accepts is already there), a store that cannot be carried with another takes that one off, and taking a store off also takes off what it needed. Every store the rules added or removed is listed under `editor_rules`, with the store that caused it. replace_payload and apply_loadout_from_library, like picking a loadout row in the editor, apply no rules. Semantics: MERGE -- pylons not mentioned in the call are left unchanged on the unit. To clear a pylon, pass an empty string as the CLSID (always valid, never flagged). To REPLACE the whole payload with exactly what you pass, use replace_payload; to take every store off, clear_payload. An empty `pylons` here changes nothing -- it is a merge of nothing. Validation runs in one pass and collects every invalid assignment. Three distinct failure modes: - "invalid_pylon": the pylon number doesn't exist on the airframe. - "clsid_unknown_for_airframe": the CLSID isn't recognized on ANY pylon of this airframe (typo, mod store, etc.). - "clsid_not_on_this_pylon": the CLSID is valid for the airframe but not on the requested pylon (the error message lists the pylons where it is valid). Returns: { unit_id, type, pylons: <every pylon as the saved file will hold it -- a store given no settings shows the store's default table, which the save writes>, coverage: {filled: [...], empty: [...]}, settings_written: {pylon: [keys]} -- the settings the file gets, on every pylon this call placed a store on: the ones given (a store the rules added takes those given with the store that caused it), or the store's default table where none were given settings_validated: true, unless some were written unchecked or forced past the check settings_not_checked?: {pylon: why} -- only when some were restricted: <the unit's restrictions after the write>, editor_rules: [{pylon, added|removed, because_of: {pylon, store, rule}}] -- [] when no rule acted, validation_warnings?: [...] -- only present when force=True wrote assignments that failed validation. } Coverage reflects the unit's actual pylon state AFTER the write -- so merged-in pylons from earlier set_payload calls are counted too. An empty coverage.empty means a fully-armed airframe; a non-empty list is informational, never a rejection (partial loadouts are legitimate).
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
pylonsobjectrequired
forcebooleanoptionalDefault: false.
restrictedobject | nulloptional

Replace an aircraft's whole payload with exactly the pylons you pass.

Details · 4 parameters (3 required)
THE TRUE SET, beside set_payload's merge. set_payload changes only the pylons named in the call and leaves the rest as they were; this one empties the unit first, so afterwards it carries what you passed and nothing else. It is what picking a loadout row in the Mission Editor does to the pylons (me_aircraft.lua:1422-1427). pylons: {pylon_number: CLSID}, or {pylon_number: {"CLSID": ..., "settings": {...}}} -- the same entries set_payload takes. The pylon, the CLSID and the store's settings are validated the same way (list_weapon_settings shows what a store takes). An empty CLSID leaves that pylon empty. {} leaves the unit unarmed, as clear_payload does. force: write even if validation fails; the rejected assignments come back under `validation_warnings`. NOTHING IS WRITTEN IF VALIDATION FAILS (without force): the unit keeps its old payload rather than being left half emptied. WHAT IT LEAVES ALONE: fuel, chaff, flare, gun and ammo_type (modify_unit), and restricted (set_payload). The editor's loadout row changes the pylons, not those. FORCED PYLONS. After setting the pylons the editor writes back any the airframe forces for its current properties; so does this, and they are returned under `forced_pylons`. One airframe in DCS declares any: a Ka-50_3 set to the 2011 modification keeps "<CLEAN>" on pylons 5 and 6. Returns: {unit_id, type, pylons, coverage, replaced: [pylons that carried something before], forced_pylons, settings_written, settings_validated, settings_not_checked? (as set_payload), validation_warnings? (force only)}
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
pylonsobjectrequired
forcebooleanoptionalDefault: false.

Take every store off an aircraft -- the named way back to unarmed.

Details · 2 parameters (2 required)
The Mission Editor's "Empty" loadout row, as a tool. The sixteen create_*_flight tools place aircraft unarmed; after set_payload, replace_payload or apply_loadout_from_library, this returns a unit to that state. (set_payload with an empty `pylons` changes nothing -- it is a merge of nothing -- which is why this exists.) WHAT IT LEAVES ALONE: fuel, chaff, flare, gun, ammo_type and restricted. The editor's "Empty" row changes the pylons, not those. FORCED PYLONS. After emptying, the editor writes back any pylon the airframe forces for its current properties, and so does this. One airframe in DCS declares any: a Ka-50_3 set to the 2011 modification keeps "<CLEAN>" on pylons 5 and 6 -- so "unarmed" on that airframe is what the editor's "Empty" gives, not an empty table. They are returned under `forced_pylons`. Returns: {unit_id, type, pylons, coverage, cleared: [pylons that carried something], forced_pylons}
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired

List the settings a store takes -- its fuzes, arm and function

Details · 1 parameters (1 required)
delays, laser code -- as the Mission Editor's ammunition panel offers them. clsid: the store, as list_weapons gives it (its `settings: true` marks the stores that have any). These are what goes in a pylon's `settings` for set_payload and replace_payload: {"CLSID": ..., "settings": {key: value, ...}}. Both check what you give against this list. Returns: clsid, known `known` is false for a store this build's DCS data does not have (a community mod's, say, or one of the few of DCS's own the data missed): nothing is listed for it and its settings are not checked settings one entry per setting, in the editor's order: key what to write -- NOT the label label the editor's name for it kind "choice", "number" or "laser_code" default what the editor starts it at values for a choice: each {value, name?, shown_as?, also_writes?}. `value` is what to write. `also_writes` is a key the editor writes with that choice, and its value min, max, step for a number. The editor rounds a number to a multiple of its step, so a value between two steps is refused fixed_in_the_editor true for a number the editor shows and does not let you change: only its default is taken unit the unit of the value WRITTEN. The editor shows some in another -- feet for a value written in metres -- and `shown_as` gives the editor's figure: under each value for a choice, as its range for a number digits, lowest_digits, highest_digits for a laser code: how many digits, and the lowest and highest each may be, place by place shown_when the editor shows the setting only when this holds -- a delay keyed by one fuze, while that fuze is fitted. [{id, value, bNot?}, "or" | "and", ...]; bNot true turns that test round -- the setting shows while that fuze is NOT fitted editor_also_writes the keys the editor adds to every settings table of this store, with their values: NFP_PRESID, and NFP_PRESVER where the store's preset has a version. Left out for a store with no preset: the editor adds neither key to its settings An empty `settings` with known true means the store takes none. The list is DCS 2.9.31's, read from a running DCS. A mission saved by an earlier DCS may carry settings under older keys; those are left as they are when a mission is opened and saved.
ParameterTypeDescription
clsidstringrequired

Apply one loadout from DCS's library -- ED's and the user's alike --

Details · 4 parameters (3 required)
to an aircraft unit. unit_id: the unit to arm; its aircraft type is read from the unit. role: required. Canonical task name, display alias, or numeric task id. loadout_name_contains: optional case-insensitive substring filter, matched against EITHER the loadout's displayName OR its name field. Some airframes (e.g. F-5E-3, A-10C, FA-18C) ship loadouts with no displayName, carrying the descriptive text only in name; others (e.g. F-16C) populate both identically. Searching both fields handles every case. Use to narrow the pick when a role has several loadouts (e.g. "AIM-120C" to prefer a C-model CAP loadout). Looks up the unit's aircraft type, reads the library (the same list as list_role_loadouts), filters by role, then by the optional substring. EXACTLY ONE MATCH IS APPLIED; MORE THAN ONE IS REFUSED, NAMING THEM, and nothing is written -- pick one and pass its name. (Ruled 11 Sep 2026. Until then the first match was applied silently.) An EXACT name, case aside, selects that loadout even when it is part of another's name -- otherwise a loadout whose name another contains could never be chosen. PER-STORE SETTINGS COME WITH IT -- fuzing, laser code, appearance, as saved with the loadout -- and are named under `settings_written`. They are NOT VALIDATED, for any weapon: DCS builds a weapon's list of valid settings when it runs and the install does not declare it in a readable form, so they are written as saved and `settings_validated` is false. A store the loadout carries with no settings is saved with the store's default settings, as the Mission Editor saves it, and `settings_written` names those keys too. REPLACES, AS THE EDITOR'S LOADOUT ROW DOES (D4, ruled 14 Sep 2026): the unit's whole payload becomes the loadout, and a pylon the loadout does not name is emptied. Until then this merged like set_payload, keeping what the loadout did not mention. The pylons that carried something before are named under `replaced`. To add stores without disturbing the rest, use set_payload. A LOADOUT IS WRITTEN AS SAVED, as the Mission Editor copies a loadout row. Some of DCS's own library loadouts carry a store that DCS's own pylon list does not offer on that pylon; those are written too, and named under not_offered (empty when every store is offered). Returns: {unit_id, aircraft_type, applied_loadout, loadout_role, loadout_role_numeric, candidates_considered, source_files, pylons, coverage, settings_written, settings_validated: false, replaced, not_offered: [{pylon, clsid, failure, message}]} plus user_loadouts_note when your own loadouts were read from one of several DCS profiles, saying which. Raises: ValueError unit_id unknown / not an aircraft, role unknown, zero loadouts match the role (+ optional substring), or MORE THAN ONE does -- the message names them. RuntimeError DCS's payload library was not found. The message names what is missing and how to fix it -- call set_dcs_install_path with the DCS World folder. FileNotFoundError no UnitPayloads file exists for this aircraft type. Common, and not a failed read: ED ships no library file for many airframes, core ED ones included. Arm those with set_payload.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
rolestring | integerrequired
loadout_name_containsstring | nulloptional

List loadouts from the DCS UnitPayloads library for an aircraft type.

Details · 2 parameters (1 required)
aircraft_type: the plane or helicopter type id (e.g. "F-16C_50", "A-10C_2", "FA-18C_hornet"). Use list_unit_types(category='plane') to discover values. role: optional filter. Accepts a canonical task name ("CAS", "CAP", "SEAD", ...) case-insensitively, a display alias ("Antiship Strike"), or a numeric task id (31). None returns all loadouts. ONE LIST, ED's and the user's alike, as the Mission Editor's grid shows it. Reads <DCS Install>/CoreMods/aircraft/<MODULE>/UnitPayloads/ <aircraft_type>.lua (ED's) and <Saved Games>/DCS/MissionEditor/ UnitPayloads/<aircraft_type>.lua (the user's own, saved from the editor), merged as the editor merges them: a user entry with the same `name` as one of ED's REPLACES it, in place; any other is appended. `pylons` gives each loadout's CLSIDs only. The per-store settings saved with a loadout are not listed here; apply_loadout_from_library fits them. Returns: {aircraft_type, source_files: [...], role_filter: <name|null>, loadouts: [{displayName, name, role, role_numeric, task_ids, pylons}]} Raises: ValueError aircraft_type unknown, or role matches no task type. RuntimeError DCS's payload library was not found. The message names what is missing and how to fix it -- call set_dcs_install_path with the DCS World folder. FileNotFoundError no UnitPayloads file exists for this aircraft_type. Common, and not a failed read: ED ships no library file for many airframes, core ED ones included. Arm those with set_payload.
ParameterTypeDescription
aircraft_typestringrequired
rolestring | integer | nulloptional

List weapons available per pylon for an aircraft type.

Details · 1 parameters (1 required)
unit_type: DCS type string, e.g. 'FA-18C_hornet' -- use list_unit_types with category='plane' or 'helicopter' to find the right id. Returns {pylon_number: [{name, clsid, weight}, ...]} for each pylon that has at least one loadable weapon. The 'clsid' value is what set_payload currently expects. The 'name' field is the human-readable weapon label. A store that has settings of its own -- fuzes, delays, a laser code -- carries `settings: true`; list_weapon_settings(clsid) lists them. Only applies to planes and helicopters -- vehicles/ships/statics have no pylon system.
ParameterTypeDescription
unit_typestringrequired

Set the livery (skin) for a unit or a static object.

Details · 3 parameters (3 required)
Livery names are airframe-specific. Use list_liveries to enumerate. Pass an empty string to revert to the default livery. Returns {unit_id, livery_id, warnings}. `warnings` is always present and usually empty; it carries `livery_unparseable` when livery files on this machine could not be read, and `livery_not_installed` when this DCS install has no such livery for an aircraft's type: it is written as given, since a player may have it installed. A ground unit's or ship's livery is not checked. A static object's livery is set as the Mission Editor's static panel sets it: a static aircraft's is checked as an aircraft's, any other static's is not.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
livery_namestringrequired

List available liveries for a unit type.

Details · 1 parameters (1 required)
unit_type: DCS type string -- use list_unit_types to find the right id. Returns [{name, id}] sorted by name. The 'id' field is what set_livery expects. Pass an empty string to set_livery to revert to the default livery. Only applies to planes and helicopters.
ParameterTypeDescription
unit_typestringrequired

Radios, kneeboards & briefing18 tools

The cockpit paperwork: radio preset channels, intra-flight frequencies, kneeboard pages, briefing text and pictures, and embedded mission resources.

Return the radio configuration of a single unit.

Details · 2 parameters (2 required)
Reports which radios exist (by radio_id), how many channels each has, and what frequency is currently set on each channel. has_panel_radio: True if the airframe supports configurable preset channels. If False, radios is [] and a warning explains. is_client_or_player: True if presets will actually take effect in DCS. AI units' presets are persisted but ignored at runtime. Use this as the discovery call before set_radio_presets to confirm valid radio_ids and channel numbers for the airframe.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired

Return the number of preset channels available on a radio.

Details · 3 parameters (3 required)
Returns 0 if the unit has no configurable radios or radio_id is invalid. Does NOT raise on these conditions (unlike the setter tools -- this is a query). For the full channel map use list_radios.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
radio_idintegerrequired

Set multiple channel presets at once for a single radio on a single unit.

Details · 4 parameters (4 required)
presets: dict mapping channel numbers to frequencies in MHz. Both string and integer keys are accepted (JSON sends strings). e.g. {"1": 251.0, "2": 252.0, "5": 254.5} Transactional: ALL channels and frequencies are validated before ANY are applied. If one channel is invalid, the call raises without mutating anything. An empty presets dict is a no-op (returns current state without mutation). previous_presets: snapshot of all channels on this radio before the call, so callers can see exactly what changed. NOTE: DCS will overwrite, with the group's intra-flight frequency, the channel the aircraft's radio panel connects to it (channel 1 on most aircraft, channel 2 on the Bf 109 and FW-190s), on a radio that takes that frequency; each preset on it is warned of. Call set_intra_flight_frequency first.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
radio_idintegerrequired
presetsobjectrequired

Set a single channel preset on a single radio on a single unit.

Details · 5 parameters (5 required)
radio_id: typically 1 or 2 on modern jets. Use list_radios to confirm valid radio_ids for the airframe. channel: the preset knob position (1-20 on F/A-18C, etc.). Use list_radios or num_radio_channels to see valid channels. frequency_mhz: must be > 0. previous_frequency_mhz: what was set before this call, for tracking. NOTE: DCS will overwrite, with the group's intra-flight frequency, the channel the aircraft's radio panel connects to it -- channel 1 on most aircraft, channel 2 on the Bf 109 and FW-190s -- on a radio that takes that frequency. A write to it is warned of. Call set_intra_flight_frequency first, then set the other channels. Warns (does not raise) if the unit is AI -- presets are persisted to the .miz but DCS does not apply them at runtime.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
radio_idintegerrequired
channelintegerrequired
frequency_mhznumberrequired

Set channel 1 of radio 1 to the given frequency.

Details · 3 parameters (3 required)
Convenience wrapper for the common "set the primary channel" pattern. Equivalent to set_radio_channel_preset(radio_id=1, channel=1, ...). NOTE: set_intra_flight_frequency overwrites channel 1 of radio 1 if it is called on the flight later. Call set_intra_flight_frequency first, then this.
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired
frequency_mhznumberrequired

Restore the airframe's default radio channel configuration.

Details · 2 parameters (2 required)
Reverts all preset channels to the values defined in the aircraft type's panel_radio defaults. Useful for undoing set_radio_presets changes. Raises if the airframe has no configurable radios (same behaviour as the setter tools).
ParameterTypeDescription
mission_idstringrequired
unit_idintegerrequired

Set the intra-flight comms frequency for a flying group, as the

Details · 4 parameters (3 required)
Mission Editor sets it when the frequency is typed into the group's frequency box. The group's modulation is set as the editor sets it: the modulation of the band of the type's radio the frequency falls in (an F-16 at 40 MHz becomes FM), else AM. `modulation` and `previous_modulation` say what it is and was; a change is also said in `warnings`. Each Client/Player unit's radio channels take it where the editor writes it: every channel the type's radio panel marks as connected to the group frequency, on each radio that takes the frequency at that modulation (an F-16 at 124 MHz: the VHF radio's channel 1, not the UHF's). A radio of one plain band takes it even where it cannot tune it, as the editor writes it: its channel then holds the band's edge (an A-10C at 124 MHz: the ARC-164's channel 1 holds 225), which `warnings` says. `channels_written` lists each {unit, radio, channel, frequency_mhz, previous_mhz}; a channel whose value changed is also in `warnings`. AI units' channels are not written, as the editor does not keep them. radio_id, AN OVERRIDE: given, channel 1 of that radio is written instead, on every Client/Player unit, and `radio_choice` says "override" (else "editor"). A radio_id a Client/Player unit lacks is refused, and nothing is changed. Recommended authoring order: 1. set_intra_flight_frequency (writes the connected channels) 2. set_radio_presets for the other channels Waypoint SetFrequency tasks: a flight may carry a SetFrequency WrappedAction on a route waypoint, and that task WINS over fg.frequency at runtime. This call also rewrites every SetFrequency task on the route to the new frequency, so the change actually takes effect; waypoint_tasks_updated reports how many were rewritten (0 for plain flights). Group-level triggered SetFrequency tasks (the rare add_triggered_action location, fg.tasks) are NOT touched. client_units_affected: how many Client/Player units had a channel written. ai_units_in_group: informational; AI units' presets are not modified. The frequency is checked as the Mission Editor checks a group's frequency box, against the bands of the type's own radio as ED's data gives them (its HumanRadio): a frequency outside them is written as asked, with a warning that the editor shows it as invalid. On a Client or Player group (one whose first aircraft is Client or Player) it is refused instead, and nothing is changed: the editor will not save a mission with it. Where the editor does not let the box be edited for a type, nothing is said, as the editor says nothing. With radio_id given, channel 1 of that radio is checked against the radio's band, as a preset channel is.
ParameterTypeDescription
mission_idstringrequired
group_idintegerrequired
frequency_mhznumberrequired
radio_idinteger | nulloptional

Add a kneeboard page, generic (all airframes) or per-airframe.

Details · 3 parameters (2 required)
Kneeboard pages live in a KNEEBOARD/ ZIP folder -- they have NO resource key and are not referenced from the mission dict; DCS shows them in-cockpit by folder location. aircraft_type: None (default) -> GENERIC page at KNEEBOARD/IMAGES/<file>, shown to every airframe. This is the proven, in-sim-verified path. a type string -> PER-AIRFRAME page at KNEEBOARD/<TYPE>/IMAGES/<file>, shown only in that airframe (e.g. "A-10C_2", "FA-18C_hornet"). The folder name is the unit type id; see needs_in_sim_confirmation below. filepath: path to an image (.png .jpg .jpeg .bmp), magic-byte validated; its contents are read now. Returns: scope - "generic" or "per_airframe" zip_path - the in-.miz path the page is stored at filename - image filename aircraft_id - type id (per-airframe only, else None) needs_in_sim_confirmation - True for per-airframe: the folder name is the best offline answer (type id) but is only proven by the live jet rendering it
ParameterTypeDescription
mission_idstringrequired
filepathstringrequired
aircraft_typestring | nulloptional

Attach a kneeboard page for a specific airframe type.

Details · 3 parameters (3 required)
Kneeboard pages are stored at KNEEBOARD/<aircraft_id>/IMAGES/<filename> inside the .miz. They have NO resource key and cannot be referenced in trigger actions. They are visible in-cockpit to all pilots of that airframe type regardless of coalition or group. DCS does NOT support flight-specific kneeboards -- the page is shown to every pilot flying that type in the mission. aircraft_type: the aircraft's type id (e.g. "FA-18C_hornet", "AH-64D_BLK_II"). Use list_unit_types(category="plane") or list_unit_types(category="helicopter") to find type strings. filepath: path to an image file (.png .jpg .jpeg .bmp); its contents are read now. A page already at the same zip path is refused. Returns: aircraft_type - the type string as resolved aircraft_id - the unit type id (the folder name in the .miz) filename - image filename page_index - 0-based index of this page for this aircraft type
ParameterTypeDescription
mission_idstringrequired
aircraft_typestringrequired
filepathstringrequired

List every kneeboard page in the mission, generic and per-airframe.

Details · 1 parameters (1 required)
Pages added this session and pages read from the .miz alike. Each entry carries its in-zip `zip_path`, which is the handle remove_kneeboard takes. Returns: kneeboard_count - total pages generic - pages under KNEEBOARD/IMAGES/ (all airframes) per_airframe - pages under KNEEBOARD/<TYPE>/IMAGES/, with aircraft_id
ParameterTypeDescription
mission_idstringrequired

Remove a kneeboard page by its in-.miz zip_path.

Details · 2 parameters (2 required)
Drops the page so it is no longer embedded on save. Kneeboards carry no resource key, so removing the page leaves no orphan: after add-then-remove the ZIP tree returns to its prior state. zip_path: the exact path as reported by list_kneeboards / add_kneeboard_image (e.g. "KNEEBOARD/IMAGES/page.png" or "KNEEBOARD/A-10C_2/IMAGES/page.png"). Returns: zip_path - the removed path scope - "generic" or "per_airframe"
ParameterTypeDescription
mission_idstringrequired
zip_pathstringrequired

Set mission briefing text fields.

Details · 4 parameters (1 required)
Write one when the user asks for a briefing; otherwise offer it in your reply. All three parameters are optional -- only the ones you supply are changed; the rest keep their existing value. description: general mission description shown to all players blue_task: briefing text for the blue (player) coalition red_task: briefing text for the red coalition Returns the resulting text for all three fields.
ParameterTypeDescription
mission_idstringrequired
descriptionstring | nulloptional
blue_taskstring | nulloptional
red_taskstring | nulloptional

Replace a tab's entire briefing-picture list with the given images.

Details · 3 parameters (3 required)
Clears the tab, garbage-collects any now-unreferenced previous images (orphan-free), then embeds and appends each filepath in order. Pass an empty list to clear the tab. Use this when you want to define a tab's pictures wholesale rather than add/remove one at a time. coalition: "blue", "red", "neutral", or "server". filepaths: list of image paths (.png .jpg .jpeg .bmp), in the order they should appear. Each is magic-byte validated BEFORE any change is made (all-or-nothing). Returns: coalition - normalised tab name resource_keys - the ResKey_ImageBriefing_N strings now on this tab, in order previous_count - how many pictures the tab held before resources_deleted - previous keys that were garbage-collected
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
filepathsstring[]required

Attach an image as a briefing picture for one of the four briefing tabs.

Details · 3 parameters (3 required)
The image is embedded into the resource pool and appended to the specified tab's pictureFileName list. It appears in the DCS briefing screen for that tab. A tab can hold multiple images (call repeatedly). coalition: "blue", "red", "neutral", or "server" (the multiplayer-server briefing tab; "white" is accepted as an alias for "neutral"). filepath: path to an image file (.png .jpg .jpeg .bmp), validated by magic bytes; its contents are read now. Returns: resource_key - the ResKey_ImageBriefing_N string (also listed by list_resources) coalition - normalised tab name filename - image filename tab_count - number of pictures now on this tab
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
filepathstringrequired

Remove a briefing picture from one tab, garbage-collecting if orphaned.

Details · 3 parameters (3 required)
Drops the reference from the named tab's picture list, THEN deletes the underlying resource (mapResource entry + embedded file) only if no other tab or trigger still references it. If the same image is shared by another tab, the file is kept -- only this tab's reference is removed. This guarantees no orphaned resource is left behind. coalition: "blue", "red", "neutral", or "server". resource_key: the resource key (from add_briefing_picture or list_resources) to remove from this tab. Returns: coalition - normalised tab name resource_key - the key removed from the tab references_removed - how many entries were removed from this tab resource_deleted - True if the resource was garbage-collected remaining_referrers - where the resource is still referenced (if kept)
ParameterTypeDescription
mission_idstringrequired
coalitionstringrequired
resource_keystringrequired

Embed a file into the mission resource pool and return its resource key.

Details · 2 parameters (2 required)
The returned resource_key (e.g. "ResKey_Action_123") is what you pass to trigger actions such as RadioTransmission that reference a file by key. filepath: path to a file on the local filesystem; its contents are read now. Supported extensions: images (.png .jpg .jpeg .bmp), sounds (.ogg .wav), scripts (.lua). Returns: resource_key - the ResKey_Action_N string for trigger action params filepath - the absolute path the file was read from filename - the file name it is embedded under resource_type - "image", "sound", or "script"
ParameterTypeDescription
mission_idstringrequired
filepathstringrequired

List all resources embedded in the mission.

Details · 1 parameters (1 required)
Returns four sections: resources - named resources with resource keys (usable in trigger actions); includes images, sounds, scripts. These are listed in mapResource and are the only ones remove_resource can target. briefing_pictures - per-tab lists of briefing picture keys, one list each for blue / red / neutral / server. Each key also appears in the resources list. kneeboards - kneeboard pages grouped by airframe folder (aircraft_type null for generic pages), each page by its zip path, whether added this session or read from the .miz. They have NO resource key. binary_files - every other file the .miz carries, kept as-is on save: files no mapResource names, and anything outside l10n/ and KNEEBOARD/.
ParameterTypeDescription
mission_idstringrequired

Purge a named resource and every reference to it -- no dangling refs.

Details · 2 parameters (2 required)
Removes the resource from the pool in every language (a file no entry names any more stops being embedded) AND strips it from all four briefing tabs, so a reference pointing at a deleted file can't be left behind either. To remove an image from only ONE briefing tab while keeping it on others, use remove_briefing_picture (reference-aware, GC-on-last-use) instead. Trigger actions that reference the key (e.g. a TransmitMessage sound) CANNOT be safely auto-edited, so they are reported as warnings for you to resolve -- the resource is still removed from the pool. resource_key: the resource key as returned by add_resource, add_briefing_picture, or list_resources. Returns: resource_key - the removed key filename - filename of the removed resource tabs_dereferenced - briefing tabs the key was removed from warnings - trigger references that may now be dangling, and group tasks left naming a file the mission no longer has
ParameterTypeDescription
mission_idstringrequired
resource_keystringrequired

Weather & environment2 tools

Mission conditions: weather presets and parameters, and the mission start time.

Set mission weather parameters.

Details · 14 parameters (1 required)
All parameters are optional -- omit to keep existing value. preset: one of DCS's own weather presets, by the name the Mission Editor's weather panel lists -- "Summer. Rain", "Winter. Snow storm", "DEFAULT WEATHER" and the rest, and any the user saved -- applied as the editor's Load button applies it: the preset's values written over the mission's weather, anything it does not set kept, and its date and start time if it carries them. An unknown name is refused with the list. Individual field overrides (applied after preset, if any): visibility_m -- horizontal visibility in metres (80-80000) wind_ground_speed_ms -- surface wind speed m/s (0-50) wind_ground_dir -- surface wind from (degrees true, 0=N; 0-360) wind_2000_speed_ms / wind_2000_dir -- wind at 2000 m wind_8000_speed_ms / wind_8000_dir -- wind at 8000 m temperature_c -- surface temperature in Celsius fog / fog_visibility_m -- enable fog and set its visibility (metres, 0-100000) dust / dust_density -- enable dust and set its density, the Mission Editor's dust box (300-20000) A value outside its range is refused, naming the range: the Mission Editor's weather panel's, and for visibility_m this tool's own (the editor has no visibility box). Returns a summary of the resulting weather state.
ParameterTypeDescription
mission_idstringrequired
presetstring | nulloptional
visibility_minteger | nulloptional
wind_ground_speed_msnumber | nulloptional
wind_ground_dirinteger | nulloptional
wind_2000_speed_msnumber | nulloptional
wind_2000_dirinteger | nulloptional
wind_8000_speed_msnumber | nulloptional
wind_8000_dirinteger | nulloptional
temperature_cnumber | nulloptional
fogboolean | nulloptional
fog_visibility_minteger | nulloptional
dustboolean | nulloptional
dust_densityinteger | nulloptional

Set the mission start date and/or time.

Details · 7 parameters (1 required)
All parameters are optional -- omitted ones keep their existing value. hour/minute/second: 24-hour UTC clock (e.g. hour=6 for 06:00Z dawn) year/month/day: calendar date (e.g. year=2025, month=3, day=21) Common usage: set_start_time(mission_id, hour=6) -- change to 06:00 same date set_start_time(mission_id, hour=14, month=8) -- afternoon in August Returns the resulting start_time as an ISO 8601 string.
ParameterTypeDescription
mission_idstringrequired
hourinteger | nulloptional
minuteinteger | nulloptional
secondinteger | nulloptional
yearinteger | nulloptional
monthinteger | nulloptional
dayinteger | nulloptional

Server & DCS install6 tools

Which server you are talking to and which DCS it found: the build hash, the install report and its capabilities, the override if you keep DCS somewhere unusual, and the one-time export that tells dcs-mcp about your community mods.

Report which build of dcs-mcp is running, and its build fingerprint.

Details
Call this FIRST when reporting or investigating a defect, and whenever a fix is supposed to have landed. It is the only way to tell a current build from a stale one. WHY THE VERSION NUMBER IS NOT ENOUGH. The version compiles in whether or not anything else did, so an old binary and a new one can both say "0.9.9". `build_sha256` is the compiled executable's own hash and cannot be wrong about itself -- if it does not match the hash quoted when the build was handed over, you are testing a different binary and any defect you find may already be fixed. Returns: version the release number running_from "compiled binary" or "source checkout" build_sha256 sha256 of the running executable; null when running from source, with a note saying why executable full path to the running binary dcs_install path to the detected DCS World install, or null dcs_version the installed DCS's version and the one this build's data was taken from, as dcs_install_report gives them terrain_packs how many terrain packages are installed python / platform for support AFTER THE CALL: if the user is reporting a defect, quote `version` and the first 12 characters of `build_sha256` back to them. That is what makes a bug report reproducible.

Show which DCS World install is in use and what it can answer.

Details
Call this whenever a tool says it could not find part of DCS, and before asking the user anything about their install -- most of what you would ask is already here. Returns: install {path, source, candidates, ambiguous, reason} `source` names which signal answered: the environment variable, a path you stored, the registry, or a default folder. `candidates` lists every install found. A path you stored is used even when others are found; they stay in `candidates`. capabilities one entry per feature, each with: name what it is path where it should be present whether it is there -- null when several installs were found and one of them has it: not known until you choose affects which tools depend on it when_absent what happens without it -- refuse / fallback / unknown degraded names of capabilities missing from an install that was otherwise found; null when no install is in use -- see install.reason HOW TO READ IT. `install.path` null means no install was found at all; `install.ambiguous` true means several were found and you should ask the user which one they want, then call set_dcs_install_path with it. A capability that is absent is NOT a broken install -- DCS editions ship different parts, and `when_absent` says what actually happens: only `refuse` stops a tool working. dcs_version `installed` -- the version of the DCS install in use, read from it -- and `data`, the DCS version this dcs-mcp's data was taken from. When they differ, `note` says what that means for the user; tell them. countries where the list of countries comes from: `source` is "install" (read from your DCS) or "shipped" (the list dcs-mcp carries), and `reason` says why it is the shipped one -- no_install, file_missing or file_unreadable. When DCS's own list was there and could not be read, `note` says so; tell the user. mods your community mods, from the export install_mod_export makes: `state` none | current | stale | unreadable, each mod and its version, the types dcs-mcp can place from them, `export_dcs_version` (the DCS that made the export, not necessarily the one installed now), and -- when stale -- the mod folders added, removed or changed since the export, or the DCS update since it. terrain_packs dcs-mcp's own terrain data for each map (from its Terrain Manager -- not the map in DCS): `packs` lists each one installed with its `state`, "current", "older_than_catalogue" or "unknown"; `older` names the ones dcs-mcp has published a newer pack for; `not_recorded` names the ones installed before dcs-mcp kept a record, which its Terrain Manager checks when opened; `note` says what to tell the user. `checked` false means the list of published packs could not be reached (`why`): nothing is known then, which is not "all current".

Tell the server where DCS World is installed, and remember it.

Details · 1 parameters (1 required)
path: the DCS World folder -- the one that CONTAINS CoreMods, e.g. "D:\Eagle Dynamics\DCS World". Not the bin folder, not Saved Games, and not the .exe. Use this when a tool reports it could not find your DCS install, or when dcs_install_report says several were found and you need to pick one. The path is stored per-user and read on every later run, so this is answered once rather than every session. The stored path is used over any other install found; those stay listed in `install.candidates`. VALIDATED BEFORE IT IS STORED. A path with no CoreMods\aircraft inside it is rejected here and now, because a stored wrong path would be read back by every future session and fail the same way with the original typo long forgotten. Returns: stored the path now in force file where it was written install which install is in use now, and via which source capabilities one entry per feature, exactly as dcs_install_report returns them degraded capabilities missing from an install that was found; null when no install is in use -- see install.reason The last three are the same fields dcs_install_report returns, at the top level rather than nested, so you can read the result of the change without a second call. Raises: ValueError the path is not a DCS World install root. NOTE: the DCS_INSTALL_PATH environment variable still takes precedence over a stored path. If one is set, `install.source` in the result will name the variable rather than the path you just stored.
ParameterTypeDescription
pathstringrequired

Forget a previously stored DCS install path and detect again.

Details
Use this after moving or reinstalling DCS, or when a stored path is pointing at the wrong one of several installs. Detection -- the registry, then the default folders -- takes over again immediately. If it finds several installs, `install.ambiguous` is true again. Returns: had_stored_path whether there was one to forget install what detection resolves now that it is gone -- check `source` to see which signal took over capabilities one entry per feature degraded capabilities missing from an install that was found; null when no install is in use -- see install.reason

Let dcs-mcp use your community mods: install a one-time export for DCS to run.

Details
Community mods -- aircraft, vehicles and statics under Saved Games\DCS\Mods -- are programs that only DCS can read, so dcs-mcp learns them from DCS itself. This writes a small script into Saved Games\DCS\Scripts\Hooks. The next time DCS starts, when its main menu appears, the script writes what DCS knows about your mods to Saved Games\DCS\dcs-mcp\mod-export.json and deletes itself. Nothing runs after that, and it changes nothing in DCS, its settings or its install. Tell the user to start DCS once and wait for the main menu. dcs-mcp picks the export up on its next call; no restart is needed. Run this again after a mod is added, removed or updated, or DCS is updated -- dcs_install_report's `mods` says when the export no longer matches. Returns: installed the script's path export where the export will be written next what the user does now mods the current export's status, as dcs_install_report gives it

Remove the script install_mod_export put in DCS, and optionally the export.

Details · 1 parameters (0 required)
The script deletes itself once DCS has run it, so usually there is nothing to remove: this is for a script DCS has not run yet, or to stop using your mods. delete_export: also delete Saved Games\DCS\dcs-mcp\mod-export.json. dcs-mcp then no longer knows your mods until the export is made again. Default false. Returns: script_removed whether a script was there to remove export_deleted whether the export was deleted mods the export's status now, as dcs_install_report gives it
ParameterTypeDescription
delete_exportbooleanoptionalDefault: false.

Geometry & spatial helpers7 tools

Stateless spatial math used while planning: bearings, distances, headings, midpoints, interpolation, and random points — all theater-aware.

Return bearing AND range from from_point to to_point in one call.

Details · 3 parameters (3 required)
Combines heading_between + distance_between for the most common mission-authoring query: "what's the bearing and range from the airbase to the target?" heading_deg: 0=North, 90=East, 0-360. reciprocal_deg: pre-computed return bearing. Distance returned in meters, kilometers, and nautical miles. NOTE: Uses planar theater-XY geometry, not great-circle.
ParameterTypeDescription
mission_idstringrequired
from_pointPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
to_pointPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,

Return the distance between two points in meters, kilometers, and nautical miles.

Details · 3 parameters (3 required)
distance_nm is provided for aviation convenience (1 NM = 1852 m). distance_km = distance_m / 1000. NOTE: Uses planar theater-XY geometry, not great-circle. Error is sub-meter within a single DCS theater.
ParameterTypeDescription
mission_idstringrequired
point_aPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
point_bPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,

Return the bearing from from_point to to_point in degrees (0-360).

Details · 3 parameters (3 required)
reciprocal_deg is the reverse bearing (to_point -> from_point), pre-computed as (heading_deg + 180) % 360. Useful when you need both the outbound and return vectors. NOTE: Uses planar theater-XY geometry.
ParameterTypeDescription
mission_idstringrequired
from_pointPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
to_pointPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,

Return the geometric midpoint between two points.

Details · 3 parameters (3 required)
Equivalent to lerp_point(point_a, point_b, t=0.5). Returns lat/lon and theater xy, plus input echo.
ParameterTypeDescription
mission_idstringrequired
point_aPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
point_bPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,

Linear interpolation along the line from point_a to point_b.

Details · 4 parameters (4 required)
t=0.0 returns point_a, t=1.0 returns point_b, t=0.5 is the midpoint. Values outside [0, 1] are accepted (extrapolation along the line). Use case: "place a marker 25% of the way from the IP to the target" -> lerp_point(point_a=<ip>, point_b=<target>, t=0.25) Returns lat/lon and theater xy, plus t and input echo.
ParameterTypeDescription
mission_idstringrequired
point_aPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
point_bPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
tnumberrequired

Return a point distance_m away from origin on bearing heading_deg.

Details · 4 parameters (4 required)
heading_deg: 0=North, 90=East, 180=South, 270=West. Any value is accepted and normalised to [0, 360). distance_m: must be >= 0. Common use: "30 km on bearing 045 from the SA-6" -> point_from_heading(origin=<sa6_pos>, heading_deg=45, distance_m=30000) Returns lat/lon and theater xy for the result, plus input echo for easy chaining. NOTE: Uses planar theater-XY geometry, not great-circle. Error is sub-meter within a single DCS theater.
ParameterTypeDescription
mission_idstringrequired
originPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
heading_degnumberrequired
distance_mnumberrequired

Return a random point within a ring around origin.

Details · 4 parameters (3 required)
The result is between min_distance_m and max_distance_m from origin. min_distance_m defaults to 0 (full disk, not just the ring edge). NON-DETERMINISTIC -- repeated calls produce different points. Use case: "spawn an enemy somewhere within 5 km of this zone, but at least 2 km away" -> random_point_within(origin=<zone_pos>, max_distance_m=5000, min_distance_m=2000)
ParameterTypeDescription
mission_idstringrequired
originPositionrequiredA point on the map, in ONE of these forms: {"lat_lon": {"lat": ...,
max_distance_mnumberrequired
min_distance_mnumberoptionalDefault: 0.0.