diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index 93a01f2070..fe7566a7d4 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -14,6 +14,7 @@ #include "newgrf_text.h" #include "station_base.h" #include "newgrf_class_func.h" +#include "town.h" #include "safeguards.h" @@ -210,6 +211,26 @@ uint32_t AirportResolverObject::GetDebugID() const this->st->airport.psa->StoreValue(pos, value); } +/** + * Get the town scope associated with a station, if it exists. + * On the first call, the town scope is created (if possible). + * @return Town scope, if available. + */ +TownScopeResolver *AirportResolverObject::GetTown() +{ + if (!this->town_scope) { + Town *t = nullptr; + if (this->airport_scope.st != nullptr) { + t = this->airport_scope.st->town; + } else if (this->airport_scope.tile != INVALID_TILE) { + t = ClosestTownFromTile(this->airport_scope.tile, UINT_MAX); + } + if (t == nullptr) return nullptr; + this->town_scope.reset(new TownScopeResolver(*this, t, this->airport_scope.st == nullptr)); + } + return this->town_scope.get(); +} + /** * Constructor of the airport resolver. * @param tile %Tile for the callback, only valid for airporttile callbacks. diff --git a/src/newgrf_airport.h b/src/newgrf_airport.h index 8eec8ad1c0..273b0d60c8 100644 --- a/src/newgrf_airport.h +++ b/src/newgrf_airport.h @@ -15,6 +15,7 @@ #include "newgrf_class.h" #include "newgrf_commons.h" #include "newgrf_spritegroup.h" +#include "newgrf_town.h" #include "tilearea_type.h" /** Copy from station_map.h */ @@ -173,14 +174,23 @@ struct AirportScopeResolver : public ScopeResolver { /** Resolver object for airports. */ struct AirportResolverObject : public ResolverObject { AirportScopeResolver airport_scope; + std::unique_ptr town_scope; ///< The town scope resolver (created on the first call). AirportResolverObject(TileIndex tile, Station *st, byte airport_id, byte layout, CallbackID callback = CBID_NO_CALLBACK, uint32_t callback_param1 = 0, uint32_t callback_param2 = 0); + TownScopeResolver *GetTown(); + ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) override { switch (scope) { case VSG_SCOPE_SELF: return &this->airport_scope; + case VSG_SCOPE_PARENT: + { + TownScopeResolver *tsr = this->GetTown(); + if (tsr != nullptr) return tsr; + FALLTHROUGH; + } default: return ResolverObject::GetScope(scope, relative); } } diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index 0f817d3b07..1abf8b20bc 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -214,7 +214,9 @@ static uint32_t GetAirportTileIDAtOffset(TileIndex tile, const Station *st, uint */ AirportTileResolverObject::AirportTileResolverObject(const AirportTileSpec *ats, TileIndex tile, Station *st, CallbackID callback, uint32_t callback_param1, uint32_t callback_param2) - : ResolverObject(ats->grf_prop.grffile, callback, callback_param1, callback_param2), tiles_scope(*this, ats, tile, st) + : ResolverObject(ats->grf_prop.grffile, callback, callback_param1, callback_param2), + tiles_scope(*this, ats, tile, st), + airport_scope(*this, tile, st, st != nullptr ? st->airport.type : (byte)AT_DUMMY, st != nullptr ? st->airport.layout : 0) { this->root_spritegroup = ats->grf_prop.spritegroup[0]; } diff --git a/src/newgrf_airporttiles.h b/src/newgrf_airporttiles.h index 90a1457b0b..c855d64c15 100644 --- a/src/newgrf_airporttiles.h +++ b/src/newgrf_airporttiles.h @@ -44,6 +44,7 @@ struct AirportTileScopeResolver : public ScopeResolver { /** Resolver for tiles of an airport. */ struct AirportTileResolverObject : public ResolverObject { AirportTileScopeResolver tiles_scope; ///< Scope resolver for the tiles. + AirportScopeResolver airport_scope; ///< Scope resolver for the airport owning the tile. AirportTileResolverObject(const AirportTileSpec *ats, TileIndex tile, Station *st, CallbackID callback = CBID_NO_CALLBACK, uint32_t callback_param1 = 0, uint32_t callback_param2 = 0); @@ -52,6 +53,7 @@ struct AirportTileResolverObject : public ResolverObject { { switch (scope) { case VSG_SCOPE_SELF: return &tiles_scope; + case VSG_SCOPE_PARENT: return &airport_scope; default: return ResolverObject::GetScope(scope, relative); } }