(svn r14683) -Change: only say a engine/vehicle is refittable when it can be refitted to at least two cargo type or when it has subcargos.
authorrubidium
Tue, 16 Dec 2008 22:02:12 +0000
changeset 10430 3125f2adebc5
parent 10429 b81d72d5b44a
child 10431 13946af4ff98
(svn r14683) -Change: only say a engine/vehicle is refittable when it can be refitted to at least two cargo type or when it has subcargos.
NOTE: it is still possible that a vehicle is marked refittable when there is nothing to refit to, e.g. when only one subcargo is available but that cannot be determined without a vehicle chain.
src/build_vehicle_gui.cpp
src/engine.cpp
src/engine_func.h
src/vehicle_gui.cpp
--- a/src/build_vehicle_gui.cpp	Tue Dec 16 20:15:36 2008 +0000
+++ b/src/build_vehicle_gui.cpp	Tue Dec 16 22:02:12 2008 +0000
@@ -566,8 +566,6 @@
 /* Draw road vehicle specific details */
 static int DrawRoadVehPurchaseInfo(int x, int y, EngineID engine_number, const RoadVehicleInfo *rvi)
 {
-	bool refittable = (EngInfo(engine_number)->refit_mask != 0);
-
 	/* Purchase cost - Max speed */
 	SetDParam(0, GetEngineProperty(engine_number, 0x11, rvi->cost_factor) * (_price.roadveh_base >> 3) >> 5);
 	SetDParam(1, rvi->max_speed * 10 / 32);
@@ -580,7 +578,7 @@
 	y += 10;
 
 	/* Cargo type + capacity */
-	return DrawCargoCapacityInfo(x, y, engine_number, VEH_ROAD, refittable);
+	return DrawCargoCapacityInfo(x, y, engine_number, VEH_ROAD, IsEngineRefittable(engine_number));
 }
 
 /* Draw ship specific details */
@@ -595,7 +593,7 @@
 	/* Cargo type + capacity */
 	SetDParam(0, svi->cargo_type);
 	SetDParam(1, GetEngineProperty(engine_number, 0x0D, svi->capacity));
-	SetDParam(2, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
+	SetDParam(2, IsEngineRefittable(engine_number) ? STR_9842_REFITTABLE : STR_EMPTY);
 	DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, TC_FROMSTRING);
 	y += 10;
 
@@ -654,15 +652,13 @@
 	const Engine *e = GetEngine(engine_number);
 	YearMonthDay ymd;
 	ConvertDateToYMD(e->intro_date, &ymd);
-	bool refitable = false;
+	bool refittable = IsEngineRefittable(engine_number);
 
 	switch (e->type) {
 		default: NOT_REACHED();
 		case VEH_TRAIN: {
 			const RailVehicleInfo *rvi = RailVehInfo(engine_number);
-			uint capacity = GetEngineProperty(engine_number, 0x14, rvi->capacity);
-
-			refitable = (EngInfo(engine_number)->refit_mask != 0) && (capacity > 0);
+			refittable &= GetEngineProperty(engine_number, 0x14, rvi->capacity) > 0;
 
 			if (rvi->railveh_type == RAILVEH_WAGON) {
 				y = DrawRailWagonPurchaseInfo(x, y, engine_number, rvi);
@@ -671,7 +667,7 @@
 			}
 
 			/* Cargo type + capacity, or N/A */
-			int new_y = DrawCargoCapacityInfo(x, y, engine_number, VEH_TRAIN, refitable);
+			int new_y = DrawCargoCapacityInfo(x, y, engine_number, VEH_TRAIN, refittable);
 
 			if (new_y == y) {
 				SetDParam(0, CT_INVALID);
@@ -685,16 +681,12 @@
 		}
 		case VEH_ROAD:
 			y = DrawRoadVehPurchaseInfo(x, y, engine_number, RoadVehInfo(engine_number));
-			refitable = true;
 			break;
-		case VEH_SHIP: {
-			const ShipVehicleInfo *svi = ShipVehInfo(engine_number);
-			y = DrawShipPurchaseInfo(x, y, engine_number, svi);
-			refitable = svi->refittable;
-		} break;
+		case VEH_SHIP:
+			y = DrawShipPurchaseInfo(x, y, engine_number, ShipVehInfo(engine_number));
+			break;
 		case VEH_AIRCRAFT:
 			y = DrawAircraftPurchaseInfo(x, y, engine_number, AircraftVehInfo(engine_number));
-			refitable = true;
 			break;
 	}
 
@@ -714,7 +706,7 @@
 
 	/* Additional text from NewGRF */
 	y += ShowAdditionalText(x, y, w, engine_number);
-	if (refitable) y += ShowRefitOptionsList(x, y, w, engine_number);
+	if (refittable) y += ShowRefitOptionsList(x, y, w, engine_number);
 
 	return y;
 }
--- a/src/engine.cpp	Tue Dec 16 20:15:36 2008 +0000
+++ b/src/engine.cpp	Tue Dec 16 22:02:12 2008 +0000
@@ -559,6 +559,32 @@
 	return true;
 }
 
+/**
+ * Check if an engine is refittable.
+ * @param engine index of the engine to check.
+ * @return true if the engine is refittable.
+ */
+bool IsEngineRefittable(EngineID engine)
+{
+	/* check if it's an engine that is in the engine array */
+	if (!IsEngineIndex(engine)) return false;
+
+	const Engine *e = GetEngine(engine);
+
+	if (e->type == VEH_SHIP && !e->u.ship.refittable) return false;
+
+	const EngineInfo *ei = &e->info;
+	if (ei->refit_mask == 0) return false;
+
+	/* Are there suffixes?
+	 * Note: This does not mean the suffixes are actually available for every consist at any time. */
+	if (HasBit(ei->callbackmask, CBM_VEHICLE_CARGO_SUFFIX)) return true;
+
+	/* Is there any cargo except the default cargo? */
+	CargoID default_cargo = GetEngineCargoType(engine);
+	return default_cargo != CT_INVALID && ei->refit_mask != 1U << default_cargo;
+}
+
 /** Get the default cargo type for a certain engine type
  * @param engine The ID to get the cargo for
  * @return The cargo type. CT_INVALID means no cargo capacity
--- a/src/engine_func.h	Tue Dec 16 20:15:36 2008 +0000
+++ b/src/engine_func.h	Tue Dec 16 22:02:12 2008 +0000
@@ -26,6 +26,7 @@
 void DeleteCustomEngineNames();
 
 bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company);
+bool IsEngineRefittable(EngineID engine);
 CargoID GetEngineCargoType(EngineID engine);
 void SetCachedEngineCounts();
 
--- a/src/vehicle_gui.cpp	Tue Dec 16 20:15:36 2008 +0000
+++ b/src/vehicle_gui.cpp	Tue Dec 16 22:02:12 2008 +0000
@@ -1666,16 +1666,16 @@
 /** Checks whether the vehicle may be refitted at the moment.*/
 static bool IsVehicleRefitable(const Vehicle *v)
 {
-	/* Why is this so different for different vehicles?
-	 * Does maybe work one solution for all?
-	 */
-	switch (v->type) {
-		case VEH_TRAIN:    return false;
-		case VEH_ROAD:     return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot();
-		case VEH_SHIP:     return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot();
-		case VEH_AIRCRAFT: return v->IsStoppedInDepot();
-		default: NOT_REACHED();
-	}
+	if (!v->IsStoppedInDepot()) return false;
+
+	do {
+		/* Skip this vehicle if it has no capacity */
+		if (v->cargo_cap == 0) continue;
+
+		if (IsEngineRefittable(v->engine_type)) return true;
+	} while ((v->type == VEH_TRAIN || v->type == VEH_ROAD) && (v = v->Next()) != NULL);
+
+	return false;
 }
 
 struct VehicleViewWindow : Window {
@@ -1858,20 +1858,6 @@
 		if (v->type == VEH_TRAIN) {
 			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localcompany);
 			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localcompany);
-
-			/* Cargo refit button is disabled, until we know we can enable it below. */
-
-			if (is_localcompany) {
-				/* See if any vehicle can be refitted */
-				for (const Vehicle *u = v; u != NULL; u = u->Next()) {
-					if (EngInfo(u->engine_type)->refit_mask != 0 ||
-							(RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) {
-						this->EnableWidget(VVW_WIDGET_REFIT_VEH);
-						/* We have a refittable carriage, bail out */
-						break;
-					}
-				}
-			}
 		}
 
 		/* draw widgets & caption */