diff --git a/src/lang/english.txt b/src/lang/english.txt index 0a015eb20f..9211dda22a 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2893,6 +2893,7 @@ STR_TRACE_RESTRICT_VARIABLE_TRAIN_POWER_WEIGHT_RATIO :power / weight STR_TRACE_RESTRICT_VARIABLE_TRAIN_MAX_TE_WEIGHT_RATIO :max T.E. / weight ratio STR_TRACE_RESTRICT_VARIABLE_TRAIN_OWNER :train owner STR_TRACE_RESTRICT_VARIABLE_TRAIN_STATUS :train status +STR_TRACE_RESTRICT_VARIABLE_TRAIN_ENGINE_CLASS :engine class STR_TRACE_RESTRICT_VARIABLE_UNDEFINED :undefined STR_TRACE_RESTRICT_VARIABLE_UNDEFINED_RED :{RED}undefined STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_INTEGER :{STRING} {STRING} {STRING} {COMMA} then @@ -2920,6 +2921,7 @@ STR_TRACE_RESTRICT_CONDITIONAL_SLOT_OCCUPANCY_STR :{STRING} {STRIN STR_TRACE_RESTRICT_CONDITIONAL_TRAIN_STATUS :{STRING} train {STRING} status: {STRING} then STR_TRACE_RESTRICT_CONDITIONAL_COUNTER :{STRING} value of counter: {TRCOUNTER} {STRING} {COMMA} then STR_TRACE_RESTRICT_CONDITIONAL_COUNTER_STR :{STRING} value of counter: {STRING} {BLACK}{STRING} {STRING} {COMMA} then +STR_TRACE_RESTRICT_CONDITIONAL_ENGINE_CLASSES :{STRING} train {STRING}: {STRING} then STR_TRACE_RESTRICT_CONDITIONAL_UNDEFINED :{STRING} {STRING} {STRING} {RED}undefined {BLACK}{STRING}then STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_UNDEFINED :{STRING} {RED}undefined {BLACK}{STRING}then STR_TRACE_RESTRICT_PF_PENALTY_ITEM :Add pathfinder penalty: {COMMA} diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 58840bb7aa..fe76d575f3 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -77,6 +77,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { 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, 2, 2, "tracerestrict_braking_cond",nullptr, nullptr, nullptr }, + { XSLFI_TRACE_RESTRICT_CTGRYCND,XSCF_NULL, 1, 1, "tracerestrict_ctgry_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 }, diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 80a7e60e98..c8756737d8 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -31,6 +31,7 @@ enum SlXvFeatureIndex { 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_TRACE_RESTRICT_CTGRYCND, ///< Trace restrict: category conditionals 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 ae2eb18812..27693af07d 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -536,6 +536,28 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp break; } + case TRIT_COND_CATEGORY: { + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRCCAF_ENGINE_CLASS: { + EngineClass ec = (EngineClass)condvalue; + result = (GetTraceRestrictCondOp(item) != TRCO_IS); + for (const Train *u = v; u != nullptr; u = u->Next()) { + /* Check if engine class present */ + if (u->IsEngine() && RailVehInfo(u->engine_type)->engclass == ec) { + result = !result; + break; + } + } + break; + } + + default: + NOT_REACHED(); + break; + } + break; + } + default: NOT_REACHED(); } @@ -820,6 +842,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector case TRIT_COND_COUNTER_VALUE: case TRIT_COND_TIME_DATE_VALUE: case TRIT_COND_RESERVED_TILES: + case TRIT_COND_CATEGORY: break; default: @@ -971,6 +994,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp case TRVT_PERCENT: case TRVT_NEWS_CONTROL: case TRVT_TIME_DATE_INT: + case TRVT_ENGINE_CLASS: SetTraceRestrictValue(item, 0); if (!IsTraceRestrictTypeAuxSubtype(GetTraceRestrictType(item))) { SetTraceRestrictAuxField(item, 0); diff --git a/src/tracerestrict.h b/src/tracerestrict.h index de74cd46ab..8d76e08a1f 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -152,6 +152,7 @@ enum TraceRestrictItemType { TRIT_COND_COUNTER_VALUE = 27, ///< Test counter value TRIT_COND_TIME_DATE_VALUE = 28, ///< Test time/date value TRIT_COND_RESERVED_TILES = 29, ///< Test reserved tiles ahead of train + TRIT_COND_CATEGORY = 30, ///< Test train category TRIT_COND_END = 48, ///< End (exclusive) of conditional item types, note that this has the same value as TRIT_REVERSE TRIT_REVERSE = 48, ///< Reverse behind signal @@ -236,6 +237,14 @@ enum TraceRestrictPhysPropRatioCondAuxField { /* space up to 3 */ }; +/** + * TraceRestrictItem auxiliary type field, for category type conditionals + */ +enum TraceRestrictCatgeoryCondAuxField { + TRCCAF_ENGINE_CLASS = 0, ///< value field is an EngineClass type + /* space up to 3 */ +}; + /** * TraceRestrictItem auxiliary type field, for TRIT_PF_PENALTY */ @@ -621,6 +630,7 @@ enum TraceRestrictValueType { TRVT_NEWS_CONTROL = 43,///< takes a TraceRestrictNewsControlField 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 }; /** @@ -758,6 +768,18 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR out.value_type = TRVT_INT; break; + case TRIT_COND_CATEGORY: + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRCCAF_ENGINE_CLASS: + out.value_type = TRVT_ENGINE_CLASS; + break; + + default: + NOT_REACHED(); + break; + } + break; + default: NOT_REACHED(); break; @@ -800,6 +822,7 @@ static inline bool IsTraceRestrictTypeAuxSubtype(TraceRestrictItemType type) case TRIT_COND_PHYS_RATIO: case TRIT_COND_SLOT_OCCUPANCY: case TRIT_COND_PBS_ENTRY_SIGNAL: + case TRIT_COND_CATEGORY: return true; default: diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index ac60b87b8c..0de3c40028 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -356,6 +356,27 @@ static const TraceRestrictDropDownListSet _time_date_value = { _time_date_value_str, _time_date_value_val, }; +static const StringID _engine_class_value_str[] = { + STR_LIVERY_STEAM, + STR_LIVERY_DIESEL, + STR_LIVERY_ELECTRIC, + STR_LIVERY_MONORAIL, + STR_LIVERY_MAGLEV, + INVALID_STRING_ID +}; +static const uint _engine_class_value_val[] = { + EC_STEAM, ///< Steam rail engine. + EC_DIESEL, ///< Diesel rail engine. + EC_ELECTRIC, ///< Electric rail engine. + EC_MONORAIL, ///< Mono rail engine. + EC_MAGLEV, ///< Maglev engine. +}; + +/** value drop down list for engine class type strings and values */ +static const TraceRestrictDropDownListSet _engine_class_value = { + _engine_class_value_str, _engine_class_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 @@ -451,6 +472,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG STR_TRACE_RESTRICT_VARIABLE_TRAIN_MAX_TE, STR_TRACE_RESTRICT_VARIABLE_TRAIN_POWER_WEIGHT_RATIO, STR_TRACE_RESTRICT_VARIABLE_TRAIN_MAX_TE_WEIGHT_RATIO, + STR_TRACE_RESTRICT_VARIABLE_TRAIN_ENGINE_CLASS, STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL, STR_TRACE_RESTRICT_VARIABLE_PBS_RES_END_SIGNAL, STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT, @@ -479,6 +501,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG 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_PBS_ENTRY_SIGNAL | (TRPESAF_VEH_POS << 16), TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_RES_END << 16), TRIT_COND_TRAIN_IN_SLOT, @@ -498,10 +521,10 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG if (_settings_client.gui.show_adv_tracerestrict_features) { *hide_mask = 0; } else { - *hide_mask = is_conditional ? 0xFF0000 : 0x2F0; + *hide_mask = is_conditional ? 0x1FE0000 : 0x2F0; } - 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 |= 0x820000; + 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; } return is_conditional ? &set_cond : &set_action; } @@ -770,6 +793,7 @@ static const TraceRestrictDropDownListSet *GetCondOpDropDownListSet(TraceRestric if (properties.value_type == TRVT_CARGO_ID) return &_cargo_cond_ops; if (properties.value_type == TRVT_TRAIN_STATUS) return &_train_status_cond_ops; + if (properties.value_type == TRVT_ENGINE_CLASS) return &_train_status_cond_ops; switch (properties.cond_type) { case TRCOT_NONE: @@ -1248,6 +1272,14 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric break; } + case TRVT_ENGINE_CLASS: + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_ENGINE_CLASSES; + assert(GetTraceRestrictCondFlags(item) <= TRCF_OR); + SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); + SetDParam(1, GetDropDownStringByValue(&_train_status_cond_ops, GetTraceRestrictCondOp(item))); + SetDParam(2, GetDropDownStringByValue(&_engine_class_value, GetTraceRestrictValue(item))); + break; + default: NOT_REACHED(); break; @@ -1749,6 +1781,10 @@ public: this->ShowDropDownListWithValue(&_news_control_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); break; + case TRVT_ENGINE_CLASS: + this->ShowDropDownListWithValue(&_engine_class_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + default: break; } @@ -2808,6 +2844,13 @@ private: break; } + case TRVT_ENGINE_CLASS: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_engine_class_value, GetTraceRestrictValue(item)); + break; + default: break; }