diff --git a/docs/landscape.html b/docs/landscape.html index d6bb9bca9a..c0c052d89c 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -1447,7 +1447,7 @@
  • m3 bits 7..4: owner of tram
  • m3 bits 3..0: track type for railway
  • m5 bit 4: pbs reservation state for railway
  • -
  • m5 bits 7 clear: tunnel entrance/exit
  • +
  • m5 bit 7 clear: tunnel entrance/exit
  • m5 bit 7 set: bridge ramp
  • +
  • m5 bits 6..5: signal simulation (signals on bridge/tunnels patch) + + + + + + + + + + + + + + + +
    0 no signal simulation
    1 signal simulation entrance (bit 5 set)
    2 signal simulation exit (bit 6 set)
    + If signal simulation entrance or exit: + +
  • m5 bits 3..2: transport type diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index 746141efd5..9fece74141 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -336,8 +336,8 @@ the array so you can quickly see what is used and what is not. - - + + @@ -345,11 +345,11 @@ the array so you can quickly see what is used and what is not. + - - + diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 8ac89749f0..8e4f8832d2 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -693,6 +693,7 @@ + @@ -909,6 +910,7 @@ + @@ -1217,6 +1219,7 @@ + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index ac16729af2..4cf380cb5e 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -1308,6 +1308,9 @@ Core Source Code + + Core Source Code + Core Source Code @@ -1956,6 +1959,9 @@ Save/Load handlers + + Save/Load handlers + Tables @@ -2880,6 +2886,9 @@ Map Accessors + + Map Accessors + Map Accessors diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index cd8606101a..33fb4b8252 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -710,6 +710,7 @@ + @@ -926,6 +927,7 @@ + @@ -1234,6 +1236,7 @@ + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index ac16729af2..4cf380cb5e 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -1308,6 +1308,9 @@ Core Source Code + + Core Source Code + Core Source Code @@ -1956,6 +1959,9 @@ Save/Load handlers + + Save/Load handlers + Tables @@ -2880,6 +2886,9 @@ Map Accessors + + Map Accessors + Map Accessors diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 5242cccb83..5b0bd2f054 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -2050,6 +2050,10 @@ RelativePath=".\..\src\core\bitmath_func.hpp" > + + @@ -2930,6 +2934,10 @@ RelativePath=".\..\src\saveload\tbtr_template_veh_sl.cpp" > + + + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 8b45f8d4e0..44e5db6ac1 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -2047,6 +2047,10 @@ RelativePath=".\..\src\core\bitmath_func.hpp" > + + @@ -2927,6 +2931,10 @@ RelativePath=".\..\src\saveload\tbtr_template_veh_sl.cpp" > + + + + diff --git a/source.list b/source.list index 4eb2265107..291fc4845d 100644 --- a/source.list +++ b/source.list @@ -675,6 +675,7 @@ saveload/extended_ver_sl.h saveload/extended_ver_sl.cpp saveload/tbtr_template_replacement_sl.cpp saveload/tbtr_template_veh_sl.cpp +saveload/bridge_signal_sl.cpp # Tables table/airport_defaults.h @@ -1022,6 +1023,7 @@ newgrf_townname.cpp # Map Accessors bridge_map.cpp bridge_map.h +bridge_signal_map.h clear_map.h industry_map.h object_map.h diff --git a/src/bridge_map.cpp b/src/bridge_map.cpp index d1e0d6024a..7d155fed64 100644 --- a/src/bridge_map.cpp +++ b/src/bridge_map.cpp @@ -12,6 +12,8 @@ #include "stdafx.h" #include "landscape.h" #include "tunnelbridge_map.h" +#include "bridge_signal_map.h" +#include "debug.h" #include "safeguards.h" @@ -78,3 +80,56 @@ int GetBridgeHeight(TileIndex t) /* one height level extra for the ramp */ return h + 1 + ApplyFoundationToSlope(f, &tileh); } + +std::unordered_map _long_bridge_signal_sim_map; + +SignalState GetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal) +{ + const auto it = _long_bridge_signal_sim_map.find(t); + if (it != _long_bridge_signal_sim_map.end()) { + const LongBridgeSignalStorage &lbss = it->second; + uint16 offset = signal - 15; + uint16 slot = offset >> 6; + uint16 bit = offset & 0x3F; + if (slot >= lbss.signal_red_bits.size()) return SIGNAL_STATE_GREEN; + return GB(lbss.signal_red_bits[slot], bit, 1) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; + } else { + return SIGNAL_STATE_GREEN; + } +} + +void SetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal, SignalState state) +{ + LongBridgeSignalStorage &lbss = _long_bridge_signal_sim_map[t]; + uint16 offset = signal - 15; + uint16 slot = offset >> 6; + uint16 bit = offset & 0x3F; + if (slot >= lbss.signal_red_bits.size()) lbss.signal_red_bits.resize(slot + 1); + SB(lbss.signal_red_bits[slot], bit, 1, (uint64) ((state == SIGNAL_STATE_RED) ? 1 : 0)); + _m[t].m2 |= 0x8000; +} + +void SetAllBridgeEntranceSimulatedSignalsGreenExtended(TileIndex t) +{ + auto it = _long_bridge_signal_sim_map.find(t); + if (it != _long_bridge_signal_sim_map.end()) { + LongBridgeSignalStorage &lbss = it->second; + for (auto &it : lbss.signal_red_bits) { + it = 0; + } + _m[t].m2 = 0x8000; + } else { + _m[t].m2 = 0; + } +} + +void ClearBridgeEntranceSimulatedSignalsExtended(TileIndex t) +{ + _long_bridge_signal_sim_map.erase(t); + _m[t].m2 = 0; +} + +void ClearBridgeSimulatedSignalMapping() +{ + _long_bridge_signal_sim_map.clear(); +} diff --git a/src/bridge_signal_map.h b/src/bridge_signal_map.h new file mode 100644 index 0000000000..3ab234cbe3 --- /dev/null +++ b/src/bridge_signal_map.h @@ -0,0 +1,75 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file bridge_signal_map.h Map accessor functions for bridge signal simulation. */ + +#ifndef BRIDGE_SIGNAL_MAP_H +#define BRIDGE_SIGNAL_MAP_H + +#include "tile_type.h" +#include "map_func.h" +#include "signal_type.h" +#include "core/bitmath_func.hpp" + +#include +#include + +struct LongBridgeSignalStorage { + std::vector signal_red_bits; +}; + +extern std::unordered_map _long_bridge_signal_sim_map; + +SignalState GetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal); + +static inline SignalState GetBridgeEntranceSimulatedSignalState(TileIndex t, uint16 signal) +{ + if (signal < 15) { + return GB(_m[t].m2, signal, 1) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; + } else { + return GetBridgeEntranceSimulatedSignalStateExtended(t, signal); + } +} + +void SetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal, SignalState state); + +static inline void SetBridgeEntranceSimulatedSignalState(TileIndex t, uint16 signal, SignalState state) +{ + if (signal < 15) { + SB(_m[t].m2, signal, 1, (state == SIGNAL_STATE_RED) ? 1 : 0); + } else { + SetBridgeEntranceSimulatedSignalStateExtended(t, signal, state); + } +} + +void SetAllBridgeEntranceSimulatedSignalsGreenExtended(TileIndex t); + +static inline void SetAllBridgeEntranceSimulatedSignalsGreen(TileIndex t) +{ + if (_m[t].m2 & 0x8000) { + SetAllBridgeEntranceSimulatedSignalsGreenExtended(t); + } else { + _m[t].m2 = 0; + } +} + +void ClearBridgeEntranceSimulatedSignalsExtended(TileIndex t); + +static inline void ClearBridgeEntranceSimulatedSignals(TileIndex t) +{ + if (_m[t].m2 & 0x8000) { + ClearBridgeEntranceSimulatedSignalsExtended(t); + } else { + _m[t].m2 = 0; + } +} + +void ClearBridgeSimulatedSignalMapping(); + +#endif /* BRIDGE_SIGNAL_MAP_H */ diff --git a/src/misc.cpp b/src/misc.cpp index 31cdfb470b..d24be86eba 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -31,6 +31,7 @@ #include "tracerestrict.h" #include "programmable_signals.h" #include "viewport_func.h" +#include "bridge_signal_map.h" #include "safeguards.h" @@ -81,6 +82,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin LinkGraphSchedule::Clear(); ClearTraceRestrictMapping(); + ClearBridgeSimulatedSignalMapping(); PoolBase::Clean(PT_NORMAL); FreeSignalPrograms(); diff --git a/src/openttd.cpp b/src/openttd.cpp index ede5cb4e51..fbef087a18 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -68,6 +68,7 @@ #include "smallmap_gui.h" #include "viewport_func.h" #include "thread/thread.h" +#include "bridge_signal_map.h" #include "linkgraph/linkgraphschedule.h" #include "tracerestrict.h" @@ -341,6 +342,7 @@ static void ShutdownGame() LinkGraphSchedule::Clear(); ClearTraceRestrictMapping(); + ClearBridgeSimulatedSignalMapping(); PoolBase::Clean(PT_ALL); FreeSignalPrograms(); diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index daab4d3779..1b624ff905 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -943,7 +943,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) break; } } - if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(dst_tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(dst_tile)) == dst_trackdir) { + if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(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; } diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index e59fde07d0..2c5b134110 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -374,7 +374,7 @@ public: } } } - if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(tile)) == trackdir) { + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(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; } diff --git a/src/pbs.cpp b/src/pbs.cpp index 26081edf8a..7770fddd34 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -143,7 +143,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); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); return true; } @@ -213,7 +213,7 @@ void UnreserveRailTrack(TileIndex tile, Track t) case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) { SetTunnelBridgeReservation(tile, false); - if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, false); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_RED); MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); } break; @@ -284,7 +284,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; + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeWithSignalSimulation(tile)) break; } return PBSTileInfo(tile, trackdir, false); @@ -313,7 +313,7 @@ static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) /* Do not find trains inside signalled bridge/tunnels. * Trains on the ramp/entrance itself are found though. */ - if (IsTileType(info->res.tile, MP_TUNNELBRIDGE) && HasWormholeSignals(info->res.tile) && info->res.tile != TileVirtXY(t->x_pos, t->y_pos)) { + if (IsTileType(info->res.tile, MP_TUNNELBRIDGE) && IsTunnelBridgeWithSignalSimulation(info->res.tile) && info->res.tile != TileVirtXY(t->x_pos, t->y_pos)) { return NULL; } } @@ -361,7 +361,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) && !HasWormholeSignals(ftoti.res.tile)) { + if (*train_on_res == NULL && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE) && !IsTunnelBridgeWithSignalSimulation(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(); @@ -481,7 +481,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo } if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) { - if (IsTunnelBridgeEntrance(tile)) { + if (IsTunnelBridgeSignalSimulationEntrance(tile)) { return true; } } @@ -546,7 +546,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; + if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && IsTunnelBridgeSignalSimulationEntrance(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_cmd.cpp b/src/rail_cmd.cpp index 68654bdf2b..3982141ee9 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -21,6 +21,7 @@ #include "autoslope.h" #include "water.h" #include "tunnelbridge_map.h" +#include "bridge_signal_map.h" #include "vehicle_func.h" #include "sound_func.h" #include "tunnelbridge.h" @@ -42,6 +43,8 @@ #include "table/railtypes.h" #include "table/track_land.h" +#include + #include "safeguards.h" /** Helper type for lists/vectors of trains */ @@ -1023,6 +1026,20 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u return cost; } +static void ClearBridgeTunnelSignalSimulation(TileIndex entrance, TileIndex exit) +{ + if (IsBridge(entrance)) ClearBridgeEntranceSimulatedSignals(entrance); + ClrTunnelBridgeSignalSimulationEntrance(entrance); + ClrTunnelBridgeSignalSimulationExit(exit); +} + +static void SetupBridgeTunnelSignalSimulation(TileIndex entrance, TileIndex exit) +{ + SetTunnelBridgeSignalSimulationEntrance(entrance); + SetTunnelBridgeSignalState(entrance, SIGNAL_STATE_GREEN); + SetTunnelBridgeSignalSimulationExit(exit); +} + /** * Build signals, alternate between double/single, signal/semaphore, * pre/exit/combo-signals, and what-else not. If the rail piece does not @@ -1077,7 +1094,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, cost = CommandCost(); bool flip_variant = false; bool is_pbs = (sigtype == SIGTYPE_PBS) || (sigtype == SIGTYPE_PBS_ONEWAY); - if (!HasWormholeSignals(tile)) { // toggle signal zero costs. + if (!IsTunnelBridgeWithSignalSimulation(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 { @@ -1090,7 +1107,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, } } if (flags & DC_EXEC) { - if (p2 == 0 && HasWormholeSignals(tile)) { // Toggle signal if already signals present. + if (p2 == 0 && IsTunnelBridgeWithSignalSimulation(tile)) { // Toggle signal if already signals present. if (convert_signal) { if (flip_variant) { SetTunnelBridgeSemaphore(tile, !IsTunnelBridgeSemaphore(tile)); @@ -1104,37 +1121,28 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, SetTunnelBridgePBS(tile, !IsTunnelBridgePBS(tile)); SetTunnelBridgePBS(tile_exit, IsTunnelBridgePBS(tile)); } else { - if (IsTunnelBridgeEntrance(tile)) { - ClrBitTunnelBridgeSignal(tile); - ClrBitTunnelBridgeExit(tile_exit); - SetBitTunnelBridgeExit(tile); - SetBitTunnelBridgeSignal(tile_exit); + if (IsTunnelBridgeSignalSimulationEntrance(tile)) { + ClearBridgeTunnelSignalSimulation(tile, tile_exit); + SetupBridgeTunnelSignalSimulation(tile_exit, tile); } else { - ClrBitTunnelBridgeSignal(tile_exit); - ClrBitTunnelBridgeExit(tile); - SetBitTunnelBridgeExit(tile_exit); - SetBitTunnelBridgeSignal(tile); + ClearBridgeTunnelSignalSimulation(tile_exit, tile); + SetupBridgeTunnelSignalSimulation(tile, tile_exit); } } } else { /* Create one direction tunnel/bridge if required. */ if (p2 == 0) { - SetBitTunnelBridgeSignal(tile); - SetBitTunnelBridgeExit(tile_exit); + SetupBridgeTunnelSignalSimulation(tile, tile_exit); } else if (p2 == 4 || p2 == 8) { DiagDirection tbdir = GetTunnelBridgeDirection(tile); /* 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); + ClearBridgeTunnelSignalSimulation(tile_exit, tile); + SetupBridgeTunnelSignalSimulation(tile, tile_exit); } else { - ClrBitTunnelBridgeSignal(tile); - ClrBitTunnelBridgeExit(tile_exit); - SetBitTunnelBridgeSignal(tile_exit); - SetBitTunnelBridgeExit(tile); + ClearBridgeTunnelSignalSimulation(tile, tile_exit); + SetupBridgeTunnelSignalSimulation(tile_exit, tile); } } if (p2 == 0 || p2 == 4 || p2 == 8) { @@ -1144,8 +1152,8 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, 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); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile) && !HasTunnelBridgeReservation(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_RED); + if (IsTunnelBridgeSignalSimulationExit(tile_exit) && IsTunnelBridgePBS(tile_exit) && !HasTunnelBridgeReservation(tile_exit)) SetTunnelBridgeSignalState(tile_exit, SIGNAL_STATE_RED); MarkBridgeOrTunnelDirty(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile)); AddSideToSignalBuffer(tile_exit, INVALID_DIAGDIR, GetTileOwner(tile)); @@ -1329,7 +1337,7 @@ static bool CheckSignalAutoFill(TileIndex &tile, Trackdir &trackdir, int &signal return true; case MP_TUNNELBRIDGE: { - if (!remove && HasWormholeSignals(tile)) return false; + if (!remove && IsTunnelBridgeWithSignalSimulation(tile)) return false; TileIndex orig_tile = tile; // backup old value if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return false; @@ -1580,7 +1588,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1 if (IsTileType(tile, MP_TUNNELBRIDGE)) { TileIndex end = GetOtherTunnelBridgeEnd(tile); if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK); - if (!HasWormholeSignals(tile)) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS); + if (!IsTunnelBridgeWithSignalSimulation(tile)) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS); cost *= ((GetTunnelBridgeLength(tile, end) + 4) >> 2); @@ -1608,14 +1616,10 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1 /* Do it? */ if (flags & DC_EXEC) { - if (HasWormholeSignals(tile)) { // handle tunnel/bridge signals. + if (IsTunnelBridgeWithSignalSimulation(tile)) { // handle tunnel/bridge signals. TileIndex end = GetOtherTunnelBridgeEnd(tile); - ClrBitTunnelBridgeExit(tile); - ClrBitTunnelBridgeExit(end); - ClrBitTunnelBridgeSignal(tile); - ClrBitTunnelBridgeSignal(end); - _m[tile].m2 = 0; - _m[end].m2 = 0; + ClearBridgeTunnelSignalSimulation(end, tile); + ClearBridgeTunnelSignalSimulation(tile, end); MarkBridgeOrTunnelDirty(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile)); AddSideToSignalBuffer(end, INVALID_DIAGDIR, GetTileOwner(tile)); diff --git a/src/rail_map.h b/src/rail_map.h index 7c5e1af7f2..c91c2af0ee 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -485,7 +485,7 @@ static inline bool HasOnewaySignalBlockingTrackdir(TileIndex tile, Trackdir td) !HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td))) { return true; } - if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(tile)) == td) { return true; } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index bf3948477c..7b8071cb57 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3245,13 +3245,28 @@ bool AfterLoadGame() /* 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)) { + if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeWithSignalSimulation(t)) { SetTunnelBridgeSemaphore(t, _cur_year < _settings_client.gui.semaphore_build_before); SetTunnelBridgePBS(t, false); UpdateSignalsOnSegment(t, INVALID_DIAGDIR, GetTileOwner(t)); } } } + if (SlXvIsFeaturePresent(XSLFI_SIG_TUNNEL_BRIDGE, 1, 2)) { + /* red/green signal state bit for tunnel entrances moved + * to no longer re-use signalled tunnel exit bit + */ + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeWithSignalSimulation(t)) { + if (HasBit(_m[t].m5, 5)) { + /* signalled tunnel entrance */ + SignalState state = HasBit(_m[t].m5, 6) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; + ClrBit(_m[t].m5, 6); + SetTunnelBridgeSignalState(t, state); + } + } + } + } /* Station acceptance is some kind of cache */ if (IsSavegameVersionBefore(127)) { diff --git a/src/saveload/bridge_signal_sl.cpp b/src/saveload/bridge_signal_sl.cpp new file mode 100644 index 0000000000..2af749a3fd --- /dev/null +++ b/src/saveload/bridge_signal_sl.cpp @@ -0,0 +1,58 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file bridge_signal_sl.cpp Code handling saving and loading of data for signal on bridges */ + +#include "../stdafx.h" +#include "../bridge_signal_map.h" +#include "saveload.h" +#include + +/** stub save header struct */ +struct LongBridgeSignalStorageStub { + uint32 length; +}; + +static const SaveLoad _long_bridge_signal_storage_stub_desc[] = { + SLE_VAR(LongBridgeSignalStorageStub, length, SLE_UINT32), + SLE_END() +}; + +static void Load_XBSS() +{ + int index; + LongBridgeSignalStorageStub stub; + while ((index = SlIterateArray()) != -1) { + LongBridgeSignalStorage &lbss = _long_bridge_signal_sim_map[index]; + SlObject(&stub, _long_bridge_signal_storage_stub_desc); + lbss.signal_red_bits.resize(stub.length); + SlArray(&(lbss.signal_red_bits[0]), stub.length, SLE_UINT64); + } +} + +static void RealSave_XBSS(const LongBridgeSignalStorage *lbss) +{ + LongBridgeSignalStorageStub stub; + stub.length = lbss->signal_red_bits.size(); + SlObject(&stub, _long_bridge_signal_storage_stub_desc); + SlArray(const_cast(&(lbss->signal_red_bits[0])), stub.length, SLE_UINT64); +} + +static void Save_XBSS() +{ + for (const auto &it : _long_bridge_signal_sim_map) { + const LongBridgeSignalStorage &lbss = it.second; + SlSetArrayIndex(it.first); + SlAutolength((AutolengthProc*) RealSave_XBSS, const_cast(&lbss)); + } +} + +extern const ChunkHandler _bridge_signal_chunk_handlers[] = { + { 'XBSS', Save_XBSS, Load_XBSS, NULL, NULL, CH_SPARSE_ARRAY | CH_LAST}, +}; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index c7723c0d41..cd2a2eff3a 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -54,7 +54,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", NULL, NULL, NULL }, { XSLFI_TIMETABLES_START_TICKS, XSCF_NULL, 2, 2, "timetable_start_ticks", NULL, NULL, NULL }, { XSLFI_TOWN_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "town_cargo_adj", NULL, NULL, NULL }, - { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 2, 2, "signal_tunnel_bridge", NULL, NULL, NULL }, + { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 4, 4, "signal_tunnel_bridge", NULL, NULL, "XBSS" }, { XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 4, 4, "improved_breakdowns", NULL, NULL, NULL }, { XSLFI_TT_WAIT_IN_DEPOT, XSCF_NULL, 1, 1, "tt_wait_in_depot", NULL, NULL, NULL }, { XSLFI_AUTO_TIMETABLE, XSCF_NULL, 4, 4, "auto_timetables", NULL, NULL, NULL }, diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 40329504f3..44682ee145 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -464,6 +464,7 @@ extern const ChunkHandler _signal_chunk_handlers[]; extern const ChunkHandler _plan_chunk_handlers[]; extern const ChunkHandler _template_replacement_chunk_handlers[]; extern const ChunkHandler _template_vehicle_chunk_handlers[]; +extern const ChunkHandler _bridge_signal_chunk_handlers[]; /** Array of all chunks in a savegame, \c NULL terminated. */ static const ChunkHandler * const _chunk_handlers[] = { @@ -506,6 +507,7 @@ static const ChunkHandler * const _chunk_handlers[] = { _plan_chunk_handlers, _template_replacement_chunk_handlers, _template_vehicle_chunk_handlers, + _bridge_signal_chunk_handlers, NULL, }; diff --git a/src/signal.cpp b/src/signal.cpp index 8a73e31f84..667a0a2494 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -408,13 +408,13 @@ static SigInfo ExploreSegment(Owner owner) if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue; DiagDirection dir = GetTunnelBridgeDirection(tile); - if (HasWormholeSignals(tile)) { + if (IsTunnelBridgeWithSignalSimulation(tile)) { if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole - if (!(info.flags & SF_TRAIN) && IsTunnelBridgeExit(tile)) { // tunnel entrence is ignored + if (!(info.flags & SF_TRAIN) && IsTunnelBridgeSignalSimulationExit(tile)) { // tunnel entrence is ignored if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN; if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN; } - if (IsTunnelBridgeExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) { + if (IsTunnelBridgeSignalSimulationExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) { info.flags |= SF_FULL; return info; } @@ -423,7 +423,7 @@ static SigInfo 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)) { + if (IsTunnelBridgeSignalSimulationExit(tile)) { if (IsTunnelBridgePBS(tile)) { info.flags |= SF_PBS; } else if (!_tbuset.Add(tile, INVALID_TRACKDIR)) { @@ -433,7 +433,7 @@ static SigInfo ExploreSegment(Owner owner) } if (!(info.flags & SF_TRAIN)) { if (HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN; - if (!(info.flags & SF_TRAIN) && IsTunnelBridgeExit(tile)) { + if (!(info.flags & SF_TRAIN) && IsTunnelBridgeSignalSimulationExit(tile)) { if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN; } } @@ -481,12 +481,12 @@ static void UpdateSignalsAroundSegment(SigInfo info) Track track; while (_tbuset.Get(&tile, &trackdir)) { - if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile)) { + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile)) { if (IsTunnelBridgePBS(tile)) continue; - bool old_state = IsTunnelBridgeExitGreen(tile); - bool new_state = !(info.flags & SF_TRAIN); + SignalState old_state = GetTunnelBridgeSignalState(tile); + SignalState new_state = (info.flags & SF_TRAIN) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; if (old_state != new_state) { - SetTunnelBridgeExitGreen(tile, new_state); + SetTunnelBridgeSignalState(tile, new_state); MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); } continue; @@ -597,7 +597,7 @@ static SigSegState UpdateSignalsInBuffer(Owner owner) assert(GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL); assert(dir == INVALID_DIAGDIR || dir == ReverseDiagDir(GetTunnelBridgeDirection(tile))); _tbdset.Add(tile, INVALID_DIAGDIR); // we can safely start from wormhole centre - if (!HasWormholeSignals(tile)) { // Don't worry with other side of tunnel. + if (!IsTunnelBridgeWithSignalSimulation(tile)) { // Don't worry with other side of tunnel. _tbdset.Add(GetOtherTunnelBridgeEnd(tile), INVALID_DIAGDIR); } break; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index ec80a1e7e8..ebc9144687 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -40,6 +40,7 @@ #include "tbtr_template_vehicle_func.h" #include "autoreplace_func.h" #include "engine_func.h" +#include "bridge_signal_map.h" #include "table/strings.h" #include "table/train_cmd.h" @@ -2000,9 +2001,9 @@ void ReverseTrainDirection(Train *v) } /* We are inside tunnel/bidge with signals, reversing will close the entrance. */ - if (HasWormholeSignals(v->tile)) { + if (IsTunnelBridgeWithSignalSimulation(v->tile)) { /* Flip signal on tunnel entrance tile red. */ - SetBitTunnelBridgeExit(v->tile); + SetTunnelBridgeSignalState(v->tile, SIGNAL_STATE_RED); MarkTileDirtyByTile(v->tile); /* Clear counters. */ v->wait_counter = 0; @@ -2353,38 +2354,57 @@ static bool CheckTrainStayInDepot(Train *v) return false; } +static int GetAndClearLastBridgeEntranceSetSignalIndex(TileIndex bridge_entrance) +{ + uint16 m = _m[bridge_entrance].m2; + if (m & 0x8000) { + auto it = _long_bridge_signal_sim_map.find(bridge_entrance); + if (it != _long_bridge_signal_sim_map.end()) { + LongBridgeSignalStorage &lbss = it->second; + size_t slot = lbss.signal_red_bits.size(); + while (slot > 0) { + slot--; + uint64 &slot_bits = lbss.signal_red_bits[slot]; + if (slot_bits) { + uint8 i = FindLastBit(slot_bits); + ClrBit(slot_bits, i); + return 1 + 15 + (64 * slot) + i; + } + } + } + } + if (m & 0x7FFF) { + uint8 i = FindLastBit(m & 0x7FFF); + ClrBit(_m[bridge_entrance].m2, i); + return 1 + i; + } + + return 0; +} + static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDirection dir, bool free) { - if (IsBridge(end) && _m[end].m2 > 0){ + if (IsBridge(end) && _m[end].m2 != 0) { /* Clearing last bridge signal. */ - uint16 m = _m[end].m2; - byte i = 15; - while((m & 0x8000) == 0 && --i > 0) m <<= 1; - ClrBit(_m[end].m2, i); - - uint x = TileX(end)* TILE_SIZE; - uint y = TileY(end)* TILE_SIZE; - uint distance = (TILE_SIZE * _settings_game.construction.simulated_wormhole_signals) * ++i; - switch (dir) { - default: NOT_REACHED(); - case DIAGDIR_NE: MarkTileDirtyByTile(TileVirtXY(x - distance, y)); break; - case DIAGDIR_SE: MarkTileDirtyByTile(TileVirtXY(x, y + distance)); break; - case DIAGDIR_SW: MarkTileDirtyByTile(TileVirtXY(x + distance, y)); break; - case DIAGDIR_NW: MarkTileDirtyByTile(TileVirtXY(x, y - distance)); break; + int signal_offset = GetAndClearLastBridgeEntranceSetSignalIndex(end); + if (signal_offset) { + TileIndex last_signal_tile = end + (TileOffsByDiagDir(dir) * _settings_game.construction.simulated_wormhole_signals * signal_offset); + MarkTileDirtyByTile(last_signal_tile); } MarkTileDirtyByTile(tile); } if (free) { /* Open up the wormhole and clear m2. */ - _m[tile].m2 = 0; - _m[end].m2 = 0; + if (IsBridge(end)) { + SetAllBridgeEntranceSimulatedSignalsGreen(end); + } - if (IsTunnelBridgeWithSignRed(end)) { - ClrBitTunnelBridgeExit(end); - if (!_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(end); - } else if (IsTunnelBridgeWithSignRed(tile)) { - ClrBitTunnelBridgeExit(tile); - if (!_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(tile); + if (IsTunnelBridgeSignalSimulationEntrance(end) && GetTunnelBridgeSignalState(end) == SIGNAL_STATE_RED) { + SetTunnelBridgeSignalState(end, SIGNAL_STATE_GREEN); + MarkTileDirtyByTile(end); + } else if (IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeSignalState(tile) == SIGNAL_STATE_RED) { + SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); + MarkTileDirtyByTile(tile); } } } @@ -2392,7 +2412,7 @@ static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDir static void UnreserveBridgeTunnelTile(TileIndex tile) { SetTunnelBridgeReservation(tile, false); - if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, false); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_RED); } /** @@ -2411,7 +2431,7 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ TileIndex end = GetOtherTunnelBridgeEnd(tile); bool free = TunnelBridgeIsFree(tile, end, v).Succeeded(); - if (HasWormholeSignals(tile)) { + if (IsTunnelBridgeWithSignalSimulation(tile)) { UnreserveBridgeTunnelTile(tile); HandleLastTunnelBridgeSignals(tile, end, dir, free); if (_settings_client.gui.show_track_reservation) { @@ -2431,7 +2451,7 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ } } } - } else if (GetTunnelBridgeDirection(tile) == dir && HasWormholeSignals(tile)) { + } else if (GetTunnelBridgeDirection(tile) == dir && IsTunnelBridgeWithSignalSimulation(tile)) { /* cancelling reservation of entry ramp, due to reverse */ UnreserveBridgeTunnelTile(tile); if (_settings_client.gui.show_track_reservation) { @@ -2965,7 +2985,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay) } } - if (IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(v->tile) && + if (IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && DiagDirToDiagTrackBits(GetTunnelBridgeDirection(v->tile)) == v->track) { // prevent any attempt to reserve the wrong way onto a tunnel/bridge exit return false; @@ -3204,7 +3224,7 @@ static TrainMovedChangeSignalEnum TrainMovedChangeSignal(Train* v, TileIndex til if (HasLongReservePbsSignalOnTrackdir(v, tile, trackdir)) return CHANGED_LR_PBS; } } - if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { + if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile) && GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { if (UpdateSignalsOnSegment(tile, dir, GetTileOwner(tile)) == SIGSEG_PBS) { return CHANGED_NORMAL_TO_PBS_BLOCK; } @@ -3473,7 +3493,7 @@ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile) if (t->force_proceed != 0) return false; /* When not exit reverse train. */ - if (!IsTunnelBridgeExit(tile)) { + if (!IsTunnelBridgeSignalSimulationExit(tile)) { t->cur_speed = 0; ToggleBit(t->flags, VRF_REVERSING); return true; @@ -3500,7 +3520,7 @@ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile) return false; } -static void HandleSignalBehindTrain(Train *v, uint signal_number) +static void HandleSignalBehindTrain(Train *v, int signal_number) { TileIndex tile; switch (v->direction) { @@ -3513,12 +3533,12 @@ static void HandleSignalBehindTrain(Train *v, uint signal_number) if(tile == v->tile) { /* Flip signal on ramp. */ - if (IsTunnelBridgeWithSignRed(tile)) { - ClrBitTunnelBridgeExit(tile); + if (IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeSignalState(tile) == SIGNAL_STATE_RED) { + SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(tile); } - } else if (IsBridge(v->tile) && signal_number <= 16) { - ClrBit(_m[v->tile].m2, signal_number); + } else if (IsBridge(v->tile) && signal_number >= 0) { + SetBridgeEntranceSimulatedSignalState(v->tile, signal_number, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(tile); } } @@ -3729,20 +3749,20 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) goto invalid_rail; } - if (HasWormholeSignals(gp.new_tile)) { + if (IsTunnelBridgeWithSignalSimulation(gp.new_tile)) { /* If red signal stop. */ if (v->IsFrontEngine() && v->force_proceed == 0) { - if (IsTunnelBridgeWithSignRed(gp.new_tile)) { + if (IsTunnelBridgeSignalSimulationEntrance(gp.new_tile) && GetTunnelBridgeSignalState(gp.new_tile) == SIGNAL_STATE_RED) { v->cur_speed = 0; v->vehstatus |= VS_TRAIN_SLOWING; return false; } - if (IsTunnelBridgeExit(gp.new_tile)) { + if (IsTunnelBridgeSignalSimulationExit(gp.new_tile)) { v->cur_speed = 0; goto invalid_rail; } /* Flip signal on tunnel entrance tile red. */ - SetBitTunnelBridgeExit(gp.new_tile); + SetTunnelBridgeSignalState(gp.new_tile, SIGNAL_STATE_RED); MarkTileDirtyByTile(gp.new_tile); } } @@ -3801,9 +3821,9 @@ 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 && IsTunnelBridgeWithSignalSimulation(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; + if (v->IsFrontEngine() && v->force_proceed == 0 && IsTunnelBridgeSignalSimulationExit(v->tile)) goto invalid_rail; /* Entered wormhole set counters. */ v->wait_counter = (TILE_SIZE * _settings_game.construction.simulated_wormhole_signals) - TILE_SIZE; v->load_unload_ticks = 0; @@ -3827,14 +3847,14 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) return false; } /* flip signal in front to red on bridges*/ - if (distance == 0 && v->load_unload_ticks <= 15 && IsBridge(v->tile)){ - SetBit(_m[v->tile].m2, v->load_unload_ticks); + if (distance == 0 && IsBridge(v->tile)) { + SetBridgeEntranceSimulatedSignalState(v->tile, v->load_unload_ticks, SIGNAL_STATE_RED); MarkTileDirtyByTile(gp.new_tile); } } } if (v->Next() == NULL) { - if (v->load_unload_ticks > 0 && v->load_unload_ticks <= 16 && distance == (TILE_SIZE * _settings_game.construction.simulated_wormhole_signals) - TILE_SIZE) HandleSignalBehindTrain(v, v->load_unload_ticks - 2); + if (v->load_unload_ticks > 0 && distance == (TILE_SIZE * _settings_game.construction.simulated_wormhole_signals) - TILE_SIZE) HandleSignalBehindTrain(v, v->load_unload_ticks - 2); if (old_tile == v->tile) { /* We left ramp into wormhole. */ v->x_pos = gp.x; diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index b7cf858be0..dec05a34fb 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -26,6 +26,7 @@ #include "newgrf_sound.h" #include "autoslope.h" #include "tunnelbridge_map.h" +#include "bridge_signal_map.h" #include "strings_func.h" #include "date_func.h" #include "clear_func.h" @@ -957,6 +958,9 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags) } DirtyCompanyInfrastructureWindows(owner); + if (IsTunnelBridgeSignalSimulationEntrance(tile)) ClearBridgeEntranceSimulatedSignals(tile); + if (IsTunnelBridgeSignalSimulationEntrance(endtile)) ClearBridgeEntranceSimulatedSignals(endtile); + DoClearSquare(tile); DoClearSquare(endtile); for (TileIndex c = tile + delta; c != endtile; c += delta) { @@ -1169,15 +1173,13 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) SignalType type = SIGTYPE_NORMAL; - bool is_green; + bool is_green = (GetTunnelBridgeSignalState(ti->tile) == SIGNAL_STATE_GREEN); bool show_exit; - if (IsTunnelBridgeExit(ti->tile)) { - is_green = IsTunnelBridgeExitGreen(ti->tile); + if (IsTunnelBridgeSignalSimulationExit(ti->tile)) { show_exit = true; position ^= 1; if (IsTunnelBridgePBS(ti->tile)) type = SIGTYPE_PBS_ONEWAY; } else { - is_green = IsTunnelBridgeWithSignGreen(ti->tile); show_exit = false; } @@ -1248,14 +1250,14 @@ static void DrawBrigeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_sta SignalVariant variant = IsTunnelBridgeSemaphore(bridge_start_tile) ? SIG_SEMAPHORE : SIG_ELECTRIC; - SpriteID sprite; + SpriteID sprite = (GetBridgeEntranceSimulatedSignalState(bridge_start_tile, m2_position) == SIGNAL_STATE_GREEN); if (variant == SIG_ELECTRIC) { /* Normal electric signals are picked from original sprites. */ - sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + !HasBit(_m[bridge_start_tile].m2, m2_position)); + sprite += SPR_ORIGINAL_SIGNALS_BASE + (position << 1); } else { /* All other signals are picked from add on sprites. */ - sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + !HasBit(_m[bridge_start_tile].m2, m2_position)); + sprite += SPR_SIGNALS_BASE + (SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1); } AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR); @@ -1379,7 +1381,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 (HasWormholeSignals(ti->tile)) DrawTunnelBridgeRampSignal(ti); + if (IsTunnelBridgeWithSignalSimulation(ti->tile)) DrawTunnelBridgeRampSignal(ti); DrawBridgeMiddle(ti); } else { // IsBridge(ti->tile) @@ -1489,7 +1491,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) } /* Draw signals for bridge. */ - if (HasWormholeSignals(ti->tile)) DrawTunnelBridgeRampSignal(ti); + if (IsTunnelBridgeWithSignalSimulation(ti->tile)) DrawTunnelBridgeRampSignal(ti); DrawBridgeMiddle(ti); } @@ -1626,7 +1628,7 @@ void DrawBridgeMiddle(const TileInfo *ti) } if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth) - && !HasWormholeSignals(rampnorth)) { + && !IsTunnelBridgeWithSignalSimulation(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)); @@ -1640,8 +1642,8 @@ void DrawBridgeMiddle(const TileInfo *ti) if (HasCatenaryDrawn(GetRailType(rampsouth))) { DrawCatenaryOnBridge(ti); } - if (HasWormholeSignals(rampsouth)) { - IsTunnelBridgeExit(rampsouth) ? DrawBrigeSignalOnMiddlePart(ti, rampnorth, z): DrawBrigeSignalOnMiddlePart(ti, rampsouth, z); + if (IsTunnelBridgeWithSignalSimulation(rampsouth)) { + IsTunnelBridgeSignalSimulationExit(rampsouth) ? DrawBrigeSignalOnMiddlePart(ti, rampnorth, z): DrawBrigeSignalOnMiddlePart(ti, rampsouth, z); } } @@ -1731,9 +1733,9 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td) TransportType tt = GetTunnelBridgeTransportType(tile); if (IsTunnel(tile)) { - td->str = (tt == TRANSPORT_RAIL) ? HasWormholeSignals(tile) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL : STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD; + td->str = (tt == TRANSPORT_RAIL) ? IsTunnelBridgeWithSignalSimulation(tile) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL : STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD; } else { // IsBridge(tile) - td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : HasWormholeSignals(tile) ? STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt]; + td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : IsTunnelBridgeWithSignalSimulation(tile) ? STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt]; } td->owner[0] = GetTileOwner(tile); diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 46129983c5..7d35df7c83 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -15,6 +15,7 @@ #include "bridge_map.h" #include "tunnel_map.h" #include "cmd_helper.h" +#include "signal_type.h" /** @@ -136,40 +137,40 @@ static inline TrackBits GetTunnelBridgeReservationTrackBits(TileIndex t) } /** - * Declare tunnel/bridge with signal simulation. + * Declare tunnel/bridge entrance with signal simulation. * @param t the tunnel/bridge tile. */ -static inline void SetBitTunnelBridgeSignal(TileIndex t) +static inline void SetTunnelBridgeSignalSimulationEntrance(TileIndex t) { assert(IsTileType(t, MP_TUNNELBRIDGE)); SetBit(_m[t].m5, 5); } /** - * Remove tunnel/bridge with signal simulation. + * Remove tunnel/bridge entrance with signal simulation. * @param t the tunnel/bridge tile. */ -static inline void ClrBitTunnelBridgeSignal(TileIndex t) +static inline void ClrTunnelBridgeSignalSimulationEntrance(TileIndex t) { assert(IsTileType(t, MP_TUNNELBRIDGE)); ClrBit(_m[t].m5, 5); } /** - * Declare tunnel/bridge exit. + * Declare tunnel/bridge exit with signal simulation. * @param t the tunnel/bridge tile. */ -static inline void SetBitTunnelBridgeExit(TileIndex t) +static inline void SetTunnelBridgeSignalSimulationExit(TileIndex t) { assert(IsTileType(t, MP_TUNNELBRIDGE)); SetBit(_m[t].m5, 6); } /** - * Remove tunnel/bridge exit declaration. + * Remove tunnel/bridge exit with signal simulation. * @param t the tunnel/bridge tile. */ -static inline void ClrBitTunnelBridgeExit(TileIndex t) +static inline void ClrTunnelBridgeSignalSimulationExit(TileIndex t) { assert(IsTileType(t, MP_TUNNELBRIDGE)); ClrBit(_m[t].m5, 6); @@ -181,85 +182,81 @@ static inline void ClrBitTunnelBridgeExit(TileIndex t) * @param t the tile that might be a tunnel/bridge. * @return true if and only if this tile is a tunnel/bridge with signal simulation. */ -static inline bool HasWormholeSignals(TileIndex t) +static inline bool IsTunnelBridgeWithSignalSimulation(TileIndex t) { - return IsTileType(t, MP_TUNNELBRIDGE) && (HasBit(_m[t].m5, 5) || HasBit(_m[t].m5, 6)) ; -} - -/** - * Is this a tunnel/bridge with sign on green? - * @param t the tile that might be a tunnel/bridge with sign set green. - * @pre IsTileType(t, MP_TUNNELBRIDGE) - * @return true if and only if this tile is a tunnel/bridge entrance. - */ -static inline bool IsTunnelBridgeWithSignGreen(TileIndex t) -{ - assert(IsTileType(t, MP_TUNNELBRIDGE)); - return HasBit(_m[t].m5, 5) && !HasBit(_m[t].m5, 6); -} - -static inline bool IsTunnelBridgeWithSignRed(TileIndex t) -{ - assert(IsTileType(t, MP_TUNNELBRIDGE)); - return HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6); + return IsTileType(t, MP_TUNNELBRIDGE) && (HasBit(_m[t].m5, 5) || HasBit(_m[t].m5, 6)); } /** * Is this a tunnel/bridge entrance tile with signal? * Tunnel bridge signal simulation has allways bit 5 on at entrance. * @param t the tile that might be a tunnel/bridge. + * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge entrance. */ -static inline bool IsTunnelBridgeEntrance(TileIndex t) +static inline bool IsTunnelBridgeSignalSimulationEntrance(TileIndex t) { assert(IsTileType(t, MP_TUNNELBRIDGE)); - return HasBit(_m[t].m5, 5) ; + return HasBit(_m[t].m5, 5) && !HasBit(_m[t].m5, 6); } /** * Is this a tunnel/bridge exit? * @param t the tile that might be a tunnel/bridge. + * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge exit. */ -static inline bool IsTunnelBridgeExit(TileIndex t) +static inline bool IsTunnelBridgeSignalSimulationExit(TileIndex t) { assert(IsTileType(t, MP_TUNNELBRIDGE)); return !HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6); } -static inline bool IsTunnelBridgeExitGreen(TileIndex t) +/** + * Get the signal state for a tunnel/bridge entrance or exit with signal simulation + * @param t the tunnel/bridge entrance or exit tile with signal simulation + * @pre IsTunnelBridgeWithSignalSimulation(t) + * @return signal state + */ +static inline SignalState GetTunnelBridgeSignalState(TileIndex t) { - assert(IsTunnelBridgeExit(t)); - return HasBit(_me[t].m6, 0); + assert(IsTunnelBridgeWithSignalSimulation(t)); + return HasBit(_me[t].m6, 0) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED; } -static inline void SetTunnelBridgeExitGreen(TileIndex t, bool green) +/** + * Set the signal state for a tunnel/bridge entrance or exit with signal simulation + * @param t the tunnel/bridge entrance or exit tile with signal simulation + * @pre IsTunnelBridgeWithSignalSimulation(t) + * @param state signal state + */ +static inline void SetTunnelBridgeSignalState(TileIndex t, SignalState state) { - assert(IsTunnelBridgeExit(t)); - SB(_me[t].m6, 0, 1, green ? 1 : 0); + assert(IsTunnelBridgeWithSignalSimulation(t)); + SB(_me[t].m6, 0, 1, (state == SIGNAL_STATE_GREEN) ? 1 : 0); } static inline bool IsTunnelBridgeSemaphore(TileIndex t) { - assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + assert(IsTunnelBridgeWithSignalSimulation(t)); return HasBit(_me[t].m6, 1); } static inline void SetTunnelBridgeSemaphore(TileIndex t, bool is_semaphore) { - assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + assert(IsTunnelBridgeWithSignalSimulation(t)); SB(_me[t].m6, 1, 1, is_semaphore ? 1 : 0); } static inline bool IsTunnelBridgePBS(TileIndex t) { - assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + assert(IsTunnelBridgeWithSignalSimulation(t)); return HasBit(_me[t].m6, 6); } static inline void SetTunnelBridgePBS(TileIndex t, bool is_pbs) { - assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t)); + assert(IsTunnelBridgeWithSignalSimulation(t)); SB(_me[t].m6, 6, 1, is_pbs ? 1 : 0); }
    OOOO OOOO OOOO OOOO XXXX XXXX OOOO OOOOXOOX XXXXOOOO OOOOXPPX XXXXOPOO OOPP XXXX XXXX
    -inherit- -inherit- -inherit-PPPP PPPP PPPP PPPP -inherit- -inherit- -inherit--inherit-OOXX XXOOOPXX XXPP -inherit-