fix(cockpit): voice entry in an orbital view is refused before it touches tracking

This commit is contained in:
Sameh Khamis committed 2026-11-08 15:55:02 -08:00
1 parent a5df391d6c
commit 5c25bc54e6
3 files changed
+28 -2

No files matched your search

+2 -2
View File
@@ -1538,8 +1538,8 @@ HUD on, in its Tactical and Cyber layouts). Turning Live AIS Vessels off ends
the bridge: the layer then has no subject (`getCockpitSubject` returns null). the bridge: the layer then has no subject (`getCockpitSubject` returns null).
The bridge picture uses AIS alone, so no other feed being off makes it partial. The bridge picture uses AIS alone, so no other feed being off makes it partial.
Voice (`control_cockpit`) and the selection entry transaction stay aircraft-only; Voice (`control_cockpit`) and the selection entry transaction stay aircraft-only;
voice `enter` on a bridge is refused before it touches tracking, with the voice `enter` on a bridge or in an orbital view is refused before it touches
reason to exit the bridge first. tracking, with the reason to exit it first.
The vessel layer supplies the subject (`getCockpitSubject`), hides that ship's The vessel layer supplies the subject (`getCockpitSubject`), hides that ship's
sprite, card, detection bracket and trail while it is held sprite, card, detection bracket and trail while it is held
(`setCockpitSubject`), and (`setCockpitSubject`), and
+6
View File
@@ -189,6 +189,12 @@ export class CockpitCoordinator {
// vessel selection before the entry can run, leaving neither. // vessel selection before the entry can run, leaving neither.
if (this.cockpitView?.active && this.cockpitView.subjectKind === 'vessel') if (this.cockpitView?.active && this.cockpitView.subjectKind === 'vessel')
return 'Cockpit is on a vessel bridge — exit the bridge first, then track an aircraft to enter Cockpit'; return 'Cockpit is on a vessel bridge — exit the bridge first, then track an aircraft to enter Cockpit';
// Likewise in orbit: the aircraft's tracking takes the satellite's.
if (
this.cockpitView?.active &&
this.cockpitView.subjectKind === 'satellite'
)
return 'Cockpit is in an orbital view — exit it first, then track an aircraft to enter Cockpit';
if (!this._aircraftLayerEnabled) if (!this._aircraftLayerEnabled)
return 'No aircraft layer is on — turn on Flights or Military Flights and track an aircraft to enter Cockpit'; return 'No aircraft layer is on — turn on Flights or Military Flights and track an aircraft to enter Cockpit';
return null; return null;
+20
View File
@@ -246,6 +246,26 @@ test('voice entry on a vessel bridge refuses before it touches tracking', (t) =>
assert.equal(cockpit.subjectKind, 'vessel'); assert.equal(cockpit.subjectKind, 'vessel');
}); });
test('voice entry in an orbital view refuses before it touches tracking', (t) => {
const { coordinator, cockpit } = fixture(t, { enabled: ['flights'] });
let navigated = false;
coordinator.services.militaryAwarenessLayer.navigateNext = () => {
navigated = true;
return true;
};
cockpit.active = true;
cockpit.subjectKind = 'satellite';
t.after(() => {
cockpit.active = false;
cockpit.subjectKind = null;
});
const voice = coordinator.controlCockpit('enter', { targetLayer: 'flights' });
assert.equal(voice.ok, false);
assert.match(voice.error, /orbital view/);
assert.equal(navigated, false, 'no aircraft was tracked');
assert.equal(cockpit.subjectKind, 'satellite');
});
test('with an aircraft layer on but nothing tracked, the reason is the missing aircraft', (t) => { test('with an aircraft layer on but nothing tracked, the reason is the missing aircraft', (t) => {
const { coordinator } = fixture(t, { enabled: ['military'] }); const { coordinator } = fixture(t, { enabled: ['military'] });
assert.equal( assert.equal(