diff --git a/src/lang/english.txt b/src/lang/english.txt index d5442b4fba..5638c7f1a3 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2556,7 +2556,11 @@ STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION :entry direction STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL :PBS entry signal STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG :entered signal of PBS block STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP :train group -STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :slot +STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT :train in slot +STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY :slot occupancy +STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY_REMAINING :slot occupancy remaining +STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY_SHORT :occupancy +STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY_REMAINING_SHORT :occupancy remaining STR_TRACE_RESTRICT_VARIABLE_TRAIN_WEIGHT :weight STR_TRACE_RESTRICT_VARIABLE_TRAIN_POWER :power STR_TRACE_RESTRICT_VARIABLE_TRAIN_MAX_TE :max T.E. @@ -2584,6 +2588,8 @@ STR_TRACE_RESTRICT_CONDITIONAL_GROUP_STR :{STRING} train STR_TRACE_RESTRICT_CONDITIONAL_OWNER :{STRING} {STRING} {STRING} {COMPANY} {COMPANY_NUM} then STR_TRACE_RESTRICT_CONDITIONAL_SLOT :{STRING} train {STRING} in slot: {TRSLOT} then STR_TRACE_RESTRICT_CONDITIONAL_SLOT_STR :{STRING} train {STRING} in slot: {STRING} {BLACK}{STRING}then +STR_TRACE_RESTRICT_CONDITIONAL_SLOT_OCCUPANCY :{STRING} {STRING} of slot: {TRSLOT} {STRING} {COMMA} then +STR_TRACE_RESTRICT_CONDITIONAL_SLOT_OCCUPANCY_STR :{STRING} {STRING} of slot: {STRING} {BLACK}{STRING} {STRING} {COMMA} 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 f5c0264126..9a78eb7863 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -47,7 +47,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_TRACE_RESTRICT, XSCF_NULL, 7, 7, "tracerestrict", NULL, NULL, "TRRM,TRRP,TRRS" }, + { XSLFI_TRACE_RESTRICT, XSCF_NULL, 8, 8, "tracerestrict", NULL, NULL, "TRRM,TRRP,TRRS" }, { XSLFI_TRACE_RESTRICT_OWNER, XSCF_NULL, 1, 1, "tracerestrict_owner", NULL, NULL, NULL }, { XSLFI_PROG_SIGS, XSCF_NULL, 1, 1, "programmable_signals", NULL, NULL, "SPRG" }, { XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", NULL, NULL, NULL }, diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index aed18cf1f2..384a8ba717 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -21,6 +21,9 @@ #include "group.h" #include "string_func.h" #include "pathfinder/yapf/yapf_cache.h" + +#include "safeguards.h" + #include #include @@ -144,7 +147,7 @@ static void HandleCondition(std::vector &condstack, * Integer condition testing * Test value op condvalue */ -static bool TestCondition(uint16 value, TraceRestrictCondOp condop, uint16 condvalue) +static bool TestCondition(int value, TraceRestrictCondOp condop, int condvalue) { switch (condop) { case TRCO_IS: @@ -354,12 +357,33 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp break; } - case TRIT_COND_SLOT: { + case TRIT_COND_TRAIN_IN_SLOT: { const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(GetTraceRestrictValue(item)); result = TestBinaryConditionCommon(item, slot != NULL && slot->IsOccupant(v->index)); break; } + case TRIT_COND_SLOT_OCCUPANCY: { + // TRIT_COND_SLOT_OCCUPANCY value type uses the next slot + i++; + uint32_t value = this->items[i]; + const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(GetTraceRestrictValue(item)); + switch (static_cast(GetTraceRestrictAuxField(item))) { + case TRSOCAF_OCCUPANTS: + result = TestCondition(slot != NULL ? slot->occupants.size() : 0, condop, value); + break; + + case TRSOCAF_REMAINING: + result = TestCondition(slot != NULL ? slot->max_occupancy - slot->occupants.size() : 0, condop, value); + break; + + default: + NOT_REACHED(); + break; + } + break; + } + case TRIT_COND_PHYS_PROP: { switch (static_cast(GetTraceRestrictAuxField(item))) { case TRPPCAF_WEIGHT: @@ -578,7 +602,8 @@ CommandCost TraceRestrictProgram::Validate(const std::vector case TRIT_COND_ENTRY_DIRECTION: case TRIT_COND_PBS_ENTRY_SIGNAL: case TRIT_COND_TRAIN_GROUP: - case TRIT_COND_SLOT: + case TRIT_COND_TRAIN_IN_SLOT: + case TRIT_COND_SLOT_OCCUPANCY: case TRIT_COND_PHYS_PROP: case TRIT_COND_PHYS_RATIO: case TRIT_COND_TRAIN_OWNER: @@ -731,6 +756,10 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp SetTraceRestrictAuxField(item, 0); break; + case TRVT_SLOT_INDEX_INT: + SetTraceRestrictValue(item, INVALID_TRACE_RESTRICT_SLOT_ID); + break; + default: NOT_REACHED(); break; @@ -934,6 +963,9 @@ static uint32 GetDualInstructionInitialValue(TraceRestrictItem item) case TRIT_COND_PBS_ENTRY_SIGNAL: return INVALID_TILE; + case TRIT_COND_SLOT_OCCUPANCY: + return 0; + default: NOT_REACHED(); } @@ -1532,9 +1564,12 @@ void TraceRestrictRemoveSlotID(TraceRestrictSlotID index) FOR_ALL_TRACE_RESTRICT_PROGRAMS(prog) { for (size_t i = 0; i < prog->items.size(); i++) { TraceRestrictItem &item = prog->items[i]; // note this is a reference, - if ((GetTraceRestrictType(item) == TRIT_SLOT || GetTraceRestrictType(item) == TRIT_COND_SLOT) && GetTraceRestrictValue(item) == index) { + if ((GetTraceRestrictType(item) == TRIT_SLOT || GetTraceRestrictType(item) == TRIT_COND_TRAIN_IN_SLOT) && GetTraceRestrictValue(item) == index) { SetTraceRestrictValueDefault(item, TRVT_SLOT_INDEX); // this updates the instruction in-place } + if ((GetTraceRestrictType(item) == TRIT_COND_SLOT_OCCUPANCY) && GetTraceRestrictValue(item) == index) { + SetTraceRestrictValueDefault(item, TRVT_SLOT_INDEX_INT); // this updates the instruction in-place + } if (IsTraceRestrictDoubleItem(item)) i++; } } diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 7db959d0bf..bfe8a844d7 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -134,7 +134,8 @@ enum TraceRestrictItemType { TRIT_COND_TRAIN_GROUP = 18, ///< Test train group membership TRIT_COND_PHYS_PROP = 19, ///< Test train physical property TRIT_COND_PHYS_RATIO = 20, ///< Test train physical property ratio - TRIT_COND_SLOT = 21, ///< Test train slot membership + TRIT_COND_TRAIN_IN_SLOT = 21, ///< Test train slot membership + TRIT_COND_SLOT_OCCUPANCY = 22, ///< Test train slot occupancy state TRIT_COND_TRAIN_OWNER = 24, ///< Test train owner /* space up to 31 */ }; @@ -233,6 +234,15 @@ enum TraceRestrictSlotCondOpField { /* space up to 8 */ }; +/** + * TraceRestrictItem auxiliary type field, for TRIT_COND_SLOT_OCCUPANCY + */ +enum TraceRestrictSlotOccupancyCondAuxField { + TRSOCAF_OCCUPANTS = 0, ///< value field is the occupancy count of the slot + TRSOCAF_REMAINING = 1, ///< value field is the remaining occupancy of the slot + /* space up to 3 */ +}; + /** * TraceRestrictItem pathfinder penalty preset index * This may not be shortened, only lengthened, as preset indexes are stored in save games @@ -452,7 +462,8 @@ static inline bool IsTraceRestrictConditional(TraceRestrictItem item) /** Is TraceRestrictItem a double-item type? */ static inline bool IsTraceRestrictDoubleItem(TraceRestrictItem item) { - return GetTraceRestrictType(item) == TRIT_COND_PBS_ENTRY_SIGNAL; + const TraceRestrictItemType type = GetTraceRestrictType(item); + return type == TRIT_COND_PBS_ENTRY_SIGNAL || type == TRIT_COND_SLOT_OCCUPANCY; } /** @@ -490,6 +501,7 @@ enum TraceRestrictValueType { TRVT_FORCE_WEIGHT_RATIO = 17,///< takes a force / weight ratio, * 100 TRVT_WAIT_AT_PBS = 18,///< takes a value 0 = wait at PBS signal, 1 = cancel wait at PBS signal TRVT_SLOT_INDEX = 19,///< takes a TraceRestrictSlotID + TRVT_SLOT_INDEX_INT = 20,///< takes a TraceRestrictSlotID, and an integer in the next item slot TRVT_OWNER = 40,///< takes a CompanyID }; @@ -557,11 +569,15 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR out.cond_type = TRCOT_BINARY; break; - case TRIT_COND_SLOT: + case TRIT_COND_TRAIN_IN_SLOT: out.value_type = TRVT_SLOT_INDEX; out.cond_type = TRCOT_BINARY; break; + case TRIT_COND_SLOT_OCCUPANCY: + out.value_type = TRVT_SLOT_INDEX_INT; + break; + case TRIT_COND_PHYS_PROP: switch (static_cast(GetTraceRestrictAuxField(item))) { case TRPPCAF_WEIGHT: @@ -635,6 +651,7 @@ static inline bool IsTraceRestrictTypeAuxSubtype(TraceRestrictItemType type) switch (type) { case TRIT_COND_PHYS_PROP: case TRIT_COND_PHYS_RATIO: + case TRIT_COND_SLOT_OCCUPANCY: return true; default: diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index ea90f1f8b1..31edbbd3fc 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -42,10 +42,13 @@ #include "vehicle_base.h" #include "vehicle_gui.h" #include "vehicle_gui_base.h" +#include "scope.h" #include "table/sprites.h" #include "toolbar_gui.h" #include "core/geometry_func.hpp" +#include "safeguards.h" + /** Widget IDs */ enum TraceRestrictWindowWidgets { TR_WIDGET_CAPTION, @@ -54,6 +57,7 @@ enum TraceRestrictWindowWidgets { TR_WIDGET_SEL_TOP_LEFT_2, TR_WIDGET_SEL_TOP_LEFT, + TR_WIDGET_SEL_TOP_LEFT_AUX, TR_WIDGET_SEL_TOP_MIDDLE, TR_WIDGET_SEL_TOP_RIGHT, TR_WIDGET_SEL_SHARE, @@ -71,6 +75,7 @@ enum TraceRestrictWindowWidgets { TR_WIDGET_VALUE_DROPDOWN, TR_WIDGET_VALUE_DEST, TR_WIDGET_VALUE_SIGNAL, + TR_WIDGET_LEFT_AUX_DROPDOWN, TR_WIDGET_BLANK_L2, TR_WIDGET_BLANK_L, @@ -97,6 +102,9 @@ enum PanelWidgets { DPL_TYPE = 0, DPL_BLANK, + // Left aux + DPLA_DROPDOWN = 0, + // Middle DPM_COMPARATOR = 0, DPM_SLOT_OP, @@ -333,6 +341,8 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG STR_TRACE_RESTRICT_VARIABLE_TRAIN_POWER_WEIGHT_RATIO, STR_TRACE_RESTRICT_VARIABLE_TRAIN_MAX_TE_WEIGHT_RATIO, STR_TRACE_RESTRICT_VARIABLE_TRAIN_SLOT, + STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY, + STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY_REMAINING, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED, INVALID_STRING_ID, }; @@ -352,7 +362,9 @@ 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_SLOT, + TRIT_COND_TRAIN_IN_SLOT, + TRIT_COND_SLOT_OCCUPANCY | (TRSOCAF_OCCUPANTS << 16), + TRIT_COND_SLOT_OCCUPANCY | (TRSOCAF_REMAINING << 16), TRIT_COND_UNDEFINED, }; static const TraceRestrictDropDownListSet set_cond = { @@ -364,7 +376,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictG if (_settings_client.gui.show_adv_tracerestrict_features) { *hide_mask = 0; } else { - *hide_mask = is_conditional ? 0x8000 : 0x30; + *hide_mask = is_conditional ? 0x38000 : 0x30; } } return is_conditional ? &set_cond : &set_action; @@ -959,6 +971,27 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric } break; + case TRVT_SLOT_INDEX_INT: { + assert(prog != NULL); + assert(GetTraceRestrictType(item) == TRIT_COND_SLOT_OCCUPANCY); + uint32 value = *(TraceRestrictProgram::InstructionAt(prog->items, index - 1) + 1); + SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); + SetDParam(1, GetTraceRestrictAuxField(item) ? STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY_REMAINING_SHORT : STR_TRACE_RESTRICT_VARIABLE_SLOT_OCCUPANCY_SHORT); + if (GetTraceRestrictValue(item) == INVALID_TRACE_RESTRICT_SLOT_ID) { + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_SLOT_OCCUPANCY_STR; + SetDParam(2, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED_RED); + SetDParam(3, selected ? STR_TRACE_RESTRICT_WHITE : STR_EMPTY); + SetDParam(4, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item))); + SetDParam(5, value); + } else { + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_SLOT_OCCUPANCY; + SetDParam(2, GetTraceRestrictValue(item)); + SetDParam(3, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item))); + SetDParam(4, value); + } + break; + } + default: NOT_REACHED(); break; @@ -1068,6 +1101,7 @@ class TraceRestrictWindow: public Window { bool value_drop_down_is_company; ///< TR_WIDGET_VALUE_DROPDOWN is a company list TraceRestrictItem expecting_inserted_item; ///< set to instruction when performing an instruction insertion, used to handle selection update on insertion int current_placement_widget; ///< which widget has a SetObjectToPlaceWnd, if any + int current_left_aux_plane; ///< current plane for TR_WIDGET_SEL_TOP_LEFT_AUX widget public: TraceRestrictWindow(WindowDesc *desc, TileIndex tile, Track track) @@ -1081,6 +1115,8 @@ public: this->CreateNestedTree(); this->vscroll = this->GetScrollbar(TR_WIDGET_SCROLLBAR); + this->GetWidget(TR_WIDGET_SEL_TOP_LEFT_AUX)->SetDisplayedPlane(SZSP_NONE); + this->current_left_aux_plane = SZSP_NONE; this->FinishInitNested(MakeTraceRestrictRefId(tile, track)); this->ReloadProgramme(); @@ -1264,6 +1300,9 @@ public: if (IsIntegerValueType(type)) { SetDParam(0, ConvertIntegerValue(type, GetTraceRestrictValue(item), true)); ShowQueryString(STR_JUST_INT, STR_TRACE_RESTRICT_VALUE_CAPTION, 10, this, CS_NUMERAL, QSF_NONE); + } else if (type == TRVT_SLOT_INDEX_INT) { + SetDParam(0, *(TraceRestrictProgram::InstructionAt(this->GetProgram()->items, this->selected_instruction - 1) + 1)); + ShowQueryString(STR_JUST_INT, STR_TRACE_RESTRICT_VALUE_CAPTION, 10, this, CS_NUMERAL, QSF_NONE); } break; } @@ -1339,6 +1378,22 @@ public: break; } + case TR_WIDGET_LEFT_AUX_DROPDOWN: { + TraceRestrictItem item = this->GetSelected(); + switch (GetTraceRestrictTypeProperties(item).value_type) { + case TRVT_SLOT_INDEX_INT: { + int selected; + DropDownList *dlist = GetSlotDropDownList(this->GetOwner(), + *(TraceRestrictProgram::InstructionAt(this->GetProgram()->items, this->selected_instruction - 1) + 1), selected); + if (dlist != NULL) ShowDropDownList(this, dlist, selected, TR_WIDGET_LEFT_AUX_DROPDOWN); + break; + } + + default: + break; + } + } + case TR_WIDGET_VALUE_DEST: { SetObjectToPlaceAction(widget, ANIMCURSOR_PICKSTATION); break; @@ -1407,6 +1462,10 @@ public: ShowErrorMessage(STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE, STR_EMPTY, WL_INFO); return; } + } else if (type == TRVT_SLOT_INDEX_INT) { + value = atoi(str); + TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_DUAL_ITEM, this->selected_instruction - 1, value, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); + return; } else { return; } @@ -1422,9 +1481,9 @@ public: return; } - if (widget == TR_WIDGET_VALUE_DROPDOWN) { + if (widget == TR_WIDGET_VALUE_DROPDOWN || widget == TR_WIDGET_LEFT_AUX_DROPDOWN) { TraceRestrictTypePropertySet type = GetTraceRestrictTypeProperties(item); - if (this->value_drop_down_is_company || type.value_type == TRVT_GROUP_INDEX || type.value_type == TRVT_SLOT_INDEX) { + if (this->value_drop_down_is_company || type.value_type == TRVT_GROUP_INDEX || type.value_type == TRVT_SLOT_INDEX || type.value_type == TRVT_SLOT_INDEX_INT) { // this is a special company drop-down or group/slot-index drop-down SetTraceRestrictValue(item, index); TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM); @@ -1745,6 +1804,8 @@ public: TraceRestrictValueType type = GetTraceRestrictTypeProperties(item).value_type; if (IsIntegerValueType(type)) { SetDParam(0, ConvertIntegerValue(type, GetTraceRestrictValue(item), true)); + } else if (type == TRVT_SLOT_INDEX_INT) { + SetDParam(0, *(TraceRestrictProgram::InstructionAt(this->GetProgram()->items, this->selected_instruction - 1) + 1)); } break; } @@ -1784,6 +1845,15 @@ public: } break; } + + case TR_WIDGET_LEFT_AUX_DROPDOWN: { + TraceRestrictItem item = this->GetSelected(); + TraceRestrictTypePropertySet type = GetTraceRestrictTypeProperties(item); + if (type.value_type == TRVT_SLOT_INDEX_INT) { + SetDParam(0, GetTraceRestrictValue(item)); + } + break; + } } } @@ -1955,9 +2025,11 @@ private: this->RaiseWidget(TR_WIDGET_VALUE_DROPDOWN); this->RaiseWidget(TR_WIDGET_VALUE_DEST); this->RaiseWidget(TR_WIDGET_VALUE_SIGNAL); + this->RaiseWidget(TR_WIDGET_LEFT_AUX_DROPDOWN); NWidgetStacked *left_2_sel = this->GetWidget(TR_WIDGET_SEL_TOP_LEFT_2); NWidgetStacked *left_sel = this->GetWidget(TR_WIDGET_SEL_TOP_LEFT); + NWidgetStacked *left_aux_sel = this->GetWidget(TR_WIDGET_SEL_TOP_LEFT_AUX); NWidgetStacked *middle_sel = this->GetWidget(TR_WIDGET_SEL_TOP_MIDDLE); NWidgetStacked *right_sel = this->GetWidget(TR_WIDGET_SEL_TOP_RIGHT); NWidgetStacked *share_sel = this->GetWidget(TR_WIDGET_SEL_SHARE); @@ -1972,6 +2044,7 @@ private: this->DisableWidget(TR_WIDGET_VALUE_DROPDOWN); this->DisableWidget(TR_WIDGET_VALUE_DEST); this->DisableWidget(TR_WIDGET_VALUE_SIGNAL); + this->DisableWidget(TR_WIDGET_LEFT_AUX_DROPDOWN); this->DisableWidget(TR_WIDGET_INSERT); this->DisableWidget(TR_WIDGET_REMOVE); @@ -1990,6 +2063,7 @@ private: left_2_sel->SetDisplayedPlane(DPL2_BLANK); left_sel->SetDisplayedPlane(DPL_BLANK); + left_aux_sel->SetDisplayedPlane(SZSP_NONE); middle_sel->SetDisplayedPlane(DPM_BLANK); right_sel->SetDisplayedPlane(DPR_BLANK); share_sel->SetDisplayedPlane(DPS_SHARE); @@ -1999,6 +2073,13 @@ private: this->GetWidget(TR_WIDGET_CAPTION)->widget_data = (prog && prog->refcount > 1) ? STR_TRACE_RESTRICT_CAPTION_SHARED : STR_TRACE_RESTRICT_CAPTION; + auto left_aux_guard = scope_guard([&]() { + if (this->current_left_aux_plane != left_aux_sel->shown_plane) { + this->current_left_aux_plane = left_aux_sel->shown_plane; + this->ReInit(); + } + }); + // Don't allow modifications if don't own if (this->GetOwner() != _local_company) { this->SetDirty(); @@ -2199,7 +2280,7 @@ private: this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = STR_TRACE_RESTRICT_COMPANY; break; - case TRVT_SLOT_INDEX: + case TRVT_SLOT_INDEX: { right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); if (!IsTraceRestrictConditional(item)) { middle_sel->SetDisplayedPlane(DPM_SLOT_OP); @@ -2226,6 +2307,32 @@ private: break; } break; + } + + case TRVT_SLOT_INDEX_INT: { + right_sel->SetDisplayedPlane(DPR_VALUE_INT); + left_aux_sel->SetDisplayedPlane(DPLA_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_INT); + + const TraceRestrictSlot *slot; + FOR_ALL_TRACE_RESTRICT_SLOTS(slot) { + if (slot->owner == this->GetOwner()) { + this->EnableWidget(TR_WIDGET_LEFT_AUX_DROPDOWN); + break; + } + } + + switch (GetTraceRestrictValue(item)) { + case INVALID_TRACE_RESTRICT_SLOT_ID: + this->GetWidget(TR_WIDGET_LEFT_AUX_DROPDOWN)->widget_data = STR_TRACE_RESTRICT_VARIABLE_UNDEFINED; + break; + + default: + this->GetWidget(TR_WIDGET_LEFT_AUX_DROPDOWN)->widget_data = STR_TRACE_RESTRICT_SLOT_NAME; + break; + } + break; + } default: break; @@ -2383,6 +2490,10 @@ static const NWidgetPart _nested_program_widgets[] = { NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_BLANK_L), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_EMPTY, STR_NULL), SetResize(1, 0), EndContainer(), + NWidget(NWID_SELECTION, INVALID_COLOUR, TR_WIDGET_SEL_TOP_LEFT_AUX), + NWidget(WWT_DROPDOWN, COLOUR_GREY, TR_WIDGET_LEFT_AUX_DROPDOWN), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_NULL, STR_TRACE_RESTRICT_COND_VALUE_TOOLTIP), SetResize(1, 0), + EndContainer(), NWidget(NWID_SELECTION, INVALID_COLOUR, TR_WIDGET_SEL_TOP_MIDDLE), NWidget(WWT_DROPDOWN, COLOUR_GREY, TR_WIDGET_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_NULL, STR_TRACE_RESTRICT_COND_COMPARATOR_TOOLTIP), SetResize(1, 0),