Fix refit in station when using articulated vehicles and simultaneous unload

This commit is contained in:
Jonathan G Rennison 2024-07-17 18:02:26 +01:00
parent e6bb811ca9
commit 29946e95b2

View File

@ -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. * Action to check whether a vehicle is wholly in the platform.
*/ */
@ -1774,14 +1790,14 @@ struct FinalizeRefitAction
/** /**
* Refit a vehicle in a station. * Refit a vehicle in a station.
* @param v Vehicle to be refitted. * @param v Vehicle to be refitted.
* @param v_start v->GetFirstEnginePart().
* @param consist_capleft Added cargo capacities in the consist. * @param consist_capleft Added cargo capacities in the consist.
* @param st Station the vehicle is loading at. * @param st Station the vehicle is loading at.
* @param next_station Possible next stations the vehicle can travel to. * @param next_station Possible next stations the vehicle can travel to.
* @param new_cid Target cargo for refit. * @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 (!IterateVehicleParts(v_start, IsEmptyAction())) return;
if (v->type == VEH_TRAIN && !IterateVehicleParts(v_start, ThroughLoadTrainInPlatformAction())) 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; CargoPayment *payment = front->cargo_payment;
uint artic_part = 0; // Articulated part we are currently trying to load. (not counting parts without capacity) 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()) { for (Vehicle *v = front; v != nullptr; v = v->Next()) {
if (pull_through_mode && HasBit(Train::From(v)->flags, VRF_BEYOND_PLATFORM_END)) { if (pull_through_mode && HasBit(Train::From(v)->flags, VRF_BEYOND_PLATFORM_END)) {
if (v->cargo_cap != 0) { if (v->cargo_cap != 0) {
@ -2076,7 +2093,10 @@ static void LoadUnloadVehicle(Vehicle *front)
} }
platform_length_left -= length; 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; if (v->cargo_cap == 0) continue;
artic_part++; artic_part++;
@ -2151,7 +2171,9 @@ static void LoadUnloadVehicle(Vehicle *front)
/* We have finished unloading (cargo count == 0) */ /* We have finished unloading (cargo count == 0) */
ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING); ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
} }
if (front->current_order.IsRefit() && front->current_order.GetRefitCargo() != v->cargo_type) {
suppress_artic_load = true;
}
continue; 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. */ /* 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) { 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]; ge = &st->goods[v->cargo_type];
ged = &ge->CreateData(); ged = &ge->CreateData();
} }
if (suppress_artic_load) continue;
/* Do not pick up goods when we have no-load set. */ /* Do not pick up goods when we have no-load set. */
if (GetLoadType(v) & OLFB_NO_LOAD) continue; if (GetLoadType(v) & OLFB_NO_LOAD) continue;