Zone setup¶
CTLD zones are declared directly in the DCS Mission Editor by naming your trigger zones with a structured convention. For most zones no scripting is required: CTLD reads every trigger zone name at mission start, parses those that match a known prefix, and registers them automatically. AI transport zones are the one exception — they are declared in your CTLD configuration (see AI transport zones below).
For how pilots actually use these zones from the cockpit, see the Pilot guide.
Naming convention¶
A zone name encodes its type and all of its parameters, separated by _:
TYPE_name_param1_param2_..._paramN
Rule:
_is the field separator. It is forbidden inside any field value (zone name, flag name, etc.). Usefarmmain, notfarp_main.
Zone types at a glance¶
Three prefixes are auto-discovered from DCS trigger zone names:
| Prefix | Zone type | Schema |
|---|---|---|
TRZ |
Troop zone — player pickup and/or extract objective | TRZ_<name>_<A\|R\|B\|N>_<stock>_<flag>_<target> — all 5 fields required |
WPZ |
Waypoint zone — troops deployed inside march to the zone centre | WPZ_<name>_[R\|B\|N] |
LGZ |
Logistic zone — crate and vehicle services | LGZ_<name>_[R\|B\|N] |
A fourth kind — AI transport zones (AIZ) — is not name-discovered. It is declared entirely in config; see AI transport zones.
There is no separate
EXZprefix. Extract objectives are a function of a TRZ (a troop zone withstock = 0and an objective flag), described under Troop zones.
Coalition parameter:
| Value | Coalition |
|---|---|
A |
All coalitions (TRZ only) |
R |
RED only |
B |
BLUE only |
N |
Neutral |
| (omit) | All coalitions (WPZ / LGZ only — TRZ requires an explicit A) |
Uniqueness: two zones of the same prefix cannot share the same
name. A zone name already registered is never overwritten by a later one.
One name space for every kind of zone
Troop zones share a single name space — TRZ_, WPZ_, AI zones and the legacy
troopZones all register into it, and the first one registered wins. What makes this easy to
trip over is that a TRZ_ zone registers under its parsed name: TRZ_dropzone1_B_0_nil_0
occupies the name dropzone1.
So an aiZones entry whose dcsZoneName is dropzone1 — pointing at a genuinely different
Mission Editor zone — collides with that TRZ and is dropped. CTLD reports it at mission
start:
[ERROR] ZoneManager: AIZ[1] ERROR 'dropzone1': name already taken by zone
'TRZ_dropzone1_B_0_nil_0' — entry ignored
The fix is always the same: give the two zones different names. Registration order is
TRZ_ → AI zones → WPZ_ → legacy tables.
Troop zones (TRZ)¶
A troop zone provides player pickup and/or an extract objective.
Schema: TRZ_<name>_<A|R|B|N>_<stock>_<flag>_<target>
All 5 fields are required. The parser rejects any TRZ name with a missing or invalid field —
a warning is written to CTLD.log and the zone is ignored.
| Field | Position | Values | Meaning |
|---|---|---|---|
name |
2 | any (no underscores, not a reserved word) | Zone identifier used in logs and F10 menus |
coalition |
3 | A R B N |
Who can interact: A=all, R=RED, B=BLUE, N=NEUTRAL |
stock |
4 | integer 0–999 | 0=no pickup · 1–998=limited · 999=unlimited |
flag |
5 | DCS flag name or nil |
Flag incremented by soldier count on extract; nil = no objective |
target |
6 | integer ≥0 | 0=no threshold · N≥1=soldier-count goal for a DCS victory trigger |
Reserved words — forbidden as
nameorflag:nil,A,R,B,N.
Stock values¶
stock |
Pickup capability | What the pilot sees |
|---|---|---|
0 |
None — no pickup | No "Load from" entry in the F10 menu |
1–998 |
Limited — decrements on each load | "Load from <name> (N remaining)" |
999 |
Unlimited — never exhausted | "Load from <name>" |
Use
999for unlimited pickup — not0.0means no pickup capability.
Flag and target values¶
flag |
target |
Behaviour |
|---|---|---|
nil |
any | Zone has no objective. Troops deployed here spawn as a DCS ground group. |
| a flag name | 0 |
Objective active, no threshold. CTLD increments the flag by the soldier count each time troops are deployed inside. |
| a flag name | N≥1 |
Objective with a threshold. CTLD increments the flag; you write the DCS victory trigger flag >= N. CTLD initialises the flag to 0 at mission start and never ends the mission itself. |
Examples¶
| Zone name | Coalition | Stock | Flag | Target | Behaviour |
|---|---|---|---|---|---|
TRZ_base_B_50_nil_0 |
BLUE | 50 (limited) | — | — | Pickup — 50 soldiers, restock on RTB |
TRZ_depot_A_999_nil_0 |
All | unlimited | — | — | Pickup — unlimited, all coalitions |
TRZ_exfil_B_0_rescue_0 |
BLUE | no pickup | rescue |
none | Extract-only — deploying troops here increments flag rescue |
TRZ_lz_R_0_secure_100 |
RED | no pickup | secure |
100 | Extract with win condition — RED objective at 100 soldiers |
TRZ_fob_N_20_defend_50 |
Neutral | 20 (limited) | defend |
50 | Mixed — pickup (20) + extract objective |
TRZ_marker_B_0_nil_0 |
BLUE | no pickup | — | — | Inert — named marker, no function |
Annotated:
TRZ _ fob _ N _ 20 _ defend _ 50
│ │ │ │ │ │
│ │ │ │ │ └─ target : 50 soldiers complete the objective
│ │ │ │ └──────────── flag : "defend" (DCS flag name)
│ │ │ └─────────────────────── stock : 20 troops max (limited pickup)
│ │ └────────────────────────────── coalition: NEUTRAL
│ └────────────────────────────────────── name : "fob"
└───────────────────────────────────────────── prefix TRZ
Extract-only zone (
stock = 0): no "Load from" entry appears in the F10 menu. The zone only serves as an objective trigger when troops are deployed inside it.Mixed zone (
stock > 0andflag ≠ nil): supports both boarding and objective scoring. When a pilot lands inside with troops aboard, the objective takes priority — the flag is incremented and no DCS group is spawned. Stock restore on RTB happens only in pickup-only zones.Smoke: troop-zone smoke colour is set globally per coalition via the
troopZoneSmokeColorsetting (see Configuration), not per zone name.
See Troop transport for the pilot-side workflow (boarding, deploying, extracting).
Pickup points on ships¶
A pickup point can sit on a ship instead of a trigger zone. The zone rides the vessel, so troops still board after the carrier has moved. Two settings, in Configuration:
| Setting | What it names | Use it when |
|---|---|---|
troopZones |
a unit name, when no trigger zone carries that name | you want this ship, with your own stock and smoke settings |
troopZoneShipTypes |
DCS type names | you want every carrier to be a pickup point, without naming them |
# Every Nimitz- and Stennis-class carrier and every Tarawa in the mission
# becomes an unlimited troop pickup point — no unit name anywhere.
troopZoneShipTypes:
- CVN_71
- Stennis
- LHA_Tarawa
A ship-backed zone always uses a 200 m radius, whichever setting created it. Discovered zones
have unlimited stock and no smoke; if you need a limit, a smoke colour or a coalition of your
own, name that ship in troopZones — an explicitly configured zone of the same name always wins.
A listed type no ship matches is not an error: it is a catalogue of types, reusable across
missions.
Use the type name, not the name shown in the editor
Both settings match the DCS type id, which is not always what the Mission Editor displays.
ctld-tools validate rejects a name that matches no known DCS type, so a typo is caught before
the mission ever runs.
Waypoint zones (WPZ)¶
When troops are deployed (fast-rope or ground drop) at a point that falls inside an active WPZ, they automatically march toward the centre of that zone instead of searching for the nearest enemy.
Schema: WPZ_<name>_[R|B|N]
| Example name | Meaning |
|---|---|
WPZ_hill47_B |
BLUE waypoint zone "hill47" |
WPZ_bridge |
All-coalition waypoint zone |
The zone radius is taken from the DCS trigger zone editor.
WPZ zones do not appear in the F10 menu — they act silently at deploy time.
Logistic zones (LGZ)¶
A logistic zone defines a base where pilots can spawn and pack crates and vehicles from the F10 menu. A pilot must be inside a logistic zone to use these services.
Schema: LGZ_<name>_[R|B|N]
| Example name | Meaning |
|---|---|
LGZ_depot1_B |
Logistic zone "depot1", BLUE only |
LGZ_farmmain_R |
Logistic zone "farmmain", RED only |
LGZ_shared |
Logistic zone open to all coalitions |
Radius: an
LGZ_zone is a circle centred on the trigger zone, with a radius taken from thedynamicZoneRadiussetting (default 200 m). The trigger zone's own editor radius is not used for LGZ. SetdynamicZoneRadiusin Configuration to change it globally.
See Crate catalogue for what can be spawned, and Crates for the pilot workflow.
Logistic zones carried by a unit or a static¶
A logistic zone can also be attached to a mission object rather than a trigger zone. The zone follows the object, so a carrier keeps its logistic point as it steams, and it disappears when the object is destroyed. Two settings do this, in Configuration:
| Setting | What it names | Use it when |
|---|---|---|
logisticUnits |
unit / static names placed in the ME | you want this specific object to be a logistic point |
logisticUnitTypes |
DCS type names | you want every carrier, or every ammo dump, without naming them |
# Every Stennis-class carrier and every FARP ammo dump in the mission
# becomes a logistic point — no unit name anywhere.
logisticUnitTypes:
- Stennis
- CVN_71
- FARP Ammo Dump Coating
A type listed here that no mission object matches is not an error: this is a catalogue of
types, reusable from mission to mission, not a list of the units a given mission holds. A name in
logisticUnits behaves the other way round — it names one object, so a missing one is logged as a
warning.
Both use the maximumDistanceLogistic radius (default 200 m). When a zone already exists under
that object's name — from an LGZ_ trigger zone or from logisticUnits — it is kept as it is:
type discovery never overwrites.
Use the type name, not the name shown in the editor
logisticUnitTypes matches the DCS type id, which is not always what the Mission Editor
displays. The FARP ammo dump is the classic trap: the editor calls it FARP Ammo Storage, but
its type id is FARP Ammo Dump Coating. ctld-tools validate rejects a name that matches no
known DCS type, so a typo is caught before the mission ever runs.
Logistic zones created at runtime¶
The only way to add a new logistic zone during a live mission is to deploy a FOB. When the
FOB build completes, CTLD automatically registers a circular logistic zone centred on the FOB
site (radius = fobLogisticZoneRadius, default 150 m, under the FOB's name). No LGZ_ trigger
zone or config entry is required. See Scenes & FOB for the full FOB lifecycle,
including how a destroyed FOB removes its logistic zone.
Deactivating and reactivating a logistic zone¶
Use the CTLDZoneManager API from a DO SCRIPT trigger to simulate zone capture or a temporary
loss. This works for both LGZ_ trigger zones and logisticUnits-based zones:
-- Deactivate — zone is ignored by all pilots until reactivated
CTLDZoneManager.getInstance():deactivateLogisticZone("depot1")
-- Reactivate — zone becomes available again
CTLDZoneManager.getInstance():activateLogisticZone("depot1")
The zone stays registered and can be toggled any number of times.
AI transport zones (AIZ)¶
AIZ zones control the automatic behaviour of AI transports (units listed in
transportPilotNames). Human players are never affected by them.
AIZ zones have no naming convention. Any DCS trigger zone can be an AIZ zone — you reference it by name in the
aiZonesconfig array. Both pickup and drop-off fire on landing (S_EVENT_LAND): the AI unit must physically land inside the zone radius.
Roles¶
| Role | Trigger | Behaviour |
|---|---|---|
| Pickup | AI transport lands inside the zone | Loads troops and/or a whole vehicle |
| Drop-off | AI transport lands inside the zone | Deploys troops and/or unloads a whole vehicle |
A zone may be pickup only, drop-off only, or both.
Config declaration¶
aiZones is a list of entries in your configuration. ctld-tools gives it a dedicated editor under
the Zones family; in a hand-written snapshot it lives under mm_facing:
mm_facing:
aiZones:
# Troops-only pickup: two templates with per-template stock
- dcsZoneName: my_base
coalition: BLUE
isPickup: true
cargoType: T
troopStock:
Standard Group: 5
Anti Tank: 2
# Troops-only pickup: every compatible template, unlimited
- dcsZoneName: depot_alpha
coalition: BLUE
isPickup: true
cargoType: T
troopStock:
All: -1
# Vehicle-only pickup (vehicles must be physically in the zone)
- dcsZoneName: armor_depot
coalition: BLUE
isPickup: true
cargoType: V
vehicleStock:
Hummer: 3
M1045 HMMWV TOW: -1
# Troops + vehicle pickup
- dcsZoneName: hub_tv
coalition: BLUE
isPickup: true
cargoType: TV
troopStock:
All: -1
vehicleStock:
Hummer: 5
# Ground-only drop-off
- dcsZoneName: lz_front
coalition: BLUE
isDropoff: true
aiDropMode: G
# Ground + parachute drop-off (default)
- dcsZoneName: lz_rear
coalition: BLUE
isDropoff: true
coalition here is a word, not a number
Every other coalition field in the CTLD configuration is the numeric side (1 = RED,
2 = BLUE). In an aiZones entry it is the string RED, BLUE or NEUTRAL. Writing a number
here means "any coalition", silently.
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
dcsZoneName |
string | ✅ | Exact name of the DCS trigger zone |
coalition |
"RED" / "BLUE" / "NEUTRAL" |
✅ | Which AI transports use this zone |
isPickup |
true |
one of the two | Marks the zone as a pickup zone |
isDropoff |
true |
one of the two | Marks the zone as a drop-off zone |
cargoType |
"T" / "V" / "TV" |
pickup only | Troops, whole vehicle, or both. Default "T" |
troopStock |
table { [name] = N } |
pickup + troops | Per-template stock. N = -1 unlimited, N > 0 limited. Special key All = every compatible template. Must be present to enable troop pickup. |
vehicleStock |
table { [type] = N } |
pickup + vehicles | Per-type stock, same -1 / N / All rules. Must be present to enable vehicle pickup. |
aiDropMode |
"G" / "P" / "GP" |
drop-off | G ground, P parachute, GP either. Default "GP" |
troopTemplates |
{ "Name1", ... } |
optional | Whitelist of troop templates eligible at this zone |
vehicleTypes |
{ "TypeName", ... } |
optional | Whitelist of DCS vehicle type names eligible for loading |
troopStockandvehicleStockare tables, not plain integers. Per-template / per-type stock replaced the old single-integer form.
AI transport setup¶
- Create trigger zones in the ME (any name, any radius suitable for landing).
- Declare them in
aiZones(above). - Add each AI unit's exact DCS unit name to
transportPilotNames, which is a plain list of names:
mm_facing:
transportPilotNames:
- heliai_supply
- heliai_medevac
- Route the AI unit so it lands inside the zones (waypoints with a "Landing" task).
A whole vehicle is only loaded if its weight does not exceed the transport's
maxVehicleWeightand at least one aircraft hascanTransportWholeVehicle = true. See Configuration for weights and capabilities.
Validation report¶
At mission start CTLD validates every aiZones entry and, if there is anything to report,
displays a grouped list of errors and warnings on screen (30 s) and in CTLD.log, in the mission
language. If everything is valid, a single INFO line is logged and nothing pops up.
An entry is ignored (error) when it has no dcsZoneName, a duplicate dcsZoneName, a zone
absent from the Mission Editor, a missing or invalid coalition (must be RED / BLUE /
NEUTRAL), neither isPickup nor isDropoff, or vehicle cargo (V / TV) while no aircraft
can carry a whole vehicle. Common warnings (the zone is still created): an invalid cargoType
falls back to "T", an invalid aiDropMode falls back to "GP", a pickup zone missing the
matching troopStock / vehicleStock has that pickup disabled, unknown troopTemplates /
vehicleTypes names, and a pickup zone overlapping a drop-off zone of the same coalition (risk of
an instant pickup+drop-off loop).
Legacy zone configuration¶
Missions built the classic CTLD v1 way — zone names listed in config tables rather than parsed
from trigger names — are still supported. The _ character is allowed in the names here,
because these are plain DCS trigger (or unit) names, not parsed schemas.
These are ordinary configuration settings, and their entries are positional arrays: the meaning
of a value comes from its place in the list. ctld-tools edits them as named fields under the
Zones family, which is the safest way to touch them; written by hand they look like this:
mm_facing:
# Troop pickup zones — v1 called this pickupZones.
# [ DCS zone name, smoke colour, limit, active, side ]
# smoke colour : none | green | red | white | orange | blue
# limit : -1 = unlimited, or any integer >= 1
# active : yes | no
# side : 0 = both, 1 = RED, 2 = BLUE
troopZones:
- - pickzone1
- blue
- -1
- yes
- 0
- - USS Tarawa # a ship unit name is also accepted — the zone rides the ship
- blue
- 10
- yes
- 2
# Waypoint zones (deployed troops march to the centre)
# [ DCS zone name, smoke colour, active, side ]
wpZones:
- - wpzone1
- green
- yes
- 2
# Logistic units: unit or static names placed in the ME.
# If the named object is destroyed, its logistic zone is removed automatically.
logisticUnits:
- logistic1
- logistic2
dropOffZones is not read in CTLD 2.x
v1's dropOffZones table (AI auto-deploy points) has no equivalent setting in CTLD 2. AI
drop-off is configured with AI transport zones — an aiZones entry
with isDropoff: true. A v1 config carrying dropOffZones will have that table ignored — CTLD
says so once at mission start, in the startup report. The v1 smoke colour has no equivalent: an
AI zone is deliberately unmarked. See
Migration v1 → v2
for the before-and-after example and the way to mark the spot anyway.
Legacy zones and auto-discovered zones (TRZ / WPZ / LGZ) coexist without conflict: a zone already registered from trigger-name discovery is never overwritten by legacy config.
For the full v1 ctld.* compatibility surface, see Legacy API.