veafAssist — Guided checklists¶
Module ID: ASSIST | File: veafAssist.lua
See it in game: step 17 “Weather, ATC and cockpit assistance” of the demo mission.
Purpose¶
Walks a pilot through a procedure, step by step. At each step the module boxes the cockpit control to operate, ticks the line as soon as that control reaches the right position — or as soon as the pilot confirms it themselves — and moves on. The whole checklist stays on screen as a picture.
The module knows nothing about any aircraft: checklists are data, written in YAML and converted when the mission is built.
One aircraft ships with a checklist: the F-16C (engine start).
For pilots¶
F10 radio menu → ASSISTANCE. One entry per checklist that applies to your aircraft; if yours has
none, no entry appears.
Once a checklist is running, two entries appear at the top level of the VEAF menu — not inside
ASSISTANCE — to spare a menu round-trip on every step:
| Entry | Effect |
|---|---|
| ASSISTANCE: CONFIRM THE STEP | Ticks the current step — only for steps that wait on your confirmation |
| ASSISTANCE: SKIP THE STEP | Ticks the step without doing it, and moves on |
The ASSISTANCE submenu keeps the occasional commands:
| Entry | Effect |
|---|---|
| Hide / show the checklist | Hides or brings back the picture |
| Stop the assistance | Ends the session, clears the box and the picture |
Two behaviours worth knowing in advance:
- Steps already done are ticked on start. You can call for assistance half-way through a procedure: what you have already set is not asked for again.
- A step can be skipped. If a step refuses to validate — a mis-measured tolerance window, say —
Skip this stepkeeps you from being stranded.
A skipped step shows as ticked like any other on the picture; the text message is what tells you at the time. The picture is the dashboard, the texts carry the events.
For mission makers¶
Enable the module¶
modules:
ASSIST:
enabled: true
display: picture # `picture` (default) or `text`
checklists: [f16c-cold-start] # the checklists this mission activates
- With a
checklists:list: exactly those. An unknownidfails the build, rather than leaving a menu entry silently missing. - With no list: the checklists you dropped in your mission's
checklists/folder are activated. Never the whole shipped catalogue — every activated checklist embeds one picture per step in the.miz. - Module absent or
enabled: false: nothing is loaded, nothing is generated, no image in the.miz.
Picture or text¶
display chooses how the checklist is shown, and it is a build-time choice:
| Mode | What the pilot sees | What it costs |
|---|---|---|
picture (default) |
the whole checklist on screen, lines ticking as you go | one image per step embedded in the .miz, around 10 KB each |
text |
a message giving the current instruction and the progress (Step 3/6: …) |
nothing: no image is rendered or embedded |
The cockpit control is boxed either way: text mode drops the picture, not the assistance. An unrecognised value fails the build — a typo must not quietly fall back to the expensive mode.
Concretely, the shipped F-16C checklist weighs 68 KB as picture and 0 as text. At forty steps the
difference passes half a megabyte.
Without knowing the technical names¶
A step needs the cockpit element, the animation argument and the value that means "in position". All three are buried in the Lua files of a DCS install — nobody should have to go and find them.
Describe the control in your own words instead, beside the label:
steps:
- label: Battery
control: MAIN PWR sur BATT # the control, then the position you want
- label: Throttle
control: throttle sur IDLE
Then run:
veaf-tools cockpit resolve-checklist checklists/my-checklist.yaml
It fills in the technical fields in your own file, under each control, and adds a
resolved_from recording the text they came from:
- label: Battery
control: MAIN PWR sur BATT
element: PTR-ELEC-TMB-MPWR-510
argument: 510
equals: 0.0
resolved_from: MAIN PWR sur BATT
Your comments, your indentation and your blank lines survive: it is your file.
One file to maintain. Edit a control, run the command again: only the steps whose text changed
are touched — that is what resolved_from is for. A step whose control no longer matches its
resolved_from fails the mission build, rather than shipping a step that would check the old
control with nobody the wiser.
--dry-run shows what would be written without touching the file.
Writing a good control¶
Name the control as the cockpit names it, then the position: throttle sur idle, not "throttle
up". Filler words (sur, the, button, switch, position…) are ignored, in English and in
French alike, and accents and case do not matter.
A refusal is not a failure¶
The tool refuses rather than guesses, because a wrong resolution produces a checklist that looks finished and never validates — and you only find out sitting in the cockpit. It refuses, saying what it found, when:
- no control matches;
- several match equally well (
MAIN PWRandMAIN PWR Test): only you know which; - the position named does not exist on that control — it then lists the ones that do;
- that control's position values are unknown. Most of the AH-64D's controls are like this: write
argumentandequalsby hand, or measure the position in game.
If a single step is refused, nothing is written: a half-resolved file is worse than an unresolved one.
Finally, a control with no readable position — a button, or a spring-loaded switch like the F-16C's JFS — resolves to a pilot-confirmed step, and the tool tells you so. That is not a shortcoming: those controls are back at rest before anything can read them, by any means.
Exploring a cockpit¶
Writing a checklist means knowing three things about a control: its element, its animation argument, and the value of the position you want. This command gives you all three by handling the cockpit, with nothing to read:
veaf-tools cockpit explore-cockpit F-14BU
Move a switch: the tool names it, and prints the step ready to paste into your file. The value is measured, not inferred. Ctrl-C to stop.
This is what unblocks the aircraft the resolver cannot help with: on the AH-64D, 7 controls out of 478 have a position value known to the files — handling them gives you all the others.
The other way round, --control "transfer pump" boxes the control in your cockpit before it starts
watching, so you can check at a glance that your wording points at the right thing — or simply find
it.
Same conditions as verification: DCS on this machine, dcs-serve running, the bridge in the
mission. And like it, the tool never moves anything: it boxes, you handle.
Verifying a checklist in the cockpit¶
A value the resolver wrote stays a hypothesis until the control has been read with the switch physically in the wanted position. This command does that, with you at the controls:
veaf-tools cockpit verify-checklist checklists/my-checklist.yaml --write
For each measurable step the tool boxes the control in your cockpit and waits for you to move it. As soon as the value changes and settles, it reads it and compares it with the checklist's. You stay at the controls throughout: the tool never throws anything itself, it only boxes — which is also handy when you cannot find the control.
--write marks the confirmed steps verified: true, so a later run does not redo them.
Three conditions: DCS runs on this machine (the read goes through Export.lua, which is local),
dcs-serve is running, and the mission embeds the bridge. A value read different from the expected
one is flagged in red: that is the interesting case, and it means the checklist has the wrong value.
Which validation mode to choose¶
A step validates in one of three ways, and the choice depends first on where your mission will run.
| Mode | What is read | Multiplayer |
|---|---|---|
argument |
the position of a cockpit control | solo and local training only |
param |
a value the aircraft publishes (altitude, speed, gear) | anywhere |
confirm |
nothing: the pilot ticks it | anywhere |
The rule, in one sentence: if your mission is meant for the server, do not use argument. That
read goes through Export.lua's environment, which runs on the pilot's machine; from a dedicated
server it probably will not work — this is not verified yet. Nothing breaks either way: the step
simply never ticks itself and the pilot uses "Skip".
The resolver produces argument wherever it can, because a start-up checklist is flown alone first.
For a server mission, turn those steps into confirm — delete the argument and equals lines and
write confirm: true.
Format reference¶
This part describes the technical fields. You do not need it to write a checklist: it is for reading a resolved file, or hand-writing a step the resolver refused.
The fields of a step¶
One file per checklist, in checklists/ beside your mission.yaml. An id that matches a shipped
checklist overrides it.
id: f16c-startup # unique; this is the override key
title: F-16C engine start # i18n catalog key, or plain text
aircraft: [F-16C_50] # DCS type names; an unknown type is rejected
menu: cold-start # slot under "ASSISTANCE"
steps:
# Pilot-validated: the element is boxed to show where to look
# (`label` also accepts {fr: …, en: …} — see below)
- label: MAIN PWR switch to MAIN PWR
element: PTR-ELEC-TMB-MPWR-510 # cockpit element to box
confirm: true
# Automatically validated: a value the aircraft publishes is read
- label: Gear down
param: BASE_SENSOR_NOSE_GEAR_DOWN
equals: 1.0 # target value…
tolerance: 0.05 # …within this tolerance (0.05 by default)
# Wide window: range replaces equals + tolerance
- label: Speed between 250 and 300 kt
param: BASE_SENSOR_IAS
range: [128.0, 154.0]
Things to keep in mind:
- A
label(and thetitle) can be written three ways:
| Written | Meaning |
|---|---|
label: assist.f16c.main_pwr_batt |
a VEAF catalog key — what the shipped checklists use |
label: MAIN PWR switch to BATT |
plain text, one language |
label: {fr: MAIN PWR sur BATT, en: MAIN PWR switch to BATT} |
your own translations, written in place |
The mapping form is resolved at build time, in the mission's language — the same one the
picture is rendered in, so the two cannot disagree. A missing language falls back to French, then
to any translation present: a label in the wrong language beats no label at all.
- element is independent of the validation mode: a gauge can be boxed while the pilot is the
one who says it is good.
- Three ways to validate a step: argument (a control's position), param (a value the
aircraft publishes), or nothing at all — then the pilot ticks it. A step declares exactly one.
- The default tolerance of 0.05 suits the values that read 0 or 1. For an altitude or a speed,
give your own tolerance, or a range.
- A mistake in the file fails the build with a message naming the offending file, rather than
producing a Lua error in game.
Iterating on a checklist without redoing the whole start-up¶
Checking step 30 of an engine start normally means performing the 29 before it, in a cockpit. That is what makes iterating on a checklist tedious enough to discourage fixing small things.
Hence dev_condition, a development hatch: the step passes without the cockpit ever being in the
required state.
- label: MAIN PWR to BATT
element: PTR-ELEC-TMB-MPWR-510
argument: 510
equals: 1.0
dev_condition: true # absent from a shipped checklist
Put it on the steps you want to skip — typically 1 to 29 — and leave the one you are testing alone: when the session opens, the assistance ticks the hatched steps and stops on yours.
It is not a validation mode: the step keeps its argument/param/confirm. The hatch
short-circuits the evaluation rather than replacing the measurement, so you can remove it without
rewriting anything.
Three guards, because a hatched checklist reaching production would tell a pilot they did something they did not:
- Absent means today's behaviour, exactly. And
dev_condition: yesordev_condition: 1are refused: onlytrueandfalseare accepted, so a typo cannot open the hatch. - The build warns you, naming the checklist and the number of every step involved. It does not refuse: otherwise you could not build the mission you wanted to try in the first place.
- The pilot sees it on screen when the checklist starts: "⚠ N step(s) tick themselves". That is the guard which depends on nobody reading a log.
Reading a switch position: argument¶
- label: MAIN PWR switch to MAIN PWR
element: PTR-ELEC-TMB-MPWR-510
argument: 510 # the control's animation argument
equals: 1.0
tolerance: 0.05
The trailing number of an element name is the argument: PTR-ELEC-TMB-MPWR-510 → 510.
Which value for which position? It cannot be worked out from the hint: the F-16C's MAIN PWR
reads MAIN PWR/BATT/OFF and runs +1 / 0 / −1 — the other way round — while OFF/BACKUP runs
0 / 1. The only reliable source is the aircraft's own keyboard and joystick bindings, which
state the position-value pair outright: MAIN PWR Switch - OFF sets −1, - BATT sets 0,
- MAIN PWR sets +1. That is exactly what the resolver reads for you; writing
a control spares you this whole paragraph.
⚠️ Multiplayer caveat: this mode is for solo and local training only — see Which validation mode to choose.
Two cases where argument will not work anyway:
- a spring-loaded switch (
springloaded_*inclickable_defs.lua, like the F-16C's JFS) is back at neutral before anything reads it; - a button is not a position: the F-16C's argument 757 is the throttle's cut-off finger lift, not the throttle's position.
Measurements and details: DCS cockpit + picture API.
Find a param¶
What can be read is a control's effect, not the control. On an F-16C on the ramp, 78 values are published, among them:
| Parameter | What it holds |
|---|---|
BASE_SENSOR_NOSE_GEAR_DOWN |
1 nose gear down |
BASE_SENSOR_WOW_LEFT_GEAR |
1 weight on the left wheel |
BASE_SENSOR_CANOPY_POS |
canopy opening, 0 to 1 |
BASE_SENSOR_FLAPS_RETRACTED |
1 flaps retracted |
BASE_SENSOR_IAS |
indicated airspeed (m/s) |
BASE_SENSOR_BAROALT |
barometric altitude (m) |
BASE_SENSOR_HEADING |
heading (radians) |
BASE_SENSOR_FUEL_TOTAL |
fuel remaining |
The list is per aircraft: each module publishes what it wants. To see yours, call
list_cockpit_params() in the mission environment — it returns one NAME:value per line.
Find the element to box¶
The easy way is to write a control and let the resolver find it: it knows
the controls of every indexed aircraft (F-16C, A-10C II, AH-64D, F-14B and F-14B(U)) and gives you
the exact name.
For an aircraft that is not indexed, the name is read from the module's files, inside your DCS installation:
<DCS>\Mods\aircraft\<Aircraft>\Cockpit\Scripts\clickabledata.lua
Only clickable elements are listed there: a gauge or a warning light has no name to box.
You can also index that aircraft once and for all, and the resolver will handle it like the others:
veaf-build update-dcs-data --cockpit-controls --dcs-path "C:/Program Files/Eagle Dynamics/DCS World"
What it costs¶
The display rests on a picture embedded in the .miz, and DCS can only show an embedded resource.
The build therefore generates one picture per progress state: a twelve-step checklist is
thirteen pictures, on the order of 60 to 80 KB in total. A mission that activates no checklist pays
nothing.
The build reports the number of pictures and their total size, so the price is visible at the moment it is incurred.
Known limitation¶
Displayed progress is linear: the picture for step 5 shows the first four ticked. A step the pilot skipped therefore appears ticked like any other. Representing "skipped" faithfully would need one picture per combination of states, which explodes. The text message carries that exception.