veafGroundAI — Artillery from a marker, and convoys under fire¶
Module ID: GROUNDAI | File: veafGroundAI.lua
Purpose¶
Gives a group of ground vehicles an autopilot that players command from the F10 map, with the
_gc marker. Two kinds of autopilot exist:
- artillery (
ArtilleryUnitHandler), told to shell a set of coordinates — a few rounds to range in, then a fire-for-effect; - the convoy (
ConvoyUnitHandler), which looks after itself: it watches ahead for the enemy, splits when it sees one, calls for air support and falls back behind cover (convoys under fire).
The module is enabled by default (veaf.registerModule(..., { enable = true }, 190)), and its
commands are reserved to pilots the server knows: KNOWN_PILOT, meaning anyone listed in
veaf-pilots.txt. An unlisted pilot must supply the matching password.
Dependencies¶
veafCommands— receives the marker and applies the security checkveafSecurity— theKNOWN_PILOTtierveafShortcuts— the-ai_setalias and the-arty*family (optional, but the common way in)
The _gc marker¶
_gc, for ground commander. A pilot places a marker on the F10 map and writes:
_gc <name>, <verb> <value>, <parameter value>, ...
The addressee first, the way you would say it on the radio. The <name> is the one you give the
autopilot — you choose it, and you reuse it for every order you give it.
| What you write | What it does |
|---|---|
_gc arty-1 (marker on the battery) |
creates the arty-1 autopilot and starts it |
_gc arty-1, groupname ARTY-1 |
the same, naming the DCS group instead of searching for it |
_gc mybattery, groupname arty-1 |
the same, on a group created by a VEAF command |
_gc arty-1, aim 37T GG 12345 12345 |
ranging fire on that position |
_gc arty-1, correction 09050 |
shifts the last aim point and fires again (adjusting the fire) |
_gc arty-1, fire |
fire for effect at the last aim point |
_gc arty-1, fire 37T GG 12345 12345, shells 40-80 |
fire for effect on a given position |
_gc arty-1, status |
shows what the battery is doing |
_gc arty-1, stop |
stops it; its orders stay in memory |
_gc arty-1, clear |
stops it and clears its orders |
_gc arty-1, start |
restarts a stopped autopilot |
_gc arty-1, unset |
stops it and forgets it entirely |
Writing _gc <name> on its own is the same as writing _gc <name>, set.
The parameters¶
| Parameter | Description |
|---|---|
groupname |
The name of the DCS group to drive. A fragment is enough: the group -arty, unitname arty-1 creates is really called [b]-arty-1#7, and groupname arty-1 finds it. If several groups match, the command is refused and you are told which names it found, rather than one being picked at random. On a set, if you leave the parameter out, the module looks for the allied group nearest the marker, within 250 metres — and tells you if it finds none. |
target |
The coordinates, if you would rather write them separately than after aim or fire (the accepted formats). |
shells |
Number of rounds. Accepts a random range, e.g. 40-80. |
radius |
Dispersion of the fire, in metres. Also accepts a range. |
correct can also be spelled correction: both work, so there is nothing to remember.
_gc arty-1
_gc arty-1, radius 15-30, aim 37T GG 12345 12345
_gc arty-1, correction 09050
_gc arty-1, fire, shells 40-80, radius 50-150
The old syntax still works.
_ground order, name arty-1, order aim; target …is still accepted so that no existing mission breaks, but it is no longer documented: it needed a semicolon where the whole of the rest of VEAF uses a comma, and that was its only trap.
The three orders¶
| Order | Effect | Default rounds | Default radius |
|---|---|---|---|
aim |
Ranging fire: a few rounds to adjust | 2 | 10 m |
fire |
Fire for effect | 40 | 100 m |
correct (or correction) |
Shifts the last aim point and fires again | 2 | 10 m |
aim and fire take the coordinates right after the word: aim 37T GG 12345 12345. correct
takes its offset the same way: correction 09050.
fire with no coordinates fires again at the last aim point — which is what lets you chain a ranging
order and then the effect without giving the position twice.
Both values are validated as they are read: a position or an offset the module cannot read is refused and announced, never guessed at. A number a gun acts on is not something to guess.
_gc arty-1, radius 15-30, aim 37T GG 12345 12345
_gc arty-1, correction 09050
_gc arty-1, fire, shells 40-80, radius 50-150
The coordinate formats accepted¶
A target accepts any of these. They work anywhere VEAF reads a coordinate — AirWaves zones, named
points, QRAs, aliases — because one reader handles them all.
| What you write | What it is | Precision |
|---|---|---|
37T GG 12345 12345 |
MGRS exactly as DCS displays it | 1 m |
37TGG12345678 |
the same, without the spaces | 10 m |
u37TGG123456 |
the older VEAF syntax, still valid | 100 m |
N42:30:15E041:45:30 |
degrees, minutes, seconds | ~30 m |
N42 30 15 E041 45 30 |
the same, separated by spaces | ~30 m |
N42°30'15"E041°45'30" |
the same, with the symbols | ~30 m |
N42:30.5E041:45.5 |
degrees and decimal minutes | ~2 m |
N42.50416E041.75833 |
decimal degrees | ~1 m |
N42E041 |
whole degrees | ~100 km |
The MGRS digit count is the precision: two digits a side is 10 km, five is one metre. An odd digit count is refused rather than guessed — it is a typo, and halving it would produce a position nobody asked for.
S and W give the negative values. Case does not matter.
The practical advice: read the coordinates off your own screen and copy them as they are. The MGRS form DCS shows is accepted untouched, and it is the hardest to mis-transcribe.
Adjusting the fire¶
A battery remembers the last point it aimed at, and correct shifts that point. This is the classic
adjustment loop: fire, watch where the rounds land, call the correction in.
_gc arty-1, aim 37T GG 12345 12345
_gc arty-1, correction 09050
_gc arty-1, fire, shells 40-80
The bearing is always written as three digits, because 090 and 90 would be the same string once
the distance is appended: 09050 is 50 m east, whereas 9050 would read as a bearing of 905 and be
refused.
Two corrections compound: two 09050 in a row and the aim point has moved 100 m east. A later
fire with no target then fires at the corrected point — it is the one aim point both orders share.
A correction is refused, and the refusal is announced to the pilot, in two cases: when it cannot be read (the message then recalls the expected form), and when the battery has no fire mission to correct — firing at the offset alone would put the rounds wherever the battery happens to stand.
Convoys under fire¶
Left to itself, a DCS convoy drives through an ambush at full speed without firing a round, and dies. Measured on 2026-10-08: four vehicles destroyed out of four, no return fire; and when it is given a new route under fire, only its lead obeys while the rest of the column stays where it is. The convoy autopilot does the work instead, with nobody at the controls.
What it does by itself¶
- It watches. Every 30 s it looks for enemy vehicles within 5 km (plus a minute of driving at its speed). While there are some, it checks every 3 s whether it can see them — terrain in between counts, vegetation does not (see the limits).
- It reacts to the first one that matters: an enemy in sight within 3 km, or the first shot received (artillery, aircraft, an ambush it could not see).
- It splits. The unarmed vehicles (trucks…) leave at once to fall back, as their own group, named
<convoy> unarmed. The armed vehicles stay in the convoy's group, which keeps its name. - The armed vehicles fight or fall back. Each vehicle has a combat value: tank 4, infantry fighting vehicle 3, armoured personnel carrier, AAA or other armed vehicle 1, unarmed 0. When the armed ones are worth at least 1.5 times the enemies in sight, they close in to 900 m of the nearest enemy, alarm red, weapons free; otherwise they fall back as well. An aircraft, or fire from beyond 3 km, cannot be fought: they fall back. A ground enemy merely seen counts for its own value, wherever it stands: an infantryman spotted at 3.2 km is worth 1, no more. A campaign assault convoy strong enough, within 5 km of its target, does not stop at 900 m: it drives on across country to the centre of the zone it was sent to take, firing as it goes, since the garrison it attacks stays in sight and the contact would never end. Fire for which DCS names only the shell counts for the vehicle that fired it, or is ignored when DCS does not say: a shell is never a threat. When nobody fires, an enemy in sight but not a shot fired or taken by the convoy for 2 minutes, and its armed vehicles at a standstill, they drive onto the nearest enemy, with no 900 m stop this time, and again every 2 minutes as long as nobody fires: DCS does not always make vehicles held in front of an enemy open fire, and moving is what makes them shoot. A convoy falling back never does this.
- When it falls back, it calls for help, to its coalition, in the shape of a troops in contact call: its position (coordinates and MGRS), how many enemies and of what type, their bearing and distance. A red smoke marks the nearest enemy, a green one the convoy, renewed every 5 minutes while the contact lasts. When the mission can speak (SRS configured), the same call goes out in voice on 243 and 121.5 MHz AM. Only when its side has pilots connected, checked at the call and at each renewal: the smokes and the call are for them, and without them they only show the convoy to the enemy. A red convoy of a campaign nobody flies red in falls back without smoke and without a call. Strong enough to fight, it asks for nothing: an information message gives the contact, how many enemies, their bearing and distance, with no smoke. Either way, an F10 marker shows the convoy to its coalition while the contact lasts ("Mule — convoy in contact"), moved every 15 s and removed once the contact is over.
- It falls back behind cover: toward the nearest friendly place (a campaign zone its side owns, one of its airbases), through a point terrain or a town hides from the enemy; when there is none, the shortest way out of range.
- After the contact. A minute with nothing in sight and nothing received:
- after a fight, once no enemy is left alive around it (an enemy merely out of its sight, it goes back for), it drives on by itself: the armed vehicles go and fetch the unarmed ones, which wait where they fell back, the convoy becomes one again, then drives on by road rather than across country (when they have not met within 10 minutes, each drives on by itself);
- after a fall back, it says so, stops and waits for an order: the enemy it fled is still there, and it does not drive back into the same ambush by itself.
When no player of its side is connected to give that order — the red side of a campaign, typically — it drives on by itself after 5 minutes, as after a fight. This is checked when the delay ends: a player who connected meanwhile keeps the choice, and the check comes back every 5 minutes while he stays. A player of that side is one in a slot of that side (aircraft, helicopter, vehicle); a game master in a neutral slot is not. A new contact during the wait cancels the drive on, and a
_gc <callsign>, holdgiven by a player is never lifted by itself.
A red convoy does exactly the same, on the red side.
It speaks like a crew on the radio, opening with its callsign: "Mule, contact ahead, 3 enemies at 2500 m bearing 045, engaging." The direction (ahead, behind, left, right) is given from the convoy's heading. The contact report comes first; the tactical messages ("the unarmed vehicles are falling back") follow 15 s later.
Which groups¶
- Every convoy spawned by
_spawn convoy, automatically. Beware:-convoyspawns a red convoy by default — a target. For a friendly one, addside blue:-convoy, dest ALPHA, side blue. - A Mission Editor group listed in
mission.yaml(below). - Any group, in game:
_gc <name>, convoy, with the marker on the group (or withgroupname).
Each convoy has a callsign, which is also the name _gc uses for it: the name given in _gc <name>, convoy, otherwise the first free one of a list of beasts of burden (Mule, Bison, Yak, Lama, Zebu, Buffle, Chameau…), without accents so that it types easily; once the list is used up, it starts again with a number (Mule 2). _gc <callsign>, status recalls it, with the group's DCS name; a part of the callsign is enough.
The orders¶
| What you write | What it does |
|---|---|
_gc mule, retreat |
falls back by road to the nearest friendly place |
_gc mule, retreat KOBULETI |
falls back to this named point, or these coordinates |
_gc mule, hold |
stops where it stands, both groups |
_gc mule, resume |
drives on (by itself after a won fight, and 5 minutes after a fall back when no player of its side is there): the armed vehicles go and fetch the unarmed ones, which wait for them, the convoy becomes one group again within 300 m and takes the road |
_gc mule, status |
what the convoy is doing (driving, alerted, fighting, falling back, holding…) |
_gc supply, convoy, groupname Supply North |
hands the group Supply North to the convoy autopilot, under the callsign supply |
These are also the markers a game master sends to steer a convoy.
Making the mission speak¶
The voice goes through SRS (DCS-SR-ExternalAudio.exe). VEAF reads its configuration from Saved Games\DCS\DCS-SimpleRadio-Standalone\SRS_for_scripting_config.lua, on the machine hosting the mission; without that file the call goes out as text only:
if not SERVER_CONFIG then SERVER_CONFIG = {} end
SERVER_CONFIG.SRS_DIRECTORY = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
SERVER_CONFIG.SRS_PORT = 5002
SERVER_CONFIG.SRS_EXECUTABLE = "DCS-SR-ExternalAudio.exe"
if not STTS then STTS = {} end
STTS.DIRECTORY = SERVER_CONFIG.SRS_DIRECTORY
STTS.SRS_PORT = SERVER_CONFIG.SRS_PORT
STTS.EXECUTABLE = SERVER_CONFIG.SRS_EXECUTABLE
SRS_DIRECTORY is the folder holding DCS-SR-ExternalAudio.exe (an ExternalAudio subfolder in recent SRS versions), SRS_PORT the SRS server's port.
The mission also needs os: a MissionScripting.lua that removes it, as DCS's own does, leaves the mission mute.
Who hears the call: it is sent for the convoy's coalition, but 243 and 121.5 MHz are guard frequencies, which both sides' pilots listen to. By the way SRS works, the enemy does not hear it only when the SRS server keeps the coalitions apart (coalition audio security) — not measured in game.
The shipped aliases¶
veafShortcuts ships ready-made shortcuts, and they are how most pilots use this module:
| Alias | What it does |
|---|---|
-ai_set |
_gc — attaches an autopilot to the nearest group; write its name after it |
-arty1, -arty2, -arty3 |
Spawns a battery and attaches its autopilot, named arty-1, arty-2, arty-3 |
-arty1_aim, -arty2_aim, -arty3_aim |
Ranging order to the matching battery |
-arty1_fire, -arty2_fire, -arty3_fire |
Fire-for-effect order to the matching battery |
Those firing aliases deliberately end on target with no value: you type the coordinates right
after, and they complete the order.
-arty1 # the battery appears and its autopilot starts
-arty1_aim 42 N 42 E # it ranges in on those coordinates
-arty1_fire # then fires in earnest, at the same target
mission.yaml configuration¶
The module is enabled and disabled like the others:
modules:
GROUNDAI: true # on by default; `false` removes the _gc marker and the convoy watch
Its one option is the list of Mission Editor groups to watch as convoys — _spawn convoy ones always are, with nothing to declare:
modules:
GROUNDAI:
enabled: true
convoys:
- Supply North
- Kutaisi Convoy
Known limits¶
- Two kinds of autopilot exist: artillery and the convoy. The module is built to host others
(
veafGroundAI.add/.remove/.gettake any named handler). - The convoy's watch does not see vegetation.
land.isVisibleonly accounts for terrain: the convoy may judge "in sight" an enemy that trees hide from DCS's AI. That is why its armed vehicles close in rather than halt: halted 1.9 km from an enemy "in sight", two Bradleys did not fire a round in two minutes (measured 2026-10-08). - Trees are no cover for the fall-back:
world.searchObjectsdoes not find them. Only terrain and towns hide the rally point. - Smoke does not blind DCS's AI (measured 2026-10-08): it marks, for the pilots. So the convoy lays no smoke screen.
- A living enemy the convoy cannot reach keeps it fighting: while one is left within its watch, it goes back for it rather than drive on.
_gc <callsign>, resumesends it on its way. - A vehicle split off or merged back comes back whole: DCS cannot recreate a unit with its damage. The watch almost always splits the convoy before the first hit.
- The 250-metre search radius is not configurable.
- Orders go through the F10 map only: this module has no radio menu.
- A correction has no automatic spotter: the pilot is the one who watches where the rounds land and calls the offset in. The module does not measure the miss itself.
See also¶
- veafShortcuts — the full alias list, including
-ai_setand the-arty*family - veafSecurity — what
KNOWN_PILOTmeans, and how an unlisted pilot still gets through - veafSpawn — spawning the battery this module will drive