diff --git a/docs/landscape.html b/docs/landscape.html
index 2e3d82313b..bd6cc4b5c8 100644
--- a/docs/landscape.html
+++ b/docs/landscape.html
@@ -907,6 +907,22 @@
m2: index into the array of stations
m3 bits 7..4: persistent random data for railway stations/waypoints and airports)
m3 bits 7..4: owner of tram tracks (road stop)
+ m3 bits 3..2: ground type (road waypoints)
+
+
+ 0 |
+ on bare land |
+
+
+ 1 |
+ on grass |
+
+
+ 2 |
+ paved |
+
+
+
m3 bits 1..0: bits to disallow vehicles to go a specific direction (drive-through road stop)
@@ -1037,6 +1053,7 @@
m7 bits 4..0: owner of road (road stops)
m7: animation frame (railway stations/waypoints, airports)
+ m8 bit 15: Snow or desert present (road waypoints)
m8 bits 14..12: Road cached one way state
m8 bits 11..6: Tramtype
m8 bits 5..0: track type for railway stations/waypoints
diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html
index e7aae85d5f..c70a18eef0 100644
--- a/docs/landscape_grid.html
+++ b/docs/landscape_grid.html
@@ -185,10 +185,10 @@ the array so you can quickly see what is used and what is not.
OOOO OOOO OOOO OOOO |
- 5 |
+ 5 |
rail station |
- OXX XXXXX |
- XXXX XXXX XXXX XXXX |
+ OXX XXXXX |
+ XXXX XXXX XXXX XXXX |
XXXX OOOO |
XXXX XXXX |
XXXX XXXX |
@@ -203,12 +203,17 @@ the array so you can quickly see what is used and what is not.
road stop |
XXXX OOPP |
- OOXX XXXX |
- OOOO OXXX |
- OPXXX OOO |
- OOOX XXXX |
+ OOXX XXXX |
+ OOOO OXXX |
+ OPXXX OOO |
+ OOOX XXXX |
OPPP XXXX XXOO OOOO |
+
+ road waypoint |
+ XXXX PP PP |
+ P PPP XXXX XXOO OOOO |
+
airport |
XXXX OOOO |
diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp
index d7b7bdffa6..d767717b64 100644
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -1865,13 +1865,13 @@ static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
* By default, roads are always drawn as unpaved if they are on desert or
* above the snow line, but NewGRFs can override this for desert.
*
- * @param tile The tile the road is on
+ * @param snow_or_desert Is snowy or desert tile
* @param roadside What sort of road this is
* @return True if snow/desert road sprites should be used.
*/
-static bool DrawRoadAsSnowDesert(TileIndex tile, Roadside roadside)
+static bool DrawRoadAsSnowDesert(bool snow_or_desert, Roadside roadside)
{
- return (IsOnSnow(tile) &&
+ return (snow_or_desert &&
!(_settings_game.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) &&
roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS));
}
@@ -2064,11 +2064,11 @@ void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *roa
* @param offset Road sprite offset
* @param[out] pal Palette to draw.
*/
-static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, PaletteID *pal)
+static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const RoadTypeInfo *rti, uint offset, PaletteID *pal, bool snow_or_desert)
{
/* Draw bare ground sprite if no road or road uses overlay system. */
if (rti == nullptr || rti->UsesOverlay()) {
- if (DrawRoadAsSnowDesert(ti->tile, roadside)) {
+ if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
}
@@ -2082,7 +2082,7 @@ static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const
}
/* Draw original road base sprite */
SpriteID image = SPR_ROAD_Y + offset;
- if (DrawRoadAsSnowDesert(ti->tile, roadside)) {
+ if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
image += 19;
} else {
switch (roadside) {
@@ -2100,11 +2100,9 @@ static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const
* Draw ground sprite and road pieces
* @param ti TileInfo
*/
-void DrawRoadBits(TileInfo *ti)
+void DrawRoadBits(TileInfo *ti, RoadBits road, RoadBits tram, Roadside roadside, bool snow_or_desert)
{
- const bool is_bridge = IsTileType(ti->tile, MP_TUNNELBRIDGE);
- RoadBits road = is_bridge ? GetCustomBridgeHeadRoadBits(ti->tile, RTT_ROAD) : GetRoadBits(ti->tile, RTT_ROAD);
- RoadBits tram = is_bridge ? GetCustomBridgeHeadRoadBits(ti->tile, RTT_TRAM) : GetRoadBits(ti->tile, RTT_TRAM);
+ const bool is_road_tile = IsTileType(ti->tile, MP_ROAD);
RoadType road_rt = GetRoadTypeRoad(ti->tile);
RoadType tram_rt = GetRoadTypeTram(ti->tile);
@@ -2112,8 +2110,8 @@ void DrawRoadBits(TileInfo *ti)
const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
if (ti->tileh != SLOPE_FLAT) {
- DrawFoundation(ti, is_bridge ? FOUNDATION_LEVELED : GetRoadFoundation(ti->tileh, road | tram));
- /* DrawFoundation() modifies ti. */
+ DrawFoundation(ti, !is_road_tile ? FOUNDATION_LEVELED : GetRoadFoundation(ti->tileh, road | tram));
+ /* DrawFoundation() is_road_tile ti. */
}
/* Determine sprite offsets */
@@ -2121,23 +2119,21 @@ void DrawRoadBits(TileInfo *ti)
uint tram_offset = GetRoadSpriteOffset(ti->tileh, tram);
/* Draw baseset underlay */
- Roadside roadside = is_bridge ? ROADSIDE_PAVED : GetRoadside(ti->tile);
-
PaletteID pal = PAL_NONE;
- SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, &pal);
+ SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, &pal, snow_or_desert);
DrawGroundSprite(image, pal);
DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset);
/* Draw one way */
- if (!is_bridge && road_rti != nullptr) {
+ if (is_road_tile && road_rti != nullptr) {
DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
if (drd != DRD_NONE) {
DrawGroundSpriteAt(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
}
}
- if (!is_bridge && HasRoadWorks(ti->tile)) {
+ if (is_road_tile && HasRoadWorks(ti->tile)) {
/* Road works */
DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
return;
@@ -2171,6 +2167,16 @@ void DrawRoadBits(TileInfo *ti)
}
}
+void DrawRoadBitsRoad(TileInfo *ti)
+{
+ DrawRoadBits(ti, GetRoadBits(ti->tile, RTT_ROAD), GetRoadBits(ti->tile, RTT_TRAM), GetRoadside(ti->tile), IsOnSnow(ti->tile));
+}
+
+void DrawRoadBitsTunnelBridge(TileInfo *ti)
+{
+ DrawRoadBits(ti, GetCustomBridgeHeadRoadBits(ti->tile, RTT_ROAD), GetCustomBridgeHeadRoadBits(ti->tile, RTT_TRAM), ROADSIDE_PAVED, false);
+}
+
/** Tile callback function for rendering a road tile to the screen */
static void DrawTile_Road(TileInfo *ti, DrawTileProcParams params)
{
@@ -2178,7 +2184,7 @@ static void DrawTile_Road(TileInfo *ti, DrawTileProcParams params)
switch (GetRoadTileType(ti->tile)) {
case ROAD_TILE_NORMAL:
- DrawRoadBits(ti);
+ DrawRoadBitsRoad(ti);
break;
case ROAD_TILE_CROSSING: {
@@ -2200,7 +2206,7 @@ static void DrawTile_Road(TileInfo *ti, DrawTileProcParams params)
SpriteID image = SPR_ROAD_Y + axis;
Roadside roadside = GetRoadside(ti->tile);
- if (DrawRoadAsSnowDesert(ti->tile, roadside)) {
+ if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
image += 19;
} else {
switch (roadside) {
@@ -2216,7 +2222,7 @@ static void DrawTile_Road(TileInfo *ti, DrawTileProcParams params)
if (IsCrossingBarred(ti->tile)) image += 2;
Roadside roadside = GetRoadside(ti->tile);
- if (DrawRoadAsSnowDesert(ti->tile, roadside)) {
+ if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
image += 8;
} else {
switch (roadside) {
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 31fea176da..9da37895ec 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -3360,6 +3360,12 @@ draw_default_foundation:
DrawClearLandTile(ti, 3);
}
}
+ } else if (IsRoadWaypointTile(ti->tile)) {
+ RoadBits bits = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? ROAD_X : ROAD_Y;
+ extern void DrawRoadBits(TileInfo *ti, RoadBits road, RoadBits tram, Roadside roadside, bool snow_or_desert);
+ DrawRoadBits(ti, GetRoadTypeRoad(ti->tile) != INVALID_ROADTYPE ? bits : ROAD_NONE,
+ GetRoadTypeTram(ti->tile) != INVALID_ROADTYPE ? bits : ROAD_NONE,
+ GetRoadWaypointRoadside(ti->tile), IsRoadWaypointOnSnowOrDesert(ti->tile));
} else {
if (layout != nullptr) {
/* Sprite layout which needs preprocessing */
@@ -3684,6 +3690,40 @@ static void TileLoop_Station(TileIndex tile)
TileLoop_Water(tile);
break;
+ case STATION_ROADWAYPOINT: {
+ switch (_settings_game.game_creation.landscape) {
+ case LT_ARCTIC:
+ if (IsRoadWaypointOnSnowOrDesert(tile) != (GetTileZ(tile) > GetSnowLine())) {
+ ToggleRoadWaypointOnSnowOrDesert(tile);
+ MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
+ }
+ break;
+
+ case LT_TROPIC:
+ if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsRoadWaypointOnSnowOrDesert(tile)) {
+ ToggleRoadWaypointOnSnowOrDesert(tile);
+ MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
+ }
+ break;
+ }
+
+ HouseZonesBits grp = HZB_TOWN_EDGE;
+ const Town *t = ClosestTownFromTile(tile, UINT_MAX);
+ if (t != nullptr) {
+ grp = GetTownRadiusGroup(t, tile);
+ }
+
+ /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
+ Roadside new_rs = grp > HZB_TOWN_EDGE ? ROADSIDE_PAVED : ROADSIDE_GRASS;
+ Roadside cur_rs = GetRoadWaypointRoadside(tile);
+
+ if (new_rs != cur_rs) {
+ SetRoadWaypointRoadside(tile, cur_rs == ROADSIDE_BARREN ? new_rs : ROADSIDE_BARREN);
+ MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
+ }
+ break;
+ }
+
default: break;
}
}
diff --git a/src/station_map.h b/src/station_map.h
index 98ef3236e3..2b8978c3c8 100644
--- a/src/station_map.h
+++ b/src/station_map.h
@@ -301,6 +301,49 @@ static inline void SetDriveThroughStopDisallowedRoadDirections(TileIndex t, Disa
SB(_m[t].m3, 0, 2, drd);
}
+/**
+ * Get the decorations of a road waypoint.
+ * @param tile The tile to query.
+ * @return The road decoration of the tile.
+ */
+static inline Roadside GetRoadWaypointRoadside(TileIndex tile)
+{
+ assert_tile(IsRoadWaypointTile(tile), tile);
+ return (Roadside)GB(_m[tile].m3, 2, 2);
+}
+
+/**
+ * Set the decorations of a road waypoint.
+ * @param tile The tile to change.
+ * @param s The new road decoration of the tile.
+ */
+static inline void SetRoadWaypointRoadside(TileIndex tile, Roadside s)
+{
+ assert_tile(IsRoadWaypointTile(tile), tile);
+ SB(_m[tile].m3, 2, 2, s);
+}
+
+/**
+ * Check if a road waypoint tile has snow/desert.
+ * @param t The tile to query.
+ * @return True if the tile has snow/desert.
+ */
+static inline bool IsRoadWaypointOnSnowOrDesert(TileIndex t)
+{
+ assert_tile(IsRoadWaypointTile(t), t);
+ return HasBit(_me[t].m8, 15);
+}
+
+/**
+ * Toggle the snow/desert state of a road waypoint tile.
+ * @param t The tile to change.
+ */
+static inline void ToggleRoadWaypointOnSnowOrDesert(TileIndex t)
+{
+ assert_tile(IsRoadWaypointTile(t), t);
+ ToggleBit(_me[t].m8, 15);
+}
+
/**
* Get the station graphics of this airport tile
* @param t the tile to query
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
index 59502a7d63..e5ecd4003a 100644
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -63,7 +63,7 @@ TileIndex _build_tunnel_endtile; ///< The end of a tunnel; as hidden return from
static const int BRIDGE_Z_START = 3;
extern void DrawTrackBits(TileInfo *ti, TrackBits track);
-extern void DrawRoadBits(TileInfo *ti);
+extern void DrawRoadBitsTunnelBridge(TileInfo *ti);
extern const RoadBits _invalid_tileh_slopes_road[2][15];
extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
@@ -2124,7 +2124,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti, DrawTileProcParams params)
DrawBridgeMiddle(ti);
} else { // IsBridge(ti->tile)
if (transport_type == TRANSPORT_ROAD && IsRoadCustomBridgeHead(ti->tile)) {
- DrawRoadBits(ti);
+ DrawRoadBitsTunnelBridge(ti);
DrawBridgeMiddle(ti);
return;
}