summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/newgrf_airport.cpp11
-rw-r--r--src/newgrf_airporttiles.cpp8
-rw-r--r--src/newgrf_canal.cpp20
-rw-r--r--src/newgrf_cargo.cpp8
-rw-r--r--src/newgrf_engine.cpp85
-rw-r--r--src/newgrf_engine.h10
-rw-r--r--src/newgrf_generic.cpp8
-rw-r--r--src/newgrf_house.cpp11
-rw-r--r--src/newgrf_industries.cpp12
-rw-r--r--src/newgrf_industrytiles.cpp10
-rw-r--r--src/newgrf_object.cpp29
-rw-r--r--src/newgrf_railtype.cpp16
-rw-r--r--src/newgrf_railtype.h2
-rw-r--r--src/newgrf_spritegroup.cpp1
-rw-r--r--src/newgrf_spritegroup.h20
-rw-r--r--src/newgrf_station.cpp72
-rw-r--r--src/table/newgrf_debug_data.h4
17 files changed, 143 insertions, 184 deletions
diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp
index 4c5b21a6b..4201fc622 100644
--- a/src/newgrf_airport.cpp
+++ b/src/newgrf_airport.cpp
@@ -237,6 +237,7 @@ AirportResolverObject::AirportResolverObject(TileIndex tile, Station *st, byte a
CallbackID callback, uint32 param1, uint32 param2)
: ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, airport_id, layout)
{
+ this->root_spritegroup = AirportSpec::Get(airport_id)->grf_prop.spritegroup[0];
}
/**
@@ -258,7 +259,7 @@ AirportScopeResolver::AirportScopeResolver(ResolverObject &ro, TileIndex tile, S
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout)
{
AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout);
- const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) return as->preview_sprite;
return group->GetResult();
@@ -267,10 +268,7 @@ SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout)
uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Station *st, TileIndex tile)
{
AirportResolverObject object(tile, st, st->airport.type, st->airport.layout, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(st->airport.GetSpec()->grf_prop.spritegroup[0], object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
/**
@@ -283,8 +281,7 @@ uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Sta
StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback)
{
AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout, (CallbackID)callback);
- const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], object);
- uint16 cb_res = (group != NULL) ? group->GetCallbackResult() : CALLBACK_FAILED;
+ uint16 cb_res = object.ResolveCallback();
if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
if (cb_res > 0x400) {
ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res);
diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp
index cc9471c80..323fb6cc1 100644
--- a/src/newgrf_airporttiles.cpp
+++ b/src/newgrf_airporttiles.cpp
@@ -217,6 +217,7 @@ AirportTileResolverObject::AirportTileResolverObject(const AirportTileSpec *ats,
CallbackID callback, uint32 callback_param1, uint32 callback_param2)
: ResolverObject(ats->grf_prop.grffile, callback, callback_param1, callback_param2), tiles_scope(*this, ats, tile, st)
{
+ this->root_spritegroup = ats->grf_prop.spritegroup[0];
}
/**
@@ -237,10 +238,7 @@ AirportTileScopeResolver::AirportTileScopeResolver(ResolverObject &ro, const Air
uint16 GetAirportTileCallback(CallbackID callback, uint32 param1, uint32 param2, const AirportTileSpec *ats, Station *st, TileIndex tile, int extra_data = 0)
{
AirportTileResolverObject object(ats, tile, st, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(ats->grf_prop.spritegroup[0], object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
static void AirportDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte colour, StationGfx gfx)
@@ -275,7 +273,7 @@ bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const Airport
}
AirportTileResolverObject object(airts, ti->tile, st);
- const SpriteGroup *group = SpriteGroup::Resolve(airts->grf_prop.spritegroup[0], object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->type != SGT_TILELAYOUT) {
return false;
}
diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp
index 7310186c0..8f81fd0d8 100644
--- a/src/newgrf_canal.cpp
+++ b/src/newgrf_canal.cpp
@@ -33,7 +33,7 @@ struct CanalScopeResolver : public ScopeResolver {
struct CanalResolverObject : public ResolverObject {
CanalScopeResolver canal_scope;
- CanalResolverObject(const GRFFile *grffile, TileIndex tile,
+ CanalResolverObject(CanalFeature feature, TileIndex tile,
CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
/* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
@@ -115,16 +115,17 @@ CanalScopeResolver::CanalScopeResolver(ResolverObject &ro, TileIndex tile) : Sco
/**
* Canal resolver constructor.
- * @param grffile Grf file.
+ * @param feature Which canal feature we want.
* @param tile Tile index of canal.
* @param callback Callback ID.
* @param callback_param1 First parameter (var 10) of the callback.
* @param callback_param2 Second parameter (var 18) of the callback.
*/
-CanalResolverObject::CanalResolverObject(const GRFFile *grffile, TileIndex tile,
+CanalResolverObject::CanalResolverObject(CanalFeature feature, TileIndex tile,
CallbackID callback, uint32 callback_param1, uint32 callback_param2)
- : ResolverObject(grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile)
+ : ResolverObject(_water_feature[feature].grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile)
{
+ this->root_spritegroup = _water_feature[feature].group;
}
/**
@@ -135,8 +136,8 @@ CanalResolverObject::CanalResolverObject(const GRFFile *grffile, TileIndex tile,
*/
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
{
- CanalResolverObject object(_water_feature[feature].grffile, tile);
- const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object);
+ CanalResolverObject object(feature, tile);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) return 0;
return group->GetResult();
@@ -153,11 +154,8 @@ SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
*/
static uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile)
{
- CanalResolverObject object(_water_feature[feature].grffile, tile, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ CanalResolverObject object(feature, tile, callback, param1, param2);
+ return object.ResolveCallback();
}
/**
diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp
index 4186b53f6..016698523 100644
--- a/src/newgrf_cargo.cpp
+++ b/src/newgrf_cargo.cpp
@@ -40,6 +40,7 @@ struct CargoResolverObject : public ResolverObject {
CargoResolverObject::CargoResolverObject(const CargoSpec *cs, CallbackID callback, uint32 callback_param1, uint32 callback_param2)
: ResolverObject(cs->grffile, callback, callback_param1, callback_param2)
{
+ this->root_spritegroup = cs->group;
}
/**
@@ -50,7 +51,7 @@ CargoResolverObject::CargoResolverObject(const CargoSpec *cs, CallbackID callbac
SpriteID GetCustomCargoSprite(const CargoSpec *cs)
{
CargoResolverObject object(cs);
- const SpriteGroup *group = SpriteGroup::Resolve(cs->group, object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) return 0;
return group->GetResult();
@@ -60,10 +61,7 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs)
uint16 GetCargoCallback(CallbackID callback, uint32 param1, uint32 param2, const CargoSpec *cs)
{
CargoResolverObject object(cs, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(cs->group, object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
/**
diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp
index 309decb72..5d3af4105 100644
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -973,12 +973,13 @@ static const GRFFile *GetEngineGrfFile(EngineID engine_type)
* Resolver of a vehicle (chain).
* @param engine_type Engine type
* @param v %Vehicle being resolved.
+ * @param wagon_override Application of wagon overrides.
* @param info_view Indicates if the item is being drawn in an info window.
* @param callback Callback ID.
* @param callback_param1 First parameter (var 10) of the callback.
* @param callback_param2 Second parameter (var 18) of the callback.
*/
-VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, bool info_view,
+VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view,
CallbackID callback, uint32 callback_param1, uint32 callback_param2)
: ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2),
self_scope(*this, engine_type, v, info_view),
@@ -986,55 +987,37 @@ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle
relative_scope(*this, engine_type, v, info_view),
cached_relative_count(0)
{
-}
-
-/**
- * Retrieve the SpriteGroup for the specified vehicle.
- * If the vehicle is not specified, the purchase list group for the engine is
- * chosen. For trains, an additional engine override lookup is performed.
- * @param engine Engine type of the vehicle.
- * @param v The vehicle itself.
- * @param use_cache Use cached override
- * @returns The selected SpriteGroup for the vehicle.
- */
-static const SpriteGroup *GetVehicleSpriteGroup(EngineID engine, const Vehicle *v, bool use_cache = true)
-{
- const SpriteGroup *group;
- CargoID cargo;
-
- if (v == NULL) {
- cargo = CT_PURCHASE;
+ if (wagon_override == WO_SELF) {
+ this->root_spritegroup = GetWagonOverrideSpriteSet(engine_type, CT_DEFAULT, engine_type);
} else {
- cargo = v->cargo_type;
+ if (wagon_override != WO_NONE && v != NULL && v->IsGroundVehicle()) {
+ assert(v->engine_type == engine_type); // overrides make little sense with fake scopes
- if (v->IsGroundVehicle()) {
/* For trains we always use cached value, except for callbacks because the override spriteset
* to use may be different than the one cached. It happens for callback 0x15 (refit engine),
* as v->cargo_type is temporary changed to the new type */
- if (use_cache && v->type == VEH_TRAIN) {
- group = Train::From(v)->tcache.cached_override;
+ if (wagon_override == WO_CACHED && v->type == VEH_TRAIN) {
+ this->root_spritegroup = Train::From(v)->tcache.cached_override;
} else {
- group = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine);
+ this->root_spritegroup = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine);
}
- if (group != NULL) return group;
}
- }
- const Engine *e = Engine::Get(engine);
-
- assert(cargo < lengthof(e->grf_prop.spritegroup));
- group = e->grf_prop.spritegroup[cargo];
- if (group != NULL) return group;
-
- /* Fall back to the default set if the selected cargo type is not defined */
- return e->grf_prop.spritegroup[CT_DEFAULT];
+ if (this->root_spritegroup == NULL) {
+ const Engine *e = Engine::Get(engine_type);
+ CargoID cargo = v != NULL ? v->cargo_type : CT_PURCHASE;
+ assert(cargo < lengthof(e->grf_prop.spritegroup));
+ this->root_spritegroup = e->grf_prop.spritegroup[cargo] != NULL ? e->grf_prop.spritegroup[cargo] : e->grf_prop.spritegroup[CT_DEFAULT];
+ }
+ }
}
+
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type)
{
- VehicleResolverObject object(engine, v, false, CBID_NO_CALLBACK, image_type);
- const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), object);
+ VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK, image_type);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
return group->GetResult() + (direction % group->GetNumResults());
@@ -1049,15 +1032,14 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi
assert(e->type == VEH_AIRCRAFT);
assert(!(e->u.air.subtype & AIR_CTOL));
- VehicleResolverObject object(engine, v, info_view, CBID_NO_CALLBACK, image_type);
- const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
- group = SpriteGroup::Resolve(group, object);
+ VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK, image_type);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
- if (v == NULL) return group->GetResult();
+ if (v == NULL || info_view) return group->GetResult();
- return group->GetResult() + (info_view ? 0 : (v->Next()->Next()->state % group->GetNumResults()));
+ return group->GetResult() + (v->Next()->Next()->state % group->GetNumResults());
}
@@ -1083,11 +1065,8 @@ bool UsesWagonOverride(const Vehicle *v)
*/
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
{
- VehicleResolverObject object(engine, v, false, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ VehicleResolverObject object(engine, v, VehicleResolverObject::WO_UNCACHED, false, callback, param1, param2);
+ return object.ResolveCallback();
}
/**
@@ -1102,13 +1081,9 @@ uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, Eng
*/
uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent)
{
- VehicleResolverObject object(engine, v, false, callback, param1, param2);
+ VehicleResolverObject object(engine, v, VehicleResolverObject::WO_NONE, false, callback, param1, param2);
object.parent_scope.SetVehicle(parent);
-
- const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
@@ -1133,10 +1108,10 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando
/* We can't trigger a non-existent vehicle... */
assert(v != NULL);
- VehicleResolverObject object(v->engine_type, v, false, CBID_RANDOM_TRIGGER);
+ VehicleResolverObject object(v->engine_type, v, VehicleResolverObject::WO_CACHED, false, CBID_RANDOM_TRIGGER);
object.trigger = trigger;
- const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(v->engine_type, v), object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) return;
byte new_random_bits = Random();
@@ -1300,7 +1275,7 @@ void CommitVehicleListOrderChanges()
*/
void FillNewGRFVehicleCache(const Vehicle *v)
{
- VehicleResolverObject ro(v->engine_type, v);
+ VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_NONE);
/* These variables we have to check; these are the ones with a cache. */
static const int cache_entries[][2] = {
diff --git a/src/newgrf_engine.h b/src/newgrf_engine.h
index 5e1661cca..4a6f211c4 100644
--- a/src/newgrf_engine.h
+++ b/src/newgrf_engine.h
@@ -38,13 +38,21 @@ struct VehicleScopeResolver : public ScopeResolver {
/** Resolver for a vehicle (chain) */
struct VehicleResolverObject : public ResolverObject {
+ /** Application of 'wagon overrides'. */
+ enum WagonOverride {
+ WO_NONE, //!< Resolve no wagon overrides.
+ WO_UNCACHED, //!< Resolve wagon overrides.
+ WO_CACHED, //!< Resolve wagon overrides using TrainCache::cached_override.
+ WO_SELF, //!< Resolve self-override (helicopter rotors and such).
+ };
+
VehicleScopeResolver self_scope; ///< Scope resolver for the indicated vehicle.
VehicleScopeResolver parent_scope; ///< Scope resolver for its parent vehicle.
VehicleScopeResolver relative_scope; ///< Scope resolver for an other vehicle in the chain.
byte cached_relative_count; ///< Relative position of the other vehicle.
- VehicleResolverObject(EngineID engine_type, const Vehicle *v, bool info_view = false,
+ VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view = false,
CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
/* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0);
diff --git a/src/newgrf_generic.cpp b/src/newgrf_generic.cpp
index f1305636d..55eee6d23 100644
--- a/src/newgrf_generic.cpp
+++ b/src/newgrf_generic.cpp
@@ -179,17 +179,17 @@ static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject &object, ui
/* Test each feature callback sprite group. */
for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) {
- const SpriteGroup *group = it->group;
object.grffile = it->file;
+ object.root_spritegroup = it->group;
/* Set callback param based on GRF version. */
object.callback_param1 = it->file->grf_version >= 8 ? param1_grfv8 : param1_grfv7;
- group = SpriteGroup::Resolve(group, object);
- if (group == NULL || group->GetCallbackResult() == CALLBACK_FAILED) continue;
+ uint16 result = object.ResolveCallback();
+ if (result == CALLBACK_FAILED) continue;
/* Return NewGRF file if necessary */
if (file != NULL) *file = it->file;
- return group->GetCallbackResult();
+ return result;
}
/* No callback returned a valid result, so we've failed. */
diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp
index a31ac4bc4..c660fe3ab 100644
--- a/src/newgrf_house.cpp
+++ b/src/newgrf_house.cpp
@@ -81,6 +81,7 @@ HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town
house_scope(*this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers),
town_scope(*this, town, not_yet_constructed) // Don't access StorePSA if house is not yet constructed.
{
+ this->root_spritegroup = HouseSpec::Get(house_id)->grf_prop.spritegroup[0];
}
HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid)
@@ -439,11 +440,7 @@ uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, House
HouseResolverObject object(house_id, tile, town, callback, param1, param2,
not_yet_constructed, initial_random_bits, watched_cargo_triggers);
-
- const SpriteGroup *group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->grf_prop.spritegroup[0], object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte stage, HouseID house_id)
@@ -490,7 +487,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
HouseResolverObject object(house_id, ti->tile, Town::GetByTile(ti->tile));
- const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], object);
+ const SpriteGroup *group = object.Resolve();
if (group != NULL && group->type == SGT_TILELAYOUT) {
/* Limit the building stage to the number of stages supplied. */
const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
@@ -615,7 +612,7 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando
HouseResolverObject object(hid, tile, Town::GetByTile(tile), CBID_RANDOM_TRIGGER);
object.trigger = trigger;
- const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) return;
byte new_random_bits = Random();
diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp
index dfc615b29..725373d10 100644
--- a/src/newgrf_industries.cpp
+++ b/src/newgrf_industries.cpp
@@ -432,6 +432,7 @@ IndustriesResolverObject::IndustriesResolverObject(TileIndex tile, Industry *ind
industries_scope(*this, tile, indus, type, random_bits),
town_scope(NULL)
{
+ this->root_spritegroup = GetIndustrySpec(type)->grf_prop.spritegroup[0];
}
IndustriesResolverObject::~IndustriesResolverObject()
@@ -490,10 +491,7 @@ IndustriesScopeResolver::IndustriesScopeResolver(ResolverObject &ro, TileIndex t
uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile)
{
IndustriesResolverObject object(tile, industry, type, 0, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
/**
@@ -523,12 +521,10 @@ CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uin
ind.psa = NULL;
IndustriesResolverObject object(tile, &ind, type, seed, CBID_INDUSTRY_LOCATION, 0, creation_type);
- const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], object);
+ uint16 result = object.ResolveCallback();
/* Unlike the "normal" cases, not having a valid result means we allow
* the building of the industry, as that's how it's done in TTDP. */
- if (group == NULL) return CommandCost();
- uint16 result = group->GetCallbackResult();
if (result == CALLBACK_FAILED) return CommandCost();
return GetErrorMessageFromLocationCallbackResult(result, indspec->grf_prop.grffile, STR_ERROR_SITE_UNSUITABLE);
@@ -596,7 +592,7 @@ void IndustryProductionCallback(Industry *ind, int reason)
}
SB(object.callback_param2, 8, 16, loop);
- const SpriteGroup *tgroup = SpriteGroup::Resolve(spec->grf_prop.spritegroup[0], object);
+ const SpriteGroup *tgroup = object.Resolve();
if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break;
const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup;
diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp
index 7e31c1bc4..f22514a03 100644
--- a/src/newgrf_industrytiles.cpp
+++ b/src/newgrf_industrytiles.cpp
@@ -147,6 +147,7 @@ IndustryTileResolverObject::IndustryTileResolverObject(IndustryGfx gfx, TileInde
indtile_scope(*this, indus, tile),
ind_scope(*this, tile, indus, indus->type)
{
+ this->root_spritegroup = GetIndustryTileSpec(gfx)->grf_prop.spritegroup[0];
}
/**
@@ -190,10 +191,7 @@ uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2
assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY));
IndustryTileResolverObject object(gfx_id, tile, industry, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup[0], object);
- if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds)
@@ -211,7 +209,7 @@ bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const Indus
IndustryTileResolverObject object(gfx, ti->tile, i);
- const SpriteGroup *group = SpriteGroup::Resolve(inds->grf_prop.spritegroup[0], object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->type != SGT_TILELAYOUT) return false;
/* Limit the building stage to the number of stages supplied. */
@@ -328,7 +326,7 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I
IndustryTileResolverObject object(gfx, tile, ind, CBID_RANDOM_TRIGGER);
object.trigger = trigger;
- const SpriteGroup *group = SpriteGroup::Resolve(itspec->grf_prop.spritegroup[0], object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) return;
byte new_random_bits = Random();
diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp
index 3917b6510..6f7e3f0ff 100644
--- a/src/newgrf_object.cpp
+++ b/src/newgrf_object.cpp
@@ -356,24 +356,6 @@ unhandled:
}
/**
- * Get the object's sprite group.
- * @param spec The specification to get the sprite group from.
- * @param o The object to get he sprite group for.
- * @return The resolved sprite group.
- */
-static const SpriteGroup *GetObjectSpriteGroup(const ObjectSpec *spec, const Object *o)
-{
- const SpriteGroup *group = NULL;
-
- if (o == NULL) group = spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT];
- if (group != NULL) return group;
-
- /* Fall back to the default set if the selected cargo type is not defined */
- return spec->grf_prop.spritegroup[0];
-
-}
-
-/**
* Constructor of the object resolver.
* @param obj Object being resolved.
* @param tile %Tile of the object.
@@ -387,6 +369,8 @@ ObjectResolverObject::ObjectResolverObject(const ObjectSpec *spec, Object *obj,
: ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(*this, obj, tile, view)
{
this->town_scope = NULL;
+ this->root_spritegroup = (obj == NULL && spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT] != NULL) ?
+ spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT] : spec->grf_prop.spritegroup[0];
}
ObjectResolverObject::~ObjectResolverObject()
@@ -428,10 +412,7 @@ TownScopeResolver *ObjectResolverObject::GetTown()
uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view)
{
ObjectResolverObject object(spec, o, tile, view, callback, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), object);
- if (group == NULL) return CALLBACK_FAILED;
-
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
/**
@@ -471,7 +452,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
Object *o = Object::GetByTile(ti->tile);
ObjectResolverObject object(spec, o, ti->tile);
- const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->type != SGT_TILELAYOUT) return;
DrawTileLayout(ti, (const TileLayoutSpriteGroup *)group, spec);
@@ -487,7 +468,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view)
{
ObjectResolverObject object(spec, NULL, INVALID_TILE, view);
- const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, NULL), object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->type != SGT_TILELAYOUT) return;
const DrawTileSprites *dts = ((const TileLayoutSpriteGroup *)group)->ProcessRegisters(NULL);
diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp
index de735193f..f43689698 100644
--- a/src/newgrf_railtype.cpp
+++ b/src/newgrf_railtype.cpp
@@ -79,15 +79,17 @@ RailTypeScopeResolver::RailTypeScopeResolver(ResolverObject &ro, TileIndex tile,
/**
* Resolver object for rail types.
+ * @param rti Railtype. NULL in NewGRF Inspect window.
* @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead.
* @param context Are we resolving sprites for the upper halftile, or on a bridge?
- * @param grffile The GRF to do the lookup for.
+ * @param rtsg Railpart of interest
* @param param1 Extra parameter (first parameter of the callback, except railtypes do not have callbacks).
* @param param2 Extra parameter (second parameter of the callback, except railtypes do not have callbacks).
*/
-RailTypeResolverObject::RailTypeResolverObject(TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1, uint32 param2)
- : ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, tile, context)
+RailTypeResolverObject::RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1, uint32 param2)
+ : ResolverObject(rti != NULL ? rti->grffile[rtsg] : NULL, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, tile, context)
{
+ this->root_spritegroup = rti != NULL ? rti->group[rtsg] : NULL;
}
/**
@@ -104,8 +106,8 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp
if (rti->group[rtsg] == NULL) return 0;
- RailTypeResolverObject object(tile, context, rti->grffile[rtsg]);
- const SpriteGroup *group = SpriteGroup::Resolve(rti->group[rtsg], object);
+ RailTypeResolverObject object(rti, tile, context, rtsg);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
return group->GetResult();
@@ -127,9 +129,9 @@ SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalTy
uint32 param1 = gui ? 0x10 : 0x00;
uint32 param2 = (type << 16) | (var << 8) | state;
- RailTypeResolverObject object(tile, TCX_NORMAL, rti->grffile[RTSG_SIGNALS], param1, param2);
+ RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2);
- const SpriteGroup *group = SpriteGroup::Resolve(rti->group[RTSG_SIGNALS], object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
return group->GetResult();
diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h
index 8c5bce843..9b00bf5bf 100644
--- a/src/newgrf_railtype.h
+++ b/src/newgrf_railtype.h
@@ -31,7 +31,7 @@ struct RailTypeScopeResolver : public ScopeResolver {
struct RailTypeResolverObject : public ResolverObject {
RailTypeScopeResolver railtype_scope; ///< Resolver for the railtype scope.
- RailTypeResolverObject(TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1 = 0, uint32 param2 = 0);
+ RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1 = 0, uint32 param2 = 0);
/* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
{
diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp
index b3a0a829f..59fc70fe4 100644
--- a/src/newgrf_spritegroup.cpp
+++ b/src/newgrf_spritegroup.cpp
@@ -150,6 +150,7 @@ ResolverObject::ResolverObject(const GRFFile *grffile, CallbackID callback, uint
this->ResetState();
this->grffile = grffile;
+ this->root_spritegroup = NULL;
}
ResolverObject::~ResolverObject() {}
diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h
index c3753dcfd..0a7705d66 100644
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -321,6 +321,26 @@ struct ResolverObject {
uint32 reseed[VSG_END]; ///< Collects bits to rerandomise while triggering triggers.
const GRFFile *grffile; ///< GRFFile the resolved SpriteGroup belongs to
+ const SpriteGroup *root_spritegroup; ///< Root SpriteGroup to use for resolving
+
+ /**
+ * Resolve SpriteGroup.
+ * @return Result spritegroup.
+ */
+ const SpriteGroup *Resolve()
+ {
+ return SpriteGroup::Resolve(this->root_spritegroup, *this);
+ }
+
+ /**
+ * Resolve callback.
+ * @return Callback result.
+ */
+ uint16 ResolveCallback()
+ {
+ const SpriteGroup *result = Resolve();
+ return result != NULL ? result->GetCallbackResult() : CALLBACK_FAILED;
+ }
virtual const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp
index 85277337d..647e8781a 100644
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -550,6 +550,32 @@ StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseSt
{
/* Invalidate all cached vars */
_svc.valid = 0;
+
+ CargoID ctype = CT_DEFAULT_NA;
+
+ if (this->station_scope.st == NULL) {
+ /* No station, so we are in a purchase list */
+ ctype = CT_PURCHASE;
+ } else if (Station::IsExpected(this->station_scope.st)) {
+ const Station *st = Station::From(this->station_scope.st);
+ /* Pick the first cargo that we have waiting */
+ const CargoSpec *cs;
+ FOR_ALL_CARGOSPECS(cs) {
+ if (this->station_scope.statspec->grf_prop.spritegroup[cs->Index()] != NULL &&
+ st->goods[cs->Index()].cargo.TotalCount() > 0) {
+ ctype = cs->Index();
+ break;
+ }
+ }
+ }
+
+ if (this->station_scope.statspec->grf_prop.spritegroup[ctype] == NULL) {
+ ctype = CT_DEFAULT;
+ }
+
+ /* Remember the cargo type we've picked */
+ this->station_scope.cargo_type = ctype;
+ this->root_spritegroup = this->station_scope.statspec->grf_prop.spritegroup[this->station_scope.cargo_type];
}
StationResolverObject::~StationResolverObject()
@@ -574,39 +600,6 @@ StationScopeResolver::StationScopeResolver(ResolverObject &ro, const StationSpec
this->axis = INVALID_AXIS;
}
-static const SpriteGroup *ResolveStation(StationResolverObject &object)
-{
- CargoID ctype = CT_DEFAULT_NA;
-
- if (object.station_scope.st == NULL) {
- /* No station, so we are in a purchase list */
- ctype = CT_PURCHASE;
- } else if (Station::IsExpected(object.station_scope.st)) {
- const Station *st = Station::From(object.station_scope.st);
- /* Pick the first cargo that we have waiting */
- const CargoSpec *cs;
- FOR_ALL_CARGOSPECS(cs) {
- if (object.station_scope.statspec->grf_prop.spritegroup[cs->Index()] != NULL &&
- st->goods[cs->Index()].cargo.TotalCount() > 0) {
- ctype = cs->Index();
- break;
- }
- }
- }
-
- const SpriteGroup *group = object.station_scope.statspec->grf_prop.spritegroup[ctype];
- if (group == NULL) {
- ctype = CT_DEFAULT;
- group = object.station_scope.statspec->grf_prop.spritegroup[ctype];
- if (group == NULL) return NULL;
- }
-
- /* Remember the cargo type we've picked */
- object.station_scope.cargo_type = ctype;
-
- return SpriteGroup::Resolve(group, object);
-}
-
/**
* Resolve sprites for drawing a station tile.
* @param statspec Station spec
@@ -618,7 +611,7 @@ static const SpriteGroup *ResolveStation(StationResolverObject &object)
SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10)
{
StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, var10);
- const SpriteGroup *group = ResolveStation(object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->type != SGT_RESULT) return 0;
return group->GetResult() - 0x42D;
}
@@ -637,7 +630,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS
/* callback_param1 == 2 means we are resolving the foundation sprites. */
StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, 2, layout | (edge_info << 16));
- const SpriteGroup *group = ResolveStation(object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL || group->type != SGT_RESULT) return 0;
/* Note: SpriteGroup::Resolve zeroes all registers, so register 0x100 is initialised to 0. (compatibility) */
@@ -648,9 +641,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS
uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile)
{
StationResolverObject object(statspec, st, tile, callback, param1, param2);
- const SpriteGroup *group = ResolveStation(object);
- if (group == NULL) return CALLBACK_FAILED;
- return group->GetCallbackResult();
+ return object.ResolveCallback();
}
/**
@@ -673,8 +664,7 @@ CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_til
(numtracks << 24) | (plat_len << 16) | (axis == AXIS_Y ? TileX(diff) << 8 | TileY(diff) : TileY(diff) << 8 | TileX(diff)));
object.station_scope.axis = axis;
- const SpriteGroup *group = ResolveStation(object);
- uint16 cb_res = group != NULL ? group->GetCallbackResult() : CALLBACK_FAILED;
+ uint16 cb_res = object.ResolveCallback();
/* Failed callback means success. */
if (cb_res == CALLBACK_FAILED) return CommandCost();
@@ -1024,7 +1014,7 @@ void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigg
StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
object.trigger = trigger_bit;
- const SpriteGroup *group = ResolveStation(object);
+ const SpriteGroup *group = object.Resolve();
if (group == NULL) continue;
uint32 reseed = object.GetReseedSum();
diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h
index b4756882f..4814ae50c 100644
--- a/src/table/newgrf_debug_data.h
+++ b/src/table/newgrf_debug_data.h
@@ -79,7 +79,7 @@ class NIHVehicle : public NIHelper {
/* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const
{
Vehicle *v = Vehicle::Get(index);
- VehicleResolverObject ro(v->engine_type, v);
+ VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_CACHED);
return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
}
};
@@ -429,7 +429,7 @@ class NIHRailType : public NIHelper {
{
/* There is no unique GRFFile for the tile. Multiple GRFs can define different parts of the railtype.
* However, currently the NewGRF Debug GUI does not display variables depending on the GRF (like 0x7F) anyway. */
- RailTypeResolverObject ro(index, TCX_NORMAL, NULL);
+ RailTypeResolverObject ro(NULL, index, TCX_NORMAL, RTSG_END);
return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
}
};