From 6a69a5495f6b02d8c8497accb9774e142b87e181 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 28 Jun 2022 01:16:57 +0100 Subject: [PATCH] Add tracerestrict action to set combined normal/shunt signal mode Add associated conditional to get reservation end tile --- src/lang/english.txt | 10 ++ src/lang/galician.txt | 2 +- src/lang/korean.txt | 2 +- src/pathfinder/yapf/yapf_costrail.hpp | 2 + src/pbs.cpp | 2 + src/saveload/extended_ver_sl.cpp | 2 +- src/signal.cpp | 23 ++++ src/tracerestrict.cpp | 27 ++++- src/tracerestrict.h | 18 +++- src/tracerestrict_gui.cpp | 144 ++++++++++++++++++++++++-- 10 files changed, 216 insertions(+), 16 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index ab941da981..7cfcefe65e 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3242,6 +3242,8 @@ STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL :PBS entry signa 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_TILE :PBS reservation end tile +STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_TILE_LONG :tile at end of PBS reservation from this signal 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 @@ -3330,6 +3332,7 @@ STR_TRACE_RESTRICT_NEWS_CONTROL :News control STR_TRACE_RESTRICT_COUNTER_OP :Counter operation STR_TRACE_RESTRICT_PF_PENALTY_CONTROL :Penalty config STR_TRACE_RESTRICT_SPEED_ADAPTATION_CONTROL :Speed adap. control +STR_TRACE_RESTRICT_SIGNAL_MODE_CONTROL :Signal mode control STR_TRACE_RESTRICT_SLOT_ACQUIRE_WAIT :Acquire or wait STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE :Try to acquire STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE_ON_RES :Try to acquire (on reserve) @@ -3384,6 +3387,10 @@ STR_TRACE_RESTRICT_MAKE_TRAIN_SPEED_ADAPTATION_EXEMPT :Make train exem STR_TRACE_RESTRICT_REMOVE_TRAIN_SPEED_ADAPTATION_EXEMPT :Remove train exemption from automatic speed adaptation STR_TRACE_RESTRICT_MAKE_TRAIN_SPEED_ADAPTATION_EXEMPT_SHORT :Make exempt STR_TRACE_RESTRICT_REMOVE_TRAIN_SPEED_ADAPTATION_EXEMPT_SHORT :Remove exemption +STR_TRACE_RESTRICT_USE_NORMAL_ASPECT_MODE :Use normal signal aspect (combined normal/shunt aspect signal) +STR_TRACE_RESTRICT_USE_SHUNT_ASPECT_MODE :Use shunt signal aspect (combined normal/shunt aspect signal) +STR_TRACE_RESTRICT_USE_NORMAL_ASPECT_MODE_SHORT :Use normal signal aspect +STR_TRACE_RESTRICT_USE_SHUNT_ASPECT_MODE_SHORT :Use shunt signal aspect STR_TRACE_RESTRICT_TIME_MINUTE :current minute (0 - 59) STR_TRACE_RESTRICT_TIME_HOUR :current hour (0 - 23) STR_TRACE_RESTRICT_TIME_HOUR_MINUTE :current hour and minute (0 - 2359) @@ -3451,6 +3458,7 @@ STR_TRACE_RESTRICT_SHARE :{BLACK}Share STR_TRACE_RESTRICT_UNSHARE :{BLACK}Unshare STR_TRACE_RESTRICT_SELECT_TARGET :{BLACK}Select Target STR_TRACE_RESTRICT_SELECT_SIGNAL :{BLACK}Select Signal +STR_TRACE_RESTRICT_SELECT_TILE :{BLACK}Select Tile STR_TRACE_RESTRICT_INSERT_TOOLTIP :{BLACK}Insert an instruction STR_TRACE_RESTRICT_REMOVE_TOOLTIP :{BLACK}Remove the selected instruction{}Ctrl+Click to remove the selected conditional instruction but retain its contents STR_TRACE_RESTRICT_RESET_TOOLTIP :{BLACK}Reset the current signal (without affecting shared programs) @@ -3461,6 +3469,8 @@ STR_TRACE_RESTRICT_SIGNAL_GUI_TOOLTIP :{BLACK}Routefin STR_TRACE_RESTRICT_INSTRUCTION_LIST_TOOLTIP :{BLACK}Click an instruction to select it{}Ctrl+Click to scroll to the instruction's target (if any) STR_TRACE_RESTRICT_HIGHLIGHT_TOOLTIP :{BLACK}Toggle highlighting all signals sharing this program STR_TRACE_RESTRICT_WARNING_REQUIRES_REALISTIC_BRAKING :{STRING} {PUSH_COLOUR}{RED}(requires realistic braking){POP_COLOUR} +STR_TRACE_RESTRICT_WARNING_SIGNAL_MODE_CONTROL_ONLY :{STRING} {PUSH_COLOUR}{RED}(only for signal mode control actions){POP_COLOUR} +STR_TRACE_RESTRICT_WARNING_NO_SIGNAL_MODE_CONTROL :{STRING} {PUSH_COLOUR}{RED}(not for signal mode control actions){POP_COLOUR} STR_TRACE_RESTRICT_ERROR_CAN_T_INSERT_ITEM :{WHITE}Can't insert instruction STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM :{WHITE}Can't modify instruction STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM :{WHITE}Can't remove instruction diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 0ad02d4384..378483c398 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -6025,7 +6025,6 @@ STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL :Sinal de entrad STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG :entrou nun sinal de entrada a cantón STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL :Sinal de saída de ruta STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG :sinal no final da reserva actual de ruta -STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG_WARN :sinal no final da reserva actual de ruta {PUSH_COLOUR}{RED}(require freo realista){POP_COLOUR} STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP :o grupo de tren STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :tren no slot STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY :ocupación de slots @@ -6237,6 +6236,7 @@ STR_TRACE_RESTRICT_SELECT_TARGET :{BLACK}Seleccio STR_TRACE_RESTRICT_SELECT_SIGNAL :{BLACK}Seleccionar sinal STR_TRACE_RESTRICT_SIGNAL_GUI_TOOLTIP :{BLACK}Restrición de busca de ruta STR_TRACE_RESTRICT_INSTRUCTION_LIST_TOOLTIP :{BLACK}Fai click nunha instrución para seleccionala{}Ctrl+Click para desplazarte ata o obxectivo da instrución(se o hai) +STR_TRACE_RESTRICT_WARNING_REQUIRES_REALISTIC_BRAKING :{STRING} {PUSH_COLOUR}{RED}(require freo realista){POP_COLOUR} STR_TRACE_RESTRICT_ERROR_CAN_T_INSERT_ITEM :{WHITE}Non se pode insertar a instrución STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM :{WHITE}Non se pode modificar a instrución STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM :{WHITE}Non se pode eliminar a instrución diff --git a/src/lang/korean.txt b/src/lang/korean.txt index f3efa73659..a3711ec9e6 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -3243,7 +3243,6 @@ STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL :경로 신호 STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG :통과한 경로 신호기 STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL :끝 경로 신호기 STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG :현재 예약된 경로의 끝에 있는 신호기 -STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG_WARN :현재 예약된 경로의 끝에 있는 신호기 {PUSH_COLOUR}{RED}(현실적인 감속을 켜야 함){POP_COLOUR} STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP :열차 그룹 STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :열차 슬롯 STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY :슬롯 사용량 @@ -3462,6 +3461,7 @@ STR_TRACE_RESTRICT_UNSHARE_TOOLTIP :{BLACK}다른 STR_TRACE_RESTRICT_SIGNAL_GUI_TOOLTIP :{BLACK}경로 탐색 제한 STR_TRACE_RESTRICT_INSTRUCTION_LIST_TOOLTIP :{BLACK}선택하려면 구문을 클릭하십시오.{}구문에서 지정된 장소가 있다면, 지정된 장소로 가려면 구문을 Ctrl+클릭하십시오. STR_TRACE_RESTRICT_HIGHLIGHT_TOOLTIP :{BLACK}이 프로그램을 공유하는 모든 신호기를 선택하여 표시합니다. +STR_TRACE_RESTRICT_WARNING_REQUIRES_REALISTIC_BRAKING :{STRING} {PUSH_COLOUR}{RED}(현실적인 감속을 켜야 함){POP_COLOUR} STR_TRACE_RESTRICT_ERROR_CAN_T_INSERT_ITEM :{WHITE}구문을 삽입할 수 없습니다. STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM :{WHITE}구문을 수정할 수 없습니다. STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM :{WHITE}구문을 제거할 수 없습니다. diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 683c928622..2a100c7cbe 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -189,6 +189,8 @@ private: */ static TileIndex TraceRestrictPreviousSignalCallback(const Train *v, const void *node_ptr, TraceRestrictPBSEntrySignalAuxField mode) { + if (mode == TRPESAF_RES_END_TILE) return INVALID_TILE; + const Node *node = static_cast(node_ptr); for (;;) { TileIndex last_signal_tile = node->m_last_non_reserve_through_signal_tile; diff --git a/src/pbs.cpp b/src/pbs.cpp index 37f056a733..93a6c41e03 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -1247,6 +1247,8 @@ CommandCost CheckTrainInTunnelBridgePreventsTrackModification(TileIndex start, T */ TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *, TraceRestrictPBSEntrySignalAuxField mode) { + if (mode == TRPESAF_RES_END_TILE) return INVALID_TILE; + TileIndex tile; Trackdir trackdir; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 47582eff5a..51fedf7c6e 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -78,7 +78,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, 2, 2, "tracerestrict_timedate", nullptr, nullptr, nullptr }, - { XSLFI_TRACE_RESTRICT_BRKCND, XSCF_NULL, 2, 2, "tracerestrict_braking_cond",nullptr, nullptr, nullptr }, + { XSLFI_TRACE_RESTRICT_BRKCND, XSCF_NULL, 3, 3, "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 }, diff --git a/src/signal.cpp b/src/signal.cpp index 6961844ea3..08b0fdb9f2 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -1514,6 +1514,29 @@ void DetermineCombineNormalShuntModeWithLookahead(Train *v, TileIndex tile, Trac if (item.start == lookahead_position && item.type == TRLIT_SIGNAL && HasBit(item.data_aux, TRSLAI_COMBINED)) { container_unordered_remove(_deferred_determine_combined_normal_shunt_mode, std::pair({ tile, trackdir })); + if (IsRestrictedSignal(tile)) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir)); + if (prog && prog->actions_used_flags & TRPAUF_CMB_SIGNAL_MODE_CTRL) { + TraceRestrictProgramResult out; + TraceRestrictProgramInput input(tile, trackdir, [](const Train *v, const void *, TraceRestrictPBSEntrySignalAuxField mode) { + if (mode == TRPESAF_RES_END_TILE) { + return v->lookahead->reservation_end_tile; + } else { + return INVALID_TILE; + } + }, nullptr); + prog->Execute(v, input, out); + if (out.flags & TRPRF_SIGNAL_MODE_NORMAL) { + return; + } + if (out.flags & TRPRF_SIGNAL_MODE_SHUNT) { + SetSignalAspect(tile, TrackdirToTrack(trackdir), 1); + SetBit(item.data_aux, TRSLAI_COMBINED_SHUNT); + return; + } + } + } + for (size_t j = i + 1; j < count; j++) { const TrainReservationLookAheadItem &ahead = v->lookahead->items[j]; if (ahead.type == TRLIT_SIGNAL) { diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index cc29da52df..6b256827ce 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -248,7 +248,7 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp condstack.clear(); byte have_previous_signal = 0; - TileIndex previous_signal_tile[2]; + TileIndex previous_signal_tile[3]; size_t size = this->items.size(); for (size_t i = 0; i < size; i++) { @@ -358,7 +358,7 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp // TRIT_COND_PBS_ENTRY_SIGNAL value type uses the next slot i++; TraceRestrictPBSEntrySignalAuxField mode = static_cast(GetTraceRestrictAuxField(item)); - assert(mode == TRPESAF_VEH_POS || mode == TRPESAF_RES_END); + assert(mode == TRPESAF_VEH_POS || mode == TRPESAF_RES_END || mode == TRPESAF_RES_END_TILE); uint32_t signal_tile = this->items[i]; if (!HasBit(have_previous_signal, mode)) { if (input.previous_signal_callback) { @@ -804,6 +804,24 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp } break; + case TRIT_SIGNAL_MODE_CONTROL: + switch (static_cast(GetTraceRestrictValue(item))) { + case TRSMCF_NORMAL_ASPECT: + out.flags |= TRPRF_SIGNAL_MODE_NORMAL; + out.flags &= ~TRPRF_SIGNAL_MODE_SHUNT; + break; + + case TRSMCF_SHUNT_ASPECT: + out.flags &= ~TRPRF_SIGNAL_MODE_NORMAL; + out.flags |= TRPRF_SIGNAL_MODE_SHUNT; + break; + + default: + NOT_REACHED(); + break; + } + break; + default: NOT_REACHED(); } @@ -1092,6 +1110,10 @@ CommandCost TraceRestrictProgram::Validate(const std::vector actions_used_flags |= TRPAUF_SPEED_ADAPTATION; break; + case TRIT_SIGNAL_MODE_CONTROL: + actions_used_flags |= TRPAUF_CMB_SIGNAL_MODE_CTRL; + break; + default: return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION); } @@ -1159,6 +1181,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp case TRVT_ENGINE_CLASS: case TRVT_PF_PENALTY_CONTROL: case TRVT_SPEED_ADAPTATION_CONTROL: + case TRVT_SIGNAL_MODE_CONTROL: SetTraceRestrictValue(item, 0); if (!IsTraceRestrictTypeAuxSubtype(GetTraceRestrictType(item))) { SetTraceRestrictAuxField(item, 0); diff --git a/src/tracerestrict.h b/src/tracerestrict.h index f1aff5da09..3f7fc7606c 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -161,6 +161,7 @@ enum TraceRestrictItemType { TRIT_COUNTER = 51, ///< Change counter value TRIT_PF_PENALTY_CONTROL = 52, ///< Control base signal penalties TRIT_SPEED_ADAPTATION_CONTROL = 53, ///< Control speed adaptation + TRIT_SIGNAL_MODE_CONTROL = 54, ///< Control signal modes /* space up to 63 */ }; @@ -300,6 +301,14 @@ enum TraceRestrictSpeedAdaptationControlField { TRSACF_REMOVE_SPEED_ADAPT_EXEMPT = 1, ///< Remove train exempt from speed adaptation }; +/** + * TraceRestrictItem value field, for TRIT_SIGNAL_MODE_CONTROL + */ +enum TraceRestrictSignalModeControlField { + TRSMCF_NORMAL_ASPECT = 0, ///< Combined normal/shunt aspect signals: use normal mode + TRSMCF_SHUNT_ASPECT = 1, ///< Combined normal/shunt aspect signals: use shunt mode +}; + /** * TraceRestrictItem value field, for TRIT_COND_TRAIN_STATUS */ @@ -369,6 +378,7 @@ enum TraceRestrictCounterCondOpField { enum TraceRestrictPBSEntrySignalAuxField { TRPESAF_VEH_POS = 0, ///< vehicle position signal TRPESAF_RES_END = 1, ///< reservation end signal + TRPESAF_RES_END_TILE = 2, ///< reservation end tile /* space up to 3 */ }; @@ -398,6 +408,8 @@ enum TraceRestrictProgramResultFlags { TRPRF_NO_PBS_BACK_PENALTY = 1 << 8, ///< Do not apply PBS back penalty TRPRF_SPEED_ADAPT_EXEMPT = 1 << 9, ///< Make speed adaptation exempt TRPRF_RM_SPEED_ADAPT_EXEMPT = 1 << 10, ///< Remove speed adaptation exemption + TRPRF_SIGNAL_MODE_NORMAL = 1 << 11, ///< Combined normal/shunt signal mode control: normal + TRPRF_SIGNAL_MODE_SHUNT = 1 << 12, ///< Combined normal/shunt signal mode control: shunt }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) @@ -423,13 +435,14 @@ enum TraceRestrictProgramActionsUsedFlags { TRPAUF_SPEED_ADAPTATION = 1 << 15, ///< Speed adaptation control TRPAUF_PBS_RES_END_SIMULATE = 1 << 16, ///< PBS reservations ending at this signal slot changes must be fully simulated in dry run mode TRPAUF_RESERVE_THROUGH_ALWAYS = 1 << 17, ///< Reserve through action is unconditionally set + TRPAUF_CMB_SIGNAL_MODE_CTRL = 1 << 18, ///< Combined normal/shunt signal mode control }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) /** * Enumeration for TraceRestrictProgramInput::permitted_slot_operations */ -enum TraceRestrictProgramInputSlotPermissions { +enum TraceRestrictProgramInputSlotPermissions : uint8 { TRPISP_ACQUIRE = 1 << 0, ///< Slot acquire is permitted TRPISP_RELEASE_BACK = 1 << 1, ///< Slot release (back) is permitted TRPISP_RELEASE_FRONT = 1 << 2, ///< Slot release (front) is permitted @@ -691,6 +704,7 @@ enum TraceRestrictValueType { TRVT_ENGINE_CLASS = 46,///< takes a EngineClass TRVT_PF_PENALTY_CONTROL = 47,///< takes a TraceRestrictPfPenaltyControlField TRVT_SPEED_ADAPTATION_CONTROL = 48,///< takes a TraceRestrictSpeedAdaptationControlField + TRVT_SIGNAL_MODE_CONTROL = 49,///< takes a TraceRestrictSignalModeControlField }; /** @@ -870,6 +884,8 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR out.value_type = TRVT_PF_PENALTY_CONTROL; } else if (GetTraceRestrictType(item) == TRIT_SPEED_ADAPTATION_CONTROL) { out.value_type = TRVT_SPEED_ADAPTATION_CONTROL; + } else if (GetTraceRestrictType(item) == TRIT_SIGNAL_MODE_CONTROL) { + out.value_type = TRVT_SIGNAL_MODE_CONTROL; } else { out.value_type = TRVT_NONE; } diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index b92f349ba0..740544f6f5 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -77,6 +77,7 @@ enum TraceRestrictWindowWidgets { TR_WIDGET_VALUE_DROPDOWN, TR_WIDGET_VALUE_DEST, TR_WIDGET_VALUE_SIGNAL, + TR_WIDGET_VALUE_TILE, TR_WIDGET_LEFT_AUX_DROPDOWN, TR_WIDGET_BLANK_L2, @@ -120,6 +121,7 @@ enum PanelWidgets { DPR_VALUE_DROPDOWN, DPR_VALUE_DEST, DPR_VALUE_SIGNAL, + DPR_VALUE_TILE, DPR_BLANK, // Share @@ -160,6 +162,7 @@ static const StringID _program_insert_str[] = { STR_TRACE_RESTRICT_COUNTER_OP, STR_TRACE_RESTRICT_PF_PENALTY_CONTROL, STR_TRACE_RESTRICT_SPEED_ADAPTATION_CONTROL, + STR_TRACE_RESTRICT_SIGNAL_MODE_CONTROL, INVALID_STRING_ID }; static const uint32 _program_insert_else_hide_mask = 8; ///< disable bitmask for else @@ -172,6 +175,7 @@ static const uint32 _program_speed_res_hide_mask = 0x800; ///< disable bitm static const uint32 _program_counter_hide_mask = 0x2000; ///< disable bitmask for counter static const uint32 _program_penalty_adj_hide_mask = 0x4000; ///< disable bitmask for penalty adjust static const uint32 _program_speed_adapt_hide_mask = 0x8000; ///< disable bitmask for speed adaptation +static const uint32 _program_signal_mode_hide_mask = 0x10000; ///< disable bitmask for signal mode control static const uint _program_insert_val[] = { TRIT_COND_UNDEFINED, // if block TRIT_COND_UNDEFINED | (TRCF_ELSE << 16), // elif block @@ -189,6 +193,7 @@ static const uint _program_insert_val[] = { TRIT_COUNTER, // counter operation TRIT_PF_PENALTY_CONTROL, // penalty control TRIT_SPEED_ADAPTATION_CONTROL, // speed adaptation control + TRIT_SIGNAL_MODE_CONTROL, // signal mode control }; /** insert drop down list strings and values */ @@ -422,6 +427,21 @@ static const TraceRestrictDropDownListSet _speed_adaptation_control_value = { _speed_adaptation_control_value_str, _speed_adaptation_control_value_val, }; +static const StringID _signal_mode_control_value_str[] = { + STR_TRACE_RESTRICT_USE_NORMAL_ASPECT_MODE_SHORT, + STR_TRACE_RESTRICT_USE_SHUNT_ASPECT_MODE_SHORT, + INVALID_STRING_ID +}; +static const uint _signal_mode_control_value_val[] = { + TRSMCF_NORMAL_ASPECT, + TRSMCF_SHUNT_ASPECT, +}; + +/** value drop down list for speed adaptation control types strings and values */ +static const TraceRestrictDropDownListSet _signal_mode_control_value = { + _signal_mode_control_value_str, _signal_mode_control_value_val, +}; + /** * Get index of @p value in @p list_set * if @p value is not present, assert if @p missing_ok is false, otherwise return -1 @@ -476,14 +496,15 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG STR_TRACE_RESTRICT_PF_PENALTY, STR_TRACE_RESTRICT_RESERVE_THROUGH, STR_TRACE_RESTRICT_LONG_RESERVE, - STR_TRACE_RESTRICT_WAIT_AT_PBS, + STR_TRACE_RESTRICT_WAIT_AT_PBS, // 0x10 STR_TRACE_RESTRICT_SLOT_OP, STR_TRACE_RESTRICT_REVERSE, STR_TRACE_RESTRICT_SPEED_RESTRICTION, - STR_TRACE_RESTRICT_NEWS_CONTROL, + STR_TRACE_RESTRICT_NEWS_CONTROL, // 0x100 STR_TRACE_RESTRICT_COUNTER_OP, STR_TRACE_RESTRICT_PF_PENALTY_CONTROL, STR_TRACE_RESTRICT_SPEED_ADAPTATION_CONTROL, + STR_TRACE_RESTRICT_SIGNAL_MODE_CONTROL, // 0x1000 INVALID_STRING_ID, }; static const uint val_action[] = { @@ -499,6 +520,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG TRIT_COUNTER, TRIT_PF_PENALTY_CONTROL, TRIT_SPEED_ADAPTATION_CONTROL, + TRIT_SIGNAL_MODE_CONTROL, }; static const TraceRestrictDropDownListSet set_action = { str_action, val_action, @@ -530,6 +552,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG STR_TRACE_RESTRICT_VARIABLE_COUNTER_VALUE, STR_TRACE_RESTRICT_VARIABLE_TIME_DATE_VALUE, STR_TRACE_RESTRICT_VARIABLE_RESERVED_TILES_AHEAD, + STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_TILE, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED, INVALID_STRING_ID, }; @@ -538,27 +561,28 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG TRIT_COND_MAX_SPEED, TRIT_COND_CURRENT_ORDER, TRIT_COND_NEXT_ORDER, - TRIT_COND_LAST_STATION, + TRIT_COND_LAST_STATION, // 0x10 TRIT_COND_CARGO, TRIT_COND_LOAD_PERCENT, TRIT_COND_ENTRY_DIRECTION, - TRIT_COND_TRAIN_GROUP, + TRIT_COND_TRAIN_GROUP, // 0x100 TRIT_COND_TRAIN_OWNER, TRIT_COND_TRAIN_STATUS, TRIT_COND_PHYS_PROP | (TRPPCAF_WEIGHT << 16), - TRIT_COND_PHYS_PROP | (TRPPCAF_POWER << 16), + TRIT_COND_PHYS_PROP | (TRPPCAF_POWER << 16), // 0x1000 TRIT_COND_PHYS_PROP | (TRPPCAF_MAX_TE << 16), TRIT_COND_PHYS_RATIO | (TRPPRCAF_POWER_WEIGHT << 16), TRIT_COND_PHYS_RATIO | (TRPPRCAF_MAX_TE_WEIGHT << 16), - TRIT_COND_CATEGORY | (TRCCAF_ENGINE_CLASS << 16), + TRIT_COND_CATEGORY | (TRCCAF_ENGINE_CLASS << 16), // 0x10000 TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_VEH_POS << 16), TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_RES_END << 16), TRIT_COND_TRAIN_IN_SLOT, - TRIT_COND_SLOT_OCCUPANCY | (TRSOCAF_OCCUPANTS << 16), + TRIT_COND_SLOT_OCCUPANCY | (TRSOCAF_OCCUPANTS << 16), // 0x100000 TRIT_COND_SLOT_OCCUPANCY | (TRSOCAF_REMAINING << 16), TRIT_COND_COUNTER_VALUE, TRIT_COND_TIME_DATE_VALUE, - TRIT_COND_RESERVED_TILES, + TRIT_COND_RESERVED_TILES, // 0x1000000 + TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_RES_END_TILE << 16), TRIT_COND_UNDEFINED, }; static const TraceRestrictDropDownListSet set_cond = { @@ -574,6 +598,10 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG } if (is_conditional && _settings_game.vehicle.train_braking_model != TBM_REALISTIC) *hide_mask |= 0x1040000; if (!is_conditional && !_settings_game.vehicle.train_speed_adaptation) *hide_mask |= 0x800; + + if (!(_settings_client.gui.show_adv_tracerestrict_features && _settings_game.vehicle.train_braking_model == TBM_REALISTIC && _signal_style_masks.combined_normal_shunt != 0)) { + *hide_mask |= is_conditional ? 0x2000000 : 0x1000; + } } return is_conditional ? &set_cond : &set_action; } @@ -1077,6 +1105,28 @@ static uint GetPathfinderPenaltyDropdownIndex(TraceRestrictItem item) } } +template +void IterateActionsInsideConditional(const TraceRestrictProgram *prog, int index, F handler) +{ + size_t instruction_count = prog->GetInstructionCount(); + int depth = 1; + for (size_t i = index; i < instruction_count; i++) { + TraceRestrictItem item = prog->items[prog->InstructionOffsetToArrayOffset(i)]; + if (IsTraceRestrictConditional(item)) { + if (GetTraceRestrictCondFlags(item) & (TRCF_ELSE | TRCF_OR)) { + /* do nothing */ + } else if (GetTraceRestrictType(item) == TRIT_COND_ENDIF) { + depth--; + if (depth == 0) return; + } else { + depth++; + } + } else { + handler(item); + } + } +} + /** Common function for drawing an ordinary conditional instruction */ static void DrawInstructionStringConditionalCommon(TraceRestrictItem item, const TraceRestrictTypePropertySet &properties) { @@ -1215,13 +1265,28 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric _temp_special_strings[0].assign(buf, end); SetDParam(1, SPECSTR_TEMP_START); }; + auto check_signal_mode_control = [&](bool allowed) { + bool warn = false; + IterateActionsInsideConditional(prog, index, [&](const TraceRestrictItem &item) { + if ((GetTraceRestrictType(item) == TRIT_SIGNAL_MODE_CONTROL) != allowed) warn = true; + }); + if (warn) insert_warning(allowed ? STR_TRACE_RESTRICT_WARNING_SIGNAL_MODE_CONTROL_ONLY : STR_TRACE_RESTRICT_WARNING_NO_SIGNAL_MODE_CONTROL); + }; switch (static_cast(GetTraceRestrictAuxField(item))) { case TRPESAF_VEH_POS: SetDParam(1, STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG); + check_signal_mode_control(false); break; case TRPESAF_RES_END: SetDParam(1, STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL_LONG); + check_signal_mode_control(false); + if (_settings_game.vehicle.train_braking_model != TBM_REALISTIC) insert_warning(STR_TRACE_RESTRICT_WARNING_REQUIRES_REALISTIC_BRAKING); + break; + + case TRPESAF_RES_END_TILE: + SetDParam(1, STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_TILE_LONG); + check_signal_mode_control(true); if (_settings_game.vehicle.train_braking_model != TBM_REALISTIC) insert_warning(STR_TRACE_RESTRICT_WARNING_REQUIRES_REALISTIC_BRAKING); break; @@ -1603,6 +1668,22 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric } break; + case TRIT_SIGNAL_MODE_CONTROL: + switch (static_cast(GetTraceRestrictValue(item))) { + case TRSMCF_NORMAL_ASPECT: + instruction_string = STR_TRACE_RESTRICT_USE_NORMAL_ASPECT_MODE; + break; + + case TRSMCF_SHUNT_ASPECT: + instruction_string = STR_TRACE_RESTRICT_USE_SHUNT_ASPECT_MODE; + break; + + default: + NOT_REACHED(); + break; + } + break; + default: NOT_REACHED(); break; @@ -1744,6 +1825,9 @@ public: if (!_settings_client.gui.show_adv_tracerestrict_features || !_settings_game.vehicle.train_speed_adaptation) { hidden |= _program_speed_adapt_hide_mask; } + if (!(_settings_client.gui.show_adv_tracerestrict_features && _settings_game.vehicle.train_braking_model == TBM_REALISTIC && _signal_style_masks.combined_normal_shunt != 0)) { + hidden |= _program_signal_mode_hide_mask; + } this->ShowDropDownListWithValue(&_program_insert, 0, true, TR_WIDGET_INSERT, disabled, hidden, 0); break; @@ -1940,6 +2024,10 @@ public: this->ShowDropDownListWithValue(&_speed_adaptation_control_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); break; + case TRVT_SIGNAL_MODE_CONTROL: + this->ShowDropDownListWithValue(&_signal_mode_control_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + default: break; } @@ -1984,6 +2072,11 @@ public: break; } + case TR_WIDGET_VALUE_TILE: { + SetObjectToPlaceAction(widget, SPR_CURSOR_MOUSE); + break; + } + case TR_WIDGET_GOTO_SIGNAL: { ScrollMainWindowToTile(this->tile); this->UpdateButtonState(); @@ -2194,6 +2287,10 @@ public: OnPlaceObjectSignalTileValue(pt, tile, widget, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); break; + case TR_WIDGET_VALUE_TILE: + OnPlaceObjectTileValue(pt, tile, widget, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); + break; + default: NOT_REACHED(); break; @@ -2339,6 +2436,17 @@ public: TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_DUAL_ITEM, this->selected_instruction - 1, tile, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); } + /** + * Common OnPlaceObject handler for instruction value modification actions which involve selecting a tile value + */ + void OnPlaceObjectTileValue(Point pt, TileIndex tile, int widget, int error_message) + { + TraceRestrictItem item = GetSelected(); + if (GetTraceRestrictTypeProperties(item).value_type != TRVT_TILE_INDEX) return; + + TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_DUAL_ITEM, this->selected_instruction - 1, tile, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); + } + virtual void OnPlaceObjectAbort() override { this->RaiseButtons(); @@ -2648,6 +2756,7 @@ private: this->RaiseWidget(TR_WIDGET_VALUE_DROPDOWN); this->RaiseWidget(TR_WIDGET_VALUE_DEST); this->RaiseWidget(TR_WIDGET_VALUE_SIGNAL); + this->RaiseWidget(TR_WIDGET_VALUE_TILE); this->RaiseWidget(TR_WIDGET_LEFT_AUX_DROPDOWN); NWidgetStacked *left_2_sel = this->GetWidget(TR_WIDGET_SEL_TOP_LEFT_2); @@ -2669,6 +2778,7 @@ private: this->DisableWidget(TR_WIDGET_VALUE_DROPDOWN); this->DisableWidget(TR_WIDGET_VALUE_DEST); this->DisableWidget(TR_WIDGET_VALUE_SIGNAL); + this->DisableWidget(TR_WIDGET_VALUE_TILE); this->DisableWidget(TR_WIDGET_LEFT_AUX_DROPDOWN); this->DisableWidget(TR_WIDGET_INSERT); @@ -2852,8 +2962,13 @@ private: break; case TRVT_TILE_INDEX: - right_sel->SetDisplayedPlane(DPR_VALUE_SIGNAL); - this->EnableWidget(TR_WIDGET_VALUE_SIGNAL); + if (GetTraceRestrictType(item) == TRIT_COND_PBS_ENTRY_SIGNAL && GetTraceRestrictAuxField(item) == TRPESAF_RES_END_TILE) { + right_sel->SetDisplayedPlane(DPR_VALUE_TILE); + this->EnableWidget(TR_WIDGET_VALUE_TILE); + } else { + right_sel->SetDisplayedPlane(DPR_VALUE_SIGNAL); + this->EnableWidget(TR_WIDGET_VALUE_SIGNAL); + } break; case TRVT_PF_PENALTY: @@ -3047,6 +3162,13 @@ private: GetDropDownStringByValue(&_speed_adaptation_control_value, GetTraceRestrictValue(item)); break; + case TRVT_SIGNAL_MODE_CONTROL: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_signal_mode_control_value, GetTraceRestrictValue(item)); + break; + default: break; } @@ -3228,6 +3350,8 @@ static const NWidgetPart _nested_program_widgets[] = { SetDataTip(STR_TRACE_RESTRICT_SELECT_TARGET, STR_TRACE_RESTRICT_SELECT_TARGET), SetResize(1, 0), NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_VALUE_SIGNAL), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_TRACE_RESTRICT_SELECT_SIGNAL, STR_TRACE_RESTRICT_SELECT_SIGNAL), SetResize(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_VALUE_TILE), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_TRACE_RESTRICT_SELECT_TILE, STR_TRACE_RESTRICT_SELECT_TILE), SetResize(1, 0), NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_BLANK_R), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_EMPTY, STR_NULL), SetResize(1, 0), EndContainer(),