Electronic Attack (EA)¶
AEGIS models electronic attack as physics-based jamming from opposing coalition aircraft. EA aircraft use the EA- naming prefix and suppress the IADS through two layers: EW contact filtering (per-contact angular masking at the EW antenna) and SAM binary suppression (jammed EMCON cycling). AI jammers auto-discover at mission start. Player jammers discover via S_EVENT_BIRTH. On by default (eaEnabled = true).
v0.8.4 Changes
This page reflects v0.8.4 EA behavior. Key changes from v0.8.3: simplified JAMMER_DB (GROWLER + HERC + UNKNOWN), per-system trackingBias replacing global samTrackingBias, and separate EW burn-through formula (ewBeta).
Singleplayer EA Setup
EA in singleplayer requires v0.8.2+. Your EA aircraft exists at mission start and AEGIS initially registers it as AI — the script automatically upgrades it to player-controlled when you spawn in.
Slotting behavior: DCS singleplayer slot-change events are unreliable. If the F10 EA menu or GUI doesn't appear on your first slot-in, slot out to a non-EA aircraft and then slot back into the EA jet. This forces a clean S_EVENT_BIRTH cycle. Once connected, it stays connected for the session.
EA GUI overlay requires one additional step: desanitize require and package in your MissionScripting.lua (same edit needed for SRS/DCS-gRPC). Without this, the mission-side UDP socket can't load and the GUI won't connect.
-- In DCS World/Scripts/MissionScripting.lua, comment out these two lines:
--_G['require'] = nil
--_G['package'] = nil
DCS updates may overwrite MissionScripting.lua — check after every patch.
Theory of Operations¶
The AEGIS EA model operates at two processing layers because of a fundamental DCS constraint: we have full per-contact control at the EW radar feed, but only binary on/off control at the SAM level. DCS AI handles SAM target selection when the radar is on — there is no ignoreTarget() API.
Layer 1 — EW Contact Filtering¶
When a jammer is active within range of an EW radar, AEGIS filters the EW's contact feed before passing it downstream to sector SAMs. This is where directional geometry lives.
_GetEWJamState(ew)computes all jam effects on a specific EW — one effect record per jammer (bearing, burn-through distance, pie width).- For each contact in the EW's
getDetectedTargets()return,_IsContactJammed(ew, contactPos, effects)checks:- Is the contact inside any jammer's angular "pie" (as seen from the EW)?
- If yes: apply cosine gradient from boresight to pie edge, compute effective burn-through at that angle.
- Contact closer than burn-through passes (radar power wins). Contact farther is masked (jammer noise wins).
- Masked contacts are dropped before they ever reach the SAM activation logic. The SAM never gets cued, never goes ALERT, DCS AI never engages.
Even omni jamming creates directional masking because the EW antenna only receives strongly from one bearing at a time. Pie width scales with power density at the EW — more focused beam = more power = wider shadow. OMNI creates a narrow pie (±25°), WIDE presets scale from ±30° (W90) to ±45° (W50), and DIR creates the widest pie (±60°) with deepest suppression. Contacts outside the pie pass completely unaffected.
Range-dependent pie narrowing: The masking pie shrinks linearly with distance beyond ewPieRefDist (default 45 NM). A jammer at 90 NM masks half the angular width of one at 30 NM. Formula: effectivePie = basePie × min(1.0, 45/dist).
The C2 Path — Sector Jam Warning¶
When an EW detects a jammer (noise floor rise), it sets sector.jammed = true and sector.jamBearing. This warning flows down the same C2 channel that feeds contacts and HARM warnings. DARK and AWARE SAMs in the jammed sector start EMCON cycling — the same autonomous behavior as if the EW were killed. The EW is still alive and still feeding contacts that survive the jam filter, but the degraded picture triggers SAM autonomy.
This is the core SOJ tradeoff: you blind the EW, but you wake up the SAMs. They start peeking independently with randomized timing, making the ingress corridor unpredictable. When the jammer leaves, the next EW poll cycle restores the feed, sector.jammed clears, and SAMs return to network-integrated behavior.
Layer 2 — SAM Binary Suppression¶
Any SAM that peeks (emits radar) while a jammer is within range gets checked by _IsJammed(sam). If jammed, after a 1-3s crew detection delay, the SAM enters jammed EMCON cycling — a separate timer chain from normal EMCON (jammedEmconGen vs emconGen):
- On-phase: Brief radar peek. During this window,
_JammedEmconOnPhasechecks if any contact is inside burn-through range. If yes, SAM stays ALERT and engages (burn-through kill). If no, goes dark. - Off-phase: Radar off, hiding from jammer. Then the cycle repeats.
Each SAM system has a per-system trackingBias field in SYSTEM_DB that scales burn-through range, allowing differentiated resistance (e.g., SA-10 harder to jam than SA-6). The global default samTrackingBias = 1.0 applies when no per-system value is set. Contacts at 20 NM burn through easily against most systems.
Priority Chain¶
1. HARM cooldown (harmCooldownUntil) — highest, never overridden
2. Jammed EMCON (jammedEmconActive) — jammer in range
3. Normal state machine — poll evaluation
Jammed EMCON uses its own generation counter (jammedEmconGen), independent of normal EMCON (emconGen). _StopEMCON() is called before starting jammed EMCON to prevent timer conflicts.
DCS Scripting Constraints
Several design decisions are bounded by what the DCS scripting API allows. Understanding these explains why the architecture works the way it does.
No per-contact SAM engagement control. DCS ground AI ROE is binary: shoot everything (OPEN_FIRE) or shoot nothing (WEAPON_HOLD). There is no ignoreTarget() — when a SAM's radar is on, DCS AI picks targets autonomously. This is why EA has two layers: we have per-contact control at the EW feed (filter before the SAM ever sees it), but only on/off at the SAM itself.
No passive track injection. Real HOJ means the SAM passively tracks the jammer's noise source. DCS has no API to create bearing-only tracks or direct a SAM to engage a specific contact. HOJ is modeled as a jam immunity window — suppression lifts, the SAM goes weapons-free, and DCS AI handles targeting. The jammer dies because the jam stopped protecting it, not because the SAM homed on the signal. The gameplay effect is identical.
No jammer pod state. DCS has no flyable ECM aircraft and the scripting API doesn't expose pod state. We can't detect whether a player's jammer is physically on. Activation is manual (F10 menu or GUI), and jammer capability comes from the group naming convention — any airframe can fly the EA role.
Separate Lua VMs on dedicated server. The standard net.dostring_in("mission", ...) hook-to-mission bridge accesses a different Lua VM from trigger-loaded scripts on dedicated servers. AEGIS mission globals are invisible to hooks. The EA GUI works around this with a mission-side UDP socket in the same VM as AEGIS, which is why it requires MissionScripting.lua desanitization for LuaSocket access.
SP vs MP slot lifecycle. In multiplayer, client aircraft don't exist until a player joins — event-driven discovery works cleanly. In singleplayer, the aircraft pre-exists at mission start and gets registered as AI before the player spawns in. The script auto-upgrades on spawn, but DCS singleplayer doesn't fire onPlayerChangeSlot, making the handoff less reliable than MP.
Jammer Modes¶
| Mode | Pods | Coverage | Gain | Use Case |
|---|---|---|---|---|
| OMNI | 2 barrage | Full sphere | 0.40x | Area denial, strike escort |
| WIDE | 1 cone + 1 directional | Configurable cone | 0.57-0.79x | Focused area + targeted |
| 2xDIR | 2 directional | 2 independent targets | 2.00x | Precision suppression |
| OFF | — | ESM only (passive) | — | Threat detection without jamming |
AI jammers default to OMNI. Player jammers default to OFF — the WSO manages modes and pod assignments via F10 menu or the EA GUI overlay.
WIDE Presets¶
WIDE mode uses one pod as a configurable cone and the other as a focused directional beam. Presets trade coverage for penetration:
| Preset | Cone | Gain | EW Pie Mask | Coverage |
|---|---|---|---|---|
| W90 | ±45° | 0.57x | ±30° | Maximum area, weakest power per EW |
| W70 | ±35° | 0.66x | ±37° | Default balance |
| W50 | ±25° | 0.79x | ±45° | Tightest beam, strongest power per EW |
Gain is derived from beam half-angle: 0.4 / (1 - cos(θ))^0.29 — a narrower beam means more concentrated power. The WIDE cone direction is set by bearing: in the GUI the WSO types a bearing (1° resolution) and presses SET; in the F10 menu the SET BRG submenu offers 12 presets at 30° spacing (see below).
F10 Menu¶
The WSO can drive the jammer entirely from the F10 radio menu — no GUI required. Each player jammer gets a per-group menu:
F10 > EA: <jammer> >
FULL OMNI full-sphere barrage (both pods)
WIDE >
W90 / W70 / W50 cone preset (coverage vs penetration)
LOCK BRG lock the cone to current aircraft heading
SET BRG > Mode: REL | ABS (toggle), then a bearing:
000° 030° 060° ... 330° 12 presets at 30° spacing
CAL MAG capture current heading as magnetic declination
Pod 2 target > ... assign the directional pod
2xDIR >
Pod 1 target / Pod 2 target
OFF ESM only (passive)
STATUS mode, pod assignments, bearings, emitter list
SET BRG gives quick 30° bearing control without the GUI; finer (1°) resolution stays in the GUI text box. The REL/ABS toggle selects whether a preset is relative to the aircraft's nose or an absolute magnetic bearing — absolute requires CAL MAG first. F10 and the GUI share state: calibrate or set a bearing in one and it shows up in the other on the next poll.
Burn-Through Physics¶
Burn-through range determines where radar power overcomes jammer noise. The formula:
| Term | Source | Effect |
|---|---|---|
burnRange |
SAM's WEZ or EW detection range | Bigger SAM = harder to suppress at range |
ratio |
burnThroughRatio (0.35) |
Baseline: 35% of reference range |
gainMult |
_BeamGain(halfAngle) |
Narrow beam = lower spread = deeper penetration |
mult |
JAMMER_DB per-type (Growler 1.0, Herc 1.3, etc.) |
Platform effectiveness |
dist / maxRange |
Jammer-to-target distance (maxRange = effectRange × gain-scaled range mult, capped at directionalRangeMult) |
Closer jammer = stronger suppression |
exponent |
burnExponent (0.5 = √R) |
Physics-based distance falloff |
SAM tracking radars scale burn range via per-system trackingBias (from SYSTEM_DB, default samTrackingBias = 1.0). The EW layer uses a separate simplified formula: BT = ewBeta / (gainMult × mult) × √dist with ewBeta = 1.8.
Practical effect: An SA-10 (WEZ 39 NM) only loses the outer ~21% of its engagement envelope to omni jamming at max jammer range. Contacts at 20 NM burn through easily.
Jammed EMCON Cycle¶
When a SAM detects jamming, it enters a suppression cycle:
SAM emitting (ALERT, EMCON_OFF, or EMCON_ENGAGED)
-> Jammer in range detects emission (1-3s delay)
-> Crew recognizes jamming -> shuts down (DARK)
-> Enters jammed EMCON cycling:
-> Off-phase: hiding from jammer
-> On-phase: brief radar peek
-> During jam detection window (1-3s): targets inside burn-through range engageable
-> Burn-through contact found -> SAM stays ALERT (monitored every 5s)
-> Contacts leave burn-through range -> back to off-phase
-> No burn-through -> jammer catches emission -> crew goes dark again
-> Jammer leaves/dies -> next on-cycle, no jam detected -> exit jammed EMCON
-> Poll restores normal state (EW alive -> ALERT, EW dead -> normal EMCON)
Differentiated Timing¶
SAMs behave differently under jamming based on capability:
| Capability | On-Phase (Peek) | Off-Phase (Hide) | Behavior |
|---|---|---|---|
| HOJ-capable (SA-10, SA-11, SA-12, SA-17, SA-20, SA-21, SA-23, PATRIOT) | 12-25s | 20-45s | Aggressive — seeking HOJ lock |
| Standard (SA-2, SA-3, SA-5, SA-6, SA-8, SA-15, TOR) | 5-10s | 60-150s | Cautious — survival mode |
HOJ-capable SAMs peek longer and more often because each peek has tactical value — they might burn through or trigger HOJ. Standard SAMs peek briefly because exposure just invites HARMs.
Home-on-Jam (HOJ)¶
Modern SAMs with homeOnJam = true in SYSTEM_DB can break through jamming using passive tracking. Each jammed EMCON peek, the SAM rolls for HOJ:
- 7% base probability, escalating +7% per consecutive peek (#1=7%, #2=14%, #3=21%...)
- On success: 75-120s jam immunity window —
_IsJammed()returns false, SAM goes weapons-free - After window expires: 60s cooldown before re-roll eligible
- Peek count resets on re-entry to jammed EMCON
HOJ-capable systems: SA-10, SA-11, PATRIOT, SA-12, SA-12G, SA-17, SA-20A, SA-20B, SA-21, SA-23, SA-23G, SA-23V4, SA-23V4G
Risk Curve for EA Pilots¶
- SOJ (50+ NM): Few peeks reach the jammer, low probability per peek. Relatively safe but weaker suppression.
- SIJ (15-25 NM): More frequent peeks (shorter hide time at close range), higher cumulative HOJ probability. Stronger suppression but you might eat an SA-10 missile.
- The skill expression: Managing standoff distance vs suppression effectiveness.
Disable with hojEnabled = false.
Passive ESM¶
The ESM receiver is independent of jammer transmit state — the emitter list populates in all modes including OFF. This enables an ESM-first workflow: observe threats before committing to a jam mode.
Each emitter displays:
- NATO radar name — from
SYSTEM_DB.srLabel(e.g., SA-2 = "Fan Song", SA-6 = "Straight Flush", SA-10 = "Big Bird"). PD/SHORAD without distinctive radar show system designator (SA-8, SA-15). EW radars show "EW". - Signal strength — 5-bar scale based on distance and emitter power:
|||||(closest) to|....(farthest) - Relative bearing — off the nose (0° = dead ahead). GUI respects ABS/REL mode toggle.
- Range estimate — builds over time via non-deterministic per-cycle rolls weighted by proximity. NONE → LOW (±20 NM band, e.g.,
40-80) → MED (±10 NM band, e.g.,40-60) → HIGH (~5 NM, e.g.,~48). Stale emitters show?suffix and decay one confidence level per 150s. - Pod assignment — P1/P2 if assigned
DIR pod bearing: Pod assignment labels show bearing to target in F10 STATUS, GUI panel, and map markers. Bearing is position-based — stays live even when target stops emitting.
Stale emitters: ~~~~~ replaces bars when a radar goes silent. Last-known bearing updates as the jammer orbits. Persists for eaEmitterMemory seconds (default 60). Destroyed emitters drop immediately.
EA GUI Overlay (Optional)¶
An optional clickable panel replaces the nested F10 menu workflow for EA pilots — one-click mode switching, pod assignment, emitter tracking, and bearing input without pausing to navigate menus. Completely optional — players without it use F10 menus with no loss of functionality.
- Server auto-discovery — SRS-style chat message auto-connect
- Copilot/WSO support — slot-based lookup resolves non-pilot crew seats
- F10 and GUI stay in sync — either interface can control the jammer
- Toggle with Ctrl+Shift+J (configurable)
See the EA GUI Overlay page for installation, configuration, and troubleshooting. Download files from the Downloads page.
Mission Maker Reference¶
Setup¶
EA works out of the box with eaEnabled = true (the default). Name your EA aircraft on the opposing coalition using the EA- prefix:
EA-GROWLER-1 Growler, auto-discovers at mission start
EA-GROWLER-SOUTH-2 Growler in SOUTH sector
EA-HERC-NORTH-1 C-130 Compass Call jammer
AI EA aircraft auto-discover. Player EA aircraft discover when the player spawns. Unrecognized type names (anything not GROWLER or HERC) fall back to UNKNOWN (mult 0.5).
JAMMER_DB¶
Each jammer type has a platform effectiveness multiplier:
| Type | mult | Notes |
|---|---|---|
| GROWLER | 1.0 | Baseline — EA-18G |
| HERC | 1.3 | EC-130H Compass Call — more power, bigger airframe |
| UNKNOWN | 0.5 | Fallback for unrecognized types |
JAMMER_BASELINE Overrides¶
All physics parameters are tunable via jammerBaseline = { ... } table merge in AEGIS:New(). Only specify fields you want to change — partial overrides are supported:
local iads = AEGIS:New({
jammerBaseline = {
effectRange = 70, -- default 60 NM
burnThroughRatio = 0.40, -- default 0.35
samTrackingBias = 1.2, -- default 1.0
}
})
Key fields: effectRange, burnThroughRatio, burnExponent, directionalRangeMult, samTrackingBias, ewBeta
Configuration Summary¶
Key config knobs for EA behavior:
| Parameter | Default | Description |
|---|---|---|
eaEnabled |
true |
Master EA toggle |
eaDebugLabels |
false |
Show full emitter names (debug) |
eaEmitterMemory |
60 |
Stale emitter retention (seconds) |
jamDetectionDelayMin/Max |
1/3 |
Crew jam detection delay (seconds) |
jamEmconOnMinHOJ/MaxHOJ |
12/25 |
HOJ SAM peek duration (seconds) |
jamEmconOffMinHOJ/MaxHOJ |
20/45 |
HOJ SAM hide duration (seconds) |
jamEmconOnMinStd/MaxStd |
5/10 |
Standard SAM peek duration (seconds) |
jamEmconOffMinStd/MaxStd |
60/150 |
Standard SAM hide duration (seconds) |
hojEnabled |
true |
Home-on-Jam toggle |
hojBasePct |
0.07 |
HOJ base probability per peek |
ewPieRefDist |
45 |
NM: full pie width inside this range, linear falloff beyond |
esmRevealChance |
0.10 |
Base probability per cycle to advance range confidence |
esmRevealRefDist |
45 |
NM: range reveal at full chance inside this distance |
esmDecayInterval |
150 |
Seconds per confidence level lost while stale |
See the Tuning Guide for full parameter reference and behavioral effects.