From 4ccbb114404701a0f5d78e3dc8f006db4c28941f Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Nov 2021 01:42:18 +0000 Subject: [PATCH] Only show level crossing overlay sprites on outsides of multi-track crossings When using both adjacent crossings and safer crossings --- src/rail_cmd.cpp | 2 ++ src/road_cmd.cpp | 45 +++++++++++++++++++++++++++++++++++++++- src/road_func.h | 1 + src/table/road_land.h | 48 +++++++++++++++++++++++++++++++++++++++++++ src/train_cmd.cpp | 14 +++++++++++++ 5 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index cc3d50e389..966e9460ec 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -817,6 +817,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (flags & DC_EXEC) { MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile)); UpdateLevelCrossing(tile, false); + MarkDirtyAdjacentLevelCrossingTilesOnAddRemove(tile, GetCrossingRoadAxis(tile)); Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR; DirtyCompanyInfrastructureWindows(_current_company); if (num_new_road_pieces > 0 && Company::IsValidID(road_owner)) { @@ -934,6 +935,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, } if (flags & DC_EXEC) { + MarkDirtyAdjacentLevelCrossingTilesOnAddRemove(tile, GetCrossingRoadAxis(tile)); if (v != nullptr) FreeTrainTrackReservation(v); owner = GetTileOwner(tile); diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 86cee206ce..3a48e7e512 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -808,6 +808,8 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec } if (flags & DC_EXEC) { + MarkDirtyAdjacentLevelCrossingTilesOnAddRemove(tile, GetCrossingRoadAxis(tile)); + /* A full diagonal road tile has two road bits. */ UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2); @@ -1111,6 +1113,7 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, p2); SetCrossingReservation(tile, reserved); UpdateLevelCrossing(tile, false); + MarkDirtyAdjacentLevelCrossingTilesOnAddRemove(tile, GetCrossingRoadAxis(tile)); if (RoadLayoutChangeNotificationEnabled(true)) NotifyRoadLayoutChangedIfTileNonLeaf(tile, rtt, GetCrossingRoadBits(tile)); if (rtt == RTT_ROAD) { UpdateRoadCachedOneWayStatesAroundTile(tile); @@ -2235,7 +2238,47 @@ static void DrawTile_Road(TileInfo *ti, DrawTileProcParams params) SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis; DrawGroundSprite(rail, pal); - DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE); + + if (_settings_game.vehicle.safer_crossings && _settings_game.vehicle.adjacent_crossings) { + const Axis axis = GetCrossingRoadAxis(ti->tile); + const DiagDirection dir1 = AxisToDiagDir(axis); + const DiagDirection dir2 = ReverseDiagDir(dir1); + uint adjacent_diagdirs = 0; + for (DiagDirection dir : { dir1, dir2 }) { + const TileIndex t = TileAddByDiagDir(ti->tile, dir); + if (t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == axis) { + SetBit(adjacent_diagdirs, dir); + } + } + + switch (adjacent_diagdirs) { + case 0: + DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE); + break; + + case (1 << DIAGDIR_NE): + DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE); + break; + + case (1 << DIAGDIR_SE): + DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE); + break; + + case (1 << DIAGDIR_SW): + DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE); + break; + + case (1 << DIAGDIR_NW): + DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE); + break; + + default: + /* Show no sprites */ + break; + } + } else { + DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE); + } } else if (draw_pbs || tram_rti != nullptr || road_rti->UsesOverlay()) { /* Add another rail overlay, unless there is only the base road sprite. */ PaletteID pal = draw_pbs ? PALETTE_CRASH : PAL_NONE; diff --git a/src/road_func.h b/src/road_func.h index 0d099fde18..46e2d8ae5a 100644 --- a/src/road_func.h +++ b/src/road_func.h @@ -155,6 +155,7 @@ RoadTypes GetRoadTypes(bool introduces); RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date); void UpdateLevelCrossing(TileIndex tile, bool sound = true, bool force_close = false); +void MarkDirtyAdjacentLevelCrossingTilesOnAddRemove(TileIndex tile, Axis road_axis); bool IsCrossingOccupiedByRoadVehicle(TileIndex t); void UpdateRoadCachedOneWayStatesAroundTile(TileIndex tile); diff --git a/src/table/road_land.h b/src/table/road_land.h index df38f935d5..cd3848bcf3 100644 --- a/src/table/road_land.h +++ b/src/table/road_land.h @@ -53,6 +53,54 @@ static const DrawTileSprites _crossing_layout = { {0, PAL_NONE}, _crossing_layout_ALL }; +static const DrawTileSeqStruct _crossing_layout_SW_ALL[] = { + //TILE_SEQ_LINE(2, PAL_NONE, 0, 0, 3, 3) + //TILE_SEQ_LINE(4, PAL_NONE, 0, 13, 3, 3) + TILE_SEQ_LINE(6, PAL_NONE, 13, 0, 3, 3) + TILE_SEQ_LINE(8, PAL_NONE, 13, 13, 3, 3) + TILE_SEQ_END() +}; + +static const DrawTileSprites _crossing_layout_SW = { + {0, PAL_NONE}, _crossing_layout_SW_ALL +}; + +static const DrawTileSeqStruct _crossing_layout_NW_ALL[] = { + TILE_SEQ_LINE(2, PAL_NONE, 0, 0, 3, 3) + //TILE_SEQ_LINE(4, PAL_NONE, 0, 13, 3, 3) + TILE_SEQ_LINE(6, PAL_NONE, 13, 0, 3, 3) + //TILE_SEQ_LINE(8, PAL_NONE, 13, 13, 3, 3) + TILE_SEQ_END() +}; + +static const DrawTileSprites _crossing_layout_NW = { + {0, PAL_NONE}, _crossing_layout_NW_ALL +}; + +static const DrawTileSeqStruct _crossing_layout_NE_ALL[] = { + TILE_SEQ_LINE(2, PAL_NONE, 0, 0, 3, 3) + TILE_SEQ_LINE(4, PAL_NONE, 0, 13, 3, 3) + //TILE_SEQ_LINE(6, PAL_NONE, 13, 0, 3, 3) + //TILE_SEQ_LINE(8, PAL_NONE, 13, 13, 3, 3) + TILE_SEQ_END() +}; + +static const DrawTileSprites _crossing_layout_NE = { + {0, PAL_NONE}, _crossing_layout_NE_ALL +}; + +static const DrawTileSeqStruct _crossing_layout_SE_ALL[] = { + //TILE_SEQ_LINE(2, PAL_NONE, 0, 0, 3, 3) + TILE_SEQ_LINE(4, PAL_NONE, 0, 13, 3, 3) + //TILE_SEQ_LINE(6, PAL_NONE, 13, 0, 3, 3) + TILE_SEQ_LINE(8, PAL_NONE, 13, 13, 3, 3) + TILE_SEQ_END() +}; + +static const DrawTileSprites _crossing_layout_SE = { + {0, PAL_NONE}, _crossing_layout_SE_ALL +}; + #undef TILE_SEQ_LINE #undef TILE_SEQ_END diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index acc9db8b5e..53263e04e9 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2610,6 +2610,20 @@ void UpdateLevelCrossing(TileIndex tile, bool sound, bool force_close) } } +void MarkDirtyAdjacentLevelCrossingTilesOnAddRemove(TileIndex tile, Axis road_axis) +{ + if (!(_settings_game.vehicle.safer_crossings && _settings_game.vehicle.adjacent_crossings)) return; + + const DiagDirection dir1 = AxisToDiagDir(road_axis); + const DiagDirection dir2 = ReverseDiagDir(dir1); + for (DiagDirection dir : { dir1, dir2 }) { + const TileIndex t = TileAddByDiagDir(tile, dir); + if (t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) { + MarkTileDirtyByTile(t, VMDF_NOT_MAP_MODE); + } + } +} + /** * Check if the level crossing is occupied by road vehicle(s). * @param t The tile to query.