diff --git a/src/lang/english.txt b/src/lang/english.txt index 841dc3d90f..91db9abb14 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2957,6 +2957,7 @@ STR_TRACE_RESTRICT_REVERSE :Reverse STR_TRACE_RESTRICT_SPEED_RESTRICTION :Speed restriction 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_SLOT_ACQUIRE_WAIT :Acquire or wait STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE :Try to acquire STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT :Release (front) @@ -3000,6 +3001,10 @@ STR_TRACE_RESTRICT_TRAIN_NOT_STUCK :Train is not st STR_TRACE_RESTRICT_TRAIN_NOT_STUCK_CANCEL :Cancel train is not stuck, do not show news reports about waiting at this PBS signal STR_TRACE_RESTRICT_TRAIN_NOT_STUCK_SHORT :Train is not stuck... STR_TRACE_RESTRICT_TRAIN_NOT_STUCK_CANCEL_SHORT :Cancel train is not stuck... +STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY :Do not apply the penalty for passing this PBS signal from the back +STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY_CANCEL :Cancel do not apply the penalty for passing this PBS signal from the back +STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY_SHORT :No PBS back penalty +STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY_CANCEL_SHORT :Cancel no PBS back penalty 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) diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 7b626fea8e..d60ebf968c 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -266,7 +266,7 @@ private: } // returns true if dead end bit has been set - inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out, bool *is_res_through) + inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out, bool *is_res_through, bool *no_pbs_back_penalty) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir)); TraceRestrictProgramActionsUsedFlags flags_to_check = TRPAUF_PF; @@ -274,6 +274,10 @@ private: *is_res_through = false; flags_to_check |= TRPAUF_RESERVE_THROUGH; } + if (no_pbs_back_penalty != nullptr) { + *no_pbs_back_penalty = false; + flags_to_check |= TRPAUF_NO_PBS_BACK_PENALTY; + } if (GetSignalType(tile, TrackdirToTrack(trackdir)) == SIGTYPE_PBS && !HasSignalOnTrackdir(tile, trackdir)) { flags_to_check |= TRPAUF_REVERSE; } @@ -282,6 +286,9 @@ private: if (out.flags & TRPRF_RESERVE_THROUGH && is_res_through != nullptr) { *is_res_through = true; } + if (out.flags & TRPRF_NO_PBS_BACK_PENALTY && no_pbs_back_penalty != nullptr) { + *no_pbs_back_penalty = true; + } if (out.flags & TRPRF_DENY) { n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; return true; @@ -358,7 +365,7 @@ public: bool is_reserve_through = false; if (ShouldCheckTraceRestrict(n, tile)) { TraceRestrictProgramResult out; - if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, &is_reserve_through)) { + if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, &is_reserve_through, nullptr)) { return -1; } if (is_reserve_through) n.m_num_signals_res_through_passed++; @@ -374,14 +381,18 @@ public: } if (has_signal_against && IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) { - cost += n.m_num_signals_passed < Yapf().PfGetSettings().rail_look_ahead_max_signals ? Yapf().PfGetSettings().rail_pbs_signal_back_penalty : 0; + bool no_add_cost = false; if (ShouldCheckTraceRestrict(n, tile)) { TraceRestrictProgramResult out; - if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, nullptr)) { + if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, nullptr, &no_add_cost)) { return -1; } } + + if (!no_add_cost) { + cost += n.m_num_signals_passed < Yapf().PfGetSettings().rail_look_ahead_max_signals ? Yapf().PfGetSettings().rail_pbs_signal_back_penalty : 0; + } } } } diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index fe76d575f3..d0959e8dff 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -78,6 +78,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_TRACE_RESTRICT_TIMEDATE,XSCF_NULL, 1, 1, "tracerestrict_timedate", nullptr, nullptr, nullptr }, { XSLFI_TRACE_RESTRICT_BRKCND, XSCF_NULL, 2, 2, "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_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 }, diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index c8756737d8..1cc9c89de1 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -32,6 +32,7 @@ enum SlXvFeatureIndex { XSLFI_TRACE_RESTRICT_TIMEDATE, ///< Trace restrict: time/date XSLFI_TRACE_RESTRICT_BRKCND, ///< Trace restrict: realistic braking related conditionals XSLFI_TRACE_RESTRICT_CTGRYCND, ///< Trace restrict: category conditionals + XSLFI_TRACE_RESTRICT_PENCTRL, ///< Trace restrict: PF penalty control XSLFI_PROG_SIGS, ///< programmable pre-signals patch XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch XSLFI_SAFER_CROSSINGS, ///< Safer level crossings diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 76161a7bf5..47d25ecc81 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -743,6 +743,22 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp break; } + case TRIT_PF_PENALTY_CONTROL: + switch (static_cast(GetTraceRestrictValue(item))) { + case TRPPCF_NO_PBS_BACK_PENALTY: + out.flags |= TRPRF_NO_PBS_BACK_PENALTY; + break; + + case TRPPCF_CANCEL_NO_PBS_BACK_PENALTY: + out.flags &= ~TRPRF_NO_PBS_BACK_PENALTY; + break; + + default: + NOT_REACHED(); + break; + } + break; + default: NOT_REACHED(); } @@ -930,6 +946,10 @@ CommandCost TraceRestrictProgram::Validate(const std::vector actions_used_flags |= TRPAUF_CHANGE_COUNTER; break; + case TRIT_PF_PENALTY_CONTROL: + actions_used_flags |= TRPAUF_NO_PBS_BACK_PENALTY; + break; + default: return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION); } @@ -995,6 +1015,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp case TRVT_NEWS_CONTROL: case TRVT_TIME_DATE_INT: case TRVT_ENGINE_CLASS: + case TRVT_PF_PENALTY_CONTROL: SetTraceRestrictValue(item, 0); if (!IsTraceRestrictTypeAuxSubtype(GetTraceRestrictType(item))) { SetTraceRestrictAuxField(item, 0); diff --git a/src/tracerestrict.h b/src/tracerestrict.h index da06ba0a27..7d8a1fad0f 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -159,6 +159,7 @@ enum TraceRestrictItemType { TRIT_SPEED_RESTRICTION = 49, ///< Speed restriction TRIT_NEWS_CONTROL = 50, ///< News control TRIT_COUNTER = 51, ///< Change counter value + TRIT_PF_PENALTY_CONTROL = 52, ///< Control base signal penalties /* space up to 63 */ }; @@ -280,6 +281,14 @@ enum TraceRestrictNewsControlField { TRNCF_CANCEL_TRAIN_NOT_STUCK = 1, ///< Cancel train is not stuck }; +/** + * TraceRestrictItem value field, for TRIT_PF_PENALTY_CONTROL + */ +enum TraceRestrictPfPenaltyControlField { + TRPPCF_NO_PBS_BACK_PENALTY = 0, ///< Do not apply PBS signal back penalty + TRPPCF_CANCEL_NO_PBS_BACK_PENALTY = 1, ///< Cancel do not apply PBS signal back penalty +}; + /** * TraceRestrictItem value field, for TRIT_COND_TRAIN_STATUS */ @@ -372,6 +381,7 @@ enum TraceRestrictProgramResultFlags { TRPRF_REVERSE = 1 << 5, ///< Reverse behind signal TRPRF_SPEED_RETRICTION_SET = 1 << 6, ///< Speed restriction field set TRPRF_TRAIN_NOT_STUCK = 1 << 7, ///< Train is not stuck + TRPRF_NO_PBS_BACK_PENALTY = 1 << 8, ///< Do not apply PBS back penalty }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) @@ -392,6 +402,7 @@ enum TraceRestrictProgramActionsUsedFlags { TRPAUF_SPEED_RESTRICTION = 1 << 10, ///< Speed restriction TRPAUF_TRAIN_NOT_STUCK = 1 << 11, ///< Train is not stuck TRPAUF_CHANGE_COUNTER = 1 << 12, ///< Change counter value is present + TRPAUF_NO_PBS_BACK_PENALTY = 1 << 13, ///< No PBS back penalty is present }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) @@ -631,6 +642,7 @@ enum TraceRestrictValueType { TRVT_COUNTER_INDEX_INT = 44,///< takes a TraceRestrictCounterID, and an integer in the next item slot TRVT_TIME_DATE_INT = 45,///< takes a TraceRestrictTimeDateValueField, and an integer in the next item slot TRVT_ENGINE_CLASS = 46,///< takes a EngineClass + TRVT_PF_PENALTY_CONTROL = 47,///< takes a TraceRestrictPfPenaltyControlField }; /** @@ -806,6 +818,8 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR out.value_type = TRVT_NEWS_CONTROL; } else if (GetTraceRestrictType(item) == TRIT_COUNTER) { out.value_type = TRVT_COUNTER_INDEX_INT; + } else if (GetTraceRestrictType(item) == TRIT_PF_PENALTY_CONTROL) { + out.value_type = TRVT_PF_PENALTY_CONTROL; } else { out.value_type = TRVT_NONE; } diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 32d06229f2..aa4cd76530 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -157,6 +157,7 @@ static const StringID _program_insert_str[] = { STR_TRACE_RESTRICT_SPEED_RESTRICTION, STR_TRACE_RESTRICT_NEWS_CONTROL, STR_TRACE_RESTRICT_COUNTER_OP, + STR_TRACE_RESTRICT_PF_PENALTY_CONTROL, INVALID_STRING_ID }; static const uint32 _program_insert_else_hide_mask = 8; ///< disable bitmask for else @@ -167,6 +168,7 @@ static const uint32 _program_slot_hide_mask = 0x200; ///< disable bitm static const uint32 _program_reverse_hide_mask = 0x400; ///< disable bitmask for reverse static const uint32 _program_speed_res_hide_mask = 0x800; ///< disable bitmask for speed restriction 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 uint _program_insert_val[] = { TRIT_COND_UNDEFINED, // if block TRIT_COND_UNDEFINED | (TRCF_ELSE << 16), // elif block @@ -182,6 +184,7 @@ static const uint _program_insert_val[] = { TRIT_SPEED_RESTRICTION, // speed restriction TRIT_NEWS_CONTROL, // news control TRIT_COUNTER, // counter operation + TRIT_PF_PENALTY_CONTROL, // penalty control }; /** insert drop down list strings and values */ @@ -377,6 +380,21 @@ static const TraceRestrictDropDownListSet _engine_class_value = { _engine_class_value_str, _engine_class_value_val, }; +static const StringID _pf_penalty_control_value_str[] = { + STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY_SHORT, + STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY_CANCEL_SHORT, + INVALID_STRING_ID +}; +static const uint _pf_penalty_control_value_val[] = { + TRPPCF_NO_PBS_BACK_PENALTY, + TRPPCF_CANCEL_NO_PBS_BACK_PENALTY, +}; + +/** value drop down list for PF penalty control types strings and values */ +static const TraceRestrictDropDownListSet _pf_penalty_control_value = { + _pf_penalty_control_value_str, _pf_penalty_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 @@ -437,6 +455,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG STR_TRACE_RESTRICT_SPEED_RESTRICTION, STR_TRACE_RESTRICT_NEWS_CONTROL, STR_TRACE_RESTRICT_COUNTER_OP, + STR_TRACE_RESTRICT_PF_PENALTY_CONTROL, INVALID_STRING_ID, }; static const uint val_action[] = { @@ -450,6 +469,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG TRIT_SPEED_RESTRICTION, TRIT_NEWS_CONTROL, TRIT_COUNTER, + TRIT_PF_PENALTY_CONTROL, }; static const TraceRestrictDropDownListSet set_action = { str_action, val_action, @@ -521,7 +541,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG if (_settings_client.gui.show_adv_tracerestrict_features) { *hide_mask = 0; } else { - *hide_mask = is_conditional ? 0x1FE0000 : 0x2F0; + *hide_mask = is_conditional ? 0x1FE0000 : 0x6F0; } if (is_conditional && !_settings_game.game_time.time_in_minutes) *hide_mask |= 0x800000; if (is_conditional && _settings_game.vehicle.train_braking_model != TBM_REALISTIC) *hide_mask |= 0x1040000; @@ -1473,6 +1493,22 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric break; } + case TRIT_PF_PENALTY_CONTROL: + switch (static_cast(GetTraceRestrictValue(item))) { + case TRPPCF_NO_PBS_BACK_PENALTY: + instruction_string = STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY; + break; + + case TRPPCF_CANCEL_NO_PBS_BACK_PENALTY: + instruction_string = STR_TRACE_RESTRICT_NO_PBS_BACK_PENALTY_CANCEL; + break; + + default: + NOT_REACHED(); + break; + } + break; + default: NOT_REACHED(); break; @@ -1596,7 +1632,10 @@ public: if (ElseIfInsertionDryRun(false)) disabled &= ~_program_insert_or_if_hide_mask; } } - if (!_settings_client.gui.show_adv_tracerestrict_features) hidden |= _program_slot_hide_mask | _program_wait_pbs_hide_mask | _program_reverse_hide_mask | _program_speed_res_hide_mask | _program_counter_hide_mask; + if (!_settings_client.gui.show_adv_tracerestrict_features) { + hidden |= _program_slot_hide_mask | _program_wait_pbs_hide_mask | _program_reverse_hide_mask | + _program_speed_res_hide_mask | _program_counter_hide_mask | _program_penalty_adj_hide_mask; + } this->ShowDropDownListWithValue(&_program_insert, 0, true, TR_WIDGET_INSERT, disabled, hidden, 0); break; @@ -1785,6 +1824,10 @@ public: this->ShowDropDownListWithValue(&_engine_class_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); break; + case TRVT_PF_PENALTY_CONTROL: + this->ShowDropDownListWithValue(&_pf_penalty_control_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + default: break; } @@ -2851,6 +2894,13 @@ private: GetDropDownStringByValue(&_engine_class_value, GetTraceRestrictValue(item)); break; + case TRVT_PF_PENALTY_CONTROL: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_pf_penalty_control_value, GetTraceRestrictValue(item)); + break; + default: break; }