diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/newgrf_airporttiles.cpp | 225 | ||||
-rw-r--r-- | src/newgrf_airporttiles.h | 2 | ||||
-rw-r--r-- | src/newgrf_callbacks.h | 14 | ||||
-rw-r--r-- | src/newgrf_industrytiles.cpp | 2 | ||||
-rw-r--r-- | src/newgrf_spritegroup.h | 5 | ||||
-rw-r--r-- | src/station_cmd.cpp | 13 | ||||
-rw-r--r-- | src/station_map.h | 13 |
7 files changed, 272 insertions, 2 deletions
diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index 0eda02e1a..c1327bd43 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -10,9 +10,17 @@ /** @file newgrf_airporttiles.cpp NewGRF handling of airport tiles. */ #include "stdafx.h" +#include "debug.h" #include "airport.h" #include "newgrf.h" #include "newgrf_airporttiles.h" +#include "newgrf_spritegroup.h" +#include "station_base.h" +#include "water.h" +#include "viewport_func.h" +#include "landscape.h" +#include "company_base.h" +#include "town.h" #include "table/airporttiles.h" @@ -67,3 +75,220 @@ void AirportTileOverrideManager::SetEntitySpec(const AirportTileSpec *airpts) } } +/** + * Do airporttile gfx ID translation for NewGRFs. + * @param gfx the type to get the override for. + * @return the gfx to actually work with. + */ +StationGfx GetTranslatedAirportTileID(StationGfx gfx) +{ + assert(gfx < NUM_AIRPORTTILES); + const AirportTileSpec *it = AirportTileSpec::Get(gfx); + return it->grf_prop.override == INVALID_AIRPORTTILE ? gfx : it->grf_prop.override; +} + + +static const SpriteGroup *AirportTileResolveReal(const ResolverObject *object, const RealSpriteGroup *group) +{ + /* AirportTile do not have 'real' groups. */ + return NULL; +} + +/** + * Based on newhouses/newindustries equivalent, but adapted for airports. + * @param parameter from callback. It's in fact a pair of coordinates + * @param tile TileIndex from which the callback was initiated + * @param index of the industry been queried for + * @return a construction of bits obeying the newgrf format + */ +uint32 GetNearbyAirportTileInformation(byte parameter, TileIndex tile, StationID index) +{ + if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required + bool is_same_airport = (IsTileType(tile, MP_STATION) && IsAirport(tile) && GetStationIndex(tile) == index); + + return GetNearbyTileInformation(tile) | (is_same_airport ? 1 : 0) << 8; +} + + +/** + * Make an analysis of a tile and check whether it belongs to the same + * airport, and/or the same grf file + * @param tile TileIndex of the tile to query + * @param st Station to which to compare the tile to + * @param cur_grfid GRFID of the current callback + * @return value encoded as per NFO specs + */ +static uint32 GetAirportTileIDAtOffset(TileIndex tile, const Station *st, uint32 cur_grfid) +{ + if (!st->TileBelongsToAirport(tile)) { + return 0xFFFF; + } + + /* Don't use GetAirportGfx here as we want the original (not overriden) + * graphics id. */ + StationGfx gfx = GetStationGfx(tile); + const AirportTileSpec *ats = AirportTileSpec::Get(gfx); + + if (gfx < NEW_AIRPORTTILE_OFFSET) { // Does it belongs to an old type? + /* It is an old tile. We have to see if it's been overriden */ + if (ats->grf_prop.override == INVALID_AIRPORTTILE) { // has it been overridden? + return 0xFF << 8 | gfx; // no. Tag FF + the gfx id of that tile + } + /* Overriden */ + const AirportTileSpec *tile_ovr = AirportTileSpec::Get(ats->grf_prop.override); + + if (tile_ovr->grf_prop.grffile->grfid == cur_grfid) { + return tile_ovr->grf_prop.local_id; // same grf file + } else { + return 0xFFFE; // not the same grf file + } + } + /* Not an 'old type' tile */ + if (ats->grf_prop.spritegroup != NULL) { // tile has a spritegroup ? + if (ats->grf_prop.grffile->grfid == cur_grfid) { // same airport, same grf ? + return ats->grf_prop.local_id; + } else { + return 0xFFFE; // Defined in another grf file + } + } + /* The tile has no spritegroup */ + return 0xFF << 8 | ats->grf_prop.subst_id; // so just give him the substitute +} + +static uint32 AirportTileGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) +{ + const Station *st = object->u.airport.st; + TileIndex tile = object->u.airport.tile; + assert(st != NULL); + + if (object->scope == VSG_SCOPE_PARENT) { + DEBUG(grf, 1, "Parent scope for airport tiles unavailable"); + *available = false; + return UINT_MAX; + } + + extern uint32 GetRelativePosition(TileIndex tile, TileIndex ind_tile); + + switch (variable) { + /* Terrain type */ + case 0x41: return GetTerrainType(tile); + + /* Current town zone of the tile in the nearest town */ + case 0x42: return GetTownRadiusGroup(ClosestTownFromTile(tile, UINT_MAX), tile); + + /* Position relative to most northern airport tile. */ + case 0x43: return GetRelativePosition(tile, st->airport_tile); + + /* Animation frame of tile */ + case 0x44: return GetStationAnimationFrame(tile); + + /* Land info of nearby tiles */ + case 0x60: return GetNearbyAirportTileInformation(parameter, tile, st->index); + + /* Animation stage of nearby tiles */ + case 0x61: + tile = GetNearbyTile(parameter, tile); + if (st->TileBelongsToAirport(tile)) { + return GetStationAnimationFrame(tile); + } + return UINT_MAX; + + /* Get airport tile ID at offset */ + case 0x62: return GetAirportTileIDAtOffset(GetNearbyTile(parameter, tile), st, object->grffile->grfid); + } + + DEBUG(grf, 1, "Unhandled airport tile property 0x%X", variable); + + *available = false; + return UINT_MAX; +} + +static void AirportTileResolver(ResolverObject *res, StationGfx gfx, TileIndex tile, Station *st) +{ + res->GetRandomBits = NULL; + res->GetTriggers = NULL; + res->SetTriggers = NULL; + res->GetVariable = AirportTileGetVariable; + res->ResolveReal = AirportTileResolveReal; + + assert(st != NULL); + res->psa = NULL; + res->u.airport.airport_id = st->airport_type; + res->u.airport.st = st; + res->u.airport.tile = tile; + + res->callback = CBID_NO_CALLBACK; + res->callback_param1 = 0; + res->callback_param2 = 0; + res->last_value = 0; + res->trigger = 0; + res->reseed = 0; + res->count = 0; + + const AirportTileSpec *ats = AirportTileSpec::Get(gfx); + res->grffile = ats->grf_prop.grffile; +} + +uint16 GetAirportTileCallback(CallbackID callback, uint32 param1, uint32 param2, StationGfx gfx_id, Station *st, TileIndex tile) +{ + ResolverObject object; + const SpriteGroup *group; + + AirportTileResolver(&object, gfx_id, tile, st); + object.callback = callback; + object.callback_param1 = param1; + object.callback_param2 = param2; + + group = SpriteGroup::Resolve(AirportTileSpec::Get(gfx_id)->grf_prop.spritegroup, &object); + if (group == NULL) return CALLBACK_FAILED; + + return group->GetCallbackResult(); +} + +static void AirportDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte colour, StationGfx gfx) +{ + const DrawTileSprites *dts = group->dts; + + SpriteID image = dts->ground.sprite; + SpriteID pal = dts->ground.pal; + + if (GB(image, 0, SPRITE_WIDTH) != 0) { + if (image == SPR_FLAT_WATER_TILE && GetWaterClass(ti->tile) != WATER_CLASS_INVALID) { + DrawWaterClassGround(ti); + } else { + DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, GENERAL_SPRITE_COLOUR(colour))); + } + } + + DrawNewGRFTileSeq(ti, dts, TO_BUILDINGS, 0, GENERAL_SPRITE_COLOUR(colour)); +} + +bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const AirportTileSpec *airts) +{ + const SpriteGroup *group; + ResolverObject object; + + if (ti->tileh != SLOPE_FLAT) { + bool draw_old_one = true; + if (HasBit(airts->callback_flags, CBM_AIRT_DRAW_FOUNDATIONS)) { + /* Called to determine the type (if any) of foundation to draw */ + uint32 callback_res = GetAirportTileCallback(CBID_AIRPTILE_DRAW_FOUNDATIONS, 0, 0, gfx, st, ti->tile); + draw_old_one = (callback_res != 0); + } + + if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED); + } + + AirportTileResolver(&object, gfx, ti->tile, st); + + group = SpriteGroup::Resolve(airts->grf_prop.spritegroup, &object); + if (group == NULL || group->type != SGT_TILELAYOUT) { + return false; + } + + const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group; + AirportDrawTileLayout(ti, tlgroup, Company::Get(st->owner)->colour, gfx); + return true; +} + + diff --git a/src/newgrf_airporttiles.h b/src/newgrf_airporttiles.h index 0a77f4e16..b5ba8787f 100644 --- a/src/newgrf_airporttiles.h +++ b/src/newgrf_airporttiles.h @@ -40,4 +40,6 @@ private: friend void AirportTileOverrideManager::SetEntitySpec(const AirportTileSpec *airpts); }; +bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const AirportTileSpec *airts); + #endif /* NEWGRF_AIRPORTTILES_H */ diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h index 3b1d26d26..661445017 100644 --- a/src/newgrf_callbacks.h +++ b/src/newgrf_callbacks.h @@ -220,6 +220,9 @@ enum CallbackID { /** Called to determine if one can alter the ground below a house tile */ CBID_HOUSE_AUTOSLOPE = 0x14F, // 15 bit callback + + /** Called to determine the type (if any) of foundation to draw for an airport tile. */ + CBID_AIRPTILE_DRAW_FOUNDATIONS = 0x150, // 15 bit callback }; /** @@ -316,6 +319,17 @@ enum IndustryTileCallbackMask { }; /** + * Callback masks for airport tiles + */ +enum AirportTileCallbackMask { + CBM_AIRT_ANIM_NEXT_FRAME = 0, ///< decides next animation frame + CBM_AIRT_ANIM_SPEED = 1, ///< decides animation speed + CBM_AIRT_SHAPE_CHECK = 4, ///< decides slope suitability + CBM_AIRT_DRAW_FOUNDATIONS = 5, ///< decides if default foundations need to be drawn + CBM_AIRT_AUTOSLOPE = 6, ///< decides allowance of autosloping +}; + +/** * Different values for Callback result evaluations */ enum { diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 70eebe0a8..63e8b7524 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -55,7 +55,7 @@ uint32 GetNearbyIndustryTileInformation(byte parameter, TileIndex tile, Industry * @param tile TileIndex of the tile to evaluate * @param ind_tile northernmost tile of the industry */ -static uint32 GetRelativePosition(TileIndex tile, TileIndex ind_tile) +uint32 GetRelativePosition(TileIndex tile, TileIndex ind_tile) { byte x = TileX(tile) - TileX(ind_tile); byte y = TileY(tile) - TileY(ind_tile); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 22c202aa6..1bcc7de7e 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -342,6 +342,11 @@ struct ResolverObject { struct { TileIndex tile; } routes; + struct { + const struct Station *st; + byte airport_id; + TileIndex tile; + } airport; } u; uint32 (*GetRandomBits)(const struct ResolverObject*); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 4539fb38f..807bbcb9f 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2398,7 +2398,18 @@ static void DrawTile_Station(TileInfo *ti) } if (IsAirport(ti->tile)) { - switch (GetStationGfx(ti->tile)) { + StationGfx gfx = GetAirportGfx(ti->tile); + if (gfx >= NEW_AIRPORTTILE_OFFSET) { + const AirportTileSpec *ats = AirportTileSpec::Get(gfx); + if (ats->grf_prop.spritegroup != NULL && DrawNewAirportTile(ti, Station::GetByTile(ti->tile), gfx, ats)) { + return; + } + /* No sprite group (or no valid one) found, meaning no graphics associated. + * Use the substitute one instead */ + assert(ats->grf_prop.subst_id != INVALID_AIRPORTTILE); + gfx = ats->grf_prop.subst_id; + } + switch (gfx) { case APT_RADAR_GRASS_FENCE_SW: t = &_station_display_datas_airport_radar_grass_fence_sw[GetStationAnimationFrame(ti->tile)]; break; diff --git a/src/station_map.h b/src/station_map.h index 35b5c55c8..060457d15 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -263,6 +263,19 @@ static inline bool IsDriveThroughStopTile(TileIndex t) } /** + * Get the station graphics of this airport tile + * @param t the tile to query + * @pre IsAirport(t) + * @return the station graphics + */ +static inline StationGfx GetAirportGfx(TileIndex t) +{ + assert(IsAirport(t)); + extern StationGfx GetTranslatedAirportTileID(StationGfx gfx); + return GetTranslatedAirportTileID(GetStationGfx(t)); +} + +/** * Gets the direction the road stop entrance points towards. * @param t the tile of the road stop * @pre IsRoadStopTile(t) |