diff --git a/newgrf_engine.c b/newgrf_engine.c index e4c3074c23..79abce13ce 100644 --- a/newgrf_engine.c +++ b/newgrf_engine.c @@ -476,7 +476,7 @@ static void VehicleSetTriggers(const ResolverObject *object, int triggers) } -static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter) +static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) { const Vehicle *v = GRV(object); @@ -487,8 +487,10 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by case 0x46: return 0; /* Motion counter */ case 0xC4: return _cur_year; /* Build year */ case 0xDA: return INVALID_VEHICLE; /* Next vehicle */ - default: return -1; } + + *available = false; + return -1; } /* Calculated vehicle parameters */ @@ -719,6 +721,7 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by DEBUG(grf, 1)("Unhandled vehicle property 0x%X, type 0x%X", variable, v->type); + *available = false; return -1; } diff --git a/newgrf_spritegroup.c b/newgrf_spritegroup.c index 110bab1ef0..0b94ff984b 100644 --- a/newgrf_spritegroup.c +++ b/newgrf_spritegroup.c @@ -70,7 +70,7 @@ void InitializeSpriteGroupPool(void) } -static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter) +static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) { /* Return common variables */ switch (variable) { @@ -90,7 +90,7 @@ static inline uint32 GetVariable(const ResolverObject *object, byte variable, by case 0x20: return _opt.landscape == LT_HILLY ? _opt.snow_line : 0xFF; /* Not a common variable, so evalute the feature specific variables */ - default: return object->GetVariable(object, variable, parameter); + default: return object->GetVariable(object, variable, parameter, available); } } @@ -142,7 +142,6 @@ BUILD_EVAL_ADJUST(int32, uint32) static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, ResolverObject *object) { static SpriteGroup nvarzero; - const SpriteGroup *target; int32 last_value = object->last_value; int32 value = -1; uint i; @@ -151,7 +150,17 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol for (i = 0; i < group->g.determ.num_adjusts; i++) { DeterministicSpriteGroupAdjust *adjust = &group->g.determ.adjusts[i]; - value = GetVariable(object, adjust->variable, adjust->parameter); + + /* Try to get the variable. We shall assume it is available, unless told otherwise. */ + bool available = true; + value = GetVariable(object, adjust->variable, adjust->parameter, &available); + + if (!available) { + /* Unsupported property: skip further processing and return either + * the group from the first range or the default group. */ + return Resolve(group->g.determ.num_ranges > 0 ? group->g.determ.ranges[0].group : group->g.determ.default_group, object); + } + switch (group->g.determ.size) { case DSG_SIZE_BYTE: value = EvalAdjust_int8(adjust, last_value, value); break; case DSG_SIZE_WORD: value = EvalAdjust_int16(adjust, last_value, value); break; @@ -161,27 +170,20 @@ static inline const SpriteGroup *ResolveVariable(const SpriteGroup *group, Resol last_value = value; } - if (value == -1) { - /* Unsupported property */ - target = group->g.determ.num_ranges > 0 ? group->g.determ.ranges[0].group : group->g.determ.default_group; - } else { - if (group->g.determ.num_ranges == 0) { - /* nvar == 0 is a special case -- we turn our value into a callback result */ - nvarzero.type = SGT_CALLBACK; - nvarzero.g.callback.result = GB(value, 0, 15) | 0x8000; - return &nvarzero; - } + if (group->g.determ.num_ranges == 0) { + /* nvar == 0 is a special case -- we turn our value into a callback result */ + nvarzero.type = SGT_CALLBACK; + nvarzero.g.callback.result = GB(value, 0, 15) | 0x8000; + return &nvarzero; + } - target = group->g.determ.default_group; - for (i = 0; i < group->g.determ.num_ranges; i++) { - if (group->g.determ.ranges[i].low <= (uint32)value && (uint32)value <= group->g.determ.ranges[i].high) { - target = group->g.determ.ranges[i].group; - break; - } + for (i = 0; i < group->g.determ.num_ranges; i++) { + if (group->g.determ.ranges[i].low <= (uint32)value && (uint32)value <= group->g.determ.ranges[i].high) { + return Resolve(group->g.determ.ranges[i].group, object); } } - return Resolve(target, object); + return Resolve(group->g.determ.default_group, object); } diff --git a/newgrf_spritegroup.h b/newgrf_spritegroup.h index bb51f56e5f..471299abbb 100644 --- a/newgrf_spritegroup.h +++ b/newgrf_spritegroup.h @@ -180,7 +180,7 @@ typedef struct ResolverObject { uint32 (*GetRandomBits)(const struct ResolverObject*); uint32 (*GetTriggers)(const struct ResolverObject*); void (*SetTriggers)(const struct ResolverObject*, int); - uint32 (*GetVariable)(const struct ResolverObject*, byte, byte); + uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*); const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const SpriteGroup*); } ResolverObject; diff --git a/newgrf_station.c b/newgrf_station.c index b1b521eeef..9ef7362ef7 100644 --- a/newgrf_station.c +++ b/newgrf_station.c @@ -309,7 +309,7 @@ static void StationSetTriggers(const ResolverObject *object, int triggers) } -static uint32 StationGetVariable(const ResolverObject *object, byte variable, byte parameter) +static uint32 StationGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) { const Station *st = object->u.station.st; TileIndex tile = object->u.station.tile; @@ -326,8 +326,10 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by case 0x43: return _current_player; /* Station owner */ case 0x44: return 2; /* PBS status */ case 0xFA: return _date; /* Build date */ - default: return -1; } + + *available = false; + return -1; } switch (variable) { @@ -390,6 +392,7 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by DEBUG(grf, 1)("Unhandled station property 0x%X", variable); + *available = false; return -1; }