Index: src/rail.h =================================================================== --- src/rail.h (revision 27261) +++ 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) @@ -89,14 +91,41 @@ * the sprites in the original data files. */ enum RailFenceOffset { - RFO_FLAT_X, - RFO_FLAT_Y, - RFO_FLAT_VERT, - RFO_FLAT_HORZ, - RFO_SLOPE_SW, - RFO_SLOPE_SE, - RFO_SLOPE_NE, - RFO_SLOPE_NW, + RFO_ONE_FLAT_X, + RFO_ONE_FLAT_Y, + RFO_ONE_FLAT_VERT, + RFO_ONE_FLAT_HORZ, + RFO_ONE_SLOPE_SW, + RFO_ONE_SLOPE_SE, + RFO_ONE_SLOPE_NE, + RFO_ONE_SLOPE_NW, + + RFO_ONE_SNOW_FLAT_X, + RFO_ONE_SNOW_FLAT_Y, + RFO_ONE_SNOW_FLAT_VERT, + RFO_ONE_SNOW_FLAT_HORZ, + RFO_ONE_SNOW_SLOPE_SW, + RFO_ONE_SNOW_SLOPE_SE, + RFO_ONE_SNOW_SLOPE_NE, + RFO_ONE_SNOW_SLOPE_NW, + + RFO_TWO_FLAT_X, + RFO_TWO_FLAT_Y, + RFO_TWO_FLAT_VERT, + RFO_TWO_FLAT_HORZ, + RFO_TWO_SLOPE_SW, + RFO_TWO_SLOPE_SE, + RFO_TWO_SLOPE_NE, + RFO_TWO_SLOPE_NW, + + RFO_TWO_SNOW_FLAT_X, + RFO_TWO_SNOW_FLAT_Y, + RFO_TWO_SNOW_FLAT_VERT, + RFO_TWO_SNOW_FLAT_HORZ, + RFO_TWO_SNOW_SLOPE_SW, + RFO_TWO_SNOW_SLOPE_SE, + RFO_TWO_SNOW_SLOPE_NE, + RFO_TWO_SNOW_SLOPE_NW, }; /** List of rail type labels. */ @@ -327,6 +356,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 27261) +++ 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" @@ -1875,16 +1876,38 @@ static void DrawTrackFence_NW(const TileInfo *ti, SpriteID base_image) { - RailFenceOffset rfo = RFO_FLAT_X; - if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_SLOPE_SW : RFO_SLOPE_NE; + RailFenceOffset rfo; + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + rfo = RFO_ONE_SNOW_FLAT_X; + if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_ONE_SNOW_SLOPE_SW : RFO_ONE_SNOW_SLOPE_NE; + } else { + rfo = RFO_ONE_FLAT_X; + if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_ONE_SLOPE_SW : RFO_ONE_SLOPE_NE; + } + } else { + rfo = RFO_ONE_FLAT_X; + if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_ONE_SLOPE_SW : RFO_ONE_SLOPE_NE; + } AddSortableSpriteToDraw(base_image + rfo, _drawtile_track_palette, ti->x, ti->y + 1, 16, 1, 4, ti->z); } static void DrawTrackFence_SE(const TileInfo *ti, SpriteID base_image) { - RailFenceOffset rfo = RFO_FLAT_X; - if (ti->tileh & SLOPE_SE) rfo = (ti->tileh & SLOPE_S) ? RFO_SLOPE_SW : RFO_SLOPE_NE; + RailFenceOffset rfo; + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + rfo = RFO_TWO_SNOW_FLAT_X; + if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_TWO_SNOW_SLOPE_SW : RFO_TWO_SNOW_SLOPE_NE; + } else { + rfo = RFO_TWO_FLAT_X; + if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_TWO_SLOPE_SW : RFO_TWO_SLOPE_NE; + } + } else { + rfo = RFO_ONE_FLAT_X; + if (ti->tileh & SLOPE_NW) rfo = (ti->tileh & SLOPE_W) ? RFO_ONE_SLOPE_SW : RFO_ONE_SLOPE_NE; + } AddSortableSpriteToDraw(base_image + rfo, _drawtile_track_palette, ti->x, ti->y + TILE_SIZE - 1, 16, 1, 4, ti->z); } @@ -1897,16 +1920,38 @@ static void DrawTrackFence_NE(const TileInfo *ti, SpriteID base_image) { - RailFenceOffset rfo = RFO_FLAT_Y; - if (ti->tileh & SLOPE_NE) rfo = (ti->tileh & SLOPE_E) ? RFO_SLOPE_SE : RFO_SLOPE_NW; + RailFenceOffset rfo; + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + rfo = RFO_ONE_SNOW_FLAT_Y; + if (ti->tileh & SLOPE_NE) rfo = (ti->tileh & SLOPE_E) ? RFO_ONE_SNOW_SLOPE_SE : RFO_ONE_SNOW_SLOPE_NW; + } else { + rfo = RFO_ONE_FLAT_Y; + if (ti->tileh & SLOPE_NE) rfo = (ti->tileh & SLOPE_E) ? RFO_ONE_SLOPE_SE : RFO_ONE_SLOPE_NW; + } + } else { + rfo = RFO_ONE_FLAT_Y; + if (ti->tileh & SLOPE_NE) rfo = (ti->tileh & SLOPE_E) ? RFO_ONE_SLOPE_SE : RFO_ONE_SLOPE_NW; + } AddSortableSpriteToDraw(base_image + rfo, _drawtile_track_palette, ti->x + 1, ti->y, 1, 16, 4, ti->z); } static void DrawTrackFence_SW(const TileInfo *ti, SpriteID base_image) { - RailFenceOffset rfo = RFO_FLAT_Y; - if (ti->tileh & SLOPE_SW) rfo = (ti->tileh & SLOPE_S) ? RFO_SLOPE_SE : RFO_SLOPE_NW; + RailFenceOffset rfo; + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + rfo = RFO_TWO_SNOW_FLAT_Y; + if (ti->tileh & SLOPE_SW) rfo = (ti->tileh & SLOPE_S) ? RFO_TWO_SNOW_SLOPE_SE : RFO_TWO_SNOW_SLOPE_NW; + } else { + rfo = RFO_TWO_FLAT_Y; + if (ti->tileh & SLOPE_SW) rfo = (ti->tileh & SLOPE_S) ? RFO_TWO_SLOPE_SE : RFO_TWO_SLOPE_NW; + } + } else { + rfo = RFO_ONE_FLAT_Y; + if (ti->tileh & SLOPE_NE) rfo = (ti->tileh & SLOPE_E) ? RFO_ONE_SLOPE_SE : RFO_ONE_SLOPE_NW; + } AddSortableSpriteToDraw(base_image + rfo, _drawtile_track_palette, ti->x + TILE_SIZE - 1, ti->y, 1, 16, 4, ti->z); } @@ -1923,8 +1968,18 @@ static void DrawTrackFence_NS_1(const TileInfo *ti, SpriteID base_image) { int z = ti->z + GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_W); - AddSortableSpriteToDraw(base_image + RFO_FLAT_VERT, _drawtile_track_palette, - ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + AddSortableSpriteToDraw(base_image + RFO_ONE_SNOW_FLAT_VERT, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } else { + AddSortableSpriteToDraw(base_image + RFO_ONE_FLAT_VERT, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } + } else { + AddSortableSpriteToDraw(base_image + RFO_ONE_FLAT_VERT, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } } /** @@ -1933,8 +1988,18 @@ static void DrawTrackFence_NS_2(const TileInfo *ti, SpriteID base_image) { int z = ti->z + GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_E); - AddSortableSpriteToDraw(base_image + RFO_FLAT_VERT, _drawtile_track_palette, - ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + AddSortableSpriteToDraw(base_image + RFO_TWO_SNOW_FLAT_VERT, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } else { + AddSortableSpriteToDraw(base_image + RFO_TWO_FLAT_VERT, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } + } else { + AddSortableSpriteToDraw(base_image + RFO_ONE_FLAT_VERT, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } } /** @@ -1943,8 +2008,18 @@ static void DrawTrackFence_WE_1(const TileInfo *ti, SpriteID base_image) { int z = ti->z + GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_N); - AddSortableSpriteToDraw(base_image + RFO_FLAT_HORZ, _drawtile_track_palette, - ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + AddSortableSpriteToDraw(base_image + RFO_TWO_SNOW_FLAT_HORZ, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z+2); + } else { + AddSortableSpriteToDraw(base_image + RFO_TWO_FLAT_HORZ, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z+2); + } + } else { + AddSortableSpriteToDraw(base_image + RFO_ONE_FLAT_HORZ, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z+2); + } } /** @@ -1953,8 +2028,18 @@ static void DrawTrackFence_WE_2(const TileInfo *ti, SpriteID base_image) { int z = ti->z + GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), CORNER_S); - AddSortableSpriteToDraw(base_image + RFO_FLAT_HORZ, _drawtile_track_palette, - ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + if (RailFencesAdvanced(GetRailType(ti->tile))) { + if (ti->z > GetSnowLine() * TILE_HEIGHT) { + AddSortableSpriteToDraw(base_image + RFO_ONE_SNOW_FLAT_HORZ, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } else { + AddSortableSpriteToDraw(base_image + RFO_ONE_FLAT_HORZ, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } + } else { + AddSortableSpriteToDraw(base_image + RFO_ONE_FLAT_HORZ, _drawtile_track_palette, + ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z); + } } @@ -1994,6 +2079,48 @@ } break; } + case RAIL_GROUND_ICE_DESERT: { + + 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); break; + case (1 << DIAGDIR_SW): DrawTrackFence_SW(ti, base_image); break; + case (1 << DIAGDIR_NW): DrawTrackFence_NW(ti, base_image); break; + case (1 << DIAGDIR_NE) | (1 << DIAGDIR_SW): DrawTrackFence_NE_SW(ti, base_image); break; + case (1 << DIAGDIR_SE) | (1 << DIAGDIR_NW): DrawTrackFence_NW_SE(ti, base_image); 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); 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); break; + default: NOT_REACHED(); + } + } + + break; + } default: break; } }