Skip to content

VEAF Lua Modules - Complete API Reference

Version: generated for 6.36.0

Last Updated: November 2026

Project: VEAF Mission Creation Tools


Table of Contents

  1. Introduction
  2. Module Architecture
  3. Core Infrastructure
  4. veaf.lua - Core utilities and logger
  5. veafEventHandler.lua - Event management
  6. veafMarkers.lua - Map marker system
  7. veafCommands.lua - Central command dispatcher
  8. veafInterpreter.lua - Command parsing
  9. Unit & Group Management
  10. veafSpawnParser.lua - Spawn command text parser
  11. veafSpawn.lua - Dynamic spawning
  12. veafUnits.lua - Unit definitions
  13. veafAssets.lua - Asset tracking
  14. Mission Systems
  15. veafCombatMission.lua - Combat missions
  16. veafCasMission.lua - CAS missions
  17. Infrastructure & Services
  18. veafAirbases.lua - Airbase data
  19. veafCarrierOperations.lua - Carrier ops
  20. Communication & Control
  21. veafRadio.lua - Radio menus
  22. Support Systems
  23. veafWeather.lua - Weather system
  24. veafTime.lua - Time management
  25. Data & Database
  26. dcsUnits.lua - DCS unit database
  27. dcsDataExport.lua - Data export
  28. Appendix

Introduction

The VEAF (Virtual European Air Force) Lua modules provide a comprehensive framework for creating dynamic DCS World missions. This API reference documents all public functions, classes, and constants available to mission creators.

Key Features

  • 33+ Lua modules providing runtime functionality
  • Event-driven architecture using DCS World event system
  • Modular design allowing selective module usage
  • Extensive logging with configurable log levels
  • Security system for controlled access
  • Radio menu integration via F10 menu
  • Marker-based commands using map markers

Module Loading Order

Modules must be loaded in dependency order: 1. veaf.lua (core - must be first) 2. veafEventHandler.lua 3. veafMarkers.lua 4. Other modules (any order)

Conventions Used

Parameter Types:

  • string - Text string
  • number - Numeric value
  • boolean - true/false
  • table - Lua table/array
  • vec3 - 3D vector: {x=number, y=number, z=number}
  • function - Callback function
  • coalition - Coalition ID: 0=neutral, 1=red, 2=blue (coalition.side.RED is 1 — see the note below)

coalition.side is RED=1, BLUE=2

coalition.side = { NEUTRAL = 0, RED = 1, BLUE = 2 }

An inversion of these values is caught by nothing: code written from a wrong mapping compiles, runs, and quietly targets the other side.

Return Values:

  • Functions return nil on failure unless otherwise specified
  • Boolean returns indicate success/failure

Module Architecture

Standard Module Structure

All VEAF modules follow this pattern:

-- Module declaration
veafModuleName = veafModuleName or {}

-- Module metadata
veafModuleName.Id = "MODULE_ID"
veafModuleName.LogLevel = "info"  -- or "debug", "trace"

-- Logger initialization
veafModuleName.logger = veaf.loggers.new(veafModuleName.Id, veafModuleName.LogLevel)

-- Initialization function
function veafModuleName.initialize()
  veafModuleName.logger:info("Initializing module")
  -- Initialization code
end

-- Start function (if applicable)
function veafModuleName.start()
  veafModuleName.logger:info("Starting module")
  -- Start monitoring/services
end

Logging Levels

All modules use standardized logging:

Level Value Usage
error 1 Critical errors only
warning 2 Warnings and errors
info 3 Normal operations (default)
debug 4 Detailed debugging
trace 5 Very verbose tracing

Setting Log Levels:

veafModuleName.LogLevel = "debug"
veaf.loggers.setBaseLevel("info")  -- Global default


Core Infrastructure

veaf.lua

Module ID: VEAF

Purpose: Root library providing core utilities, constants, and logger system

Constants

veaf.BuildVersion = "6.7.x+<sha>"  -- build stamp (package version + git sha) injected at build time; "dev" when unbuilt
veaf.Development = false  -- Enable development features
veaf.HideNamesFromSpawnedGroups = true  -- hides the zone and the type in spawned group names; set per mission with `mission.hide_names_from_spawned_groups`
veaf.BaseLogLevel = 3  -- Default log level (info); acts as a cap for module log levels
veaf.DEFAULT_GROUND_SPEED_KPH = 30
veaf.DEFAULT_GROUND_SPEED_KTS = 16.2
veaf.DEFAULT_SPEED_KTS = 350

Localization (i18n) & pilot feedback

In-game pilot-facing messages are localized (FR/EN). The active language is veaf.config.language (set from mission.language, else the tools' resolved language at build time, whose final fallback is en); logs always stay in English.

veaf.t(key, ...)

Returns the localized string for key from veaf.i18nCatalog (populated by veafI18n.lua), with string.format interpolation. Fallback: requested language → French → the key itself (a missing entry never crashes).

trigger.action.outText(veaf.t("spawn.group_spawned", group.description, country), 5)
veaf.reportToPilot(message, duration, coalition)

Shows message in-game. With a coalition it uses outTextForCoalition; otherwise (or nil) it shows it to everyone (outText). Use it for command feedback addressed to the requester.

veaf.nearestMatch(word, candidates, maxDistance)

Returns the closest string in candidates within maxDistance Levenshtein edits (or nil). Used for the "did you mean …?" spawn-parameter hint.

veaf.getRequesterCoalition(event)

The coalition that issued a command (marker placer / interpreter unit), normalized to coalition.side.RED/.BLUE, or nil when unknown/all. Use it for pilot feedback — not for deciding the side of spawned units.

veaf.getOppositeCoalition(side)

The opposing coalition — the default side of units spawned from a marker (RED↔BLUE; neutral/all → RED). Pass an explicit side/country parameter to override.

JSON Functions

veaf.json.stringify(obj, as_key)

Convert Lua object to JSON string.

Parameters:

  • obj (any) - Lua object to serialize
  • as_key (boolean, optional) - Format as JSON key

Returns: string - JSON representation

Example:

local data = {name = "Strike", type = "mission"}
local json = veaf.json.stringify(data)
-- Result: '{"name":"Strike","type":"mission"}'

veaf.json.parse(str, pos, end_delim)

Parse JSON string to Lua object.

Parameters:

  • str (string) - JSON string
  • pos (number, optional) - Starting position (default: 1)
  • end_delim (string, optional) - End delimiter

Returns: table - Parsed Lua object

Example:

local json = '{"name":"Strike","type":"mission"}'
local data = veaf.json.parse(json)
-- Result: {name = "Strike", type = "mission"}

String Utilities

veaf.trim(s)

Remove leading and trailing whitespace.

Parameters:

  • s (string) - String to trim

Returns: string - Trimmed string

Example:

local trimmed = veaf.trim("  hello  ")
-- Result: "hello"

veaf.split(str, sep)

Split string by separator into array.

Parameters:

  • str (string) - String to split
  • sep (string) - Separator character/string

Returns: table - Array of substrings

Example:

local parts = veaf.split("red,blue,green", ",")
-- Result: {"red", "blue", "green"}

veaf.splitWithPattern(str, pat)

Split string using regex pattern.

Parameters:

  • str (string) - String to split
  • pat (string) - Lua pattern

Returns: table - Array of substrings

veaf.breakString(str, sep)

Break string around separator (returns 2 parts).

Parameters:

  • str (string) - String to break
  • sep (string) - Separator

Returns: string, string - Two parts (before and after separator)

Example:

local before, after = veaf.breakString("key=value", "=")
-- Result: before="key", after="value"

veaf.escapeRegex(stringToEscape)

Escape special regex characters.

Parameters:

  • stringToEscape (string) - String to escape

Returns: string - Escaped string

Table/Array Utilities

veaf.length(T)

Get table length (handles non-sequential keys).

Parameters:

  • T (table) - Table to measure

Returns: number - Number of elements

Example:

local t = {a=1, b=2, c=3}
local len = veaf.length(t)
-- Result: 3

veaf.arrayRemoveWhen(t, fnKeep)

Remove elements from array based on condition.

Parameters:

  • t (table) - Array to filter
  • fnKeep (function) - Keep function: function(element) return boolean end

Returns: table - Modified array

Example:

local numbers = {1, 2, 3, 4, 5}
veaf.arrayRemoveWhen(numbers, function(n) return n > 3 end)
-- Result: {1, 2, 3}

veaf.shuffle(tbl)

Randomly shuffle array elements in place.

Parameters:

  • tbl (table) - Array to shuffle

Returns: table - Shuffled array (same reference)

veaf.tableContains(table, element)

Check if table contains element.

Parameters:

  • table (table) - Table to search
  • element (any) - Element to find

Returns: boolean - True if found

veaf.randomlyChooseFrom(aTable, bias)

Choose random element from table with optional bias.

Parameters:

  • aTable (table) - Table to choose from
  • bias (number, optional) - Bias factor (default: 1.0)

Returns: any - Random element

Example:

local colors = {"red", "blue", "green"}
local color = veaf.randomlyChooseFrom(colors)

Vector & Coordinate Functions

veaf.vecToString(vec)

Convert 3D vector to human-readable string.

Parameters:

  • vec (vec3) - Vector {x, y, z}

Returns: string - Formatted string

Example:

local pos = {x=1000, y=50, z=2000}
local str = veaf.vecToString(pos)
-- Result: "x=1000, y=50, z=2000"

veaf.findPointInZone(spawnSpot, dispersion, isShip)

Find random spawn point within zone with dispersion.

Parameters:

  • spawnSpot (vec3) - Center position
  • dispersion (number) - Radius in meters
  • isShip (boolean, optional) - Find water location

Returns: vec3 - Random point within zone

veaf.placePointOnLand(vec3)

Place point on land surface (adjusts Y altitude).

Parameters:

  • vec3 (vec3) - Position to adjust

Returns: vec3 - Position on land surface

veaf.findSpawnPoint(vec3, radius, safeRadius)

Searches for an acceptable ground spawn point near a centre. Where placePointOnLand moves a point vertically, this one searches for one.

The search degrades in three bounded tiers:

  1. Every criterion, clearance from scenery included - through the Disposition DCS singleton, which returns points clear of buildings and forests.
  2. Every criterion except that clearance - validated random draws within the radius.
  3. Failure - returns nil; the caller reports it and aborts the spawn.

Parameters:

  • vec3 (vec3) - Centre of the search
  • radius (number) - Search radius in metres, used by the random tier
  • safeRadius (number, optional) - Required clearance (default veaf.DEFAULT_SPAWN_CLEARANCE)

Returns: vec3 placed on land, or nil when no acceptable point was found

Settings:

  • veaf.SPAWN_SEARCH_ATTEMPTS (default 10) - candidates examined per tier
  • veaf.DEFAULT_SPAWN_CLEARANCE (default 100) - requested clearance, in metres
  • veaf.doNotAvoidScenery (default false) - when true, skips tier 1

Note: Disposition is a native but undocumented DCS API, absent from dcs-world-schema. The call is guarded and pcall-wrapped: if the singleton is missing on this DCS version or map, the search falls through to tier 2 instead of failing.

veafUnits.settleGroup(units, honourDeclaredPosition)

Moves the whole group, as one rigid body, into a clearing wide enough to hold it. veaf.findSpawnPoint only places the group's centre; veafUnits.placeGroup then spreads the vehicles around that centre without looking at the scenery, so a battery standing in the open can still have half its pieces in the trees.

Every vehicle gets the same offset, so the distances between them do not change: the formation is preserved. A vehicle-by-vehicle nudge cannot work — a battery's natural spacing is 20 to 27 m, while the closest free point DCS can propose is 52 m away.

How it searches: it sweeps rings of growing radius around the group, closest first, and keeps the first offset where every vehicle stands on drivable terrain and passes the small scenery probe (Disposition.getSimpleZones asked about one point: 5 m free within 20 m). It never asks Disposition to propose a clearing: that query is not deterministic and returns nothing where a group most needs moving (measured 2026-09-26).

Parameters:

  • units - the unit list, as veafUnits.placeGroup filled it in
  • honourDeclaredPosition - when true, the caller states that it owns the placement and nothing moves. Same contract as VeafGroupSpawn:honouringDeclaredPosition(), and explicit for the same reason: a zero radius is this codebase's default, not a statement. Measured 2026-09-25 on GermanyCW-v6, 100 of the 118 spawn commands of one launch pass radius 0 - that is to say every battery this lot has to move.

Returns: the distance the group was moved by, 0 when it stayed put.

Never moves: a group holding an air unit, a naval unit or a naval static; a convoy; a caller that set honourDeclaredPosition; a mission that set veaf.doNotAvoidScenery to true; and Mission Editor content, which goes through VeafGroupSpawn:honouringDeclaredPosition() and never reaches here.

Settings:

  • veafUnits.SETTLE_MAX_TRANSLATION (default 300) - acceptable translation distance, in metres, and how far the sweep looks. Beyond it the group stays where it is.
  • veafUnits.SETTLE_SWEEP_STEP (default 20) - spacing between two rings of the sweep, and between two offsets on one ring, in metres.
  • veafUnits.SETTLE_SWEEP_PROBE_BUDGET (default 1000) - most probes spent on one group. It all runs in the spawn's frame, so this is the hitch a group with no way out costs on every activation (one probe ≈ 0.38 ms, measured 2026-09-26).
veaf.getLandHeight(vec3)

Get terrain height at coordinates.

Parameters:

  • vec3 (vec3) - Position

Returns: number - Terrain altitude in meters

veaf.headingBetweenPoints(point1, point2)

Calculate heading from point1 to point2.

Parameters:

  • point1 (vec3) - Starting point
  • point2 (vec3) - Destination point

Returns: number - Heading in degrees (0-360)

veaf.getBearingAndRangeFromTo(fromPoint, toPoint)

Calculate bearing and range between two points.

Parameters:

  • fromPoint (vec3) - Starting point
  • toPoint (vec3) - Destination point

Returns: number, number - Bearing (degrees), Range (meters)

Example:

local bearing, range = veaf.getBearingAndRangeFromTo(pos1, pos2)
veaf.logger:info("Target at %d° for %.0f meters", bearing, range)

veaf.computeLLFromString(value)

Parse latitude/longitude from string.

Parameters:

  • value (string) - Lat/Lon string (various formats supported)

Returns: table - {lat=number, lon=number} or nil

Supported Formats:

  • DMS: N 43°15'30" E 005°45'20"
  • Decimal: 43.258333, 5.755556
  • MGRS: (via conversion)
veaf.computeCoordinatesOffsetFromRoute(startingPoint, destinationPoint, distanceFromStartingPoint, offset)

Calculate position offset from a route.

Parameters:

  • startingPoint (vec3) - Route start
  • destinationPoint (vec3) - Route end
  • distanceFromStartingPoint (number) - Distance along route (meters)
  • offset (number) - Perpendicular offset (meters, positive = right)

Returns: vec3 - Offset position

Unit & Group Functions

veaf.addUnit(group, spawnSpot, dispersion, unitType, unitName, skill)

Add unit to group definition.

Parameters:

  • group (table) - Group definition table
  • spawnSpot (vec3) - Spawn position
  • dispersion (number) - Dispersion radius (meters)
  • unitType (string) - DCS unit type name
  • unitName (string) - Unit name
  • skill (string) - Skill level: "Average", "Good", "High", "Excellent", "Random"

Returns: table - Modified group table

veaf.getAveragePosition(group)

Get center position of group.

Parameters:

  • group (table or DCS Group) - Group object or table

Returns: vec3 - Average position

veaf.getAvgGroupPos(groupName)

Get average position of group by name.

Parameters:

  • groupName (string) - Group name

Returns: vec3 - Average position or nil

veaf.moveGroupAt(groupName, leadUnitName, heading, speed, timeInSeconds, endPosition, pMiddlePointDistance)

Move group in specific direction and speed.

Parameters:

  • groupName (string) - Group to move
  • leadUnitName (string) - Lead unit name
  • heading (number) - Direction in degrees
  • speed (number) - Speed in m/s
  • timeInSeconds (number) - Duration of movement
  • endPosition (vec3, optional) - Final position
  • pMiddlePointDistance (number, optional) - Intermediate waypoint distance

Returns: boolean - Success flag

veaf.moveGroupTo(groupName, pos, speed, altitude)

Move group to position.

Parameters:

  • groupName (string) - Group name
  • pos (vec3) - Destination
  • speed (number, optional) - Speed in m/s (default: 30 kph)
  • altitude (number, optional) - Altitude override

Returns: boolean - Success

veaf.readyForCombat(group, alarm, disperseTime)

Prepare ground group for combat.

Parameters:

  • group (DCS Group or string) - Group or group name
  • alarm (boolean, optional) - Alarm state (default: false)
  • disperseTime (number, optional) - Time to disperse in seconds

Returns: None

Description: Sets group to combat ready state, optionally disperses units.

veaf.getGroupsOfCoalition(coa)

Get all groups of coalition.

Parameters:

  • coa (coalition, optional) - Coalition filter (default: all)

Returns: table - Array of DCS Group objects

veaf.getUnitsOfCoalition(includeStatics, coa)

Get all units of coalition.

Parameters:

  • includeStatics (boolean) - Include static objects
  • coa (coalition, optional) - Coalition filter

Returns: table - Array of unit/static objects

veaf.findUnitsInCircle(center, radius, includeStatics, onlyTheseUnits)

Find units in circular area.

Parameters:

  • center (vec3) - Circle center
  • radius (number) - Radius in meters
  • includeStatics (boolean, optional) - Include statics
  • onlyTheseUnits (table, optional) - Filter to these units only

Returns: table - Array of units/statics

Example:

local targetPos = {x=1000, y=0, z=2000}
local enemyUnits = veaf.findUnitsInCircle(targetPos, 500, false)
veaf.logger:info("Found %d enemy units", #enemyUnits)

veaf.isUnitInZone(unitOrName, zoneOrName)

Check if unit is inside trigger zone.

Parameters:

  • unitOrName (DCS Unit or string) - Unit or unit name
  • zoneOrName (DCS Zone or string) - Zone or zone name

Returns: boolean - True if inside zone

veaf.isUnitAlive(unit)

Check if unit is alive.

Parameters:

  • unit (DCS Unit or string) - Unit or unit name

Returns: boolean - True if alive

veaf.getUnitLifeRelative(unit)

Get unit health as percentage.

Parameters:

  • unit (DCS Unit or string) - Unit or unit name

Returns: number - Health percentage (0-100)

veaf.fixUnitsTable(unitsOrNames)

Convert unit names to unit objects.

Parameters:

  • unitsOrNames (table) - Array of units or unit names

Returns: table - Array of unit objects

Route Generation

veaf.generateVehiclesRoute(startPoint, destination, onRoad, speed, groupName)

Generate vehicle movement route.

Parameters:

  • startPoint (vec3) - Starting position
  • destination (vec3) - Destination position
  • onRoad (boolean) - Use roads when possible
  • speed (number) - Speed in m/s
  • groupName (string, optional) - Group name for logging

Returns: table - Route table

Route Table Structure:

{
  [1] = {
    x = number,
    y = number,
    action = "On Road" or "Off Road",
    speed = number,
    type = "Turning Point"
  },
  -- ... more waypoints
}

veaf.PatrolWatchdog(groupName, patrolRoute, speed, firstPass)

Monitor patrol route and repeat.

Parameters:

  • groupName (string) - Group name
  • patrolRoute (table) - Route table
  • speed (number) - Speed in m/s
  • firstPass (boolean) - Is first iteration

Returns: None (schedules itself)

Information Functions

veaf.getTankerData(tankerGroupName)

Get tanker information.

Parameters:

  • tankerGroupName (string) - Tanker group name

Returns: table - Tanker data structure

Tanker Data Structure:

{
  name = "Texaco-1",
  type = "KC-135",
  TACANchannel = "61X",
  TACANfrequency = "1088 MHz",
  TACANmorse = "\u2013\u2022 \u2022\u2022\u2022\u2022 \u2013\u2022\u2022",
  RadioFrequency = "251.0 MHz",
  RadioModulation = "AM",
  callsign = "Texaco 1-1",
  position = vec3
}

veaf.getCarrierATCdata(carrierGroupName, carrierUnitName)

Get carrier ATC information.

Parameters:

  • carrierGroupName (string) - Carrier group name
  • carrierUnitName (string, optional) - Specific unit name

Returns: table - ATC data

ATC Data Structure:

{
  name = "CVN-73",
  callsign = "Mother",
  RadioFrequency = "127.5 MHz",
  RadioModulation = "AM",
  TACANchannel = "73X",
  TACANfrequency = "1205 MHz",
  TACANmorse = "\u2013\u2022\u2022\u2022 \u2022\u2022\u2022\u2013 \u2013\u2022\u2022",
  ICLS = "13",
  position = vec3,
  heading = number
}

veaf.getGroupData(groupIdent)

Get raw DCS group data.

Parameters:

  • groupIdent (string or number) - Group name or ID

Returns: table - DCS group data table

veafWeatherData.getWeatherString(vec3, dcsElementName, unitSystem, iSurfaceAltitudeMeters)

Generate a weather report string for a position. The unit system and LASTE inclusion are derived from the supplied DCS element (e.g. an A-10 enables LASTE automatically).

Parameters:

  • vec3 (vec3) - Position for report
  • dcsElementName (string, optional) - Name of a DCS element (unit/airbase) used to derive the unit system and LASTE
  • unitSystem (string, optional) - Unit system; defaults based on the element
  • iSurfaceAltitudeMeters (number, optional) - Surface altitude in metres

Returns: string - Weather report text

Example Output:

Weather at position:
QNH: 29.92 inHg (1013 hPa)
Temperature: 15°C (59°F)
Wind: 270° at 10 kts

Output Functions

veaf.outTextForUnit(unitName, message, duration, forAllGroup)

Display text message to unit.

Parameters:

  • unitName (string) - Target unit name
  • message (string) - Message text
  • duration (number, optional) - Display duration in seconds (default: 5)
  • forAllGroup (boolean, optional) - Show to all group members

Returns: None

Example:

veaf.outTextForUnit("Viper 1-1", "Target destroyed!", 10, true)

veaf.outTextForGroup(unitName, message, duration)

Display text to entire group.

Parameters:

  • unitName (string) - Any unit in group
  • message (string) - Message text
  • duration (number, optional) - Duration in seconds

Returns: None

Conversion Functions

veaf.convertMachSpeed(mach, altitude, temperature)

Convert Mach number to true airspeed.

Parameters:

  • mach (number) - Mach number
  • altitude (number) - Altitude in meters
  • temperature (number, optional) - Temperature offset in °C

Returns: number - True airspeed in knots

veaf.convertTrueAirSpeed(ktas, altitude, temperature)

Convert true airspeed to Mach.

Parameters:

  • ktas (number) - True airspeed in knots
  • altitude (number) - Altitude in meters
  • temperature (number, optional) - Temperature offset

Returns: number - Mach number

veaf.convertSpeeds(mach, kias, ktas, altitude, temperature, pressure)

Convert between speed formats.

Parameters:

  • mach (number, optional) - Mach number
  • kias (number, optional) - Indicated airspeed (knots)
  • ktas (number, optional) - True airspeed (knots)
  • altitude (number) - Altitude in meters
  • temperature (number, optional) - Temperature offset
  • pressure (number, optional) - Pressure in hPa

Returns: table - {mach, kias, ktas}

Example:

local speeds = veaf.convertSpeeds(0.9, nil, nil, 10000)
-- Result: {mach=0.9, kias=calculated, ktas=calculated}

veaf.getMagneticDeclination()

Get magnetic declination for current theater.

Returns: number - Declination in degrees

veaf.getWind(point)

Get wind at position.

Parameters:

  • point (vec3) - Position

Returns: table - {direction=number, strength=number}

Math & Utility Functions

veaf.round(num, numDecimalPlaces)

Round number to decimal places.

Parameters:

  • num (number) - Number to round
  • numDecimalPlaces (number, optional) - Decimal places (default: 0)

Returns: number - Rounded number

veaf.getRandomizableNumeric(val)

Parse randomizable numeric value.

Parameters:

  • val (string or number) - Value like "2-6" or "5"

Returns: number - Random value in range

Example:

local size = veaf.getRandomizableNumeric("3-7")
-- Result: Random number between 3 and 7

veaf.invertHeading(heading)

Get opposite heading.

Parameters:

  • heading (number) - Heading in degrees

Returns: number - Opposite heading (0-360)

veaf.laserCodeToDigit(code)

Convert laser code to digit.

Parameters:

  • code (number) - Laser code (e.g., 1688)

Returns: number - Digit representation

Country & Coalition Functions

veaf.getCountryId(countryName)

Get DCS country ID from name.

Parameters:

  • countryName (string) - Country name (e.g., "USA", "Russia")

Returns: number - Country ID or nil

veaf.getCountryName(countryId)

Get country name from ID.

Parameters:

  • countryId (number) - DCS country ID

Returns: string - Country name

veaf.getCountryForCoalition(coalition)

Get default country for coalition.

Parameters:

  • coalition (coalition) - Coalition ID

Returns: number - Country ID

Default Mapping:

  • Blue → USA (2)
  • Red → Russia (0)
veaf.getCoalitionForCountry(countryName, asNumber)

Get coalition for country.

Parameters:

  • countryName (string) - Country name
  • asNumber (boolean, optional) - Return as number instead of coalition object

Returns: coalition or number - Coalition

veaf.getAirbaseForCoalition(airbase_name, coa)

Get airbase object for coalition.

Parameters:

  • airbase_name (string) - Airbase name
  • coa (coalition) - Coalition

Returns: DCS Airbase - Airbase object or nil

Airbase Functions

veaf.findDcsAirbase(name)

Find DCS airbase by name (case-insensitive).

Parameters:

  • name (string) - Airbase name

Returns: DCS Airbase - Airbase object or nil

veaf.silenceAtcOnAllAirbases()

Disable ATC on all airbases.

Returns: None

Description: Useful for immersion or to prevent ATC conflicts.

veaf.loadAirbasesLife0()

Load airbase initial health data.

Returns: None

Description: Must be called before using veaf.getAirbaseLife().

veaf.getAirbaseLife(airbase_name, percentage, loading)

Get airbase health/damage.

Parameters:

  • airbase_name (string) - Airbase name
  • percentage (boolean, optional) - Return as percentage
  • loading (boolean, optional) - Loading initial data

Returns: number - Health value (0-1 or 0-100 if percentage)

veaf.getPolygonFromUnits(unitNames)

Create polygon from unit positions.

Parameters:

  • unitNames (table) - Array of unit names

Returns: table - Array of vec3 positions

Trigger Zone Functions

veaf.getTriggerZone(zoneName)

Get trigger zone by name.

Parameters:

  • zoneName (string) - Zone name

Returns: DCS Zone - Zone object or nil

veaf.getZoneProperty(zoneName, key)

Reads a trigger-zone property, as typed by the mission maker in the editor.

DCS stores these as an array of pairs { key = "…", value = "…" }, never a map, and every value is a string. These three accessors replace the linear scan and the tonumber every caller would otherwise write.

Parameters:

  • zoneName (string) - Zone name
  • key (string) - Property name

Returns: string - or nil when the zone, its properties or the key are missing

veaf.getZonePropertyBoolean(zoneName, key, default)

Reads a property as a boolean. Accepts true/false in any case; anything else is a failed read and yields default - so a typo cannot silently read as false.

Parameters:

  • zoneName (string) - Zone name
  • key (string) - Property name
  • default (boolean) - Value returned when absent or unparseable

Returns: boolean

veaf.getZonePropertyNumber(zoneName, key, default, min, max)

Reads a property as a number, clamped into an optional range. Clamps rather than rejects: a mission maker who types an absurd value gets the bound, not a dead module.

Parameters:

  • zoneName (string) - Zone name
  • key (string) - Property name
  • default (number) - Value returned when absent or not a number
  • min (number, optional) - Lower bound
  • max (number, optional) - Upper bound

Returns: number

Mission Control Functions

veaf.endMissionAt(endTimeHour, endTimeMinute, checkIntervalInSeconds, checkMessage, ...)

Schedule mission end at specific time.

Parameters:

  • endTimeHour (number) - Hour (0-23)
  • endTimeMinute (number) - Minute (0-59)
  • checkIntervalInSeconds (number) - Check frequency
  • checkMessage (string, optional) - Message to display
  • Additional parameters for message formatting

Returns: None

Example:

-- End mission at 14:30 (2:30 PM)
veaf.endMissionAt(14, 30, 60, "Mission ends at %s")

veaf.getDcsTypeName(dcsElementName)

Get DCS type name from element name.

Parameters:

  • dcsElementName (string) - DCS element name

Returns: string - Type name

Serialization Functions

veaf.p(o, level, skip, includeMeta, dontRecurse)

Pretty-print/serialize object.

Parameters:

  • o (any) - Object to serialize
  • level (number, optional) - Indentation level
  • skip (table, optional) - Keys to skip
  • includeMeta (boolean, optional) - Include metatables
  • dontRecurse (table, optional) - Objects not to recurse

Returns: string - Serialized representation

Example:

local data = {name = "Strike", units = {1, 2, 3}}
local str = veaf.p(data)
print(str)
-- Output:
-- {
--   name = "Strike",
--   units = {
--     [1] = 1,
--     [2] = 2,
--     [3] = 3
--   }
-- }

veaf.serialize(name, value, level)

Serialize value to Lua code string.

Parameters:

  • name (string) - Variable name
  • value (any) - Value to serialize
  • level (number, optional) - Indentation level

Returns: string - Lua code string

veaf.exportAsJson(data, name, jsonify, filename, export_path)

Export data to JSON file.

Parameters:

  • data (any) - Data to export
  • name (string) - Variable name
  • jsonify (boolean) - Convert to JSON (vs Lua)
  • filename (string, optional) - Output filename
  • export_path (string, optional) - Export directory path

Returns: boolean - Success flag

Example:

local missions = {
  {name = "CAP Alpha", type = "air"},
  {name = "Strike Bravo", type = "ground"}
}
veaf.exportAsJson(missions, "missions", true, "missions.json")

Logger Class

The veaf.Logger class provides structured logging with levels.

Creating Loggers
-- Global loggers
veaf.loggers.setBaseLevel("info")  -- Set default level
local logger = veaf.loggers.new("MYMODULE", "debug")  -- Create logger
local existingLogger = veaf.loggers.get("MYMODULE")  -- Get existing

-- Instance loggers
local myLogger = veaf.Logger:new("MYMODULE", "info")
Logger Methods

logger:setName(value)

Set logger name.

logger:setLevel(value, force)

Set logging level.

Parameters:

  • value (string or number) - Level: "error", "warning", "info", "debug", "trace"
  • force (boolean, optional) - Force override base level

logger:error(text, ...)

Log error message (level 1).

Parameters:

  • text (string) - Message with format placeholders
  • ... - Format arguments

Example:

logger:error("Failed to spawn %s at position %s", groupName, veaf.vecToString(pos))

logger:warn(text, ...)

Log warning message (level 2).

logger:info(text, ...)

Log info message (level 3).

logger:debug(text, ...)

Log debug message (level 4).

logger:trace(text, ...)

Log trace message (level 5).

logger:wouldLogDebug()

Check if debug logging enabled.

Returns: boolean

logger:wouldLogTrace()

Check if trace logging enabled.

Returns: boolean

Usage:

if logger:wouldLogTrace() then
  -- Expensive trace logging
  logger:trace("Complex data: %s", veaf.p(largeTable))
end

Map Marker Logging

logger:marker(id, header, message, position, markersTable, radius, fillColor)

Add map marker for debugging.

Parameters:

  • id (number) - Marker ID
  • header (string) - Marker header text
  • message (string) - Marker message
  • position (vec3) - Marker position
  • markersTable (table, optional) - Track markers in table
  • radius (number, optional) - Circle radius
  • fillColor (table, optional) - Fill color {r, g, b, a}

Returns: None

logger:markerArrow(id, header, message, positionStart, positionEnd, markersTable, lineType, fillColor)

Add arrow marker.

Parameters:

  • id (number) - Marker ID
  • header (string) - Header text
  • message (string) - Message
  • positionStart (vec3) - Arrow start
  • positionEnd (vec3) - Arrow end
  • markersTable (table, optional) - Track markers
  • lineType (number, optional) - Line type
  • fillColor (table, optional) - Color

logger:markerQuad(id, header, message, points, markersTable, lineType, fillColor)

Add quadrilateral marker.

Parameters:

  • id (number) - Marker ID
  • header (string) - Header
  • message (string) - Message
  • points (table) - Array of 4 vec3 points
  • markersTable (table, optional) - Track markers
  • lineType (number, optional) - Line type
  • fillColor (table, optional) - Color

veafEventHandler.lua

Module ID: EVENTS

Purpose: DCS World event handling and callback management

Constants

Event Types
veafEventHandler.EVENTS = {
  [0] = "S_EVENT_INVALID",
  [1] = "S_EVENT_SHOT",
  [2] = "S_EVENT_HIT",
  [3] = "S_EVENT_TAKEOFF",
  [4] = "S_EVENT_LAND",
  [5] = "S_EVENT_CRASH",
  [6] = "S_EVENT_EJECTION",
  [7] = "S_EVENT_REFUELING",
  [8] = "S_EVENT_DEAD",
  [9] = "S_EVENT_PILOT_DEAD",
  [10] = "S_EVENT_BASE_CAPTURED",
  [11] = "S_EVENT_MISSION_START",
  [12] = "S_EVENT_MISSION_END",
  [13] = "S_EVENT_TOOK_CONTROL",
  [14] = "S_EVENT_REFUELING_STOP",
  [15] = "S_EVENT_BIRTH",
  [16] = "S_EVENT_HUMAN_FAILURE",
  [17] = "S_EVENT_DETAILED_FAILURE",
  [18] = "S_EVENT_ENGINE_STARTUP",
  [19] = "S_EVENT_ENGINE_SHUTDOWN",
  [20] = "S_EVENT_PLAYER_ENTER_UNIT",
  [21] = "S_EVENT_PLAYER_LEAVE_UNIT",
  [22] = "S_EVENT_PLAYER_COMMENT",
  [23] = "S_EVENT_SHOOTING_START",
  [24] = "S_EVENT_SHOOTING_END",
  [25] = "S_EVENT_MARK_ADDED",
  [26] = "S_EVENT_MARK_CHANGE",
  [27] = "S_EVENT_MARK_REMOVED",
  [28] = "S_EVENT_KILL",
  [29] = "S_EVENT_SCORE",
  [30] = "S_EVENT_UNIT_LOST",
  [31] = "S_EVENT_LANDING_AFTER_EJECTION",
  [32] = "S_EVENT_PARATROOPER_LENDING",
  [33] = "S_EVENT_DISCARD_CHAIR_AFTER_EJECTION",
  [34] = "S_EVENT_WEAPON_ADD",
  [35] = "S_EVENT_TRIGGER_ZONE",
  -- ... up to event 61
}
Callback Delay
veafEventHandler.CALLBACK_DELAY = 0.5  -- seconds

Functions

veafEventHandler.addCallback(name, events, callback)

Register event callback function.

Parameters:

  • name (string) - Unique callback name
  • events (table or nil) - Array of event IDs/names, or nil for all events
  • callback (function) - Callback function

Callback Signature:

function callback(transformedEvent)
  -- transformedEvent is enhanced event table
end

Returns: boolean - True if registered successfully

Example:

-- Listen to all events
veafEventHandler.addCallback("myHandler", nil, function(event)
  veaf.logger:info("Event: %s", event.type.name)
end)

-- Listen to specific events
veafEventHandler.addCallback("birthHandler",
  {"S_EVENT_BIRTH", "S_EVENT_PLAYER_ENTER_UNIT"},
  function(event)
    if event.initiator then
      veaf.logger:info("Unit spawned: %s", event.initiator.unitName)
    end
  end
)

-- Listen by event ID
veafEventHandler.addCallback("shotHandler", {1, 23}, function(event)
  -- Handle S_EVENT_SHOT and S_EVENT_SHOOTING_START
end)

veafEventHandler.completeUnit(unit)

Get complete unit information from DCS unit.

Parameters:

  • unit (DCS Unit) - Unit object

Returns: table - Unit info table

Unit Info Structure:

{
  unitName = "Viper 1-1",
  unitCallsign = "Viper11",
  unitType = "F-16C_50",
  unitGroupName = "Viper Flight",
  unitGroupId = 123,
  unitCoalition = coalition.side.BLUE,
  unitCategory = Unit.Category.AIRPLANE,
  unitPilotName = "Player Name",  -- if human
  unitPilotUcid = "abc123...",    -- if human with SRS
  unitLifePercent = 100.0
}

veafEventHandler.completeUnitFromName(unitName)

Get unit information from unit name.

Parameters:

  • unitName (string) - Unit name

Returns: table - Unit info table (same as completeUnit)

Example:

local unitInfo = veafEventHandler.completeUnitFromName("Viper 1-1")
if unitInfo then
  veaf.logger:info("Unit %s is at %.0f%% health",
    unitInfo.unitName, unitInfo.unitLifePercent)
end

veafEventHandler.checkEventKnown(eventNameOrId, warnOnly)

Validate event is recognized by DCS.

Parameters:

  • eventNameOrId (string or number) - Event name or ID
  • warnOnly (boolean, optional) - Only warn, don't error

Returns: boolean - True if event is known

veafEventHandler.setEventEnabled(eventNameOrId, enabled)

Enable or disable event processing.

Parameters:

  • eventNameOrId (string or number) - Event to control
  • enabled (boolean) - Enable flag

Returns: None

Example:

-- Disable shooting events for performance
veafEventHandler.setEventEnabled("S_EVENT_SHOOTING_START", false)
veafEventHandler.setEventEnabled("S_EVENT_SHOOTING_END", false)

veafEventHandler.isEventEnabled(eventNameOrId)

Check if event processing is enabled.

Parameters:

  • eventNameOrId (string or number) - Event to check

Returns: boolean - True if enabled

veafEventHandler.isEventDelayedCallback(eventNameOrId)

Check if event uses delayed callback.

Parameters:

  • eventNameOrId (string or number) - Event to check

Returns: boolean - True if delayed

Description: Some events like BIRTH need delayed callbacks to allow DCS to fully initialize objects.

veafEventHandler.initialize()

Initialize event handler system.

Returns: None

Description: Called automatically by VEAF initialization. Registers DCS world event handler.

Transformed Event Structure

Events passed to callbacks are enhanced with additional fields:

{
  -- Original DCS event fields
  id = number,                    -- DCS event ID
  time = number,                  -- Mission time
  initiator = DCS_Unit,           -- Unit that triggered event
  target = DCS_Unit,              -- Target unit (if applicable)
  weapon = DCS_Weapon,            -- Weapon object (if applicable)
  place = DCS_Airbase,            -- Airbase (for takeoff/land)

  -- VEAF enhancements
  type = {                        -- Event type info
    id = number,
    name = "S_EVENT_XXX",
    definition = event_definition
  },
  idx = number,                   -- Event index
  coordinates = vec3,             -- Event position
  text = string,                  -- Marker text (for marker events)
  coalition = coalition,          -- Coalition ID
  groupId = number,               -- Group ID

  -- Enhanced unit info (if initiator exists)
  initiator = {
    unitName = string,
    unitCallsign = string,
    unitType = string,
    unitGroupName = string,
    unitGroupId = number,
    unitCoalition = coalition,
    unitCategory = category,
    unitPilotName = string,       -- if human
    unitPilotUcid = string,       -- if human
    unitLifePercent = number
  },

  -- Enhanced target info (if target exists)
  target = {
    -- same structure as initiator
  },

  -- Weapon info (if weapon fired/hit)
  weaponName = string,            -- Weapon type name

  -- Marker event fields
  comment = string                -- Marker comment text
}

Event Handling Best Practices

Performance:

  • Disable unused events to reduce overhead
  • Use delayed callbacks for expensive operations
  • Filter events by type when registering callbacks

Event Timing:

  • BIRTH events fire before units fully initialized
  • Use delayed callbacks for BIRTH if accessing unit properties
  • PLAYER_ENTER_UNIT fires after player fully loaded

Example: Complete Event Handler:

-- Track player kills
local playerKills = {}

veafEventHandler.addCallback("killTracker", {"S_EVENT_KILL"}, function(event)
  if event.initiator and event.initiator.unitPilotName then
    -- Human player got a kill
    local playerName = event.initiator.unitPilotName
    playerKills[playerName] = (playerKills[playerName] or 0) + 1

    local targetName = "unknown"
    if event.target and event.target.unitName then
      targetName = event.target.unitName
    end

    veaf.outTextForUnit(event.initiator.unitName,
      string.format("Kill confirmed! Total: %d", playerKills[playerName]),
      10, false)

    veaf.logger:info("%s killed %s (total kills: %d)",
      playerName, targetName, playerKills[playerName])
  end
end)


veafMarkers.lua

Module ID: MARKERS

Purpose: Listen to map marker events and execute handlers

Constants

veafMarkers.MarkerAdd = 1       -- Marker added event
veafMarkers.MarkerChange = 2    -- Marker changed event
veafMarkers.MarkerRemove = 3    -- Marker removed event
veafMarkers.DCSbugfixed = true  -- DCS marker bug status

Functions

veafMarkers.registerEventHandler(eventType, eventHandler)

Register handler for marker events.

Parameters:

  • eventType (number) - Event type: MarkerAdd, MarkerChange, or MarkerRemove
  • eventHandler (function) - Handler function

Handler Signature:

function eventHandler(vec3_position, event)
  -- vec3_position: marker position
  -- event: DCS event table
end

Returns: number - Handler ID for unregistering

Example:

-- Listen for marker additions
local handlerId = veafMarkers.registerEventHandler(
  veafMarkers.MarkerAdd,
  function(pos, event)
    local text = event.text or ""
    if text:match("^_spawn") then
      -- Handle spawn command
      veaf.logger:info("Spawn marker at %s", veaf.vecToString(pos))
    end
  end
)

veafMarkers.unregisterEventHandler(id)

Remove marker event handler.

Parameters:

  • id (number) - Handler ID from registerEventHandler

Returns: boolean - True if unregistered successfully

Example:

local handlerId = veafMarkers.registerEventHandler(veafMarkers.MarkerAdd, myHandler)
-- Later...
veafMarkers.unregisterEventHandler(handlerId)

Marker Event Structure

Marker events received by handlers contain:

{
  id = number,              -- Marker ID
  time = number,            -- Mission time
  initiator = DCS_Unit,     -- Unit that created marker (if applicable)
  coalition = coalition,    -- Coalition (-1 for all, 0=neutral, 1=red, 2=blue)
  groupID = number,         -- Group ID
  text = string,            -- Marker text
  pos = vec3                -- Marker position
}

Usage Patterns

Command Pattern:

Modules register a handler with veafCommands which routes all F10 marker commands centrally:

-- In a module's initialize() function:
veafCommands.registerCommandHandler(function(pos, event, bypass, fromMarker, groups, route)
  local text = event.text or ""
  if not text:lower():match("^_mycommand") then
    return false  -- not our command
  end
  -- handle the command...
  return true   -- consumed
end, veafCommands.PRIORITY_SPAWN)

All handlers are called in priority order until one returns true. The central dispatcher (veafCommands.dispatchMarker) handles the mark removal automatically.

Security Pattern:

Check coalition before executing:

veafMarkers.registerEventHandler(veafMarkers.MarkerAdd, function(pos, event)
  -- Only allow blue coalition markers
  if event.coalition == coalition.side.BLUE then
    processCommand(pos, event.text)
  else
    veaf.logger:warn("Unauthorized marker from coalition %d", event.coalition)
  end
end)

Cleanup Pattern:

Remove markers after processing:

veafMarkers.registerEventHandler(veafMarkers.MarkerChange, function(pos, event)
  if processMarkerCommand(pos, event.text) then
    -- Remove marker after successful processing
    trigger.action.removeMark(event.id)
  end
end)


veafCommands.lua

Module ID: COMMANDS

Init order: 15 (after veafMarkers, before all command modules)

Purpose: Central registry and dispatcher for all text commands (F10 markers and interpreter)

Constants

veafCommands.PRIORITY_SHORTCUTS    = 10
veafCommands.PRIORITY_SPAWN        = 20
veafCommands.PRIORITY_NAMEDPOINTS  = 30
veafCommands.PRIORITY_CASMISSION   = 40
veafCommands.PRIORITY_SECURITY     = 50
veafCommands.PRIORITY_MOVE         = 60
veafCommands.PRIORITY_RADIO        = 70
veafCommands.PRIORITY_REMOTE       = 80

Functions

veafCommands.registerCommandHandler(fn, priority)

Register a command handler function. Handlers are called in ascending priority order.

Parameters:

  • fn (function) - Handler with signature (pos, event, bypass, fromMarker, groups, route) → boolean
  • priority (number) - Execution order (lower = earlier); use the PRIORITY_* constants
veafCommands.execute(pos, text, coalition, groups, route)

Execute a command from the interpreter path (unit names). The coalition is used as-is.

Parameters:

  • pos (vec3) - Execution position
  • text (string) - Command text
  • coalition (number) - Coalition number
  • groups (table, optional) - Table to receive spawned group names
  • route (table, optional) - Route definition

Returns: boolean — true if a handler consumed the command

veafCommands.dispatchMarker(eventPos, event)

Handle a marker change event. Inverts coalition (marker events report the placer's side, not the target's), calls all registered handlers in priority order, and removes the mark on success.

Parameters:

  • eventPos (vec3) - Marker position
  • event (table) - Marker event object

veafInterpreter.lua

Module ID: INTERPRETER

Purpose: Interpret and execute commands from unit names and markers

Constants

veafInterpreter.Starter = "#veafInterpreter[\""  -- Unit name command prefix
veafInterpreter.Trailer = "\"]"                   -- Unit name command suffix
veafInterpreter.DelayForStartup = 1              -- Startup delay (seconds)

Functions

veafInterpreter.interpret(text)

Extract command from text string.

Parameters:

  • text (string) - Text containing command (unit name or marker text)

Returns: string - Extracted command or nil

Example:

local unitName = "#veafInterpreter[\"_spawn, name F-16C, group 2\"]"
local command = veafInterpreter.interpret(unitName)
-- Result: "_spawn, name F-16C, group 2"

veafInterpreter.execute(command, position, coalition, route, spawnedGroups)

Execute VEAF command. Delegates to veafCommands.execute() — all registered handlers are tried in priority order.

Parameters:

  • command (string) - Command string
  • position (vec3) - Command execution position
  • coalition (coalition, optional) - Coalition executing command
  • route (table, optional) - Route definition for spawned groups
  • spawnedGroups (table, optional) - Table to receive spawned group names

Returns: boolean - True if command executed successfully

Note: Command routing is handled by veafCommands. Modules register themselves via veafCommands.registerCommandHandler().

Example:

local pos = {x=1000, y=50, z=2000}
local success = veafInterpreter.execute("_spawn, name F-16C, group 2", pos, coalition.side.BLUE)
if success then
  veaf.logger:info("Command executed successfully")
end

veafInterpreter.executeCommandOnUnit(unitName, command)

Execute command from unit's position.

Parameters:

  • unitName (string) - Unit or static name
  • command (string) - Command to execute

Returns: None

Description:

  • Finds unit or static object by name
  • Executes command at unit's position
  • Destroys unit/static after successful execution
  • Useful for pre-placed trigger units

Example:

-- In mission editor, create unit named: "#veafInterpreter[\"_spawn, name SA-6\"]"
-- Or execute via script:
veafInterpreter.executeCommandOnUnit("TriggerUnit1", "_spawn, name SA-6")

veafInterpreter.initialize()

Initialize interpreter module.

Returns: None

Description:

  • Called automatically during VEAF initialization
  • Scans for units with interpreter commands in names
  • Executes commands after delay

Command Execution Flow

1. Command received (unit name or marker)
   ↓
2. veafInterpreter.interpret() extracts command
   ↓
3. Check veafShortcuts for shorthand
   ↓
4. Try module-specific handlers in order:
   - veafSpawn (spawn commands)
   - veafNamedPoints (named locations)
   - veafCasMission (CAS missions)
   - veafSecurity (security commands)
   - veafMove (movement)
   - veafRadio (radio/comms)
   - veafRemote (remote API)
   ↓
5. Return success/failure

Unit Name Command Pattern

Mission Editor Usage: 1. Create unit (any type, even static) 2. Name unit: #veafInterpreter["COMMAND HERE"] 3. Unit will execute command on mission start and self-destruct

Example Use Cases:

-- Spawn CAP on mission start
Unit name: #veafInterpreter["_spawn, name CAP-2, alt 25000, hdg 090, speed 450"]

-- Create CAS target area
Unit name: #veafInterpreter["_cas, size 5, defense 3, armor 2"]

-- Spawn convoy on road
Unit name: #veafInterpreter["_spawn, convoy, name convoy1, dest marker1, speed 50"]


Unit & Group Management

veafSpawnParser.lua

Purpose: Parse spawn command text into options tables. Extracted sub-module of veafSpawn.

Functions

veafSpawn.markTextAnalysis(text)

Parse marker text for spawn parameters. Defined in veafSpawnParser.lua, available on the veafSpawn table.

Parameters:

  • text (string) - Marker text to parse

Returns: table — options table with parsed key/value pairs

veafSpawn.convertLaserToFreq(laser)

Convert a laser code to a TACAN/radio frequency string.

Parameters:

  • laser (number) - Laser code (1111–1788)

Returns: string — frequency label, or nil if not found


veafSpawn.lua

Module ID: SPAWN

Purpose: Dynamic spawning system for units, groups, convoys, and effects

Constants

Keyphrases
veafSpawn.SpawnKeyphrase = "_spawn"
veafSpawn.DestroyKeyphrase = "_destroy"
veafSpawn.TeleportKeyphrase = "_teleport"
veafSpawn.DrawingKeyphrase = "_drawing"
veafSpawn.MissionMasterKeyphrase = "_mm"
Configuration
veafSpawn.IlluminationFlareAglAltitude = 1000  -- meters
veafSpawn.LogisticUnitType = "FARP Ammo Dump Coating"
veafSpawn.CAP_WATCHDOG_DELAY = 10  -- seconds
veafSpawn.AFAC.maximumAmount = 8   -- max simultaneous AFACs

Main Functions

veafSpawn.executeCommand(eventPos, eventText, coalition, markId, bypassSecurity, spawnedGroups, repeatCount, repeatDelay, route, allowStartDelay, requesterCoalition)

Execute spawn command from marker or script.

Parameters:

  • eventPos (vec3) - Spawn position
  • eventText (string) - Command text
  • coalition (coalition, optional) - Coalition
  • markId (number, optional) - Marker ID to remove
  • bypassSecurity (boolean, optional) - Skip security check
  • spawnedGroups (table, optional) - Receive spawned group names
  • repeatCount (number, optional) - Number of repetitions
  • repeatDelay (number, optional) - Delay between spawns (seconds)
  • route (table, optional) - Route for spawned groups
  • allowStartDelay (boolean, optional) - Allow delayed start
  • requesterCoalition (coalition, optional) - Requester coalition

Returns: boolean - Success flag

Example:

local pos = {x=1000, y=0, z=2000}
veafSpawn.executeCommand(pos, "_spawn, name F-16C, group 2, hdg 270", coalition.side.BLUE)

veafSpawn.markTextAnalysis(text)

Parse marker text for spawn parameters.

Parameters:

  • text (string) - Marker text

Returns: table - Parsed options

Returned Table Fields:

{
  name = string,           -- Unit/group name
  unitName = string,       -- Specific unit name
  groupName = string,      -- Override group name
  alias = string,          -- Name alias
  group = number,          -- Group count
  country = string,        -- Country name
  alt = number,            -- Altitude (feet)
  altitude = number,       -- Altitude (feet)
  hdg = number,            -- Heading (degrees)
  heading = number,        -- Heading (degrees)
  speed = number,          -- Speed (knots)
  dist = number,           -- Distance
  spacing = number,        -- Unit spacing (meters)
  side = coalition,        -- Coalition
  defense = number,        -- Defense level (0-5)
  armor = number,          -- Armor level (0-5)
  size = number,           -- Size (0-5)
  shells = number,         -- Shell count
  power = number,          -- Explosion power
  radius = number,         -- Dispersion radius
  color = string,          -- Smoke color
  smoke = boolean,         -- Add smoke
  type = string,           -- Type specification
  skill = string,          -- Skill level
  password = string,       -- Security password
  silent = boolean,        -- Suppress messages

  -- Specific spawn types
  convoy = boolean,
  dest = vec3,             -- Destination
  patrol = boolean,
  offroad = boolean,

  -- Air units
  cap = boolean,           -- CAP mission
  capRadius = number,      -- CAP radius
  afac = boolean,          -- AFAC unit
  immortal = boolean,      -- Invulnerable

  -- Effects
  bomb = boolean,
  smoke = boolean,
  flare = boolean,
  illumination = boolean,

  -- FARP/FOB
  farp = boolean,
  fob = boolean,
  farptype = string,
  fobtype = string,

  -- Advanced
  code = number,           -- Laser/TACAN code
  freq = number,           -- Frequency
  mod = string,            -- Modulation
  role = string,           -- Unit role
  static = boolean,        -- Spawn as static
  hidden = boolean         -- Hide from MFD
}

Unit Spawning Functions

veafSpawn.spawnUnit(spawnPosition, radius, name, czName, country, alt, hdg, unitName, role, static, code, freq, mod, silent, hiddenOnMFD)

Spawn single unit.

Parameters:

  • spawnPosition (vec3) - Spawn position
  • radius (number) - Dispersion radius (meters)
  • name (string) - Unit type name (DCS type or alias)
  • czName (string, optional) - Combat zone name
  • country (number, optional) - Country ID
  • alt (number, optional) - Altitude (feet)
  • hdg (number, optional) - Heading (degrees)
  • unitName (string, optional) - Override unit name
  • role (string, optional) - Unit role
  • static (boolean, optional) - Spawn as static object
  • code (number, optional) - Laser/TACAN code
  • freq (number, optional) - Radio frequency
  • mod (string, optional) - Radio modulation
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - Spawned group info

Example:

-- Spawn F-16C at position
local pos = {x=1000, y=0, z=2000}
veafSpawn.spawnUnit(pos, 50, "F-16C", nil, nil, 5000, 270)

-- Spawn JTAC with laser code
veafSpawn.spawnUnit(pos, 0, "JTAC", nil, nil, nil, nil, "JTAC-1", "forward_observer", false, 1688)

-- Spawn tanker with TACAN
veafSpawn.spawnUnit(pos, 100, "KC-135", nil, nil, 25000, 270, "Texaco", nil, false, 61, 251.0, "AM")

veafSpawn.spawnGroup(spawnSpot, radius, name, czName, country, alt, hdg, spacing, groupName, silent, hasDest, hiddenOnMFD)

Spawn predefined group.

Parameters:

  • spawnSpot (vec3) - Spawn position
  • radius (number) - Dispersion radius
  • name (string) - Group template name
  • czName (string, optional) - Combat zone
  • country (number, optional) - Country
  • alt (number, optional) - Altitude
  • hdg (number, optional) - Heading
  • spacing (number, optional) - Unit spacing
  • groupName (string, optional) - Override group name
  • silent (boolean, optional) - Suppress messages
  • hasDest (vec3, optional) - Destination for movement
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - Group info

Example:

-- Spawn armor platoon from template
veafSpawn.spawnGroup(pos, 100, "Soviet Armor Platoon", nil, nil, nil, 180, 50)

Ground Force Spawning

veafSpawn.spawnInfantryGroup(spawnSpot, radius, czName, country, side, heading, spacing, defense, armor, size, silent, hiddenOnMFD)

Spawn infantry group with parameters.

Parameters:

  • spawnSpot (vec3) - Spawn position
  • radius (number) - Dispersion radius
  • czName (string, optional) - Combat zone
  • country (number, optional) - Country
  • side (coalition) - Coalition
  • heading (number, optional) - Formation heading
  • spacing (number) - Unit spacing (meters)
  • defense (number) - Defense level 0-5
  • armor (number) - Armor level 0-5
  • size (number) - Size 0-5 (affects unit count)
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - Group info

Example:

-- Spawn small infantry squad
veafSpawn.spawnInfantryGroup(pos, 50, nil, nil, coalition.side.RED, 0, 10, 0, 0, 1, false)

veafSpawn.spawnArmoredPlatoon(spawnSpot, radius, czName, country, side, heading, spacing, defense, armor, size, silent, hasDest, hiddenOnMFD)

Spawn armored platoon.

Parameters: Same as infantry + hasDest for movement

Returns: table - Group info

Example:

-- Spawn medium tank platoon
veafSpawn.spawnArmoredPlatoon(pos, 100, nil, nil, coalition.side.BLUE, 90, 50, 2, 3, 3, false)

veafSpawn.spawnAirDefenseBattery(spawnSpot, radius, czName, country, side, heading, spacing, defense, silent, hasDest, hiddenOnMFD)

Spawn SAM/AAA battery.

Parameters: Similar to armor platoon

Returns: table - Group info

Example:

-- Spawn SA-6 battery
veafSpawn.spawnAirDefenseBattery(pos, 200, nil, nil, coalition.side.RED, 0, 75, 4, false)

veafSpawn.spawnTransportCompany(spawnSpot, radius, czName, country, side, heading, spacing, defense, size, silent, hasDest, hiddenOnMFD)

Spawn transport company (trucks).

Returns: table - Group info

veafSpawn.spawnFullCombatGroup(spawnSpot, radius, czName, country, side, heading, spacing, defense, armor, size, silent, hiddenOnMFD)

Spawn combined arms group (infantry + armor + transport).

Returns: table - Multiple group info

Convoy System

veafSpawn.spawnConvoy(spawnSpot, name, czName, radius, country, side, heading, spacing, speed, patrol, offroad, destination, defense, size, armor, silent, hiddenOnMFD)

Spawn vehicle convoy with waypoints.

Parameters:

  • spawnSpot (vec3) - Starting position
  • name (string) - Convoy name
  • czName (string, optional) - Combat zone
  • radius (number) - Dispersion
  • country (number, optional) - Country
  • side (coalition) - Coalition
  • heading (number, optional) - Initial heading
  • spacing (number) - Vehicle spacing
  • speed (number) - Speed (km/h)
  • patrol (boolean) - Patrol mode (return to start)
  • offroad (boolean) - Allow offroad movement
  • destination (vec3) - Destination position
  • defense (number) - Defense level 0-5
  • size (number) - Size 0-5
  • armor (number) - Armor level 0-5
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - Convoy info

Example:

local start = {x=1000, y=0, z=2000}
local dest = {x=5000, y=0, z=6000}
veafSpawn.spawnConvoy(start, "Convoy1", nil, 50, nil, coalition.side.RED,
  nil, 25, 40, false, false, dest, 2, 3, 2, false)

Convoy Control Functions

veafSpawn.stopClosestConvoy(unitName)

Stop nearest convoy to unit.

veafSpawn.moveClosestConvoy(unitName)

Resume nearest convoy movement.

veafSpawn.markClosestConvoyWithSmoke(unitName)

Mark nearest convoy with smoke.

veafSpawn.markClosestConvoyRouteWithSmoke(unitName)

Mark convoy route with smoke markers.

veafSpawn.infoOnAllConvoys(unitName)

Display info on all active convoys.

veafSpawn.cleanupAllConvoys()

Destroy all active convoys.

Aircraft Spawning

veafSpawn.spawnCombatAirPatrol(spawnSpot, radius, name, country, altitude, altitudeDelta, hdg, distance, speed, capRadius, skill, silent, hiddenOnMFD)

Spawn CAP flight with patrol orbit.

Parameters:

  • spawnSpot (vec3) - Spawn position
  • radius (number) - Dispersion
  • name (string) - Aircraft type
  • country (number, optional) - Country
  • altitude (number) - Patrol altitude (feet)
  • altitudeDelta (number, optional) - Altitude randomization
  • hdg (number) - Orbit heading
  • distance (number) - Length of the race-track leg (nautical miles, 20 by default)
  • speed (number) - Speed (knots)
  • capRadius (number) - Radius of the defended zone, centred on the middle of the leg (nautical miles, 60 by default)
  • skill (string) - Skill level
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - CAP flight info

Description:

  • Spawns aircraft at position
  • Creates racetrack orbit at specified location
  • Starts watchdog to monitor and engage targets

Example:

-- Spawn F-15C CAP
local pos = {x=0, y=0, z=0}
veafSpawn.spawnCombatAirPatrol(pos, 100, "F-15C", nil, 25000, 2000,
  90, 50000, 450, 20000, "Good", false)

veafSpawn.spawnAFAC(spawnSpot, name, country, altitude, speed, hdg, frequency, mod, code, immortal, silent, hiddenOnMFD)

Spawn Airborne Forward Air Controller (AFAC).

Parameters:

  • spawnSpot (vec3) - Spawn position
  • name (string) - Aircraft type
  • country (number, optional) - Country
  • altitude (number) - Orbit altitude (feet)
  • speed (number) - Speed (knots)
  • hdg (number) - Orbit heading
  • frequency (number) - Radio frequency (MHz)
  • mod (string) - "AM" or "FM"
  • code (number) - Laser code (e.g., 1688)
  • immortal (boolean) - Invulnerable flag
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - AFAC info

Example:

-- Spawn A-10C AFAC
veafSpawn.spawnAFAC(pos, "A-10C", nil, 15000, 250, 0, 133.0, "AM", 1688, true, false)

veafSpawn.startCapWatchdog(capGroupName, capCoalition, capZone, pTargetsList, pEngagedTargetIds)

Start CAP engagement watchdog.

Parameters:

  • capGroupName (string) - CAP group name
  • capCoalition (coalition) - Coalition
  • capZone (table) - Zone definition
  • pTargetsList (table, optional) - Targets tracked, from the previous pass
  • pEngagedTargetIds (table, optional) - Targets that already have an EngageUnit, from the previous pass

Returns: None

Description: Monitors area and tasks CAP to engage enemy aircraft. Targets are ranked by type, distance and aspect; a cold target past veafSpawn.CAP_COLD_CUTOFF (40,000 m) is not engaged. Facing several targets, each aircraft is given its own on its own controller (veafSpawn.spreadCapTargets).

veafSpawn.targetAspect(targetPosition, targetVelocity, capPosition)

Returns "hot", "flanking" or "cold" from the angle between the target's track and the target → CAP line, on the horizontal plane: up to veafSpawn.CAP_ASPECT_HOT_MAX (60°) hot, from veafSpawn.CAP_ASPECT_COLD_MIN (120°) cold. With no readable velocity, "flanking". Also returns the angle in degrees (nil with no velocity).

veafSpawn.spreadCapTargets(unitNames, targets)

Spreads the targets (sorted, most important first) over the CAP's aircraft, round-robin. Returns a table aircraft name → target id, empty with one target or one aircraft.

Cargo & Logistics

veafSpawn.spawnCargo(spawnSpot, radius, cargoType, country, weightBias, cargoSmoke, unitName, silent, hiddenOnMFD)

Spawn CTLD cargo.

Parameters:

  • spawnSpot (vec3) - Spawn position
  • radius (number) - Dispersion
  • cargoType (string) - Cargo type: "container", "barrels", "ammo", "fuel"
  • country (number, optional) - Country
  • weightBias (number, optional) - Weight preference (0-1)
  • cargoSmoke (boolean) - Add smoke marker
  • unitName (string, optional) - Cargo name
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD

Returns: table - Cargo info

Example:

-- Spawn fuel containers
veafSpawn.spawnCargo(pos, 10, "fuel", nil, 0.5, true, "Fuel-1", false)

veafSpawn.spawnLogistic(spawnSpot, radius, country, silent, hiddenOnMFD)

Spawn CTLD logistic unit.

Returns: table - Logistic unit info

FARP & FOB

veafSpawn.spawnFarp(spawnSpot, radius, name, country, farptype, side, hdg, spacing, silent, hiddenOnMFD, noFarpMarkers, code, freq, mod)

Spawn Forward Arming and Refueling Point (FARP).

Parameters:

  • spawnSpot (vec3) - Position
  • radius (number) - Dispersion
  • name (string) - FARP name
  • country (number, optional) - Country
  • farptype (string, optional) - FARP configuration type
  • side (coalition) - Coalition
  • hdg (number, optional) - Heading
  • spacing (number) - Unit spacing
  • silent (boolean, optional) - Suppress messages
  • hiddenOnMFD (boolean, optional) - Hide from MFD
  • noFarpMarkers (boolean, optional) - Don't create markers
  • code (number, optional) - TACAN code
  • freq (number, optional) - Radio frequency
  • mod (string, optional) - Modulation

Returns: string|nil - the FARP name, or nil when it is refused for want of clear ground for its escort (nothing is created then)

Example:

-- Spawn basic FARP
veafSpawn.spawnFarp(pos, 100, "FARP Alpha", nil, nil, coalition.side.BLUE,
  0, 50, false, false, false, 71, 251.0, "AM")

veafSpawn.spawnFob(spawnSpot, radius, name, country, fobtype, side, hdg, spacing, silent, hiddenOnMFD)

Spawn Forward Operating Base (FOB).

Parameters: Similar to FARP

Returns: table - FOB info

Effects & Markers

veafSpawn.spawnBomb(spawnSpot, radius, shells, power, altitude, altitudedelta, password)

Create explosion effect.

Parameters:

  • spawnSpot (vec3) - Explosion position
  • radius (number) - Dispersion
  • shells (number) - Number of explosions
  • power (number) - Explosion power (kg TNT equivalent)
  • altitude (number, optional) - Altitude offset
  • altitudedelta (number, optional) - Altitude randomization
  • password (string, optional) - Security password

Returns: None

Example:

-- Create 5x 500kg explosions
veafSpawn.spawnBomb(pos, 50, 5, 500, 0, 0)

veafSpawn.spawnSmoke(spawnSpot, color, radius, shells)

Add smoke markers.

Parameters:

  • spawnSpot (vec3) - Position
  • color (string) - "Green", "Red", "White", "Orange", "Blue"
  • radius (number) - Dispersion
  • shells (number) - Number of smoke markers

Returns: None

Example:

-- Mark position with red smoke
veafSpawn.spawnSmoke(pos, "Red", 0, 1)

veafSpawn.spawnSignalFlare(spawnSpot, radius, shells, color)

Fire signal flare(s).

Parameters:

  • spawnSpot (vec3) - Position
  • radius (number) - Dispersion
  • shells (number) - Number of flares
  • color (string) - Flare color

Returns: None

veafSpawn.spawnIlluminationFlare(spawnSpot, radius, steps, power, height, heading, distance, speed)

Create illumination flare pattern.

Parameters:

  • spawnSpot (vec3) - Position
  • radius (number) - Dispersion
  • steps (number) - Number of flares in line
  • power (number) - Flare power
  • height (number, optional) - Altitude AGL
  • heading (number, optional) - Line heading
  • distance (number, optional) - Distance between flares
  • speed (number, optional) - Drop speed

Returns: None

Example:

-- Create illumination line
veafSpawn.spawnIlluminationFlare(pos, 0, 5, 1000000, 1000, 90, 500, 0)

Drawing Functions

veafSpawn.drawCircle(point, name, radius, color, fillColor, lineType)

Draw circle on map.

Parameters:

  • point (vec3) - Center position
  • name (string) - Drawing name
  • radius (number) - Circle radius (meters)
  • color (table, optional) - Line color {r, g, b, a} (0-1 range)
  • fillColor (table, optional) - Fill color
  • lineType (number, optional) - Line type

Returns: None

Example:

-- Draw red circle
veafSpawn.drawCircle(pos, "Zone1", 5000, {1, 0, 0, 1}, {1, 0, 0, 0.3})

veafSpawn.drawSquare(point, name, side, color, fillColor, lineType)

Draw square on map.

Parameters:

  • point (vec3) - Center
  • name (string) - Drawing name
  • side (number) - Side length (meters)
  • color (table, optional) - Line color
  • fillColor (table, optional) - Fill color
  • lineType (number, optional) - Line type

Returns: None

veafSpawn.eraseDrawing(name)

Remove drawing from map.

Parameters:

  • name (string) - Drawing name

Returns: None

Destruction & Teleport

veafSpawn.destroy(spawnSpot, radius, unitName)

Destroy units in area or specific unit.

Parameters:

  • spawnSpot (vec3) - Position
  • radius (number) - Search radius (0 for specific unit)
  • unitName (string, optional) - Specific unit name

Returns: None

Example:

-- Destroy all units in 500m radius
veafSpawn.destroy(pos, 500)

-- Destroy specific unit
veafSpawn.destroy(pos, 0, "Tank-1")

veafSpawn.teleport(spawnSpot, name, silent)

Teleport group to position.

Parameters:

  • spawnSpot (vec3) - Destination
  • name (string) - Group name
  • silent (boolean, optional) - Suppress messages

Returns: None

Example:

-- Teleport player group to position
veafSpawn.teleport(newPos, "Viper Flight", false)

JTAC Functions

veafSpawn.JTACAutoLase(groupName, laserCode, radioData)

Setup auto-lasing JTAC.

Parameters:

  • groupName (string) - JTAC group name
  • laserCode (number) - Laser code (e.g., 1688)
  • radioData (table, optional) - Radio configuration

Returns: None

Example:

veafSpawn.JTACAutoLase("JTAC-1", 1688, {freq=133.0, mod="AM"})

veafSpawn.convertLaserToFreq(laser)

Convert laser code to radio frequency.

Parameters:

  • laser (number) - Laser code

Returns: number - Frequency in MHz

Mission Master Functions

Mission Master provides scriptable mission control.

veafSpawn.missionMasterSetMessagingMode(silent, toGroupId)

Set message output mode.

Parameters:

  • silent (boolean) - Silent mode
  • toGroupId (number, optional) - Target group ID

Returns: None

veafSpawn.missionMasterOutText(message)

Output Mission Master message.

Parameters:

  • message (string) - Message text

Returns: None

veafSpawn.missionMasterAddRunnable(name, code, parameters)

Add executable command.

Parameters:

  • name (string) - Command name
  • code (string) - Lua code to execute
  • parameters (table, optional) - Parameters

Returns: None

veafSpawn.missionMasterRun(name)

Run Mission Master command.

Parameters:

  • name (string) - Command name

Returns: None

veafSpawn.missionMasterSetFlag(name, value)

Set Mission Master flag.

Parameters:

  • name (string) - Flag name
  • value (any) - Flag value

Returns: None

veafSpawn.missionMasterGetFlag(name)

Get flag value.

Parameters:

  • name (string) - Flag name

Returns: any - Flag value

veafSpawn.missionMasterAddValueToFlag(name, increment)

Modify flag value.

Parameters:

  • name (string) - Flag name
  • increment (number) - Value to add

Returns: None

Utility Functions

veafSpawn.listAllCAP(unitName)

Display list of all active CAP flights.

Parameters:

  • unitName (string) - Requesting unit name

Returns: None

veafSpawn.dumpSpawnablePlanesList(export_path)

Export spawnable aircraft list to file.

Parameters:

  • export_path (string, optional) - Export directory

Returns: None

veafSpawn.buildRadioMenu()

Build spawn radio menu.

Returns: None

veafSpawn.initialize()

Initialize spawn module.

Returns: None


veafUnits.lua

Module ID: UNITS

Purpose: Unit/group definitions and utilities

Constants

veafUnits.DefaultCellWidth = 10        -- meters
veafUnits.DefaultCellHeight = 10       -- meters
veafUnits.DefaultPathfindingUnitType = "TZ-22_KrAZ"
veafUnits.delayBeforePathfindingFix = 5  -- seconds

Functions

veafUnits.findDcsUnit(unitType)

Find DCS unit by type name (case-insensitive).

Parameters:

  • unitType (string) - Unit type (e.g., "F-16C", "M-1 Abrams")

Returns: table - Unit definition or nil

Example:

local f16 = veafUnits.findDcsUnit("F-16C_50")
if f16 then
  veaf.logger:info("Found: %s", f16.displayName)
end

veafUnits.countInfantryAndVehicles(groupname)

Count infantry and vehicle units in group.

Parameters:

  • groupname (string) - Group name

Returns: number, number - Vehicle count, Infantry count

veafUnits.processGroup(group)

Process and validate group definition.

Parameters:

  • group (table) - Group definition table

Returns: table - Processed group

Description: Handles unit positioning, spacing, formation.


veafAssets.lua

Module ID: ASSETS

Purpose: Manage and track mission assets (tankers, AWACS, carriers)

Data Structures

Asset Definition
{
  name = "Tanker-1",              -- Group name
  description = "KC-135 Texaco",  -- Display name
  information = "TACAN 61X",      -- Optional info
  disposable = false,             -- Can be destroyed
  jtac = 1688,                    -- Optional JTAC laser code
  linked = {"AWACS-1"}            -- Respawn these groups too
}

Functions

veafAssets.respawn(name)

Respawn asset group.

Parameters:

  • name (string) - Asset name

Returns: None

Description:

  • Respawns asset group
  • Respawns all linked groups
  • Repairs its escort's Escort task — the group named <name> escort, if there is one. DCS invalidates that task as soon as the escorted group is recreated, and the escort then leaves to land after about ten minutes. See Escorting an asset
  • Starts JTAC if configured

Example:

veafAssets.respawn("Tanker-1")

veafAssets.dispose(name)

Destroy asset.

Parameters:

  • name (string) - Asset name

Returns: None

Example:

veafAssets.dispose("AWACS-1")

veafAssets.info(parameters)

Get asset information.

Parameters:

  • parameters (table) - {name=string, unitName=string}

Returns: string - Asset info text

Example:

local info = veafAssets.info({name="Tanker-1", unitName="Viper 1-1"})
-- Displays tanker position, TACAN, frequency

veafAssets.get(assetName)

Get asset definition.

Parameters:

  • assetName (string) - Asset name

Returns: table - Asset definition

veafAssets.help(unitName)

Display help text.

Parameters:

  • unitName (string) - Unit to receive help

Returns: None

veafAssets.buildRadioMenu()

Build assets radio menu.

Returns: None

veafAssets.buildAssetsDatabase()

Build asset lookup tables.

Returns: None

veafAssets.initialize()

Initialize assets module.

Returns: None

Description:

  • Builds asset database
  • Creates radio menus
  • Must be called after assets defined

Mission Systems

veafCombatMission.lua

Module ID: COMBATMISSION

Purpose: Create and manage combat missions with objectives

Constants

veafCombatMission.SecondsBetweenWatchdogChecks = 30
veafCombatMission.RadioMenuName = "MISSIONS"
veafCombatMission.MinimumSpacingBetweenClones = 300  -- meters

Classes

VeafCombatMissionObjective

Mission objective definition.

Fields:

  • name (string) - Objective name
  • description (string) - Description text
  • message (string) - Completion message
  • parameters (table) - Objective parameters
  • onStartupFunction (function) - Called when mission starts
  • onCheckFunction (function) - Called periodically to check completion

States:

VeafCombatMissionObjective.FAILED = -1
VeafCombatMissionObjective.SUCCESS = 1
VeafCombatMissionObjective.NOTHING = 0

Methods:

obj = VeafCombatMissionObjective:new()
obj:setName(value)
obj:getName()
obj:setDescription(value)
obj:getDescription()
obj:setMessage(value)
obj:getMessage()
obj:setParameters(value)
obj:getParameters()
obj:setOnStartup(value)
obj:getOnStartup()
obj:setOnCheck(value)
obj:getOnCheck()
obj:onStartup(mission)
obj:onCheck(mission)
obj:configureAsTimedObjective(timeInSeconds)
obj:configureAsKillEnemiesObjective(nbKillsToWin, whatsInAKill)
obj:configureAsPreventDestructionOfSceneryObjectsInZone(zones, objects)

Example:

local objective = VeafCombatMissionObjective:new()
objective:setName("Destroy Armor")
objective:setDescription("Destroy all enemy tanks")
objective:setOnStartup(function(mission)
  -- Spawn enemy tanks
end)
objective:setOnCheck(function(mission)
  -- Check if tanks destroyed
  if allTanksDestroyed() then
    return VeafCombatMissionObjective.SUCCESS
  end
  return VeafCombatMissionObjective.NOTHING
end)

VeafCombatMission

Complete mission definition.

Fields:

  • name (string) - Mission name (technical)
  • friendlyName (string) - Human-friendly mission name
  • briefing (string) - Full briefing text
  • secured (boolean) - Requires security clearance
  • radioMenuEnabled (boolean) - Show in F10 menu
  • objectives (table) - Array of objectives
  • elements (table) - Elements defined in the mission
  • spawnedGroups (table) - Spawned DCS groups
  • active (boolean) - Mission is active
  • training (boolean) - Training mission
  • hidden (boolean) - No message on activation/deactivation
  • silent (boolean) - Same as hidden, but for a single activation

Methods:

mission = VeafCombatMission:new()
mission:setName(value)
mission:getName()
mission:setFriendlyName(value)
mission:getFriendlyName()
mission:setBriefing(value)
mission:getBriefing()
mission:setSecured(value)
mission:isSecured()
mission:setRadioMenuEnabled(value)
mission:isRadioMenuEnabled()
mission:setActive(value)
mission:isActive()
mission:setTraining(value)
mission:isTraining()
mission:setHidden(value)
mission:isHidden()
mission:setSilent(value)
mission:isSilent()
mission:addObjective(objective)
mission:getObjectives()
mission:addElement(value)
mission:addSpawnedGroup(group)
mission:addDefaultObjectives()
mission:getRemainingEnemies(whatsInAKill)
mission:getInformation()
mission:initialize()
mission:activate(silent)
mission:desactivate()

Example:

local mission = VeafCombatMission:new()
mission:setName("Strike Alpha")
mission:setFriendlyName("Strike Alpha")
mission:setBriefing("Enemy armor advancing on friendly position. Destroy all tanks.")
mission:addObjective(destroyTanksObjective)
mission:addObjective(rtbObjective)

veafCombatMission.AddMission(mission)

Functions

veafCombatMission.AddMission(mission)

Register mission.

Parameters:

  • mission (VeafCombatMission) - Mission object

Returns: None

veafCombatMission.AddMissionsWithSkillAndScale(mission, includeOriginal, skills, scales)

Add mission variants with different skill/scale.

Parameters:

  • mission (VeafCombatMission) - Base mission
  • includeOriginal (boolean) - Include original
  • skills (table) - Skill levels: {"Average", "Good", "High"}
  • scales (table) - Scale factors: {0.5, 1.0, 1.5}

Returns: None

Description: Creates multiple variants (e.g., "Strike Alpha - Good - 1.0x")

Example:

veafCombatMission.AddMissionsWithSkillAndScale(
  baseMission,
  false,
  {"Average", "Good", "High", "Excellent"},
  {0.5, 1.0, 1.5, 2.0}
)
-- Creates 16 mission variants (4 skills × 4 scales)

veafCombatMission.GetMission(name)

Get mission by name.

Parameters:

  • name (string) - Mission name

Returns: VeafCombatMission - Mission object or nil

veafCombatMission.GetMissionNumber(number)

Get mission by index.

Parameters:

  • number (number) - Mission index (1-based)

Returns: VeafCombatMission - Mission object

veafCombatMission.ActivateMission(name, silent, unitName)

Activate mission.

Parameters:

  • name (string) - Mission name
  • silent (boolean, optional) - Suppress messages
  • unitName (string, optional) - Unit to receive messages

Returns: None

Description:

  • Executes all objective startup functions
  • Spawns mission elements
  • Starts watchdog timer
  • Displays briefing

Example:

veafCombatMission.ActivateMission("Strike Alpha", false, "Viper 1-1")

veafCombatMission.ActivateMissionNumber(number, silent)

Activate mission by index.

Parameters:

  • number (number) - Mission index
  • silent (boolean, optional) - Suppress messages

Returns: None

veafCombatMission.DesactivateMission(name, silent, unitName)

Deactivate mission.

Parameters:

  • name (string) - Mission name
  • silent (boolean, optional) - Suppress messages
  • unitName (string, optional) - Unit to receive messages

Returns: None

Description:

  • Stops mission watchdog
  • Destroys spawned groups
  • Clears objectives
veafCombatMission.DesactivateMissionNumber(number, silent)

Deactivate mission by index.

Returns: None

veafCombatMission.GetInformationOnMission(parameters)

Get mission status.

Parameters:

  • parameters (table) - {name=string, unitName=string}

Returns: string - Mission status text

Example:

local status = veafCombatMission.GetInformationOnMission({
  name = "Strike Alpha",
  unitName = "Viper 1-1"
})

veafCombatMission.CompletionCheck(name)

Check mission completion status.

Parameters:

  • name (string) - Mission name

Returns: number - Status: FAILED (-1), SUCCESS (1), NOTHING (0)

Description: Calls all objective check functions and aggregates results.

veafCombatMission.addCapMission(missionName, missionDescription, missionBriefing, secured, radioMenuEnabled, skills, scales, spawnRadius)

Create CAP mission helper.

Parameters:

  • missionName (string) - Mission name
  • missionDescription (string) - Description
  • missionBriefing (string) - Briefing
  • secured (boolean) - Security required
  • radioMenuEnabled (boolean) - Show in menu
  • skills (table) - Skill levels
  • scales (table) - Scale factors
  • spawnRadius (number) - Spawn dispersion

Returns: VeafCombatMission - Mission object

Description: Helper for creating CAP missions with standard objectives.

veafCombatMission.listAvailableMissions(unitName)

Display mission list to player.

Parameters:

  • unitName (string) - Unit to receive list

Returns: None

veafCombatMission.listActiveMissions()

Show active missions.

Returns: None

veafCombatMission.help(unitName)

Display help text.

Parameters:

  • unitName (string) - Unit to receive help

Returns: None

veafCombatMission.buildRadioMenu()

Build missions radio menu.

Returns: None

veafCombatMission.executeCommandFromRemote(parameters)

Execute command from remote API.

Parameters:

  • parameters (table) - Remote command parameters

Returns: None

veafCombatMission.dumpMissionsList(export_path)

Export missions to file.

Parameters:

  • export_path (string, optional) - Export directory

Returns: None

veafCombatMission.initialize()

Initialize module.

Returns: None


veafCasMission.lua

Module ID: CASMISSION

Purpose: Create close air support training missions

Constants

veafCasMission.Keyphrase = "_cas"
veafCasMission.SecondsBetweenWatchdogChecks = 15
veafCasMission.SecondsBetweenSmokeRequests = 180
veafCasMission.SecondsBetweenFlareRequests = 120
veafCasMission.RedCasGroupName = "Red CAS Group"
veafCasMission.BlueCasGroupName = "Blue CAS Group"
veafCasMission.RadioMenuName = "CAS MISSION"

Unit Type Tables

Units are categorized by coalition, era, and defense level:

TRANSPORT_TYPES[coalition][era][defense] = {unit_types}
ARMOR_TYPES[coalition][era][defense] = {unit_types}
DEFENSE_TYPES[coalition][era][defense] = {unit_types}

Coalition: "blue", "red"

Era: "cold", "modern"

Defense: 0-5 (0=none, 5=heavy)

Functions

veafCasMission.executeCommand(eventPos, eventText, coalition, markId, bypassSecurity)

Execute CAS mission command.

Parameters:

  • eventPos (vec3) - Spawn position
  • eventText (string) - Command text
  • coalition (coalition, optional) - Coalition
  • markId (number, optional) - Marker ID
  • bypassSecurity (boolean, optional) - Skip security

Returns: boolean - Success flag

veafCasMission.markTextAnalysis(text)

Parse CAS marker text.

Parameters:

  • text (string) - Marker text

Returns: table - Parsed options

Options:

{
  size = 0-5,              -- Force size
  defense = 0-5,           -- Defense level
  armor = 0-5,             -- Armor level
  spacing = number,        -- Unit spacing (meters)
  disperseOnAttack = boolean,  -- Units disperse when attacked
  side = coalition         -- Coalition
}

veafCasMission.generateCasMission(spawnSpot, size, defense, armor, spacing, disperseOnAttack, side)

Generate complete CAS mission.

Parameters:

  • spawnSpot (vec3) - Spawn position
  • size (number) - Size 0-5
  • defense (number) - Defense 0-5
  • armor (number) - Armor 0-5
  • spacing (number) - Unit spacing (meters)
  • disperseOnAttack (boolean) - Disperse on attack
  • side (coalition) - Coalition

Returns: table - Generated group info

Description:

  • Spawns infantry, armor, transport, and air defense
  • Groups react to player attacks
  • Provides smoke/flare marking

Example:

-- Generate medium difficulty CAS mission
local pos = {x=1000, y=0, z=2000}
veafCasMission.generateCasMission(pos, 3, 3, 3, 50, true, coalition.side.RED)

veafCasMission.smokeCasTargetGroup()

Add smoke to current CAS target.

Returns: None

Description: Limited by SecondsBetweenSmokeRequests timer.

veafCasMission.flareCasTargetGroup()

Add flare to current CAS target.

Returns: None

veafCasMission.smokeReset()

Reset smoke request timer.

Returns: None

veafCasMission.flareReset()

Reset flare request timer.

Returns: None

veafCasMission.skipCasTarget()

Skip current target group (destroy without score).

Returns: None

veafCasMission.reportTargetInformation(unitName)

Get CAS target info.

Parameters:

  • unitName (string) - Unit to receive report

Returns: None

veafCasMission.help(unitName)

Display CAS help text.

Parameters:

  • unitName (string) - Unit to receive help

Returns: None

veafCasMission.buildRadioMenu()

Build CAS radio menu.

Returns: None

veafCasMission.initialize()

Initialize CAS module.

Returns: None


Infrastructure & Services

veafAirbases.lua

Module ID: AIRBASES

Purpose: Normalized airbase and runway information

Classes

veafAirbase

Airbase descriptor holding normalized information about a DCS airbase.

Fields:

  • Name (string) - Airbase name
  • DisplayName (string) - Normalized display name
  • Category (number) - DCS category (AIRDROME, HELIPAD, SHIP)
  • DcsAirbase (DCS Airbase) - Underlying DCS airbase object
  • Runways (table) - Array of veafAirbaseRunway objects

Methods:

airbase = veafAirbase:create(dcsAirbase)
airbase:getRunwayInService(iWindDirectionTrue)        -- Best runway end facing the wind
airbase:getRunwayInServiceString(iWindDirectionTrue)  -- In-service runway number ("02")
airbase:toString()

veafAirbaseRunway

Runway descriptor holding normalized information about a DCS airbase runway.

Each object is an indexed table of the two runway ends ([1] and [2]), each having:

  • Number (number) - Runway number (1-36)
  • Heading (number) - True heading of the end (degrees)

Methods:

runway = veafAirbaseRunway:create(dcsAirbase, dcsRunway, iReportOrder)
runway:toString()

Functions

veafAirbases.initialize(bReset)

Initialize airbase database.

Parameters:

  • bReset (boolean, optional) - Force rebuild database

Returns: None

veafAirbases.getAirbaseByName(sAirbaseName)

Get airbase by name.

Parameters:

  • sAirbaseName (string) - Airbase name

Returns: veafAirbase - Airbase object or nil

Example:

local kutaisi = veafAirbases.getAirbaseByName("Kutaisi")
if kutaisi then
  veaf.loggers.get("AIRBASES"):info("Kutaisi has %d runways", #kutaisi.Runways)
  veaf.loggers.get("AIRBASES"):info("Airbase: %s", kutaisi:toString())
end

veafAirbases.getAirbaseFromDcsAirbase(dcsAirbase)

Convert DCS airbase to veafAirbase object.

Parameters:

  • dcsAirbase (DCS Airbase) - DCS airbase object

Returns: veafAirbase - VEAF airbase object

veafAirbases.getNearestAirbaseList(dcsUnit, iCount)

Get nearest airbases to unit.

Parameters:

  • dcsUnit (DCS Unit) - Unit object
  • iCount (number) - Number of results

Returns: table - Array of {veafAirbase, distance} pairs sorted by ascending distance

Example:

local unit = Unit.getByName("Viper 1-1")
local nearestBases = veafAirbases.getNearestAirbaseList(unit, 3)
for i, pair in ipairs(nearestBases) do
  local airbase = pair[1]
  local distance = pair[2]
  veaf.loggers.get("AIRBASES"):info("%d. %s (%dm)", i, airbase.Name, distance)
end

veafAirbases.getNearestAirbase(dcsUnit)

Get single nearest airbase.

Parameters:

  • dcsUnit (DCS Unit) - Unit object

Returns: veafAirbase - Nearest airbase

Example:

local unit = Unit.getByName("Viper 1-1")
local nearest = veafAirbases.getNearestAirbase(unit)
veaf.outTextForUnit("Viper 1-1",
  string.format("Nearest airbase: %s", nearest.Name), 10)

veafAirbases.getAtcFrequencies(veafAirbase)

Tower frequencies (MHz) and TACAN DCS gives the airfield, read from veafAirfieldFrequencies (a table shipped with the scripts, since the mission scripts have no API to ask DCS for them).

Parameters:

  • veafAirbase (veafAirbase) - Airbase

Returns: table|nil - { uhf?, vhf?, fm?, tacan? }, or nil for a carrier, a FARP or an airfield the table lacks

veafAirbases.getMissionChannel(veafAirbase)

The channel the mission's radio plan gives the airfield (bases collection of src/presets.yaml), written by the build into veaf-config.lua.

Parameters:

  • veafAirbase (veafAirbase) - Airbase

Returns: table|nil - { alias, title, uhf?, vhf?, fm? }, or nil when the mission has none


veafCarrierOperations.lua

Module ID: CARRIER

Purpose: Manage aircraft carrier operations

Functions

veafCarrierOperations.startCarrierOperations(parameters)

Start carrier recovery operations.

Parameters:

  • parameters (table) - {carrierGroupName=string, userUnitName=string}

Returns: None

Description:

  • Turns carrier into wind
  • Maintains position for recovery
  • Reports wind direction and ATC info

Example:

veafCarrierOperations.startCarrierOperations({
  carrierGroupName = "CVN-73",
  userUnitName = "Hornet 1-1"
})

veafCarrierOperations.continueCarrierOperations(groupName, userUnitName)

Continue carrier operations.

Parameters:

  • groupName (string) - Carrier group name
  • userUnitName (string, optional) - User unit

Returns: None

veafCarrierOperations.stopCarrierOperations(parameters)

Stop carrier operations.

Parameters:

  • parameters (table) - {carrierGroupName=string}

Returns: None

Description: Returns carrier to normal navigation.

veafCarrierOperations.getAtcForCarrierOperations(groupName, skipNavigationData)

Get carrier ATC data.

Parameters:

  • groupName (string) - Carrier group name
  • skipNavigationData (boolean, optional) - Skip nav info

Returns: string - ATC information text

Example Output:

CVN-73 Washington
Callsign: Mother
Position: N 42°15' E 041°45'
Heading: 270°
Wind: 285° at 25 kts
Radio: 127.5 MHz AM
TACAN: 73X (1205 MHz)
ICLS: 13

veafCarrierOperations.atcForCarrierOperations(parameters)

Get ATC for carrier (with output).

Parameters:

  • parameters (table) - {carrierGroupName=string, userUnitName=string}

Returns: None

veafCarrierOperations.listAvailableCarriers(forGroup)

Display available carriers.

Parameters:

  • forGroup (string, optional) - Group name to receive list

Returns: None

veafCarrierOperations.executeCommandFromRemote(parameters)

Execute from remote API.

Parameters:

  • parameters (table) - Remote command parameters

Returns: None

veafCarrierOperations.initializeCarrierGroups()

Initialize carrier groups.

Returns: None

veafCarrierOperations.buildRadioMenu()

Build carrier radio menu.

Returns: None

veafCarrierOperations.initialize()

Initialize carrier operations module.

Returns: None


Communication & Control

veafRadio.lua

Module ID: RADIO

Purpose: Manage F10 radio menus and communications

Constants

veafRadio.RadioMenuName = "VEAF"
veafRadio.Keyphrase = "_radio"
veafRadio.BEACONS_SCHEDULE = 5  -- seconds
veafRadio.USAGE_ForAll = 0
veafRadio.USAGE_ForGroup = 1
veafRadio.USAGE_ForUnit = 2

Functions

veafRadio.addSubMenu(title, parentMenu, coalitionSide)

Add submenu to radio.

Parameters:

  • title (string) - Submenu title
  • parentMenu (menu, optional) - Parent menu (nil = root VEAF menu)
  • coalitionSide (number, optional) - coalition.side.RED / coalition.side.BLUE: the submenu and everything under it is only shown to that coalition (nil = everyone). The side is inherited by child submenus, commands and pagination pages; a USAGE_ForGroup command is only attached for groups of that side.

Returns: menu - Submenu object

Example:

local assetsMenu = veafRadio.addSubMenu("Assets")
local tankersMenu = veafRadio.addSubMenu("Tankers", assetsMenu)

veafRadio.addCommandToSubmenu(text, menu, callback, parameters, usage)

Add command to submenu.

Parameters:

  • text (string) - Command text
  • menu (menu) - Target menu
  • callback (function) - Callback function
  • parameters (any, optional) - Parameters passed to callback
  • usage (number, optional) - Usage type: USAGE_ForAll, USAGE_ForGroup, USAGE_ForUnit

Returns: None

Callback Signature:

function callback(parameters)
  -- parameters: value passed to addCommandToSubmenu
end

Example:

local menu = veafRadio.addSubMenu("Test")
veafRadio.addCommandToSubmenu("Say Hello", menu, function(params)
  veaf.logger:info("Hello from %s!", params.unitName)
end, {unitName = "Player"}, veafRadio.USAGE_ForAll)

veafRadio.addSecuredCommandToSubmenu(text, menu, callback, parameters, usage)

Add security-protected command.

Parameters: Same as addCommandToSubmenu

Returns: None

Description: Command only appears if user has security clearance.

veafRadio.executeCommand(eventPos, eventText, eventCoalition, bypassSecurity)

Execute radio command from marker.

Parameters:

  • eventPos (vec3) - Command position
  • eventText (string) - Command text
  • eventCoalition (coalition) - Coalition
  • bypassSecurity (boolean, optional) - Skip security check

Returns: boolean - Success flag

Supported Commands:

  • transmit - Transmit via SRS
  • playmp3 - Play MP3 via SRS
veafRadio.markTextAnalysis(text)

Parse radio marker text.

Parameters:

  • text (string) - Marker text

Returns: table - Parsed options

Options:

{
  transmit = boolean,      -- Transmit message
  playmp3 = boolean,       -- Play MP3 file
  message = string,        -- Message text
  frequencies = table,     -- Array of frequencies (MHz)
  modulations = table,     -- Array of "AM"/"FM"
  name = string,           -- Transmission name
  path = string,           -- MP3 file path
  quiet = boolean          -- Suppress confirmation
}

veafRadio.transmitMessage(message, frequencies, modulations, name, coalition, position, quiet)

Transmit message via SRS.

Parameters:

  • message (string) - Message text (TTS)
  • frequencies (table) - Array of frequencies
  • modulations (table) - Array of modulations
  • name (string) - Transmission name/callsign
  • coalition (coalition, optional) - Coalition
  • position (vec3, optional) - Transmission origin
  • quiet (boolean, optional) - Suppress confirmation

Returns: None

Example:

veafRadio.transmitMessage(
  "All aircraft, return to base",
  {251.0, 305.0},
  {"AM", "AM"},
  "Tower",
  coalition.side.BLUE,
  airbasePos,
  false
)

veafRadio.playToRadio(path, frequencies, modulations, name, coalition, position, quiet)

Play MP3 file via SRS.

Parameters:

  • path (string) - MP3 file path
  • Other parameters same as transmitMessage

Returns: None

Example:

veafRadio.playToRadio(
  "D:\\Sounds\\airraid.mp3",
  {305.0},
  {"AM"},
  "Alert",
  coalition.side.BLUE,
  nil,
  false
)

veafRadio.refreshRadioMenu()

Rebuild radio menu (delayed).

Returns: None

Description: Schedules menu rebuild after delay to prevent conflicts. The rebuild only touches what changed in DCS: an unchanged entry keeps its place, a new entry is added at the end of its menu. DCS gives a removed entry's id to the next one created, and a player whose F10 menu stayed open would fire that one (f10-menu-entry-id-is-recycled in the DCS runtime traps).

veafRadio.addPaginatedRadioElements(menu, buildFunction, elements, sortKey, sortField)

Add paginated elements to menu.

Parameters:

  • menu (menu) - Target menu
  • buildFunction (function) - Function to build each element
  • elements (table) - Array of elements
  • sortKey (string, optional) - Sort key
  • sortField (string, optional) - Sort field

Returns: None

Description: Creates pages of 10 items with next/previous navigation.

veafRadio.onBirthEvent(event)

Handle unit birth (add to radio menu).

Parameters:

  • event (table) - Birth event

Returns: None

Description: Automatically adds human units to radio menu.

veafRadio.initialize()

Initialize radio module.

Returns: None


Support Systems

veafWeather.lua

Module ID: WEATHER

Version: (varies)

Purpose: Dynamic weather system

Functions

veafWeatherData.getWeatherString(vec3, dcsElementName, unitSystem, iSurfaceAltitudeMeters)

Builds the full textual weather report at a given position.

Parameters:

  • vec3 (vec3) - Position
  • dcsElementName (string) - DCS element name (used to infer the default unit system)
  • unitSystem (optional) - Unit system (defaults to the one inferred from the element type)
  • iSurfaceAltitudeMeters (number, optional) - Surface altitude in meters

Returns: string - The weather report

veafWeather.getWind(vec3, iAltitudeMeters, bTurbulence)

Computes the wind at a position and altitude.

Parameters:

  • vec3 (vec3) - Position
  • iAltitudeMeters (number) - Altitude in meters
  • bTurbulence (boolean, optional) - Include turbulence (defaults to false)

Returns: number, number - Direction (degrees, "where the wind comes from", [1, 360]) and speed (m/s)

veafWeather.messageWeatherAtClosestPoint(unitName, forUnit)

Displays the weather report for the named point closest to the unit.

Parameters:

  • unitName (string) - Unit name
  • forUnit (boolean) - If true, displays to the pilot only; otherwise to the group
veafWeather.messageAtcClosestAirbase(unitName, forUnit)

Displays the ATC (ATIS) report for the airbase closest to the unit.

Parameters:

  • unitName (string) - Unit name
  • forUnit (boolean) - If true, displays to the pilot only; otherwise to the group
veafWeather.messageAtcAndWeather(unitName, forUnit)

Displays the ATC report followed by the weather report.

Parameters:

  • unitName (string) - Unit name
  • forUnit (boolean) - If true, displays to the pilot only; otherwise to the group
veafWeather.createStaticFog(name, thickness, visibility)

Creates a static fog object.

Parameters:

  • name (string) - Fog name
  • thickness (number) - Thickness (meters)
  • visibility (number) - Visibility (meters)

Returns: A fog object

veafWeather.createDynamicFog(name, baseFactor, notAnimated)

Creates a dynamic fog object.

Parameters:

  • name (string) - Fog name
  • baseFactor (number) - Dynamic fog base factor
  • notAnimated (boolean, optional) - If true, the fog is not animated

Returns: A fog object

veafWeather.createAnimatedFog(name, minutes, thickness, visibility)

Creates a fog object animated over a given duration.

Parameters:

  • name (string) - Fog name
  • minutes (number) - Animation duration (minutes)
  • thickness (number) - Thickness (meters)
  • visibility (number) - Visibility (meters)

Returns: A fog object

veafWeather.setAndActivateFog(fogObject)

Disables the existing fog (if any) then activates the supplied fog object.

Parameters:

  • fogObject - A fog object (created via the create*Fog functions or a veafWeather.FOG_* constant)

Returns: The activated fog object

Predefined fog constants: veafWeather.FOG_DYNAMIC_HEAVY, FOG_DYNAMIC_MEDIUM, FOG_DYNAMIC_SPARSE, FOG_STATIC_HEAVY, FOG_STATIC_MEDIUM, FOG_STATIC_MEDIUM_LOW, FOG_STATIC_SPARSE, FOG_STATIC_SPARSE_LOW, FOG_STATIC_NO.


veafTime.lua

Module ID: TIME

Version: (varies)

Purpose: Mission time management

Read-only module: it computes date and time information from the mission time, it never sets the mission time or date.

Functions

veafTime.getMissionDateTime(iAbsTime)

Computes the mission date and time matching an absolute time (handles day, month and year rollover).

Parameters:

  • iAbsTime (number, optional) - Absolute time (defaults to timer.getAbsTime())

Returns: table - { year, month, day, yday, hour, min, sec }

veafTime.absTimeToStringTime(iAbsTime, bWithSeconds)

Formats an absolute time into a time string.

Parameters:

  • iAbsTime (number) - Absolute time
  • bWithSeconds (boolean, optional) - Include seconds

Returns: string

veafTime.toZulu(dateTime, nOffsetHours)

Converts a local date/time to Zulu time (UTC).

Parameters:

  • dateTime (table) - Date/time (format of getMissionDateTime)
  • nOffsetHours (number, optional) - Timezone offset (defaults to the one inferred from getTimezone)

Returns: table - Date/time in Zulu

veafTime.getSunTimesZulu(vec3, iAbsTime)

Computes the sunrise and sunset times (in Zulu) for a position.

Parameters:

  • vec3 (vec3) - Position
  • iAbsTime (number) - Absolute time

Returns: The sunrise and sunset times

veafTime.determineSeason(month, latitude)

Determines the season from the month and latitude (handles both hemispheres).

Parameters:

  • month (number) - Month (1-12)
  • latitude (number, optional) - Latitude (northern hemisphere if nil or >= 0)

Returns: string - Season ("spring", "summer", "autumn", "winter")

Other available functions: getMissionAbsTime, absTimeToDateTime, toStringDate / absTimeToStringDate, toStringTime, toStringDateTime / absTimeToStringDateTime, getTimezone, toLocal, getSunTimesLocal, isAeronauticalNight.


Data & Database

dcsUnits.lua

Module ID: DCSUNITS

Version: datamine-dc7d15e8

Purpose: Complete DCS unit database

This module exposes no functions: it only provides data tables.

Data Structures

dcsUnits.DcsUnitsDatabase

Raw DCS units database, keyed by DCS type id.

Schema of each entry:

{
  type = ".Ammunition depot",      -- DCS type id (table key)
  name = "Ammunition depot",       -- Human-readable name
  kind = "static",                 -- Kind ("static", "vehicle", "plane", etc.)
  category = "Warehouse",          -- DCS category
  description = "Ammunition depot", -- Description
  attribute = {},                  -- DCS attributes table
}

dcsUnits.NavalStatics

Set (table of booleans) of static names considered naval:

dcsUnits.NavalStatics = {
  ["Gas platform"] = true,
  ["M1 barrage balloon"] = true,
  ["Oil platform"] = true,
  ["Oil rig"] = true,
  ["Orca"] = true,
  ["offshore WindTurbine"] = true,
  ["offshore WindTurbine2"] = true,
}

See also dcs-data.md for the detailed schema description.


dcsDataExport.lua

Module ID: DCSEXPORT

Purpose: DCS data export script, to be run in the mission editor

Description

This is not a library: the script exposes no public function. It is meant to be loaded (dofile) at the end of DCS World\MissionEditor\modules\me_mission.lua. On load it defines the global DcsDataExport table (internal logging and serialization helpers) then immediately runs the export: it writes the units database (db.Units.lua) and calls browseUnits(...) for each unit category (Animal, Cargo, Vehicle, Effect, Fortification, GrassAirfield, GroundObject, Helicopter, Heliport, Personnel, Plane, Ship, Warehouse).

The output directory is set by the local export_path variable (defaults to .\, the current directory).

Returns: None


Appendix

Common Patterns

Creating a Spawn Command

-- Via marker
local pos = {x=1000, y=0, z=2000}
veafSpawn.executeCommand(pos, "_spawn, name F-16C, group 2, hdg 270", coalition.side.BLUE)

-- Via interpreter (in unit name)
veafInterpreter.executeCommandOnUnit("SpawnTrigger1", "_spawn, name F-16C, group 2")

-- Programmatically
veafSpawn.spawnUnit(pos, 50, "F-16C", nil, nil, 5000, 270)

Listening to Events

-- Register callback
veafEventHandler.addCallback("myHandler", {"S_EVENT_TAKEOFF", "S_EVENT_LAND"},
  function(event)
    if event.initiator then
      veaf.logger:info("%s - %s", event.type.name, event.initiator.unitName)
    end
  end
)

Creating a Mission

-- Define objective
local objective = VeafCombatMissionObjective:new()
objective:setName("Destroy Tanks")
objective:setOnStartup(function(mission)
  -- Spawn tanks
  local spawnPos = veafGeo.zoneToVec3("TargetZone")
  veafSpawn.spawnArmoredPlatoon(spawnPos, 100, nil, nil,
    coalition.side.RED, 0, 50, 2, 3, 3, true)
end)
objective:setOnCheck(function(mission)
  -- Check completion
  if allTanksDestroyed() then
    return VeafCombatMissionObjective.SUCCESS
  end
  return VeafCombatMissionObjective.NOTHING
end)

-- Define mission
local mission = VeafCombatMission:new()
mission:setName("Tank Hunt")
mission:setFriendlyName("Tank Hunt")
mission:setBriefing("Destroy enemy armor")
mission:addObjective(objective)

-- Register
veafCombatMission.AddMission(mission)

Building Radio Menus

-- Create submenu
local myMenu = veafRadio.addSubMenu("My Commands")

-- Add command
veafRadio.addCommandToSubmenu("Do Something", myMenu, function(params)
  veaf.logger:info("Command executed!")
  veaf.outTextForUnit(params.unitName, "Done!", 5)
end, {unitName = "Viper 1-1"}, veafRadio.USAGE_ForAll)

Security Best Practices

  1. Use veafSecurity for sensitive commands
  2. Validate coalition before spawning
  3. Use bypassSecurity only when necessary
  4. Check user permissions via radio menus

Performance Optimization

  1. Disable unused events: veafEventHandler.setEventEnabled("S_EVENT_SHOOTING_START", false)
  2. Use delayed callbacks for expensive operations
  3. Limit spawn counts and areas
  4. Clean up inactive groups regularly

Debugging Tips

  1. Enable trace logging: veafModuleName.LogLevel = "trace"
  2. Use logger markers: logger:marker(id, "Debug", "Position", pos)
  3. Export data for analysis: veaf.exportAsJson(data, "debug", true, "debug.json")
  4. Check event handlers: Verify callbacks registered correctly

Version History

  • v1.57.0 (veaf.lua) - Latest core utilities
  • v1.59.3 (veafSpawn.lua) - Latest spawn system
  • v2.2.1 (veafCombatMission.lua) - Latest mission system
  • v1.15.3 (veafCasMission.lua) - Latest CAS system

Credits

VEAF Project: https://www.veaf.org

Repository: https://github.com/VEAF/VEAF-Mission-Creation-Tools

Documentation: https://veaf.github.io/documentation/

Lead Developer: Zip (davidp57)


Document Version: 1.0

Last Updated: November 2026

Generated for: VEAF Mission Creation Tools v6.36.0