diff --git a/docs/landscape.html b/docs/landscape.html
index c8886be7d8..328f07ab0c 100644
--- a/docs/landscape.html
+++ b/docs/landscape.html
@@ -1735,6 +1735,7 @@
- m2 bit 15: for bridge entrances only: storage for visual red/green state of signals starting from 15 is allocated outside the map array
- m2 bits 14..4: for bridge entrances only: for signals 0..10 on bridge, signal is visually red if corresponding bit in 4..14 is set
+ - m3 bit 6: the entrance and/or exit signals on this tile are restricted (tracerestrict patch)
- m3 bits 5..3: entrance signal aspect (only valid if signal is present and not red, and multi-aspect signalling is in effect)
- m3 bits 2..0: exit signal aspect (only valid if signal is present and not red, and multi-aspect signalling is in effect)
- m6 bit 7: set = exit signal shows green, clear = exit signal shows red
diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html
index de2d94fb0e..19b7309117 100644
--- a/docs/landscape_grid.html
+++ b/docs/landscape_grid.html
@@ -287,7 +287,7 @@ the array so you can quickly see what is used and what is not.
tunnel entrance |
OOO XXXXX |
PPPP PPPP PPPP PPPP |
- XXXX OOOO OO PPPPPP |
+ XXXX OOOO OP PPPPPP |
OOXX XXXX |
OPPX XX XX |
PPOO OOPP |
diff --git a/src/map.cpp b/src/map.cpp
index 4778fd9c5a..aa59cc3c13 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -572,6 +572,7 @@ void DumpMapStats(char *b, const char *last)
if (IsTunnelBridgeWithSignalSimulation(t)) {
bucket |= TBB_SIGNALLED;
if (IsTunnelBridgeSignalSimulationBidirectional(t)) bucket |= TBB_SIGNALLED_BIDI;
+ if (IsTunnelBridgeRestrictedSignal(t)) restricted_signals++;
}
if (GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD) {
if (HasTileRoadType(t, RTT_ROAD)) bucket |= TBB_ROAD;
diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp
index a4a2096540..bd192255ef 100644
--- a/src/pathfinder/yapf/yapf_costrail.hpp
+++ b/src/pathfinder/yapf/yapf_costrail.hpp
@@ -176,6 +176,13 @@ private:
IsRestrictedSignal(tile);
}
+ // returns true if ExecuteTunnelBridgeTraceRestrict should be called
+ inline bool ShouldCheckTunnelBridgeTraceRestrict(Node& n, TileIndex tile)
+ {
+ return n.m_num_signals_passed < m_sig_look_ahead_costs.size() &&
+ IsTunnelBridgeRestrictedSignal(tile);
+ }
+
/**
* This is called to retrieve the previous signal, as required
* This is not run all the time as it is somewhat expensive and most restrictions will not test for the previous signal
@@ -312,6 +319,22 @@ private:
return false;
}
+ // returns true if dead end bit has been set
+ inline bool ExecuteTunnelBridgeTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out)
+ {
+ const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir));
+ TraceRestrictProgramActionsUsedFlags flags_to_check = TRPAUF_PF;
+ if (prog && prog->actions_used_flags & flags_to_check) {
+ prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir, &TraceRestrictPreviousSignalCallback, &n), out);
+ if (out.flags & TRPRF_DENY) {
+ n.m_segment->m_end_segment_reason |= ESRB_DEAD_END;
+ return true;
+ }
+ cost += out.penalty;
+ }
+ return false;
+ }
+
public:
int SignalCost(Node &n, TileIndex tile, Trackdir trackdir)
{
@@ -417,17 +440,27 @@ public:
}
}
}
- if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExitOnly(tile) && TrackdirEntersTunnelBridge(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;
- }
- if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgeEffectivelyPBS(tile) && TrackdirExitsTunnelBridge(tile, trackdir)) {
- /* Exiting a PBS signalled tunnel/bridge, record the last non-reserve through signal */
- n.m_last_non_reserve_through_signal_tile = tile;
- n.m_last_non_reserve_through_signal_td = trackdir;
- }
- if (n.flags_u.flags_s.m_reverse_pending && IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationEntrance(tile)) {
- n.m_segment->m_end_segment_reason |= ESRB_SAFE_TILE;
+ if (IsTunnelBridgeWithSignalSimulation(tile)) {
+ const bool entering = TrackdirEntersTunnelBridge(tile, trackdir);
+ const bool exiting = TrackdirExitsTunnelBridge(tile, trackdir);
+ if (IsTunnelBridgeSignalSimulationExitOnly(tile) && entering) {
+ /* 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;
+ }
+ if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgeEffectivelyPBS(tile) && exiting) {
+ /* Exiting a PBS signalled tunnel/bridge, record the last non-reserve through signal */
+ n.m_last_non_reserve_through_signal_tile = tile;
+ n.m_last_non_reserve_through_signal_td = trackdir;
+ }
+ if (ShouldCheckTunnelBridgeTraceRestrict(n, tile)) {
+ TraceRestrictProgramResult out;
+ if (ExecuteTunnelBridgeTraceRestrict(n, tile, trackdir, cost, out)) {
+ return -1;
+ }
+ }
+ if (n.flags_u.flags_s.m_reverse_pending && entering && IsTunnelBridgeSignalSimulationEntrance(tile)) {
+ n.m_segment->m_end_segment_reason |= ESRB_SAFE_TILE;
+ }
}
return cost;
}
diff --git a/src/pbs.cpp b/src/pbs.cpp
index 6b52f10dae..35cd42e2ac 100644
--- a/src/pbs.cpp
+++ b/src/pbs.cpp
@@ -353,6 +353,39 @@ static int LookaheadTileHeightForChunnel(int length, int offset)
return 0;
}
+static uint16 ApplyTunnelBridgeLookaheadSignalSpeedRestriction(TileIndex tile, Trackdir trackdir, const Train *v,
+ uint16 initial_speed_restriction, TrainReservationLookAhead *lookahead, int offset, int16 z)
+{
+ uint16 speed_restriction = initial_speed_restriction;
+
+ if (v != nullptr && IsTunnelBridgeRestrictedSignal(tile)) {
+ if (trackdir == INVALID_TRACKDIR) {
+ trackdir = GetTunnelBridgeExitTrackdir(tile);
+ }
+ const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir));
+ if (prog && prog->actions_used_flags & TRPAUF_SPEED_RESTRICTION) {
+ TraceRestrictProgramResult out;
+ TraceRestrictProgramInput input(tile, trackdir, nullptr, nullptr);
+ prog->Execute(v, input, out);
+ if (out.flags & TRPRF_SPEED_RESTRICTION_SET) {
+ int duration;
+ if (TrackdirEntersTunnelBridge(tile, trackdir)) {
+ duration = 4 + (IsDiagonalTrackdir(trackdir) ? 16 : 8);
+ } else {
+ duration = 4;
+ }
+ lookahead->AddSpeedRestriction(out.speed_restriction, offset, duration, z);
+ if (out.speed_restriction != 0 && (speed_restriction == 0 || out.speed_restriction < speed_restriction)) {
+ /* lower of the speed restrictions before or after the signal */
+ speed_restriction = out.speed_restriction;
+ }
+ }
+ }
+ }
+
+ return speed_restriction;
+}
+
/** Follow a reservation starting from a specific tile to the end. */
static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, FollowReservationFlags flags, const Train *v, TrainReservationLookAhead *lookahead)
{
@@ -525,8 +558,10 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
const int spacing = GetTunnelBridgeSignalSimulationSpacing(tile);
const int signals = length / spacing;
+ uint16 speed_restriction = ApplyTunnelBridgeLookaheadSignalSpeedRestriction(tile, trackdir, v, lookahead->speed_restriction, lookahead, 0, z);
+
uint16 signal_speed = GetRailTypeInfo(rt)->max_speed;
- if (signal_speed == 0 || (lookahead->speed_restriction != 0 && lookahead->speed_restriction < signal_speed)) signal_speed = lookahead->speed_restriction;
+ if (signal_speed == 0 || (speed_restriction != 0 && speed_restriction < signal_speed)) signal_speed = speed_restriction;
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
/* Entrance signal */
@@ -548,7 +583,16 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
}
/* Exit signal */
- const int end_offset = start_offset + (TILE_SIZE * length) /* + ((DiagDirToDiagTrackBits(GetTunnelBridgeDirection(end)) & GetTunnelBridgeTrackBits(end)) ? 16 : 8)*/;
+ const int end_offset = start_offset + (TILE_SIZE * length);
+
+ uint16 exit_speed_restriction = ApplyTunnelBridgeLookaheadSignalSpeedRestriction(end, INVALID_TRACKDIR, v, lookahead->speed_restriction, lookahead, end_offset, z);
+ if (exit_speed_restriction != speed_restriction) {
+ speed_restriction = exit_speed_restriction;
+ signal_speed = GetRailTypeInfo(rt)->max_speed;
+ if (signal_speed == 0 || (speed_restriction != 0 && speed_restriction < signal_speed)) signal_speed = speed_restriction;
+ if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
+ }
+
lookahead->AddSignal(signal_speed, end_offset, z);
lookahead->SetNextExtendPositionIfUnset();
@@ -580,7 +624,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
lookahead->AddReverse(z);
}
if (out.flags & TRPRF_SPEED_RESTRICTION_SET) {
- lookahead->AddSpeedRestriction(out.speed_restriction, z);
+ lookahead->AddSpeedRestriction(out.speed_restriction, 0, 0, z);
if (out.speed_restriction != 0 && (speed_restriction == 0 || out.speed_restriction < speed_restriction)) {
/* lower of the speed restrictions before or after the signal */
speed_restriction = out.speed_restriction;
@@ -869,12 +913,14 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
if (IsTunnel(t->tile) && Tunnel::GetByTile(t->tile)->is_chunnel) SetBit(t->lookahead->flags, TRLF_CHUNNEL);
if (IsTunnelBridgeSignalSimulationEntrance(t->tile)) {
- uint16 bridge_speed = IsBridge(t->tile) ? GetBridgeSpec(GetBridgeType(t->tile))->speed : 0;
- const int length = GetTunnelBridgeLength(t->tile, GetOtherTunnelBridgeEnd(t->tile));
+ const uint16 bridge_speed = IsBridge(t->tile) ? GetBridgeSpec(GetBridgeType(t->tile))->speed : 0;
+ const TileIndex end = GetOtherTunnelBridgeEnd(t->tile);
+ const int length = GetTunnelBridgeLength(t->tile, end);
const int spacing = GetTunnelBridgeSignalSimulationSpacing(t->tile);
const int signals = length / spacing;
- uint16 signal_speed = GetRailTypeInfo(GetRailTypeByTrack(t->tile, TrackdirToTrack(t->lookahead->reservation_end_trackdir)))->max_speed;
+ const RailType rt = GetRailTypeByTrack(t->tile, TrackdirToTrack(t->lookahead->reservation_end_trackdir));
+ uint16 signal_speed = GetRailTypeInfo(rt)->max_speed;
if (signal_speed == 0 || (t->speed_restriction != 0 && t->speed_restriction < signal_speed)) signal_speed = t->speed_restriction;
if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
@@ -889,6 +935,14 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
/* Exit signal */
const int end_offset = TILE_SIZE * length;
+
+ uint16 exit_speed_restriction = ApplyTunnelBridgeLookaheadSignalSpeedRestriction(end, INVALID_TRACKDIR, t, t->speed_restriction, t->lookahead.get(), end_offset, z);
+ if (exit_speed_restriction != t->speed_restriction) {
+ signal_speed = GetRailTypeInfo(rt)->max_speed;
+ if (signal_speed == 0 || (exit_speed_restriction != 0 && exit_speed_restriction < signal_speed)) signal_speed = exit_speed_restriction;
+ if (signal_speed == 0 || (bridge_speed != 0 && bridge_speed < signal_speed)) signal_speed = bridge_speed;
+ }
+
t->lookahead->AddSignal(signal_speed, end_offset, z);
t->lookahead->SetNextExtendPositionIfUnset();
@@ -1157,10 +1211,8 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
}
- if (IsRailTunnelBridgeTile(tile) && IsTrackAcrossTunnelBridge(tile, TrackdirToTrack(trackdir))) {
- if (IsTunnelBridgeSignalSimulationEntrance(tile)) {
- return true;
- }
+ if (IsTunnelBridgeSignalSimulationEntranceTile(tile) && IsTrackAcrossTunnelBridge(tile, TrackdirToTrack(trackdir))) {
+ return true;
}
/* Check next tile. For performance reasons, we check for 90 degree turns ourself. */
@@ -1229,8 +1281,8 @@ 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;
- auto pbs_res_end_wait_test = [v, restricted_signal_info](TileIndex t, Trackdir td) -> bool {
- if (IsRestrictedSignal(t)) {
+ auto pbs_res_end_wait_test = [v, restricted_signal_info](TileIndex t, Trackdir td, bool tunnel_bridge) -> bool {
+ if (tunnel_bridge ? IsTunnelBridgeRestrictedSignal(t) : IsRestrictedSignal(t)) {
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(t, TrackdirToTrack(td));
if (restricted_signal_info && prog) {
restricted_signal_info->tile = t;
@@ -1250,11 +1302,12 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
};
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) {
- return pbs_res_end_wait_test(tile, trackdir);
+ return pbs_res_end_wait_test(tile, trackdir, false);
}
if (IsTunnelBridgeSignalSimulationEntranceTile(tile) && IsTrackAcrossTunnelBridge(tile, TrackdirToTrack(trackdir))) {
- if (IsTunnelBridgeSignalSimulationBidirectional(tile)) {
+ bool free = pbs_res_end_wait_test(tile, trackdir, true);
+ if (free && IsTunnelBridgeSignalSimulationBidirectional(tile)) {
TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
if (HasAcrossTunnelBridgeReservation(other_end) && GetTunnelBridgeExitSignalState(other_end) == SIGNAL_STATE_RED) return false;
Direction dir = DiagDirToDir(GetTunnelBridgeDirection(other_end));
@@ -1267,7 +1320,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
return nullptr;
})) return false;
}
- return true;
+ return free;
}
/* Check the next tile, if it's a PBS signal, it has to be free as well. */
@@ -1285,7 +1338,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
Trackdir td = FindFirstTrackdir(ft.m_new_td_bits);
/* PBS signal on next trackdir? */
if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) {
- return pbs_res_end_wait_test(ft.m_new_tile, td);
+ return pbs_res_end_wait_test(ft.m_new_tile, td, false);
}
}
diff --git a/src/pbs.h b/src/pbs.h
index 50d69027e5..398ecbd37d 100644
--- a/src/pbs.h
+++ b/src/pbs.h
@@ -114,10 +114,10 @@ struct TrainReservationLookAhead {
this->items.push_back({ end + offset, end + offset + duration, z_pos, speed, TRLIT_TRACK_SPEED });
}
- void AddSpeedRestriction(uint16 speed, int16 z_pos)
+ void AddSpeedRestriction(uint16 speed, int offset, int duration, int16 z_pos)
{
int end = this->RealEndPosition();
- this->items.push_back({ end, end, z_pos, speed, TRLIT_SPEED_RESTRICTION });
+ this->items.push_back({ end + offset, end + offset + duration, z_pos, speed, TRLIT_SPEED_RESTRICTION });
this->speed_restriction = speed;
}
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index 495c601196..cc3d50e389 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -2110,6 +2110,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1
}
}
if (flags & DC_EXEC) {
+ Track end_track = FindFirstTrack(GetAcrossTunnelBridgeTrackBits(end));
Company *c = Company::Get(GetTileOwner(tile));
c->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, end);
ClearBridgeTunnelSignalSimulation(end, tile);
@@ -2118,7 +2119,9 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1
AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile));
AddSideToSignalBuffer(end, INVALID_DIAGDIR, GetTileOwner(tile));
YapfNotifyTrackLayoutChange(tile, track);
- YapfNotifyTrackLayoutChange(end, track);
+ YapfNotifyTrackLayoutChange(end, end_track);
+ TraceRestrictNotifySignalRemoval(tile, track);
+ TraceRestrictNotifySignalRemoval(end, end_track);
DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
for (Train *v : re_reserve_trains) {
ReReserveTrainPath(v);
diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp
index 179612506e..6249ea7b6c 100644
--- a/src/rail_gui.cpp
+++ b/src/rail_gui.cpp
@@ -248,6 +248,9 @@ static void GenericPlaceSignals(TileIndex tile)
if (IsPlainRailTile(tile) && HasTrack(tile, track) && HasSignalOnTrack(tile, track)) {
ShowTraceRestrictProgramWindow(tile, track);
}
+ if (IsTunnelBridgeWithSignalSimulation(tile) && HasTrack(GetAcrossTunnelBridgeTrackBits(tile), track)) {
+ ShowTraceRestrictProgramWindow(tile, track);
+ }
return;
}
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index 4affa30050..85e4eeaec3 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -3971,6 +3971,14 @@ bool AfterLoadGame()
}
}
+ if (SlXvIsFeatureMissing(XSLFI_TRACE_RESTRICT_TUNBRIDGE)) {
+ for (TileIndex t = 0; t < map_size; t++) {
+ if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeWithSignalSimulation(t)) {
+ SetTunnelBridgeRestrictedSignal(t, false);
+ }
+ }
+ }
+
InitializeRoadGUI();
/* This needs to be done after conversion. */
diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp
index f23bc4223a..1399b169d7 100644
--- a/src/saveload/extended_ver_sl.cpp
+++ b/src/saveload/extended_ver_sl.cpp
@@ -80,6 +80,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_TRACE_RESTRICT_BRKCND, XSCF_NULL, 2, 2, "tracerestrict_braking_cond",nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_CTGRYCND,XSCF_NULL, 1, 1, "tracerestrict_ctgry_cond", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_PENCTRL, XSCF_NULL, 1, 1, "tracerestrict_pfpenctrl", nullptr, nullptr, nullptr },
+ { XSLFI_TRACE_RESTRICT_TUNBRIDGE,XSCF_NULL, 1, 1, "tracerestrict_sigtunbridge",nullptr, nullptr, nullptr },
{ XSLFI_PROG_SIGS, XSCF_NULL, 2, 2, "programmable_signals", nullptr, nullptr, "SPRG" },
{ XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", nullptr, nullptr, nullptr },
{ XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", nullptr, nullptr, nullptr },
diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h
index 52f74b1908..387fb34d05 100644
--- a/src/saveload/extended_ver_sl.h
+++ b/src/saveload/extended_ver_sl.h
@@ -34,6 +34,7 @@ enum SlXvFeatureIndex {
XSLFI_TRACE_RESTRICT_BRKCND, ///< Trace restrict: realistic braking related conditionals
XSLFI_TRACE_RESTRICT_CTGRYCND, ///< Trace restrict: category conditionals
XSLFI_TRACE_RESTRICT_PENCTRL, ///< Trace restrict: PF penalty control
+ XSLFI_TRACE_RESTRICT_TUNBRIDGE, ///< Trace restrict: restricted signalled tunnel/bridge support
XSLFI_PROG_SIGS, ///< programmable pre-signals patch
XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch
XSLFI_SAFER_CROSSINGS, ///< Safer level crossings
diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp
index 1f113dbaa7..0cb0c85571 100644
--- a/src/tracerestrict.cpp
+++ b/src/tracerestrict.cpp
@@ -1124,7 +1124,18 @@ void TraceRestrictSetIsSignalRestrictedBit(TileIndex t)
TraceRestrictMapping::iterator upper_bound = _tracerestrictprogram_mapping.lower_bound(MakeTraceRestrictRefId(t + 1, static_cast