diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index f0a50b012f..d67969c006 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -328,8 +328,6 @@ CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine * v->reliability_spd_dec = e->reliability_spd_dec; v->max_age = e->GetLifeLengthInDays(); - _new_vehicle_id = v->index; - v->pos = GetVehiclePosOnBuild(tile); v->state = HANGAR; diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 9fef038393..5bdf8d0e59 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -345,17 +345,18 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic } /* Build the new vehicle */ - cost = Command::Do(DC_EXEC | DC_AUTOREPLACE, old_veh->tile, e, true, CT_INVALID, INVALID_CLIENT_ID); + VehicleID new_veh_id; + std::tie(cost, new_veh_id, std::ignore, std::ignore) = Command::Do(DC_EXEC | DC_AUTOREPLACE, old_veh->tile, e, true, CT_INVALID, INVALID_CLIENT_ID); if (cost.Failed()) return cost; - Vehicle *new_veh = Vehicle::Get(_new_vehicle_id); + Vehicle *new_veh = Vehicle::Get(new_veh_id); *new_vehicle = new_veh; /* Refit the vehicle if needed */ if (refit_cargo != CT_NO_REFIT) { byte subtype = GetBestFittingSubType(old_veh, new_veh, refit_cargo); - cost.AddCost(Command::Do(DC_EXEC, new_veh->index, refit_cargo, subtype, false, false, 0)); + cost.AddCost(std::get<0>(Command::Do(DC_EXEC, new_veh->index, refit_cargo, subtype, false, false, 0))); assert(cost.Succeeded()); // This should be ensured by GetNewCargoTypeForReplace() } diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 39f840f73b..04392c9b03 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1229,11 +1229,11 @@ struct BuildVehicleWindow : Window { if (!this->listview_mode) { /* Query for cost and refitted capacity */ - CommandCost ret = Command::Do(DC_QUERY_COST, this->window_number, this->sel_engine, true, cargo, INVALID_CLIENT_ID); + auto [ret, veh_id, refit_capacity, refit_mail] = Command::Do(DC_QUERY_COST, this->window_number, this->sel_engine, true, cargo, INVALID_CLIENT_ID); if (ret.Succeeded()) { this->te.cost = ret.GetCost() - e->GetCost(); - this->te.capacity = _returned_refit_capacity; - this->te.mail_capacity = _returned_mail_refit_capacity; + this->te.capacity = refit_capacity; + this->te.mail_capacity = refit_mail; this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo; return; } @@ -1469,10 +1469,13 @@ struct BuildVehicleWindow : Window { case WID_BV_BUILD: { EngineID sel_eng = this->sel_engine; if (sel_eng != INVALID_ENGINE) { - CommandCallback *callback = (this->vehicle_type == VEH_TRAIN && RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildPrimaryVehicle; CargoID cargo = this->cargo_filter[this->cargo_filter_criteria]; if (cargo == CF_ANY || cargo == CF_ENGINES) cargo = CF_NONE; - Command::Post(GetCmdBuildVehMsg(this->vehicle_type), callback, this->window_number, sel_eng, true, cargo, INVALID_CLIENT_ID); + if (this->vehicle_type == VEH_TRAIN && RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) { + Command::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildWagon, this->window_number, sel_eng, true, cargo, INVALID_CLIENT_ID); + } else { + Command::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildPrimaryVehicle, this->window_number, sel_eng, true, cargo, INVALID_CLIENT_ID); + } } break; } diff --git a/src/depot_cmd.h b/src/depot_cmd.h index d476aecaf9..c8583c4405 100644 --- a/src/depot_cmd.h +++ b/src/depot_cmd.h @@ -17,6 +17,6 @@ CommandCost CmdRenameDepot(DoCommandFlag flags, DepotID depot_id, const std::str DEF_CMD_TRAIT(CMD_RENAME_DEPOT, CmdRenameDepot, 0, CMDT_OTHER_MANAGEMENT) -CommandCallback CcCloneVehicle; +void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id); #endif /* DEPOT_CMD_H */ diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index c636065824..f95f9ade60 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -116,13 +116,13 @@ extern void DepotSortList(VehicleList *list); * This is the Callback method after the cloning attempt of a vehicle * @param cmd unused * @param result the result of the cloning command - * @param tile unused + * @param veh_id cloned vehicle ID */ -void CcCloneVehicle(Commands cmd, const CommandCost &result, TileIndex tile) +void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id) { if (result.Failed()) return; - const Vehicle *v = Vehicle::Get(_new_vehicle_id); + const Vehicle *v = Vehicle::Get(veh_id); ShowVehicleViewWindow(v); } diff --git a/src/economy.cpp b/src/economy.cpp index 6fb3d2795d..7080aad8e5 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1488,14 +1488,14 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station if (st->goods[cid].cargo.HasCargoFor(next_station)) { /* Try to find out if auto-refitting would succeed. In case the refit is allowed, * the returned refit capacity will be greater than zero. */ - Command::Do(DC_QUERY_COST, v_start->index, cid, 0xFF, true, false, 1); // Auto-refit and only this vehicle including artic parts. + auto [cc, refit_capacity, mail_capacity] = Command::Do(DC_QUERY_COST, v_start->index, cid, 0xFF, true, false, 1); // Auto-refit and only this vehicle including artic parts. /* Try to balance different loadable cargoes between parts of the consist, so that * all of them can be loaded. Avoid a situation where all vehicles suddenly switch * to the first loadable cargo for which there is only one packet. If the capacities * are equal refit to the cargo of which most is available. This is important for * consists of only a single vehicle as those will generally have a consist_capleft * of 0 for all cargoes. */ - if (_returned_refit_capacity > 0 && (consist_capleft[cid] < consist_capleft[new_cid] || + if (refit_capacity > 0 && (consist_capleft[cid] < consist_capleft[new_cid] || (consist_capleft[cid] == consist_capleft[new_cid] && st->goods[cid].cargo.AvailableCount() > st->goods[new_cid].cargo.AvailableCount()))) { new_cid = cid; @@ -1511,7 +1511,7 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station * "via any station" before reserving. We rather produce some more "any station" cargo than * misrouting it. */ IterateVehicleParts(v_start, ReturnCargoAction(st, INVALID_STATION)); - CommandCost cost = Command::Do(DC_EXEC, v_start->index, new_cid, 0xFF, true, false, 1); // Auto-refit and only this vehicle including artic parts. + CommandCost cost = std::get<0>(Command::Do(DC_EXEC, v_start->index, new_cid, 0xFF, true, false, 1)); // Auto-refit and only this vehicle including artic parts. if (cost.Succeeded()) v->First()->profit_this_year -= cost.GetCost() << 8; } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index c1e510273a..27900a2c8e 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -295,7 +295,6 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; v->max_age = e->GetLifeLengthInDays(); - _new_vehicle_id = v->index; v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh); diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index f95433bd9e..3cddb12f83 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -159,8 +159,6 @@ ScriptObject::ActiveInstance::~ActiveInstance() /* static */ void ScriptObject::SetLastCommandRes(bool res) { GetStorage()->last_command_res = res; - /* Also store the results of various global variables */ - SetNewVehicleID(_new_vehicle_id); } /* static */ bool ScriptObject::GetLastCommandRes() @@ -178,16 +176,6 @@ ScriptObject::ActiveInstance::~ActiveInstance() return GetStorage()->last_cmd_ret; } -/* static */ void ScriptObject::SetNewVehicleID(VehicleID vehicle_id) -{ - GetStorage()->new_vehicle_id = vehicle_id; -} - -/* static */ VehicleID ScriptObject::GetNewVehicleID() -{ - return GetStorage()->new_vehicle_id; -} - /* static */ void ScriptObject::SetAllowDoCommand(bool allow) { GetStorage()->allow_do_command = allow; diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index d90fec351a..5fffe783b2 100644 --- a/src/script/api/script_object.hpp +++ b/src/script/api/script_object.hpp @@ -192,11 +192,6 @@ protected: */ static const CommandDataBuffer &GetLastCommandResData(); - /** - * Get the latest stored new_vehicle_id. - */ - static VehicleID GetNewVehicleID(); - /** * Store a allow_do_command per company. * @param allow The new allow. @@ -274,12 +269,6 @@ protected: static char *GetString(StringID string); private: - /** - * Store a new_vehicle_id per company. - * @param vehicle_id The new VehicleID. - */ - static void SetNewVehicleID(VehicleID vehicle_id); - /* Helper functions for DoCommand. */ static std::tuple DoCommandPrep(); static bool DoCommandProcessResult(const CommandCost &res, Script_SuspendCallbackProc *callback, bool estimate_only); diff --git a/src/script/api/script_vehicle.cpp b/src/script/api/script_vehicle.cpp index c925026616..b7b5fd9503 100644 --- a/src/script/api/script_vehicle.cpp +++ b/src/script/api/script_vehicle.cpp @@ -94,8 +94,8 @@ if (!ScriptEngine::IsBuildable(engine_id)) return -1; if (!ScriptCargo::IsValidCargo(cargo)) return -1; - CommandCost res = ::Command::Do(DC_QUERY_COST, depot, engine_id, true, cargo, INVALID_CLIENT_ID); - return res.Succeeded() ? _returned_refit_capacity : -1; + auto [res, veh_id, refit_capacity, refit_mail] = ::Command::Do(DC_QUERY_COST, depot, engine_id, true, cargo, INVALID_CLIENT_ID); + return res.Succeeded() ? refit_capacity : -1; } /* static */ VehicleID ScriptVehicle::CloneVehicle(TileIndex depot, VehicleID vehicle_id, bool share_orders) @@ -143,8 +143,8 @@ if (!IsValidVehicle(vehicle_id)) return -1; if (!ScriptCargo::IsValidCargo(cargo)) return -1; - CommandCost res = ::Command::Do(DC_QUERY_COST, vehicle_id, cargo, 0, false, false, 0); - return res.Succeeded() ? _returned_refit_capacity : -1; + auto [res, refit_capacity, refit_mail] = ::Command::Do(DC_QUERY_COST, vehicle_id, cargo, 0, false, false, 0); + return res.Succeeded() ? refit_capacity : -1; } /* static */ bool ScriptVehicle::RefitVehicle(VehicleID vehicle_id, CargoID cargo) diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index 9d978f8339..bcd8b2d4bd 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -270,7 +270,7 @@ void ScriptInstance::CollectGarbage() /* static */ void ScriptInstance::DoCommandReturnVehicleID(ScriptInstance *instance) { - instance->engine->InsertResult(ScriptObject::GetNewVehicleID()); + instance->engine->InsertResult(EndianBufferReader::ToValue(ScriptObject::GetLastCommandResData())); } /* static */ void ScriptInstance::DoCommandReturnSignID(ScriptInstance *instance) diff --git a/src/script/script_storage.hpp b/src/script/script_storage.hpp index f95eb7e710..2afb03827d 100644 --- a/src/script/script_storage.hpp +++ b/src/script/script_storage.hpp @@ -49,8 +49,6 @@ private: Commands last_cmd; ///< The last cmd passed to a command. CommandDataBuffer last_cmd_ret; ///< The extra data returned by the last command. - VehicleID new_vehicle_id; ///< The ID of the new Vehicle. - std::vector callback_value; ///< The values which need to survive a callback. RoadType road_type; ///< The current roadtype we build. @@ -73,7 +71,6 @@ public: last_command_res (true), last_tile (INVALID_TILE), last_cmd (CMD_END), - new_vehicle_id (0), /* calback_value (can't be set) */ road_type (INVALID_ROADTYPE), rail_type (INVALID_RAILTYPE), diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 2729030d31..b423fe4a61 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -879,7 +879,6 @@ CommandCost CmdBuildShip(DoCommandFlag flags, TileIndex tile, const Engine *e, V v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; v->max_age = e->GetLifeLengthInDays(); - _new_vehicle_id = v->index; v->state = TRACK_BIT_DEPOT; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 6bb8d0986a..2fd081898e 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -641,8 +641,6 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const AddArticulatedParts(v); - _new_vehicle_id = v->index; - v->UpdatePosition(); v->First()->ConsistChanged(CCF_ARRANGE); UpdateTrainGroupID(v->First()); @@ -762,7 +760,6 @@ CommandCost CmdBuildRailVehicle(DoCommandFlag flags, TileIndex tile, const Engin v->max_age = e->GetLifeLengthInDays(); v->railtype = rvi->railtype; - _new_vehicle_id = v->index; v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains); v->date_of_last_service = _date; diff --git a/src/train_cmd.h b/src/train_cmd.h index 5d75171607..97bd43a74b 100644 --- a/src/train_cmd.h +++ b/src/train_cmd.h @@ -25,6 +25,6 @@ DEF_CMD_TRAIT(CMD_MOVE_RAIL_VEHICLE, CmdMoveRailVehicle, 0, CMDT_VEH DEF_CMD_TRAIT(CMD_FORCE_TRAIN_PROCEED, CmdForceTrainProceed, 0, CMDT_VEHICLE_MANAGEMENT) DEF_CMD_TRAIT(CMD_REVERSE_TRAIN_DIRECTION, CmdReverseTrainDirection, 0, CMDT_VEHICLE_MANAGEMENT) -CommandCallback CcBuildWagon; +void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16, TileIndex tile, EngineID, bool, CargoID, ClientID); #endif /* TRAIN_CMD_H */ diff --git a/src/train_gui.cpp b/src/train_gui.cpp index d6c7320e65..f65b359dfa 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -24,9 +24,10 @@ * Callback for building wagons. * @param cmd Unused. * @param result The result of the command. + * @param new_veh_id ID of the ne vehicle. * @param tile The tile the command was executed on. */ -void CcBuildWagon(Commands cmd, const CommandCost &result, TileIndex tile) +void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16, TileIndex tile, EngineID, bool, CargoID, ClientID) { if (result.Failed()) return; @@ -43,7 +44,7 @@ void CcBuildWagon(Commands cmd, const CommandCost &result, TileIndex tile) if (found != nullptr) { found = found->Last(); /* put the new wagon at the end of the loco. */ - Command::Post( _new_vehicle_id, found->index, false); + Command::Post(new_veh_id, found->index, false); InvalidateWindowClassesData(WC_TRAINS_LIST, 0); } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 3bbca46f0e..11b4095943 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -85,10 +85,6 @@ static const int GEN_HASHY_INC = 1 << GEN_HASHX_BITS; static const uint GEN_HASHX_MASK = (1 << GEN_HASHX_BITS) - 1; static const uint GEN_HASHY_MASK = ((1 << GEN_HASHY_BITS) - 1) << GEN_HASHX_BITS; -VehicleID _new_vehicle_id; -uint _returned_refit_capacity; ///< Stores the capacity after a refit operation. -uint16 _returned_mail_refit_capacity; ///< Stores the mail capacity after a refit operation (Aircraft only). - /** The pool with all our precious vehicles. */ VehiclePool _vehicle_pool("Vehicle"); @@ -1565,7 +1561,7 @@ void VehicleEnterDepot(Vehicle *v) if (v->current_order.IsRefit()) { Backup cur_company(_current_company, v->owner, FILE_LINE); - CommandCost cost = Command::Do(DC_EXEC, v->index, v->current_order.GetRefitCargo(), 0xFF, false, false, 0); + CommandCost cost = std::get<0>(Command::Do(DC_EXEC, v->index, v->current_order.GetRefitCargo(), 0xFF, false, false, 0)); cur_company.Restore(); if (cost.Failed()) { diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 2f6a01cab7..438f733678 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -83,27 +83,27 @@ const StringID _send_to_depot_msg_table[] = { * @param use_free_vehicles use free vehicles when building the vehicle. * @param cargo refit cargo type. * @param client_id User - * @return the cost of this operation or an error + * @return the cost of this operation + the new vehicle ID + the refitted capacity + the refitted mail capacity (aircraft) or an error */ -CommandCost CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id) +std::tuple CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id) { /* Elementary check for valid location. */ - if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; + if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0 }; VehicleType type = GetDepotVehicleType(tile); /* Validate the engine type. */ - if (!IsEngineBuildable(eid, type, _current_company)) return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type); + if (!IsEngineBuildable(eid, type, _current_company)) return { CommandCost(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type), INVALID_VEHICLE, 0, 0 }; /* Validate the cargo type. */ - if (cargo >= NUM_CARGO && cargo != CT_INVALID) return CMD_ERROR; + if (cargo >= NUM_CARGO && cargo != CT_INVALID) return { CMD_ERROR, INVALID_VEHICLE, 0, 0 }; const Engine *e = Engine::Get(eid); CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); /* Engines without valid cargo should not be available */ CargoID default_cargo = e->GetDefaultCargoType(); - if (default_cargo == CT_INVALID) return CMD_ERROR; + if (default_cargo == CT_INVALID) return { CMD_ERROR, INVALID_VEHICLE, 0, 0 }; bool refitting = cargo != CT_INVALID && cargo != default_cargo; @@ -116,13 +116,13 @@ CommandCost CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, b 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); + if (!Vehicle::CanAllocateItem(num_vehicles)) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE, 0, 0 }; /* Check whether we can allocate a unit number. Autoreplace does not allocate * an unit number as it will (always) reuse the one of the replaced vehicle * and (train) wagons don't have an unit number in any scenario. */ UnitID unit_num = (flags & DC_QUERY_COST || flags & DC_AUTOREPLACE || (type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type); - if (unit_num == UINT16_MAX) return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME); + if (unit_num == UINT16_MAX) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE, 0, 0 }; /* If we are refitting we need to temporarily purchase the vehicle to be able to * test it. */ @@ -143,18 +143,24 @@ CommandCost CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, b default: NOT_REACHED(); // Safe due to IsDepotTile() } + VehicleID veh_id = INVALID_VEHICLE; + uint refitted_capacity = 0; + uint16 refitted_mail_capacity = 0; if (value.Succeeded()) { if (subflags & DC_EXEC) { v->unitnumber = unit_num; v->value = value.GetCost(); + veh_id = v->index; } if (refitting) { /* Refit only one vehicle. If we purchased an engine, it may have gained free wagons. */ - value.AddCost(CmdRefitVehicle(flags, v->index, cargo, 0, false, false, 1)); + CommandCost cc; + std::tie(cc, refitted_capacity, refitted_mail_capacity) = CmdRefitVehicle(flags, v->index, cargo, 0, false, false, 1); + value.AddCost(cc); } else { /* Fill in non-refitted capacities */ - _returned_refit_capacity = e->GetDisplayDefaultCapacity(&_returned_mail_refit_capacity); + refitted_capacity = e->GetDisplayDefaultCapacity(&refitted_mail_capacity); } if (flags & DC_EXEC) { @@ -186,7 +192,7 @@ CommandCost CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, b /* Only restore if we actually did some refitting */ if (flags != subflags) RestoreRandomSeeds(saved_seeds); - return value; + return { value, veh_id, refitted_capacity, refitted_mail_capacity }; } /** @@ -333,9 +339,9 @@ struct RefitResult { * @param new_subtype Cargo subtype to refit to. 0xFF means to try keeping the same subtype according to GetBestFittingSubType(). * @param flags Command flags * @param auto_refit Refitting is done as automatic refitting outside a depot. - * @return Refit cost. + * @return Refit cost + refittet capacity + mail capacity (aircraft). */ -static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, CargoID new_cid, byte new_subtype, DoCommandFlag flags, bool auto_refit) +static std::tuple RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, CargoID new_cid, byte new_subtype, DoCommandFlag flags, bool auto_refit) { CommandCost cost(v->GetExpenseType(false)); uint total_capacity = 0; @@ -441,9 +447,7 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, } refit_result.clear(); - _returned_refit_capacity = total_capacity; - _returned_mail_refit_capacity = total_mail_capacity; - return cost; + return { cost, total_capacity, total_mail_capacity }; } /** @@ -458,42 +462,42 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, * Only used if "refit only this vehicle" is false. * @return the cost of this operation or an error */ -CommandCost CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_cid, byte new_subtype, bool auto_refit, bool only_this, uint8 num_vehicles) +std::tuple CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_cid, byte new_subtype, bool auto_refit, bool only_this, uint8 num_vehicles) { Vehicle *v = Vehicle::GetIfValid(veh_id); - if (v == nullptr) return CMD_ERROR; + if (v == nullptr) return { CMD_ERROR, 0, 0 }; /* Don't allow disasters and sparks and such to be refitted. * We cannot check for IsPrimaryVehicle as autoreplace also refits in free wagon chains. */ - if (!IsCompanyBuildableVehicleType(v->type)) return CMD_ERROR; + if (!IsCompanyBuildableVehicleType(v->type)) return { CMD_ERROR, 0, 0 }; Vehicle *front = v->First(); CommandCost ret = CheckOwnership(front->owner); - if (ret.Failed()) return ret; + if (ret.Failed()) return { ret, 0, 0 }; bool free_wagon = v->type == VEH_TRAIN && Train::From(front)->IsFreeWagon(); // used by autoreplace/renew /* Don't allow shadows and such to be refitted. */ - if (v != front && (v->type == VEH_SHIP || v->type == VEH_AIRCRAFT)) return CMD_ERROR; + if (v != front && (v->type == VEH_SHIP || v->type == VEH_AIRCRAFT)) return { CMD_ERROR, 0, 0 }; /* Allow auto-refitting only during loading and normal refitting only in a depot. */ if ((flags & DC_QUERY_COST) == 0 && // used by the refit GUI, including the order refit GUI. !free_wagon && // used by autoreplace/renew (!auto_refit || !front->current_order.IsType(OT_LOADING)) && // refit inside stations !front->IsStoppedInDepot()) { // refit inside depots - return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type); + return { CommandCost(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type), 0, 0}; } - if (front->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED); + if (front->vehstatus & VS_CRASHED) return { CommandCost(STR_ERROR_VEHICLE_IS_DESTROYED), 0, 0}; /* Check cargo */ - if (new_cid >= NUM_CARGO) return CMD_ERROR; + if (new_cid >= NUM_CARGO) return { CMD_ERROR, 0, 0 }; /* For ships and aircraft there is always only one. */ only_this |= front->type == VEH_SHIP || front->type == VEH_AIRCRAFT; - CommandCost cost = RefitVehicle(v, only_this, num_vehicles, new_cid, new_subtype, flags, auto_refit); + auto [cost, refit_capacity, mail_capacity] = RefitVehicle(v, only_this, num_vehicles, new_cid, new_subtype, flags, auto_refit); if (flags & DC_EXEC) { /* Update the cached variables */ @@ -530,7 +534,7 @@ CommandCost CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_c v->InvalidateNewGRFCacheOfChain(); } - return cost; + return { cost, refit_capacity, mail_capacity }; } /** @@ -790,14 +794,14 @@ static void CloneVehicleName(const Vehicle *src, Vehicle *dst) * @param tile tile of the depot where the cloned vehicle is build * @param veh_id the original vehicle's index * @param share_orders shared orders, else copied orders - * @return the cost of this operation or an error + * @return the cost of this operation + the new vehicle ID or an error */ -CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_id, bool share_orders) +std::tuple CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_id, bool share_orders) { CommandCost total_cost(EXPENSES_NEW_VEHICLES); Vehicle *v = Vehicle::GetIfValid(veh_id); - if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; + if (v == nullptr || !v->IsPrimaryVehicle()) return { CMD_ERROR, INVALID_VEHICLE }; Vehicle *v_front = v; Vehicle *w = nullptr; Vehicle *w_front = nullptr; @@ -812,9 +816,9 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i */ CommandCost ret = CheckOwnership(v->owner); - if (ret.Failed()) return ret; + if (ret.Failed()) return { ret, INVALID_VEHICLE }; - if (v->type == VEH_TRAIN && (!v->IsFrontEngine() || Train::From(v)->crash_anim_pos >= 4400)) return CMD_ERROR; + if (v->type == VEH_TRAIN && (!v->IsFrontEngine() || Train::From(v)->crash_anim_pos >= 4400)) return { CMD_ERROR, INVALID_VEHICLE }; /* check that we can allocate enough vehicles */ if (!(flags & DC_EXEC)) { @@ -824,12 +828,13 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i } while ((v = v->Next()) != nullptr); if (!Vehicle::CanAllocateItem(veh_counter)) { - return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME); + return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE }; } } v = v_front; + VehicleID new_veh_id = INVALID_VEHICLE; do { if (v->type == VEH_TRAIN && Train::From(v)->IsRearDualheaded()) { /* we build the rear ends of multiheaded trains with the front ones */ @@ -845,18 +850,19 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i DoCommandFlag build_flags = flags; if ((flags & DC_EXEC) && !v->IsPrimaryVehicle()) build_flags |= DC_AUTOREPLACE; - CommandCost cost = Command::Do(build_flags, tile, v->engine_type, false, CT_INVALID, INVALID_CLIENT_ID); + CommandCost cost; + std::tie(cost, new_veh_id, std::ignore, std::ignore) = Command::Do(build_flags, tile, v->engine_type, false, CT_INVALID, INVALID_CLIENT_ID); if (cost.Failed()) { /* Can't build a part, then sell the stuff we already made; clear up the mess */ if (w_front != nullptr) Command::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID); - return cost; + return { cost, INVALID_VEHICLE }; } total_cost.AddCost(cost); if (flags & DC_EXEC) { - w = Vehicle::Get(_new_vehicle_id); + w = Vehicle::Get(new_veh_id); if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) { SetBit(Train::From(w)->flags, VRF_REVERSE_DIRECTION); @@ -871,7 +877,7 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i * Sell what we already made (clean up) and return an error. */ Command::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID); Command::Do(flags, w->index, true, false, INVALID_CLIENT_ID); - return result; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE + return { result, INVALID_VEHICLE }; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE } } else { /* this is a front engine or not a train. */ @@ -886,7 +892,7 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i if ((flags & DC_EXEC) && v_front->type == VEH_TRAIN) { /* for trains this needs to be the front engine due to the callback function */ - _new_vehicle_id = w_front->index; + new_veh_id = w_front->index; } if (flags & DC_EXEC) { @@ -913,7 +919,7 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i /* Find out what's the best sub type */ byte subtype = GetBestFittingSubType(v, w, v->cargo_type); if (w->cargo_type != v->cargo_type || w->cargo_subtype != subtype) { - CommandCost cost = Command::Do(flags, w->index, v->cargo_type, subtype, false, true, 0); + CommandCost cost = std::get<0>(Command::Do(flags, w->index, v->cargo_type, subtype, false, true, 0)); if (cost.Succeeded()) total_cost.AddCost(cost); } @@ -952,7 +958,7 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i if (result.Failed()) { /* The vehicle has already been bought, so now it must be sold again. */ Command::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID); - return result; + return { total_cost, INVALID_VEHICLE }; } /* Now clone the vehicle's name, if it has one. */ @@ -963,11 +969,11 @@ CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_i if (!CheckCompanyHasMoney(total_cost)) { /* The vehicle has already been bought, so now it must be sold again. */ Command::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID); - return total_cost; + return { total_cost, INVALID_VEHICLE }; } } - return total_cost; + return { total_cost, new_veh_id }; } /** diff --git a/src/vehicle_cmd.h b/src/vehicle_cmd.h index 38852347c8..2f203b8652 100644 --- a/src/vehicle_cmd.h +++ b/src/vehicle_cmd.h @@ -15,13 +15,13 @@ #include "vehicle_type.h" #include "vehiclelist.h" -CommandCost CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id); +std::tuple CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id); CommandCost CmdSellVehicle(DoCommandFlag flags, VehicleID v_id, bool sell_chain, bool backup_order, ClientID client_id); -CommandCost CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_cid, byte new_subtype, bool auto_refit, bool only_this, uint8 num_vehicles); +std::tuple CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_cid, byte new_subtype, bool auto_refit, bool only_this, uint8 num_vehicles); CommandCost CmdSendVehicleToDepot(DoCommandFlag flags, VehicleID veh_id, DepotCommand depot_cmd, const VehicleListIdentifier &vli); CommandCost CmdChangeServiceInt(DoCommandFlag flags, VehicleID veh_id, uint16 serv_int, bool is_custom, bool is_percent); CommandCost CmdRenameVehicle(DoCommandFlag flags, VehicleID veh_id, const std::string &text); -CommandCost CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_id, bool share_orders); +std::tuple CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_id, bool share_orders); CommandCost CmdStartStopVehicle(DoCommandFlag flags, VehicleID veh_id, bool evaluate_startstop_cb); CommandCost CmdMassStartStopVehicle(DoCommandFlag flags, TileIndex tile, bool do_start, bool vehicle_list_window, const VehicleListIdentifier &vli); CommandCost CmdDepotSellAllVehicles(DoCommandFlag flags, TileIndex tile, VehicleType vehicle_type); @@ -39,7 +39,7 @@ DEF_CMD_TRAIT(CMD_MASS_START_STOP, CmdMassStartStopVehicle, 0, DEF_CMD_TRAIT(CMD_DEPOT_SELL_ALL_VEHICLES, CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_DEPOT_MASS_AUTOREPLACE, CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION) -CommandCallback CcBuildPrimaryVehicle; +void CcBuildPrimaryVehicle(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16); void CcStartStopVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id, bool); template diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 5784de1081..aa3a027dfb 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -164,10 +164,6 @@ static inline StringID GetCmdSendToDepotMsg(const BaseVehicle *v) CommandCost EnsureNoVehicleOnGround(TileIndex tile); CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits); -extern VehicleID _new_vehicle_id; -extern uint _returned_refit_capacity; -extern uint16 _returned_mail_refit_capacity; - bool CanVehicleUseStation(EngineID engine_type, const struct Station *st); bool CanVehicleUseStation(const Vehicle *v, const struct Station *st); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 4965cac0a9..5ca65ea641 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -776,17 +776,17 @@ struct RefitWindow : public Window { StringID GetCapacityString(RefitOption *option) const { assert(_current_company == _local_company); - CommandCost cost = Command::Do(DC_QUERY_COST, this->selected_vehicle, option->cargo, option->subtype, this->auto_refit, false, this->num_vehicles); + auto [cost, refit_capacity, mail_capacity] = Command::Do(DC_QUERY_COST, this->selected_vehicle, option->cargo, option->subtype, this->auto_refit, false, this->num_vehicles); if (cost.Failed()) return INVALID_STRING_ID; SetDParam(0, option->cargo); - SetDParam(1, _returned_refit_capacity); + SetDParam(1, refit_capacity); Money money = cost.GetCost(); - if (_returned_mail_refit_capacity > 0) { + if (mail_capacity > 0) { SetDParam(2, CT_MAIL); - SetDParam(3, _returned_mail_refit_capacity); + SetDParam(3, mail_capacity); if (this->order != INVALID_VEH_ORDER_ID) { /* No predictable cost */ return STR_PURCHASE_INFO_AIRCRAFT_CAPACITY; @@ -3119,15 +3119,15 @@ void StopGlobalFollowVehicle(const Vehicle *v) /** * This is the Callback method after the construction attempt of a primary vehicle - * @param result indicates completion (or not) of the operation * @param cmd unused - * @param tile unused + * @param result indicates completion (or not) of the operation + * @param new_veh_id ID of the new vehicle. */ -void CcBuildPrimaryVehicle(Commands cmd, const CommandCost &result, TileIndex tile) +void CcBuildPrimaryVehicle(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16) { if (result.Failed()) return; - const Vehicle *v = Vehicle::Get(_new_vehicle_id); + const Vehicle *v = Vehicle::Get(new_veh_id); ShowVehicleViewWindow(v); }