diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 66c3e94360..3b01c3aa09 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -1636,9 +1636,11 @@ STR_ORDER_APPEND_REVERSED_ORDER_LIST :Append reversed STR_ORDER_DUPLICATE_ORDER :Duplicate order STR_ORDER_CHANGE_JUMP_TARGET :Change jump target +STR_ORDER_TRY_ACQUIRE_SLOT_BUTTON :Try acquire slot STR_ORDER_RELEASE_SLOT_BUTTON :Release slot STR_ORDER_CHANGE_COUNTER_BUTTON :Change counter STR_ORDER_RELEASE_SLOT_TOOLTIP :{BLACK}The train slot to release +STR_ORDER_TRY_ACQUIRE_SLOT_TOOLTIP :{BLACK}The train slot to try to acquire STR_ORDER_CHANGE_COUNTER_TOOLTIP :{BLACK}The counter to change @@ -1706,6 +1708,7 @@ STR_ORDER_CONDITIONAL_TIME_HHMM :Jump to order { STR_ORDER_CONDITIONAL_TIMETABLE :Jump to order {COMMA} when {STRING} {STRING} {TT_TICKS} STR_ORDER_CONDITIONAL_DISPATCH_SLOT_DISPLAY :Jump to order {COMMA} when {STRING} {STRING} {STRING} +STR_ORDER_TRY_ACQUIRE_SLOT :Try to acquire slot: {STRING1} STR_ORDER_RELEASE_SLOT :Release slot: {STRING1} STR_TIMETABLE_MINUTES :{COMMA}{NBSP}minute{P "" s} diff --git a/src/order_base.h b/src/order_base.h index d39f572c05..f6bb3ece3f 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -223,6 +223,7 @@ public: void MakeWaiting(); void MakeLoadingAdvance(StationID destination); void MakeReleaseSlot(); + void MakeTryAcquireSlot(); void MakeChangeCounter(); void MakeLabel(OrderLabelSubType subtype); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 1f9f31f44e..b8a9583f7d 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -247,6 +247,13 @@ void Order::MakeReleaseSlot() this->flags = OSST_RELEASE; } +void Order::MakeTryAcquireSlot() +{ + this->type = OT_SLOT; + this->dest = INVALID_TRACE_RESTRICT_SLOT_ID; + this->flags = OSST_TRY_ACQUIRE; +} + void Order::MakeChangeCounter() { this->type = OT_COUNTER; @@ -1277,6 +1284,7 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s } switch (new_order.GetSlotSubType()) { case OSST_RELEASE: + case OSST_TRY_ACQUIRE: break; default: @@ -3070,6 +3078,31 @@ static std::vector _pco_deferred_slot_releases; static btree::btree_map _pco_deferred_counter_values; static btree::btree_map _pco_deferred_original_percent_cond; +static bool ExecuteVehicleInSlotOrderCondition(VehicleID vehicle, TraceRestrictSlot *slot, ProcessConditionalOrderMode mode, bool acquire) +{ + bool occupant = slot->IsOccupant(vehicle); + if (mode == PCO_DEFERRED) { + if (occupant && find_index(_pco_deferred_slot_releases, slot->index) >= 0) { + occupant = false; + } else if (!occupant && find_index(_pco_deferred_slot_acquires, slot->index) >= 0) { + occupant = true; + } + } + if (acquire) { + if (!occupant && mode == PCO_EXEC) { + occupant = slot->Occupy(vehicle); + } + if (!occupant && mode == PCO_DEFERRED) { + occupant = slot->OccupyDryRun(vehicle); + if (occupant) { + include(_pco_deferred_slot_acquires, slot->index); + container_unordered_remove(_pco_deferred_slot_releases, slot->index); + } + } + } + return occupant; +} + /** * Process a conditional order and determine the next order. * @param order the order the vehicle currently has @@ -3140,30 +3173,14 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro break; } case OCV_VEH_IN_SLOT: { - TraceRestrictSlotID slot_id = order->GetXData(); - TraceRestrictSlot* slot = TraceRestrictSlot::GetIfValid(slot_id); + TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(order->GetXData()); if (slot != nullptr) { - bool occupant = slot->IsOccupant(v->index); - if (mode == PCO_DEFERRED) { - if (occupant && find_index(_pco_deferred_slot_releases, slot_id) >= 0) { - occupant = false; - } else if (!occupant && find_index(_pco_deferred_slot_acquires, slot_id) >= 0) { - occupant = true; - } - } + bool acquire = false; if (occ == OCC_EQUALS || occ == OCC_NOT_EQUALS) { - if (!occupant && mode == PCO_EXEC) { - occupant = slot->Occupy(v->index); - } - if (!occupant && mode == PCO_DEFERRED) { - occupant = slot->OccupyDryRun(v->index); - if (occupant) { - include(_pco_deferred_slot_acquires, slot_id); - container_unordered_remove(_pco_deferred_slot_releases, slot_id); - } - } + acquire = true; occ = (occ == OCC_EQUALS) ? OCC_IS_TRUE : OCC_IS_FALSE; } + bool occupant = ExecuteVehicleInSlotOrderCondition(v->index, slot, mode, acquire); skip_order = OrderConditionCompare(occ, occupant, value); } break; @@ -3254,6 +3271,9 @@ VehicleOrderID AdvanceOrderIndexDeferred(const Vehicle *v, VehicleOrderID index) include(_pco_deferred_slot_releases, order->GetDestination()); container_unordered_remove(_pco_deferred_slot_acquires, order->GetDestination()); break; + case OSST_TRY_ACQUIRE: + ExecuteVehicleInSlotOrderCondition(v->index, TraceRestrictSlot::Get(order->GetDestination()), PCO_DEFERRED, true); + break; } } break; @@ -3435,6 +3455,9 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool case OSST_RELEASE: slot->Vacate(v->index); break; + case OSST_TRY_ACQUIRE: + slot->Occupy(v->index); + break; } } } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 589c0c476e..1a09837dc4 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -618,28 +618,16 @@ static const StringID _order_unload_drowdown[] = { INVALID_STRING_ID }; -static const StringID _order_goto_dropdown[] = { - STR_ORDER_GO_TO, - STR_ORDER_GO_TO_NEAREST_DEPOT, - STR_ORDER_CONDITIONAL, - STR_ORDER_SHARE, - STR_ORDER_RELEASE_SLOT_BUTTON, - STR_ORDER_CHANGE_COUNTER_BUTTON, - STR_ORDER_LABEL_TEXT_BUTTON, - STR_ORDER_LABEL_DEPARTURES_VIA_BUTTON, - INVALID_STRING_ID -}; - -static const StringID _order_goto_dropdown_aircraft[] = { - STR_ORDER_GO_TO, - STR_ORDER_GO_TO_NEAREST_HANGAR, - STR_ORDER_CONDITIONAL, - STR_ORDER_SHARE, - STR_ORDER_RELEASE_SLOT_BUTTON, - STR_ORDER_CHANGE_COUNTER_BUTTON, - STR_ORDER_LABEL_TEXT_BUTTON, - STR_ORDER_LABEL_DEPARTURES_VIA_BUTTON, - INVALID_STRING_ID +enum OrderDropDownID { + ODDI_GO_TO, + ODDI_GO_TO_NEAREST_DEPOT, + ODDI_CONDITIONAL, + ODDI_SHARE, + ODDI_TRY_ACQUIRE_SLOT, + ODDI_RELEASE_SLOT, + ODDI_CHANGE_COUNTER, + ODDI_LABEL_TEXT, + ODDI_LABEL_DEPARTURES_VIA, }; static const StringID _order_manage_list_dropdown[] = { @@ -1175,6 +1163,10 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(0, STR_ORDER_RELEASE_SLOT); break; + case OSST_TRY_ACQUIRE: + SetDParam(0, STR_ORDER_TRY_ACQUIRE_SLOT); + break; + default: NOT_REACHED(); break; @@ -1664,6 +1656,19 @@ private: this->InsertNewOrder(order.Pack()); } + /** + * Handle the click on the try acquire slot button. + */ + void OrderClick_TryAcquireSlot() + { + Order order; + order.next = nullptr; + order.index = 0; + order.MakeTryAcquireSlot(); + + this->InsertNewOrder(order.Pack()); + } + /** * Handle the click on the release slot button. */ @@ -2313,7 +2318,9 @@ public: TraceRestrictSlotID slot_id = (order != nullptr && TraceRestrictSlot::IsValidID(order->GetDestination()) ? order->GetDestination() : INVALID_TRACE_RESTRICT_SLOT_ID); - this->GetWidget(WID_O_RELEASE_SLOT)->widget_data = (slot_id != INVALID_TRACE_RESTRICT_SLOT_ID) ? STR_TRACE_RESTRICT_SLOT_NAME : STR_TRACE_RESTRICT_VARIABLE_UNDEFINED; + NWidgetCore *slot_widget = this->GetWidget(WID_O_SLOT); + slot_widget->widget_data = (slot_id != INVALID_TRACE_RESTRICT_SLOT_ID) ? STR_TRACE_RESTRICT_SLOT_NAME : STR_TRACE_RESTRICT_VARIABLE_UNDEFINED; + slot_widget->SetToolTip((order != nullptr && order->GetSlotSubType() == OSST_RELEASE) ? STR_ORDER_RELEASE_SLOT_TOOLTIP : STR_ORDER_TRY_ACQUIRE_SLOT_TOOLTIP); break; } @@ -2616,7 +2623,7 @@ public: } break; - case WID_O_RELEASE_SLOT: { + case WID_O_SLOT: { VehicleOrderID sel = this->OrderGetSel(); const Order *order = this->vehicle->GetOrder(sel); @@ -2859,32 +2866,37 @@ public: if (this->goto_type == OPOS_COND_VIA || this->goto_type == OPOS_COND_STATION) ResetObjectToPlace(); int sel; switch (this->goto_type) { - case OPOS_NONE: sel = -1; break; - case OPOS_GOTO: sel = 0; break; - case OPOS_CONDITIONAL: sel = 2; break; - case OPOS_SHARE: sel = 3; break; + case OPOS_NONE: sel = -1; break; + case OPOS_GOTO: sel = ODDI_GO_TO; break; + case OPOS_CONDITIONAL: sel = ODDI_CONDITIONAL; break; + case OPOS_SHARE: sel = ODDI_SHARE; break; case OPOS_CONDITIONAL_RETARGET: sel = -1; break; - case OPOS_DEPARTURE_VIA: sel = 7; break; + case OPOS_DEPARTURE_VIA: sel = ODDI_LABEL_DEPARTURES_VIA; break; default: NOT_REACHED(); } - uint32_t hidden_mask = 0; + bool show_counters = false; if (_settings_client.gui.show_adv_tracerestrict_features) { - bool have_counters = false; for (const TraceRestrictCounter *ctr : TraceRestrictCounter::Iterate()) { if (ctr->owner == this->vehicle->owner) { - have_counters = true; + show_counters = true; break; } } - if (!have_counters) { - // Owner has no counters, don't both showing the menu item - hidden_mask |= 0x20; - } - } else { - hidden_mask |= 0x30; } - ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, sel, WID_O_GOTO, - 0, hidden_mask, 0, DDSF_LOST_FOCUS); + DropDownList list; + list.push_back(std::make_unique(STR_ORDER_GO_TO, ODDI_GO_TO, false)); + list.push_back(std::make_unique((this->vehicle->type == VEH_AIRCRAFT) ? STR_ORDER_GO_TO_NEAREST_HANGAR : STR_ORDER_GO_TO_NEAREST_DEPOT, ODDI_GO_TO_NEAREST_DEPOT, false)); + list.push_back(std::make_unique(STR_ORDER_CONDITIONAL, ODDI_CONDITIONAL, false)); + list.push_back(std::make_unique(STR_ORDER_SHARE, ODDI_SHARE, false)); + list.push_back(std::make_unique(STR_ORDER_TRY_ACQUIRE_SLOT_BUTTON, ODDI_TRY_ACQUIRE_SLOT, false)); + list.push_back(std::make_unique(STR_ORDER_RELEASE_SLOT_BUTTON, ODDI_RELEASE_SLOT, false)); + if (show_counters) { + list.push_back(std::make_unique(STR_ORDER_CHANGE_COUNTER_BUTTON, ODDI_CHANGE_COUNTER, false)); + } + list.push_back(std::make_unique(STR_ORDER_LABEL_TEXT_BUTTON, ODDI_LABEL_TEXT, false)); + list.push_back(std::make_unique(STR_ORDER_LABEL_DEPARTURES_VIA_BUTTON, ODDI_LABEL_DEPARTURES_VIA, false)); + + ShowDropDownList(this, std::move(list), sel, WID_O_GOTO, 0, false, DDSF_LOST_FOCUS); } break; @@ -3134,11 +3146,11 @@ public: this->ReInit(); break; - case WID_O_RELEASE_SLOT: { + case WID_O_SLOT: { int selected; TraceRestrictSlotID value = this->vehicle->GetOrder(this->OrderGetSel())->GetDestination(); DropDownList list = GetSlotDropDownList(this->vehicle->owner, value, selected, this->vehicle->type, false); - if (!list.empty()) ShowDropDownList(this, std::move(list), selected, WID_O_RELEASE_SLOT, 0); + if (!list.empty()) ShowDropDownList(this, std::move(list), selected, WID_O_SLOT, 0); break; } @@ -3258,14 +3270,15 @@ public: case WID_O_GOTO: switch (index) { - case 0: this->OrderClick_Goto(OPOS_GOTO); break; - case 1: this->OrderClick_NearestDepot(); break; - case 2: this->OrderClick_Goto(OPOS_CONDITIONAL); break; - case 3: this->OrderClick_Goto(OPOS_SHARE); break; - case 4: this->OrderClick_ReleaseSlot(); break; - case 5: this->OrderClick_ChangeCounter(); break; - case 6: this->OrderClick_TextLabel(); break; - case 7: this->OrderClick_Goto(OPOS_DEPARTURE_VIA); break; + case ODDI_GO_TO: this->OrderClick_Goto(OPOS_GOTO); break; + case ODDI_GO_TO_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break; + case ODDI_CONDITIONAL: this->OrderClick_Goto(OPOS_CONDITIONAL); break; + case ODDI_SHARE: this->OrderClick_Goto(OPOS_SHARE); break; + case ODDI_TRY_ACQUIRE_SLOT: this->OrderClick_TryAcquireSlot(); break; + case ODDI_RELEASE_SLOT: this->OrderClick_ReleaseSlot(); break; + case ODDI_CHANGE_COUNTER: this->OrderClick_ChangeCounter(); break; + case ODDI_LABEL_TEXT: this->OrderClick_TextLabel(); break; + case ODDI_LABEL_DEPARTURES_VIA: this->OrderClick_Goto(OPOS_DEPARTURE_VIA); break; default: NOT_REACHED(); } break; @@ -3329,7 +3342,7 @@ public: break; } - case WID_O_RELEASE_SLOT: + case WID_O_SLOT: this->ModifyOrder(this->OrderGetSel(), MOF_SLOT | index << 8); break; @@ -3723,8 +3736,8 @@ static const NWidgetPart _nested_orders_train_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_RELEASE_SLOT), SetMinimalSize(124, 12), SetFill(1, 0), - SetDataTip(STR_NULL, STR_ORDER_RELEASE_SLOT_TOOLTIP), SetResize(1, 0), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_SLOT), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_NULL, STR_NULL), SetResize(1, 0), EndContainer(), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COUNTER_OP), SetMinimalSize(124, 12), SetFill(1, 0), @@ -3868,8 +3881,8 @@ static const NWidgetPart _nested_orders_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_RELEASE_SLOT), SetMinimalSize(124, 12), SetFill(1, 0), - SetDataTip(STR_NULL, STR_ORDER_RELEASE_SLOT_TOOLTIP), SetResize(1, 0), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_SLOT), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_NULL, STR_NULL), SetResize(1, 0), EndContainer(), /* Buttons for changing a counter. */ diff --git a/src/order_type.h b/src/order_type.h index 1f5967f2e9..37e2003e98 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -54,6 +54,7 @@ enum OrderType : byte { enum OrderSlotSubType : byte { OSST_RELEASE = 0, + OSST_TRY_ACQUIRE = 1, }; enum OrderLabelSubType : byte { diff --git a/src/sl/extended_ver_sl.cpp b/src/sl/extended_ver_sl.cpp index c608dec652..04d01a1f8b 100644 --- a/src/sl/extended_ver_sl.cpp +++ b/src/sl/extended_ver_sl.cpp @@ -105,7 +105,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_INFRA_SHARING, XSCF_NULL, 2, 2, "infra_sharing", nullptr, nullptr, "CPDP" }, { XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 3, 3, "variable_day_length", nullptr, nullptr, nullptr }, { XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr }, - { XSLFI_MORE_COND_ORDERS, XSCF_NULL, 15, 15, "more_cond_orders", nullptr, nullptr, nullptr }, + { XSLFI_MORE_COND_ORDERS, XSCF_NULL, 16, 16, "more_cond_orders", nullptr, nullptr, nullptr }, { XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr }, { XSLFI_REVERSE_AT_WAYPOINT, XSCF_NULL, 1, 1, "reverse_at_waypoint", nullptr, nullptr, nullptr }, { XSLFI_VEH_LIFETIME_PROFIT, XSCF_NULL, 1, 1, "veh_lifetime_profit", nullptr, nullptr, nullptr }, diff --git a/src/widgets/order_widget.h b/src/widgets/order_widget.h index a0775c31c5..e522d4427e 100644 --- a/src/widgets/order_widget.h +++ b/src/widgets/order_widget.h @@ -45,7 +45,7 @@ enum OrderWidgets : WidgetID { WID_O_COND_AUX_VIA, ///< Condition via button. WID_O_COND_SCHED_TEST, ///< Choose scheduled dispatch test. WID_O_COND_AUX_STATION, ///< Condition station button. - WID_O_RELEASE_SLOT, ///< Choose slot to release. + WID_O_SLOT, ///< Choose slot to try acquire/release. WID_O_COUNTER_OP, ///< Choose counter operation. WID_O_CHANGE_COUNTER, ///< Choose counter to change. WID_O_COUNTER_VALUE, ///< Choose counter value.