MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / CmdBuildVehicle

Function CmdBuildVehicle

src/vehicle_cmd.cpp:100–225  ·  view source on GitHub ↗

* Build a vehicle. * @param flags for command * @param tile tile of depot where the vehicle is built * @param eid vehicle type being built. * @param use_free_vehicles use free vehicles when building the vehicle. * @param cargo refit cargo type. * @param client_id User * @return the cost of this operation + the new vehicle ID + the refitted capacity + the refitted mail capacity (aircraft) or

Source from the content-addressed store, hash-verified

98 * @return the cost of this operation + the new vehicle ID + the refitted capacity + the refitted mail capacity (aircraft) or an error
99 */
100std::tuple<CommandCost, VehicleID, uint, uint16_t, CargoArray> CmdBuildVehicle(DoCommandFlags flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoType cargo, ClientID client_id)
101{
102 /* Elementary check for valid location. */
103 if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return { CMD_ERROR, VehicleID::Invalid(), 0, 0, {} };
104
105 VehicleType type = GetDepotVehicleType(tile);
106
107 /* Validate the engine type. */
108 if (!IsEngineBuildable(eid, type, _current_company)) return { CommandCost(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type), VehicleID::Invalid(), 0, 0, {} };
109
110 /* Validate the cargo type. */
111 if (cargo >= NUM_CARGO && IsValidCargoType(cargo)) return { CMD_ERROR, VehicleID::Invalid(), 0, 0, {} };
112
113 const Engine *e = Engine::Get(eid);
114 CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
115
116 /* Engines without valid cargo should not be available */
117 CargoType default_cargo = e->GetDefaultCargoType();
118 if (!IsValidCargoType(default_cargo)) return { CMD_ERROR, VehicleID::Invalid(), 0, 0, {} };
119
120 bool refitting = IsValidCargoType(cargo) && cargo != default_cargo;
121
122 /* Check whether the number of vehicles we need to build can be built according to pool space. */
123 uint num_vehicles;
124 switch (type) {
125 case VEH_TRAIN: num_vehicles = (e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); break;
126 case VEH_ROAD: num_vehicles = 1 + CountArticulatedParts(eid, false); break;
127 case VEH_SHIP: num_vehicles = 1; break;
128 case VEH_AIRCRAFT: num_vehicles = e->VehInfo<AircraftVehicleInfo>().subtype & AIR_CTOL ? 2 : 3; break;
129 default: NOT_REACHED(); // Safe due to IsDepotTile()
130 }
131 if (!Vehicle::CanAllocateItem(num_vehicles)) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), VehicleID::Invalid(), 0, 0, {} };
132
133 /* Check whether we can allocate a unit number. Autoreplace does not allocate
134 * an unit number as it will (always) reuse the one of the replaced vehicle
135 * and (train) wagons don't have an unit number in any scenario. */
136 UnitID unit_num = (flags.Test(DoCommandFlag::QueryCost) || flags.Test(DoCommandFlag::AutoReplace) || (type == VEH_TRAIN && e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type);
137 if (unit_num == UINT16_MAX) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), VehicleID::Invalid(), 0, 0, {} };
138
139 /* If we are refitting we need to temporarily purchase the vehicle to be able to
140 * test it. */
141 DoCommandFlags subflags = flags;
142 if (refitting && !flags.Test(DoCommandFlag::Execute)) subflags.Set({DoCommandFlag::Execute, DoCommandFlag::AutoReplace});
143
144 /* Vehicle construction needs random bits, so we have to save the random
145 * seeds to prevent desyncs. */
146 SavedRandomSeeds saved_seeds;
147 SaveRandomSeeds(&saved_seeds);
148
149 Vehicle *v = nullptr;
150 switch (type) {
151 case VEH_TRAIN: value.AddCost(CmdBuildRailVehicle(subflags, tile, e, &v)); break;
152 case VEH_ROAD: value.AddCost(CmdBuildRoadVehicle(subflags, tile, e, &v)); break;
153 case VEH_SHIP: value.AddCost(CmdBuildShip (subflags, tile, e, &v)); break;
154 case VEH_AIRCRAFT: value.AddCost(CmdBuildAircraft (subflags, tile, e, &v)); break;
155 default: NOT_REACHED(); // Safe due to IsDepotTile()
156 }
157

Callers

nothing calls this directly

Calls 15

IsDepotTileFunction · 0.85
IsTileOwnerFunction · 0.85
InvalidFunction · 0.85
GetDepotVehicleTypeFunction · 0.85
IsEngineBuildableFunction · 0.85
CommandCostClass · 0.85
IsValidCargoTypeFunction · 0.85
CountArticulatedPartsFunction · 0.85
NOT_REACHEDFunction · 0.85
GetFreeUnitNumberFunction · 0.85
SaveRandomSeedsFunction · 0.85
CmdBuildRailVehicleFunction · 0.85

Tested by

no test coverage detected