summaryrefslogtreecommitdiff
path: root/src/articulated_vehicles.cpp
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2009-03-13 21:28:40 +0000
committerfrosch <frosch@openttd.org>2009-03-13 21:28:40 +0000
commit4129b418ccab3ed2bc6b7ab196e99d401ca67599 (patch)
tree8317c89e21d332e45318d53d44851fe0a13c0a4a /src/articulated_vehicles.cpp
parente6353a1a221bee43d2f04b060f62d3ea41633483 (diff)
downloadopenttd-4129b418ccab3ed2bc6b7ab196e99d401ca67599.tar.xz
(svn r15701) -Fix [FS#2595]: Blame NewGRFs returning inconsistent information in purchase-list/after building before users have a chance to blame OpenTTD for incorrectly autorenewing/-replacing.
Diffstat (limited to 'src/articulated_vehicles.cpp')
-rw-r--r--src/articulated_vehicles.cpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp
index 4729b5a55..2a6fb6b2c 100644
--- a/src/articulated_vehicles.cpp
+++ b/src/articulated_vehicles.cpp
@@ -9,6 +9,8 @@
#include "newgrf_engine.h"
#include "vehicle_func.h"
+#include "table/strings.h"
+
static const uint MAX_ARTICULATED_PARTS = 100; ///< Maximum of articulated parts per vehicle, i.e. when to abort calling the articulated vehicle callback.
uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
@@ -238,6 +240,64 @@ bool IsArticulatedVehicleCarryingDifferentCargos(const Vehicle *v, CargoID *carg
return false;
}
+/**
+ * Checks whether the specs of freshly build articulated vehicles are consistent with the information specified in the purchase list.
+ * Only essential information is checked to leave room for magic tricks/workarounds to grfcoders.
+ * It checks:
+ * For autoreplace/-renew:
+ * - Default cargo type (without capacity)
+ * - intersection and union of refit masks.
+ */
+void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
+{
+ const Engine *engine = GetEngine(v->engine_type);
+
+ uint32 purchase_refit_union = GetUnionOfArticulatedRefitMasks(v->engine_type, v->type, true);
+ uint32 purchase_refit_intersection = GetIntersectionOfArticulatedRefitMasks(v->engine_type, v->type, true);
+ uint16 *purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type, v->type);
+
+ uint32 real_refit_union = 0;
+ uint32 real_refit_intersection = UINT_MAX;
+ uint16 real_default_capacity[NUM_CARGO];
+ memset(real_default_capacity, 0, sizeof(real_default_capacity));
+
+ do {
+ uint32 refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, v->type, true);
+ real_refit_union |= refit_mask;
+ if (refit_mask != 0) real_refit_intersection &= refit_mask;
+
+ assert(v->cargo_type < NUM_CARGO);
+ real_default_capacity[v->cargo_type] += v->cargo_cap;
+
+ switch (v->type) {
+ case VEH_TRAIN:
+ v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
+ break;
+
+ case VEH_ROAD:
+ v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
+ break;
+
+ default:
+ v = NULL;
+ break;
+ }
+ } while (v != NULL);
+
+ /* Check whether the vehicle carries more cargos than expected */
+ bool carries_more = false;
+ for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
+ if (real_default_capacity[cid] != 0 && purchase_default_capacity[cid] == 0) {
+ carries_more = true;
+ break;
+ }
+ }
+
+ /* show a warning once for each GRF after each game load */
+ if (real_refit_union != purchase_refit_union || real_refit_intersection != purchase_refit_intersection || carries_more) {
+ ShowNewGrfVehicleError(engine->index, STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ARTICULATED_CARGO, GBUG_VEH_REFIT, false);
+ }
+}
void AddArticulatedParts(Vehicle **vl, VehicleType type)
{