diff --git a/docs/landscape.html b/docs/landscape.html index cba92906aa..c8886be7d8 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -1741,6 +1741,7 @@
  • m6 bit 6: set = PBS signals, clear = block signals
  • m6 bit 1: set = semaphore signals, clear = light signals
  • m6 bit 0: set = entrance signal shows green, clear = entrance signal shows red
  • +
  • m8 bits 15..12: signal simulation spacing
  • m5 bit 4: pbs reservation state for railway (tunnel only)
  • diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index cf5000358e..428ac71f3b 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -292,7 +292,7 @@ the array so you can quickly see what is used and what is not. OPPX XX XX PPOO OOPP PPPX XXXX - OPPP XXXX XXXX XXXX + PPPP XXXX XXXX XXXX bridge ramp - rail @@ -300,7 +300,7 @@ the array so you can quickly see what is used and what is not. OOPP PPPP 1PPO 00 XX PPXX XXPP - OOOO PPPP PPXX XXXX + PPPP PPPP PPXX XXXX bridge ramp - road diff --git a/src/bridge_map.h b/src/bridge_map.h index b6f37cb36b..fb72170e55 100644 --- a/src/bridge_map.h +++ b/src/bridge_map.h @@ -189,6 +189,7 @@ static inline void MakeRailBridgeRamp(TileIndex t, Owner o, BridgeType bridgetyp SB(_me[t].m6, 0, 2, GB(m6_backup, 0, 2)); SB(_me[t].m6, 6, 1, GB(m6_backup, 6, 1)); SB(_me[t].m8, 6, 6, GB(m8_backup, 6, 6)); + SB(_me[t].m8, 12, 4, GB(m8_backup, 12, 4)); } else { /* Set bridge head tracks to axial track only. */ SB(_m[t].m4, 0, 6, DiagDirToDiagTrackBits(d)); diff --git a/src/lang/english.txt b/src/lang/english.txt index 9366f6add4..fbf201e398 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1879,6 +1879,7 @@ STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Set the minimum STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Percentage of leg profit to pay in feeder systems: {STRING2} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Percentage of income given to the intermediate legs in feeder systems, giving more control over the income STR_CONFIG_SETTING_SIMULATE_SIGNALS :Simulate signals in tunnels, bridges every: {STRING2} +STR_CONFIG_SETTING_SIMULATE_SIGNALS_HELPTEXT :This sets the target signal spacing for newly signalled bridges and tunnels. The actual spacing may slightly differ from this to avoid uneven spacing. Changing this setting does not re-signal existing signalled bridges and tunnels. STR_CONFIG_SETTING_SIMULATE_SIGNALS_VALUE :{COMMA} tile{P 0 "" s} STR_CONFIG_SETTING_DAY_LENGTH_FACTOR :Day length factor: {STRING2} STR_CONFIG_SETTING_DAY_LENGTH_FACTOR_HELPTEXT :Game pace is slowed by this factor diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 640c4b59f9..125b54ed98 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1527,8 +1527,11 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, Company * const c = Company::Get(GetTileOwner(tile)); std::vector re_reserve_trains; if (IsTunnelBridgeWithSignalSimulation(tile)) { - c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, tile, tile_exit); + c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, tile_exit); } else { + uint spacing = GetBestTunnelBridgeSignalSimulationSpacing(GetTileOwner(tile), tile, tile_exit); + SetTunnelBridgeSignalSimulationSpacing(tile, spacing); + SetTunnelBridgeSignalSimulationSpacing(tile_exit, spacing); for (TileIndex t : { tile, tile_exit }) { if (HasAcrossTunnelBridgeReservation(t)) { Train *re_reserve_train = GetTrainForReservation(t, FindFirstTrack(GetAcrossTunnelBridgeReservationTrackBits(t))); @@ -1602,7 +1605,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, AddSideToSignalBuffer(tile_exit, INVALID_DIAGDIR, GetTileOwner(tile)); YapfNotifyTrackLayoutChange(tile, track); YapfNotifyTrackLayoutChange(tile_exit, track); - if (IsTunnelBridgeWithSignalSimulation(tile)) c->infrastructure.signal += GetTunnelBridgeSignalSimulationSignalCount(c, tile, tile_exit); + if (IsTunnelBridgeWithSignalSimulation(tile)) c->infrastructure.signal += GetTunnelBridgeSignalSimulationSignalCount(tile, tile_exit); DirtyCompanyInfrastructureWindows(GetTileOwner(tile)); for (Train *re_reserve_train : re_reserve_trains) { ReReserveTrainPath(re_reserve_train); @@ -2095,7 +2098,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1 } if (flags & DC_EXEC) { Company *c = Company::Get(GetTileOwner(tile)); - c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, tile, end); + c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, end); ClearBridgeTunnelSignalSimulation(end, tile); ClearBridgeTunnelSignalSimulation(tile, end); MarkBridgeOrTunnelDirty(tile); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index a10485da66..706b16ff7e 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -29,6 +29,7 @@ #include "../station_base.h" #include "../waypoint_base.h" #include "../roadstop_base.h" +#include "../tunnelbridge.h" #include "../tunnelbridge_map.h" #include "../pathfinder/yapf/yapf_cache.h" #include "../elrail_func.h" @@ -3637,6 +3638,22 @@ bool AfterLoadGame() c->settings.simulated_wormhole_signals = _settings_game.construction.old_simulated_wormhole_signals; } } + if (SlXvIsFeaturePresent(XSLFI_SIG_TUNNEL_BRIDGE, 1, 8)) { + /* spacing made per tunnel/bridge */ + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeWithSignalSimulation(t)) { + DiagDirection dir = GetTunnelBridgeDirection(t); + if (dir == DIAGDIR_NE || dir == DIAGDIR_SE) { + TileIndex other = GetOtherTunnelBridgeEnd(t); + uint spacing = GetBestTunnelBridgeSignalSimulationSpacing(GetTileOwner(t), t, other); + SetTunnelBridgeSignalSimulationSpacing(t, spacing); + SetTunnelBridgeSignalSimulationSpacing(other, spacing); + } + } + } + /* force aspect re-calculation */ + _extra_aspects = 0; + } if (SlXvIsFeatureMissing(XSLFI_CUSTOM_BRIDGE_HEADS)) { /* ensure that previously unused custom bridge-head bits are cleared */ diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 8cfad01739..40c83824a1 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -85,7 +85,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", nullptr, nullptr, nullptr }, { XSLFI_TIMETABLES_START_TICKS, XSCF_NULL, 2, 2, "timetable_start_ticks", nullptr, nullptr, nullptr }, { XSLFI_TOWN_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 2, 2, "town_cargo_adj", nullptr, nullptr, nullptr }, - { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 8, 8, "signal_tunnel_bridge", nullptr, nullptr, "XBSS" }, + { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 9, 9, "signal_tunnel_bridge", nullptr, nullptr, "XBSS" }, { XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 7, 7, "improved_breakdowns", nullptr, nullptr, nullptr }, { XSLFI_CONSIST_BREAKDOWN_FLAG, XSCF_NULL, 1, 1, "consist_breakdown_flag", nullptr, nullptr, nullptr }, { XSLFI_TT_WAIT_IN_DEPOT, XSCF_NULL, 1, 1, "tt_wait_in_depot", nullptr, nullptr, nullptr }, diff --git a/src/settings.cpp b/src/settings.cpp index e9ce4ef8dd..3ec5efe75c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1482,14 +1482,6 @@ static bool InvalidateCompanyWindow(int32 p1) return true; } -static bool SimulatedWormholeSignalsChanged(int32 p1) -{ - extern void AfterLoadCompanyStats(); - AfterLoadCompanyStats(); - MarkWholeScreenDirty(); - return true; -} - static bool EnableSingleVehSharedOrderGuiChanged(int32) { for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) { diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index 99ec3f871a..aaaa60f7fb 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -11,7 +11,6 @@ static bool UpdateIntervalTrains(int32 p1); static bool UpdateIntervalRoadVeh(int32 p1); static bool UpdateIntervalShips(int32 p1); static bool UpdateIntervalAircraft(int32 p1); -static bool SimulatedWormholeSignalsChanged(int32 p1); static const SettingDesc _company_settings[] = { [post-amble] @@ -269,8 +268,8 @@ def = 4 min = 1 max = 16 str = STR_CONFIG_SETTING_SIMULATE_SIGNALS +strhelp = STR_CONFIG_SETTING_SIMULATE_SIGNALS_HELPTEXT strval = STR_CONFIG_SETTING_SIMULATE_SIGNALS_VALUE -proc = SimulatedWormholeSignalsChanged cat = SC_ADVANCED patxname = ""simulated_wormhole_signals"" diff --git a/src/tunnelbridge.h b/src/tunnelbridge.h index 417899ba7a..c2d1fc879a 100644 --- a/src/tunnelbridge.h +++ b/src/tunnelbridge.h @@ -13,8 +13,9 @@ #include "map_func.h" #include "tile_map.h" -uint GetTunnelBridgeSignalSimulationSpacing(TileIndex tile); -uint GetTunnelBridgeSignalSimulationSignalCount(Company *c, TileIndex begin, TileIndex end); +uint GetTunnelBridgeSignalSimulationSpacingTarget(Owner owner); +uint GetBestTunnelBridgeSignalSimulationSpacing(Owner owner, TileIndex begin, TileIndex end); +uint GetTunnelBridgeSignalSimulationSignalCount(TileIndex begin, TileIndex end); /** * Calculates the length of a tunnel or a bridge (without end tiles) diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 49e92930b1..225256e619 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -131,9 +131,8 @@ void MarkBridgeOrTunnelDirtyOnReservationChange(TileIndex tile, ViewportMarkDirt } } -uint GetTunnelBridgeSignalSimulationSpacing(TileIndex tile) +uint GetTunnelBridgeSignalSimulationSpacingTarget(Owner owner) { - Owner owner = GetTileOwner(tile); if (Company::IsValidID(owner)) { return Company::Get(owner)->settings.simulated_wormhole_signals; } else { @@ -141,16 +140,37 @@ uint GetTunnelBridgeSignalSimulationSpacing(TileIndex tile) } } +uint GetBestTunnelBridgeSignalSimulationSpacing(Owner owner, TileIndex begin, TileIndex end) +{ + int target = GetTunnelBridgeSignalSimulationSpacingTarget(owner); + if (target <= 2) return target; + int length = GetTunnelBridgeLength(begin, end); + if (target > length || ((length + 1) % target) == 0) return target; + + int lower = target - (target / 4); + int upper = std::min(16, target + (target / 3)); + + int best_gap = -1; + int best_spacing = 0; + for (int i = lower; i <= upper; i++) { + int gap = length % i; + if (gap > best_gap) { + best_gap = gap; + best_spacing = i; + } + } + return best_spacing; +} + /** * Get number of signals on bridge or tunnel with signal simulation. - * @param c Company to use. * @param begin The begin of the tunnel or bridge. * @param end The end of the tunnel or bridge. * @pre IsTunnelBridgeWithSignalSimulation(begin) */ -uint GetTunnelBridgeSignalSimulationSignalCount(Company *c, TileIndex begin, TileIndex end) +uint GetTunnelBridgeSignalSimulationSignalCount(TileIndex begin, TileIndex end) { - uint result = 2 + (GetTunnelBridgeLength(begin, end) / c->settings.simulated_wormhole_signals); + uint result = 2 + (GetTunnelBridgeLength(begin, end) / GetTunnelBridgeSignalSimulationSpacing(begin)); if (IsTunnelBridgeSignalSimulationBidirectional(begin)) result *= 2; return result; } @@ -1254,7 +1274,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) Company *c = Company::Get(owner); c->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR; if (IsTunnelBridgeWithSignalSimulation(tile)) { // handle tunnel/bridge signals. - c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, tile, endtile); + c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, endtile); } DirtyCompanyInfrastructureWindows(owner); } @@ -2730,9 +2750,9 @@ static void UpdateRailTunnelBridgeInfrastructure(Company *c, TileIndex begin, Ti if (IsTunnelBridgeWithSignalSimulation(begin)) { if (add) { - c->infrastructure.signal += GetTunnelBridgeSignalSimulationSignalCount(c, begin, end); + c->infrastructure.signal += GetTunnelBridgeSignalSimulationSignalCount(begin, end); } else { - c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, begin, end); + c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(begin, end); } } } diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 123c4a0dcf..6e73e05f2b 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -530,6 +530,18 @@ static inline void SetTunnelBridgeExitSignalAspect(TileIndex t, uint8 aspect) SB(_m[t].m3, 3, 3, aspect); } +static inline uint GetTunnelBridgeSignalSimulationSpacing(TileIndex t) +{ + assert_tile(IsRailTunnelBridgeTile(t), t); + return 1 + GB(_me[t].m8, 12, 4); +} + +static inline void SetTunnelBridgeSignalSimulationSpacing(TileIndex t, uint spacing) +{ + assert_tile(IsRailTunnelBridgeTile(t), t); + SB(_me[t].m8, 12, 4, spacing - 1); +} + static inline Trackdir GetTunnelBridgeExitTrackdir(TileIndex t, DiagDirection tunnel_bridge_dir) { return TrackEnterdirToTrackdir((Track)FIND_FIRST_BIT(GetAcrossTunnelBridgeTrackBits(t)), ReverseDiagDir(tunnel_bridge_dir));