diff --git a/src/cargotype.h b/src/cargotype.h index 9645bf7c59..65208c9616 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -139,6 +139,9 @@ void InitializeSortedCargoSpecs(); extern std::vector _sorted_cargo_specs; extern uint8 _sorted_standard_cargo_specs_size; +uint ConvertCargoQuantityToDisplayQuantity(CargoID cargo, uint quantity); +uint ConvertDisplayQuantityToCargoQuantity(CargoID cargo, uint quantity); + /** * Does cargo \a c have cargo class \a cc? * @param c Cargo type. diff --git a/src/lang/english.txt b/src/lang/english.txt index fb2e703822..04b2d9ad3e 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4648,7 +4648,7 @@ STR_ORDERS_TIMETABLE_VIEW_TOOLTIP :{BLACK}Switch t STR_ORDERS_LIST_TOOLTIP :{BLACK}Order list - click on an order to highlight it. Ctrl+Click scrolls to the order's destination STR_ORDER_INDEX :{COMMA}:{NBSP} -STR_ORDER_TEXT :{STRING4} {STRING4} {STRING} +STR_ORDER_TEXT :{STRING5} {STRING4} {STRING} STR_ORDERS_END_OF_ORDERS :- - End of Orders - - STR_ORDERS_END_OF_SHARED_ORDERS :- - End of Shared Orders - - @@ -4711,6 +4711,8 @@ STR_ORDER_CONDITIONAL_FREE_PLATFORMS :Free platforms STR_ORDER_CONDITIONAL_PERCENT :Percent of times STR_ORDER_CONDITIONAL_SLOT_OCCUPANCY :Slot occupancy STR_ORDER_CONDITIONAL_TRAIN_IN_SLOT :Train in slot +STR_ORDER_CONDITIONAL_CARGO_LOAD_PERCENTAGE :Cargo load percentage +STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT :Waiting cargo amount STR_ORDER_CONDITIONAL_REQUIRES_SERVICE_ORDER :Requires service {STRING} STR_ORDER_CONDITIONAL_CARGO_WAITING_ORDER :Next station {STRING} {STRING} waiting @@ -4862,6 +4864,8 @@ STR_ORDER_CONDITIONAL_INVALID_SLOT :Jump to order { STR_ORDER_CONDITIONAL_IN_SLOT :Jump to order {COMMA} when {STRING} slot: {TRSLOT} STR_ORDER_CONDITIONAL_IN_INVALID_SLOT :Jump to order {COMMA} when {STRING} {PUSH_COLOUR}{RED}{STRING} {POP_COLOUR} STR_ORDER_CONDITIONAL_TRUE_FALSE :Jump to order {COMMA} when {STRING} {STRING} +STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE_DISPLAY :Jump to order {COMMA} when Load percentage of {STRING} {STRING} {COMMA} +STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_DISPLAY :Jump to order {COMMA} when {STRING} at next station {STRING} {CARGO_SHORT} STR_INVALID_ORDER :{RED} (Invalid Order) diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 4b1a65d9b6..2233d794e2 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1114,6 +1114,17 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s break; } + case OCV_CARGO_LOAD_PERCENTAGE: + if (!CargoSpec::Get(new_order.GetConditionValue())->IsValid()) return CMD_ERROR; + if (new_order.GetXData() > 100) return CMD_ERROR; + if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR; + break; + + case OCV_CARGO_WAITING_AMOUNT: + if (!CargoSpec::Get(new_order.GetConditionValue())->IsValid()) return CMD_ERROR; + if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR; + break; + case OCV_CARGO_WAITING: case OCV_CARGO_ACCEPTANCE: if (!CargoSpec::Get(new_order.GetConditionValue())->IsValid()) return CMD_ERROR; @@ -1598,7 +1609,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 break; case OT_CONDITIONAL: - if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_DESTINATION) return CMD_ERROR; + if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_VALUE_2 && mof != MOF_COND_DESTINATION) return CMD_ERROR; break; default: @@ -1685,6 +1696,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 case OCV_LOAD_PERCENTAGE: case OCV_RELIABILITY: case OCV_PERCENT: + case OCV_CARGO_LOAD_PERCENTAGE: if (data > 100) return CMD_ERROR; break; @@ -1698,12 +1710,27 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (!(data < NUM_CARGO && CargoSpec::Get(data)->IsValid())) return CMD_ERROR; break; + case OCV_CARGO_WAITING_AMOUNT: + break; + default: if (data > 2047) return CMD_ERROR; break; } break; + case MOF_COND_VALUE_2: + switch (order->GetConditionVariable()) { + case OCV_CARGO_LOAD_PERCENTAGE: + case OCV_CARGO_WAITING_AMOUNT: + if (!(data < NUM_CARGO && CargoSpec::Get(data)->IsValid())) return CMD_ERROR; + break; + + default: + return CMD_ERROR; + } + break; + case MOF_COND_DESTINATION: if (data >= v->GetNumOrders()) return CMD_ERROR; break; @@ -1779,7 +1806,8 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 case MOF_COND_VARIABLE: { /* Check whether old conditional variable had a cargo as value */ - bool old_var_was_cargo = (order->GetConditionVariable() == OCV_CARGO_ACCEPTANCE || order->GetConditionVariable() == OCV_CARGO_WAITING); + bool old_var_was_cargo = (order->GetConditionVariable() == OCV_CARGO_ACCEPTANCE || order->GetConditionVariable() == OCV_CARGO_WAITING + || order->GetConditionVariable() == OCV_CARGO_LOAD_PERCENTAGE || order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT); bool old_var_was_slot = (order->GetConditionVariable() == OCV_SLOT_OCCUPANCY || order->GetConditionVariable() == OCV_TRAIN_IN_SLOT); order->SetConditionVariable((OrderConditionVariable)data); @@ -1801,6 +1829,11 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (!old_var_was_cargo) order->SetConditionValue((uint16) GetFirstValidCargo()); if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE); break; + case OCV_CARGO_LOAD_PERCENTAGE: + case OCV_CARGO_WAITING_AMOUNT: + if (!old_var_was_cargo) order->SetConditionValue((uint16) GetFirstValidCargo()); + order->GetXDataRef() = 0; + break; case OCV_REQUIRES_SERVICE: if (old_var_was_cargo || old_var_was_slot) order->SetConditionValue(0); if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE); @@ -1831,6 +1864,8 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 switch (order->GetConditionVariable()) { case OCV_SLOT_OCCUPANCY: case OCV_TRAIN_IN_SLOT: + case OCV_CARGO_LOAD_PERCENTAGE: + case OCV_CARGO_WAITING_AMOUNT: order->GetXDataRef() = data; break; @@ -1840,6 +1875,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 } break; + case MOF_COND_VALUE_2: + order->SetConditionValue(data); + break; + case MOF_COND_DESTINATION: order->SetConditionSkipToOrder(data); break; @@ -2537,6 +2576,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v) // OrderConditionCompare ignores the last parameter for occ == OCC_IS_TRUE or occ == OCC_IS_FALSE. switch (order->GetConditionVariable()) { case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, nullptr), value); break; + case OCV_CARGO_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilledOfCargo(v, (CargoType) value), order->GetXData()); break; case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break; case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break; case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break; @@ -2546,7 +2586,12 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v) case OCV_CARGO_WAITING: { StationID next_station = GetNextRealStation(v, order); if (Station::IsValidID(next_station)) skip_order = OrderConditionCompare(occ, (Station::Get(next_station)->goods[value].cargo.AvailableCount() > 0), value); - break; + break; + } + case OCV_CARGO_WAITING_AMOUNT: { + StationID next_station = GetNextRealStation(v, order); + if (Station::IsValidID(next_station)) skip_order = OrderConditionCompare(occ, Station::Get(next_station)->goods[value].cargo.AvailableCount(), order->GetXData()); + break; } case OCV_CARGO_ACCEPTANCE: { StationID next_station = GetNextRealStation(v, order); diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 594ca2636a..b47696ef1d 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -31,6 +31,7 @@ #include "engine_func.h" #include "vehiclelist.h" #include "tracerestrict.h" +#include "scope.h" #include "widgets/order_widget.h" @@ -596,6 +597,7 @@ static const StringID _order_goto_dropdown_aircraft[] = { /** Variables for conditional orders; this defines the order of appearance in the dropdown box */ static const OrderConditionVariable _order_conditional_variable[] = { OCV_LOAD_PERCENTAGE, + OCV_CARGO_LOAD_PERCENTAGE, OCV_RELIABILITY, OCV_MAX_RELIABILITY, OCV_MAX_SPEED, @@ -603,6 +605,7 @@ static const OrderConditionVariable _order_conditional_variable[] = { OCV_REMAINING_LIFETIME, OCV_REQUIRES_SERVICE, OCV_CARGO_WAITING, + OCV_CARGO_WAITING_AMOUNT, OCV_CARGO_ACCEPTANCE, OCV_FREE_PLATFORMS, OCV_SLOT_OCCUPANCY, @@ -736,13 +739,13 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(0, order_index + 1); DrawString(left, rtl ? right - 2 * sprite_size.width - 3 : middle, y, STR_ORDER_INDEX, colour, SA_RIGHT | SA_FORCE); - SetDParam(5, STR_EMPTY); - SetDParam(10, STR_EMPTY); + SetDParam(6, STR_EMPTY); + SetDParam(11, STR_EMPTY); /* Check range for aircraft. */ if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->GetRange() > 0 && order->IsGotoOrder()) { const Order *next = order->next != nullptr ? order->next : v->GetFirstOrder(); - if (GetOrderDistance(order, next, v) > Aircraft::From(v)->acache.cached_max_range_sqr) SetDParam(10, STR_ORDER_OUT_OF_RANGE); + if (GetOrderDistance(order, next, v) > Aircraft::From(v)->acache.cached_max_range_sqr) SetDParam(11, STR_ORDER_OUT_OF_RANGE); } bool timetable_wait_time_valid = false; @@ -772,8 +775,8 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(3, STR_EMPTY); if (order->GetWaitTime() > 0) { - SetDParam(5, order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED); - SetTimetableParams(6, order->GetWaitTime()); + SetDParam(6, order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED); + SetTimetableParams(7, order->GetWaitTime()); } timetable_wait_time_valid = true; } else { @@ -782,7 +785,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(4, order->IsAutoRefit() ? STR_ORDER_AUTO_REFIT_ANY : CargoSpec::Get(order->GetRefitCargo())->name); } if (v->type == VEH_TRAIN && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) { - SetDParam(5, order->GetStopLocation() + STR_ORDER_STOP_LOCATION_NEAR_END); + SetDParam(6, order->GetStopLocation() + STR_ORDER_STOP_LOCATION_NEAR_END); } } break; @@ -811,22 +814,22 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int } if (!timetable && (order->GetDepotActionType() & ODATFB_SELL)) { - SetDParam(5, STR_ORDER_SELL_ORDER); + SetDParam(6, STR_ORDER_SELL_ORDER); } else { if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) { - SetDParam(5, STR_ORDER_STOP_ORDER); + SetDParam(6, STR_ORDER_STOP_ORDER); } if (!timetable && order->IsRefit()) { - SetDParam(5, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER); - SetDParam(6, CargoSpec::Get(order->GetRefitCargo())->name); + SetDParam(6, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER); + SetDParam(7, CargoSpec::Get(order->GetRefitCargo())->name); } } if (timetable) { if (order->GetWaitTime() > 0) { - SetDParam(5, order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED); - SetTimetableParams(6, order->GetWaitTime()); + SetDParam(6, order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED); + SetTimetableParams(7, order->GetWaitTime()); } timetable_wait_time_valid = !(order->GetDepotActionType() & ODATFB_HALT); } @@ -838,8 +841,8 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(0, str); SetDParam(1, order->GetDestination()); if (timetable && order->IsWaitTimetabled()) { - SetDParam(5, STR_TIMETABLE_STAY_FOR); - SetTimetableParams(6, order->GetWaitTime()); + SetDParam(6, STR_TIMETABLE_STAY_FOR); + SetTimetableParams(7, order->GetWaitTime()); timetable_wait_time_valid = true; } break; @@ -876,6 +879,17 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetDParam(3, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED); } SetDParam(2, order->GetConditionComparator() == OCC_IS_TRUE ? STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_IN_SLOT : STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_NOT_IN_SLOT); + } else if (ocv == OCV_CARGO_LOAD_PERCENTAGE) { + SetDParam(0, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE_DISPLAY); + SetDParam(2, CargoSpec::Get(order->GetConditionValue())->name); + SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + order->GetConditionComparator()); + SetDParam(4, order->GetXData()); + } else if (ocv == OCV_CARGO_WAITING_AMOUNT) { + SetDParam(0, STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_DISPLAY); + SetDParam(2, CargoSpec::Get(order->GetConditionValue())->name); + SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + order->GetConditionComparator()); + SetDParam(4, order->GetConditionValue()); + SetDParam(5, order->GetXData()); } else { OrderConditionComparator occ = order->GetConditionComparator(); bool is_cargo = ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_CARGO_WAITING; @@ -901,15 +915,15 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int /* FALL THROUGH */ default: SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ); - SetDParam(4, value); + SetDParam(4, value); } } if (timetable && order->GetWaitTime() > 0) { - SetDParam(5, order->IsWaitTimetabled() ? STR_TIMETABLE_AND_TRAVEL_FOR : STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED); - SetTimetableParams(6, order->GetWaitTime()); + SetDParam(6, order->IsWaitTimetabled() ? STR_TIMETABLE_AND_TRAVEL_FOR : STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED); + SetTimetableParams(7, order->GetWaitTime()); } else { - SetDParam(5, STR_EMPTY); + SetDParam(6, STR_EMPTY); } break; @@ -1110,6 +1124,9 @@ private: DP_COND_VALUE_CARGO = 1, ///< Display dropdown widget cargo types DP_COND_VALUE_SLOT = 2, ///< Display dropdown widget tracerestrict slots + /* WID_O_SEL_COND_AUX */ + DP_COND_AUX_CARGO = 0, ///< Display dropdown widget cargo types + DP_ROW_CONDITIONAL = 2, ///< Display the conditional order buttons in the top row of the ship/airplane order window. /* WID_O_SEL_BOTTOM_MIDDLE */ @@ -1129,6 +1146,7 @@ private: bool can_do_refit; ///< Vehicle chain can be refitted in depot. bool can_do_autorefit; ///< Vehicle chain can be auto-refitted. int query_text_widget; ///< widget which most recently called ShowQueryString + int current_aux_plane; /** * Return the memorised selected order. @@ -1423,6 +1441,8 @@ public: if (v->owner == _local_company) { this->GetWidget(WID_O_SEL_OCCUPANCY)->SetDisplayedPlane(SZSP_NONE); } + this->GetWidget(WID_O_SEL_COND_AUX)->SetDisplayedPlane(SZSP_NONE); + this->current_aux_plane = SZSP_NONE; this->FinishInitNested(v->index); if (v->owner == _local_company) { this->DisableWidget(WID_O_EMPTY); @@ -1635,6 +1655,14 @@ public: NWidgetStacked *row_sel = this->GetWidget(WID_O_SEL_TOP_ROW); assert(row_sel != nullptr || (train_row_sel != nullptr && left_sel != nullptr && middle_sel != nullptr && right_sel != nullptr)); + NWidgetStacked *aux_sel = this->GetWidget(WID_O_SEL_COND_AUX); + + auto aux_plane_guard = scope_guard([&]() { + if (this->current_aux_plane != aux_sel->shown_plane) { + this->current_aux_plane = aux_sel->shown_plane; + this->ReInit(); + } + }); if (order == nullptr) { if (row_sel != nullptr) { @@ -1723,6 +1751,7 @@ public: OrderConditionVariable ocv = (order == nullptr) ? OCV_LOAD_PERCENTAGE : order->GetConditionVariable(); bool is_cargo = (ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_CARGO_WAITING); bool is_slot_occupancy = (ocv == OCV_SLOT_OCCUPANCY || ocv == OCV_TRAIN_IN_SLOT); + bool is_auxiliary_cargo = (ocv == OCV_CARGO_LOAD_PERCENTAGE || ocv == OCV_CARGO_WAITING_AMOUNT); if (is_cargo) { if (order == nullptr || !CargoSpec::Get(order->GetConditionValue())->IsValid()) { @@ -1740,6 +1769,17 @@ public: this->GetWidget(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(DP_COND_VALUE_NUMBER); } + if (is_auxiliary_cargo) { + if (order == nullptr || !CargoSpec::Get(order->GetConditionValue())->IsValid()) { + this->GetWidget(WID_O_COND_AUX_CARGO)->widget_data = STR_NEWGRF_INVALID_CARGO; + } else { + this->GetWidget(WID_O_COND_AUX_CARGO)->widget_data = CargoSpec::Get(order->GetConditionValue())->name; + } + aux_sel->SetDisplayedPlane(DP_COND_AUX_CARGO); + } else { + aux_sel->SetDisplayedPlane(SZSP_NONE); + } + /* Set the strings for the dropdown boxes. */ this->GetWidget(WID_O_COND_VARIABLE)->widget_data = STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv; this->GetWidget(WID_O_COND_COMPARATOR)->widget_data = GetComparatorStrings(order)[order->GetConditionComparator()]; @@ -1886,8 +1926,10 @@ public: const Order *order = this->vehicle->GetOrder(sel); if (order != nullptr && order->IsType(OT_CONDITIONAL)) { - uint value = order->GetConditionValue(); + OrderConditionVariable ocv = order->GetConditionVariable(); + uint value = (ocv == OCV_CARGO_LOAD_PERCENTAGE || ocv == OCV_CARGO_WAITING_AMOUNT) ? order->GetXData() : order->GetConditionValue(); if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value); + if (order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT) value = ConvertCargoQuantityToDisplayQuantity(order->GetConditionValue(), value); SetDParam(0, value); } break; @@ -2085,14 +2127,15 @@ public: break; } - case WID_O_COND_CARGO: { + case WID_O_COND_CARGO: + case WID_O_COND_AUX_CARGO: { uint value = this->vehicle->GetOrder(this->OrderGetSel())->GetConditionValue(); DropDownList list; for (size_t i = 0; i < _sorted_standard_cargo_specs_size; ++i) { const CargoSpec *cs = _sorted_cargo_specs[i]; list.emplace_back(new DropDownListStringItem(cs->name, cs->Index(), false)); } - if (!list.empty()) ShowDropDownList(this, std::move(list), value, WID_O_COND_CARGO, 0); + if (!list.empty()) ShowDropDownList(this, std::move(list), value, widget, 0); break; } @@ -2127,9 +2170,11 @@ public: case WID_O_COND_VALUE: { const Order *order = this->vehicle->GetOrder(this->OrderGetSel()); - uint value = order->GetConditionValue(); + OrderConditionVariable ocv = order->GetConditionVariable(); + uint value = (ocv == OCV_CARGO_LOAD_PERCENTAGE || ocv == OCV_CARGO_WAITING_AMOUNT) ? order->GetXData() : order->GetConditionValue(); if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value); - this->query_text_widget = WID_O_COND_VALUE; + if (order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT) value = ConvertCargoQuantityToDisplayQuantity(order->GetConditionValue(), value); + this->query_text_widget = widget; SetDParam(0, value); ShowQueryString(STR_JUST_INT, STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, this, CS_NUMERAL, QSF_NONE); break; @@ -2167,9 +2212,14 @@ public: case OCV_PERCENT: case OCV_RELIABILITY: case OCV_LOAD_PERCENTAGE: + case OCV_CARGO_LOAD_PERCENTAGE: value = Clamp(value, 0, 100); break; + case OCV_CARGO_WAITING_AMOUNT: + value = ConvertDisplayQuantityToCargoQuantity(this->vehicle->GetOrder(sel)->GetConditionValue(), value); + break; + default: break; } @@ -2226,6 +2276,10 @@ public: DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_VALUE | index << 4, CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); break; + case WID_O_COND_AUX_CARGO: + DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_VALUE_2 | index << 4, CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); + break; + case WID_O_COND_SLOT: DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_VALUE | index << 4, CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); break; @@ -2444,6 +2498,10 @@ static const NWidgetPart _nested_orders_train_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0), + NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_AUX), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_AUX_CARGO), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_CARGO_TOOLTIP), SetResize(1, 0), + EndContainer(), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_VALUE), @@ -2532,6 +2590,10 @@ static const NWidgetPart _nested_orders_widgets[] = { NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0), + NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_AUX), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_AUX_CARGO), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_CARGO_TOOLTIP), SetResize(1, 0), + EndContainer(), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_VALUE), diff --git a/src/order_type.h b/src/order_type.h index c90b7ec0eb..61ff8a8888 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -143,6 +143,8 @@ enum OrderConditionVariable { OCV_PERCENT, ///< Skip xx percent of times OCV_SLOT_OCCUPANCY, ///< Test if train slot is fully occupied OCV_TRAIN_IN_SLOT, ///< Test if train is in slot + OCV_CARGO_LOAD_PERCENTAGE, ///< Skip based on the amount of load of a specific cargo + OCV_CARGO_WAITING_AMOUNT, ///< Skip based on the amount of a specific cargo waiting at next station OCV_END }; @@ -174,6 +176,7 @@ enum ModifyOrderFlags { MOF_COND_VARIABLE, ///< A conditional variable changes. MOF_COND_COMPARATOR, ///< A comparator changes. MOF_COND_VALUE, ///< The value to set the condition to. + MOF_COND_VALUE_2, ///< The secondary value to set the condition to. MOF_COND_DESTINATION,///< Change the destination of a conditional order. MOF_WAYPOINT_FLAGS, ///< Change the waypoint flags MOF_CARGO_TYPE_UNLOAD, ///< Passes an OrderUnloadType and a CargoID. diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 478b01d523..4aa1e30fdb 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -77,7 +77,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, 2, 2, "variable_day_length", nullptr, nullptr, nullptr }, { XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr }, - { XSLFI_MORE_COND_ORDERS, XSCF_NULL, 2, 2, "more_cond_orders", nullptr, nullptr, nullptr }, + { XSLFI_MORE_COND_ORDERS, XSCF_NULL, 3, 3, "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/strings.cpp b/src/strings.cpp index b20870122b..1ff3edeb43 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -947,6 +947,36 @@ uint ConvertDisplayToForceWeightRatio(double in) return ConvertDisplayToWeightRatio(_units_force[_settings_game.locale.units_force], in); } +uint ConvertCargoQuantityToDisplayQuantity(CargoID cargo, uint quantity) +{ + switch (CargoSpec::Get(cargo)->units_volume) { + case STR_TONS: + return _units_weight[_settings_game.locale.units_weight].c.ToDisplay(quantity); + + case STR_LITERS: + return _units_volume[_settings_game.locale.units_volume].c.ToDisplay(quantity); + + default: + break; + } + return quantity; +} + +uint ConvertDisplayQuantityToCargoQuantity(CargoID cargo, uint quantity) +{ + switch (CargoSpec::Get(cargo)->units_volume) { + case STR_TONS: + return _units_weight[_settings_game.locale.units_weight].c.FromDisplay(quantity); + + case STR_LITERS: + return _units_volume[_settings_game.locale.units_volume].c.FromDisplay(quantity); + + default: + break; + } + return quantity; +} + /** * Parse most format codes within a string and write the result to a buffer. * @param buff The buffer to write the final string to. diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 2ba1ff9ab4..913d5ce574 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2158,6 +2158,31 @@ uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour) } } +uint8 CalcPercentVehicleFilledOfCargo(const Vehicle *front, CargoID cargo) +{ + int count = 0; + int max = 0; + + /* Count up max and used */ + for (const Vehicle *v = front; v != nullptr; v = v->Next()) { + if (v->cargo_type != cargo) continue; + count += v->cargo.StoredCount(); + max += v->cargo_cap; + } + + /* Train without capacity */ + if (max == 0) return 100; + + /* Return the percentage */ + if (count * 2 < max) { + /* Less than 50%; round up, so that 0% means really empty. */ + return CeilDiv(count * 100, max); + } else { + /* More than 50%; round down, so that 100% means really full. */ + return (count * 100) / max; + } +} + /** * Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it, etc. * @param v Vehicle that entered a depot. diff --git a/src/vehicle_func.h b/src/vehicle_func.h index ce3f32c2a3..2c889dde15 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -46,6 +46,7 @@ bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc); bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc); void CallVehicleTicks(); uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour); +uint8 CalcPercentVehicleFilledOfCargo(const Vehicle *v, CargoID cargo); void VehicleLengthChanged(const Vehicle *u); diff --git a/src/widgets/order_widget.h b/src/widgets/order_widget.h index f8b06f72ba..d5a6936fd6 100644 --- a/src/widgets/order_widget.h +++ b/src/widgets/order_widget.h @@ -34,8 +34,10 @@ enum OrderWidgets { WID_O_COND_COMPARATOR, ///< Choose condition type. WID_O_COND_VALUE, ///< Choose condition value. WID_O_COND_CARGO, ///< Choose condition cargo. + WID_O_COND_AUX_CARGO, ///< Choose condition cargo. WID_O_COND_SLOT, ///< Choose condition slot. 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_TOP_LEFT, ///< #NWID_SELECTION widget for left part of the top row of the 'your train' order window. WID_O_SEL_TOP_MIDDLE, ///< #NWID_SELECTION widget for middle part of the top row of the 'your train' order window. WID_O_SEL_TOP_RIGHT, ///< #NWID_SELECTION widget for right part of the top row of the 'your train' order window.