From 29946e95b2bdb2cfd8499d139941dc9c40a79381 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 17 Jul 2024 18:02:26 +0100 Subject: [PATCH] Fix refit in station when using articulated vehicles and simultaneous unload --- src/economy.cpp | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/economy.cpp b/src/economy.cpp index 3aff51a1e5..41e54be13d 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1658,6 +1658,22 @@ struct IsEmptyAction } }; +/** + * Action to check if a vehicle is unloading cargo. + */ +struct IsUnloadingAction +{ + /** + * Checks if the vehicle is unloading cargo. + * @param v Vehicle to be checked. + * @return true if v is unloading, false otherwise. + */ + bool operator()(const Vehicle *v) + { + return HasBit(v->vehicle_flags, VF_CARGO_UNLOADING); + } +}; + /** * Action to check whether a vehicle is wholly in the platform. */ @@ -1774,14 +1790,14 @@ struct FinalizeRefitAction /** * Refit a vehicle in a station. * @param v Vehicle to be refitted. + * @param v_start v->GetFirstEnginePart(). * @param consist_capleft Added cargo capacities in the consist. * @param st Station the vehicle is loading at. * @param next_station Possible next stations the vehicle can travel to. * @param new_cid Target cargo for refit. */ -static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, CargoStationIDStackSet next_station, CargoID new_cid) +static void HandleStationRefit(Vehicle *v, Vehicle *v_start, CargoArray &consist_capleft, Station *st, CargoStationIDStackSet next_station, CargoID new_cid) { - Vehicle *v_start = v->GetFirstEnginePart(); if (!IterateVehicleParts(v_start, IsEmptyAction())) return; if (v->type == VEH_TRAIN && !IterateVehicleParts(v_start, ThroughLoadTrainInPlatformAction())) return; @@ -2039,6 +2055,7 @@ static void LoadUnloadVehicle(Vehicle *front) CargoPayment *payment = front->cargo_payment; uint artic_part = 0; // Articulated part we are currently trying to load. (not counting parts without capacity) + bool suppress_artic_load = false; for (Vehicle *v = front; v != nullptr; v = v->Next()) { if (pull_through_mode && HasBit(Train::From(v)->flags, VRF_BEYOND_PLATFORM_END)) { if (v->cargo_cap != 0) { @@ -2076,7 +2093,10 @@ static void LoadUnloadVehicle(Vehicle *front) } platform_length_left -= length; } - if (v == front || !v->Previous()->HasArticulatedPart()) artic_part = 0; + if (v == front || !v->IsArticulatedPart()) { + artic_part = 0; + suppress_artic_load = false; + } if (v->cargo_cap == 0) continue; artic_part++; @@ -2151,7 +2171,9 @@ static void LoadUnloadVehicle(Vehicle *front) /* We have finished unloading (cargo count == 0) */ ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING); } - + if (front->current_order.IsRefit() && front->current_order.GetRefitCargo() != v->cargo_type) { + suppress_artic_load = true; + } continue; } @@ -2161,11 +2183,18 @@ static void LoadUnloadVehicle(Vehicle *front) /* This order has a refit, if this is the first vehicle part carrying cargo and the whole vehicle is empty, try refitting. */ if (front->current_order.IsRefit() && artic_part == 1) { - HandleStationRefit(v, consist_capleft, st, next_station, front->current_order.GetRefitCargo()); + Vehicle *v_start = v->GetFirstEnginePart(); + if (front->current_order.GetRefitCargo() != v->cargo_type && IterateVehicleParts(v_start, IsUnloadingAction())) { + suppress_artic_load = true; + continue; + } + HandleStationRefit(v, v_start, consist_capleft, st, next_station, front->current_order.GetRefitCargo()); ge = &st->goods[v->cargo_type]; ged = &ge->CreateData(); } + if (suppress_artic_load) continue; + /* Do not pick up goods when we have no-load set. */ if (GetLoadType(v) & OLFB_NO_LOAD) continue;