Changeset - r15839:2b7528d029e3
[Not reviewed]
master
0 7 0
rubidium - 14 years ago 2010-08-17 23:15:55
rubidium@openttd.org
(svn r20531) -Codechange: unify quite a bit of the vehicle building commands
7 files changed with 155 insertions and 231 deletions:
0 comments (0 inline, 0 general)
src/aircraft_cmd.cpp
Show inline comments
 
@@ -215,48 +215,25 @@ void GetAircraftSpriteSize(EngineID engi
 

	
 
/**
 
 * Build an aircraft.
 
 * @param tile tile of depot where aircraft is built
 
 * @param flags for command
 
 * @param p1 aircraft type being built (engine)
 
 * @param p2 unused
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 * @param tile     tile of the depot where aircraft is built.
 
 * @param flags    type of operation.
 
 * @param e        the engine to build.
 
 * @param data     unused.
 
 * @param ret[out] the vehicle that has been built.
 
 * @return the cost of this operation or an error.
 
 */
 
CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
 
{
 
	EngineID eid = GB(p1, 0, 16);
 
	if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _current_company)) return_cmd_error(STR_ERROR_AIRCRAFT_NOT_AVAILABLE);
 

	
 
	const Engine *e = Engine::Get(eid);
 
	const AircraftVehicleInfo *avi = &e->u.air;
 
	CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
 

	
 
	/* Engines without valid cargo should not be available */
 
	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
 

	
 
	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
 
	if (flags & DC_QUERY_COST) return value;
 

	
 
	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
 

	
 
	/* Prevent building aircraft types at places which can't handle them */
 
	if (!CanVehicleUseStation(eid, Station::GetByTile(tile))) return CMD_ERROR;
 

	
 
	/* We will need to allocate 2 or 3 vehicle structs, depending on type */
 
	if (!Vehicle::CanAllocateItem(avi->subtype & AIR_CTOL ? 2 : 3)) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	UnitID unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_AIRCRAFT);
 
	if (unit_num > _settings_game.vehicle.max_aircraft) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 
	if (!CanVehicleUseStation(e->index, Station::GetByTile(tile))) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		Aircraft *v = new Aircraft(); // aircraft
 
		Aircraft *u = new Aircraft(); // shadow
 
		*ret = v;
 

	
 
		v->unitnumber = unit_num;
 
		v->direction = DIR_SE;
 

	
 
		v->owner = u->owner = _current_company;
 
@@ -288,12 +265,11 @@ CommandCost CmdBuildAircraft(TileIndex t
 

	
 
		v->max_speed = avi->max_speed;
 
		v->acceleration = avi->acceleration;
 
		v->engine_type = eid;
 
		u->engine_type = eid;
 
		v->engine_type = e->index;
 
		u->engine_type = e->index;
 

	
 
		v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER);
 
		v->UpdateDeltaXY(INVALID_DIR);
 
		v->value = value.GetCost();
 

	
 
		u->subtype = AIR_SHADOW;
 
		u->UpdateDeltaXY(INVALID_DIR);
 
@@ -338,7 +314,7 @@ CommandCost CmdBuildAircraft(TileIndex t
 
		/* Aircraft with 3 vehicles (chopper)? */
 
		if (v->subtype == AIR_HELICOPTER) {
 
			Aircraft *w = new Aircraft();
 
			w->engine_type = eid;
 
			w->engine_type = e->index;
 
			w->direction = DIR_N;
 
			w->owner = _current_company;
 
			w->x_pos = v->x_pos;
 
@@ -356,18 +332,9 @@ CommandCost CmdBuildAircraft(TileIndex t
 
			u->SetNext(w);
 
			VehicleMove(w, false);
 
		}
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Aircraft window
 
		}
 

	
 
		Company::Get(_current_company)->num_engines[eid]++;
 
	}
 

	
 
	return value;
 
	return CommandCost();
 
}
 

	
 

	
src/command.cpp
Show inline comments
 
@@ -77,9 +77,9 @@ CommandProc CmdBuildBuoy;
 

	
 
CommandProc CmdPlantTree;
 

	
 
CommandProc CmdBuildRailVehicle;
 
CommandProc CmdMoveRailVehicle;
 

	
 
CommandProc CmdBuildVehicle;
 
CommandProc CmdSellRailWagon;
 

	
 
CommandProc CmdSendTrainToDepot;
 
@@ -113,14 +113,12 @@ CommandProc CmdRenameStation;
 
CommandProc CmdRenameDepot;
 

	
 
CommandProc CmdSellAircraft;
 
CommandProc CmdBuildAircraft;
 
CommandProc CmdSendAircraftToHangar;
 
CommandProc CmdRefitAircraft;
 

	
 
CommandProc CmdPlaceSign;
 
CommandProc CmdRenameSign;
 

	
 
CommandProc CmdBuildRoadVeh;
 
CommandProc CmdSellRoadVeh;
 
CommandProc CmdSendRoadVehToDepot;
 
CommandProc CmdTurnRoadVeh;
 
@@ -142,7 +140,6 @@ CommandProc CmdChangeSetting;
 
CommandProc CmdChangeCompanySetting;
 

	
 
CommandProc CmdSellShip;
 
CommandProc CmdBuildShip;
 
CommandProc CmdSendShipToDepot;
 
CommandProc CmdRefitShip;
 

	
 
@@ -229,7 +226,7 @@ static const Command _command_proc_table
 
	DEF_CMD(CmdBuildShipDepot,                          CMD_AUTO), // CMD_BUILD_SHIP_DEPOT
 
	DEF_CMD(CmdBuildBuoy,                               CMD_AUTO), // CMD_BUILD_BUOY
 
	DEF_CMD(CmdPlantTree,                               CMD_AUTO), // CMD_PLANT_TREE
 
	DEF_CMD(CmdBuildRailVehicle,                               0), // CMD_BUILD_RAIL_VEHICLE
 
	DEF_CMD(CmdBuildVehicle,                                   0), // CMD_BUILD_VEHICLE
 
	DEF_CMD(CmdMoveRailVehicle,                                0), // CMD_MOVE_RAIL_VEHICLE
 

	
 
	DEF_CMD(CmdSellRailWagon,                                  0), // CMD_SELL_RAIL_WAGON
 
@@ -264,14 +261,12 @@ static const Command _command_proc_table
 

	
 
	DEF_CMD(CmdSellAircraft,                                   0), // CMD_SELL_AIRCRAFT
 

	
 
	DEF_CMD(CmdBuildAircraft,                                  0), // CMD_BUILD_AIRCRAFT
 
	DEF_CMD(CmdSendAircraftToHangar,                           0), // CMD_SEND_AIRCRAFT_TO_HANGAR
 
	DEF_CMD(CmdRefitAircraft,                                  0), // CMD_REFIT_AIRCRAFT
 

	
 
	DEF_CMD(CmdPlaceSign,                                      0), // CMD_PLACE_SIGN
 
	DEF_CMD(CmdRenameSign,                                     0), // CMD_RENAME_SIGN
 

	
 
	DEF_CMD(CmdBuildRoadVeh,                                   0), // CMD_BUILD_ROAD_VEH
 
	DEF_CMD(CmdSellRoadVeh,                                    0), // CMD_SELL_ROAD_VEH
 
	DEF_CMD(CmdSendRoadVehToDepot,                             0), // CMD_SEND_ROADVEH_TO_DEPOT
 
	DEF_CMD(CmdTurnRoadVeh,                                    0), // CMD_TURN_ROADVEH
 
@@ -290,7 +285,6 @@ static const Command _command_proc_table
 
	DEF_CMD(CmdDeleteTown,                           CMD_OFFLINE), // CMD_DELETE_TOWN
 

	
 
	DEF_CMD(CmdSellShip,                                       0), // CMD_SELL_SHIP
 
	DEF_CMD(CmdBuildShip,                                      0), // CMD_BUILD_SHIP
 
	DEF_CMD(CmdSendShipToDepot,                                0), // CMD_SEND_SHIP_TO_DEPOT
 
	DEF_CMD(CmdRefitShip,                                      0), // CMD_REFIT_SHIP
 

	
src/command_type.h
Show inline comments
 
@@ -177,7 +177,7 @@ enum Commands {
 

	
 
	CMD_PLANT_TREE,                   ///< plant a tree
 

	
 
	CMD_BUILD_RAIL_VEHICLE,           ///< build a rail vehicle
 
	CMD_BUILD_VEHICLE,                ///< build a vehicle
 
	CMD_MOVE_RAIL_VEHICLE,            ///< move a rail vehicle (in the depot)
 

	
 
	CMD_SELL_RAIL_WAGON,              ///< sell a rail wagon
 
@@ -211,14 +211,12 @@ enum Commands {
 
	CMD_RENAME_DEPOT,                 ///< rename a depot
 

	
 
	CMD_SELL_AIRCRAFT,                ///< sell an aircraft
 
	CMD_BUILD_AIRCRAFT,               ///< build an aircraft
 
	CMD_SEND_AIRCRAFT_TO_HANGAR,      ///< send an aircraft to a hanger
 
	CMD_REFIT_AIRCRAFT,               ///< refit the cargo space of an aircraft
 

	
 
	CMD_PLACE_SIGN,                   ///< place a sign
 
	CMD_RENAME_SIGN,                  ///< rename a sign
 

	
 
	CMD_BUILD_ROAD_VEH,               ///< build a road vehicle
 
	CMD_SELL_ROAD_VEH,                ///< sell a road vehicle
 
	CMD_SEND_ROADVEH_TO_DEPOT,        ///< send a road vehicle to the depot
 
	CMD_TURN_ROADVEH,                 ///< turn a road vehicle around
 
@@ -237,7 +235,6 @@ enum Commands {
 
	CMD_DELETE_TOWN,                  ///< delete a town
 

	
 
	CMD_SELL_SHIP,                    ///< sell a ship
 
	CMD_BUILD_SHIP,                   ///< build a new ship
 
	CMD_SEND_SHIP_TO_DEPOT,           ///< send a ship to a depot
 
	CMD_REFIT_SHIP,                   ///< refit the cargo space of a ship
 

	
src/roadveh_cmd.cpp
Show inline comments
 
@@ -202,50 +202,22 @@ void RoadVehUpdateCache(RoadVehicle *v)
 

	
 
/**
 
 * Build a road vehicle.
 
 * @param tile tile of depot where road vehicle is built
 
 * @param flags operation to perform
 
 * @param p1 bus/truck type being built (engine)
 
 * @param p2 unused
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 * @param tile     tile of the depot where road vehicle is built.
 
 * @param flags    type of operation.
 
 * @param e        the engine to build.
 
 * @param data     unused.
 
 * @param ret[out] the vehicle that has been built.
 
 * @return the cost of this operation or an error.
 
 */
 
CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
 
{
 
	EngineID eid = GB(p1, 0, 16);
 
	if (!IsEngineBuildable(eid, VEH_ROAD, _current_company)) return_cmd_error(STR_ERROR_ROAD_VEHICLE_NOT_AVAILABLE);
 

	
 
	const Engine *e = Engine::Get(eid);
 
	/* Engines without valid cargo should not be available */
 
	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
 

	
 
	CommandCost cost(EXPENSES_NEW_VEHICLES, e->GetCost());
 
	if (flags & DC_QUERY_COST) return cost;
 

	
 
	/* The ai_new queries the vehicle cost before building the route,
 
	 * so we must check against cheaters no sooner than now. --pasky */
 
	if (!IsRoadDepotTile(tile)) return CMD_ERROR;
 
	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
 

	
 
	if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
 

	
 
	uint num_vehicles = 1 + CountArticulatedParts(eid, false);
 

	
 
	/* Allow for the front and the articulated parts */
 
	if (!Vehicle::CanAllocateItem(num_vehicles)) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	/* find the first free roadveh id */
 
	UnitID unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_ROAD);
 
	if (unit_num > _settings_game.vehicle.max_roadveh) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		const RoadVehicleInfo *rvi = &e->u.road;
 

	
 
		RoadVehicle *v = new RoadVehicle();
 
		v->unitnumber = unit_num;
 
		*ret = v;
 
		v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
 
		v->owner = _current_company;
 

	
 
@@ -262,11 +234,10 @@ CommandCost CmdBuildRoadVeh(TileIndex ti
 
		v->spritenum = rvi->image_index;
 
		v->cargo_type = e->GetDefaultCargoType();
 
		v->cargo_cap = rvi->capacity;
 
		v->value = cost.GetCost();
 

	
 
		v->last_station_visited = INVALID_STATION;
 
		v->max_speed = rvi->max_speed;
 
		v->engine_type = eid;
 
		v->engine_type = e->index;
 
		v->rcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
 

	
 
		v->reliability = e->reliability;
 
@@ -304,19 +275,10 @@ CommandCost CmdBuildRoadVeh(TileIndex ti
 

	
 
		VehicleMove(v, false);
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window
 
		}
 

	
 
		Company::Get(_current_company)->num_engines[eid]++;
 

	
 
		CheckConsistencyOfArticulatedVehicle(v);
 
	}
 

	
 
	return cost;
 
	return CommandCost();
 
}
 

	
 
bool RoadVehicle::IsStoppedInDepot() const
src/ship_cmd.cpp
Show inline comments
 
@@ -604,37 +604,15 @@ bool Ship::Tick()
 

	
 
/**
 
 * Build a ship.
 
 * @param tile tile of depot where ship is built
 
 * @param flags type of operation
 
 * @param p1 ship type being built (engine)
 
 * @param p2 unused
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 * @param tile     tile of the depot where ship is built.
 
 * @param flags    type of operation.
 
 * @param e        the engine to build.
 
 * @param data     unused.
 
 * @param ret[out] the vehicle that has been built.
 
 * @return the cost of this operation or an error.
 
 */
 
CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
 
{
 
	EngineID eid = GB(p1, 0, 16);
 
	UnitID unit_num;
 

	
 
	if (!IsEngineBuildable(eid, VEH_SHIP, _current_company)) return_cmd_error(STR_ERROR_SHIP_NOT_AVAILABLE);
 

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

	
 
	/* Engines without valid cargo should not be available */
 
	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
 

	
 
	if (flags & DC_QUERY_COST) return value;
 

	
 
	/* The ai_new queries the vehicle cost before building the route,
 
	 * so we must check against cheaters no sooner than now. --pasky */
 
	if (!IsShipDepotTile(tile)) return CMD_ERROR;
 
	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
 

	
 
	unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_SHIP);
 

	
 
	if (!Vehicle::CanAllocateItem() || unit_num > _settings_game.vehicle.max_ships) return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 

	
 
	if (flags & DC_EXEC) {
 
		int x;
 
		int y;
 
@@ -642,7 +620,7 @@ CommandCost CmdBuildShip(TileIndex tile,
 
		const ShipVehicleInfo *svi = &e->u.ship;
 

	
 
		Ship *v = new Ship();
 
		v->unitnumber = unit_num;
 
		*ret = v;
 

	
 
		v->owner = _current_company;
 
		v->tile = tile;
 
@@ -658,11 +636,10 @@ CommandCost CmdBuildShip(TileIndex tile,
 
		v->spritenum = svi->image_index;
 
		v->cargo_type = e->GetDefaultCargoType();
 
		v->cargo_cap = svi->capacity;
 
		v->value = value.GetCost();
 

	
 
		v->last_station_visited = INVALID_STATION;
 
		v->max_speed = svi->max_speed;
 
		v->engine_type = eid;
 
		v->engine_type = e->index;
 

	
 
		v->reliability = e->reliability;
 
		v->reliability_spd_dec = e->reliability_spd_dec;
 
@@ -686,18 +663,9 @@ CommandCost CmdBuildShip(TileIndex tile,
 
		v->InvalidateNewGRFCacheOfChain();
 

	
 
		VehicleMove(v, false);
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Ship window
 
		}
 

	
 
		Company::Get(_current_company)->num_engines[eid]++;
 
	}
 

	
 
	return value;
 
	return CommandCost();
 
}
 

	
 
/**
src/train_cmd.cpp
Show inline comments
 
@@ -574,32 +574,27 @@ void DrawTrainEngine(int left, int right
 
	}
 
}
 

	
 
static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandFlag flags)
 
/**
 
 * Build a railroad wagon.
 
 * @param tile     tile of the depot where rail-vehicle is built.
 
 * @param flags    type of operation.
 
 * @param e        the engine to build.
 
 * @param ret[out] the vehicle that has been built.
 
 * @return the cost of this operation or an error.
 
 */
 
CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const Engine *e, Vehicle **ret)
 
{
 
	const Engine *e = Engine::Get(engine);
 
	const RailVehicleInfo *rvi = &e->u.rail;
 
	CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
 

	
 
	/* Engines without valid cargo should not be available */
 
	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
 

	
 
	if (flags & DC_QUERY_COST) return value;
 

	
 
	/* Check that the wagon can drive on the track in question */
 
	if (!IsCompatibleRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
 

	
 
	uint num_vehicles = 1 + CountArticulatedParts(engine, false);
 

	
 
	/* Allow for the wagon and the articulated parts */
 
	if (!Vehicle::CanAllocateItem(num_vehicles)) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		Train *v = new Train();
 
		*ret = v;
 
		v->spritenum = rvi->image_index;
 

	
 
		v->engine_type = engine;
 
		v->engine_type = e->index;
 
		v->tcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
 

	
 
		DiagDirection dir = GetRailDepotDirection(tile);
 
@@ -624,7 +619,6 @@ static CommandCost CmdBuildRailWagon(Eng
 

	
 
		v->cargo_type = e->GetDefaultCargoType();
 
		v->cargo_cap = rvi->capacity;
 
		v->value = value.GetCost();
 

	
 
		v->railtype = rvi->railtype;
 

	
 
@@ -642,12 +636,6 @@ static CommandCost CmdBuildRailWagon(Eng
 
		v->First()->ConsistChanged(false);
 
		UpdateTrainGroupID(v->First());
 

	
 
		SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
 
		}
 
		Company::Get(_current_company)->num_engines[engine]++;
 

	
 
		CheckConsistencyOfArticulatedVehicle(v);
 

	
 
		/* Try to connect the vehicle to one of free chains of wagons. */
 
@@ -655,7 +643,7 @@ static CommandCost CmdBuildRailWagon(Eng
 
		FOR_ALL_TRAINS(w) {
 
			if (w->tile == tile &&              ///< Same depot
 
					w->IsFreeWagon() &&             ///< A free wagon chain
 
					w->engine_type == engine &&     ///< Same type
 
					w->engine_type == e->index &&   ///< Same type
 
					w->First() != v &&              ///< Don't connect to ourself
 
					!(w->vehstatus & VS_CRASHED)) { ///< Not crashed/flooded
 
				DoCommand(0, v->index | (w->Last()->index << 16), 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
 
@@ -664,7 +652,7 @@ static CommandCost CmdBuildRailWagon(Eng
 
		}
 
	}
 

	
 
	return value;
 
	return CommandCost();
 
}
 

	
 
/** Move all free vehicles in the depot to the train */
 
@@ -715,60 +703,30 @@ static void AddRearEngineToMultiheadedTr
 

	
 
/**
 
 * Build a railroad vehicle.
 
 * @param tile tile of the depot where rail-vehicle is built
 
 * @param flags type of operation
 
 * @param p1 engine type id
 
 * @param p2 bit 1 prevents any free cars from being added to the train
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 * @param tile     tile of the depot where rail-vehicle is built.
 
 * @param flags    type of operation.
 
 * @param e        the engine to build.
 
 * @param data     bit 0 prevents any free cars from being added to the train.
 
 * @param ret[out] the vehicle that has been built.
 
 * @return the cost of this operation or an error.
 
 */
 
CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
 
{
 
	EngineID eid = GB(p1, 0, 16);
 
	/* Check if the engine-type is valid (for the company) */
 
	if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company)) return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE);
 

	
 
	const Engine *e = Engine::Get(eid);
 
	const RailVehicleInfo *rvi = &e->u.rail;
 
	CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
 

	
 
	/* Engines with CT_INVALID should not be available */
 
	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
 

	
 
	if (flags & DC_QUERY_COST) return value;
 

	
 
	/* Check if the train is actually being built in a depot belonging
 
	 * to the company. Doesn't matter if only the cost is queried */
 
	if (!IsRailDepotTile(tile)) return CMD_ERROR;
 
	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
 

	
 
	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(eid, tile, flags);
 

	
 
	uint num_vehicles =
 
		(rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
 
		CountArticulatedParts(eid, false);
 

	
 
	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(tile, flags, e, ret);
 

	
 
	/* Check if depot and new engine uses the same kind of tracks *
 
	 * We need to see if the engine got power on the tile to avoid electric engines in non-electric depots */
 
	if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
 

	
 
	/* Allow for the dual-heads and the articulated parts */
 
	if (!Vehicle::CanAllocateItem(num_vehicles)) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	UnitID unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_TRAIN);
 
	if (unit_num > _settings_game.vehicle.max_trains) {
 
		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		DiagDirection dir = GetRailDepotDirection(tile);
 
		int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
 
		int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
 

	
 
		Train *v = new Train();
 
		v->unitnumber = unit_num;
 
		*ret = v;
 
		v->direction = DiagDirToDir(dir);
 
		v->tile = tile;
 
		v->owner = _current_company;
 
@@ -781,10 +739,9 @@ CommandCost CmdBuildRailVehicle(TileInde
 
		v->cargo_type = e->GetDefaultCargoType();
 
		v->cargo_cap = rvi->capacity;
 
		v->max_speed = rvi->max_speed;
 
		v->value = value.GetCost();
 
		v->last_station_visited = INVALID_STATION;
 

	
 
		v->engine_type = eid;
 
		v->engine_type = e->index;
 
		v->tcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
 

	
 
		v->reliability = e->reliability;
 
@@ -818,23 +775,14 @@ CommandCost CmdBuildRailVehicle(TileInde
 
		v->ConsistChanged(false);
 
		UpdateTrainGroupID(v);
 

	
 
		if (!HasBit(p2, 1) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
 
		if (!HasBit(data, 0) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
 
			NormalizeTrainVehInDepot(v);
 
		}
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
 
		}
 

	
 
		Company::Get(_current_company)->num_engines[eid]++;
 

	
 
		CheckConsistencyOfArticulatedVehicle(v);
 
	}
 

	
 
	return value;
 
	return CommandCost();
 
}
 

	
 

	
src/vehicle_cmd.cpp
Show inline comments
 
@@ -28,15 +28,19 @@
 
#include "depot_map.h"
 
#include "vehiclelist.h"
 
#include "engine_base.h"
 
#include "engine_func.h"
 
#include "articulated_vehicles.h"
 
#include "autoreplace_gui.h"
 
#include "company_base.h"
 

	
 
#include "table/strings.h"
 

	
 
/* Tables used in vehicle.h to find the right command for a certain vehicle type */
 
const uint32 _veh_build_proc_table[] = {
 
	CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN),
 
	CMD_BUILD_ROAD_VEH     | CMD_MSG(STR_ERROR_CAN_T_BUY_ROAD_VEHICLE),
 
	CMD_BUILD_SHIP         | CMD_MSG(STR_ERROR_CAN_T_BUY_SHIP),
 
	CMD_BUILD_AIRCRAFT     | CMD_MSG(STR_ERROR_CAN_T_BUY_AIRCRAFT),
 
	CMD_BUILD_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN),
 
	CMD_BUILD_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_ROAD_VEHICLE),
 
	CMD_BUILD_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_SHIP),
 
	CMD_BUILD_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_AIRCRAFT),
 
};
 

	
 
const uint32 _veh_sell_proc_table[] = {
 
@@ -61,6 +65,90 @@ const uint32 _send_to_depot_proc_table[]
 
	CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_MSG(STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR),
 
};
 

	
 

	
 
CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **v);
 
CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **v);
 
CommandCost CmdBuildShip       (TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **v);
 
CommandCost CmdBuildAircraft   (TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **v);
 

	
 
/**
 
 * Build a vehicle.
 
 * @param tile tile of depot where the vehicle is built
 
 * @param flags for command
 
 * @param p1 various bitstuffed data
 
 *  bits  0-15: vehicle type being built.
 
 *  bits 16-31: vehicle type specific bits passed on to the vehicle build functions.
 
 * @param p2 unused
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	/* Elementary check for valid location. */
 
	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
 

	
 
	VehicleType type;
 
	switch (GetTileType(tile)) {
 
		case MP_RAILWAY: type = VEH_TRAIN;    break;
 
		case MP_ROAD:    type = VEH_ROAD;     break;
 
		case MP_WATER:   type = VEH_SHIP;     break;
 
		case MP_STATION: type = VEH_AIRCRAFT; break;
 
		default: NOT_REACHED(); // Safe due to IsDepotTile()
 
	}
 

	
 
	/* Validate the engine type. */
 
	EngineID eid = GB(p1, 0, 16);
 
	if (!IsEngineBuildable(eid, type, _current_company)) return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type);
 

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

	
 
	/* Engines without valid cargo should not be available */
 
	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
 

	
 
	/* 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_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 

	
 
	/* 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_AUTOREPLACE || (type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type);
 
	if (unit_num == UINT16_MAX) return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
 

	
 
	Vehicle *v;
 
	switch (type) {
 
		case VEH_TRAIN:    value.AddCost(CmdBuildRailVehicle(tile, flags, e, GB(p1, 16, 16), &v)); break;
 
		case VEH_ROAD:     value.AddCost(CmdBuildRoadVehicle(tile, flags, e, GB(p1, 16, 16), &v)); break;
 
		case VEH_SHIP:     value.AddCost(CmdBuildShip       (tile, flags, e, GB(p1, 16, 16), &v)); break;
 
		case VEH_AIRCRAFT: value.AddCost(CmdBuildAircraft   (tile, flags, e, GB(p1, 16, 16), &v)); break;
 
		default: NOT_REACHED(); // Safe due to IsDepotTile()
 
	}
 

	
 
	if (value.Succeeded() && flags & DC_EXEC) {
 
		v->unitnumber = unit_num;
 
		v->value      = value.GetCost();
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
 
		InvalidateWindowClassesData(GetWindowClassForVehicleType(type), 0);
 
		SetWindowDirty(WC_COMPANY, _current_company);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the auto replace window
 
		}
 

	
 
		Company::Get(_current_company)->num_engines[eid]++;
 
	}
 

	
 
	return value;
 
}
 

	
 
/**
 
 * Start/Stop a vehicle
 
 * @param tile unused
 
@@ -467,7 +555,7 @@ CommandCost CmdCloneVehicle(TileIndex ti
 
		DoCommandFlag build_flags = flags;
 
		if ((flags & DC_EXEC) && !v->IsPrimaryVehicle()) build_flags |= DC_AUTOREPLACE;
 

	
 
		CommandCost cost = DoCommand(tile, v->engine_type, 2, build_flags, GetCmdBuildVeh(v));
 
		CommandCost cost = DoCommand(tile, v->engine_type | (1 << 16), 0, build_flags, GetCmdBuildVeh(v));
 

	
 
		if (cost.Failed()) {
 
			/* Can't build a part, then sell the stuff we already made; clear up the mess */
0 comments (0 inline, 0 general)