Add refit sub-mode to waiting cargo/capacity conditional order

See: #738
This commit is contained in:
Jonathan G Rennison 2024-09-03 19:47:17 +01:00
parent c463cc17b9
commit 33e53ec8e0
6 changed files with 89 additions and 7 deletions

View File

@ -1660,6 +1660,8 @@ STR_ORDER_CONDITIONAL_VIA :{BLACK}Via
STR_ORDER_CONDITIONAL_VIA_TOOLTIP :{BLACK}The via station to check the waiting cargo amount for
STR_ORDER_CONDITIONAL_STATION :{BLACK}Station
STR_ORDER_CONDITIONAL_STATION_TOOLTIP :{BLACK}The station to check
STR_ORDER_CONDITIONAL_REFIT_MODE :{BLACK}Refit
STR_ORDER_CONDITIONAL_REFIT_MODE_TOOLTIP :{BLACK}Whether to use the estimated cargo capacity after refitting
STR_ORDER_CONDITIONAL_COMPARATOR_ACCEPTS :accepts
STR_ORDER_CONDITIONAL_COMPARATOR_DOES_NOT_ACCEPT :does not accept
@ -1783,6 +1785,7 @@ STR_ORDER_CONDITIONAL_TIMETABLE :Jump to order {
STR_ORDER_CONDITIONAL_DISPATCH_SLOT_DISPLAY :Jump to order {COMMA} when {STRING} {STRING} {STRING}
STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY :{COMMA} percent of {STRING} capacity
STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY_REFIT :{COMMA} percent of refit to {STRING} capacity
STR_ORDER_TRY_ACQUIRE_SLOT :Try to acquire slot: {STRING1}
STR_ORDER_RELEASE_SLOT :Release slot: {STRING1}

View File

@ -78,7 +78,7 @@ void ClearOrderDestinationRefcountMap();
* OCV_CARGO_ACCEPTANCE: Bits 0-15: Station ID to test + 1
* OCV_FREE_PLATFORMS: Bits 0-15: Station ID to test + 1
* OCV_CARGO_WAITING_AMOUNT: Bits 0-15: Station ID to test + 1
* OCV_CARGO_WAITING_AMOUNT_PERCENTAGE: Bits 0-15: Station ID to test + 1
* OCV_CARGO_WAITING_AMOUNT_PERCENTAGE: Bits 0-15: Station ID to test + 1, Bit 16: Refit mode
*/
struct OrderExtraInfo {

View File

@ -1923,7 +1923,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
break;
case OT_CONDITIONAL:
if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_VALUE_2 && mof != MOF_COND_VALUE_3 && mof != MOF_COND_DESTINATION && mof != MOF_COND_STATION_ID) return CMD_ERROR;
if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_VALUE_2 && mof != MOF_COND_VALUE_3 && mof != MOF_COND_VALUE_4 && mof != MOF_COND_DESTINATION && mof != MOF_COND_STATION_ID) return CMD_ERROR;
break;
case OT_SLOT:
@ -2137,6 +2137,17 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
}
break;
case MOF_COND_VALUE_4:
switch (order->GetConditionVariable()) {
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
if (data > 1) return CMD_ERROR;
break;
default:
return CMD_ERROR;
}
break;
case MOF_COND_STATION_ID:
if (ConditionVariableHasStationID(order->GetConditionVariable())) {
if (Station::GetIfValid(data) == nullptr) return CMD_ERROR;
@ -2426,6 +2437,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
SB(order->GetXDataRef(), 16, 16, data + 2);
break;
case MOF_COND_VALUE_4:
SB(order->GetXData2Ref(), 16, 1, data);
break;
case MOF_COND_STATION_ID:
SB(order->GetXData2Ref(), 0, 16, data + 1);
if (ConditionVariableTestsCargoWaitingAmount(order->GetConditionVariable()) && data == GB(order->GetXData(), 16, 16) - 2) {
@ -3390,16 +3405,41 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE: {
StationID next_station = GB(order->GetXData2(), 0, 16) - 1;
if (Station::IsValidID(next_station)) {
const bool refit_mode = HasBit(order->GetXData2(), 16);
const CargoID cargo = static_cast<CargoID>(value);
uint32_t waiting;
if (GB(order->GetXData(), 16, 16) == 0) {
waiting = Station::Get(next_station)->goods[value].CargoAvailableCount();
waiting = Station::Get(next_station)->goods[cargo].CargoAvailableCount();
} else {
waiting = Station::Get(next_station)->goods[value].CargoAvailableViaCount(GB(order->GetXData(), 16, 16) - 2);
waiting = Station::Get(next_station)->goods[cargo].CargoAvailableViaCount(GB(order->GetXData(), 16, 16) - 2);
}
uint32_t veh_capacity = 0;
for (const Vehicle *v_iter = v; v_iter != nullptr; v_iter = v_iter->Next()) {
if (v_iter->cargo_type == value) veh_capacity += v_iter->cargo_cap;
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
if (u->cargo_type == cargo) {
veh_capacity += u->cargo_cap;
} else if (refit_mode) {
const Engine *e = Engine::Get(u->engine_type);
if (!HasBit(e->info.refit_mask, cargo)) {
continue;
}
/* Back up the vehicle's cargo type */
const CargoID temp_cid = u->cargo_type;
const uint8_t temp_subtype = u->cargo_subtype;
const_cast<Vehicle *>(u)->cargo_type = value;
if (e->refit_capacity_values == nullptr || !(e->callbacks_used & SGCU_REFIT_CB_ALL_CARGOES) || cargo == e->GetDefaultCargoType() || (e->type == VEH_AIRCRAFT && IsCargoInClass(cargo, CC_PASSENGERS))) {
/* This can be omitted when the refit capacity values are already determined, and the capacity is definitely from the refit callback */
const_cast<Vehicle *>(u)->cargo_subtype = GetBestFittingSubType(u, const_cast<Vehicle *>(u), cargo);
}
veh_capacity += e->DetermineCapacity(u, nullptr); // special mail handling for aircraft is not required here
/* Restore the original cargo type */
const_cast<Vehicle *>(u)->cargo_type = temp_cid;
const_cast<Vehicle *>(u)->cargo_subtype = temp_subtype;
}
}
uint32_t percentage = GB(order->GetXData(), 0, 16);
uint32_t threshold = static_cast<uint32_t>(((uint64_t)veh_capacity * percentage) / 100);

View File

@ -1060,7 +1060,9 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
auto output_condition_value = [&](int param_offset) {
if (percent_mode) {
auto capacity_params = MakeParameters(GB(order->GetXData(), 0, 16), CargoSpec::Get(order->GetConditionValue())->name);
_temp_special_strings[0] = GetStringWithArgs(STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY, capacity_params);
bool refit = HasBit(order->GetXData2(), 16);
StringID capacity_str = refit ? STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY_REFIT : STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY;
_temp_special_strings[0] = GetStringWithArgs(capacity_str, capacity_params);
tmp_params.SetParam(param_offset, SPECSTR_TEMP_START);
} else {
tmp_params.SetParam(param_offset, order->GetConditionValue());
@ -1527,6 +1529,9 @@ private:
/* WID_O_SEL_COND_AUX3 */
DP_COND_AUX3_STATION = 0, ///< Display station button
/* WID_O_SEL_COND_AUX4 */
DP_COND_AUX4_REFIT_MODE = 0, ///< Display refit mode button
/* WID_O_SEL_BOTTOM_MIDDLE */
DP_BOTTOM_MIDDLE_DELETE = 0, ///< Display 'delete' in the middle button of the bottom row of the vehicle order window.
DP_BOTTOM_MIDDLE_STOP_SHARING = 1, ///< Display 'stop sharing' in the middle button of the bottom row of the vehicle order window.
@ -1550,6 +1555,7 @@ private:
int current_aux_plane;
int current_aux2_plane;
int current_aux3_plane;
int current_aux4_plane;
int current_mgmt_plane;
/**
@ -1950,17 +1956,21 @@ public:
this->current_aux_plane = SZSP_NONE;
this->current_aux2_plane = SZSP_NONE;
this->current_aux3_plane = SZSP_NONE;
this->current_aux4_plane = SZSP_NONE;
this->current_mgmt_plane = this->GetOrderManagementPlane();
if (v->owner == _local_company) {
NWidgetStacked *aux_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX);
NWidgetStacked *aux2_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX2);
NWidgetStacked *aux3_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX3);
NWidgetStacked *aux4_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX4);
aux_sel->independent_planes = true;
aux2_sel->independent_planes = true;
aux3_sel->independent_planes = true;
aux4_sel->independent_planes = true;
aux_sel->SetDisplayedPlane(this->current_aux_plane);
aux2_sel->SetDisplayedPlane(this->current_aux2_plane);
aux3_sel->SetDisplayedPlane(this->current_aux3_plane);
aux4_sel->SetDisplayedPlane(this->current_aux4_plane);
this->GetWidget<NWidgetStacked>(WID_O_SEL_MGMT)->SetDisplayedPlane(this->current_mgmt_plane);
}
this->FinishInitNested(v->index);
@ -2191,6 +2201,7 @@ public:
NWidgetStacked *aux_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX);
NWidgetStacked *aux2_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX2);
NWidgetStacked *aux3_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX3);
NWidgetStacked *aux4_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_AUX4);
NWidgetStacked *mgmt_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_MGMT);
mgmt_sel->SetDisplayedPlane(this->GetOrderManagementPlane());
@ -2208,6 +2219,10 @@ public:
this->current_aux3_plane = aux3_sel->shown_plane;
reinit = true;
}
if (this->current_aux4_plane != aux4_sel->shown_plane) {
this->current_aux4_plane = aux4_sel->shown_plane;
reinit = true;
}
if ((this->current_mgmt_plane == SZSP_NONE) != (mgmt_sel->shown_plane == SZSP_NONE)) {
this->current_mgmt_plane = mgmt_sel->shown_plane;
reinit = true;
@ -2220,6 +2235,7 @@ public:
aux_sel->SetDisplayedPlane(SZSP_NONE);
aux2_sel->SetDisplayedPlane(SZSP_NONE);
aux3_sel->SetDisplayedPlane(SZSP_NONE);
aux4_sel->SetDisplayedPlane(SZSP_NONE);
if (order == nullptr) {
if (row_sel != nullptr) {
@ -2373,6 +2389,13 @@ public:
aux3_sel->SetDisplayedPlane(SZSP_NONE);
}
if (ocv == OCV_CARGO_WAITING_AMOUNT_PERCENTAGE) {
aux4_sel->SetDisplayedPlane(DP_COND_AUX4_REFIT_MODE);
this->SetWidgetLoweredState(WID_O_COND_AUX_REFIT_MODE, HasBit(order->GetXData2(), 16));
} else {
aux4_sel->SetDisplayedPlane(SZSP_NONE);
}
/* Set the strings for the dropdown boxes. */
this->GetWidget<NWidgetCore>(WID_O_COND_VARIABLE)->widget_data = OrderStringForVariable(this->vehicle, ocv);
this->GetWidget<NWidgetCore>(WID_O_COND_COMPARATOR)->widget_data = GetComparatorStrings(this->vehicle, order)[order->GetConditionComparator()];
@ -3165,6 +3188,11 @@ public:
break;
}
case WID_O_COND_AUX_REFIT_MODE: {
this->ModifyOrder(this->OrderGetSel(), MOF_COND_VALUE_4 | (HasBit(this->vehicle->GetOrder(this->OrderGetSel())->GetXData2(), 16) ? 0 : 1) << 8);
break;
}
case WID_O_TIMETABLE_VIEW:
ShowTimetableWindow(this->vehicle);
break;
@ -3904,6 +3932,10 @@ static constexpr NWidgetPart _nested_orders_train_widgets[] = {
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_SCHED_TEST), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_SCHED_TEST_TOOLTIP), SetResize(1, 0),
EndContainer(),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_AUX4),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_O_COND_AUX_REFIT_MODE), SetMinimalSize(72, 12),
SetDataTip(STR_ORDER_CONDITIONAL_REFIT_MODE, STR_ORDER_CONDITIONAL_REFIT_MODE_TOOLTIP),
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),
@ -4047,6 +4079,10 @@ static constexpr NWidgetPart _nested_orders_widgets[] = {
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_SCHED_TEST), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_SCHED_TEST_TOOLTIP), SetResize(1, 0),
EndContainer(),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_AUX4),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_O_COND_AUX_REFIT_MODE), SetMinimalSize(72, 12),
SetDataTip(STR_ORDER_CONDITIONAL_REFIT_MODE, STR_ORDER_CONDITIONAL_REFIT_MODE_TOOLTIP),
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),

View File

@ -230,6 +230,7 @@ enum ModifyOrderFlags : uint8_t {
MOF_COND_VALUE, ///< The value to set the condition to.
MOF_COND_VALUE_2, ///< The secondary value to set the condition to.
MOF_COND_VALUE_3, ///< The tertiary value to set the condition to.
MOF_COND_VALUE_4, ///< The quaternary value to set the condition to.
MOF_COND_STATION_ID, ///< The station ID to set the condition to.
MOF_COND_DESTINATION,///< Change the destination of a conditional order.
MOF_WAYPOINT_FLAGS, ///< Change the waypoint flags

View File

@ -45,6 +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_COND_AUX_REFIT_MODE, ///< Condition refit mode button.
WID_O_SLOT, ///< Choose slot to try acquire/release.
WID_O_COUNTER_OP, ///< Choose counter operation.
WID_O_CHANGE_COUNTER, ///< Choose counter to change.
@ -55,6 +56,7 @@ enum OrderWidgets : WidgetID {
WID_O_SEL_COND_AUX, ///< Widget for auxiliary conditional cargo type.
WID_O_SEL_COND_AUX2, ///< Widget for auxiliary conditional via button.
WID_O_SEL_COND_AUX3, ///< Widget for auxiliary conditional station button.
WID_O_SEL_COND_AUX4, ///< Widget for auxiliary conditional refit mode button.
WID_O_SEL_MGMT, ///< Widget for management buttons.
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.