@@ -1507,96 +1507,98 @@ int32 CmdCloneVehicle(int x, int y, uint
w_front = NULL;
w_rear = NULL;
/*
* v_front is the front engine in the original vehicle
* v is the car/vehicle of the original vehicle, that is currently being copied
* w_front is the front engine of the cloned vehicle
* w is the car/vehicle currently being cloned
* w_rear is the rear end of the cloned train. It's used to add more cars and is only used by trains
*/
if (!CheckOwnership(v->owner)) return CMD_ERROR;
if (v->type == VEH_Train && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR;
// check that we can allocate enough vehicles
if (!(flags & DC_EXEC)) {
int veh_counter = 0;
do {
veh_counter++;
} while ((v = v->next) != NULL);
if (!AllocateVehicles(NULL, veh_counter)) {
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
}
v = v_front;
if (IsMultiheaded(v) && !IsTrainEngine(v)) {
/* we build the rear ends of multiheaded trains with the front ones */
continue;
cost = DoCommand(x, y, v->engine_type, 1, flags, CMD_BUILD_VEH(v->type));
if (CmdFailed(cost)) return cost;
total_cost += cost;
if (flags & DC_EXEC) {
w = GetVehicle(_new_vehicle_id);
if (v->type != VEH_Road) { // road vehicles can't be refitted
if (v->cargo_type != w->cargo_type) {
// we can't pay for refitting because we can't estimate refitting costs for a vehicle before it's build
// if we pay for it anyway, the cost and the estimated cost will not be the same and we will have an assert
DoCommand(x, y, w->index, v->cargo_type, flags, CMD_REFIT_VEH(v->type));
if (v->type == VEH_Train && !IsFrontEngine(v)) {
// this s a train car
// add this unit to the end of the train
DoCommand(x, y, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);
} else {
// this is a front engine or not a train. It need orders
w_front = w;
DoCommand(x, y, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
} while (v->type == VEH_Train && (v = GetNextVehicle(v)) != NULL);
if (flags & DC_EXEC && v_front->type == VEH_Train) {
// _new_train_id needs to be the front engine due to the callback function
_new_train_id = w_front->index;
return total_cost;
* move the cargo from one engine to another if possible
static void MoveVehicleCargo(Vehicle *dest, Vehicle *source)
{
Vehicle *v = dest;
int units_moved;
if (source->cargo_type != dest->cargo_type)
continue; // cargo not compatible
if (dest->cargo_count == dest->cargo_cap)
continue; // the destination vehicle is already full
units_moved = min(source->cargo_count, dest->cargo_cap - dest->cargo_count);
source->cargo_count -= units_moved;
dest->cargo_count += units_moved;
dest->cargo_source = source->cargo_source;
// copy the age of the cargo
dest->cargo_days = source->cargo_days;
dest->day_counter = source->day_counter;
Status change: