Add tracerestrict PBS end signal conditional

This is for realistic braking long reserve
This commit is contained in:
Jonathan G Rennison
2021-02-13 02:12:16 +00:00
parent c17ec5f923
commit 35d720b0ad
10 changed files with 88 additions and 32 deletions

View File

@@ -2773,6 +2773,9 @@ STR_TRACE_RESTRICT_VARIABLE_LOAD_PERCENT :load percentage
STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION :entry direction 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 :PBS entry signal
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG :entered signal of PBS block 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_GROUP :train group
STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :train in slot STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :train in slot
STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY :slot occupancy STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY :slot occupancy

View File

@@ -178,14 +178,15 @@ private:
* This is called to retrieve the previous signal, as required * 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 * 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); const Node *node = static_cast<const Node *>(node_ptr);
for (;;) { for (;;) {
TileIndex last_signal_tile = node->m_last_non_reserve_through_signal_tile; TileIndex last_signal_tile = node->m_last_non_reserve_through_signal_tile;
if (last_signal_tile != INVALID_TILE) { if (last_signal_tile != INVALID_TILE) {
Trackdir last_signal_trackdir = node->m_last_non_reserve_through_signal_td; 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; return last_signal_tile;
} else { } else {
return INVALID_TILE; return INVALID_TILE;
@@ -208,16 +209,22 @@ private:
TileIndex origin_tile = node->GetTile(); TileIndex origin_tile = node->GetTile();
Trackdir origin_trackdir = node->GetTrackdir(); Trackdir origin_trackdir = node->GetTrackdir();
TileIndex tile = v->tile;
Trackdir trackdir = v->GetVehicleTrackdir();
TileIndex candidate_tile = INVALID_TILE; TileIndex candidate_tile = INVALID_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)) { if (IsRailDepotTile(v->tile)) {
candidate_tile = v->tile; candidate_tile = v->tile;
} else if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) { } else if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) {
candidate_tile = v->tile; candidate_tile = v->tile;
} }
}
CFollowTrackRail ft(v); 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 */ /* 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; 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; return cost;
} }

View File

@@ -213,7 +213,7 @@ public:
if (restricted_signal_info.tile != INVALID_TILE) { if (restricted_signal_info.tile != INVALID_TILE) {
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir)); const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir));
if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_SLOT) { 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; TraceRestrictProgramResult out;
TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, nullptr); TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, nullptr);

View File

@@ -1043,20 +1043,27 @@ CommandCost CheckTrainInTunnelBridgePreventsTrackModification(TileIndex start, T
* This is called to retrieve the previous signal, as required * 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 * 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)
{ {
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)) { if (IsRailDepotTile(v->tile)) {
return v->tile; return v->tile;
} }
if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) { if (v->track & TRACK_BIT_WORMHOLE && IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(v->tile) && IsTunnelBridgeEffectivelyPBS(v->tile)) {
return 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 // 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); CFollowTrackRail ft(v);
for (;;) { 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 // advance to next tile
if (!ft.Follow(tile, trackdir)) { if (!ft.Follow(tile, trackdir)) {
// ran out of track // ran out of track

View File

@@ -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_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_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_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_PROG_SIGS, XSCF_NULL, 2, 2, "programmable_signals", nullptr, nullptr, "SPRG" },
{ XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", nullptr, nullptr, nullptr }, { XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", nullptr, nullptr, nullptr },
{ XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", nullptr, nullptr, nullptr }, { XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", nullptr, nullptr, nullptr },

View File

@@ -30,6 +30,7 @@ enum SlXvFeatureIndex {
XSLFI_TRACE_RESTRICT_NEWSCTRL, ///< Trace restrict: news control XSLFI_TRACE_RESTRICT_NEWSCTRL, ///< Trace restrict: news control
XSLFI_TRACE_RESTRICT_COUNTER, ///< Trace restrict: counters XSLFI_TRACE_RESTRICT_COUNTER, ///< Trace restrict: counters
XSLFI_TRACE_RESTRICT_TIMEDATE, ///< Trace restrict: time/date 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_PROG_SIGS, ///< programmable pre-signals patch
XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch
XSLFI_SAFER_CROSSINGS, ///< Safer level crossings XSLFI_SAFER_CROSSINGS, ///< Safer level crossings

View File

@@ -244,8 +244,8 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
static std::vector<TraceRestrictCondStackFlags> condstack; static std::vector<TraceRestrictCondStackFlags> condstack;
condstack.clear(); condstack.clear();
bool have_previous_signal = false; byte have_previous_signal = 0;
TileIndex previous_signal_tile = INVALID_TILE; TileIndex previous_signal_tile[2];
size_t size = this->items.size(); size_t size = this->items.size();
for (size_t i = 0; i < size; i++) { 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: { 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++; i++;
TraceRestrictPBSEntrySignalAuxField mode = static_cast<TraceRestrictPBSEntrySignalAuxField>(GetTraceRestrictAuxField(item));
assert(mode == TRPESAF_VEH_POS || mode == TRPESAF_RES_END);
uint32_t signal_tile = this->items[i]; uint32_t signal_tile = this->items[i];
if (!have_previous_signal) { if (!HasBit(have_previous_signal, mode)) {
if (input.previous_signal_callback) { 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) bool match = (signal_tile != INVALID_TILE)
&& (previous_signal_tile == signal_tile); && (previous_signal_tile[mode] == signal_tile);
result = TestBinaryConditionCommon(item, match); result = TestBinaryConditionCommon(item, match);
break; break;
} }

View File

@@ -330,6 +330,15 @@ enum TraceRestrictCounterCondOpField {
/* space up to 8 */ /* 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 * TraceRestrictItem pathfinder penalty preset index
* This may not be shortened, only lengthened, as preset indexes are stored in save games * 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 * Execution input of a TraceRestrictProgram
*/ */
struct TraceRestrictProgramInput { 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 TileIndex tile; ///< Tile of restrict signal, for direction testing
Trackdir trackdir; ///< Track direction on 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_PROP:
case TRIT_COND_PHYS_RATIO: case TRIT_COND_PHYS_RATIO:
case TRIT_COND_SLOT_OCCUPANCY: case TRIT_COND_SLOT_OCCUPANCY:
case TRIT_COND_PBS_ENTRY_SIGNAL:
return true; return true;
default: default:

View File

@@ -444,6 +444,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
STR_TRACE_RESTRICT_VARIABLE_LOAD_PERCENT, STR_TRACE_RESTRICT_VARIABLE_LOAD_PERCENT,
STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION, STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION,
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL, 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_GROUP,
STR_TRACE_RESTRICT_VARIABLE_TRAIN_OWNER, STR_TRACE_RESTRICT_VARIABLE_TRAIN_OWNER,
STR_TRACE_RESTRICT_VARIABLE_TRAIN_STATUS, STR_TRACE_RESTRICT_VARIABLE_TRAIN_STATUS,
@@ -469,7 +470,8 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
TRIT_COND_CARGO, TRIT_COND_CARGO,
TRIT_COND_LOAD_PERCENT, TRIT_COND_LOAD_PERCENT,
TRIT_COND_ENTRY_DIRECTION, 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_GROUP,
TRIT_COND_TRAIN_OWNER, TRIT_COND_TRAIN_OWNER,
TRIT_COND_TRAIN_STATUS, TRIT_COND_TRAIN_STATUS,
@@ -494,9 +496,10 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG
if (_settings_client.gui.show_adv_tracerestrict_features) { if (_settings_client.gui.show_adv_tracerestrict_features) {
*hide_mask = 0; *hide_mask = 0;
} else { } 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; return is_conditional ? &set_cond : &set_action;
} }
@@ -1090,11 +1093,22 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
} else { } else {
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_TILE_INDEX; instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_TILE_INDEX;
SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); 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(2, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item)));
SetDParam(3, TileX(tile)); SetDParam(3, TileX(tile));
SetDParam(4, TileY(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; break;
} }

View File

@@ -76,7 +76,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // Also us
static TileIndex TrainApproachingCrossingTile(const Train *v); static TileIndex TrainApproachingCrossingTile(const Train *v);
static void CheckIfTrainNeedsService(Train *v); static void CheckIfTrainNeedsService(Train *v);
static void CheckNextTrainTile(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 TrainEnterStation(Train *v, StationID station);
static void UnreserveBridgeTunnelTile(TileIndex tile); static void UnreserveBridgeTunnelTile(TileIndex tile);
static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile); static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile);