API changelog
This page documents breaking changes and new features in the scripting API. If your scripts stop working after an update, check here for migration guides.
1.7.1 - API improvements
Named parameters
All multi-parameter methods now accept an object as an alternative to positional arguments. Named parameters are clearer and reduce ordering mistakes.
// Positional (still works)
aircraft.hold('MERIT', { legNm: 10, turn: 'L' });
aircraft.sta('MERIT', 3600);
aircraft.crossFix('GREKI', 200);
aircraft.over('MERIT', (ac) => ac.handover());
aircraft.before('KMART', 30, (ac) => ac.descend(fl(240)));
// Named (new)
aircraft.hold({ fix: 'MERIT', legNm: 10, turn: 'L' });
aircraft.sta({ fix: 'MERIT', time: 3600 });
aircraft.crossFix({ fix: 'GREKI', altFt: 200 });
aircraft.over({ waypoint: 'MERIT', callback: (ac) => ac.handover() });
aircraft.before({ waypoint: 'KMART', distanceNm: 30, callback: (ac) => ac.descend(fl(240)) });Methods with named overloads: hold, sta, crossFix, over, before.
direct() array form
direct() now accepts a single array in addition to variadic arguments.
aircraft.direct("KMART", "ROBUC"); // variadic (existing)
aircraft.direct(["KMART", "ROBUC"]); // array (new)Case-insensitive identifiers
All waypoint names, runway IDs, and sector identifiers are now case-insensitive. aircraft.direct("merit") and aircraft.direct("MERIT") produce identical results.
crossFix() on aircraft
crossFix(fix, altFt) is now available directly on the aircraft object (previously only via center API).
aircraft.crossFix({ fix: 'GREKI', altFt: 200 });Pilot readbacks for procedures
descendVia, climbVia, cancelProcedure, and crossFix commands now generate proper pilot readbacks instead of generic "roger". Readbacks vary by pilot personality and verbosity.
"American one two three, descending via the RAVNN8 arrival"
"Cancel restrictions, Delta seven eight niner"
"Cross GREKI at flight level two four zero, Southwest one two three"1.6.0 - SID/STAR procedure execution
Aircraft on SIDs and STARs now carry published altitude and speed constraints. Controllers can manage procedure compliance through new interactive commands and scripting APIs.
Interactive commands
| Command | Description |
|---|---|
dv | Descend via STAR |
cv | Climb via SID |
xp | Cancel procedure restrictions |
x FIX ALT | Cross fix at altitude (e.g., x GREKI 240) |
Scripting API - aircraft methods
aircraft.descendVia(); // Follow STAR constraints
aircraft.climbVia(); // Follow SID constraints
aircraft.cancelProcedure(); // Cancel restrictions (can re-engage later)
aircraft.crossFix('GREKI', 20000); // Override one constraintINFO
The center.* methods were deprecated in 1.7.1. Use aircraft instance methods instead (e.g., aircraft.descendVia() instead of center.descendVia('AAL123')).
Procedure data API
Look up any SID or STAR to see its waypoints, altitude and speed constraints.
onTick(({ procedures }) => {
const star = procedures.getSTAR('PARCH4');
// { id, airport, runways, waypoints, altitudeConstraints, speedConstraints }
const allStars = procedures.allSTARs();
const allSids = procedures.allSIDs();
const byName = procedures.get('DEEZZ5'); // Checks both SIDs and STARs
});Aircraft procedure state
aircraft.procedureState is now readable on every aircraft object:
const ps = aircraft.procedureState;
// { procedureId, procedureType, viaActive, constraints: [{ fix, altType, alt1, satisfied, busted }] }Event callbacks
| Callback | When it fires |
|---|---|
onConstraintSatisfied(event) | Aircraft met a constraint at a fix |
onConstraintBusted(event) | Aircraft failed a constraint |
onProcedureComplete(event) | All constraints resolved (with satisfied/busted counts) |
Constraint validation
Constraints are automatically validated when aircraft cross fix waypoints. Results update the procedureState.constraints array and emit events.
- AT: within 200ft tolerance
- AT_OR_ABOVE: crossing altitude >= target
- AT_OR_BELOW: crossing altitude <= target
- BETWEEN: within altitude window
- Speed: 10kt tolerance for "at", 5kt for "at or below"
Scoring
- +40 per satisfied constraint
- -60 per busted constraint
- +100 bonus for completing a procedure with zero busts
Radar UI
- Constraint markers on route waypoints (ring + altitude annotation)
- Green = satisfied, red = busted, blue = upcoming
- Procedure badge on aircraft label when via is active
- Procedure info in flight strip detail panel with docsite link
Final approach sequence query
traffic.onFinal() returns a sorted sequence of aircraft on approach, closest to threshold first. Filter by runway with traffic.onFinal('27L').
Each entry: { aircraft, state, distanceToThresholdNm, groundspeedKts }
States: vectoring → intercepting → established → final → landing
onTick(({ traffic }) => {
const seq = traffic.onFinal('27L');
for (const e of seq) {
log(`${e.aircraft.cs} ${e.state} ${e.distanceToThresholdNm}nm ${e.groundspeedKts}kts`);
}
});1.5.3 - Handoff lifecycle events
Six new event callbacks for the full handoff state machine. Scripts can now react to every stage of the handoff process.
| Callback | When it fires |
|---|---|
onHandoffOffered(event) | Handoff initiated to adjacent sector |
onHandoffAccepted(event) | Receiving controller accepted |
onHandoffRejected(event) | Receiving controller rejected (with reason) |
onHandoffFrequencyChange(event) | Pilot told to contact next frequency |
onHandoffTransferred(event) | Aircraft ownership transferred |
onApproachingExit(event) | Aircraft within 30nm of exit point |
onApproachingExit((event) => {
log(`${event.cs} approaching ${event.exitFix} - ${event.distanceNm}nm out`);
// Initiate handoff
});
onHandoffAccepted((event) => {
log(`${event.cs} accepted by ${event.toSector}`);
});1.5.2 - Comms interference model
Realistic radio communications interference based on traffic density. As more aircraft are on frequency, the probability of blocked transmissions (stepped-on calls) increases - up to 8% at 25+ aircraft in sector.
Pilot skill level error rates tuned to realistic baselines (EUROCONTROL readback studies, FAA/CAST). Use sim_readback_error_rate_multiplier (default 5x) for training visibility.
1.5.1 - Progressive difficulty ramp
Traffic can now build non-linearly over session time, simulating a realistic morning push. Enable it in settings or via the spawn scheduler.
Behavior:
- 0-10 minutes: 3-minute intervals (~20 ops/hr, light)
- 10-20 minutes: ramp from 3 min to 2 min (~30 ops/hr, moderate)
- 20-30 minutes: ramp from 2 min to 90 sec (~40 ops/hr, busy)
- 30+ minutes: hold at 90 sec (sustained high workload)
The ramp is non-linear - traffic builds in bursts, not a smooth slope, matching how real-world push periods develop.
1.5.0 - New aircraft methods and events
The following methods are now available on aircraft objects, closing the gap between interactive commands and the scripting API. All methods return this for chaining.
aircraft.setRoute(fixes)
Set a new multi-waypoint route.
aircraft.setRoute(['MERIT', 'GREKI', 'JUDDS']);Previously, you had to issue multiple aircraft.direct() calls.
aircraft.hold(fix, options?)
Enter a holding pattern at a waypoint.
// Default: 4nm legs, right turns
aircraft.hold('MERIT');
// Custom options
aircraft.hold('GREKI', { legNm: 8, turn: 'L', efc: 3600 });aircraft.exitHold()
Exit a holding pattern and resume route navigation.
aircraft.exitHold();aircraft.sta(fix, time)
Assign scheduled time of arrival at a waypoint.
aircraft.sta('MERIT', 3600);aircraft.clearILS(runwayId)
Clear the aircraft for an ILS approach.
aircraft.clearILS('27L');aircraft.contactTower()
Hand the aircraft off to tower frequency.
aircraft.contactTower();aircraft.goAround()
Initiate a go-around / missed approach.
aircraft.goAround();Full approach sequence example
onTick(({ traffic }) => {
for (const ac of traffic.all()) {
if (ac.altFt < 4000 && !ac.isOnApproach) {
ac.clearILS('27L');
}
}
});
onILSEstablished((event) => {
log(`${event.cs} established on ILS ${event.runway}`);
});
onLanding((event) => {
log(`${event.cs} landed on ${event.runway}`);
});New event callbacks
Seven new event callbacks are now available for event-driven scripting. Register them the same way as onTick or onSpawn.
onApproachCleared(event)
Fired when an aircraft is cleared for an ILS approach.
onApproachCleared((event) => {
log(`${event.cs} cleared ILS ${event.runway}`);
});Event object: { cs, runway, airport }
onILSEstablished(event)
Fired when an aircraft captures the ILS localizer and glideslope.
onILSEstablished((event) => {
log(`${event.cs} established on ${event.runway}`);
// Good time to hand off to tower
});Event object: { cs, runway }
onTowerContact(event)
Fired when an aircraft is handed off to tower frequency.
onTowerContact((event) => {
log(`${event.cs} now on tower frequency`);
});Event object: { cs, runway }
onLanding(event)
Fired when an aircraft touches down.
onLanding((event) => {
log(`${event.cs} landed on runway ${event.runway}`);
});Event object: { cs, runway, airport }
onGoAround(event)
Fired when an aircraft initiates a go-around.
onGoAround((event) => {
log(`${event.cs} going around!`);
// Re-sequence the aircraft
});Event object: { cs, runway }
onUnableILS(event)
Fired when an ILS clearance cannot be executed (wrong altitude, too far, etc).
onUnableILS((event) => {
log(`${event.cs} unable ILS ${event.runway}: ${event.reason}`);
});Event object: { cs, runway, reason }
onAircraftRemoved(event)
Fired when an aircraft leaves the airspace (handoff complete, landing, etc).
onAircraftRemoved((event) => {
log(`${event.callsign} removed: ${event.reason}`);
});Event object: { callsign, reason }
Summary of all available callbacks
| Callback | When it fires |
|---|---|
onTick(ctx) | Every simulation frame |
onSpawn(aircraft) | Aircraft enters airspace |
onConflict(pair) | Potential conflict detected |
onMeterAlert(fix) | Metering threshold crossed |
onHandoffRequest(req) | Incoming handoff request |
onDepartureControllable(ac) | Departure above 10,000ft |
onDeviationRequest(req) | Pilot requests weather deviation |
onApproachCleared(event) | Aircraft cleared for approach |
onILSEstablished(event) | Aircraft on ILS |
onTowerContact(event) | Aircraft handed to tower |
onLanding(event) | Aircraft touched down |
onGoAround(event) | Go-around initiated |
onUnableILS(event) | ILS clearance failed |
onAircraftRemoved(event) | Aircraft left airspace |
No breaking changes
All existing scripts continue to work without modification. The new methods and events are additive - no existing API was changed or removed.