diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 7ee5813606..c7f578892c 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -650,7 +650,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlag flags, TileIndex tile, Track track cost.AddCost(RailClearCost(GetRailType(tile))); if (flags & DC_EXEC) { - MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile)); + UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(tile, GetCrossingRoadAxis(tile)); if (HasReservedTracks(tile, trackbit)) { v = GetTrainForReservation(tile, track); diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 94d2d6b5ba..2bd62bdda2 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -503,7 +503,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec } if (flags & DC_EXEC) { - MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile)); + UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(tile, GetCrossingRoadAxis(tile)); /* A full diagonal road tile has two road bits. */ UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2); diff --git a/src/road_func.h b/src/road_func.h index 2db2f24fe3..25843037f2 100644 --- a/src/road_func.h +++ b/src/road_func.h @@ -155,6 +155,7 @@ RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date); void UpdateLevelCrossing(TileIndex tile, bool sound = true, bool force_bar = false); void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis); +void UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(TileIndex tile, Axis road_axis); void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count); struct TileInfo; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5b7ea459a1..bb17b0a89d 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1778,7 +1778,8 @@ void UpdateLevelCrossing(TileIndex tile, bool sound, bool force_bar) /** * Find adjacent level crossing tiles in this multi-track crossing and mark them dirty. - * @param The tile which causes the update. + * @param tile The tile which causes the update. + * @param road_axis The road axis. */ void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis) { @@ -1792,6 +1793,44 @@ void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis) } } +/** + * Update adjacent level crossing tiles in this multi-track crossing, due to removal of a level crossing tile. + * @param tile The crossing tile which has been or is about to be removed, and which caused the update. + * @param road_axis The road axis. + */ +void UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(TileIndex tile, Axis road_axis) +{ + const DiagDirection dir1 = AxisToDiagDir(road_axis); + const DiagDirection dir2 = ReverseDiagDir(dir1); + for (DiagDirection dir : { dir1, dir2 }) { + const TileIndexDiff diff = TileOffsByDiagDir(dir); + bool occupied = false; + for (TileIndex t = tile + diff; t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis; t += diff) { + occupied |= CheckLevelCrossing(t); + } + if (occupied) { + /* Mark the immediately adjacent tile dirty */ + const TileIndex t = tile + diff; + if (t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) { + MarkTileDirtyByTile(t); + } + } else { + /* Unbar the crossing tiles in this direction as necessary */ + for (TileIndex t = tile + diff; t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis; t += diff) { + if (IsCrossingBarred(t)) { + /* The crossing tile is barred, unbar it and continue to check the next tile */ + SetCrossingBarred(t, false); + MarkTileDirtyByTile(t); + } else { + /* The crossing tile is already unbarred, mark the tile dirty and stop checking */ + MarkTileDirtyByTile(t); + break; + } + } + } + } +} + /** * Bars crossing and plays ding-ding sound if not barred already * @param tile tile with crossing