Tracerestrict: Add long reserve (unless stopping) mode

Requires realistic braking
This commit is contained in:
Jonathan G Rennison 2023-10-03 20:59:28 +01:00
parent b299c4dce8
commit 0620026d56
6 changed files with 41 additions and 11 deletions

View File

@ -890,6 +890,7 @@ STR_TRACE_RESTRICT_RESERVE_THROUGH :Reserve through
STR_TRACE_RESTRICT_RESERVE_THROUGH_CANCEL :Cancel reserve through
STR_TRACE_RESTRICT_LONG_RESERVE :Long reserve
STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL :Cancel long reserve
STR_TRACE_RESTRICT_LONG_RESERVE_UNLESS_STOPPING :Long reserve (unless stopping)
STR_TRACE_RESTRICT_WAIT_AT_PBS :Wait at PBS signal
STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL :Cancel wait at PBS signal
STR_TRACE_RESTRICT_PBS_RES_END_WAIT :Wait at start PBS signal for reservation ending here

View File

@ -76,7 +76,7 @@ static uint32 saveSTC(const SlxiSubChunkInfo *info, bool dry_run);
const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_VERSION_LABEL, XSCF_IGNORABLE_ALL, 1, 1, "version_label", saveVL, loadVL, nullptr },
{ XSLFI_UPSTREAM_VERSION, XSCF_NULL, 1, 1, "upstream_version", saveUV, loadUV, nullptr },
{ XSLFI_TRACE_RESTRICT, XSCF_NULL, 15, 15, "tracerestrict", nullptr, nullptr, "TRRM,TRRP,TRRS" },
{ XSLFI_TRACE_RESTRICT, XSCF_NULL, 16, 16, "tracerestrict", nullptr, nullptr, "TRRM,TRRP,TRRS" },
{ XSLFI_TRACE_RESTRICT_OWNER, XSCF_NULL, 1, 1, "tracerestrict_owner", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_ORDRCND, XSCF_NULL, 4, 4, "tracerestrict_order_cond", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_STATUSCND, XSCF_NULL, 2, 2, "tracerestrict_status_cond", nullptr, nullptr, nullptr },

View File

@ -687,6 +687,12 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
out.flags &= ~TRPRF_LONG_RESERVE;
break;
case TRLRVF_LONG_RESERVE_UNLESS_STOPPING:
if (!(input.input_flags & TRPIF_PASSED_STOP)) {
out.flags |= TRPRF_LONG_RESERVE;
}
break;
default:
NOT_REACHED();
break;

View File

@ -273,8 +273,9 @@ enum TraceRestrictTargetDirectionCondAuxField {
* TraceRestrictItem value field, for TRIT_LONG_RESERVE
*/
enum TraceRestrictLongReserveValueField {
TRLRVF_LONG_RESERVE = 0, ///< Long reserve
TRLRVF_CANCEL_LONG_RESERVE = 1, ///< Cancel long reserve
TRLRVF_LONG_RESERVE = 0, ///< Long reserve
TRLRVF_CANCEL_LONG_RESERVE = 1, ///< Cancel long reserve
TRLRVF_LONG_RESERVE_UNLESS_STOPPING = 2, ///< Long reserve (unless passed stop)
};
/**
@ -474,6 +475,14 @@ enum TraceRestrictProgramInputSlotPermissions : uint8 {
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputSlotPermissions)
/**
* Enumeration for TraceRestrictProgramInput::input_flags
*/
enum TraceRestrictProgramInputFlags : uint8 {
TRPIF_PASSED_STOP = 1 << 0, ///< Train has passed stop
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputFlags)
/**
* Execution input of a TraceRestrictProgram
*/
@ -485,10 +494,12 @@ struct TraceRestrictProgramInput {
PreviousSignalProc *previous_signal_callback; ///< Callback to retrieve tile and direction of previous signal, may be nullptr
const void *previous_signal_ptr; ///< Opaque pointer suitable to be passed to previous_signal_callback
TraceRestrictProgramInputSlotPermissions permitted_slot_operations; ///< Permitted slot operations
TraceRestrictProgramInputFlags input_flags; ///< Input flags
TraceRestrictProgramInput(TileIndex tile_, Trackdir trackdir_, PreviousSignalProc *previous_signal_callback_, const void *previous_signal_ptr_)
: tile(tile_), trackdir(trackdir_), previous_signal_callback(previous_signal_callback_), previous_signal_ptr(previous_signal_ptr_),
permitted_slot_operations(static_cast<TraceRestrictProgramInputSlotPermissions>(0)) { }
permitted_slot_operations(static_cast<TraceRestrictProgramInputSlotPermissions>(0)),
input_flags(static_cast<TraceRestrictProgramInputFlags>(0)) { }
};
/**

View File

@ -242,11 +242,13 @@ static const TraceRestrictDropDownListSet _reserve_through_value = {
static const StringID _long_reserve_value_str[] = {
STR_TRACE_RESTRICT_LONG_RESERVE,
STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL,
STR_TRACE_RESTRICT_LONG_RESERVE_UNLESS_STOPPING,
INVALID_STRING_ID
};
static const uint _long_reserve_value_val[] = {
0,
1,
2,
};
/** value drop down list for long reserve types strings and values */
@ -1554,6 +1556,10 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
instruction_string = STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL;
break;
case TRLRVF_LONG_RESERVE_UNLESS_STOPPING:
instruction_string = STR_TRACE_RESTRICT_LONG_RESERVE_UNLESS_STOPPING;
break;
default:
NOT_REACHED();
break;
@ -2061,9 +2067,12 @@ public:
this->ShowDropDownListWithValue(&_reserve_through_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0);
break;
case TRVT_LONG_RESERVE:
this->ShowDropDownListWithValue(&_long_reserve_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0);
case TRVT_LONG_RESERVE: {
uint hidden = 0;
if (_settings_game.vehicle.train_braking_model != TBM_REALISTIC) hidden |= 4;
this->ShowDropDownListWithValue(&_long_reserve_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, hidden);
break;
}
case TRVT_WAIT_AT_PBS:
this->ShowDropDownListWithValue(&_wait_at_pbs_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0);

View File

@ -4179,7 +4179,7 @@ static bool LookaheadWithinCurrentTunnelBridge(const Train *t)
return t->lookahead->current_position >= t->lookahead->reservation_end_position - ((int)TILE_SIZE * t->lookahead->tunnel_bridge_reserved_tiles) && !HasBit(t->lookahead->flags, TRLF_TB_EXIT_FREE);
}
static bool HasLongReservePbsSignalOnTrackdir(Train* v, TileIndex tile, Trackdir trackdir, bool default_value)
static bool HasLongReservePbsSignalOnTrackdir(Train* v, TileIndex tile, Trackdir trackdir, bool default_value, uint16 lookahead_state_flags)
{
if (HasPbsSignalOnTrackdir(tile, trackdir)) {
if (IsNoEntrySignal(tile, TrackdirToTrack(trackdir))) return false;
@ -4188,7 +4188,9 @@ static bool HasLongReservePbsSignalOnTrackdir(Train* v, TileIndex tile, Trackdir
if (prog && prog->actions_used_flags & TRPAUF_LONG_RESERVE) {
TraceRestrictProgramResult out;
if (default_value) out.flags |= TRPRF_LONG_RESERVE;
prog->Execute(v, TraceRestrictProgramInput(tile, trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, nullptr), out);
TraceRestrictProgramInput input(tile, trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, nullptr);
if (HasBit(lookahead_state_flags, CTTLASF_STOP_FOUND)) input.input_flags |= TRPIF_PASSED_STOP;
prog->Execute(v, input, out);
return (out.flags & TRPRF_LONG_RESERVE);
}
}
@ -4249,6 +4251,7 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
TraceRestrictProgramResult out;
if (long_reserve) out.flags |= TRPRF_LONG_RESERVE;
TraceRestrictProgramInput input(exit_tile, exit_td, nullptr, nullptr);
if (HasBit(lookahead_state.flags, CTTLASF_STOP_FOUND)) input.input_flags |= TRPIF_PASSED_STOP;
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_ACQUIRE_ON_RES;
prog->Execute(v, input, out);
if (out.flags & TRPRF_WAIT_AT_PBS) {
@ -4292,7 +4295,7 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
}
CFollowTrackRail ft(v);
if (ft.Follow(tile, td) && HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits), !long_enough)) {
if (ft.Follow(tile, td) && HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits), !long_enough, lookahead_state.flags)) {
// We reserved up to a LR signal, reserve past it as well. recursion
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);
}
@ -4412,7 +4415,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
CFollowTrackRail ft(v);
if (ft.Follow(res_dest.tile, res_dest.trackdir)) {
Trackdir new_td = FindFirstTrackdir(ft.m_new_td_bits);
long_reserve = HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td, _settings_game.vehicle.train_braking_model == TBM_REALISTIC);
long_reserve = HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td, _settings_game.vehicle.train_braking_model == TBM_REALISTIC, lookahead_state.flags);
}
}
@ -4898,7 +4901,7 @@ static TrainMovedChangeSignalEnum TrainMovedChangeSignal(Train* v, TileIndex til
/* A PBS block with a non-PBS signal facing us? */
if (!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return CHANGED_NORMAL_TO_PBS_BLOCK;
if (front && HasLongReservePbsSignalOnTrackdir(v, tile, trackdir, _settings_game.vehicle.train_braking_model == TBM_REALISTIC)) return CHANGED_LR_PBS;
if (front && HasLongReservePbsSignalOnTrackdir(v, tile, trackdir, _settings_game.vehicle.train_braking_model == TBM_REALISTIC, 0)) return CHANGED_LR_PBS;
}
}
if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile) && GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {