Store tunnel/bridge signal spacing on tile, adjust spacing to fit length

pull/306/head
Jonathan G Rennison 3 years ago
parent 67c1e0dd11
commit 16f2ef227b

@ -1741,6 +1741,7 @@
<li>m6 bit 6: set = PBS signals, clear = block signals</li> <li>m6 bit 6: set = PBS signals, clear = block signals</li>
<li>m6 bit 1: set = semaphore signals, clear = light signals</li> <li>m6 bit 1: set = semaphore signals, clear = light signals</li>
<li>m6 bit 0: set = entrance signal shows green, clear = entrance signal shows red</li> <li>m6 bit 0: set = entrance signal shows green, clear = entrance signal shows red</li>
<li>m8 bits 15..12: signal simulation spacing</li>
</ul> </ul>
</li> </li>
<li>m5 bit 4: pbs reservation state for railway (tunnel only)</li> <li>m5 bit 4: pbs reservation state for railway (tunnel only)</li>

@ -292,7 +292,7 @@ the array so you can quickly see what is used and what is not.
<td class="bits"><span class="used" title="Bridge or tunnel bit">O</span><span class="patch" title="Signal simulation mode (rail only)">PP</span><span class="rearrange" title="PBS reservation (rail; a rearrangement can free some of these bits)">X</span> <span class="used" title="Transport type">XX</span> <span class="used" title="Direction of the tunnel/bridge">XX</span></td> <td class="bits"><span class="used" title="Bridge or tunnel bit">O</span><span class="patch" title="Signal simulation mode (rail only)">PP</span><span class="rearrange" title="PBS reservation (rail; a rearrangement can free some of these bits)">X</span> <span class="used" title="Transport type">XX</span> <span class="used" title="Direction of the tunnel/bridge">XX</span></td>
<td class="bits"><span class="patch" title="PBS mode, exit signal state">PP</span><span class="free">OO OO</span><span class="patch" title="Semaphore/light mode, entrance signal state">PP</span></td> <td class="bits"><span class="patch" title="PBS mode, exit signal state">PP</span><span class="free">OO OO</span><span class="patch" title="Semaphore/light mode, entrance signal state">PP</span></td>
<td class="bits" rowspan=4><span class="patch" title="Snow/desert present or rail custom bridge head ground type">PPP</span><span class="rearrange" title="Owner of road (road only; a rearrangement can free some of these bits)">X XXXX</span></td> <td class="bits" rowspan=4><span class="patch" title="Snow/desert present or rail custom bridge head ground type">PPP</span><span class="rearrange" title="Owner of road (road only; a rearrangement can free some of these bits)">X XXXX</span></td>
<td class="bits"><span class="free">O</span><span class="patch" title="Road cached one way state">PPP</span> <span class="used" title="Tram type">XXXX XX</span><span class="rearrange" title="Railway type (rail only; a rearrangement can free some of these bits)">XX XXXX</span></td> <td class="bits"><span class="patch" title="Road cached one way state (road only) or signal simulation spacing (rail only)">PPPP</span> <span class="used" title="Tram type">XXXX XX</span><span class="rearrange" title="Railway type (rail only; a rearrangement can free some of these bits)">XX XXXX</span></td>
</tr> </tr>
<tr> <tr>
<td>bridge ramp - rail</td> <td>bridge ramp - rail</td>
@ -300,7 +300,7 @@ the array so you can quickly see what is used and what is not.
<td class="bits"><span class="free">OO</span><span class="patch" title="Track pieces">PP PPPP</span></td> <td class="bits"><span class="free">OO</span><span class="patch" title="Track pieces">PP PPPP</span></td>
<td class="bits"><span class="used" title="Bridge or tunnel bit">1</span><span class="patch" title="Signal simulation mode">PP</span><span class="free">O</span> <span class="used" title="Transport type">00</span> <span class="used" title="Direction of the tunnel/bridge">XX</span></td> <td class="bits"><span class="used" title="Bridge or tunnel bit">1</span><span class="patch" title="Signal simulation mode">PP</span><span class="free">O</span> <span class="used" title="Transport type">00</span> <span class="used" title="Direction of the tunnel/bridge">XX</span></td>
<td class="bits"><span class="patch" title="PBS mode, exit signal state">PP</span><span class="used" title="Bridge type: wooden, steel,...">XX XX</span><span class="patch" title="Semaphore/light mode, entrance signal state">PP</span></td> <td class="bits"><span class="patch" title="PBS mode, exit signal state">PP</span><span class="used" title="Bridge type: wooden, steel,...">XX XX</span><span class="patch" title="Semaphore/light mode, entrance signal state">PP</span></td>
<td class="bits"><span class="free">OOOO</span> <span class="patch" title="Secondary railway type (used for bridge-bypassing track when two parallel tracks on custom bridge head)">PPPP PP</span><span class="rearrange" title="Railway type (a rearrangement can free some of these bits)">XX XXXX</span></td> <td class="bits"><span class="patch" title="Signal simulation spacing">PPPP</span> <span class="patch" title="Secondary railway type (used for bridge-bypassing track when two parallel tracks on custom bridge head)">PPPP PP</span><span class="rearrange" title="Railway type (a rearrangement can free some of these bits)">XX XXXX</span></td>
</tr> </tr>
<tr> <tr>
<td>bridge ramp - road</td> <td>bridge ramp - road</td>

@ -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, 0, 2, GB(m6_backup, 0, 2));
SB(_me[t].m6, 6, 1, GB(m6_backup, 6, 1)); 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, 6, 6, GB(m8_backup, 6, 6));
SB(_me[t].m8, 12, 4, GB(m8_backup, 12, 4));
} else { } else {
/* Set bridge head tracks to axial track only. */ /* Set bridge head tracks to axial track only. */
SB(_m[t].m4, 0, 6, DiagDirToDiagTrackBits(d)); SB(_m[t].m4, 0, 6, DiagDirToDiagTrackBits(d));

@ -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 :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_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 :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_SIMULATE_SIGNALS_VALUE :{COMMA} tile{P 0 "" s}
STR_CONFIG_SETTING_DAY_LENGTH_FACTOR :Day length factor: {STRING2} STR_CONFIG_SETTING_DAY_LENGTH_FACTOR :Day length factor: {STRING2}
STR_CONFIG_SETTING_DAY_LENGTH_FACTOR_HELPTEXT :Game pace is slowed by this factor STR_CONFIG_SETTING_DAY_LENGTH_FACTOR_HELPTEXT :Game pace is slowed by this factor

@ -1527,8 +1527,11 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
Company * const c = Company::Get(GetTileOwner(tile)); Company * const c = Company::Get(GetTileOwner(tile));
std::vector<Train *> re_reserve_trains; std::vector<Train *> re_reserve_trains;
if (IsTunnelBridgeWithSignalSimulation(tile)) { if (IsTunnelBridgeWithSignalSimulation(tile)) {
c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, tile, tile_exit); c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, tile_exit);
} else { } else {
uint spacing = GetBestTunnelBridgeSignalSimulationSpacing(GetTileOwner(tile), tile, tile_exit);
SetTunnelBridgeSignalSimulationSpacing(tile, spacing);
SetTunnelBridgeSignalSimulationSpacing(tile_exit, spacing);
for (TileIndex t : { tile, tile_exit }) { for (TileIndex t : { tile, tile_exit }) {
if (HasAcrossTunnelBridgeReservation(t)) { if (HasAcrossTunnelBridgeReservation(t)) {
Train *re_reserve_train = GetTrainForReservation(t, FindFirstTrack(GetAcrossTunnelBridgeReservationTrackBits(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)); AddSideToSignalBuffer(tile_exit, INVALID_DIAGDIR, GetTileOwner(tile));
YapfNotifyTrackLayoutChange(tile, track); YapfNotifyTrackLayoutChange(tile, track);
YapfNotifyTrackLayoutChange(tile_exit, 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)); DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
for (Train *re_reserve_train : re_reserve_trains) { for (Train *re_reserve_train : re_reserve_trains) {
ReReserveTrainPath(re_reserve_train); ReReserveTrainPath(re_reserve_train);
@ -2095,7 +2098,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1
} }
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
Company *c = Company::Get(GetTileOwner(tile)); Company *c = Company::Get(GetTileOwner(tile));
c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, tile, end); c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, end);
ClearBridgeTunnelSignalSimulation(end, tile); ClearBridgeTunnelSignalSimulation(end, tile);
ClearBridgeTunnelSignalSimulation(tile, end); ClearBridgeTunnelSignalSimulation(tile, end);
MarkBridgeOrTunnelDirty(tile); MarkBridgeOrTunnelDirty(tile);

@ -29,6 +29,7 @@
#include "../station_base.h" #include "../station_base.h"
#include "../waypoint_base.h" #include "../waypoint_base.h"
#include "../roadstop_base.h" #include "../roadstop_base.h"
#include "../tunnelbridge.h"
#include "../tunnelbridge_map.h" #include "../tunnelbridge_map.h"
#include "../pathfinder/yapf/yapf_cache.h" #include "../pathfinder/yapf/yapf_cache.h"
#include "../elrail_func.h" #include "../elrail_func.h"
@ -3637,6 +3638,22 @@ bool AfterLoadGame()
c->settings.simulated_wormhole_signals = _settings_game.construction.old_simulated_wormhole_signals; 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)) { if (SlXvIsFeatureMissing(XSLFI_CUSTOM_BRIDGE_HEADS)) {
/* ensure that previously unused custom bridge-head bits are cleared */ /* ensure that previously unused custom bridge-head bits are cleared */

@ -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_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_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_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_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_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 }, { XSLFI_TT_WAIT_IN_DEPOT, XSCF_NULL, 1, 1, "tt_wait_in_depot", nullptr, nullptr, nullptr },

@ -1482,14 +1482,6 @@ static bool InvalidateCompanyWindow(int32 p1)
return true; return true;
} }
static bool SimulatedWormholeSignalsChanged(int32 p1)
{
extern void AfterLoadCompanyStats();
AfterLoadCompanyStats();
MarkWholeScreenDirty();
return true;
}
static bool EnableSingleVehSharedOrderGuiChanged(int32) static bool EnableSingleVehSharedOrderGuiChanged(int32)
{ {
for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) { for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {

@ -11,7 +11,6 @@ static bool UpdateIntervalTrains(int32 p1);
static bool UpdateIntervalRoadVeh(int32 p1); static bool UpdateIntervalRoadVeh(int32 p1);
static bool UpdateIntervalShips(int32 p1); static bool UpdateIntervalShips(int32 p1);
static bool UpdateIntervalAircraft(int32 p1); static bool UpdateIntervalAircraft(int32 p1);
static bool SimulatedWormholeSignalsChanged(int32 p1);
static const SettingDesc _company_settings[] = { static const SettingDesc _company_settings[] = {
[post-amble] [post-amble]
@ -269,8 +268,8 @@ def = 4
min = 1 min = 1
max = 16 max = 16
str = STR_CONFIG_SETTING_SIMULATE_SIGNALS str = STR_CONFIG_SETTING_SIMULATE_SIGNALS
strhelp = STR_CONFIG_SETTING_SIMULATE_SIGNALS_HELPTEXT
strval = STR_CONFIG_SETTING_SIMULATE_SIGNALS_VALUE strval = STR_CONFIG_SETTING_SIMULATE_SIGNALS_VALUE
proc = SimulatedWormholeSignalsChanged
cat = SC_ADVANCED cat = SC_ADVANCED
patxname = ""simulated_wormhole_signals"" patxname = ""simulated_wormhole_signals""

@ -13,8 +13,9 @@
#include "map_func.h" #include "map_func.h"
#include "tile_map.h" #include "tile_map.h"
uint GetTunnelBridgeSignalSimulationSpacing(TileIndex tile); uint GetTunnelBridgeSignalSimulationSpacingTarget(Owner owner);
uint GetTunnelBridgeSignalSimulationSignalCount(Company *c, TileIndex begin, TileIndex end); 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) * Calculates the length of a tunnel or a bridge (without end tiles)

@ -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)) { if (Company::IsValidID(owner)) {
return Company::Get(owner)->settings.simulated_wormhole_signals; return Company::Get(owner)->settings.simulated_wormhole_signals;
} else { } 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<int>(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. * 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 begin The begin of the tunnel or bridge.
* @param end The end of the tunnel or bridge. * @param end The end of the tunnel or bridge.
* @pre IsTunnelBridgeWithSignalSimulation(begin) * @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; if (IsTunnelBridgeSignalSimulationBidirectional(begin)) result *= 2;
return result; return result;
} }
@ -1254,7 +1274,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
Company *c = Company::Get(owner); Company *c = Company::Get(owner);
c->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR; c->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
if (IsTunnelBridgeWithSignalSimulation(tile)) { // handle tunnel/bridge signals. if (IsTunnelBridgeWithSignalSimulation(tile)) { // handle tunnel/bridge signals.
c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, tile, endtile); c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, endtile);
} }
DirtyCompanyInfrastructureWindows(owner); DirtyCompanyInfrastructureWindows(owner);
} }
@ -2730,9 +2750,9 @@ static void UpdateRailTunnelBridgeInfrastructure(Company *c, TileIndex begin, Ti
if (IsTunnelBridgeWithSignalSimulation(begin)) { if (IsTunnelBridgeWithSignalSimulation(begin)) {
if (add) { if (add) {
c->infrastructure.signal += GetTunnelBridgeSignalSimulationSignalCount(c, begin, end); c->infrastructure.signal += GetTunnelBridgeSignalSimulationSignalCount(begin, end);
} else { } else {
c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(c, begin, end); c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(begin, end);
} }
} }
} }

@ -530,6 +530,18 @@ static inline void SetTunnelBridgeExitSignalAspect(TileIndex t, uint8 aspect)
SB(_m[t].m3, 3, 3, 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) static inline Trackdir GetTunnelBridgeExitTrackdir(TileIndex t, DiagDirection tunnel_bridge_dir)
{ {
return TrackEnterdirToTrackdir((Track)FIND_FIRST_BIT(GetAcrossTunnelBridgeTrackBits(t)), ReverseDiagDir(tunnel_bridge_dir)); return TrackEnterdirToTrackdir((Track)FIND_FIRST_BIT(GetAcrossTunnelBridgeTrackBits(t)), ReverseDiagDir(tunnel_bridge_dir));

Loading…
Cancel
Save