mirror of https://github.com/OpenTTD/OpenTTD
(svn r20531) -Codechange: unify quite a bit of the vehicle building commands
parent
bf29e5d860
commit
c14853b72e
|
@ -215,48 +215,25 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an aircraft.
|
* Build an aircraft.
|
||||||
* @param tile tile of depot where aircraft is built
|
* @param tile tile of the depot where aircraft is built.
|
||||||
* @param flags for command
|
* @param flags type of operation.
|
||||||
* @param p1 aircraft type being built (engine)
|
* @param e the engine to build.
|
||||||
* @param p2 unused
|
* @param data unused.
|
||||||
* @param text unused
|
* @param ret[out] the vehicle that has been built.
|
||||||
* @return the cost of this operation or an error
|
* @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;
|
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 */
|
/* Prevent building aircraft types at places which can't handle them */
|
||||||
if (!CanVehicleUseStation(eid, Station::GetByTile(tile))) return CMD_ERROR;
|
if (!CanVehicleUseStation(e->index, 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 (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
Aircraft *v = new Aircraft(); // aircraft
|
Aircraft *v = new Aircraft(); // aircraft
|
||||||
Aircraft *u = new Aircraft(); // shadow
|
Aircraft *u = new Aircraft(); // shadow
|
||||||
|
*ret = v;
|
||||||
|
|
||||||
v->unitnumber = unit_num;
|
|
||||||
v->direction = DIR_SE;
|
v->direction = DIR_SE;
|
||||||
|
|
||||||
v->owner = u->owner = _current_company;
|
v->owner = u->owner = _current_company;
|
||||||
|
@ -288,12 +265,11 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||||
|
|
||||||
v->max_speed = avi->max_speed;
|
v->max_speed = avi->max_speed;
|
||||||
v->acceleration = avi->acceleration;
|
v->acceleration = avi->acceleration;
|
||||||
v->engine_type = eid;
|
v->engine_type = e->index;
|
||||||
u->engine_type = eid;
|
u->engine_type = e->index;
|
||||||
|
|
||||||
v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER);
|
v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER);
|
||||||
v->UpdateDeltaXY(INVALID_DIR);
|
v->UpdateDeltaXY(INVALID_DIR);
|
||||||
v->value = value.GetCost();
|
|
||||||
|
|
||||||
u->subtype = AIR_SHADOW;
|
u->subtype = AIR_SHADOW;
|
||||||
u->UpdateDeltaXY(INVALID_DIR);
|
u->UpdateDeltaXY(INVALID_DIR);
|
||||||
|
@ -338,7 +314,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||||
/* Aircraft with 3 vehicles (chopper)? */
|
/* Aircraft with 3 vehicles (chopper)? */
|
||||||
if (v->subtype == AIR_HELICOPTER) {
|
if (v->subtype == AIR_HELICOPTER) {
|
||||||
Aircraft *w = new Aircraft();
|
Aircraft *w = new Aircraft();
|
||||||
w->engine_type = eid;
|
w->engine_type = e->index;
|
||||||
w->direction = DIR_N;
|
w->direction = DIR_N;
|
||||||
w->owner = _current_company;
|
w->owner = _current_company;
|
||||||
w->x_pos = v->x_pos;
|
w->x_pos = v->x_pos;
|
||||||
|
@ -356,18 +332,9 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||||
u->SetNext(w);
|
u->SetNext(w);
|
||||||
VehicleMove(w, false);
|
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 CommandCost();
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,9 +77,9 @@ CommandProc CmdBuildBuoy;
|
||||||
|
|
||||||
CommandProc CmdPlantTree;
|
CommandProc CmdPlantTree;
|
||||||
|
|
||||||
CommandProc CmdBuildRailVehicle;
|
|
||||||
CommandProc CmdMoveRailVehicle;
|
CommandProc CmdMoveRailVehicle;
|
||||||
|
|
||||||
|
CommandProc CmdBuildVehicle;
|
||||||
CommandProc CmdSellRailWagon;
|
CommandProc CmdSellRailWagon;
|
||||||
|
|
||||||
CommandProc CmdSendTrainToDepot;
|
CommandProc CmdSendTrainToDepot;
|
||||||
|
@ -113,14 +113,12 @@ CommandProc CmdRenameStation;
|
||||||
CommandProc CmdRenameDepot;
|
CommandProc CmdRenameDepot;
|
||||||
|
|
||||||
CommandProc CmdSellAircraft;
|
CommandProc CmdSellAircraft;
|
||||||
CommandProc CmdBuildAircraft;
|
|
||||||
CommandProc CmdSendAircraftToHangar;
|
CommandProc CmdSendAircraftToHangar;
|
||||||
CommandProc CmdRefitAircraft;
|
CommandProc CmdRefitAircraft;
|
||||||
|
|
||||||
CommandProc CmdPlaceSign;
|
CommandProc CmdPlaceSign;
|
||||||
CommandProc CmdRenameSign;
|
CommandProc CmdRenameSign;
|
||||||
|
|
||||||
CommandProc CmdBuildRoadVeh;
|
|
||||||
CommandProc CmdSellRoadVeh;
|
CommandProc CmdSellRoadVeh;
|
||||||
CommandProc CmdSendRoadVehToDepot;
|
CommandProc CmdSendRoadVehToDepot;
|
||||||
CommandProc CmdTurnRoadVeh;
|
CommandProc CmdTurnRoadVeh;
|
||||||
|
@ -142,7 +140,6 @@ CommandProc CmdChangeSetting;
|
||||||
CommandProc CmdChangeCompanySetting;
|
CommandProc CmdChangeCompanySetting;
|
||||||
|
|
||||||
CommandProc CmdSellShip;
|
CommandProc CmdSellShip;
|
||||||
CommandProc CmdBuildShip;
|
|
||||||
CommandProc CmdSendShipToDepot;
|
CommandProc CmdSendShipToDepot;
|
||||||
CommandProc CmdRefitShip;
|
CommandProc CmdRefitShip;
|
||||||
|
|
||||||
|
@ -229,7 +226,7 @@ static const Command _command_proc_table[] = {
|
||||||
DEF_CMD(CmdBuildShipDepot, CMD_AUTO), // CMD_BUILD_SHIP_DEPOT
|
DEF_CMD(CmdBuildShipDepot, CMD_AUTO), // CMD_BUILD_SHIP_DEPOT
|
||||||
DEF_CMD(CmdBuildBuoy, CMD_AUTO), // CMD_BUILD_BUOY
|
DEF_CMD(CmdBuildBuoy, CMD_AUTO), // CMD_BUILD_BUOY
|
||||||
DEF_CMD(CmdPlantTree, CMD_AUTO), // CMD_PLANT_TREE
|
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(CmdMoveRailVehicle, 0), // CMD_MOVE_RAIL_VEHICLE
|
||||||
|
|
||||||
DEF_CMD(CmdSellRailWagon, 0), // CMD_SELL_RAIL_WAGON
|
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(CmdSellAircraft, 0), // CMD_SELL_AIRCRAFT
|
||||||
|
|
||||||
DEF_CMD(CmdBuildAircraft, 0), // CMD_BUILD_AIRCRAFT
|
|
||||||
DEF_CMD(CmdSendAircraftToHangar, 0), // CMD_SEND_AIRCRAFT_TO_HANGAR
|
DEF_CMD(CmdSendAircraftToHangar, 0), // CMD_SEND_AIRCRAFT_TO_HANGAR
|
||||||
DEF_CMD(CmdRefitAircraft, 0), // CMD_REFIT_AIRCRAFT
|
DEF_CMD(CmdRefitAircraft, 0), // CMD_REFIT_AIRCRAFT
|
||||||
|
|
||||||
DEF_CMD(CmdPlaceSign, 0), // CMD_PLACE_SIGN
|
DEF_CMD(CmdPlaceSign, 0), // CMD_PLACE_SIGN
|
||||||
DEF_CMD(CmdRenameSign, 0), // CMD_RENAME_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(CmdSellRoadVeh, 0), // CMD_SELL_ROAD_VEH
|
||||||
DEF_CMD(CmdSendRoadVehToDepot, 0), // CMD_SEND_ROADVEH_TO_DEPOT
|
DEF_CMD(CmdSendRoadVehToDepot, 0), // CMD_SEND_ROADVEH_TO_DEPOT
|
||||||
DEF_CMD(CmdTurnRoadVeh, 0), // CMD_TURN_ROADVEH
|
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(CmdDeleteTown, CMD_OFFLINE), // CMD_DELETE_TOWN
|
||||||
|
|
||||||
DEF_CMD(CmdSellShip, 0), // CMD_SELL_SHIP
|
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(CmdSendShipToDepot, 0), // CMD_SEND_SHIP_TO_DEPOT
|
||||||
DEF_CMD(CmdRefitShip, 0), // CMD_REFIT_SHIP
|
DEF_CMD(CmdRefitShip, 0), // CMD_REFIT_SHIP
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ enum Commands {
|
||||||
|
|
||||||
CMD_PLANT_TREE, ///< plant a tree
|
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_MOVE_RAIL_VEHICLE, ///< move a rail vehicle (in the depot)
|
||||||
|
|
||||||
CMD_SELL_RAIL_WAGON, ///< sell a rail wagon
|
CMD_SELL_RAIL_WAGON, ///< sell a rail wagon
|
||||||
|
@ -211,14 +211,12 @@ enum Commands {
|
||||||
CMD_RENAME_DEPOT, ///< rename a depot
|
CMD_RENAME_DEPOT, ///< rename a depot
|
||||||
|
|
||||||
CMD_SELL_AIRCRAFT, ///< sell an aircraft
|
CMD_SELL_AIRCRAFT, ///< sell an aircraft
|
||||||
CMD_BUILD_AIRCRAFT, ///< build an aircraft
|
|
||||||
CMD_SEND_AIRCRAFT_TO_HANGAR, ///< send an aircraft to a hanger
|
CMD_SEND_AIRCRAFT_TO_HANGAR, ///< send an aircraft to a hanger
|
||||||
CMD_REFIT_AIRCRAFT, ///< refit the cargo space of an aircraft
|
CMD_REFIT_AIRCRAFT, ///< refit the cargo space of an aircraft
|
||||||
|
|
||||||
CMD_PLACE_SIGN, ///< place a sign
|
CMD_PLACE_SIGN, ///< place a sign
|
||||||
CMD_RENAME_SIGN, ///< rename 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_SELL_ROAD_VEH, ///< sell a road vehicle
|
||||||
CMD_SEND_ROADVEH_TO_DEPOT, ///< send a road vehicle to the depot
|
CMD_SEND_ROADVEH_TO_DEPOT, ///< send a road vehicle to the depot
|
||||||
CMD_TURN_ROADVEH, ///< turn a road vehicle around
|
CMD_TURN_ROADVEH, ///< turn a road vehicle around
|
||||||
|
@ -237,7 +235,6 @@ enum Commands {
|
||||||
CMD_DELETE_TOWN, ///< delete a town
|
CMD_DELETE_TOWN, ///< delete a town
|
||||||
|
|
||||||
CMD_SELL_SHIP, ///< sell a ship
|
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_SEND_SHIP_TO_DEPOT, ///< send a ship to a depot
|
||||||
CMD_REFIT_SHIP, ///< refit the cargo space of a ship
|
CMD_REFIT_SHIP, ///< refit the cargo space of a ship
|
||||||
|
|
||||||
|
|
|
@ -202,50 +202,22 @@ void RoadVehUpdateCache(RoadVehicle *v)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a road vehicle.
|
* Build a road vehicle.
|
||||||
* @param tile tile of depot where road vehicle is built
|
* @param tile tile of the depot where road vehicle is built.
|
||||||
* @param flags operation to perform
|
* @param flags type of operation.
|
||||||
* @param p1 bus/truck type being built (engine)
|
* @param e the engine to build.
|
||||||
* @param p2 unused
|
* @param data unused.
|
||||||
* @param text unused
|
* @param ret[out] the vehicle that has been built.
|
||||||
* @return the cost of this operation or an error
|
* @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);
|
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) {
|
if (flags & DC_EXEC) {
|
||||||
const RoadVehicleInfo *rvi = &e->u.road;
|
const RoadVehicleInfo *rvi = &e->u.road;
|
||||||
|
|
||||||
RoadVehicle *v = new RoadVehicle();
|
RoadVehicle *v = new RoadVehicle();
|
||||||
v->unitnumber = unit_num;
|
*ret = v;
|
||||||
v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
|
v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
|
||||||
v->owner = _current_company;
|
v->owner = _current_company;
|
||||||
|
|
||||||
|
@ -262,11 +234,10 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
||||||
v->spritenum = rvi->image_index;
|
v->spritenum = rvi->image_index;
|
||||||
v->cargo_type = e->GetDefaultCargoType();
|
v->cargo_type = e->GetDefaultCargoType();
|
||||||
v->cargo_cap = rvi->capacity;
|
v->cargo_cap = rvi->capacity;
|
||||||
v->value = cost.GetCost();
|
|
||||||
|
|
||||||
v->last_station_visited = INVALID_STATION;
|
v->last_station_visited = INVALID_STATION;
|
||||||
v->max_speed = rvi->max_speed;
|
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->rcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
|
||||||
|
|
||||||
v->reliability = e->reliability;
|
v->reliability = e->reliability;
|
||||||
|
@ -304,19 +275,10 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
||||||
|
|
||||||
VehicleMove(v, false);
|
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);
|
CheckConsistencyOfArticulatedVehicle(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cost;
|
return CommandCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RoadVehicle::IsStoppedInDepot() const
|
bool RoadVehicle::IsStoppedInDepot() const
|
||||||
|
|
|
@ -604,37 +604,15 @@ bool Ship::Tick()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a ship.
|
* Build a ship.
|
||||||
* @param tile tile of depot where ship is built
|
* @param tile tile of the depot where ship is built.
|
||||||
* @param flags type of operation
|
* @param flags type of operation.
|
||||||
* @param p1 ship type being built (engine)
|
* @param e the engine to build.
|
||||||
* @param p2 unused
|
* @param data unused.
|
||||||
* @param text unused
|
* @param ret[out] the vehicle that has been built.
|
||||||
* @return the cost of this operation or an error
|
* @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) {
|
if (flags & DC_EXEC) {
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
@ -642,7 +620,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
||||||
const ShipVehicleInfo *svi = &e->u.ship;
|
const ShipVehicleInfo *svi = &e->u.ship;
|
||||||
|
|
||||||
Ship *v = new Ship();
|
Ship *v = new Ship();
|
||||||
v->unitnumber = unit_num;
|
*ret = v;
|
||||||
|
|
||||||
v->owner = _current_company;
|
v->owner = _current_company;
|
||||||
v->tile = tile;
|
v->tile = tile;
|
||||||
|
@ -658,11 +636,10 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
||||||
v->spritenum = svi->image_index;
|
v->spritenum = svi->image_index;
|
||||||
v->cargo_type = e->GetDefaultCargoType();
|
v->cargo_type = e->GetDefaultCargoType();
|
||||||
v->cargo_cap = svi->capacity;
|
v->cargo_cap = svi->capacity;
|
||||||
v->value = value.GetCost();
|
|
||||||
|
|
||||||
v->last_station_visited = INVALID_STATION;
|
v->last_station_visited = INVALID_STATION;
|
||||||
v->max_speed = svi->max_speed;
|
v->max_speed = svi->max_speed;
|
||||||
v->engine_type = eid;
|
v->engine_type = e->index;
|
||||||
|
|
||||||
v->reliability = e->reliability;
|
v->reliability = e->reliability;
|
||||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||||
|
@ -686,18 +663,9 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
||||||
v->InvalidateNewGRFCacheOfChain();
|
v->InvalidateNewGRFCacheOfChain();
|
||||||
|
|
||||||
VehicleMove(v, false);
|
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 CommandCost();
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -574,32 +574,27 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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 */
|
/* Check that the wagon can drive on the track in question */
|
||||||
if (!IsCompatibleRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
|
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) {
|
if (flags & DC_EXEC) {
|
||||||
Train *v = new Train();
|
Train *v = new Train();
|
||||||
|
*ret = v;
|
||||||
v->spritenum = rvi->image_index;
|
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
|
v->tcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
|
||||||
|
|
||||||
DiagDirection dir = GetRailDepotDirection(tile);
|
DiagDirection dir = GetRailDepotDirection(tile);
|
||||||
|
@ -624,7 +619,6 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF
|
||||||
|
|
||||||
v->cargo_type = e->GetDefaultCargoType();
|
v->cargo_type = e->GetDefaultCargoType();
|
||||||
v->cargo_cap = rvi->capacity;
|
v->cargo_cap = rvi->capacity;
|
||||||
v->value = value.GetCost();
|
|
||||||
|
|
||||||
v->railtype = rvi->railtype;
|
v->railtype = rvi->railtype;
|
||||||
|
|
||||||
|
@ -642,12 +636,6 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF
|
||||||
v->First()->ConsistChanged(false);
|
v->First()->ConsistChanged(false);
|
||||||
UpdateTrainGroupID(v->First());
|
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);
|
CheckConsistencyOfArticulatedVehicle(v);
|
||||||
|
|
||||||
/* Try to connect the vehicle to one of free chains of wagons. */
|
/* Try to connect the vehicle to one of free chains of wagons. */
|
||||||
|
@ -655,7 +643,7 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF
|
||||||
FOR_ALL_TRAINS(w) {
|
FOR_ALL_TRAINS(w) {
|
||||||
if (w->tile == tile && ///< Same depot
|
if (w->tile == tile && ///< Same depot
|
||||||
w->IsFreeWagon() && ///< A free wagon chain
|
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->First() != v && ///< Don't connect to ourself
|
||||||
!(w->vehstatus & VS_CRASHED)) { ///< Not crashed/flooded
|
!(w->vehstatus & VS_CRASHED)) { ///< Not crashed/flooded
|
||||||
DoCommand(0, v->index | (w->Last()->index << 16), 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
DoCommand(0, v->index | (w->Last()->index << 16), 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
||||||
|
@ -664,7 +652,7 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return CommandCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move all free vehicles in the depot to the train */
|
/** Move all free vehicles in the depot to the train */
|
||||||
|
@ -715,60 +703,30 @@ static void AddRearEngineToMultiheadedTrain(Train *v)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a railroad vehicle.
|
* Build a railroad vehicle.
|
||||||
* @param tile tile of the depot where rail-vehicle is built
|
* @param tile tile of the depot where rail-vehicle is built.
|
||||||
* @param flags type of operation
|
* @param flags type of operation.
|
||||||
* @param p1 engine type id
|
* @param e the engine to build.
|
||||||
* @param p2 bit 1 prevents any free cars from being added to the train
|
* @param data bit 0 prevents any free cars from being added to the train.
|
||||||
* @param text unused
|
* @param ret[out] the vehicle that has been built.
|
||||||
* @return the cost of this operation or an error
|
* @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;
|
const RailVehicleInfo *rvi = &e->u.rail;
|
||||||
CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
|
|
||||||
|
|
||||||
/* Engines with CT_INVALID should not be available */
|
if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(tile, flags, e, ret);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Check if depot and new engine uses the same kind of tracks *
|
/* 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 */
|
* 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;
|
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) {
|
if (flags & DC_EXEC) {
|
||||||
DiagDirection dir = GetRailDepotDirection(tile);
|
DiagDirection dir = GetRailDepotDirection(tile);
|
||||||
int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
|
int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
|
||||||
int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
|
int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
|
||||||
|
|
||||||
Train *v = new Train();
|
Train *v = new Train();
|
||||||
v->unitnumber = unit_num;
|
*ret = v;
|
||||||
v->direction = DiagDirToDir(dir);
|
v->direction = DiagDirToDir(dir);
|
||||||
v->tile = tile;
|
v->tile = tile;
|
||||||
v->owner = _current_company;
|
v->owner = _current_company;
|
||||||
|
@ -781,10 +739,9 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||||
v->cargo_type = e->GetDefaultCargoType();
|
v->cargo_type = e->GetDefaultCargoType();
|
||||||
v->cargo_cap = rvi->capacity;
|
v->cargo_cap = rvi->capacity;
|
||||||
v->max_speed = rvi->max_speed;
|
v->max_speed = rvi->max_speed;
|
||||||
v->value = value.GetCost();
|
|
||||||
v->last_station_visited = INVALID_STATION;
|
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->tcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
|
||||||
|
|
||||||
v->reliability = e->reliability;
|
v->reliability = e->reliability;
|
||||||
|
@ -818,23 +775,14 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||||
v->ConsistChanged(false);
|
v->ConsistChanged(false);
|
||||||
UpdateTrainGroupID(v);
|
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);
|
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);
|
CheckConsistencyOfArticulatedVehicle(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return CommandCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,15 +28,19 @@
|
||||||
#include "depot_map.h"
|
#include "depot_map.h"
|
||||||
#include "vehiclelist.h"
|
#include "vehiclelist.h"
|
||||||
#include "engine_base.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"
|
#include "table/strings.h"
|
||||||
|
|
||||||
/* Tables used in vehicle.h to find the right command for a certain vehicle type */
|
/* Tables used in vehicle.h to find the right command for a certain vehicle type */
|
||||||
const uint32 _veh_build_proc_table[] = {
|
const uint32 _veh_build_proc_table[] = {
|
||||||
CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN),
|
CMD_BUILD_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN),
|
||||||
CMD_BUILD_ROAD_VEH | CMD_MSG(STR_ERROR_CAN_T_BUY_ROAD_VEHICLE),
|
CMD_BUILD_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_ROAD_VEHICLE),
|
||||||
CMD_BUILD_SHIP | CMD_MSG(STR_ERROR_CAN_T_BUY_SHIP),
|
CMD_BUILD_VEHICLE | 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_AIRCRAFT),
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 _veh_sell_proc_table[] = {
|
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),
|
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
|
* Start/Stop a vehicle
|
||||||
* @param tile unused
|
* @param tile unused
|
||||||
|
@ -467,7 +555,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
||||||
DoCommandFlag build_flags = flags;
|
DoCommandFlag build_flags = flags;
|
||||||
if ((flags & DC_EXEC) && !v->IsPrimaryVehicle()) build_flags |= DC_AUTOREPLACE;
|
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()) {
|
if (cost.Failed()) {
|
||||||
/* Can't build a part, then sell the stuff we already made; clear up the mess */
|
/* Can't build a part, then sell the stuff we already made; clear up the mess */
|
||||||
|
|
Loading…
Reference in New Issue