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.
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.