File diff r27420:b37b70eb3169 → r27421:e8c2cdc1e8e6
src/vehicle_cmd.cpp
Show inline comments
 
@@ -74,58 +74,58 @@ const StringID _send_to_depot_msg_table[
 
};
 

	
 

	
 
/**
 
 * 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 an error
 
 */
 
std::tuple<CommandCost, VehicleID, uint, uint16, CargoArray> CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id)
 
{
 
	/* Elementary check for valid location. */
 
	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
 

	
 
	VehicleType type = GetDepotVehicleType(tile);
 

	
 
	/* Validate the engine type. */
 
	if (!IsEngineBuildable(eid, type, _current_company)) return { CommandCost(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type), INVALID_VEHICLE, 0, 0, {} };
 

	
 
	/* Validate the cargo type. */
 
	if (cargo >= NUM_CARGO && cargo != CT_INVALID) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
 
	if (cargo >= NUM_CARGO && IsValidCargoID(cargo)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
 

	
 
	const Engine *e = Engine::Get(eid);
 
	CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
 

	
 
	/* Engines without valid cargo should not be available */
 
	CargoID default_cargo = e->GetDefaultCargoType();
 
	if (default_cargo == CT_INVALID) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
 
	if (!IsValidCargoID(default_cargo)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
 

	
 
	bool refitting = cargo != CT_INVALID && cargo != default_cargo;
 
	bool refitting = IsValidCargoID(cargo) && cargo != default_cargo;
 

	
 
	/* Check whether the number of vehicles we need to build can be built according to pool space. */
 
	uint num_vehicles;
 
	switch (type) {
 
		case VEH_TRAIN:    num_vehicles = (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); break;
 
		case VEH_ROAD:     num_vehicles = 1 + CountArticulatedParts(eid, false); break;
 
		case VEH_SHIP:     num_vehicles = 1; break;
 
		case VEH_AIRCRAFT: num_vehicles = e->u.air.subtype & AIR_CTOL ? 2 : 3; break;
 
		default: NOT_REACHED(); // Safe due to IsDepotTile()
 
	}
 
	if (!Vehicle::CanAllocateItem(num_vehicles)) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE, 0, 0, {} };
 

	
 
	/* Check whether we can allocate a unit number. Autoreplace does not allocate
 
	 * an unit number as it will (always) reuse the one of the replaced vehicle
 
	 * and (train) wagons don't have an unit number in any scenario. */
 
	UnitID unit_num = (flags & DC_QUERY_COST || flags & DC_AUTOREPLACE || (type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type);
 
	if (unit_num == UINT16_MAX) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE, 0, 0, {} };
 

	
 
	/* If we are refitting we need to temporarily purchase the vehicle to be able to
 
	 * test it. */
 
	DoCommandFlag subflags = flags;
 
	if (refitting && !(flags & DC_EXEC)) subflags |= DC_EXEC | DC_AUTOREPLACE;
 

	
 
	/* Vehicle construction needs random bits, so we have to save the random
 
@@ -930,49 +930,49 @@ std::tuple<CommandCost, VehicleID> CmdCl
 
	 * different numbers of articulated parts, so when refitting we have to
 
	 * loop over real vehicles first, and then the articulated parts of those
 
	 * vehicles in a different loop. */
 
	do {
 
		do {
 
			if (flags & DC_EXEC) {
 
				assert(w != nullptr);
 

	
 
				/* Find out what's the best sub type */
 
				byte subtype = GetBestFittingSubType(v, w, v->cargo_type);
 
				if (w->cargo_type != v->cargo_type || w->cargo_subtype != subtype) {
 
					CommandCost cost = std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(flags, w->index, v->cargo_type, subtype, false, true, 0));
 
					if (cost.Succeeded()) total_cost.AddCost(cost);
 
				}
 

	
 
				if (w->IsGroundVehicle() && w->HasArticulatedPart()) {
 
					w = w->GetNextArticulatedPart();
 
				} else {
 
					break;
 
				}
 
			} else {
 
				const Engine *e = v->GetEngine();
 
				CargoID initial_cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : (CargoID)CT_INVALID);
 

	
 
				if (v->cargo_type != initial_cargo && initial_cargo != CT_INVALID) {
 
				if (v->cargo_type != initial_cargo && IsValidCargoID(initial_cargo)) {
 
					bool dummy;
 
					total_cost.AddCost(GetRefitCost(nullptr, v->engine_type, v->cargo_type, v->cargo_subtype, &dummy));
 
				}
 
			}
 

	
 
			if (v->IsGroundVehicle() && v->HasArticulatedPart()) {
 
				v = v->GetNextArticulatedPart();
 
			} else {
 
				break;
 
			}
 
		} while (v != nullptr);
 

	
 
		if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = w->GetNextVehicle();
 
	} while (v->type == VEH_TRAIN && (v = v->GetNextVehicle()) != nullptr);
 

	
 
	if (flags & DC_EXEC) {
 
		/*
 
		 * Set the orders of the vehicle. Cannot do it earlier as we need
 
		 * the vehicle refitted before doing this, otherwise the moved
 
		 * cargo types might not match (passenger vs non-passenger)
 
		 */
 
		CommandCost result = Command<CMD_CLONE_ORDER>::Do(flags, (share_orders ? CO_SHARE : CO_COPY), w_front->index, v_front->index);
 
		if (result.Failed()) {
 
			/* The vehicle has already been bought, so now it must be sold again. */