MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / CmdCloneVehicle

Function CmdCloneVehicle

src/vehicle_cmd.cpp:830–1013  ·  view source on GitHub ↗

* Clone a vehicle. If it is a train, it will clone all the cars too * @param flags type of operation * @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 + the new vehicle ID or an error */

Source from the content-addressed store, hash-verified

828 * @return the cost of this operation + the new vehicle ID or an error
829 */
830std::tuple<CommandCost, VehicleID> CmdCloneVehicle(DoCommandFlags flags, TileIndex tile, VehicleID veh_id, bool share_orders)
831{
832 CommandCost total_cost(EXPENSES_NEW_VEHICLES);
833
834 Vehicle *v = Vehicle::GetIfValid(veh_id);
835 if (v == nullptr || !v->IsPrimaryVehicle()) return { CMD_ERROR, VehicleID::Invalid() };
836 Vehicle *v_front = v;
837 Vehicle *w = nullptr;
838 Vehicle *w_front = nullptr;
839 Vehicle *w_rear = nullptr;
840
841 /*
842 * v_front is the front engine in the original vehicle
843 * v is the car/vehicle of the original vehicle that is currently being copied
844 * w_front is the front engine of the cloned vehicle
845 * w is the car/vehicle currently being cloned
846 * w_rear is the rear end of the cloned train. It's used to add more cars and is only used by trains
847 */
848
849 CommandCost ret = CheckOwnership(v->owner);
850 if (ret.Failed()) return { ret, VehicleID::Invalid() };
851
852 /* Crashed trains can only be cloned before cleanup begins. */
853 if (v->type == VEH_TRAIN && (!v->IsFrontEngine() || Train::From(v)->crash_anim_pos >= 4400)) return { CommandCost(STR_ERROR_VEHICLE_IS_DESTROYED), VehicleID::Invalid() };
854
855 /* check that we can allocate enough vehicles */
856 if (!flags.Test(DoCommandFlag::Execute)) {
857 int veh_counter = 0;
858 do {
859 veh_counter++;
860 } while ((v = v->Next()) != nullptr);
861
862 if (!Vehicle::CanAllocateItem(veh_counter)) {
863 return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), VehicleID::Invalid() };
864 }
865 }
866
867 v = v_front;
868
869 VehicleID new_veh_id = VehicleID::Invalid();
870 do {
871 if (v->type == VEH_TRAIN && Train::From(v)->IsRearDualheaded()) {
872 /* we build the rear ends of multiheaded trains with the front ones */
873 continue;
874 }
875
876 /* In case we're building a multi headed vehicle and the maximum number of
877 * vehicles is almost reached (e.g. max trains - 1) not all vehicles would
878 * be cloned. When the non-primary engines were build they were seen as
879 * 'new' vehicles whereas they would immediately be joined with a primary
880 * engine. This caused the vehicle to be not build as 'the limit' had been
881 * reached, resulting in partially build vehicles and such. */
882 DoCommandFlags build_flags = flags;
883 if (flags.Test(DoCommandFlag::Execute) && !v->IsPrimaryVehicle()) build_flags.Set(DoCommandFlag::AutoReplace);
884
885 CommandCost cost;
886 std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command<CMD_BUILD_VEHICLE>::Do(build_flags, tile, v->engine_type, false, INVALID_CARGO, INVALID_CLIENT_ID);
887

Callers

nothing calls this directly

Calls 15

InvalidFunction · 0.85
CheckOwnershipFunction · 0.85
CommandCostClass · 0.85
GetBestFittingSubTypeFunction · 0.85
IsValidCargoTypeFunction · 0.85
GetRefitCostFunction · 0.85
CloneVehicleNameFunction · 0.85
CheckCompanyHasMoneyFunction · 0.85
FailedMethod · 0.80
IsFrontEngineMethod · 0.80
TestMethod · 0.80

Tested by

no test coverage detected