changeset 18168:ac1c1cc6e8a4 draft

(svn r22997) -Feature: [NewGRF] Allow access to other vehicles in the vehicle chain in VarAction 2.
author michi_cc <michi_cc@openttd.org>
date Tue, 04 Oct 2011 21:35:29 +0000
parents 9c82695de33e
children c0dd5603dfd4
files src/newgrf_engine.cpp src/vehicle_base.h
diffstat 2 files changed, 62 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -483,36 +483,8 @@
 	return chain_before | chain_after << 8 | (chain_before + chain_after + consecutive) << 16;
 }
 
-static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
+static uint32 VehicleGetVariable(Vehicle *v, const ResolverObject *object, byte variable, byte parameter, bool *available)
 {
-	Vehicle *v = const_cast<Vehicle*>(GRV(object));
-
-	if (v == NULL) {
-		/* Vehicle does not exist, so we're in a purchase list */
-		switch (variable) {
-			case 0x43: return GetCompanyInfo(_current_company, LiveryHelper(object->u.vehicle.self_type, NULL)); // Owner information
-			case 0x46: return 0;               // Motion counter
-			case 0x47: { // Vehicle cargo info
-				const Engine *e = Engine::Get(object->u.vehicle.self_type);
-				CargoID cargo_type = e->GetDefaultCargoType();
-				if (cargo_type != CT_INVALID) {
-					const CargoSpec *cs = CargoSpec::Get(cargo_type);
-					return (cs->classes << 16) | (cs->weight << 8) | GetEngineGRF(e->index)->cargo_map[cargo_type];
-				} else {
-					return 0x000000FF;
-				}
-			}
-			case 0x48: return Engine::Get(object->u.vehicle.self_type)->flags; // Vehicle Type Info
-			case 0x49: return _cur_year; // 'Long' format build year
-			case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
-			case 0xDA: return INVALID_VEHICLE; // Next vehicle
-			case 0xF2: return 0; // Cargo subtype
-		}
-
-		*available = false;
-		return UINT_MAX;
-	}
-
 	/* Calculated vehicle parameters */
 	switch (variable) {
 		case 0x25: // Get engine GRF ID
@@ -668,6 +640,18 @@
 				return count;
 			}
 
+		case 0x61: // Get variable of n-th vehicle in chain [signed number relative to vehicle]
+			if (!v->IsGroundVehicle() || parameter == 0x61) return 0;
+
+			/* Only allow callbacks that don't change properties to avoid circular dependencies. */
+			if (object->callback == CBID_NO_CALLBACK || object->callback == CBID_TRAIN_ALLOW_WAGON_ATTACH || object->callback == CBID_VEHICLE_START_STOP_CHECK || object->callback == CBID_VEHICLE_32DAY_CALLBACK) {
+				Vehicle *u = v->Move((int32)GetRegister(0x10F));
+				if (u == NULL) return 0;
+
+				return VehicleGetVariable(u, object, parameter, GetRegister(0x10E), available);
+			}
+			return 0;
+
 		case 0xFE:
 		case 0xFF: {
 			uint16 modflags = 0;
@@ -846,6 +830,39 @@
 	return UINT_MAX;
 }
 
+static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
+{
+	Vehicle *v = const_cast<Vehicle*>(GRV(object));
+
+	if (v == NULL) {
+		/* Vehicle does not exist, so we're in a purchase list */
+		switch (variable) {
+			case 0x43: return GetCompanyInfo(_current_company, LiveryHelper(object->u.vehicle.self_type, NULL)); // Owner information
+			case 0x46: return 0;               // Motion counter
+			case 0x47: { // Vehicle cargo info
+				const Engine *e = Engine::Get(object->u.vehicle.self_type);
+				CargoID cargo_type = e->GetDefaultCargoType();
+				if (cargo_type != CT_INVALID) {
+					const CargoSpec *cs = CargoSpec::Get(cargo_type);
+					return (cs->classes << 16) | (cs->weight << 8) | GetEngineGRF(e->index)->cargo_map[cargo_type];
+				} else {
+					return 0x000000FF;
+				}
+			}
+			case 0x48: return Engine::Get(object->u.vehicle.self_type)->flags; // Vehicle Type Info
+			case 0x49: return _cur_year; // 'Long' format build year
+			case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
+			case 0xDA: return INVALID_VEHICLE; // Next vehicle
+			case 0xF2: return 0; // Cargo subtype
+		}
+
+		*available = false;
+		return UINT_MAX;
+	}
+
+	return VehicleGetVariable(v, object, variable, parameter, available);
+}
+
 
 static const SpriteGroup *VehicleResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
 {
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -499,6 +499,22 @@
 	}
 
 	/**
+	 * Get the vehicle at offset #n of this vehicle chain.
+	 * @param n Offset from the current vehicle.
+	 * @return The new vehicle or NULL if the offset is out-of-bounds.
+	 */
+	inline Vehicle *Move(int n)
+	{
+		Vehicle *v = this;
+		if (n < 0) {
+			for (int i = 0; i != n && v != NULL; i--) v = v->Previous();
+		} else {
+			for (int i = 0; i != n && v != NULL; i++) v = v->Next();
+		}
+		return v;
+	}
+
+	/**
 	 * Get the first order of the vehicles order list.
 	 * @return first order of order list.
 	 */