Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0d3ab5b
aircraft: add PilotAltim fields and SimulatePilotAltimeter toggle
Jud6969 Apr 17, 2026
fc37b38
sim: add altimeter bias helpers
Jud6969 Apr 17, 2026
19f6f6a
nav: plumb altimBiasFeet parameter through Update call chain
Jud6969 Apr 17, 2026
4bf756d
sim: compute altimeter bias per tick and pass to aircraft Update
Jud6969 Apr 17, 2026
4bafd1e
sim: initialize PilotAltim at aircraft spawn
Jud6969 Apr 17, 2026
6e2e88a
sim: add altimeter readback transmission type and intent
Jud6969 Apr 17, 2026
77f6ea3
sim: handle altimeter setting command from controllers
Jud6969 Apr 17, 2026
f8565b7
stt: extract altimeter setting value from transmissions
Jud6969 Apr 17, 2026
1538165
stt+sim: dispatch ALT command to handleAltimeterSetting
Jud6969 Apr 17, 2026
7e18e56
test: end-to-end altimeter bias and readback correction
Jud6969 Apr 17, 2026
f3610a0
stt: extract altimeter setting mid-sentence and dispatch when sole co…
Jud6969 Apr 17, 2026
f090a92
N90: enable simulate_pilot_altimeter
Jud6969 Apr 17, 2026
d4d9196
sim+nav: report indicated altitude in SayAltitude
Jud6969 Apr 17, 2026
37947d2
sim+aviation: integrate altimeter readback into bulk transmissions
Jud6969 Apr 17, 2026
a9f4786
sim: tune pilot altimeter when controller issues ATIS letter
Jud6969 Apr 17, 2026
edcdf2c
altim: enable pilot altimeter simulation by default
Jud6969 Apr 17, 2026
b185e48
sim: show pilot altimeter and indicated altitude in paused hover
Jud6969 Apr 20, 2026
4bebc24
sim: collapse repeated PilotAltim+SetAt writes into a helper
Jud6969 Apr 20, 2026
05ba6d0
sim: make incorrect altimeters configurable in sim creation
Jud6969 Apr 20, 2026
357fd28
sim: replace altimeter toggle with probability slider, add faulty tra…
Jud6969 Apr 20, 2026
401e62b
sim: default faulty transponder chance to 5%
Jud6969 Apr 20, 2026
b31a101
sim+stt+nav+av: add stop-altitude-squawk and report-reaching commands
Jud6969 Apr 20, 2026
c73ffb8
sim: dispatch RR{alt} under case 'R' and scale altitude
Jud6969 Apr 20, 2026
e9a745b
sim: don't flag reaching-altitude report as unexpected
Jud6969 Apr 20, 2026
e92a232
sim: render reaching-altitude report as a readback-style advisory
Jud6969 Apr 20, 2026
2719cb0
stt: block say<->stop fuzzy match
Jud6969 Apr 20, 2026
a015c2f
nav: pass 0 altimBiasFeet to UpdateWithWeather in hold tests
Jud6969 May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions aviation/intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,38 @@ func (t TransponderIntent) Render(rt *RadioTransmission, r *rand.Rand) {
}
}

// StopAltitudeSquawkIntent represents the pilot acknowledging a "stop
// altitude squawk" command (controller has observed the Mode C readout
// disagrees with the pilot-reported altitude). The aircraft switches from
// Mode C to Mode A.
type StopAltitudeSquawkIntent struct{}

func (StopAltitudeSquawkIntent) Render(rt *RadioTransmission, r *rand.Rand) {
rt.Add("[stopping altitude squawk|stop altitude squawk]")
}

// ReportReachingIntent represents the pilot acknowledging a "report
// reaching (altitude)" instruction. The actual reaching-the-altitude call
// is issued later when the aircraft levels off.
type ReportReachingIntent struct {
Altitude float32
}

func (r ReportReachingIntent) Render(rt *RadioTransmission, rnd *rand.Rand) {
rt.Add("[wilco|will do|will report reaching {alt}]", r.Altitude)
}

// ReachingAltitudeIntent is the unsolicited pilot transmission fired when
// the aircraft levels off at a previously requested "report reaching"
// altitude.
type ReachingAltitudeIntent struct {
Altitude float32
}

func (r ReachingAltitudeIntent) Render(rt *RadioTransmission, rnd *rand.Rand) {
rt.Add("[reaching|leveling off at|level] {alt}", r.Altitude)
}

///////////////////////////////////////////////////////////////////////////
// Special Intents

Expand Down Expand Up @@ -1018,6 +1050,20 @@ func (m MixUpIntent) Render(rt *RadioTransmission, r *rand.Rand) {
rt.Add("sorry, was that for {callsign}?", csArg)
}

///////////////////////////////////////////////////////////////////////////
// AltimeterReadback Intent

// AltimeterReadbackIntent renders a pilot's readback of an altimeter setting
// issued by the controller, e.g., "altimeter three zero zero two".
type AltimeterReadbackIntent struct {
SettingHundredths int // e.g., 3002 for 30.02
}

func (a AltimeterReadbackIntent) Render(rt *RadioTransmission, r *rand.Rand) {
digits := sayDigits(a.SettingHundredths, 4)
rt.Add("[altimeter " + digits + "|" + digits + "|roger " + digits + "]")
}

///////////////////////////////////////////////////////////////////////////
// LookForFieldIntent

Expand Down
12 changes: 12 additions & 0 deletions cmd/vice/simconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,18 @@ func (c *NewSimConfiguration) DrawConfigurationUI(p platform.Platform, config *C
imgui.SetNextItemWidth(200)
imgui.SliderFloatV("##errorInterval", &c.PilotErrorInterval, 0, 30,
util.Select(c.PilotErrorInterval == 0, "never", "%.1f min"), imgui.SliderFlagsNone)

imgui.Text("Incorrect altimeter chance:")
imgui.SameLine()
imgui.SetNextItemWidth(200)
imgui.SliderFloatV("##altimChance", &c.NewSimRequest.IncorrectAltimeterChance, 0, 100,
util.Select(c.NewSimRequest.IncorrectAltimeterChance == 0, "off", "%.0f%%"), imgui.SliderFlagsNone)

imgui.Text("Faulty transponder chance:")
imgui.SameLine()
imgui.SetNextItemWidth(200)
imgui.SliderFloatV("##xpndrChance", &c.NewSimRequest.FaultyTransponderChance, 0, 100,
util.Select(c.NewSimRequest.FaultyTransponderChance == 0, "off", "%.0f%%"), imgui.SliderFlagsNone)
imgui.Spacing()

// WEATHER & TIME section
Expand Down
18 changes: 9 additions & 9 deletions nav/alt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ func TestAssignAltitudeDelaysVerticalGuidance(t *testing.T) {
}

wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.AssertLevelFlight()

f.simTime = f.nav.Altitude.ActivateAt
wxs = f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)

if f.nav.Altitude.ActiveAssigned == nil || *f.nav.Altitude.ActiveAssigned != 3000 {
t.Fatalf("expected ActiveAssigned=3000 after delay, got %v", f.nav.Altitude.ActiveAssigned)
Expand Down Expand Up @@ -70,7 +70,7 @@ func TestAssignAltitudeKeepsPreviousActiveAltitudeDuringDelay(t *testing.T) {
}

f.simTime = f.nav.Altitude.ActivateAt
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, 0, f.simTime, nil)
target, _, _ = f.nav.TargetAltitude()
if target != 3000 {
t.Fatalf("expected new assigned altitude 3000 after delay, got %.0f", target)
Expand All @@ -89,7 +89,7 @@ func TestAssignAltitudeKeepsSTARDescentDuringDelay(t *testing.T) {

for range 300 {
wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)
if f.nav.FlightState.AltitudeRate < -50 {
break
Expand Down Expand Up @@ -121,7 +121,7 @@ func TestSayAltitudeReportsPendingAssignedAltitude(t *testing.T) {
})

f.AssignAltitude(3000)
intent, ok := f.nav.SayAltitude().(av.ReportAltitudeIntent)
intent, ok := f.nav.SayAltitude(0).(av.ReportAltitudeIntent)
if !ok {
t.Fatalf("expected ReportAltitudeIntent, got %T", intent)
}
Expand Down Expand Up @@ -153,7 +153,7 @@ func TestExpediteDuringAssignedAltitudeDelay(t *testing.T) {
}

f.simTime = f.nav.Altitude.ActivateAt.Add(time.Second)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, 0, f.simTime, nil)
if f.nav.Altitude.Rate != RateExpedite {
t.Fatalf("expected expedite rate after delayed activation, got %v", f.nav.Altitude.Rate)
}
Expand Down Expand Up @@ -616,7 +616,7 @@ func TestAltitudeAfterSpeedDelaysAfterSpeedReached(t *testing.T) {

for range 300 {
wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)
if f.nav.Altitude.AfterSpeed == nil {
break
Expand All @@ -637,7 +637,7 @@ func TestAltitudeAfterSpeedDelaysAfterSpeedReached(t *testing.T) {
f.AssertLevelFlight()

f.simTime = f.nav.Altitude.ActivateAt.Add(time.Second)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, 0, f.simTime, nil)
if f.nav.Altitude.ActiveAssigned == nil || *f.nav.Altitude.ActiveAssigned != 3000 {
t.Fatalf("expected ActiveAssigned=3000 after delayed activation, got %v", f.nav.Altitude.ActiveAssigned)
}
Expand Down Expand Up @@ -747,7 +747,7 @@ func TestGoodRateDescentFasterThanNormal(t *testing.T) {
runForTicks := func(f *FlightTest, ticks int) {
for range ticks {
wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(1e9)
}
}
Expand Down
16 changes: 11 additions & 5 deletions nav/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ func (nav *Nav) AssignAltitude(alt float32, afterSpeed bool, simTime Time, delay
if !ok {
return intent
}
// A new controller-issued altitude supersedes any pending "report
// reaching" target.
nav.ReportReachingAltitude = nil
nav.enqueueAssignedAltitude(alt, simTime, delayReduction)
return intent
}
Expand Down Expand Up @@ -346,14 +349,17 @@ func (nav *Nav) SayHeading() av.CommandIntent {
return intent
}

func (nav *Nav) SayAltitude() av.CommandIntent {
currentAltitude := nav.FlightState.Altitude
intent := av.ReportAltitudeIntent{Current: currentAltitude}
// SayAltitude reports the pilot's *indicated* altitude. The pilot reads
// off their altimeter, which is offset from true altitude by altimBiasFeet
// when the pilot's setting differs from the local actual.
func (nav *Nav) SayAltitude(altimBiasFeet float32) av.CommandIntent {
indicatedAltitude := nav.FlightState.Altitude - altimBiasFeet
intent := av.ReportAltitudeIntent{Current: indicatedAltitude}
if nav.Altitude.Assigned != nil {
intent.Assigned = nav.Altitude.Assigned
if *nav.Altitude.Assigned < currentAltitude {
if *nav.Altitude.Assigned < indicatedAltitude {
intent.Direction = av.AltitudeDescend
} else if *nav.Altitude.Assigned > currentAltitude {
} else if *nav.Altitude.Assigned > indicatedAltitude {
intent.Direction = av.AltitudeClimb
} else {
intent.Direction = av.AltitudeMaintain
Expand Down
4 changes: 2 additions & 2 deletions nav/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func TestExpectDirectReducesDelay(t *testing.T) {
// Wait for heading to take effect
for i := 0; i < 10; i++ {
wxs := fNoExpect.weather(fNoExpect.nav.FlightState.Altitude)
fNoExpect.nav.UpdateWithWeather(fNoExpect.callsign, wxs, &fNoExpect.fp, fNoExpect.simTime, nil)
fNoExpect.nav.UpdateWithWeather(fNoExpect.callsign, wxs, &fNoExpect.fp, 0, fNoExpect.simTime, nil)
fNoExpect.simTime = fNoExpect.simTime.Add(1e9) // 1 second
}
fNoExpect.nav.DirectFix("DETGY", av.TurnClosest, fNoExpect.simTime, 0)
Expand All @@ -191,7 +191,7 @@ func TestExpectDirectReducesDelay(t *testing.T) {
fExpect.nav.AssignHeading(math.MagneticHeading(360), av.TurnClosest, fExpect.simTime, 0)
for i := 0; i < 10; i++ {
wxs := fExpect.weather(fExpect.nav.FlightState.Altitude)
fExpect.nav.UpdateWithWeather(fExpect.callsign, wxs, &fExpect.fp, fExpect.simTime, nil)
fExpect.nav.UpdateWithWeather(fExpect.callsign, wxs, &fExpect.fp, 0, fExpect.simTime, nil)
fExpect.simTime = fExpect.simTime.Add(1e9)
}
fExpect.nav.ExpectDirect("DETGY")
Expand Down
10 changes: 5 additions & 5 deletions nav/hold_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestHoldTurningInboundDoesNotFlyAwayAfterOvershoot(t *testing.T) {
}}

f.nav.UpdateWithWeather(f.callsign, wx.MakeStandardSampleForAltitude(f.nav.FlightState.Altitude),
&f.fp, f.simTime, nil)
&f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)
if f.nav.Heading.Hold == nil {
t.Fatal("hold unexpectedly ended")
Expand All @@ -65,7 +65,7 @@ func TestHoldTurningInboundDoesNotFlyAwayAfterOvershoot(t *testing.T) {

for range 90 {
f.nav.UpdateWithWeather(f.callsign, wx.MakeStandardSampleForAltitude(f.nav.FlightState.Altitude),
&f.fp, f.simTime, nil)
&f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)
}

Expand Down Expand Up @@ -124,7 +124,7 @@ func TestHoldInboundTurnDistanceMatchesOutboundTurn(t *testing.T) {
previousStep := hold.currentStep()

for tick := range 300 {
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)

step := hold.currentStep()
Expand Down Expand Up @@ -191,7 +191,7 @@ func TestFQM3HoldInboundTurnCompletesNearExpectedTrack(t *testing.T) {
flyFixStep := "fly toward fix until fix"

for tick := range 2000 {
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)

if f.nav.Heading.Hold != nil && hold == nil {
Expand Down Expand Up @@ -311,7 +311,7 @@ func TestHoldInboundTurnCompletesAfterHalfCircuitWithStrongWind(t *testing.T) {
inboundTurnStartTick := -1

for tick := range 240 {
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, f.weather(f.nav.FlightState.Altitude), &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)

step := hold.currentStep()
Expand Down
11 changes: 6 additions & 5 deletions nav/lateral.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@ func (nav *Nav) Check(lg *log.Logger) {
}
}

func (nav *Nav) Update(callsign string, model *wx.Model, fp *av.FlightPlan, simTime Time, bravo *av.AirspaceGrid) UpdateResult {
func (nav *Nav) Update(callsign string, model *wx.Model, fp *av.FlightPlan, altimBiasFeet float32, simTime Time, bravo *av.AirspaceGrid) UpdateResult {
// Perform single weather lookup at the start
wxs := model.Lookup(nav.FlightState.Position, nav.FlightState.Altitude, simTime.Time())
return nav.UpdateWithWeather(callsign, wxs, fp, simTime, bravo)
return nav.UpdateWithWeather(callsign, wxs, fp, altimBiasFeet, simTime, bravo)
}

// UpdateWithWeather is a helper for simulations that use pre-fetched weather
func (nav *Nav) UpdateWithWeather(callsign string, wxs wx.Sample, fp *av.FlightPlan, simTime Time, bravo *av.AirspaceGrid) UpdateResult {
func (nav *Nav) UpdateWithWeather(callsign string, wxs wx.Sample, fp *av.FlightPlan, altimBiasFeet float32, simTime Time, bravo *av.AirspaceGrid) UpdateResult {
nav.PendingWaypointActionEvents = nil
nav.activatePendingAltitude(simTime)

Expand All @@ -139,6 +139,7 @@ func (nav *Nav) UpdateWithWeather(callsign string, wxs wx.Sample, fp *av.FlightP
nav.FlightState.BankAngle, nav.FlightState.AltitudeRate)

targetAltitude, altitudeRate, geometricDescent := nav.TargetAltitude()
targetAltitude += altimBiasFeet
deltaKts, slowingTo250 := nav.updateAirspeed(callsign, targetAltitude, geometricDescent, fp, wxs, simTime, bravo)
nav.updateAltitude(callsign, targetAltitude, altitudeRate, geometricDescent, deltaKts, slowingTo250, wxs, simTime)
nav.updateHeading(callsign, wxs, simTime)
Expand Down Expand Up @@ -722,7 +723,7 @@ func (nav *Nav) shouldTurnForOutbound(p math.Point2LL, hdg math.MagneticHeading,
// Don't simulate the turn longer than it will take to do it.
n := int(1 + turnAngle/3)
for range n {
nav2.UpdateWithWeather("", wxs, nil, Time{}, nil)
nav2.UpdateWithWeather("", wxs, nil, 0, Time{}, nil)
curDist := math.SignedPointLineDistance(math.LL2NM(nav2.FlightState.Position,
nav2.FlightState.NmPerLongitude),
p0, p1)
Expand Down Expand Up @@ -778,7 +779,7 @@ func (nav *Nav) shouldTurnToIntercept(p0 math.Point2LL, hdg math.MagneticHeading
n := int(1 + turnAngle)
lastDist := initialDist
for range n {
nav2.UpdateWithWeather("", wxs, nil, Time{}, nil)
nav2.UpdateWithWeather("", wxs, nil, 0, Time{}, nil)
curDist := math.SignedPointLineDistance(math.LL2NM(nav2.FlightState.Position, nav2.FlightState.NmPerLongitude), p0nm, p1)

intercepted := math.Abs(curDist) < 0.02
Expand Down
6 changes: 6 additions & 0 deletions nav/nav.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ type Nav struct {

PendingWaypointActionEvents []av.WaypointActionEvent

// ReportReachingAltitude stores the most-recent "report reaching NNNN"
// target. Cleared when a new altitude is assigned, and cleared when the
// aircraft levels off within tolerance (the leveling-off triggers a
// reaching-altitude transmission).
ReportReachingAltitude *float32

Rand *rand.Rand
}

Expand Down
2 changes: 1 addition & 1 deletion nav/nav_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ func (f *FlightTest) Run() {

for f.tick = 0; f.tick < f.maxTicks; f.tick++ {
wxs := f.weather(f.nav.FlightState.Altitude)
passedWp := f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil).PassedWaypoint
passedWp := f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil).PassedWaypoint

if passedWp != nil {
f.passed = append(f.passed, passedWp.Fix)
Expand Down
6 changes: 3 additions & 3 deletions nav/pt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func TestStandard45ProcedureTurnCompletes(t *testing.T) {
f := makePTFlight(t, "FORMU/pt45/flyover ZIVUX WENGA", 3000, 180)

wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)

f.nav.flyProcedureTurnIfNecessary()
Expand Down Expand Up @@ -180,7 +180,7 @@ func TestRacetrackPTCreatesManeuvers(t *testing.T) {
f := makePTFlight(t, "FORMU/hilpt4.0nm/flyover ZIVUX WENGA", 3000, 180)

wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)

f.nav.flyProcedureTurnIfNecessary()
Expand Down Expand Up @@ -231,7 +231,7 @@ func TestProcedureTurnDescendsToExitAltitude(t *testing.T) {
f := makePTFlight(t, "FORMU/pt45/pta2000/flyover ZIVUX WENGA", 3000, 180)

wxs := f.weather(f.nav.FlightState.Altitude)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, f.simTime, nil)
f.nav.UpdateWithWeather(f.callsign, wxs, &f.fp, 0, f.simTime, nil)
f.simTime = f.simTime.Add(time.Second)

f.nav.flyProcedureTurnIfNecessary()
Expand Down
11 changes: 9 additions & 2 deletions server/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,19 @@ type NewSimRequest struct {

PilotErrorInterval float32

IncorrectAltimeterChance float32 // 0-100%
FaultyTransponderChance float32 // 0-100%

Initials string // Controller initials (e.g., "XX")
Privileged bool
}

func MakeNewSimRequest() NewSimRequest {
return NewSimRequest{
NewSimName: rand.Make().AdjectiveNoun(),
PilotErrorInterval: 0,
NewSimName: rand.Make().AdjectiveNoun(),
PilotErrorInterval: 0,
IncorrectAltimeterChance: 30,
FaultyTransponderChance: 5,
}
}

Expand Down Expand Up @@ -220,6 +225,8 @@ func (sm *SimManager) makeSimConfiguration(req *NewSimRequest, lg *log.Logger) *
DisableTFRRestrictionAreas: sg.FacilityConfig.DisableTFRRestrictionAreas,
EnforceUniqueCallsignSuffix: req.EnforceUniqueCallsignSuffix,
PilotErrorInterval: req.PilotErrorInterval,
IncorrectAltimeterChance: req.IncorrectAltimeterChance,
FaultyTransponderChance: req.FaultyTransponderChance,
DepartureRunways: sc.DepartureRunways,
ArrivalRunways: sc.ArrivalRunways,
VFRReportingPoints: sg.VFRReportingPoints,
Expand Down
Loading
Loading