summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/newgrf_engine.cpp75
-rw-r--r--src/vehicle_base.h16
2 files changed, 62 insertions, 29 deletions
diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp
index 6e0ce75ec..80e249710 100644
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -483,36 +483,8 @@ static uint32 PositionHelper(const Vehicle *v, bool consecutive)
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 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
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 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
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)
{
diff --git a/src/vehicle_base.h b/src/vehicle_base.h
index 958144115..5fc2500eb 100644
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -499,6 +499,22 @@ public:
}
/**
+ * 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.
*/