summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vehicle_cmd.cpp6
-rw-r--r--src/vehicle_func.h1
-rw-r--r--src/vehicle_gui.cpp63
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;