* Refit a vehicle in a station. * @param v Vehicle to be refitted. * @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_cargo_type Target cargo for refit. */
| 1473 | * @param new_cargo_type Target cargo for refit. |
| 1474 | */ |
| 1475 | static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, std::span<const StationID> next_station, CargoType new_cargo_type) |
| 1476 | { |
| 1477 | Vehicle *v_start = v->GetFirstEnginePart(); |
| 1478 | if (!IterateVehicleParts(v_start, IsEmptyAction())) return; |
| 1479 | |
| 1480 | Backup<CompanyID> cur_company(_current_company, v->owner); |
| 1481 | |
| 1482 | CargoTypes refit_mask = v->GetEngine()->info.refit_mask; |
| 1483 | |
| 1484 | /* Remove old capacity from consist capacity and collect refit mask. */ |
| 1485 | IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask)); |
| 1486 | |
| 1487 | bool is_auto_refit = new_cargo_type == CARGO_AUTO_REFIT; |
| 1488 | if (is_auto_refit) { |
| 1489 | /* Get a refittable cargo type with waiting cargo for next_station or StationID::Invalid(). */ |
| 1490 | new_cargo_type = v_start->cargo_type; |
| 1491 | for (CargoType cargo_type : SetCargoBitIterator(refit_mask)) { |
| 1492 | if (st->goods[cargo_type].HasData() && st->goods[cargo_type].GetData().cargo.HasCargoFor(next_station)) { |
| 1493 | /* Try to find out if auto-refitting would succeed. In case the refit is allowed, |
| 1494 | * the returned refit capacity will be greater than zero. */ |
| 1495 | auto [cc, refit_capacity, mail_capacity, cargo_capacities] = Command<CMD_REFIT_VEHICLE>::Do(DoCommandFlag::QueryCost, v_start->index, cargo_type, 0xFF, true, false, 1); // Auto-refit and only this vehicle including artic parts. |
| 1496 | /* Try to balance different loadable cargoes between parts of the consist, so that |
| 1497 | * all of them can be loaded. Avoid a situation where all vehicles suddenly switch |
| 1498 | * to the first loadable cargo for which there is only one packet. If the capacities |
| 1499 | * are equal refit to the cargo of which most is available. This is important for |
| 1500 | * consists of only a single vehicle as those will generally have a consist_capleft |
| 1501 | * of 0 for all cargoes. */ |
| 1502 | if (refit_capacity > 0 && (consist_capleft[cargo_type] < consist_capleft[new_cargo_type] || |
| 1503 | (consist_capleft[cargo_type] == consist_capleft[new_cargo_type] && |
| 1504 | st->goods[cargo_type].AvailableCount() > st->goods[new_cargo_type].AvailableCount()))) { |
| 1505 | new_cargo_type = cargo_type; |
| 1506 | } |
| 1507 | } |
| 1508 | } |
| 1509 | } |
| 1510 | |
| 1511 | /* Refit if given a valid cargo. */ |
| 1512 | if (new_cargo_type < NUM_CARGO && new_cargo_type != v_start->cargo_type) { |
| 1513 | /* StationID::Invalid() because in the DT_MANUAL case that's correct and in the DT_(A)SYMMETRIC |
| 1514 | * cases the next hop of the vehicle doesn't really tell us anything if the cargo had been |
| 1515 | * "via any station" before reserving. We rather produce some more "any station" cargo than |
| 1516 | * misrouting it. */ |
| 1517 | IterateVehicleParts(v_start, ReturnCargoAction(st, StationID::Invalid())); |
| 1518 | CommandCost cost = std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(DoCommandFlag::Execute, v_start->index, new_cargo_type, 0xFF, true, false, 1)); // Auto-refit and only this vehicle including artic parts. |
| 1519 | if (cost.Succeeded()) v->First()->profit_this_year -= cost.GetCost() << 8; |
| 1520 | } |
| 1521 | |
| 1522 | /* Add new capacity to consist capacity and reserve cargo */ |
| 1523 | IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station, |
| 1524 | is_auto_refit || v->First()->current_order.IsFullLoadOrder())); |
| 1525 | |
| 1526 | cur_company.Restore(); |
| 1527 | } |
| 1528 | |
| 1529 | /** |
| 1530 | * Test whether a vehicle can load cargo at a station even if exclusive transport rights are present. |
no test coverage detected