diff --git a/src/elrail.cpp b/src/elrail.cpp index 108dc419cf..15ff1b0fac 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -165,20 +165,20 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks) /** * Get the base wire sprite to use. */ -static inline SpriteID GetWireBase(TileIndex tile, bool upper_halftile = false) +static inline SpriteID GetWireBase(TileIndex tile, TileContext context = TCX_NORMAL) { const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile)); - SpriteID wires = GetCustomRailSprite(rti, tile, RTSG_WIRES, upper_halftile); + SpriteID wires = GetCustomRailSprite(rti, tile, RTSG_WIRES, context); return wires == 0 ? SPR_WIRE_BASE : wires; } /** * Get the base pylon sprite to use. */ -static inline SpriteID GetPylonBase(TileIndex tile, bool upper_halftile = false) +static inline SpriteID GetPylonBase(TileIndex tile, TileContext context = TCX_NORMAL) { const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile)); - SpriteID pylons = GetCustomRailSprite(rti, tile, RTSG_PYLONS, upper_halftile); + SpriteID pylons = GetCustomRailSprite(rti, tile, RTSG_PYLONS, context); return pylons == 0 ? SPR_PYLON_BASE : pylons; } @@ -300,7 +300,7 @@ static void DrawCatenaryRailway(const TileInfo *ti) AdjustTileh(ti->tile, &tileh[TS_HOME]); SpriteID pylon_normal = GetPylonBase(ti->tile); - SpriteID pylon_halftile = (halftile_corner != CORNER_INVALID) ? GetPylonBase(ti->tile, true) : pylon_normal; + SpriteID pylon_halftile = (halftile_corner != CORNER_INVALID) ? GetPylonBase(ti->tile, TCX_UPPER_HALFTILE) : pylon_normal; for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) { static const uint edge_corners[] = { @@ -439,7 +439,7 @@ static void DrawCatenaryRailway(const TileInfo *ti) } SpriteID wire_normal = GetWireBase(ti->tile); - SpriteID wire_halftile = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, true) : wire_normal; + SpriteID wire_halftile = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, TCX_UPPER_HALFTILE) : wire_normal; Track halftile_track; switch (halftile_corner) { case CORNER_W: halftile_track = TRACK_LEFT; break; @@ -501,14 +501,14 @@ void DrawCatenaryOnBridge(const TileInfo *ti) height = GetBridgeHeight(end); - SpriteID wire_base = GetWireBase(start); + SpriteID wire_base = GetWireBase(end, TCX_ON_BRIDGE); AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset, sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset, IsTransparencySet(TO_CATENARY) ); - SpriteID pylon_base = GetPylonBase(start); + SpriteID pylon_base = GetPylonBase(end, TCX_ON_BRIDGE); /* Finished with wires, draw pylons * every other tile needs a pylon on the northern end */ diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index 5a1de575f0..c5a2ebea90 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -21,6 +21,7 @@ #include "station_map.h" #include "tree_map.h" #include "tunnelbridge_map.h" +#include "variables.h" #include "core/mem_func.hpp" /** Constructor of generic class @@ -283,7 +284,7 @@ void IndustryTileOverrideManager::SetEntitySpec(const IndustryTileSpec *its) * @param upper_halftile If true, query upper halftile in case of rail tiles. * @return value corresponding to the grf expected format: * Terrain type: 0 normal, 1 desert, 2 rainforest, 4 on or above snowline */ -uint32 GetTerrainType(TileIndex tile, bool upper_halftile) +uint32 GetTerrainType(TileIndex tile, TileContext context) { switch (_settings_game.game_creation.landscape) { case LT_TROPIC: return GetTropicZone(tile); @@ -291,27 +292,41 @@ uint32 GetTerrainType(TileIndex tile, bool upper_halftile) bool has_snow; switch (GetTileType(tile)) { case MP_CLEAR: + /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */ + if (_generating_world) goto genworld; has_snow = IsSnowTile(tile) && GetClearDensity(tile) >= 2; break; case MP_RAILWAY: { + /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */ + if (_generating_world) goto genworld; // we do not care about foundations here RailGroundType ground = GetRailGroundType(tile); - has_snow = (ground == RAIL_GROUND_ICE_DESERT || (upper_halftile && ground == RAIL_GROUND_HALF_SNOW)); + has_snow = (ground == RAIL_GROUND_ICE_DESERT || (context == TCX_UPPER_HALFTILE && ground == RAIL_GROUND_HALF_SNOW)); break; } case MP_ROAD: + /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */ + if (_generating_world) goto genworld; // we do not care about foundations here has_snow = IsOnSnow(tile); break; case MP_TREES: { + /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */ + if (_generating_world) goto genworld; TreeGround ground = GetTreeGround(tile); has_snow = (ground == TREE_GROUND_SNOW_DESERT || ground == TREE_GROUND_ROUGH_SNOW) && GetTreeDensity(tile) >= 2; break; } case MP_TUNNELBRIDGE: - has_snow = HasTunnelBridgeSnowOrDesert(tile); + if (context == TCX_ON_BRIDGE) { + has_snow = (GetBridgeHeight(tile) > GetSnowLine()); + } else { + /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */ + if (_generating_world) goto genworld; // we do not care about foundations here + has_snow = HasTunnelBridgeSnowOrDesert(tile); + } break; case MP_STATION: @@ -324,6 +339,7 @@ uint32 GetTerrainType(TileIndex tile, bool upper_halftile) case MP_VOID: case MP_WATER: + genworld: has_snow = (GetTileZ(tile) > GetSnowLine()); break; diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index df277b4b03..3c0ae571ef 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -16,6 +16,13 @@ #include "tile_cmd.h" +/** Contextx for tile accesses */ +enum TileContext { + TCX_NORMAL, ///< Nothing special. + TCX_UPPER_HALFTILE, ///< Querying information about the upper part of a tile with halftile foundation. + TCX_ON_BRIDGE, ///< Querying information about stuff on the bridge (via some bridgehead). +}; + /** * Maps an entity id stored on the map to a GRF file. * Entities are objects used ingame (houses, industries, industry tiles) for @@ -101,7 +108,7 @@ extern HouseOverrideManager _house_mngr; extern IndustryOverrideManager _industry_mngr; extern IndustryTileOverrideManager _industile_mngr; -uint32 GetTerrainType(TileIndex tile, bool upper_halftile = false); +uint32 GetTerrainType(TileIndex tile, TileContext context = TCX_NORMAL); TileIndex GetNearbyTile(byte parameter, TileIndex tile); uint32 GetNearbyTileInformation(TileIndex tile); diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 9aa6e2b544..7f35982caa 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -45,7 +45,7 @@ static uint32 RailTypeGetVariable(const ResolverObject *object, byte variable, b } switch (variable) { - case 0x40: return GetTerrainType(tile, object->u.routes.upper_halftile); + case 0x40: return GetTerrainType(tile, object->u.routes.context); case 0x41: return 0; case 0x42: return IsLevelCrossingTile(tile) && IsCrossingBarred(tile); } @@ -63,7 +63,7 @@ static const SpriteGroup *RailTypeResolveReal(const ResolverObject *object, cons return NULL; } -static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, bool upper_halftile) +static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, TileContext context) { res->GetRandomBits = &RailTypeGetRandomBits; res->GetTriggers = &RailTypeGetTriggers; @@ -72,7 +72,7 @@ static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, bool res->ResolveReal = &RailTypeResolveReal; res->u.routes.tile = tile; - res->u.routes.upper_halftile = upper_halftile; + res->u.routes.context = context; res->callback = CBID_NO_CALLBACK; res->callback_param1 = 0; @@ -83,7 +83,7 @@ static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, bool res->count = 0; } -SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, bool upper_halftile) +SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context) { assert(rtsg < RTSG_END); @@ -92,7 +92,7 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp const SpriteGroup *group; ResolverObject object; - NewRailTypeResolver(&object, tile, upper_halftile); + NewRailTypeResolver(&object, tile, context); group = SpriteGroup::Resolve(rti->group[rtsg], &object); if (group == NULL || group->GetNumResults() == 0) return 0; diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index 40f772c034..622c14e5a9 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -4,8 +4,9 @@ #define NEWGRF_RAILTYPE_H #include "rail.h" +#include "newgrf_commons.h" -SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, bool upper_halftile = false); +SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL); uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 5f63ed6ad2..61c03ff350 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -22,6 +22,7 @@ #include "newgrf_callbacks.h" #include "newgrf_generic.h" #include "newgrf_storage.h" +#include "newgrf_commons.h" /** * Gets the value of a so-called newgrf "register". @@ -341,8 +342,8 @@ struct ResolverObject { uint8 station_size; } generic; struct { - TileIndex tile; - bool upper_halftile; ///< Are we resolving sprites for the upper halftile? + TileIndex tile; ///< Tracktile. For track on a bridge this is the southern bridgehead. + TileContext context; ///< Are we resolving sprites for the upper halftile, or on a bridge? } routes; } u; diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 4a8fda85a9..2aeb3c5026 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1756,7 +1756,7 @@ static void DrawTrackDetails(const TileInfo *ti, const RailtypeInfo *rti) { /* Base sprite for track fences. * Note: Halftile slopes only have fences on the upper part. */ - SpriteID base_image = GetCustomRailSprite(rti, ti->tile, RTSG_FENCES, IsHalftileSlope(ti->tileh)); + SpriteID base_image = GetCustomRailSprite(rti, ti->tile, RTSG_FENCES, IsHalftileSlope(ti->tileh) ? TCX_UPPER_HALFTILE : TCX_NORMAL); if (base_image == 0) base_image = SPR_TRACK_FENCE_FLAT_X; switch (GetRailGroundType(ti->tile)) { @@ -1915,8 +1915,8 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailtypeIn if (IsValidCorner(halftile_corner)) { DrawFoundation(ti, HalftileFoundation(halftile_corner)); - overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY, true); - ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND, true); + overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY, TCX_UPPER_HALFTILE); + ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND, TCX_UPPER_HALFTILE); /* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */ Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner)); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 0968de9e1f..98db3bc9f5 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1221,7 +1221,7 @@ void DrawBridgeMiddle(const TileInfo *ti) } else if (transport_type == TRANSPORT_RAIL) { const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth)); if (rti->UsesOverlay()) { - SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE); + SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE); if (surface != 0) { AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES)); } @@ -1364,12 +1364,17 @@ static void TileLoop_TunnelBridge(TileIndex tile) { bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile); switch (_settings_game.game_creation.landscape) { - case LT_ARCTIC: - if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) { + case LT_ARCTIC: { + /* As long as we do not have a snow density, we want to use the density + * from the entry endge. For tunnels this is the lowest point for bridges the highest point. + * (Independent of foundations) */ + uint z = IsBridge(tile) ? GetTileMaxZ(tile) : GetTileZ(tile); + if (snow_or_desert != (z > GetSnowLine())) { SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert); MarkTileDirtyByTile(tile); } break; + } case LT_TROPIC: if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {