Add tracerestrict PBS end signal conditional

This is for realistic braking long reserve
pull/217/head
Jonathan G Rennison 3 years ago
parent c17ec5f923
commit 35d720b0ad

@ -2773,6 +2773,9 @@ STR_TRACE_RESTRICT_VARIABLE_LOAD_PERCENT :load percentage
STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION :entry direction
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL :PBS entry signal
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG :entered signal of PBS block
STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL :PBS end signal
STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG :signal at current end of PBS reservation
STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG_WARN :signal at current end of PBS reservation {PUSH_COLOUR}{RED}(requires realistic braking){POP_COLOUR}
STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP :train group
STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :train in slot
STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY :slot occupancy

@ -178,14 +178,15 @@ private:
* 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
*/
static TileIndex TraceRestrictPreviousSignalCallback(const Train *v, const void *node_ptr)
static TileIndex TraceRestrictPreviousSignalCallback(const Train *v, const void *node_ptr, TraceRestrictPBSEntrySignalAuxField mode)
{
const Node *node = static_cast<const Node *>(node_ptr);
for (;;) {
TileIndex last_signal_tile = node->m_last_non_reserve_through_signal_tile;
if (last_signal_tile != INVALID_TILE) {
Trackdir last_signal_trackdir = node->m_last_non_reserve_through_signal_td;
if (HasPbsSignalOnTrackdir(last_signal_tile, last_signal_trackdir)) {
if (HasPbsSignalOnTrackdir(last_signal_tile, last_signal_trackdir) ||
(IsTileType(last_signal_tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(last_signal_tile) && IsTunnelBridgeEffectivelyPBS(last_signal_tile) && TrackdirExitsTunnelBridge(last_signal_tile, last_signal_trackdir))) {
return last_signal_tile;
} else {
return INVALID_TILE;
@ -208,15 +209,21 @@ private:
TileIndex origin_tile = node->GetTile();
Trackdir origin_trackdir = node->GetTrackdir();
TileIndex tile = v->tile;
Trackdir trackdir = v->GetVehicleTrackdir();
TileIndex candidate_tile = INVALID_TILE;
if (IsRailDepotTile(v->tile)) {
candidate_tile = v->tile;
} else if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) {
candidate_tile = v->tile;
TileIndex tile;
Trackdir trackdir;
if (mode == TRPESAF_RES_END && v->lookahead != nullptr) {
tile = v->lookahead->reservation_end_tile;
trackdir = v->lookahead->reservation_end_trackdir;
} else {
tile = v->tile;
trackdir = v->GetVehicleTrackdir();
if (IsRailDepotTile(v->tile)) {
candidate_tile = v->tile;
} else if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) {
candidate_tile = v->tile;
}
}
CFollowTrackRail ft(v);
@ -381,6 +388,11 @@ public:
/* 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;
}
return cost;
}

@ -213,7 +213,7 @@ public:
if (restricted_signal_info.tile != INVALID_TILE) {
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir));
if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_SLOT) {
extern TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *);
extern TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *, TraceRestrictPBSEntrySignalAuxField mode);
TraceRestrictProgramResult out;
TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, nullptr);

@ -1043,20 +1043,27 @@ CommandCost CheckTrainInTunnelBridgePreventsTrackModification(TileIndex start, T
* 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
*/
TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *)
TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *, TraceRestrictPBSEntrySignalAuxField mode)
{
if (IsRailDepotTile(v->tile)) {
return v->tile;
}
if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) {
return v->tile;
TileIndex tile;
Trackdir trackdir;
if (mode == TRPESAF_RES_END && v->lookahead != nullptr) {
tile = v->lookahead->reservation_end_tile;
trackdir = v->lookahead->reservation_end_trackdir;
} else {
if (IsRailDepotTile(v->tile)) {
return v->tile;
}
if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) {
return v->tile;
}
tile = v->tile;
trackdir = v->GetVehicleTrackdir();
}
// scan forwards from vehicle position, for the case that train is waiting at/approaching PBS signal
TileIndex tile = v->tile;
Trackdir trackdir = v->GetVehicleTrackdir();
CFollowTrackRail ft(v);
for (;;) {
@ -1070,6 +1077,10 @@ TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const vo
}
}
if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgeEffectivelyPBS(tile) && TrackdirExitsTunnelBridge(tile, trackdir)) {
return tile;
}
// advance to next tile
if (!ft.Follow(tile, trackdir)) {
// ran out of track

@ -76,6 +76,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_TRACE_RESTRICT_NEWSCTRL,XSCF_NULL, 1, 1, "tracerestrict_newsctrl", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_COUNTER, XSCF_NULL, 1, 1, "tracerestrict_counter", nullptr, nullptr, "TRRC" },
{ XSLFI_TRACE_RESTRICT_TIMEDATE,XSCF_NULL, 1, 1, "tracerestrict_timedate", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_BRKCND, XSCF_NULL, 1, 1, "tracerestrict_braking_cond",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 },

@ -30,6 +30,7 @@ enum SlXvFeatureIndex {
XSLFI_TRACE_RESTRICT_NEWSCTRL, ///< Trace restrict: news control
XSLFI_TRACE_RESTRICT_COUNTER, ///< Trace restrict: counters
XSLFI_TRACE_RESTRICT_TIMEDATE, ///< Trace restrict: time/date
XSLFI_TRACE_RESTRICT_BRKCND, ///< Trace restrict: realistic braking related conditionals
XSLFI_PROG_SIGS, ///< programmable pre-signals patch
XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch
XSLFI_SAFER_CROSSINGS, ///< Safer level crossings

@ -244,8 +244,8 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
static std::vector<TraceRestrictCondStackFlags> condstack;
condstack.clear();
bool have_previous_signal = false;
TileIndex previous_signal_tile = INVALID_TILE;
byte have_previous_signal = 0;
TileIndex previous_signal_tile[2];
size_t size = this->items.size();
for (size_t i = 0; i < size; i++) {
@ -344,17 +344,21 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
}
case TRIT_COND_PBS_ENTRY_SIGNAL: {
// TRVT_TILE_INDEX value type uses the next slot
// TRIT_COND_PBS_ENTRY_SIGNAL value type uses the next slot
i++;
TraceRestrictPBSEntrySignalAuxField mode = static_cast<TraceRestrictPBSEntrySignalAuxField>(GetTraceRestrictAuxField(item));
assert(mode == TRPESAF_VEH_POS || mode == TRPESAF_RES_END);
uint32_t signal_tile = this->items[i];
if (!have_previous_signal) {
if (!HasBit(have_previous_signal, mode)) {
if (input.previous_signal_callback) {
previous_signal_tile = input.previous_signal_callback(v, input.previous_signal_ptr);
previous_signal_tile[mode] = input.previous_signal_callback(v, input.previous_signal_ptr, mode);
} else {
previous_signal_tile[mode] = INVALID_TILE;
}
have_previous_signal = true;
SetBit(have_previous_signal, mode);
}
bool match = (signal_tile != INVALID_TILE)
&& (previous_signal_tile == signal_tile);
&& (previous_signal_tile[mode] == signal_tile);
result = TestBinaryConditionCommon(item, match);
break;
}

@ -330,6 +330,15 @@ enum TraceRestrictCounterCondOpField {
/* space up to 8 */
};
/**
* TraceRestrictItem auxiliary type field, for TRIT_COND_PBS_ENTRY_SIGNAL
*/
enum TraceRestrictPBSEntrySignalAuxField {
TRPESAF_VEH_POS = 0, ///< vehicle position signal
TRPESAF_RES_END = 1, ///< reservation end signal
/* space up to 3 */
};
/**
* TraceRestrictItem pathfinder penalty preset index
* This may not be shortened, only lengthened, as preset indexes are stored in save games
@ -394,7 +403,7 @@ DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputSlotPermissions)
* Execution input of a TraceRestrictProgram
*/
struct TraceRestrictProgramInput {
typedef TileIndex PreviousSignalProc(const Train *v, const void *ptr);
typedef TileIndex PreviousSignalProc(const Train *v, const void *ptr, TraceRestrictPBSEntrySignalAuxField mode);
TileIndex tile; ///< Tile of restrict signal, for direction testing
Trackdir trackdir; ///< Track direction on tile of restrict signal, for direction testing
@ -785,6 +794,7 @@ static inline bool IsTraceRestrictTypeAuxSubtype(TraceRestrictItemType type)
case TRIT_COND_PHYS_PROP:
case TRIT_COND_PHYS_RATIO:
case TRIT_COND_SLOT_OCCUPANCY:
case TRIT_COND_PBS_ENTRY_SIGNAL:
return true;
default:

@ -444,6 +444,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
STR_TRACE_RESTRICT_VARIABLE_LOAD_PERCENT,
STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION,
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL,
STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL,
STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP,
STR_TRACE_RESTRICT_VARIABLE_TRAIN_OWNER,
STR_TRACE_RESTRICT_VARIABLE_TRAIN_STATUS,
@ -469,7 +470,8 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
TRIT_COND_CARGO,
TRIT_COND_LOAD_PERCENT,
TRIT_COND_ENTRY_DIRECTION,
TRIT_COND_PBS_ENTRY_SIGNAL,
TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_VEH_POS << 16),
TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_RES_END << 16),
TRIT_COND_TRAIN_GROUP,
TRIT_COND_TRAIN_OWNER,
TRIT_COND_TRAIN_STATUS,
@ -494,9 +496,10 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
if (_settings_client.gui.show_adv_tracerestrict_features) {
*hide_mask = 0;
} else {
*hide_mask = is_conditional ? 0x3E0000 : 0x2F0;
*hide_mask = is_conditional ? 0x7C0000 : 0x2F0;
}
if (is_conditional && !_settings_game.game_time.time_in_minutes) *hide_mask |= 0x200000;
if (is_conditional && !_settings_game.game_time.time_in_minutes) *hide_mask |= 0x400000;
if (is_conditional && _settings_game.vehicle.train_braking_model != TBM_REALISTIC) *hide_mask |= 0x200;
}
return is_conditional ? &set_cond : &set_action;
}
@ -1090,11 +1093,22 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
} else {
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_TILE_INDEX;
SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]);
SetDParam(1, STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG);
SetDParam(2, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item)));
SetDParam(3, TileX(tile));
SetDParam(4, TileY(tile));
}
switch (static_cast<TraceRestrictPBSEntrySignalAuxField>(GetTraceRestrictAuxField(item))) {
case TRPESAF_VEH_POS:
SetDParam(1, STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG);
break;
case TRPESAF_RES_END:
SetDParam(1, _settings_game.vehicle.train_braking_model == TBM_REALISTIC ? STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG : STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG_WARN);
break;
default:
NOT_REACHED();
}
break;
}

@ -76,7 +76,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // Also us
static TileIndex TrainApproachingCrossingTile(const Train *v);
static void CheckIfTrainNeedsService(Train *v);
static void CheckNextTrainTile(Train *v);
TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *);
extern TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *, TraceRestrictPBSEntrySignalAuxField mode);
static void TrainEnterStation(Train *v, StationID station);
static void UnreserveBridgeTunnelTile(TileIndex tile);
static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile);

Loading…
Cancel
Save