diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index dd39b4fed0..b94d6e11a4 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 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 f90536b4d0..58c606a91a 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 callback_param1 = 0, uint32 callback_param2 = 0); + TownScopeResolver *GetTown(); + ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, VarSpriteGroupScopeOffset 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 b43fb4733e..4339f4978c 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -223,7 +223,9 @@ static uint32 GetAirportTileIDAtOffset(TileIndex tile, const Station *st, uint32 */ AirportTileResolverObject::AirportTileResolverObject(const AirportTileSpec *ats, TileIndex tile, Station *st, CallbackID callback, uint32 callback_param1, uint32 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 dff59e1375..aa2965583e 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 callback_param1 = 0, uint32 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); } }