changeset 14009:809a3be57aef draft

(svn r18551) -Fix [FS#1762]: When autoreplace is the only allowed reason to send vehicles to depot, first check some minimal requirements (engine availability, refittability) and a heuristic for the needed money.
author frosch <frosch@openttd.org>
date Sat, 19 Dec 2009 21:54:34 +0000
parents 6eca3533ed1d
children 122bec54f0ad
files src/vehicle.cpp
diffstat 1 files changed, 30 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -45,6 +45,7 @@
 #include "network/network.h"
 #include "core/pool_func.hpp"
 #include "economy_base.h"
+#include "articulated_vehicles.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -96,7 +97,8 @@
 	if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
 
 	/* Are we ready for the next service cycle? */
-	if (Company::Get(this->owner)->settings.vehicle.servint_ispercent ?
+	const Company *c = Company::Get(this->owner);
+	if (c->settings.vehicle.servint_ispercent ?
 			(this->reliability >= Engine::Get(this->engine_type)->reliability * (100 - this->service_interval) / 100) :
 			(this->date_of_last_service + this->service_interval >= _date)) {
 		return false;
@@ -109,9 +111,33 @@
 		return true;
 	}
 
-	/* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off.
-	 * Note: If servicing is enabled, we postpone replacement till next service. */
-	return EngineHasReplacementForCompany(Company::Get(this->owner), this->engine_type, this->group_id);
+	/* Test whether there is some pending autoreplace.
+	 * Note: We do this after the service-interval test.
+	 * There are a lot more reasons for autoreplace to fail than we can test here reasonably. */
+	bool pending_replace = false;
+	Money needed_money = c->settings.engine_renew_money;
+	if (needed_money > c->money) return false;
+
+	const Vehicle *v = this;
+	do {
+		EngineID new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id);
+		/* Check engine availability */
+		if (new_engine != INVALID_ENGINE && HasBit(Engine::Get(new_engine)->company_avail, v->owner)) {
+			/* Check refittability */
+			CargoID cargo_type = CT_INVALID;
+			if (!IsArticulatedVehicleCarryingDifferentCargos(v, &cargo_type) && cargo_type != CT_INVALID &&
+					HasBit(GetIntersectionOfArticulatedRefitMasks(new_engine, true), cargo_type)) {
+				/* Check money.
+				 * We want 2*(the price of the new vehicle) without looking at the value of the vehicle we are going to sell. */
+				pending_replace = true;
+				needed_money += 2 * Engine::Get(new_engine)->GetCost();
+				if (needed_money > c->money) break;
+			}
+		}
+		v = (v->type == VEH_TRAIN) ? Train::From(v)->GetNextUnit() : NULL;
+	} while (v != NULL);
+
+	return pending_replace && needed_money <= c->money;
 }
 
 bool Vehicle::NeedsAutomaticServicing() const