diff --git a/src/departures.cpp b/src/departures.cpp index b1c2f984a6..57d8563bbf 100644 --- a/src/departures.cpp +++ b/src/departures.cpp @@ -541,6 +541,10 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorGetType() == OT_LABEL && order->GetLabelSubType() == OLST_DEPARTURES_REMOVE_VIA && !d->calling_at.empty()) { + d->remove_vias.push_back({ (StationID)order->GetDestination(), (uint)(d->calling_at.size() - 1) }); + } + if (c.scheduled_date != 0 && (order->GetTravelTime() != 0 || order->IsTravelTimetabled())) { c.scheduled_date += order->GetTravelTime(); /* TODO smart terminal may not work correctly */ } else { @@ -624,10 +628,18 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorterminus >= c && d_first->calling_at.size() >= 2) { d_first->terminus = CallAt(d_first->calling_at[k]); - if (d_first->via2 == d_first->terminus.station) d_first->via2 = INVALID_STATION; - if (d_first->via == d_first->terminus.station) { - d_first->via = d_first->via2; - d_first->via2 = INVALID_STATION; + auto remove_via = [&](StationID st) { + if (d_first->via2 == st) d_first->via2 = INVALID_STATION; + if (d_first->via == st) { + d_first->via = d_first->via2; + d_first->via2 = INVALID_STATION; + } + }; + remove_via(d_first->terminus.station); + for (const RemoveVia &rv : d_first->remove_vias) { + if (rv.calling_at_offset == k) { + remove_via(rv.via); + } } if (k == 0) break; diff --git a/src/departures_type.h b/src/departures_type.h index af8e1cd5e1..91ccfadb66 100644 --- a/src/departures_type.h +++ b/src/departures_type.h @@ -63,6 +63,11 @@ struct CallAt { } }; +struct RemoveVia { + StationID via; + uint calling_at_offset; +}; + /** A scheduled departure. */ struct Departure { DateTicksScaled scheduled_date; ///< The date this departure is scheduled to finish on (i.e. when the vehicle leaves the station) @@ -71,6 +76,7 @@ struct Departure { StationID via; ///< The station the departure should list as going via StationID via2; ///< Secondary station the departure should list as going via std::vector calling_at; ///< The stations both called at and unloaded at by the vehicle after this departure before it terminates + std::vector remove_vias; ///< Vias to remove when using smart terminus. DepartureStatus status; ///< Whether the vehicle has arrived yet for this departure DepartureType type; ///< The type of the departure (departure or arrival) const Vehicle *vehicle; ///< The vehicle performing this departure diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 7c37edac1a..8d0a5aa4a3 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -1567,7 +1567,11 @@ STR_ORDER_LABEL_TEXT_CAPTION :{WHITE}Label STR_ORDER_LABEL_TEXT_BUTTON :Label STR_ORDER_LABEL_TEXT_BUTTON_TOOLTIP :{BLACK}Change label text STR_ORDER_LABEL_DEPARTURES_VIA_BUTTON :Departure board via -STR_ORDER_LABEL_DEPARTURES_VIA :Departure board: Show as via: {STRING1} +STR_ORDER_LABEL_DEPARTURES_VIA :Departure board: {STRING}: {STRING1} +STR_ORDER_LABEL_DEPARTURES_SHOW_AS_VIA :Show as via +STR_ORDER_LABEL_DEPARTURES_REMOVE_VIA :Remove via for prior terminus +STR_ORDER_LABEL_DEPARTURES_REMOVE_VIA_SHORT :Remove via +STR_ORDER_LABEL_DEPARTURES_VIA_TYPE_TOOLTIP :{BLACK}Show as via: Show this station/waypoint as the via station in the departure board for departures from stations before this order to terminuses after this order.{}Use two in a row for a double via.{}{}Remove via for prior terminus: Do not show this station as a via station, when showing a calling point before this order as the terminus. STR_ORDERS_OCCUPANCY_BUTTON :{BLACK}{STRING2}% STR_ORDERS_OCCUPANCY_BUTTON_TOOLTIP :{BLACK}Show occupancy running averages{}The percentage shown is the overall average of the order occupancies diff --git a/src/lang/extra/korean.txt b/src/lang/extra/korean.txt index dcd31d51d5..b7adca8f88 100644 --- a/src/lang/extra/korean.txt +++ b/src/lang/extra/korean.txt @@ -1524,7 +1524,8 @@ STR_ORDER_LABEL_TEXT_CAPTION :{WHITE}이름 STR_ORDER_LABEL_TEXT_BUTTON :이름표 STR_ORDER_LABEL_TEXT_BUTTON_TOOLTIP :{BLACK}이름표 내용 변경 STR_ORDER_LABEL_DEPARTURES_VIA_BUTTON :발착전광판 경유 -STR_ORDER_LABEL_DEPARTURES_VIA :발착전광판: 경유로 표시: {STRING} +STR_ORDER_LABEL_DEPARTURES_VIA :발착전광판: {STRING}: {STRING} +STR_ORDER_LABEL_DEPARTURES_SHOW_AS_VIA :경유로 표시 STR_ORDERS_OCCUPANCY_BUTTON :{BLACK}{STRING}% STR_ORDERS_OCCUPANCY_BUTTON_TOOLTIP :{BLACK}평균 경로 사용률입니다.{}경로 사용률의 전체 평균을 보여줍니다. diff --git a/src/order_base.h b/src/order_base.h index 1f675ada22..3fc1c005bd 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -621,6 +621,11 @@ public: return (OrderLabelSubType)GB(this->flags, 0, 8); } + inline void SetLabelSubType(OrderLabelSubType subtype) + { + SB(this->flags, 0, 8, subtype); + } + const char *GetLabelText() const; void SetLabelText(const char *text); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index a981ce6b5d..e797f15b06 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1314,7 +1314,8 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s case OLST_TEXT: break; - case OLST_DEPARTURES_VIA: { + case OLST_DEPARTURES_VIA: + case OLST_DEPARTURES_REMOVE_VIA: { const BaseStation *st = BaseStation::GetIfValid(new_order.GetDestination()); if (st == nullptr) return CMD_ERROR; @@ -1872,6 +1873,8 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 case OT_LABEL: if (order->GetLabelSubType() == OLST_TEXT) { if (mof != MOF_LABEL_TEXT) return CMD_ERROR; + } else if (IsDeparturesOrderLabelSubType(order->GetLabelSubType())) { + if (mof != MOF_DEPARTURES_SUBTYPE) return CMD_ERROR; } else { return CMD_ERROR; } @@ -2085,6 +2088,12 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 case MOF_LABEL_TEXT: break; + + case MOF_DEPARTURES_SUBTYPE: + if (!IsDeparturesOrderLabelSubType(static_cast(data))) { + return CMD_ERROR; + } + break; } if (flags & DC_EXEC) { @@ -2334,6 +2343,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 order->SetLabelText(text == nullptr ? "" : text); break; + case MOF_DEPARTURES_SUBTYPE: + order->SetLabelSubType(static_cast(data)); + break; + default: NOT_REACHED(); } @@ -2860,7 +2873,7 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool if (ot == OT_GOTO_DEPOT && (o->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return false; if (ot == OT_GOTO_DEPOT && hangar && v->type != VEH_AIRCRAFT) return false; // Not an aircraft? Can't have a hangar order. if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION; - if (ot == OT_LABEL && o->GetLabelSubType() == OLST_DEPARTURES_VIA && (type == OT_GOTO_STATION || type == OT_GOTO_WAYPOINT) && o->GetDestination() == destination) return true; + if (ot == OT_LABEL && IsDestinationOrderLabelSubType(o->GetLabelSubType()) && (type == OT_GOTO_STATION || type == OT_GOTO_WAYPOINT) && o->GetDestination() == destination) return true; return (ot == type && o->GetDestination() == destination); }); } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 101a2b85cc..d2f1471a74 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -1169,7 +1169,15 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(3, order->GetXData()); break; - case OT_LABEL: + case OT_LABEL: { + auto show_destination_subtype = [&](uint offset) { + if (Waypoint::IsValidID(order->GetDestination())) { + SetDParam(offset, STR_WAYPOINT_NAME); + } else { + SetDParam(offset, STR_STATION_NAME); + } + SetDParam(offset + 1, order->GetDestination()); + }; switch (order->GetLabelSubType()) { case OLST_TEXT: { SetDParam(0, STR_ORDER_LABEL_TEXT); @@ -1180,12 +1188,14 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int case OLST_DEPARTURES_VIA: SetDParam(0, STR_ORDER_LABEL_DEPARTURES_VIA); - if (Waypoint::IsValidID(order->GetDestination())) { - SetDParam(1, STR_WAYPOINT_NAME); - } else { - SetDParam(1, STR_STATION_NAME); - } - SetDParam(2, order->GetDestination()); + SetDParam(1, STR_ORDER_LABEL_DEPARTURES_SHOW_AS_VIA); + show_destination_subtype(2); + break; + + case OLST_DEPARTURES_REMOVE_VIA: + SetDParam(0, STR_ORDER_LABEL_DEPARTURES_VIA); + SetDParam(1, STR_ORDER_LABEL_DEPARTURES_REMOVE_VIA); + show_destination_subtype(2); break; default: @@ -1193,6 +1203,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int break; } break; + } default: NOT_REACHED(); } @@ -1391,7 +1402,8 @@ private: DP_GROUNDVEHICLE_ROW_SLOT = 2, ///< Display the row for release slot orders in the top row of the train/rv order window. DP_GROUNDVEHICLE_ROW_COUNTER = 3, ///< Display the row for change counter orders in the top row of the train/rv order window. DP_GROUNDVEHICLE_ROW_TEXT_LABEL = 4, ///< Display the row for text label orders in the top row of the train/rv order window. - DP_GROUNDVEHICLE_ROW_EMPTY = 5, ///< Display the row for no buttons in the top row of the train/rv order window. + DP_GROUNDVEHICLE_ROW_DEPARTURES = 5, ///< Display the row for departure via label orders in the top row of the train/rv order window. + DP_GROUNDVEHICLE_ROW_EMPTY = 6, ///< Display the row for no buttons in the top row of the train/rv order window. /* WID_O_SEL_TOP_LEFT */ DP_LEFT_LOAD = 0, ///< Display 'load' in the left button of the top row of the train/rv order window. @@ -1413,7 +1425,8 @@ private: DP_ROW_SLOT = 3, ///< Display the release slot buttons in the top row of the ship/airplane order window. DP_ROW_COUNTER = 4, ///< Display the change counter buttons in the top row of the ship/airplane order window. DP_ROW_TEXT_LABEL = 5, ///< Display the text label buttons in the top row of the ship/airplane order window. - DP_ROW_EMPTY = 6, ///< Display no buttons in the top row of the ship/airplane order window. + DP_ROW_DEPARTURES = 6, ///< Display the row for departure via label orders in the top row of the ship/airplane order window. + DP_ROW_EMPTY = 7, ///< Display no buttons in the top row of the ship/airplane order window. /* WID_O_SEL_COND_VALUE */ DP_COND_VALUE_NUMBER = 0, ///< Display number widget @@ -2255,10 +2268,16 @@ public: } case OT_LABEL: { + std::pair sections = { DP_ROW_EMPTY, DP_GROUNDVEHICLE_ROW_EMPTY }; + if (order->GetLabelSubType() == OLST_TEXT) { + sections = { DP_ROW_TEXT_LABEL, DP_GROUNDVEHICLE_ROW_TEXT_LABEL }; + } else if (IsDeparturesOrderLabelSubType(order->GetLabelSubType())) { + sections = { DP_ROW_DEPARTURES, DP_GROUNDVEHICLE_ROW_DEPARTURES }; + } if (row_sel != nullptr) { - row_sel->SetDisplayedPlane(order->GetLabelSubType() == OLST_TEXT ? DP_ROW_TEXT_LABEL : DP_ROW_EMPTY); + row_sel->SetDisplayedPlane(sections.first); } else { - train_row_sel->SetDisplayedPlane(order->GetLabelSubType() == OLST_TEXT ? DP_GROUNDVEHICLE_ROW_TEXT_LABEL : DP_GROUNDVEHICLE_ROW_EMPTY); + train_row_sel->SetDisplayedPlane(sections.second); } break; } @@ -2572,6 +2591,30 @@ public: } break; } + + case WID_O_DEPARTURE_VIA_TYPE: { + VehicleOrderID sel = this->OrderGetSel(); + const Order *order = this->vehicle->GetOrder(sel); + + if (order != nullptr && order->IsType(OT_LABEL) && IsDeparturesOrderLabelSubType(order->GetLabelSubType())) { + switch (order->GetLabelSubType()) { + case OLST_DEPARTURES_VIA: + SetDParam(0, STR_ORDER_LABEL_DEPARTURES_SHOW_AS_VIA); + break; + + case OLST_DEPARTURES_REMOVE_VIA: + SetDParam(0, STR_ORDER_LABEL_DEPARTURES_REMOVE_VIA_SHORT); + break; + + default: + SetDParam(0, STR_EMPTY); + break; + } + } else { + SetDParam(0, STR_EMPTY); + } + break; + } } } @@ -3033,6 +3076,15 @@ public: break; } + case WID_O_DEPARTURE_VIA_TYPE: { + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_ORDER_LABEL_DEPARTURES_SHOW_AS_VIA, OLST_DEPARTURES_VIA, false)); + list.emplace_back(new DropDownListStringItem(STR_ORDER_LABEL_DEPARTURES_REMOVE_VIA, OLST_DEPARTURES_REMOVE_VIA, false)); + int selected = this->vehicle->GetOrder(this->OrderGetSel())->GetLabelSubType(); + ShowDropDownList(this, std::move(list), selected, WID_O_DEPARTURE_VIA_TYPE, 0); + break; + } + case WID_O_TOGGLE_SIZE: { _settings_client.gui.show_order_management_button = !_settings_client.gui.show_order_management_button; InvalidateWindowClassesData(WC_VEHICLE_ORDERS); @@ -3195,6 +3247,10 @@ public: this->ModifyOrder(this->OrderGetSel(), MOF_COUNTER_ID | index << 8); break; + case WID_O_DEPARTURE_VIA_TYPE: + this->ModifyOrder(this->OrderGetSel(), MOF_DEPARTURES_SUBTYPE | index << 8); + break; + case WID_O_MANAGE_LIST: case WID_O_MGMT_LIST_BTN: switch (index) { @@ -3575,6 +3631,12 @@ static const NWidgetPart _nested_orders_train_widgets[] = { NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TEXT_LABEL), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_ORDER_LABEL_TEXT_BUTTON, STR_ORDER_LABEL_TEXT_BUTTON_TOOLTIP), SetResize(1, 0), EndContainer(), + 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_DEPARTURE_VIA_TYPE), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_BLACK_STRING, STR_ORDER_LABEL_DEPARTURES_VIA_TYPE_TOOLTIP), SetResize(1, 0), + EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 0), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_O_OCCUPANCY_TOGGLE), SetMinimalSize(36, 12), SetDataTip(STR_ORDERS_OCCUPANCY_BUTTON, STR_ORDERS_OCCUPANCY_BUTTON_TOOLTIP), @@ -3720,6 +3782,14 @@ static const NWidgetPart _nested_orders_widgets[] = { SetDataTip(STR_ORDER_LABEL_TEXT_BUTTON, STR_ORDER_LABEL_TEXT_BUTTON_TOOLTIP), SetResize(1, 0), EndContainer(), + /* Buttons for changing a departure board via order */ + 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_DEPARTURE_VIA_TYPE), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_BLACK_STRING, STR_ORDER_LABEL_DEPARTURES_VIA_TYPE_TOOLTIP), SetResize(1, 0), + EndContainer(), + /* No buttons */ NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 0), SetResize(1, 0), EndContainer(), EndContainer(), diff --git a/src/order_type.h b/src/order_type.h index 16f3d0e3c0..8e08d71e46 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -53,10 +53,21 @@ enum OrderType : byte { }; enum OrderLabelSubType : byte { - OLST_TEXT = 0, - OLST_DEPARTURES_VIA = 1, + OLST_TEXT = 0, + OLST_DEPARTURES_VIA = 1, + OLST_DEPARTURES_REMOVE_VIA = 2, }; +inline bool IsDestinationOrderLabelSubType(OrderLabelSubType subtype) +{ + return subtype == OLST_DEPARTURES_VIA || subtype == OLST_DEPARTURES_REMOVE_VIA; +} + +inline bool IsDeparturesOrderLabelSubType(OrderLabelSubType subtype) +{ + return subtype == OLST_DEPARTURES_VIA || subtype == OLST_DEPARTURES_REMOVE_VIA; +} + /** * Flags related to the unloading order. */ @@ -210,6 +221,7 @@ enum ModifyOrderFlags { MOF_COUNTER_VALUE, ///< Change the counter value MOF_COLOUR, ///< Change the colour value MOF_LABEL_TEXT, ///< Change the label text value + MOF_DEPARTURES_SUBTYPE, ///< Change the label departures subtype MOF_END }; template <> struct EnumPropsT : MakeEnumPropsT {}; diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index ed8ba01540..edb72755e8 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -187,7 +187,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_TNNC_CHUNK, XSCF_IGNORABLE_ALL, 0, 1, "tnnc_chunk", nullptr, nullptr, "TNNC" }, { XSLFI_MULTI_CARGO_SHIPS, XSCF_NULL, 1, 1, "multi_cargo_ships", nullptr, nullptr, nullptr }, { XSLFI_REMAIN_NEXT_ORDER_STATION, XSCF_IGNORABLE_UNKNOWN, 1, 1, "remain_next_order_station", nullptr, nullptr, nullptr }, - { XSLFI_LABEL_ORDERS, XSCF_NULL, 1, 1, "label_orders", nullptr, nullptr, nullptr }, + { XSLFI_LABEL_ORDERS, XSCF_NULL, 2, 2, "label_orders", nullptr, nullptr, nullptr }, { XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr }, { XSLFI_U64_TICK_COUNTER, XSCF_NULL, 1, 1, "u64_tick_counter", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_TRAVEL_TIME, XSCF_NULL, 1, 1, "linkgraph_travel_time", nullptr, nullptr, nullptr }, diff --git a/src/widgets/order_widget.h b/src/widgets/order_widget.h index 3af4551b2c..98f6e2397d 100644 --- a/src/widgets/order_widget.h +++ b/src/widgets/order_widget.h @@ -50,6 +50,7 @@ enum OrderWidgets { WID_O_CHANGE_COUNTER, ///< Choose counter to change. WID_O_COUNTER_VALUE, ///< Choose counter value. WID_O_TEXT_LABEL, ///< Choose text label. + WID_O_DEPARTURE_VIA_TYPE, ///< Choose departure board via subtype. WID_O_SEL_COND_VALUE, ///< Widget for conditional value or conditional cargo type. WID_O_SEL_COND_AUX, ///< Widget for auxiliary conditional cargo type. WID_O_SEL_COND_AUX2, ///< Widget for auxiliary conditional via button.