@ -4001,11 +4001,12 @@ static bool HasLongReservePbsSignalOnTrackdir(Train* v, TileIndex tile, Trackdir
return false ;
}
static TileIndex CheckLongReservePbsTunnelBridgeOnTrackdir ( Train * v , TileIndex tile , Trackdir trackdir )
static TileIndex CheckLongReservePbsTunnelBridgeOnTrackdir ( Train * v , TileIndex tile , Trackdir trackdir , bool restricted_only = false )
{
if ( _settings_game . vehicle . train_braking_model = = TBM_REALISTIC & & IsTunnelBridgeSignalSimulationEntranceTile ( tile ) & & TrackdirEntersTunnelBridge ( tile , trackdir ) ) {
TileIndex end = GetOtherTunnelBridgeEnd ( tile ) ;
if ( restricted_only & & ! IsTunnelBridgeRestrictedSignal ( end ) ) return INVALID_TILE ;
int raw_free_tiles ;
if ( v - > lookahead ! = nullptr & & v - > lookahead - > reservation_end_tile = = tile & & v - > lookahead - > reservation_end_trackdir = = trackdir ) { // TODO fix loop case
if ( HasBit ( v - > lookahead - > flags , TRLF_TB_EXIT_FREE ) ) {
@ -4033,7 +4034,7 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
const bool long_enough = IsReservationLookAheadLongEnough ( v , lookahead_state ) ;
// We reserved up to a unoccupied signalled tunnel/bridge, reserve past it as well. recursion
TileIndex exit_tile = long_enough ? INVALID_TILE : CheckLongReservePbsTunnelBridgeOnTrackdir( v , tile , td ) ;
TileIndex exit_tile = CheckLongReservePbsTunnelBridgeOnTrackdir( v , tile , td , long_enough ) ;
if ( exit_tile ! = INVALID_TILE ) {
CFollowTrackRail ft ( v ) ;
Trackdir exit_td = GetTunnelBridgeExitTrackdir ( exit_tile ) ;
@ -4042,6 +4043,23 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
if ( ( ft . m_new_td_bits & TrackBitsToTrackdirBits ( reserved_bits ) ) = = TRACKDIR_BIT_NONE ) {
/* next tile is not reserved */
bool long_reserve = ! long_enough ;
if ( IsTunnelBridgeRestrictedSignal ( exit_tile ) ) {
const TraceRestrictProgram * prog = GetExistingTraceRestrictProgram ( exit_tile , TrackdirToTrack ( exit_td ) ) ;
if ( prog & & prog - > actions_used_flags & ( TRPAUF_WAIT_AT_PBS | TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_ACQUIRE_ON_RES | TRPAUF_LONG_RESERVE ) ) {
TraceRestrictProgramResult out ;
if ( long_reserve ) out . flags | = TRPRF_LONG_RESERVE ;
TraceRestrictProgramInput input ( exit_tile , exit_td , nullptr , nullptr ) ;
input . permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_ACQUIRE_ON_RES ;
prog - > Execute ( v , input , out ) ;
if ( out . flags & TRPRF_WAIT_AT_PBS ) {
return ;
}
long_reserve = ( out . flags & TRPRF_LONG_RESERVE ) ;
}
}
if ( ! long_reserve ) return ;
SignalState exit_state = GetTunnelBridgeExitSignalState ( exit_tile ) ;
/* reserve exit to make contiguous reservation */
@ -4051,10 +4069,6 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
SetTunnelReservation ( exit_tile , true ) ;
}
SetTunnelBridgeExitSignalState ( exit_tile , SIGNAL_STATE_GREEN ) ;
if ( _extra_aspects > 0 ) {
SetTunnelBridgeExitSignalAspect ( exit_tile , 0 ) ;
UpdateAspectDeferred ( exit_tile , GetTunnelBridgeExitTrackdir ( exit_tile ) ) ;
}
ChooseTrainTrack ( v , ft . m_new_tile , ft . m_exitdir , TrackdirBitsToTrackBits ( ft . m_new_td_bits ) , CTTF_NO_LOOKAHEAD_VALIDATE | ( force_res ? CTTF_FORCE_RES : CTTF_NONE ) , nullptr , lookahead_state ) ;
@ -4067,6 +4081,10 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
}
SetTunnelBridgeExitSignalState ( exit_tile , exit_state ) ;
} else {
if ( _extra_aspects > 0 ) {
SetTunnelBridgeExitSignalAspect ( exit_tile , 0 ) ;
UpdateAspectDeferred ( exit_tile , GetTunnelBridgeExitTrackdir ( exit_tile ) ) ;
}
MarkTileDirtyByTile ( exit_tile , VMDF_NOT_MAP_MODE ) ;
}
}
@ -4995,6 +5013,23 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
}
}
auto try_exit_reservation = [ & ] ( ) - > bool {
if ( IsTunnelBridgeRestrictedSignal ( tile ) ) {
const TraceRestrictProgram * prog = GetExistingTraceRestrictProgram ( tile , TrackdirToTrack ( td ) ) ;
if ( prog & & prog - > actions_used_flags & ( TRPAUF_WAIT_AT_PBS | TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_ACQUIRE_ON_RES ) ) {
TraceRestrictProgramResult out ;
TraceRestrictProgramInput input ( tile , td , nullptr , nullptr ) ;
input . permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_ACQUIRE_ON_RES ;
prog - > Execute ( t , input , out ) ;
if ( out . flags & TRPRF_WAIT_AT_PBS ) {
return false ;
}
}
}
return TryPathReserve ( t ) ;
} ;
if ( _settings_game . vehicle . train_braking_model = = TBM_REALISTIC ) {
if ( unlikely ( t - > lookahead = = nullptr ) ) {
FillTrainReservationLookAhead ( t ) ;
@ -5004,10 +5039,6 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
if ( t - > lookahead - > reservation_end_tile = = t - > tile & & t - > lookahead - > reservation_end_position - t - > lookahead - > current_position < = ( int ) TILE_SIZE & & ! HasBit ( t - > lookahead - > flags , TRLF_TB_EXIT_FREE ) ) return false ;
SignalState exit_state = GetTunnelBridgeExitSignalState ( tile ) ;
SetTunnelBridgeExitSignalState ( tile , SIGNAL_STATE_GREEN ) ;
if ( _extra_aspects > 0 ) {
SetTunnelBridgeExitSignalAspect ( tile , 0 ) ;
UpdateAspectDeferred ( tile , GetTunnelBridgeExitTrackdir ( tile ) ) ;
}
/* Get tile margin before changing vehicle direction */
const int tile_margin = GetTileMarginInFrontOfTrain ( t ) ;
@ -5018,7 +5049,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
t - > tile = tile ;
t - > track = TRACK_BIT_WORMHOLE ;
t - > direction = TrackdirToDirection ( td ) ;
bool ok = TryPathReserve( t ) ;
bool ok = try_exit_reservation( ) ;
if ( ! ok & & ( t - > lookahead - > reservation_end_position > = t - > lookahead - > current_position & & t - > lookahead - > reservation_end_position > t - > lookahead - > current_position + tile_margin ) ) {
/* Reservation was made previously and was valid then.
* To avoid unexpected braking due to stopping short of the lookahead end ,
@ -5026,6 +5057,10 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
ok = true ;
}
if ( ok ) {
if ( _extra_aspects > 0 ) {
SetTunnelBridgeExitSignalAspect ( tile , 0 ) ;
UpdateAspectDeferred ( tile , GetTunnelBridgeExitTrackdir ( tile ) ) ;
}
mark_dirty = true ;
if ( t - > lookahead - > reservation_end_tile = = veh_orig_tile & & t - > lookahead - > reservation_end_position - t - > lookahead - > current_position < = ( int ) TILE_SIZE ) {
/* Less than a tile of lookahead, advance tile */
@ -5057,7 +5092,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
t - > tile = tile ;
t - > track = TRACK_BIT_WORMHOLE ;
t - > direction = TrackdirToDirection ( td ) ;
bool ok = TryPathReserve( t ) ;
bool ok = try_exit_reservation( ) ;
t - > tile = veh_orig_tile ;
t - > track = veh_orig_track ;
t - > direction = veh_orig_direction ;
@ -5170,6 +5205,21 @@ void DecrementPendingSpeedRestrictions(Train *v)
}
}
void HandleTraceRestrictSpeedRestrictionAction ( const TraceRestrictProgramResult & out , Train * v , Trackdir signal_td )
{
if ( out . flags & TRPRF_SPEED_RESTRICTION_SET ) {
SetBit ( v - > flags , VRF_PENDING_SPEED_RESTRICTION ) ;
auto range = pending_speed_restriction_change_map . equal_range ( v - > index ) ;
for ( auto it = range . first ; it ! = range . second ; + + it ) {
if ( ( uint16 ) ( out . speed_restriction + 0xFFFF ) < ( uint16 ) ( it - > second . new_speed + 0xFFFF ) ) it - > second . new_speed = out . speed_restriction ;
}
uint16 flags = 0 ;
if ( IsDiagonalTrack ( TrackdirToTrack ( signal_td ) ) ) SetBit ( flags , PSRCF_DIAGONAL ) ;
pending_speed_restriction_change_map . insert ( { v - > index , { ( uint16 ) ( v - > gcache . cached_total_length + ( HasBit ( flags , PSRCF_DIAGONAL ) ? 8 : 4 ) ) , out . speed_restriction , v - > speed_restriction , flags } } ) ;
if ( ( uint16 ) ( out . speed_restriction + 0xFFFF ) < ( uint16 ) ( v - > speed_restriction + 0xFFFF ) ) v - > speed_restriction = out . speed_restriction ;
}
}
/**
* Move a vehicle chain one movement stop forwards .
* @ param v First vehicle to move .
@ -5366,17 +5416,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
v - > reverse_distance = v - > gcache . cached_total_length + ( IsDiagonalTrack ( TrackdirToTrack ( dir ) ) ? 16 : 8 ) ;
SetWindowDirty ( WC_VEHICLE_VIEW , v - > index ) ;
}
if ( out . flags & TRPRF_SPEED_RESTRICTION_SET ) {
SetBit ( v - > flags , VRF_PENDING_SPEED_RESTRICTION ) ;
auto range = pending_speed_restriction_change_map . equal_range ( v - > index ) ;
for ( auto it = range . first ; it ! = range . second ; + + it ) {
if ( ( uint16 ) ( out . speed_restriction + 0xFFFF ) < ( uint16 ) ( it - > second . new_speed + 0xFFFF ) ) it - > second . new_speed = out . speed_restriction ;
}
uint16 flags = 0 ;
if ( IsDiagonalTrack ( TrackdirToTrack ( dir ) ) ) SetBit ( flags , PSRCF_DIAGONAL ) ;
pending_speed_restriction_change_map . insert ( { v - > index , { ( uint16 ) ( v - > gcache . cached_total_length + ( HasBit ( flags , PSRCF_DIAGONAL ) ? 8 : 4 ) ) , out . speed_restriction , v - > speed_restriction , flags } } ) ;
if ( ( uint16 ) ( out . speed_restriction + 0xFFFF ) < ( uint16 ) ( v - > speed_restriction + 0xFFFF ) ) v - > speed_restriction = out . speed_restriction ;
}
HandleTraceRestrictSpeedRestrictionAction ( out , v , dir ) ;
}
}
}
@ -5519,6 +5559,31 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
/* Entered wormhole set counters. */
v - > wait_counter = ( TILE_SIZE * simulated_wormhole_signals ) - TILE_SIZE ;
v - > tunnel_bridge_signal_num = 0 ;
if ( v - > IsFrontEngine ( ) & & IsTunnelBridgeSignalSimulationEntrance ( old_tile ) & & IsTunnelBridgeRestrictedSignal ( old_tile ) ) {
const Trackdir trackdir = GetTunnelBridgeEntranceTrackdir ( old_tile ) ;
const TraceRestrictProgram * prog = GetExistingTraceRestrictProgram ( old_tile , TrackdirToTrack ( trackdir ) ) ;
if ( prog & & prog - > actions_used_flags & ( TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_SPEED_RESTRICTION | TRPAUF_CHANGE_COUNTER ) ) {
TraceRestrictProgramResult out ;
TraceRestrictProgramInput input ( old_tile , trackdir , nullptr , nullptr ) ;
input . permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_RELEASE_FRONT | TRPISP_CHANGE_COUNTER ;
prog - > Execute ( v , input , out ) ;
HandleTraceRestrictSpeedRestrictionAction ( out , v , trackdir ) ;
}
}
if ( v - > Next ( ) = = nullptr & & IsTunnelBridgeSignalSimulationEntrance ( old_tile ) & & IsTunnelBridgeRestrictedSignal ( old_tile ) ) {
const Trackdir trackdir = GetTunnelBridgeEntranceTrackdir ( old_tile ) ;
const Track track = TrackdirToTrack ( trackdir ) ;
const TraceRestrictProgram * prog = GetExistingTraceRestrictProgram ( old_tile , track ) ;
if ( prog & & prog - > actions_used_flags & TRPAUF_SLOT_RELEASE_BACK ) {
TraceRestrictProgramResult out ;
TraceRestrictProgramInput input ( old_tile , trackdir , nullptr , nullptr ) ;
input . permitted_slot_operations = TRPISP_RELEASE_BACK ;
prog - > Execute ( first , input , out ) ;
}
}
}
uint distance = v - > wait_counter ;
@ -5534,6 +5599,17 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
return false ;
}
leaving = true ;
if ( IsTunnelBridgeRestrictedSignal ( gp . new_tile ) & & IsTunnelBridgeSignalSimulationExit ( gp . new_tile ) ) {
const Trackdir trackdir = GetTunnelBridgeExitTrackdir ( gp . new_tile ) ;
const TraceRestrictProgram * prog = GetExistingTraceRestrictProgram ( gp . new_tile , TrackdirToTrack ( trackdir ) ) ;
if ( prog & & prog - > actions_used_flags & ( TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_SPEED_RESTRICTION | TRPAUF_CHANGE_COUNTER ) ) {
TraceRestrictProgramResult out ;
TraceRestrictProgramInput input ( gp . new_tile , trackdir , nullptr , nullptr ) ;
input . permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_RELEASE_FRONT | TRPISP_CHANGE_COUNTER ;
prog - > Execute ( v , input , out ) ;
HandleTraceRestrictSpeedRestrictionAction ( out , v , trackdir ) ;
}
}
} else {
if ( IsTooCloseBehindTrain ( v , gp . new_tile , v - > wait_counter , distance = = 0 ) ) {
if ( distance = = 0 ) v - > wait_counter = 0 ;
@ -5765,6 +5841,22 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
}
}
}
if ( IsTileType ( gp . old_tile , MP_TUNNELBRIDGE ) & & IsTunnelBridgeSignalSimulationExit ( gp . old_tile ) & & IsTunnelBridgeRestrictedSignal ( gp . old_tile ) ) {
const TrackdirBits rev_tracks = TrackBitsToTrackdirBits ( GetTunnelBridgeTrackBits ( gp . old_tile ) ) & DiagdirReachesTrackdirs ( ReverseDiagDir ( enterdir ) ) ;
const Trackdir rev_trackdir = FindFirstTrackdir ( rev_tracks ) ;
const Track track = TrackdirToTrack ( rev_trackdir ) ;
if ( TrackdirEntersTunnelBridge ( gp . old_tile , rev_trackdir ) ) {
const TraceRestrictProgram * prog = GetExistingTraceRestrictProgram ( gp . old_tile , track ) ;
if ( prog & & prog - > actions_used_flags & TRPAUF_SLOT_RELEASE_BACK ) {
TraceRestrictProgramResult out ;
TraceRestrictProgramInput input ( gp . old_tile , ReverseTrackdir ( rev_trackdir ) , nullptr , nullptr ) ;
input . permitted_slot_operations = TRPISP_RELEASE_BACK ;
prog - > Execute ( first , input , out ) ;
}
}
}
}
}