Keep the crew when a vehicle is swapped in the depot

The crew was copied to the card but not to the new cars, which are what is
shown and exported, so a swapped locomotive came out unstaffed. Swapping now
moves the crew over and otherwise staffs the vehicle as adding would.
This commit is contained in:
maj00r
2026-10-04 13:31:53 +02:00
parent 76f104798c
commit 04f6a4cc8d
3 changed files with 160 additions and 26 deletions

View File

@@ -236,6 +236,57 @@ public sealed class Consist : IReadOnlyList<ConsistItem>
public void Insert(int at, ConsistItem item) =>
_items.Insert(Math.Clamp(at, 0, _items.Count), item);
/// <summary>
/// Crew for a vehicle joining at position: a driver in cab A when it is powered
/// and either leads or the consist has no driver yet, nobody otherwise.
/// </summary>
public void Staff(ConsistItem item, int position)
{
item.Driver = eDriverType.Nobody;
foreach (var car in item.Cars)
car.DriverType = eDriverType.Nobody;
if (!IsPowered(item))
return;
bool staffed = _items.Any(other => !ReferenceEquals(other, item) &&
other.Driver is eDriverType.Headdriver or eDriverType.Reardriver);
if (position == 0 || !staffed)
Crew(item, eDriverType.Headdriver);
}
/// <summary>
/// Puts item in place of the vehicle at index. Its crew moves over where the
/// replacement can take it - a driver only into something powered - and the
/// rest is staffed as a newly added vehicle would be.
/// </summary>
public void Replace(int index, ConsistItem item)
{
var replaced = _items[index];
_items[index] = item;
Staff(item, index);
var crew = replaced.Driver;
if (crew == eDriverType.Passenger ||
(crew is eDriverType.Headdriver or eDriverType.Reardriver && IsPowered(item)))
Crew(item, crew);
}
// The crew lives on the cars - they are what is shown and exported - and the
// card only mirrors it.
private static void Crew(ConsistItem item, eDriverType crew)
{
if (item.Cars.Count == 0)
return;
item.Cars[0].DriverType = crew;
item.Driver = crew;
}
private bool IsPowered(ConsistItem item) =>
item.Cars.Count > 0 && _db.TextureForSkin(item.Cars[0].SkinFile) is { } texture &&
VehicleInfo.IsPoweredCategory(VehicleInfo.CategoryOf(texture));
public void MoveLeft(ConsistItem item)
{
int i = _items.IndexOf(item);

View File

@@ -573,10 +573,9 @@ public partial class Depot : UserControl
{
Cars = unit.Select(NewVehicle).ToList(),
Grouped = unit.Count > 1,
Driver = _consist.Selected.Driver,
Flipped = _consist.Selected.Flipped
};
_consist[i] = item;
_consist.Replace(i, item);
_consist.Selected = item;
_consist.AutoConnectAll();
RebuildConsist();
@@ -607,36 +606,13 @@ public partial class Depot : UserControl
};
at = Math.Clamp(at, 0, _consist.Count);
MatchOccupancy(item, at);
_consist.Staff(item, at);
_consist.Insert(at, item);
_consist.Selected = item;
_consist.AutoConnectAll();
RebuildConsist();
}
private void MatchOccupancy(ConsistItem item, int position)
{
item.Driver = eDriverType.Nobody;
var lead = item.Cars.FirstOrDefault();
if (lead is null) return;
foreach (var car in item.Cars)
car.DriverType = eDriverType.Nobody;
var tex = _db.TextureForSkin(lead.SkinFile);
string? cat = tex != null ? VehicleInfo.CategoryOf(tex) : null;
if (!VehicleInfo.IsPoweredCategory(cat))
return;
bool staffed = _consist.Any(i =>
i.Driver is eDriverType.Headdriver or eDriverType.Reardriver);
if (position == 0 || !staffed)
{
item.Driver = eDriverType.Headdriver;
lead.DriverType = eDriverType.Headdriver;
}
}
private async void TextureBaseButton_OnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
if (TopLevel.GetTopLevel(this) is not Window owner) return;