Index: src/newgrf_railtype.cpp =================================================================== --- src/newgrf_railtype.cpp (revision 27298) +++ src/newgrf_railtype.cpp (working copy) @@ -102,7 +102,7 @@ * @param content Where are we drawing the tile? * @return The sprite to draw. */ -SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context) +SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *SpritesCount) { assert(rtsg < RTSG_END); @@ -112,6 +112,10 @@ const SpriteGroup *group = object.Resolve(); if (group == NULL || group->GetNumResults() == 0) return 0; + if (SpritesCount and group) { + *SpritesCount = group->GetNumResults(); + } + return group->GetResult(); } Index: src/newgrf_railtype.h =================================================================== --- src/newgrf_railtype.h (revision 27298) +++ src/newgrf_railtype.h (working copy) @@ -44,7 +44,7 @@ /* virtual */ const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const; }; -SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL); +SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL, uint *SpritesCount = NULL); SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui = false); uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile); Index: src/rail.h =================================================================== --- src/rail.h (revision 27298) +++ src/rail.h (working copy) @@ -26,10 +26,12 @@ enum RailTypeFlags { RTF_CATENARY = 0, ///< Bit number for drawing a catenary. RTF_NO_LEVEL_CROSSING = 1, ///< Bit number for disallowing level crossings. + RTF_ADVANCED_FENCES = 2, ///< Bit number for enabling fences in snow. RTFB_NONE = 0, ///< All flags cleared. RTFB_CATENARY = 1 << RTF_CATENARY, ///< Value for drawing a catenary. RTFB_NO_LEVEL_CROSSING = 1 << RTF_NO_LEVEL_CROSSING, ///< Value for disallowing level crossings. + RTFB_ADVANCED_FENCES = 1 << RTF_ADVANCED_FENCES, ///< Value for enabling advanced fences. }; DECLARE_ENUM_AS_BIT_SET(RailTypeFlags) @@ -327,6 +329,11 @@ return HasBit(GetRailTypeInfo(rt)->flags, RTF_NO_LEVEL_CROSSING); } +static inline bool RailFencesAdvanced(RailType rt) +{ + return HasBit(GetRailTypeInfo(rt)->flags, RTF_ADVANCED_FENCES); +} + /** * Returns the cost of building the specified railtype. * @param railtype The railtype being built. Index: src/rail_cmd.cpp =================================================================== --- src/rail_cmd.cpp (revision 27298) +++ src/rail_cmd.cpp (working copy) @@ -37,6 +37,7 @@ #include "table/strings.h" #include "table/railtypes.h" #include "table/track_land.h" +#include "table/sprites.h" #include "safeguards.h" @@ -1881,18 +1882,18 @@ ti->x, ti->y + 1, 16, 1, 4, ti->z); } -static void DrawTrackFence_SE(const TileInfo *ti, SpriteID base_image) +static void DrawTrackFence_SE(const TileInfo *ti, SpriteID base_image, uint SpriteCount) { RailFenceOffset rfo = RFO_FLAT_X; if (ti->tileh & SLOPE_SE) rfo = (ti->tileh & SLOPE_S) ? RFO_SLOPE_SW : RFO_SLOPE_NE; - AddSortableSpriteToDraw(base_image + rfo, _drawtile_track_palette, + AddSortableSpriteToDraw(base_image + rfo + (SpriteCount > 8 ? 8 : 0), _drawtile_track_palette, ti->x, ti->y + TILE_SIZE - 1, 16, 1, 4, ti->z); } -static void DrawTrackFence_NW_SE(const TileInfo *ti, SpriteID base_image) +static void DrawTrackFence_NW_SE(const TileInfo *ti, SpriteID base_image, uint SpriteCount) { DrawTrackFence_NW(ti, base_image); - DrawTrackFence_SE(ti, base_image); + DrawTrackFence_SE(ti, base_image, SpriteCount); } static void DrawTrackFence_NE(const TileInfo *ti, SpriteID base_image) @@ -1903,18 +1904,18 @@ ti->x + 1, ti->y, 1, 16, 4, ti->z); } -static void DrawTrackFence_SW(const TileInfo *ti, SpriteID base_image) +static void DrawTrackFence_SW(const TileInfo *ti, SpriteID base_image, uint SpriteCount) { RailFenceOffset rfo = RFO_FLAT_Y; if (ti->tileh & SLOPE_SW) rfo = (ti->tileh & SLOPE_S) ? RFO_SLOPE_SE : RFO_SLOPE_NW; - AddSortableSpriteToDraw(base_image + rfo, _drawtile_track_palette, + AddSortableSpriteToDraw(base_image + rfo + (SpriteCount > 8 ? 8 : 0), _drawtile_track_palette, ti->x + TILE_SIZE - 1, ti->y, 1, 16, 4, ti->z); } -static void DrawTrackFence_NE_SW(const TileInfo *ti, SpriteID base_image) +static void DrawTrackFence_NE_SW(const TileInfo *ti, SpriteID base_image, uint SpriteCount) { DrawTrackFence_NE(ti, base_image); - DrawTrackFence_SW(ti, base_image); + DrawTrackFence_SW(ti, base_image, SpriteCount); } /** @@ -1930,10 +1931,10 @@ /** * Draw fence at western side of track. */ -static void DrawTrackFence_NS_2(const TileInfo *ti, SpriteID base_image) +static void DrawTrackFence_NS_2(const TileInfo *ti, SpriteID base_image, uint SpriteCount) { int z = ti->z + GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_E); - AddSortableSpriteToDraw(base_image + RFO_FLAT_VERT, _drawtile_track_palette, + AddSortableSpriteToDraw(base_image + RFO_FLAT_VERT + (SpriteCount > 8 ? 8 : 0), _drawtile_track_palette, ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); } @@ -1950,32 +1951,33 @@ /** * Draw fence at northern side of track. */ -static void DrawTrackFence_WE_2(const TileInfo *ti, SpriteID base_image) +static void DrawTrackFence_WE_2(const TileInfo *ti, SpriteID base_image, uint SpriteCount) { int z = ti->z + GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_S); - AddSortableSpriteToDraw(base_image + RFO_FLAT_HORZ, _drawtile_track_palette, + AddSortableSpriteToDraw(base_image + RFO_FLAT_HORZ + (SpriteCount > 8 ? 8 : 0), _drawtile_track_palette, ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); } static void DrawTrackDetails(const TileInfo *ti, const RailtypeInfo *rti) { + uint FenceSpriteCount = 0; /* 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) ? TCX_UPPER_HALFTILE : TCX_NORMAL); + SpriteID base_image = GetCustomRailSprite(rti, ti->tile, RTSG_FENCES, IsHalftileSlope(ti->tileh) ? TCX_UPPER_HALFTILE : TCX_NORMAL, &FenceSpriteCount); if (base_image == 0) base_image = SPR_TRACK_FENCE_FLAT_X; switch (GetRailGroundType(ti->tile)) { - case RAIL_GROUND_FENCE_NW: DrawTrackFence_NW(ti, base_image); break; - case RAIL_GROUND_FENCE_SE: DrawTrackFence_SE(ti, base_image); break; - case RAIL_GROUND_FENCE_SENW: DrawTrackFence_NW_SE(ti, base_image); break; - case RAIL_GROUND_FENCE_NE: DrawTrackFence_NE(ti, base_image); break; - case RAIL_GROUND_FENCE_SW: DrawTrackFence_SW(ti, base_image); break; - case RAIL_GROUND_FENCE_NESW: DrawTrackFence_NE_SW(ti, base_image); break; - case RAIL_GROUND_FENCE_VERT1: DrawTrackFence_NS_1(ti, base_image); break; - case RAIL_GROUND_FENCE_VERT2: DrawTrackFence_NS_2(ti, base_image); break; - case RAIL_GROUND_FENCE_HORIZ1: DrawTrackFence_WE_1(ti, base_image); break; - case RAIL_GROUND_FENCE_HORIZ2: DrawTrackFence_WE_2(ti, base_image); break; + case RAIL_GROUND_FENCE_NW: DrawTrackFence_NW(ti, base_image); break; + case RAIL_GROUND_FENCE_SE: DrawTrackFence_SE(ti, base_image, FenceSpriteCount); break; + case RAIL_GROUND_FENCE_SENW: DrawTrackFence_NW_SE(ti, base_image, FenceSpriteCount); break; + case RAIL_GROUND_FENCE_NE: DrawTrackFence_NE(ti, base_image); break; + case RAIL_GROUND_FENCE_SW: DrawTrackFence_SW(ti, base_image, FenceSpriteCount); break; + case RAIL_GROUND_FENCE_NESW: DrawTrackFence_NE_SW(ti, base_image, FenceSpriteCount); break; + case RAIL_GROUND_FENCE_VERT1: DrawTrackFence_NS_1(ti, base_image); break; + case RAIL_GROUND_FENCE_VERT2: DrawTrackFence_NS_2(ti, base_image, FenceSpriteCount); break; + case RAIL_GROUND_FENCE_HORIZ1: DrawTrackFence_WE_1(ti, base_image); break; + case RAIL_GROUND_FENCE_HORIZ2: DrawTrackFence_WE_2(ti, base_image, FenceSpriteCount); break; case RAIL_GROUND_WATER: { Corner track_corner; if (IsHalftileSlope(ti->tileh)) { @@ -1986,14 +1988,56 @@ track_corner = OppositeCorner(GetHighestSlopeCorner(ComplementSlope(ti->tileh))); } switch (track_corner) { - case CORNER_W: DrawTrackFence_NS_1(ti, base_image); break; - case CORNER_S: DrawTrackFence_WE_2(ti, base_image); break; - case CORNER_E: DrawTrackFence_NS_2(ti, base_image); break; - case CORNER_N: DrawTrackFence_WE_1(ti, base_image); break; + case CORNER_W: DrawTrackFence_NS_1(ti, base_image); break; + case CORNER_S: DrawTrackFence_WE_2(ti, base_image, FenceSpriteCount); break; + case CORNER_E: DrawTrackFence_NS_2(ti, base_image, FenceSpriteCount); break; + case CORNER_N: DrawTrackFence_WE_1(ti, base_image); break; default: NOT_REACHED(); } break; } + case RAIL_GROUND_ICE_DESERT: { + if (!RailFencesAdvanced(GetRailType(ti->tile))) + break; + if (IsPlainRail(ti->tile)) { // wait until bottom is green + /* determine direction of fence */ + TrackBits rail = GetTrackBits(ti->tile); + + Owner owner = GetTileOwner(ti->tile); + byte fences = 0; + + for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) { + static const TrackBits dir_to_trackbits[DIAGDIR_END] = {TRACK_BIT_3WAY_NE, TRACK_BIT_3WAY_SE, TRACK_BIT_3WAY_SW, TRACK_BIT_3WAY_NW}; + + /* Track bit on this edge => no fence. */ + if ((rail & dir_to_trackbits[d]) != TRACK_BIT_NONE) continue; + + TileIndex tile2 = ti->tile + TileOffsByDiagDir(d); + + /* Show fences if it's a house, industry, object, road, tunnelbridge or not owned by us. */ + if (!IsValidTile(tile2) || IsTileType(tile2, MP_HOUSE) || IsTileType(tile2, MP_INDUSTRY) || + IsTileType(tile2, MP_ROAD) || (IsTileType(tile2, MP_OBJECT) && !IsObjectType(tile2, OBJECT_OWNED_LAND)) || IsTileType(tile2, MP_TUNNELBRIDGE) || !IsTileOwner(tile2, owner)) { + fences |= 1 << d; + } + } + + switch (fences) { + case 0: break; + case (1 << DIAGDIR_NE): DrawTrackFence_NE(ti, base_image); break; + case (1 << DIAGDIR_SE): DrawTrackFence_SE(ti, base_image, FenceSpriteCount); break; + case (1 << DIAGDIR_SW): DrawTrackFence_SW(ti, base_image, FenceSpriteCount); break; + case (1 << DIAGDIR_NW): DrawTrackFence_NW(ti, base_image); break; + case (1 << DIAGDIR_NE) | (1 << DIAGDIR_SW): DrawTrackFence_NE_SW(ti, base_image, FenceSpriteCount); break; + case (1 << DIAGDIR_SE) | (1 << DIAGDIR_NW): DrawTrackFence_NW_SE(ti, base_image, FenceSpriteCount); break; + case (1 << DIAGDIR_NE) | (1 << DIAGDIR_SE): DrawTrackFence_NS_1(ti, base_image); break; + case (1 << DIAGDIR_NE) | (1 << DIAGDIR_NW): DrawTrackFence_WE_2(ti, base_image, FenceSpriteCount); break; + case (1 << DIAGDIR_SE) | (1 << DIAGDIR_SW): DrawTrackFence_WE_1(ti, base_image); break; + case (1 << DIAGDIR_SW) | (1 << DIAGDIR_NW): DrawTrackFence_NS_2(ti, base_image, FenceSpriteCount); break; + default: NOT_REACHED(); + } + } + break; + } default: break; } }