Keep a last-vehicle coupler set by hand

The back of the consist goes to 0 after every change unless its coupler was
set in the editor; a car that gets a neighbour loses that mark, so it is
freed again once it is last again.
This commit is contained in:
maj00r
2026-10-04 14:33:48 +02:00
parent 925ac87129
commit 00795513b9
9 changed files with 52 additions and 12 deletions

View File

@@ -56,6 +56,32 @@ public class ConsistTailTests
Assert.Equal("0.BP", car.Cars[0].Coupling.ToString());
}
[Fact]
public void A_coupler_set_by_hand_on_the_last_car_stays()
{
Append("b111-01");
var last = Append("b111-02");
last.Cars[0].Coupling.Flags = 3;
last.Cars[0].CouplerSetByHand = true;
_consist.AutoConnectAll();
Assert.Equal(3, last.Cars[0].Coupling.Flags);
}
[Fact]
public void A_car_set_by_hand_that_gets_a_neighbour_is_freed_again_once_it_is_last_again()
{
var first = Append("b111-01");
first.Cars[0].CouplerSetByHand = true;
var second = Append("b111-02");
_consist.AutoConnectAll();
_consist.Remove(second);
Assert.Equal(0, first.Cars[0].Coupling.Flags);
}
private ConsistItem Append(string skin)
{
var item = new ConsistItem

View File

@@ -235,6 +235,12 @@ public class Dynamic
public bool Flipped;
/// <summary>
/// The coupler was set in the editor, so the consist leaves it be at the back of
/// the train. Not written out: in the scenery a coupler is just a coupler.
/// </summary>
public bool CouplerSetByHand;
public static bool IsPantStateType(string? type) =>
string.Equals(type, PantState, StringComparison.OrdinalIgnoreCase);
@@ -302,7 +308,8 @@ public class Dynamic
LoadCount = LoadCount,
LoadType = LoadType,
MiniName = MiniName,
Flipped = Flipped
Flipped = Flipped,
CouplerSetByHand = CouplerSetByHand
};
public string ToTrainsetNode()

View File

@@ -554,6 +554,7 @@ public sealed class Consist : IReadOnlyList<ConsistItem>
common &= ~Coupling.ControlMU;
left.Coupling.Flags = left.Coupling.Locked ? -common : common;
left.CouplerSetByHand = false;
}
FreeTail();
@@ -605,15 +606,19 @@ public sealed class Consist : IReadOnlyList<ConsistItem>
item.Flipped ? item.Cars[^1] : item.Cars[0];
/// <summary>
/// Clears the coupler at the back of the consist. The simulator hangs the end
/// signals only on a last vehicle whose coupler is 0 - anything else couples it
/// to whatever stands behind - and every new car comes with 3. Its parameters,
/// the brake setting among them, stay.
/// Clears the coupler at the back of the consist, unless it was set in the
/// editor. The simulator hangs the end signals only on a last vehicle whose
/// coupler is 0 - anything else couples it to whatever stands behind - and every
/// new car comes with 3. Its parameters, the brake setting among them, stay.
/// </summary>
private void FreeTail()
{
if (_items.Count > 0 && _items[^1].Cars.Count > 0)
TailCar(_items[^1]).Coupling.Flags = 0;
if (_items.Count == 0 || _items[^1].Cars.Count == 0)
return;
var tail = TailCar(_items[^1]);
if (!tail.CouplerSetByHand)
tail.Coupling.Flags = 0;
}
/// <summary>

View File

@@ -207,6 +207,7 @@ public sealed class VehicleDetails
check.IsCheckedChanged += (_, _) =>
{
d.Coupling.Set(bit, check.IsChecked == true);
d.CouplerSetByHand = true;
_redraw();
};
Grid.SetRow(check, i / 2);
@@ -229,6 +230,7 @@ public sealed class VehicleDetails
{
if (unitIdx <= 0) return;
d.Coupling.Flags = Consist.TailCar(_consist[unitIdx - 1]).Coupling.Flags;
d.CouplerSetByHand = true;
_redraw();
Refresh();
};

View File

@@ -280,7 +280,7 @@
<String key="TipSplit">Rozdělit jednotku na jednotlivé vozy</String>
<String key="AppliesToUnit">Společné pro celou jednotku</String>
<String key="CouplingUnitRear">Spřáhlo na konci jednotky</String>
<String key="CouplingLastNote">Poslední vozidlo: spřáhlo 0 dává koncovky. Jiný kód spojí soupravu s tím, co stojí za ní, a simulátor koncovky nenasadí.</String>
<String key="CouplingLastNote">Poslední vozidlo: spřáhlo 0 dává koncovky, jiný kód spojí soupravu s tím, co stojí za ní, bez koncovek. Starter zde po každé změně soupravy nastaví 0, pokud spřáhlo nenastavíte ručně.</String>
<String key="Join">Spojit</String>
<String key="TipJoin">Spojit toto vozidlo s následujícím do jedné jednotky</String>
<String key="TipReorder">Přetáhněte pro změnu pořadí</String>

View File

@@ -280,7 +280,7 @@
<String key="TipSplit">Split the unit into individual cars</String>
<String key="AppliesToUnit">Shared by the whole unit</String>
<String key="CouplingUnitRear">Coupler at the rear of the unit</String>
<String key="CouplingLastNote">Last vehicle: coupler 0 gets the end signals. Any other code couples the train to whatever stands behind it, and the simulator puts up no end signals.</String>
<String key="CouplingLastNote">Last vehicle: coupler 0 gets the end signals; any other code couples the train to whatever stands behind it, with no end signals. The starter sets 0 here after every change to the consist, unless you set the coupler by hand.</String>
<String key="Join">Join</String>
<String key="TipJoin">Couple this vehicle with the next one into a single unit</String>
<String key="TipReorder">Drag to reorder</String>

View File

@@ -280,7 +280,7 @@
<String key="TipSplit">Az egység szétbontása külön kocsikra</String>
<String key="AppliesToUnit">Az egész egységre közös</String>
<String key="CouplingUnitRear">Az egység végén lévő kapcsolókészülék</String>
<String key="CouplingLastNote">Utolsó jármű: a 0-s kapcsolat adja a zárjelzőket. Más kód a mögötte álló járműhöz kapcsolja a szerelvényt, és a szimulátor nem tesz fel zárjelzőt.</String>
<String key="CouplingLastNote">Utolsó jármű: a 0-s kapcsolat adja a zárjelzőket, más kód a mögötte állóhoz kapcsolja a szerelvényt, zárjelzők nélkül. A starter minden szerelvényváltozás után 0-ra állítja, hacsak kézzel nem állítod be.</String>
<String key="Join">Összekapcsolás</String>
<String key="TipJoin">A jármű összekapcsolása a következővel egy egységgé</String>
<String key="TipReorder">Húzza az átrendezéshez</String>

View File

@@ -280,7 +280,7 @@
<String key="TipSplit">Rozdziel zespół na pojedyncze człony</String>
<String key="AppliesToUnit">Ustawienie wspólne dla całego zespołu</String>
<String key="CouplingUnitRear">Sprzęg na końcu zespołu</String>
<String key="CouplingLastNote">Ostatni pojazd: sprzęg 0 daje końcówki. Inny kod połączy skład z tym, co stoi za nim, a symulator nie założy końcówek.</String>
<String key="CouplingLastNote">Ostatni pojazd: sprzęg 0 daje końcówki, a inny kod połączy skład z tym, co stoi za nim, bez końcówek. Starter ustawia tu 0 po każdej zmianie składu, chyba że ustawisz sprzęg ręcznie.</String>
<String key="Join">Złącz</String>
<String key="TipJoin">Połącz ten pojazd z następnym w jeden zespół</String>
<String key="TipReorder">Przeciągnij, aby zmienić kolejność</String>

View File

@@ -280,7 +280,7 @@
<String key="TipSplit">Разделить сцеп на отдельные вагоны</String>
<String key="AppliesToUnit">Общее для всего состава</String>
<String key="CouplingUnitRear">Сцепка в конце состава</String>
<String key="CouplingLastNote">Последняя единица: сцепка 0 даёт хвостовые сигналы. Другой код сцепит состав с тем, что стоит за ним, и симулятор не поставит хвостовые сигналы.</String>
<String key="CouplingLastNote">Последняя единица: сцепка 0 даёт хвостовые сигналы, другой код сцепит состав с тем, что стоит за ним, без хвостовых сигналов. Стартер ставит здесь 0 после каждого изменения состава, если вы не задали сцепку вручную.</String>
<String key="Join">Соединить</String>
<String key="TipJoin">Соединить этот вагон со следующим в один состав</String>
<String key="TipReorder">Перетащите для изменения порядка</String>