diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 7d888dabbc..9c9844bda1 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -517,7 +517,8 @@ CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 * @param tile unused * @param flags type of operation * @param p1 packed VehicleListIdentifier - * @param p2 unused + * @param p2 bitmask + * - bit 0-7 Cargo filter * @param text the new name or an empty string when setting to the default * @return the cost of this operation or an error */ @@ -527,7 +528,7 @@ CommandCost CmdCreateGroupFromList(TileIndex tile, DoCommandFlag flags, uint32 p VehicleList list; if (!vli.UnpackIfValid(p1)) return CMD_ERROR; if (!IsCompanyBuildableVehicleType(vli.vtype)) return CMD_ERROR; - if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR; + if (!GenerateVehicleSortList(&list, vli, GB(p2, 0, 8))) return CMD_ERROR; CommandCost ret = DoCommand(tile, vli.vtype, INVALID_GROUP, flags, CMD_CREATE_GROUP); if (ret.Failed()) return ret; diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 2fadb0a0ac..b1d007b040 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -881,7 +881,7 @@ public: case WID_GL_START_ALL: case WID_GL_STOP_ALL: { // Start/stop all vehicles of the list - DoCommandP(0, (1 << 1) | (widget == WID_GL_START_ALL ? (1 << 0) : 0), this->vli.Pack(), CMD_MASS_START_STOP); + DoCommandP(0, (1 << 1) | (widget == WID_GL_START_ALL ? (1 << 0) : 0) | (this->GetCargoFilter() << 8), this->vli.Pack(), CMD_MASS_START_STOP); break; } @@ -1005,7 +1005,7 @@ public: std::string name = GenerateAutoNameForVehicleGroup(v); - DoCommandP(0, VehicleListIdentifier(_ctrl_pressed ? VL_SHARED_ORDERS : VL_SINGLE_VEH, v->type, v->owner, v->index).Pack(), 0, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, name.c_str()); + DoCommandP(0, VehicleListIdentifier(_ctrl_pressed ? VL_SHARED_ORDERS : VL_SINGLE_VEH, v->type, v->owner, v->index).Pack(), CF_ANY, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, name.c_str()); break; } @@ -1060,14 +1060,14 @@ public: break; case ADI_SERVICE: // Send for servicing case ADI_DEPOT: { // Send to Depots - DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : 0U), this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); + DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : 0U) | this->GetCargoFilter(), this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); break; } case ADI_DEPOT_SELL: - DoCommandP(0, DEPOT_MASS_SEND | DEPOT_SELL, this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); + DoCommandP(0, DEPOT_MASS_SEND | DEPOT_SELL | this->GetCargoFilter(), this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); break; case ADI_CANCEL_DEPOT: - DoCommandP(0, DEPOT_MASS_SEND | DEPOT_CANCEL, this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); + DoCommandP(0, DEPOT_MASS_SEND | DEPOT_CANCEL | this->GetCargoFilter(), this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype)); break; case ADI_ADD_SHARED: // Add shared Vehicles diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 406fa19d0e..08493f4534 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -3508,6 +3508,7 @@ bool Order::CanLeaveWithCargo(bool has_cargo, CargoID cargo) const * - p1 = (bit 0 - 15) - The destination ID to change from * - p1 = (bit 16 - 18) - The vehicle type * - p1 = (bit 20 - 23) - The order type + * - p1 = (bit 24 - 31) - Cargo filter * @param p2 various bitstuffed elements * - p2 = (bit 0 - 15) - The destination ID to change to * @param text unused @@ -3518,11 +3519,12 @@ CommandCost CmdMassChangeOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, u DestinationID from_dest = GB(p1, 0, 16); VehicleType vehtype = Extract(p1); OrderType order_type = (OrderType) GB(p1, 20, 4); + CargoID cargo_filter = GB(p1, 24, 8); DestinationID to_dest = GB(p2, 0, 16); if (flags & DC_EXEC) { for (Vehicle *v : Vehicle::Iterate()) { - if (v->type == vehtype && v->IsPrimaryVehicle() && CheckOwnership(v->owner).Succeeded()) { + if (v->type == vehtype && v->IsPrimaryVehicle() && CheckOwnership(v->owner).Succeeded() && VehicleCargoFilter(v, cargo_filter)) { int index = 0; bool changed = false; diff --git a/src/order_gui.cpp b/src/order_gui.cpp index e1525cea96..a1c25333b8 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -2971,7 +2971,7 @@ public: } if (this->query_text_widget == WID_O_ADD_VEH_GROUP) { - DoCommandP(0, VehicleListIdentifier(VL_SINGLE_VEH, this->vehicle->type, this->vehicle->owner, this->vehicle->index).Pack(), 0, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, str); + DoCommandP(0, VehicleListIdentifier(VL_SINGLE_VEH, this->vehicle->type, this->vehicle->owner, this->vehicle->index).Pack(), CF_ANY, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, str); } } diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index faa41faac1..bc0350b7f9 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -1146,7 +1146,7 @@ struct TimetableWindow : GeneralVehicleWindow { } case WID_VT_ADD_VEH_GROUP: { - DoCommandP(0, VehicleListIdentifier(VL_SINGLE_VEH, v->type, v->owner, v->index).Pack(), 0, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, str); + DoCommandP(0, VehicleListIdentifier(VL_SINGLE_VEH, v->type, v->owner, v->index).Pack(), CF_ANY, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, str); break; } } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 07a738be7e..37be3a97ed 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -704,6 +704,7 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, * @param p1 bitmask * - bit 0 set = start vehicles, unset = stop vehicles * - bit 1 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case + * - bit 8-15 Cargo filter * @param p2 packed VehicleListIdentifier * @param text unused * @return the cost of this operation or an error @@ -719,7 +720,7 @@ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 if (!IsCompanyBuildableVehicleType(vli.vtype)) return CMD_ERROR; if (vehicle_list_window) { - if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR; + if (!GenerateVehicleSortList(&list, vli, GB(p1, 8, 8))) return CMD_ERROR; } else { if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; /* Get the list of vehicles in the depot */ @@ -1657,11 +1658,11 @@ CommandCost CmdCloneVehicleFromTemplate(TileIndex tile, DoCommandFlag flags, uin * @param vli identifier of the vehicle list * @return 0 for success and CMD_ERROR if no vehicle is able to go to depot */ -static CommandCost SendAllVehiclesToDepot(DoCommandFlag flags, DepotCommand depot_flags, const VehicleListIdentifier &vli) +static CommandCost SendAllVehiclesToDepot(DoCommandFlag flags, DepotCommand depot_flags, const VehicleListIdentifier &vli, const CargoID cid) { VehicleList list; - if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR; + if (!GenerateVehicleSortList(&list, vli, cid)) return CMD_ERROR; /* Send all the vehicles to a depot */ bool had_success = false; @@ -1688,7 +1689,8 @@ static CommandCost SendAllVehiclesToDepot(DoCommandFlag flags, DepotCommand depo * @param tile unused * @param flags for command type * @param p1 bitmask - * - p1 0-20: bitvehicle ID to send to the depot + * - p1 0-19: bitvehicle ID to send to the depot + * - p1 0- 7: cargo filter for DEPOT_MASS_SEND mode * - p1 bits 27-31 - DEPOT_ flags (see vehicle_type.h) * @param p2 packed VehicleListIdentifier, or specific depot tile * @param text unused @@ -1702,7 +1704,7 @@ CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1 if (!vli.UnpackIfValid(p2)) return CMD_ERROR; uint32 depot_flags = (p1 & (DEPOT_SERVICE | DEPOT_CANCEL | DEPOT_SELL)); if (!(p1 & DEPOT_CANCEL)) depot_flags |= DEPOT_DONT_CANCEL; - return SendAllVehiclesToDepot(flags, (DepotCommand) depot_flags, vli); + return SendAllVehiclesToDepot(flags, (DepotCommand) depot_flags, vli, GB(p1, 0, 8)); } Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20)); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 75c0abec90..f373a851e8 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -274,45 +274,11 @@ void BaseVehicleListWindow::BuildVehicleList() this->vscroll->SetCount(static_cast(this->vehgroups.size())); } -/** Cargo filter functions */ -static bool CargoFilter(const Vehicle * const *vid, const CargoID cid) -{ - if (cid == BaseVehicleListWindow::CF_ANY) { - return true; - } else if (cid == BaseVehicleListWindow::CF_NONE) { - for (const Vehicle *w = (*vid); w != nullptr; w = w->Next()) { - if (w->cargo_cap > 0) { - return false; - } - } - return true; - } else if (cid == BaseVehicleListWindow::CF_FREIGHT) { - bool have_capacity = false; - for (const Vehicle *w = (*vid); w != nullptr; w = w->Next()) { - if (w->cargo_cap) { - if (IsCargoInClass(w->cargo_type, CC_PASSENGERS)) { - return false; - } else { - have_capacity = true; - } - } - } - return have_capacity; - } else { - for (const Vehicle *w = (*vid); w != nullptr; w = w->Next()) { - if (w->cargo_cap > 0 && w->cargo_type == cid) { - return true; - } - } - return false; - } -} - static bool GroupCargoFilter(const GUIVehicleGroup* group, const CargoID cid) { - if (cid == BaseVehicleListWindow::CF_ANY) return true; + if (cid == CF_ANY) return true; for (VehicleList::const_iterator v = group->vehicles_begin; v != group->vehicles_end; ++v) { - if (CargoFilter(&(*v), cid)) return true; + if (VehicleCargoFilter(*v, cid)) return true; } return false; } @@ -2413,7 +2379,7 @@ public: case WID_VL_STOP_ALL: case WID_VL_START_ALL: - DoCommandP(0, (1 << 1) | (widget == WID_VL_START_ALL ? (1 << 0) : 0), this->window_number, CMD_MASS_START_STOP); + DoCommandP(0, (1 << 1) | (widget == WID_VL_START_ALL ? (1 << 0) : 0) | (this->GetCargoFilter() << 8), this->window_number, CMD_MASS_START_STOP); break; } } @@ -2446,14 +2412,14 @@ public: break; case ADI_SERVICE: // Send for servicing case ADI_DEPOT: // Send to Depots - DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : (DepotCommand)0), this->window_number, GetCmdSendToDepot(this->vli.vtype)); + DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : (DepotCommand)0) | this->GetCargoFilter(), this->window_number, GetCmdSendToDepot(this->vli.vtype)); break; case ADI_CANCEL_DEPOT: - DoCommandP(0, DEPOT_MASS_SEND | DEPOT_CANCEL, this->window_number, GetCmdSendToDepot(this->vli.vtype)); + DoCommandP(0, DEPOT_MASS_SEND | DEPOT_CANCEL | this->GetCargoFilter(), this->window_number, GetCmdSendToDepot(this->vli.vtype)); break; case ADI_DEPOT_SELL: - DoCommandP(0, DEPOT_MASS_SEND | DEPOT_SELL, this->window_number, GetCmdSendToDepot(this->vli.vtype)); + DoCommandP(0, DEPOT_MASS_SEND | DEPOT_SELL | this->GetCargoFilter(), this->window_number, GetCmdSendToDepot(this->vli.vtype)); break; case ADI_CHANGE_ORDER: @@ -2487,7 +2453,7 @@ public: void OnQueryTextFinished(char *str) override { - DoCommandP(0, this->window_number, 0, CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, str); + DoCommandP(0, this->window_number, this->GetCargoFilter(), CMD_CREATE_GROUP_FROM_LIST | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), nullptr, str); } virtual void OnPlaceObject(Point pt, TileIndex tile) override @@ -2499,7 +2465,7 @@ public: if (this->vli.vtype == VEH_ROAD && GetPresentRoadTramTypes(Depot::Get(this->vli.index)->xy) != GetPresentRoadTramTypes(tile)) return; DestinationID dest = (this->vli.vtype == VEH_AIRCRAFT) ? GetStationIndex(tile) : GetDepotIndex(tile); - DoCommandP(0, this->vli.index | (this->vli.vtype << 16) | (OT_GOTO_DEPOT << 20), dest, CMD_MASS_CHANGE_ORDER); + DoCommandP(0, this->vli.index | (this->vli.vtype << 16) | (OT_GOTO_DEPOT << 20) | (this->GetCargoFilter() << 24), dest, CMD_MASS_CHANGE_ORDER); ResetObjectToPlace(); return; } @@ -2510,7 +2476,7 @@ public: || (IsBuoyTile(tile) && this->vli.vtype == VEH_SHIP)) { if (this->vli.type != VL_STATION_LIST) return; if (!(Station::Get(this->vli.index)->facilities & FACIL_WAYPOINT)) return; - DoCommandP(0, this->vli.index | (this->vli.vtype << 16) | (OT_GOTO_WAYPOINT << 20), GetStationIndex(tile), CMD_MASS_CHANGE_ORDER); + DoCommandP(0, this->vli.index | (this->vli.vtype << 16) | (OT_GOTO_WAYPOINT << 20) | (this->GetCargoFilter() << 24), GetStationIndex(tile), CMD_MASS_CHANGE_ORDER); ResetObjectToPlace(); return; } @@ -2528,7 +2494,7 @@ public: (this->vli.vtype == VEH_TRAIN && st->facilities & FACIL_TRAIN) || (this->vli.vtype == VEH_AIRCRAFT && st->facilities & FACIL_AIRPORT) || (this->vli.vtype == VEH_ROAD && st->facilities & (FACIL_BUS_STOP | FACIL_TRUCK_STOP))) { - DoCommandP(0, this->vli.index | (this->vli.vtype << 16) | (OT_GOTO_STATION << 20), GetStationIndex(tile), CMD_MASS_CHANGE_ORDER); + DoCommandP(0, this->vli.index | (this->vli.vtype << 16) | (OT_GOTO_STATION << 20) | (this->GetCargoFilter() << 24), GetStationIndex(tile), CMD_MASS_CHANGE_ORDER); ResetObjectToPlace(); return; } diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index f904a3600e..cfb556db92 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -92,17 +92,12 @@ public: typedef GUIVehicleGroupList::SortFunction VehicleGroupSortFunction; typedef GUIVehicleList::SortFunction VehicleIndividualSortFunction; - /** Special cargo filter criteria */ - enum CargoFilterSpecialType { - CF_ANY = CT_NO_REFIT, ///< Show all vehicles independent of carried cargo (i.e. no filtering) - CF_NONE = CT_INVALID, ///< Show only vehicles which do not carry cargo (e.g. train engines) - CF_FREIGHT = CT_AUTO_REFIT, ///< Show only vehicles which carry any freight (non-passenger) cargo - }; - CargoID cargo_filter[NUM_CARGO + 3]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE StringID cargo_filter_texts[NUM_CARGO + 4]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID byte cargo_filter_criteria; ///< Selected cargo filter + inline CargoID GetCargoFilter() const { return this->cargo_filter[this->cargo_filter_criteria]; } + enum ActionDropdownItem { ADI_TEMPLATE_REPLACE, ADI_REPLACE, diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp index b3d365eea3..76bdff3d32 100644 --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -106,20 +106,58 @@ void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine if (wagons != nullptr && wagons != engines) wagons->shrink_to_fit(); } +/** Cargo filter functions */ +bool VehicleCargoFilter(const Vehicle *v, const CargoID cid) +{ + if (cid == CF_ANY) { + return true; + } else if (cid == CF_NONE) { + for (const Vehicle *w = v; w != nullptr; w = w->Next()) { + if (w->cargo_cap > 0) { + return false; + } + } + return true; + } else if (cid == CF_FREIGHT) { + bool have_capacity = false; + for (const Vehicle *w = v; w != nullptr; w = w->Next()) { + if (w->cargo_cap) { + if (IsCargoInClass(w->cargo_type, CC_PASSENGERS)) { + return false; + } else { + have_capacity = true; + } + } + } + return have_capacity; + } else { + for (const Vehicle *w = v; w != nullptr; w = w->Next()) { + if (w->cargo_cap > 0 && w->cargo_type == cid) { + return true; + } + } + return false; + } +} + /** * Generate a list of vehicles based on window type. * @param list Pointer to list to add vehicles to * @param vli The identifier of this vehicle list. * @return false if invalid list is requested */ -bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli) +bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli, const CargoID cid) { list->clear(); + auto add_veh = [&](const Vehicle *v) { + if (cid == CF_ANY || VehicleCargoFilter(v, cid)) list->push_back(v); + }; + auto fill_all_vehicles = [&]() { for (const Vehicle *v : Vehicle::Iterate()) { if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->type == vli.vtype && v->owner == vli.company && v->IsPrimaryVehicle()) { - list->push_back(v); + add_veh(v); } } }; @@ -131,7 +169,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli for (const Order *order : v->Orders()) { if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT)) && order->GetDestination() == vli.index) { - list->push_back(v); + add_veh(v); break; } } @@ -145,7 +183,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli if (v == nullptr || v->type != vli.vtype || !v->IsPrimaryVehicle()) return false; for (; v != nullptr; v = v->NextShared()) { - list->push_back(v); + add_veh(v); } break; } @@ -155,7 +193,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli for (const Vehicle *v : Vehicle::Iterate()) { if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->type == vli.vtype && v->IsPrimaryVehicle() && v->owner == vli.company && GroupIsInGroup(v->group_id, vli.index)) { - list->push_back(v); + add_veh(v); } } break; @@ -172,7 +210,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli if (v->type == vli.vtype && v->IsPrimaryVehicle()) { for (const Order *order : v->Orders()) { if (order->IsType(OT_GOTO_DEPOT) && !(order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) && order->GetDestination() == vli.index) { - list->push_back(v); + add_veh(v); break; } } @@ -187,7 +225,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(vli.index); if (slot == nullptr) return false; for (VehicleID id : slot->occupants) { - list->push_back(Vehicle::Get(id)); + add_veh(Vehicle::Get(id)); } } break; @@ -195,7 +233,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli case VL_SINGLE_VEH: { const Vehicle *v = Vehicle::GetIfValid(vli.index); - if (v != nullptr) list->push_back(v); + if (v != nullptr) add_veh(v); break; } diff --git a/src/vehiclelist.h b/src/vehiclelist.h index c17a9f8d51..690c6ba33a 100644 --- a/src/vehiclelist.h +++ b/src/vehiclelist.h @@ -14,6 +14,7 @@ #include "vehicle_type.h" #include "company_type.h" #include "tile_type.h" +#include "cargo_type.h" /** Vehicle List type flags */ enum VehicleListType { @@ -51,10 +52,18 @@ struct VehicleListIdentifier { VehicleListIdentifier() : type(), vtype(), company(), index() {} }; +/** Special cargo filter criteria */ +enum VehicleCargoFilterSpecialType { + CF_ANY = CT_NO_REFIT, ///< Show all vehicles independent of carried cargo (i.e. no filtering) + CF_NONE = CT_INVALID, ///< Show only vehicles which do not carry cargo (e.g. train engines) + CF_FREIGHT = CT_AUTO_REFIT, ///< Show only vehicles which carry any freight (non-passenger) cargo +}; + /** A list of vehicles. */ typedef std::vector VehicleList; -bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &identifier); +bool VehicleCargoFilter(const Vehicle *v, const CargoID cid); +bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &identifier, const CargoID cid = CF_ANY); void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine_list, VehicleList *wagon_list, bool individual_wagons = false); uint GetUnitNumberDigits(VehicleList &vehicles);