diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vehicle_cmd.cpp | 6 | ||||
-rw-r--r-- | src/vehicle_func.h | 1 | ||||
-rw-r--r-- | src/vehicle_gui.cpp | 63 |
3 files changed, 68 insertions, 2 deletions
diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index e710b905d..f696d1153 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -536,8 +536,10 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (flags & DC_EXEC) { assert(w != NULL); - if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_subtype) { - CommandCost cost = DoCommand(0, w->index, v->cargo_type | (v->cargo_subtype << 8) | 1U << 16, flags, GetCmdRefitVeh(v)); + /* Find out what's the best sub type */ + byte subtype = GetBestFittingSubType(v, w); + if (w->cargo_type != v->cargo_type || w->cargo_subtype != subtype) { + CommandCost cost = DoCommand(0, w->index, v->cargo_type | (subtype << 8) | 1U << 16, flags, GetCmdRefitVeh(v)); if (CmdSucceeded(cost)) total_cost.AddCost(cost); } diff --git a/src/vehicle_func.h b/src/vehicle_func.h index b709dba14..b37f8e56e 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -42,6 +42,7 @@ byte VehicleRandomBits(); void ResetVehiclePosHash(); void ResetVehicleColourMap(); +byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for); CommandCost RefitVehicle(Vehicle *v, bool only_this, CargoID new_cid, byte new_subtype, DoCommandFlag flags); void ViewportAddVehicles(DrawPixelInfo *dpi); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 614259e34..a9401784f 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -159,6 +159,69 @@ static void DrawVehicleProfitButton(const Vehicle *v, int x, int y) /** Maximum number of refit cycles we try, to prevent infinite loops. */ static const int MAX_REFIT_CYCLE = 16; +/** + * Get the best fitting subtype when 'cloning'/'replacing' v_from with v_for. + * Assuming they are going to carry the same cargo ofcourse! + * @param v_from the vehicle to match the subtype from + * @param v_for the vehicle to get the subtype for + * @return the best sub type + */ +byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for) +{ + const Engine *e_from = Engine::Get(v_from->engine_type); + const Engine *e_for = Engine::Get(v_for->engine_type); + + /* If one them doesn't carry cargo, there's no need to find a sub type */ + if (!e_from->CanCarryCargo() || !e_for->CanCarryCargo()) return 0; + + if (!HasBit(e_from->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX) || + !HasBit(e_for->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) { + /* One of the engines doesn't have cargo suffixes, i.e. sub types. */ + return 0; + } + + /* It has to be possible for v_for to carry the cargo of v_from. */ + assert(HasBit(e_for->info.refit_mask, v_from->cargo_type)); + + StringID expected_string = GetCargoSubtypeText(v_from); + + CargoID old_cargo_type = v_for->cargo_type; + byte old_cargo_subtype = v_for->cargo_subtype; + byte ret_refit_cyc = 0; + + /* Set the 'destination' cargo */ + v_for->cargo_type = v_from->cargo_type; + + /* Cycle through the refits */ + for (byte refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) { + v_for->cargo_subtype = refit_cyc; + + /* Make sure we don't pick up anything cached. */ + v_for->First()->InvalidateNewGRFCache(); + v_for->InvalidateNewGRFCache(); + uint16 callback = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v_for->engine_type, v_for); + + if (callback == 0xFF) callback = CALLBACK_FAILED; + if (callback == CALLBACK_FAILED) break; + + if (GetCargoSubtypeText(v_for) != expected_string) continue; + + /* We found something matching. */ + ret_refit_cyc = refit_cyc; + break; + } + + /* Reset the vehicle's cargo type */ + v_for->cargo_type = old_cargo_type; + v_for->cargo_subtype = old_cargo_subtype; + + /* Make sure we don't taint the vehicle. */ + v_for->First()->InvalidateNewGRFCache(); + v_for->InvalidateNewGRFCache(); + + return ret_refit_cyc; +} + struct RefitOption { CargoID cargo; byte subtype; |