# HG changeset patch # User Jonathan G Rennison # Date 2023-06-03 21:04:24 # Node ID ea724a82d4342a99e61740653db14d432ba57ccb # Parent 151ee53cd970b5ba8a9bd0302734c97e0add10bd Fix #10831: Level crossing parts left barred after crossing tile removal (#10874) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -651,7 +651,7 @@ CommandCost CmdRemoveSingleRail(DoComman 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 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -504,7 +504,7 @@ static CommandCost RemoveRoad(TileIndex } 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 --- a/src/road_func.h +++ b/src/road_func.h @@ -155,6 +155,7 @@ RoadTypes AddDateIntroducedRoadTypes(Roa 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 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1790,7 +1790,8 @@ void UpdateLevelCrossing(TileIndex tile, /** * 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) { @@ -1805,6 +1806,44 @@ void MarkDirtyAdjacentLevelCrossingTiles } /** + * 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 < Map::Size() && 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 < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) { + MarkTileDirtyByTile(t); + } + } else { + /* Unbar the crossing tiles in this direction as necessary */ + for (TileIndex t = tile + diff; t < Map::Size() && 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 * @pre tile is a rail-road crossing