From a25ac7a1610e5ce7fcee29ef8d1016d42f917fb6 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Feb 2016 20:12:10 +0000 Subject: [PATCH 1/9] Enable signals on bridges/tunnels to work with PBS. --- src/pathfinder/follow_track.hpp | 4 +-- src/pathfinder/npf/npf.cpp | 4 +++ src/pathfinder/yapf/yapf_costrail.hpp | 4 +++ src/pbs.cpp | 10 +++++++- src/rail_map.h | 12 +++++++-- src/train_cmd.cpp | 37 +++++++++++++++++++++++---- src/tunnelbridge_cmd.cpp | 3 ++- 7 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index 76f33407fb..9f19b029c0 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -358,7 +358,7 @@ protected: if (IsTunnel(m_new_tile)) { if (!m_is_tunnel) { DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(m_new_tile); - if (tunnel_enterdir != m_exitdir || IsTunnelBridgeExit(m_new_tile)) { + if (tunnel_enterdir != m_exitdir) { m_err = EC_NO_WAY; return false; } @@ -366,7 +366,7 @@ protected: } else { // IsBridge(m_new_tile) if (!m_is_bridge) { DiagDirection ramp_enderdir = GetTunnelBridgeDirection(m_new_tile); - if (ramp_enderdir != m_exitdir || IsTunnelBridgeExit(m_new_tile)) { + if (ramp_enderdir != m_exitdir) { m_err = EC_NO_WAY; return false; } diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index bb705e5f4a..496a9fdc53 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -936,6 +936,10 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) break; } } + if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(dst_tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(dst_tile)) == dst_trackdir) { + /* Entering a signalled bridge/tunnel from the wrong side, equivalent to encountering a one-way signal from the wrong side */ + break; + } { /* We've found ourselves a neighbour :-) */ AyStarNode *neighbour = &aystar->neighbours[i]; diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 64cf963800..15da32d9f7 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -244,6 +244,10 @@ public: } } } + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(tile)) == trackdir) { + /* Entering a signalled bridge/tunnel from the wrong side, equivalent to encountering a one-way signal from the wrong side */ + n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; + } return cost; } diff --git a/src/pbs.cpp b/src/pbs.cpp index 133293909f..2ca4422cc8 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -246,6 +246,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra if (IsRailDepotTile(tile)) break; /* Non-pbs signal? Reservation can't continue. */ if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) break; + if (IsTileType(tile, MP_TUNNELBRIDGE) && HasWormholeSignals(tile)) break; } return PBSTileInfo(tile, trackdir, false); @@ -314,7 +315,7 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res) if (ftoti.best != NULL) *train_on_res = ftoti.best->First(); } } - if (*train_on_res == NULL && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) { + if (*train_on_res == NULL && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE) && !HasWormholeSignals(ftoti.res.tile)) { /* The target tile is a bridge/tunnel, also check the other end tile. */ FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum); if (ftoti.best != NULL) *train_on_res = ftoti.best->First(); @@ -389,6 +390,12 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true; } + if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) { + if (IsTunnelBridgeEntrance(tile)) { + return true; + } + } + /* Check next tile. For performance reasons, we check for 90 degree turns ourself. */ CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes); @@ -437,6 +444,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo /* Not reserved and depot or not a pbs signal -> free. */ if (IsRailDepotTile(tile)) return true; if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) return true; + if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && IsTunnelBridgeEntrance(tile)) return true; /* Check the next tile, if it's a PBS signal, it has to be free as well. */ CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes); diff --git a/src/rail_map.h b/src/rail_map.h index 2431a79202..d2befc4686 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -18,6 +18,7 @@ #include "track_func.h" #include "tile_map.h" #include "signal_type.h" +#include "tunnelbridge_map.h" /** Different types of Rail-related tiles */ @@ -475,8 +476,15 @@ static inline bool HasPbsSignalOnTrackdir(TileIndex tile, Trackdir td) */ static inline bool HasOnewaySignalBlockingTrackdir(TileIndex tile, Trackdir td) { - return IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && - !HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td)); + if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && + !HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td))) { + return true; + } + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && + DiagDirToDiagTrackdir(GetTunnelBridgeDirection(tile)) == td) { + return true; + } + return false; } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 345bff3ff7..78b19e8e3a 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2260,7 +2260,13 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ TileIndex end = GetOtherTunnelBridgeEnd(tile); bool free = TunnelBridgeIsFree(tile, end, v).Succeeded(); - if (free) { + if (HasWormholeSignals(tile)) { + SetTunnelBridgeReservation(tile, false); + HandleLastTunnelBridgeSignals(tile, end, dir, free); + if (_settings_client.gui.show_track_reservation) { + MarkTileDirtyByTile(tile); + } + } else if (free) { /* Free the reservation only if no other train is on the tiles. */ SetTunnelBridgeReservation(tile, false); SetTunnelBridgeReservation(end, false); @@ -2274,7 +2280,12 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ } } } - if (HasWormholeSignals(tile)) HandleLastTunnelBridgeSignals(tile, end, dir, free); + } else if (GetTunnelBridgeDirection(tile) == dir && HasWormholeSignals(tile)) { + /* cancelling reservation of entry ramp, due to reverse */ + SetTunnelBridgeReservation(tile, false); + if (_settings_client.gui.show_track_reservation) { + MarkTileDirtyByTile(tile); + } } } else if (IsRailStationTile(tile)) { TileIndex new_tile = TileAddByDiagDir(tile, dir); @@ -2955,6 +2966,12 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir) if (!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true; } } + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { + if (UpdateSignalsOnSegment(tile, dir, GetTileOwner(tile)) == SIGSEG_PBS) { + return true; + } + } + return false; } @@ -3192,6 +3209,15 @@ static bool IsToCloseBehindTrain(Vehicle *v, TileIndex tile, bool check_endtile) return false; } +static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile) +{ + TileIndex veh_orig = t->tile; + t->tile = tile; + bool ok = TryPathReserve(t); + t->tile = veh_orig; + return ok; +} + /** Simulate signals in tunnel - bridge. */ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile) { @@ -3204,7 +3230,7 @@ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile) return true; } SigSegState seg_state = _settings_game.pf.reserve_paths ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner); - if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !TryPathReserve(t))) { + if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !CheckTrainStayInWormHolePathReserve(t, tile))) { t->vehstatus |= VS_TRAIN_SLOWING; t->cur_speed = 0; return true; @@ -3493,7 +3519,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) } else { /* Handle signal simulation on tunnel/bridge. */ TileIndex old_tile = TileVirtXY(v->x_pos, v->y_pos); - if (old_tile != gp.new_tile && HasWormholeSignals(v->tile) && (v->IsFrontEngine() || v->Next() == NULL)){ + if (old_tile != gp.new_tile && HasWormholeSignals(v->tile) && (v->IsFrontEngine() || v->Next() == NULL)) { if (old_tile == v->tile) { if (v->IsFrontEngine() && v->force_proceed == 0 && IsTunnelBridgeExit(v->tile)) goto invalid_rail; /* Entered wormhole set counters. */ @@ -3532,6 +3558,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) v->x_pos = gp.x; v->y_pos = gp.y; UpdateSignalsOnSegment(old_tile, INVALID_DIAGDIR, v->owner); + SetTunnelBridgeReservation(old_tile, false); } } if (distance == 0) v->load_unload_ticks++; @@ -3553,7 +3580,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { /* Perform look-ahead on tunnel exit. */ if (v->IsFrontEngine()) { - TryReserveRailTrack(gp.new_tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(gp.new_tile))); + if (!HasWormholeSignals(gp.new_tile)) TryReserveRailTrack(gp.new_tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(gp.new_tile))); CheckNextTrainTile(v); } /* Prevent v->UpdateInclination() being called with wrong parameters. diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 4dec3f80e0..22350db906 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1598,7 +1598,8 @@ void DrawBridgeMiddle(const TileInfo *ti) } } - if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) { + if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth) + && !HasWormholeSignals(rampnorth)) { if (rti->UsesOverlay()) { SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY); AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES)); From 2b4dbf582ae20dccacb3641eb235ad3ed64be586 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Feb 2016 21:37:45 +0000 Subject: [PATCH 2/9] Show tunnel/bridge exit signal facing correct way with correct colour. --- src/signal.cpp | 16 ++++++++++++++++ src/tunnelbridge_cmd.cpp | 22 ++++++++++++++++++---- src/tunnelbridge_map.h | 10 ++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/signal.cpp b/src/signal.cpp index e3c3da0e91..6893bb4ef5 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -390,11 +390,17 @@ static SigFlags ExploreSegment(Owner owner) if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) flags |= SF_TRAIN; if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) flags |= SF_TRAIN; } + if (IsTunnelBridgeExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) { + return flags | SF_FULL; + } enterdir = dir; exitdir = ReverseDiagDir(dir); tile += TileOffsByDiagDir(exitdir); // just skip to next tile } else { // NOT incoming from the wormhole! if (ReverseDiagDir(enterdir) != dir) continue; + if (IsTunnelBridgeExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) { + return flags | SF_FULL; + } if (!(flags & SF_TRAIN)) { if (HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) flags |= SF_TRAIN; if (!(flags & SF_TRAIN) && IsTunnelBridgeExit(tile)) { @@ -443,6 +449,16 @@ static void UpdateSignalsAroundSegment(SigFlags flags) Trackdir trackdir; while (_tbuset.Get(&tile, &trackdir)) { + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile)) { + bool old_state = IsTunnelBridgeExitGreen(tile); + bool new_state = !(flags & SF_TRAIN); + if (old_state != new_state) { + SetTunnelBridgeExitGreen(tile, new_state); + MarkTileDirtyByTile(tile); + } + continue; + } + assert(HasSignalOnTrackdir(tile, trackdir)); SignalType sig = GetSignalType(tile, TrackdirToTrack(trackdir)); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 22350db906..0149b6aaba 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1164,20 +1164,34 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) case DIAGDIR_NW: position = 3; break; } - uint x = TileX(ti->tile) * TILE_SIZE + SignalPositions[side][position].x; - uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side][position].y; + bool is_green; + bool show_exit; + if (IsTunnelBridgeExit(ti->tile) && IsBridge(ti->tile)) { + is_green = IsTunnelBridgeExitGreen(ti->tile); + show_exit = true; + position ^= 1; + } else { + is_green = IsTunnelBridgeWithSignGreen(ti->tile); + show_exit = false; + } + + uint x = TileX(ti->tile) * TILE_SIZE + SignalPositions[side != show_exit][position ^ show_exit].x; + uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side != show_exit][position ^ show_exit].y; uint z = ti->z; + if (ti->tileh == SLOPE_FLAT && side == show_exit && dir == DIAGDIR_SE) z += 2; + if (ti->tileh == SLOPE_FLAT && side != show_exit && dir == DIAGDIR_SW) z += 2; + if (ti->tileh != SLOPE_FLAT && IsBridge(ti->tile)) z += 8; // sloped bridge head SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); SpriteID sprite; if (variant == SIG_ELECTRIC) { /* Normal electric signals are picked from original sprites. */ - sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + IsTunnelBridgeWithSignGreen(ti->tile)); + sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + is_green); } else { /* All other signals are picked from add on sprites. */ - sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + IsTunnelBridgeWithSignGreen(ti->tile)); + sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + is_green); } AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR); diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 57f338b8be..43aa4f29cd 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -213,6 +213,16 @@ static inline bool IsTunnelBridgeExit(TileIndex t) return !HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6); } +static inline bool IsTunnelBridgeExitGreen(TileIndex t) +{ + assert(IsTunnelBridgeExit(t)); + return HasBit(_me[t].m6, 0); +} +static inline void SetTunnelBridgeExitGreen(TileIndex t, bool green) +{ + assert(IsTunnelBridgeExit(t)); + SB(_me[t].m6, 0, 1, green ? 1 : 0); +} #endif /* TUNNELBRIDGE_MAP_H */ From 38619687652e2078ceacd18ce2f1f9467affd8d4 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Feb 2016 22:13:30 +0000 Subject: [PATCH 3/9] Enable setting semaphore/electric type of signals on bridges/tunnels. --- src/rail_cmd.cpp | 38 +++++++++++++++++++++++++++++--------- src/tunnelbridge_cmd.cpp | 4 ++-- src/tunnelbridge_map.h | 12 ++++++++++++ 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index e71d732d00..edaa0d56c6 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1056,21 +1056,39 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, if (IsTileType(tile, MP_TUNNELBRIDGE)) { TileIndex tile_exit = GetOtherTunnelBridgeEnd(tile); cost = CommandCost(); + bool flip_variant = false; if (!HasWormholeSignals(tile)) { // toggle signal zero costs. + if (convert_signal) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS); if (p2 != 12) cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS] * ((GetTunnelBridgeLength(tile, tile_exit) + 4) >> 2)); // minimal 1 + } else { + if (HasBit(p1, 17)) return CommandCost(); + if (ctrl_pressed && !convert_signal) return CommandCost(); + if ((p2 != 0 && (sigvar == SIG_SEMAPHORE) != IsTunnelBridgeSemaphore(tile)) || + (convert_signal && (ctrl_pressed || (sigvar == SIG_SEMAPHORE) != IsTunnelBridgeSemaphore(tile)))) { + flip_variant = true; + cost = CommandCost(EXPENSES_CONSTRUCTION, (_price[PR_BUILD_SIGNALS] + _price[PR_CLEAR_SIGNALS]) * + ((GetTunnelBridgeLength(tile, tile_exit) + 4) >> 2)); // minimal 1 + } } if (flags & DC_EXEC) { if (p2 == 0 && HasWormholeSignals(tile)) { // Toggle signal if already signals present. - if (IsTunnelBridgeEntrance(tile)) { - ClrBitTunnelBridgeSignal(tile); - ClrBitTunnelBridgeExit(tile_exit); - SetBitTunnelBridgeExit(tile); - SetBitTunnelBridgeSignal(tile_exit); + if (convert_signal) { + if (flip_variant) { + SetTunnelBridgeSemaphore(tile, !IsTunnelBridgeSemaphore(tile)); + SetTunnelBridgeSemaphore(tile_exit, !IsTunnelBridgeSemaphore(tile_exit)); + } } else { - ClrBitTunnelBridgeSignal(tile_exit); - ClrBitTunnelBridgeExit(tile); - SetBitTunnelBridgeExit(tile_exit); - SetBitTunnelBridgeSignal(tile); + if (IsTunnelBridgeEntrance(tile)) { + ClrBitTunnelBridgeSignal(tile); + ClrBitTunnelBridgeExit(tile_exit); + SetBitTunnelBridgeExit(tile); + SetBitTunnelBridgeSignal(tile_exit); + } else { + ClrBitTunnelBridgeSignal(tile_exit); + ClrBitTunnelBridgeExit(tile); + SetBitTunnelBridgeExit(tile_exit); + SetBitTunnelBridgeSignal(tile); + } } } else { /* Create one direction tunnel/bridge if required. */ @@ -1089,6 +1107,8 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, SetBitTunnelBridgeExit(tile); } } + SetTunnelBridgeSemaphore(tile, sigvar == SIG_SEMAPHORE); + SetTunnelBridgeSemaphore(tile_exit, sigvar == SIG_SEMAPHORE); } MarkBridgeOrTunnelDirty(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile)); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 0149b6aaba..1700a28757 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1183,7 +1183,7 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) if (ti->tileh == SLOPE_FLAT && side != show_exit && dir == DIAGDIR_SW) z += 2; if (ti->tileh != SLOPE_FLAT && IsBridge(ti->tile)) z += 8; // sloped bridge head - SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); + SignalVariant variant = IsTunnelBridgeSemaphore(ti->tile) ? SIG_SEMAPHORE : SIG_ELECTRIC; SpriteID sprite; if (variant == SIG_ELECTRIC) { @@ -1233,7 +1233,7 @@ static void DrawBrigeSignalOnMiddelPart(const TileInfo *ti, TileIndex bridge_sta uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side][position].y; z += 5; - SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); + SignalVariant variant = IsTunnelBridgeSemaphore(bridge_start_tile) ? SIG_SEMAPHORE : SIG_ELECTRIC; SpriteID sprite; diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 43aa4f29cd..ccaface2fc 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -225,4 +225,16 @@ static inline void SetTunnelBridgeExitGreen(TileIndex t, bool green) SB(_me[t].m6, 0, 1, green ? 1 : 0); } +static inline bool IsTunnelBridgeSemaphore(TileIndex t) +{ + assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + return HasBit(_me[t].m6, 1); +} + +static inline void SetTunnelBridgeSemaphore(TileIndex t, bool is_semaphore) +{ + assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + SB(_me[t].m6, 1, 1, is_semaphore ? 1 : 0); +} + #endif /* TUNNELBRIDGE_MAP_H */ From 1a2b5e51723f571e05db13c876b2c216f8674437 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Feb 2016 22:24:14 +0000 Subject: [PATCH 4/9] Also draw signals for tunnel exits. --- src/tunnelbridge_cmd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 1700a28757..e17ee62a19 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1166,7 +1166,7 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) bool is_green; bool show_exit; - if (IsTunnelBridgeExit(ti->tile) && IsBridge(ti->tile)) { + if (IsTunnelBridgeExit(ti->tile)) { is_green = IsTunnelBridgeExitGreen(ti->tile); show_exit = true; position ^= 1; @@ -1366,7 +1366,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x + BB_data[4], ti->y + BB_data[5], BB_data[6], BB_data[7], TILE_HEIGHT, ti->z); /* Draw signals for tunnel. */ - if (IsTunnelBridgeEntrance(ti->tile)) DrawTunnelBridgeRampSignal(ti); + if (HasWormholeSignals(ti->tile)) DrawTunnelBridgeRampSignal(ti); DrawBridgeMiddle(ti); } else { // IsBridge(ti->tile) From 69c2cf352e93311491c073917e88341ecc1bf622 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Feb 2016 23:18:54 +0000 Subject: [PATCH 5/9] Fix drag-convert not updating bridge/tunnel direction correctly. --- src/rail_cmd.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index edaa0d56c6..33c97cebf4 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1100,9 +1100,13 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, /* If signal only on one side build accoringly one-way tunnel/bridge. */ if ((p2 == 8 && (tbdir == DIAGDIR_NE || tbdir == DIAGDIR_SE)) || (p2 == 4 && (tbdir == DIAGDIR_SW || tbdir == DIAGDIR_NW))) { + ClrBitTunnelBridgeExit(tile); + ClrBitTunnelBridgeSignal(tile_exit); SetBitTunnelBridgeSignal(tile); SetBitTunnelBridgeExit(tile_exit); } else { + ClrBitTunnelBridgeSignal(tile); + ClrBitTunnelBridgeExit(tile_exit); SetBitTunnelBridgeSignal(tile_exit); SetBitTunnelBridgeExit(tile); } From 35b93a42ace803cc0ce8463e1f540b8a33b38734 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 20 Feb 2016 23:26:16 +0000 Subject: [PATCH 6/9] Enable bridge/tunnel exit signals to be one-way PBS. Add signal conversion support. --- src/pbs.cpp | 6 +++++- src/rail_cmd.cpp | 15 +++++++++++++-- src/signal.cpp | 9 +++++++-- src/train_cmd.cpp | 20 +++++++++++++------- src/tunnelbridge_cmd.cpp | 11 +++++++---- src/tunnelbridge_map.h | 12 ++++++++++++ 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/pbs.cpp b/src/pbs.cpp index 2ca4422cc8..f0511a73b3 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -125,6 +125,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && !GetTunnelBridgeReservationTrackBits(tile)) { SetTunnelBridgeReservation(tile, true); + if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, true); return true; } break; @@ -177,7 +178,10 @@ void UnreserveRailTrack(TileIndex tile, Track t) break; case MP_TUNNELBRIDGE: - if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) SetTunnelBridgeReservation(tile, false); + if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) { + SetTunnelBridgeReservation(tile, false); + if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, false); + } break; default: diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 33c97cebf4..bfdfcbfea8 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1057,12 +1057,12 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, TileIndex tile_exit = GetOtherTunnelBridgeEnd(tile); cost = CommandCost(); bool flip_variant = false; + bool is_pbs = (sigtype == SIGTYPE_PBS) || (sigtype == SIGTYPE_PBS_ONEWAY); if (!HasWormholeSignals(tile)) { // toggle signal zero costs. if (convert_signal) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS); if (p2 != 12) cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS] * ((GetTunnelBridgeLength(tile, tile_exit) + 4) >> 2)); // minimal 1 } else { if (HasBit(p1, 17)) return CommandCost(); - if (ctrl_pressed && !convert_signal) return CommandCost(); if ((p2 != 0 && (sigvar == SIG_SEMAPHORE) != IsTunnelBridgeSemaphore(tile)) || (convert_signal && (ctrl_pressed || (sigvar == SIG_SEMAPHORE) != IsTunnelBridgeSemaphore(tile)))) { flip_variant = true; @@ -1075,8 +1075,15 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, if (convert_signal) { if (flip_variant) { SetTunnelBridgeSemaphore(tile, !IsTunnelBridgeSemaphore(tile)); - SetTunnelBridgeSemaphore(tile_exit, !IsTunnelBridgeSemaphore(tile_exit)); + SetTunnelBridgeSemaphore(tile_exit, IsTunnelBridgeSemaphore(tile)); } + if (!ctrl_pressed) { + SetTunnelBridgePBS(tile, is_pbs); + SetTunnelBridgePBS(tile_exit, is_pbs); + } + } else if (ctrl_pressed) { + SetTunnelBridgePBS(tile, !IsTunnelBridgePBS(tile)); + SetTunnelBridgePBS(tile_exit, IsTunnelBridgePBS(tile)); } else { if (IsTunnelBridgeEntrance(tile)) { ClrBitTunnelBridgeSignal(tile); @@ -1113,7 +1120,11 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, } SetTunnelBridgeSemaphore(tile, sigvar == SIG_SEMAPHORE); SetTunnelBridgeSemaphore(tile_exit, sigvar == SIG_SEMAPHORE); + SetTunnelBridgePBS(tile, is_pbs); + SetTunnelBridgePBS(tile_exit, is_pbs); } + if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile) && !HasTunnelBridgeReservation(tile)) SetTunnelBridgeExitGreen(tile, false); + if (IsTunnelBridgeExit(tile_exit) && IsTunnelBridgePBS(tile_exit) && !HasTunnelBridgeReservation(tile_exit)) SetTunnelBridgeExitGreen(tile_exit, false); MarkBridgeOrTunnelDirty(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile)); AddSideToSignalBuffer(tile_exit, INVALID_DIAGDIR, GetTileOwner(tile)); diff --git a/src/signal.cpp b/src/signal.cpp index 6893bb4ef5..4639def78f 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -398,8 +398,12 @@ static SigFlags ExploreSegment(Owner owner) tile += TileOffsByDiagDir(exitdir); // just skip to next tile } else { // NOT incoming from the wormhole! if (ReverseDiagDir(enterdir) != dir) continue; - if (IsTunnelBridgeExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) { - return flags | SF_FULL; + if (IsTunnelBridgeExit(tile)) { + if (IsTunnelBridgePBS(tile)) { + flags |= SF_PBS; + } else if (!_tbuset.Add(tile, INVALID_TRACKDIR)) { + return flags | SF_FULL; + } } if (!(flags & SF_TRAIN)) { if (HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) flags |= SF_TRAIN; @@ -450,6 +454,7 @@ static void UpdateSignalsAroundSegment(SigFlags flags) while (_tbuset.Get(&tile, &trackdir)) { if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile)) { + if (IsTunnelBridgePBS(tile)) continue; bool old_state = IsTunnelBridgeExitGreen(tile); bool new_state = !(flags & SF_TRAIN); if (old_state != new_state) { diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 78b19e8e3a..af4ec021f0 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2244,6 +2244,12 @@ static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDir } } +static void UnreserveBridgeTunnelTile(TileIndex tile) +{ + SetTunnelBridgeReservation(tile, false); + if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, false); +} + /** * Clear the reservation of \a tile that was just left by a wagon on \a track_dir. * @param v %Train owning the reservation. @@ -2261,15 +2267,15 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ bool free = TunnelBridgeIsFree(tile, end, v).Succeeded(); if (HasWormholeSignals(tile)) { - SetTunnelBridgeReservation(tile, false); + UnreserveBridgeTunnelTile(tile); HandleLastTunnelBridgeSignals(tile, end, dir, free); if (_settings_client.gui.show_track_reservation) { MarkTileDirtyByTile(tile); } } else if (free) { /* Free the reservation only if no other train is on the tiles. */ - SetTunnelBridgeReservation(tile, false); - SetTunnelBridgeReservation(end, false); + UnreserveBridgeTunnelTile(tile); + UnreserveBridgeTunnelTile(end); if (_settings_client.gui.show_track_reservation) { if (IsBridge(tile)) { @@ -2282,7 +2288,7 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ } } else if (GetTunnelBridgeDirection(tile) == dir && HasWormholeSignals(tile)) { /* cancelling reservation of entry ramp, due to reverse */ - SetTunnelBridgeReservation(tile, false); + UnreserveBridgeTunnelTile(tile); if (_settings_client.gui.show_track_reservation) { MarkTileDirtyByTile(tile); } @@ -3012,7 +3018,7 @@ uint Train::Crash(bool flooded) if (IsTileType(v->tile, MP_TUNNELBRIDGE)) { /* ClearPathReservation will not free the wormhole exit * if the train has just entered the wormhole. */ - SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(v->tile), false); + UnreserveBridgeTunnelTile(GetOtherTunnelBridgeEnd(v->tile)); } } @@ -3229,7 +3235,7 @@ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile) ToggleBit(t->flags, VRF_REVERSING); return true; } - SigSegState seg_state = _settings_game.pf.reserve_paths ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner); + SigSegState seg_state = (_settings_game.pf.reserve_paths || IsTunnelBridgePBS(tile)) ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner); if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !CheckTrainStayInWormHolePathReserve(t, tile))) { t->vehstatus |= VS_TRAIN_SLOWING; t->cur_speed = 0; @@ -3558,7 +3564,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) v->x_pos = gp.x; v->y_pos = gp.y; UpdateSignalsOnSegment(old_tile, INVALID_DIAGDIR, v->owner); - SetTunnelBridgeReservation(old_tile, false); + UnreserveBridgeTunnelTile(old_tile); } } if (distance == 0) v->load_unload_ticks++; diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index e17ee62a19..64bd366b15 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1164,12 +1164,15 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) case DIAGDIR_NW: position = 3; break; } + SignalType type = SIGTYPE_NORMAL; + bool is_green; bool show_exit; if (IsTunnelBridgeExit(ti->tile)) { is_green = IsTunnelBridgeExitGreen(ti->tile); show_exit = true; position ^= 1; + if (IsTunnelBridgePBS(ti->tile)) type = SIGTYPE_PBS_ONEWAY; } else { is_green = IsTunnelBridgeWithSignGreen(ti->tile); show_exit = false; @@ -1186,19 +1189,19 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) SignalVariant variant = IsTunnelBridgeSemaphore(ti->tile) ? SIG_SEMAPHORE : SIG_ELECTRIC; SpriteID sprite; - if (variant == SIG_ELECTRIC) { + if (variant == SIG_ELECTRIC && type == SIGTYPE_NORMAL) { /* Normal electric signals are picked from original sprites. */ sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + is_green); } else { /* All other signals are picked from add on sprites. */ - sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + is_green); + sprite = SPR_SIGNALS_BASE + ((type - 1) * 16 + variant * 64 + (position << 1) + is_green) + (type > SIGTYPE_LAST_NOPBS ? 64 : 0); } AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR); } /* Draws a signal on tunnel / bridge entrance tile. */ -static void DrawBrigeSignalOnMiddelPart(const TileInfo *ti, TileIndex bridge_start_tile, uint z) +static void DrawBrigeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_start_tile, uint z) { uint bridge_signal_position = 0; @@ -1628,7 +1631,7 @@ void DrawBridgeMiddle(const TileInfo *ti) DrawCatenaryOnBridge(ti); } if (HasWormholeSignals(rampsouth)) { - IsTunnelBridgeExit(rampsouth) ? DrawBrigeSignalOnMiddelPart(ti, rampnorth, z): DrawBrigeSignalOnMiddelPart(ti, rampsouth, z); + IsTunnelBridgeExit(rampsouth) ? DrawBrigeSignalOnMiddlePart(ti, rampnorth, z): DrawBrigeSignalOnMiddlePart(ti, rampsouth, z); } } diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index ccaface2fc..2196f794f1 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -237,4 +237,16 @@ static inline void SetTunnelBridgeSemaphore(TileIndex t, bool is_semaphore) SB(_me[t].m6, 1, 1, is_semaphore ? 1 : 0); } +static inline bool IsTunnelBridgePBS(TileIndex t) +{ + assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + return HasBit(_me[t].m6, 6); +} + +static inline void SetTunnelBridgePBS(TileIndex t, bool is_pbs) +{ + assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + SB(_me[t].m6, 6, 1, is_pbs ? 1 : 0); +} + #endif /* TUNNELBRIDGE_MAP_H */ From 7e4898ad42f6a0d117c70f20fa81dfd94a579c8f Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 21 Feb 2016 02:00:21 +0000 Subject: [PATCH 7/9] Fix PBS reservation from bridge/tunnel exit when next tile not a junction. --- src/train_cmd.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index af4ec021f0..1276d827d8 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3219,6 +3219,14 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile) { TileIndex veh_orig = t->tile; t->tile = tile; + CFollowTrackRail ft(GetTileOwner(tile), GetRailTypeInfo(t->railtype)->compatible_railtypes); + if (ft.Follow(t->tile, DiagDirToDiagTrackdir(ReverseDiagDir(GetTunnelBridgeDirection(tile))))) { + TrackdirBits reserved = ft.m_new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.m_new_tile)); + if (reserved == TRACKDIR_BIT_NONE) { + /* next tile is not reserved, so reserve the exit tile */ + SetTunnelBridgeReservation(tile, true); + } + } bool ok = TryPathReserve(t); t->tile = veh_orig; return ok; From 891fd08e9d491704e9a535b19f99d61809726df8 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 21 Feb 2016 12:09:50 +0000 Subject: [PATCH 8/9] Handle case where a non-PBS tun/bridge exit is followed by a PBS signal. Prevent the entrance being reserved if an attempt is made to reverse on the exit tile. --- src/train_cmd.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 1276d827d8..a96e52597b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2767,6 +2767,12 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay) } } + if (IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(v->tile) && + DiagDirToDiagTrackBits(GetTunnelBridgeDirection(v->tile)) == v->track) { + // prevent any attempt to reserve the wrong way onto a tunnel/bridge exit + return false; + } + Vehicle *other_train = NULL; PBSTileInfo origin = FollowTrainReservation(v, &other_train); /* The path we are driving on is already blocked by some other train. @@ -3220,7 +3226,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile) TileIndex veh_orig = t->tile; t->tile = tile; CFollowTrackRail ft(GetTileOwner(tile), GetRailTypeInfo(t->railtype)->compatible_railtypes); - if (ft.Follow(t->tile, DiagDirToDiagTrackdir(ReverseDiagDir(GetTunnelBridgeDirection(tile))))) { + if (ft.Follow(tile, DiagDirToDiagTrackdir(ReverseDiagDir(GetTunnelBridgeDirection(tile))))) { TrackdirBits reserved = ft.m_new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.m_new_tile)); if (reserved == TRACKDIR_BIT_NONE) { /* next tile is not reserved, so reserve the exit tile */ @@ -3244,6 +3250,18 @@ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile) return true; } SigSegState seg_state = (_settings_game.pf.reserve_paths || IsTunnelBridgePBS(tile)) ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner); + if (seg_state != SIGSEG_PBS) { + CFollowTrackRail ft(GetTileOwner(tile), GetRailTypeInfo(t->railtype)->compatible_railtypes); + if (ft.Follow(tile, DiagDirToDiagTrackdir(ReverseDiagDir(GetTunnelBridgeDirection(tile))))) { + if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) { + Trackdir td = FindFirstTrackdir(ft.m_new_td_bits); + if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) { + /* immediately after the exit, there is a PBS signal, switch to PBS mode */ + seg_state = SIGSEG_PBS; + } + } + } + } if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !CheckTrainStayInWormHolePathReserve(t, tile))) { t->vehstatus |= VS_TRAIN_SLOWING; t->cur_speed = 0; @@ -3594,7 +3612,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { /* Perform look-ahead on tunnel exit. */ if (v->IsFrontEngine()) { - if (!HasWormholeSignals(gp.new_tile)) TryReserveRailTrack(gp.new_tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(gp.new_tile))); + TryReserveRailTrack(gp.new_tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(gp.new_tile))); CheckNextTrainTile(v); } /* Prevent v->UpdateInclination() being called with wrong parameters. From 83f6463a6fbaad72a0662fead0b98f474d183a0f Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 21 Feb 2016 03:23:25 +0000 Subject: [PATCH 9/9] Bump version, set semaphore/pbs/exit sig state on upgrade. --- src/saveload/afterload.cpp | 11 +++++++++++ src/saveload/extended_ver_sl.cpp | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 9690481154..ec5a207644 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2968,6 +2968,17 @@ bool AfterLoadGame() #endif } + if (SlXvIsFeaturePresent(XSLFI_SIG_TUNNEL_BRIDGE, 1, 1)) { + /* set the semaphore bit to match what it would have been in v1 */ + /* clear the PBS bit, update the end signal state */ + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && HasWormholeSignals(t)) { + SetTunnelBridgeSemaphore(t, _cur_year < _settings_client.gui.semaphore_build_before); + SetTunnelBridgePBS(t, false); + UpdateSignalsOnSegment(t, INVALID_DIAGDIR, GetTileOwner(t)); + } + } + } /* Station acceptance is some kind of cache */ if (IsSavegameVersionBefore(127)) { diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index ef5dca9bce..b7fc0fc859 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,7 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 1, 1, "signal_tunnel_bridge", NULL, NULL, NULL }, + { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 2, 2, "signal_tunnel_bridge", NULL, NULL, NULL }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker };