mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-10-16 23:49:19 +02:00
Move the battery option to the depot as a consist property
It was a global preference that rewrote the trainset speed at launch, while what it really sets is whether this consist starts prepared or cold. Now a checkbox in the consist-scope section, acting on the consist being edited.
This commit is contained in:
56
StarterNG.Tests/TrainsetReadyTests.cs
Normal file
56
StarterNG.Tests/TrainsetReadyTests.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using StarterNG.Classes;
|
||||
|
||||
namespace StarterNG.Tests;
|
||||
|
||||
public class TrainsetReadyTests
|
||||
{
|
||||
private static Trainset Parse(string velocity) =>
|
||||
new($"trainset pociag tor_1 10 {velocity}\n" +
|
||||
"node -1 -1 ep07-001 dynamic PKP/EP07 ep07 ep07.mmd 0 headdriver 0\n" +
|
||||
"endtrainset");
|
||||
|
||||
[Fact]
|
||||
public void A_consist_authored_standing_still_is_not_ready()
|
||||
{
|
||||
Assert.False(Parse("0").ReadyToGo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Marking_a_standing_consist_ready_gives_it_the_prepared_creep()
|
||||
{
|
||||
var trainset = Parse("0");
|
||||
|
||||
trainset.ReadyToGo = true;
|
||||
|
||||
Assert.True(trainset.ReadyToGo);
|
||||
Assert.Equal(0.1f, trainset.Velocity, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_consist_authored_on_the_move_is_ready_and_keeps_its_speed()
|
||||
{
|
||||
var trainset = Parse("40");
|
||||
|
||||
Assert.True(trainset.ReadyToGo);
|
||||
|
||||
trainset.ReadyToGo = false;
|
||||
Assert.Equal(0f, trainset.Velocity);
|
||||
|
||||
trainset.ReadyToGo = true;
|
||||
Assert.Equal(40f, trainset.Velocity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_consist_running_the_other_way_keeps_its_direction()
|
||||
{
|
||||
// The sign of the speed is what DynObj.cpp turns into the running
|
||||
// direction, so restoring readiness must not flip it.
|
||||
var trainset = Parse("-40");
|
||||
|
||||
trainset.ReadyToGo = false;
|
||||
trainset.ReadyToGo = true;
|
||||
|
||||
Assert.Equal(-40f, trainset.Velocity);
|
||||
Assert.True(trainset.ReadyToGo);
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ public sealed class StartSimulation
|
||||
{
|
||||
private const char ExportPrefix = '$';
|
||||
|
||||
private const float BatteryOnVelocity = 0.1f;
|
||||
|
||||
private readonly AppState _state;
|
||||
private readonly SettingsStore _settings;
|
||||
@@ -80,8 +79,6 @@ public sealed class StartSimulation
|
||||
if (scenery is null || trainset is null)
|
||||
return new SimulationStartResult(SimulationStartOutcome.NothingSelected);
|
||||
|
||||
ApplyBatteryDefault(trainset);
|
||||
|
||||
string? vehicle = TrainsetDisplay.UniquifyForLaunch(trainset, scenery, _state.StartingVehicleName)
|
||||
?? StartableVehicle(trainset, _state.StartingVehicleName);
|
||||
_state.StartingVehicleName = vehicle;
|
||||
@@ -123,18 +120,4 @@ public sealed class StartSimulation
|
||||
return new SimulationStartResult(SimulationStartOutcome.Started, process, executable);
|
||||
}
|
||||
|
||||
private void ApplyBatteryDefault(Trainset trainset)
|
||||
{
|
||||
if (trainset.Vehicles.Count == 0)
|
||||
return;
|
||||
|
||||
trainset.Velocity = _settings.Settings.BatteryDefault switch
|
||||
{
|
||||
BatteryDefault.AlwaysOff => 0f,
|
||||
BatteryDefault.AlwaysOn => MathF.Abs(trainset.OriginalVelocity) < 0.01f
|
||||
? BatteryOnVelocity
|
||||
: trainset.OriginalVelocity,
|
||||
_ => trainset.OriginalVelocity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,29 @@ public class Trainset
|
||||
public float Offset;
|
||||
public float Velocity;
|
||||
public float OriginalVelocity;
|
||||
|
||||
// The scenery format has no battery field: a trainset with a non-zero speed is
|
||||
// the prepared one. DynObj.cpp derives ReadyFlag from it, and that branch of
|
||||
// CheckLocomotiveParameters is what charges the pipes, sets the brake handle
|
||||
// and closes the battery contactor. The sign carries the direction, so a
|
||||
// consist authored on the move keeps its own speed.
|
||||
private const float StandingStill = 0.01f;
|
||||
private const float PreparedCreep = 0.1f;
|
||||
|
||||
public bool ReadyToGo
|
||||
{
|
||||
get => MathF.Abs(Velocity) >= StandingStill;
|
||||
set
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
Velocity = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Velocity = MathF.Abs(OriginalVelocity) < StandingStill ? PreparedCreep : OriginalVelocity;
|
||||
}
|
||||
}
|
||||
public string Description;
|
||||
public List<Dynamic> Vehicles;
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ using System;
|
||||
|
||||
namespace StarterNG.Domain.Settings;
|
||||
|
||||
public enum BatteryDefault { Default = 0, AlwaysOff = 1, AlwaysOn = 2 }
|
||||
|
||||
public enum ExeProblem { None, NotFound, NotExecutable, WrongPlatform }
|
||||
|
||||
public sealed class SimulatorSettings
|
||||
@@ -107,7 +105,6 @@ public sealed class SimulatorSettings
|
||||
public bool AutoCloseStarter;
|
||||
public bool LargeThumbnails;
|
||||
public bool AutoExpandSceneryTree;
|
||||
public BatteryDefault BatteryDefault = BatteryDefault.Default;
|
||||
|
||||
public bool ShowAiVehicles = true;
|
||||
public bool DrivableOnly = true;
|
||||
|
||||
@@ -136,7 +136,6 @@ public sealed class SettingsSerializer
|
||||
s.AutoCloseStarter = c.GetBool("starter.autoclose", false);
|
||||
s.LargeThumbnails = c.GetBool("starter.largethumbnails", false);
|
||||
s.AutoExpandSceneryTree = c.GetBool("starter.expandtree", false);
|
||||
s.BatteryDefault = (BatteryDefault)Clamp(c.GetInt("starter.batterydefault", 0), 0, 2);
|
||||
s.ShowAiVehicles = c.GetBool("starter.show.ai", true);
|
||||
s.DrivableOnly = c.GetBool("starter.drivableonly", true);
|
||||
s.ShowArchivalSceneries = c.GetBool("starter.show.archival", true);
|
||||
@@ -265,7 +264,6 @@ public sealed class SettingsSerializer
|
||||
c.SetBool("starter.autoclose", s.AutoCloseStarter);
|
||||
c.SetBool("starter.largethumbnails", s.LargeThumbnails);
|
||||
c.SetBool("starter.expandtree", s.AutoExpandSceneryTree);
|
||||
c.SetInt("starter.batterydefault", (int)s.BatteryDefault);
|
||||
c.SetBool("starter.show.ai", s.ShowAiVehicles);
|
||||
c.SetBool("starter.drivableonly", s.DrivableOnly);
|
||||
c.SetBool("starter.show.archival", s.ShowArchivalSceneries);
|
||||
|
||||
@@ -555,7 +555,7 @@ public sealed class VehicleDetails
|
||||
if (_consist.Count == 0)
|
||||
return;
|
||||
|
||||
var buttons = Stack(
|
||||
var tools = Stack(
|
||||
LoadToolButton(App.Loc["ConsistRandomType"],
|
||||
() => { _cargo.RandomTypes(_consist); _redraw(); }, secondary: true),
|
||||
LoadToolButton(App.Loc["ConsistMaxAmount"],
|
||||
@@ -563,6 +563,8 @@ public sealed class VehicleDetails
|
||||
LoadToolButton(App.Loc["ConsistRandomAmount"],
|
||||
() => { _cargo.RandomAmounts(_consist); _redraw(); }, secondary: true));
|
||||
|
||||
var buttons = Stack(ReadyToGoRow(), tools);
|
||||
|
||||
var count = new TextBlock
|
||||
{
|
||||
Text = $"{App.Loc["VehicleCount"]}: {_consist.Count}",
|
||||
@@ -574,6 +576,29 @@ public sealed class VehicleDetails
|
||||
loadsPanel.Children.Add(Section(App.Loc["ConsistLoadTools"], buttons, count));
|
||||
}
|
||||
|
||||
private Control ReadyToGoRow()
|
||||
{
|
||||
var trainset = _consist.EditingTrainset;
|
||||
var ready = new CheckBox
|
||||
{
|
||||
Content = App.Loc["ConsistReady"],
|
||||
FontSize = 12,
|
||||
IsEnabled = trainset is not null,
|
||||
IsChecked = trainset?.ReadyToGo ?? false
|
||||
};
|
||||
ToolTip.SetTip(ready, App.Loc["ConsistReadyDesc"]);
|
||||
|
||||
ready.IsCheckedChanged += (_, _) =>
|
||||
{
|
||||
if (trainset is null)
|
||||
return;
|
||||
trainset.ReadyToGo = ready.IsChecked == true;
|
||||
_redraw();
|
||||
};
|
||||
|
||||
return Row(content: ready);
|
||||
}
|
||||
|
||||
private Button LoadToolButton(string text, Action onClick, bool secondary = false)
|
||||
{
|
||||
var b = new Button
|
||||
|
||||
@@ -118,14 +118,6 @@
|
||||
<ctl:SettingRow ConfigKey="starter.expandtree">
|
||||
<CheckBox x:Name="AutoExpandTreeCb" Content="{Binding [AutoExpandSceneryTree], Source={x:Static starterNg:App.Loc}}" />
|
||||
</ctl:SettingRow>
|
||||
<ctl:SettingRow ConfigKey="starter.batterydefault" Label="{Binding [BatteryDefault], Source={x:Static starterNg:App.Loc}}"
|
||||
Description="{Binding [BatteryDefaultDesc], Source={x:Static starterNg:App.Loc}}">
|
||||
<ComboBox x:Name="BatteryDefaultCb" SelectedIndex="0">
|
||||
<ComboBoxItem Content="{Binding [BatteryDefaultScenario], Source={x:Static starterNg:App.Loc}}" />
|
||||
<ComboBoxItem Content="{Binding [BatteryDefaultOff], Source={x:Static starterNg:App.Loc}}" />
|
||||
<ComboBoxItem Content="{Binding [BatteryDefaultOn], Source={x:Static starterNg:App.Loc}}" />
|
||||
</ComboBox>
|
||||
</ctl:SettingRow>
|
||||
</StackPanel>
|
||||
</ctl:SettingsSection>
|
||||
|
||||
|
||||
@@ -260,7 +260,6 @@ public partial class Settings : UserControl, ISettingsCapture
|
||||
AutoCloseStarterCb.IsChecked = s.AutoCloseStarter;
|
||||
LargeThumbnailsCb.IsChecked = s.LargeThumbnails;
|
||||
AutoExpandTreeCb.IsChecked = s.AutoExpandSceneryTree;
|
||||
BatteryDefaultCb.SelectedIndex = (int)s.BatteryDefault;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -358,7 +357,6 @@ public partial class Settings : UserControl, ISettingsCapture
|
||||
s.AutoCloseStarter = IsChecked(AutoCloseStarterCb);
|
||||
s.LargeThumbnails = IsChecked(LargeThumbnailsCb);
|
||||
s.AutoExpandSceneryTree = IsChecked(AutoExpandTreeCb);
|
||||
s.BatteryDefault = (BatteryDefault)Math.Max(0, BatteryDefaultCb.SelectedIndex);
|
||||
}
|
||||
|
||||
private void ComButton_OnClick(object? sender, RoutedEventArgs e)
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
<String key="LoadToAllShort">Na následující</String>
|
||||
<String key="LoadMaxShort">Maximální</String>
|
||||
<String key="ConsistLoadTools">Náklad celé soupravy</String>
|
||||
<String key="ConsistReady">Consist ready to go</String>
|
||||
<String key="ConsistReadyDesc">The consist starts prepared: brake pipe charged, driver’s brake valve set, batteries closed. Unchecked it starts cold and braked.</String>
|
||||
<String key="ConsistRandomType">Náhodný druh</String>
|
||||
<String key="ConsistMaxAmount">Maximální množství</String>
|
||||
<String key="ConsistRandomAmount">Náhodné množství</String>
|
||||
@@ -440,10 +442,6 @@
|
||||
<String key="AutoCloseStarter">Automaticky zavřít starter</String>
|
||||
<String key="LargeThumbnails">Velké náhledy</String>
|
||||
<String key="AutoExpandSceneryTree">Automaticky rozbalit strom scenérií</String>
|
||||
<String key="BatteryDefault">Baterie při spuštění</String>
|
||||
<String key="BatteryDefaultScenario">Podle scénáře</String>
|
||||
<String key="BatteryDefaultOff">Vždy vypnutá</String>
|
||||
<String key="BatteryDefaultOn">Vždy zapnutá</String>
|
||||
|
||||
<!-- Controls / key bindings -->
|
||||
<String key="Controls">Ovládání</String>
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
<String key="LoadToAllShort">To following</String>
|
||||
<String key="LoadMaxShort">Maximum</String>
|
||||
<String key="ConsistLoadTools">Whole-consist load</String>
|
||||
<String key="ConsistReady">Consist ready to go</String>
|
||||
<String key="ConsistReadyDesc">The consist starts prepared: brake pipe charged, driver’s brake valve set, batteries closed. Unchecked it starts cold and braked.</String>
|
||||
<String key="ConsistRandomType">Random type</String>
|
||||
<String key="ConsistMaxAmount">Maximum amount</String>
|
||||
<String key="ConsistRandomAmount">Random amount</String>
|
||||
@@ -474,11 +476,6 @@
|
||||
<String key="AutoCloseStarter">Automatically close starter</String>
|
||||
<String key="LargeThumbnails">Large thumbnails</String>
|
||||
<String key="AutoExpandSceneryTree">Automatically expand scenery tree</String>
|
||||
<String key="BatteryDefault">Battery on launch</String>
|
||||
<String key="BatteryDefaultDesc">Battery state when the simulation starts, unless the scenario decides otherwise.</String>
|
||||
<String key="BatteryDefaultScenario">Scenario default</String>
|
||||
<String key="BatteryDefaultOff">Always off</String>
|
||||
<String key="BatteryDefaultOn">Always on</String>
|
||||
|
||||
<!-- Controls / key bindings -->
|
||||
<String key="Controls">Controls</String>
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
<String key="LoadToAllShort">A következőkre</String>
|
||||
<String key="LoadMaxShort">Legnagyobb</String>
|
||||
<String key="ConsistLoadTools">A teljes szerelvény rakománya</String>
|
||||
<String key="ConsistReady">Consist ready to go</String>
|
||||
<String key="ConsistReadyDesc">The consist starts prepared: brake pipe charged, driver’s brake valve set, batteries closed. Unchecked it starts cold and braked.</String>
|
||||
<String key="ConsistRandomType">Véletlen típus</String>
|
||||
<String key="ConsistMaxAmount">Legnagyobb mennyiség</String>
|
||||
<String key="ConsistRandomAmount">Véletlen mennyiség</String>
|
||||
@@ -440,10 +442,6 @@
|
||||
<String key="AutoCloseStarter">A starter automatikus bezárása</String>
|
||||
<String key="LargeThumbnails">Nagy előnézetek</String>
|
||||
<String key="AutoExpandSceneryTree">Pályafa automatikus kibontása</String>
|
||||
<String key="BatteryDefault">Akkumulátor indításkor</String>
|
||||
<String key="BatteryDefaultScenario">Forgatókönyv szerint</String>
|
||||
<String key="BatteryDefaultOff">Mindig ki</String>
|
||||
<String key="BatteryDefaultOn">Mindig be</String>
|
||||
|
||||
<!-- Controls / key bindings -->
|
||||
<String key="Controls">Irányítás</String>
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
<String key="LoadToAllShort">Do następnych</String>
|
||||
<String key="LoadMaxShort">Maksymalny</String>
|
||||
<String key="ConsistLoadTools">Ładunki zestawienia</String>
|
||||
<String key="ConsistReady">Skład gotowy do jazdy</String>
|
||||
<String key="ConsistReadyDesc">Skład startuje przygotowany: przewód główny napełniony, kran maszynisty ustawiony, akumulatory załączone. Odznaczony startuje zimny i zahamowany.</String>
|
||||
<String key="ConsistRandomType">Losowy rodzaj</String>
|
||||
<String key="ConsistMaxAmount">Maksymalna ilość</String>
|
||||
<String key="ConsistRandomAmount">Losowa ilość</String>
|
||||
@@ -474,11 +476,6 @@
|
||||
<String key="AutoCloseStarter">Zamknij starter automatycznie</String>
|
||||
<String key="LargeThumbnails">Duże miniaturki</String>
|
||||
<String key="AutoExpandSceneryTree">Automatycznie rozwijanie drzewka scenerii</String>
|
||||
<String key="BatteryDefault">Akumulator przy starcie</String>
|
||||
<String key="BatteryDefaultDesc">Stan akumulatora przy starcie symulacji, o ile scenariusz nie zdecyduje inaczej.</String>
|
||||
<String key="BatteryDefaultScenario">Domyślnie ze scenerii</String>
|
||||
<String key="BatteryDefaultOff">Zawsze wyłączony</String>
|
||||
<String key="BatteryDefaultOn">Zawsze włączony</String>
|
||||
|
||||
<!-- Sterowanie / przypisania klawiszy -->
|
||||
<String key="Controls">Sterowanie</String>
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
<String key="LoadToAllShort">На следующие</String>
|
||||
<String key="LoadMaxShort">Максимум</String>
|
||||
<String key="ConsistLoadTools">Груз всего состава</String>
|
||||
<String key="ConsistReady">Consist ready to go</String>
|
||||
<String key="ConsistReadyDesc">The consist starts prepared: brake pipe charged, driver’s brake valve set, batteries closed. Unchecked it starts cold and braked.</String>
|
||||
<String key="ConsistRandomType">Случайный тип</String>
|
||||
<String key="ConsistMaxAmount">Максимальное количество</String>
|
||||
<String key="ConsistRandomAmount">Случайное количество</String>
|
||||
@@ -440,10 +442,6 @@
|
||||
<String key="AutoCloseStarter">Автоматически закрывать стартер</String>
|
||||
<String key="LargeThumbnails">Крупные миниатюры</String>
|
||||
<String key="AutoExpandSceneryTree">Автоматически разворачивать дерево сценерий</String>
|
||||
<String key="BatteryDefault">Батарея при запуске</String>
|
||||
<String key="BatteryDefaultScenario">По сценарию</String>
|
||||
<String key="BatteryDefaultOff">Всегда выключена</String>
|
||||
<String key="BatteryDefaultOn">Всегда включена</String>
|
||||
|
||||
<!-- Controls / key bindings -->
|
||||
<String key="Controls">Управление</String>
|
||||
|
||||
Reference in New Issue
Block a user