Version: v2.1.1
A DCS World Lua mission script that sends coalition-specific attack alerts when enemy aircraft destroy friendly ground units inside defined trigger zones.
ZoneAttackAlert monitors the DCS World event stream for S_EVENT_KILL events, filters them according to strict criteria (aircraft attacker, ground victim, opposite coalitions, zone containment), and broadcasts location-aware alert messages to the affected coalition. Blue coalition receives distances in nautical miles (NM); Red coalition receives distances in kilometers (KM).
| Fix | Description | Impact |
|---|---|---|
| Pre-cached zones | trigger.misc.getZone() resolved once at startup into Lua tables | Eliminates 10 C++ API calls per zone check |
| Coalition-split zones | BT* zones cached separately from RT* zones; handler only scans relevant half | ~50% fewer zone iterations per event |
| Pre-cached airbases | world.getAirbases() + :getPoint() resolved once at startup | Eliminates 20-40 C++ API calls per location lookup |
| Localized globals | math.floor, string.format, timer.getTime, ipairs, env.info cached to locals at file scope | Faster table lookups, no repeated global resolution |
| Inlined helpers | Small single-call functions kept inline where hot | Reduced function call overhead per alert |
| Pure-Lua distance check | Compares squared distance from cached zone points | No math.sqrt() inside loop |
| Single format call | Message built in one string.format instead of concatenating two | Fewer string allocations |
| Fix | Description |
|---|---|
| Aircraft-only filter | Unit.Category.AIRPLANE or Unit.Category.HELICOPTER required; missiles, artillery, ships ignored |
| Ground-unit victim | Unit.Category.GROUND_UNIT required; air-to-air kills ignored |
| No friendly fire | Same-coalition initiator/victim silently skipped |
| Distance rounding fix | < 1 NM / < 1 KM instead of "0 NM" / "0 KM" for sub-unit distances |
| pcall wrapper | Event handler body wrapped; errors logged to env.info without breaking mission scripts |
| Fix | Description |
|---|---|
| snake_case | All variables and functions converted (message_cooldown, get_location_string, etc.) |
| PascalCase modules | Handler table follows convention |
| 2-space indent | Entire file reformatted |
| 120 char line limit | Long expressions broken |
| Local preference | No globals leaked; all functions and state local |
ZAA.config = {
zone_names = {
"RT1", "RT2", "RT3", "RT4", "RT5",
"BT1", "BT2", "BT3", "BT4", "BT5"
},
message_cooldown = 180, -- seconds per zone
message_duration = 18, -- seconds on screen
heartbeatEnabled = false, -- periodic "ZAA script is still running ..." in-game message
heartbeatInterval = 10, -- seconds between heartbeat messages
}
Zone prefixes:
RT* — Red Team trigger zones (checked when Red coalition victim dies)BT* — Blue Team trigger zones (checked when Blue coalition victim dies)ZoneAttackAlert.lua
├── ZAA CONFIGURATION (table, user-editable)
├── GLOBAL LOCALIZATION (captured locals for hot path)
├── STATIC DATA (country_to_noun, cardinal_directions)
├── ZAA.ZONE CACHE (built at load time, split by coalition)
├── ZAA.AIRBASE CACHE (built at load time, includes ALL airbases; lookup is geographical proximity)
├── ZAA.STATE (last_alert_time table)
├── HELPERS (get_country_noun, get_cardinal, get_location_string)
└── EVENT HANDLER (onEvent + handle_event)
ZoneAttackAlert.lua to your DCS mission's trigger DO SCRIPT action or load it via require in your mission scriptingRT1–RT5 and BT1–BT5 exist in your missionworld.addEventHandler)| Version | Changes |
|---|---|
| v1.x | Original: camelCase, runtime API calls, all unit types, no pcall, distance printed "0 NM/KM" |
| v2.0 | Optimized caches, aircraft/ground-only filtering, snake_case, pcall guards, < 1 distance fix, coalition-split zones |
| v2.1.1 | Heartbeat option added (heartbeatEnabled, heartbeatInterval). Heartbeat and script-load messages now sent to all players in-game. Script-load message also logged. |
| v2.1 | Removed redundant isExist() and getCategory() checks (simplified guard chain); namespaced config/state into ZAA table; airbase cache now documented as geographical proximity |