diff options
author | rubidium <rubidium@openttd.org> | 2010-08-17 23:15:55 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2010-08-17 23:15:55 +0000 |
commit | c14853b72e38f23d034e737450b5e894ba794e12 (patch) | |
tree | 6e6235b304e5d7cb91cf987c687e49a4af3c3435 | |
parent | bf29e5d860d2dd7c1e3d3105c4edc14a1a448238 (diff) | |
download | openttd-c14853b72e38f23d034e737450b5e894ba794e12.tar.xz |
(svn r20531) -Codechange: unify quite a bit of the vehicle building commands
-rw-r--r-- | src/aircraft_cmd.cpp | 59 | ||||
-rw-r--r-- | src/command.cpp | 10 | ||||
-rw-r--r-- | src/command_type.h | 5 | ||||
-rw-r--r-- | src/roadveh_cmd.cpp | 58 | ||||
-rw-r--r-- | src/ship_cmd.cpp | 52 | ||||
-rw-r--r-- | src/train_cmd.cpp | 102 | ||||
-rw-r--r-- | src/vehicle_cmd.cpp | 98 |
7 files changed, 154 insertions, 230 deletions
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 1c8b7e360..fe1f62113 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -215,48 +215,25 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height) /** * 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 tile, DoCommandFlag flags, uint32 p1, uin 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 tile, DoCommandFlag flags, uint32 p1, uin /* 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 tile, DoCommandFlag flags, uint32 p1, uin 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(); } diff --git a/src/command.cpp b/src/command.cpp index 31d70be88..ac4d56aed 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -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 diff --git a/src/command_type.h b/src/command_type.h index be7c14441..78f6fa8eb 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -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 diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index b9296a866..545068583 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -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 tile, DoCommandFlag flags, uint32 p1, uint 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 tile, DoCommandFlag flags, uint32 p1, uint 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 diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 5ec206648..1b0bb2421 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -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, DoCommandFlag flags, uint32 p1, uint32 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, DoCommandFlag flags, uint32 p1, uint32 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, DoCommandFlag flags, uint32 p1, uint32 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(); } /** diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 70c275925..8a83755a5 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -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; - 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(EngineID engine, TileIndex tile, DoCommandF 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(EngineID engine, TileIndex tile, DoCommandF 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(EngineID engine, TileIndex tile, DoCommandF 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(EngineID engine, TileIndex tile, DoCommandF } } - return value; + return CommandCost(); } /** Move all free vehicles in the depot to the train */ @@ -715,60 +703,30 @@ static void AddRearEngineToMultiheadedTrain(Train *v) /** * 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(TileIndex tile, DoCommandFlag flags, uint32 p1, 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(TileIndex tile, DoCommandFlag flags, uint32 p1, 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(); } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index e63609434..b08c9406d 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -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 tile, DoCommandFlag flags, uint32 p1, uint 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 */ |