Add tracerestrict PBS end signal conditional
This is for realistic braking long reserve
This commit is contained in:
@@ -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,16 +209,22 @@ private:
|
||||
TileIndex origin_tile = node->GetTile();
|
||||
Trackdir origin_trackdir = node->GetTrackdir();
|
||||
|
||||
TileIndex tile = v->tile;
|
||||
Trackdir trackdir = v->GetVehicleTrackdir();
|
||||
|
||||
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)) {
|
||||
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);
|
||||
|
19
src/pbs.cpp
19
src/pbs.cpp
@@ -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)
|
||||
{
|
||||
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);
|
||||
|
Reference in New Issue
Block a user