diff --git a/src/lang/english.txt b/src/lang/english.txt index 11a4725808..5ac2026188 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3269,6 +3269,7 @@ STR_TRACE_RESTRICT_VARIABLE_TRAIN_MAX_TE_WEIGHT_RATIO :max T.E. / weig 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_ORDER_TARGET_DIRECTION :direction of order target 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 @@ -3298,6 +3299,7 @@ STR_TRACE_RESTRICT_CONDITIONAL_TRAIN_STATUS :{STRING} train 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_TARGET_DIRECTION :{STRING} tile of {STRING} {STRING} further {STRING} than this signal tile 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 294e222c4a..d6308a40f6 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -70,7 +70,7 @@ static uint32 saveLC(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_TRACE_RESTRICT, XSCF_NULL, 13, 13, "tracerestrict", nullptr, nullptr, "TRRM,TRRP,TRRS" }, + { XSLFI_TRACE_RESTRICT, XSCF_NULL, 14, 14, "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, 1, 1, "tracerestrict_status_cond", nullptr, nullptr, nullptr }, diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 5459af6286..a3fd6311ea 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -569,6 +569,49 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp break; } + case TRIT_COND_TARGET_DIRECTION: { + const Order *o = nullptr; + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRTDCAF_CURRENT_ORDER: + o = &(v->current_order); + break; + + case TRTDCAF_NEXT_ORDER: + if (v->orders == nullptr) break; + if (v->orders->GetNumOrders() == 0) break; + + const Order *current_order = v->GetOrder(v->cur_real_order_index); + for (const Order *order = v->orders->GetNext(current_order); order != current_order; order = v->orders->GetNext(order)) { + if (order->IsGotoOrder()) { + o = order; + break; + } + } + break; + } + + if (o == nullptr) break; + + TileIndex target = o->GetLocation(v, true); + if (target == INVALID_TILE) break; + + switch (condvalue) { + case DIAGDIR_NE: + result = TestBinaryConditionCommon(item, TileX(target) < TileX(input.tile)); + break; + case DIAGDIR_SE: + result = TestBinaryConditionCommon(item, TileY(target) > TileY(input.tile)); + break; + case DIAGDIR_SW: + result = TestBinaryConditionCommon(item, TileX(target) > TileX(input.tile)); + break; + case DIAGDIR_NW: + result = TestBinaryConditionCommon(item, TileY(target) < TileY(input.tile)); + break; + } + break; + } + default: NOT_REACHED(); } @@ -980,6 +1023,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector case TRIT_COND_CURRENT_ORDER: case TRIT_COND_NEXT_ORDER: case TRIT_COND_LAST_STATION: + case TRIT_COND_TARGET_DIRECTION: actions_used_flags |= TRPAUF_ORDER_CONDITIONALS; break; @@ -1198,6 +1242,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp case TRVT_PF_PENALTY_CONTROL: case TRVT_SPEED_ADAPTATION_CONTROL: case TRVT_SIGNAL_MODE_CONTROL: + case TRVT_ORDER_TARGET_DIAGDIR: SetTraceRestrictValue(item, 0); if (!IsTraceRestrictTypeAuxSubtype(GetTraceRestrictType(item))) { SetTraceRestrictAuxField(item, 0); diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 3bb3abf5e4..bce3a76ffb 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -153,6 +153,7 @@ enum TraceRestrictItemType { 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_TARGET_DIRECTION = 31, ///< Test direction of order target tile relative to this signal tile 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 @@ -259,6 +260,15 @@ enum TraceRestrictPathfinderPenaltyAuxField { /* space up to 3 */ }; +/** + * TraceRestrictItem auxiliary type field, for TRIT_COND_TARGET_DIRECTION + */ +enum TraceRestrictTargetDirectionCondAuxField { + TRTDCAF_CURRENT_ORDER = 0, ///< Current order + TRTDCAF_NEXT_ORDER = 1, ///< Next order + /* space up to 3 */ +}; + /** * TraceRestrictItem value field, for TRIT_WAIT_AT_PBS */ @@ -706,6 +716,7 @@ enum TraceRestrictValueType { TRVT_PF_PENALTY_CONTROL = 47,///< takes a TraceRestrictPfPenaltyControlField TRVT_SPEED_ADAPTATION_CONTROL = 48,///< takes a TraceRestrictSpeedAdaptationControlField TRVT_SIGNAL_MODE_CONTROL = 49,///< takes a TraceRestrictSignalModeControlField + TRVT_ORDER_TARGET_DIAGDIR = 50,///< takes a DiagDirection, and the order type in the auxiliary field }; /** @@ -855,6 +866,11 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR } break; + case TRIT_COND_TARGET_DIRECTION: + out.value_type = TRVT_ORDER_TARGET_DIAGDIR; + out.cond_type = TRCOT_BINARY; + break; + default: NOT_REACHED(); break; diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 2c801ca92b..b31a6262eb 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -397,6 +397,40 @@ static const TraceRestrictDropDownListSet _engine_class_value = { _engine_class_value_str, _engine_class_value_val, }; +static const StringID _diagdir_value_str[] = { + STR_TRACE_RESTRICT_DIRECTION_NE, + STR_TRACE_RESTRICT_DIRECTION_SE, + STR_TRACE_RESTRICT_DIRECTION_SW, + STR_TRACE_RESTRICT_DIRECTION_NW, + INVALID_STRING_ID +}; +static const uint _diagdir_value_val[] = { + DIAGDIR_NE, + DIAGDIR_SE, + DIAGDIR_SW, + DIAGDIR_NW, +}; + +/** value drop down list for DiagDirection strings and values */ +static const TraceRestrictDropDownListSet _diagdir_value = { + _diagdir_value_str, _diagdir_value_val, +}; + +static const StringID _dtarget_direction_aux_value_str[] = { + STR_TRACE_RESTRICT_VARIABLE_CURRENT_ORDER, + STR_TRACE_RESTRICT_VARIABLE_NEXT_ORDER, + INVALID_STRING_ID +}; +static const uint _target_direction_aux_value_val[] = { + TRTDCAF_CURRENT_ORDER, + TRTDCAF_NEXT_ORDER, +}; + +/** value drop down list for TRIT_COND_TARGET_DIRECTION auxiliary type strings and values */ +static const TraceRestrictDropDownListSet _target_direction_aux_value = { + _dtarget_direction_aux_value_str, _target_direction_aux_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, @@ -553,6 +587,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG 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_ORDER_TARGET_DIRECTION, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED, INVALID_STRING_ID, }; @@ -583,6 +618,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG TRIT_COND_TIME_DATE_VALUE, TRIT_COND_RESERVED_TILES, // 0x1000000 TRIT_COND_PBS_ENTRY_SIGNAL | (TRPESAF_RES_END_TILE << 16), + TRIT_COND_TARGET_DIRECTION, TRIT_COND_UNDEFINED, }; static const TraceRestrictDropDownListSet set_cond = { @@ -786,7 +822,7 @@ static const uint _train_status_cond_ops_val[] = { TRCO_IS, TRCO_ISNOT, }; -/** cargo conditional operators dropdown list set */ +/** train status conditional operators dropdown list set */ static const TraceRestrictDropDownListSet _train_status_cond_ops = { _train_status_cond_ops_str, _train_status_cond_ops_val, }; @@ -1439,6 +1475,15 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric SetDParam(2, GetDropDownStringByValue(&_engine_class_value, GetTraceRestrictValue(item))); break; + case TRVT_ORDER_TARGET_DIAGDIR: + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_TARGET_DIRECTION; + assert(GetTraceRestrictCondFlags(item) <= TRCF_OR); + SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); + SetDParam(1, GetDropDownStringByValue(&_target_direction_aux_value, GetTraceRestrictAuxField(item))); + SetDParam(2, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item))); + SetDParam(3, GetDropDownStringByValue(&_diagdir_value, GetTraceRestrictValue(item))); + break; + default: NOT_REACHED(); break; @@ -2028,6 +2073,10 @@ public: this->ShowDropDownListWithValue(&_signal_mode_control_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); break; + case TRVT_ORDER_TARGET_DIAGDIR: + this->ShowDropDownListWithValue(&_diagdir_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + default: break; } @@ -2056,6 +2105,11 @@ public: break; } + case TRVT_ORDER_TARGET_DIAGDIR: { + this->ShowDropDownListWithValue(&_target_direction_aux_value, GetTraceRestrictAuxField(item), false, TR_WIDGET_LEFT_AUX_DROPDOWN, 0, 0, 0); + break; + } + default: break; } @@ -2172,6 +2226,11 @@ public: TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); return; } + if (type.value_type == TRVT_ORDER_TARGET_DIAGDIR && widget == TR_WIDGET_LEFT_AUX_DROPDOWN) { + SetTraceRestrictAuxField(item, index); + TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); + return; + } } const TraceRestrictDropDownListSet *list_set = this->drop_down_list_mapping[widget]; @@ -3169,6 +3228,17 @@ private: GetDropDownStringByValue(&_signal_mode_control_value, GetTraceRestrictValue(item)); break; + case TRVT_ORDER_TARGET_DIAGDIR: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + left_aux_sel->SetDisplayedPlane(DPLA_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_LEFT_AUX_DROPDOWN); + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_diagdir_value, GetTraceRestrictValue(item)); + this->GetWidget(TR_WIDGET_LEFT_AUX_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_target_direction_aux_value, GetTraceRestrictAuxField(item)); + break; + default: break; }