Add conditional order to test if last/next dispatch slot is first/last

pull/407/head
Jonathan G Rennison 2 years ago
parent 116ddf4b35
commit 4e8a8a5e0a

@ -81,13 +81,17 @@ static bool IsArrival(const Order *order, StationID station) {
!(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION));
}
static uint8 GetDepartureConditionalOrderMode(const Order *order, DateTicksScaled eval_date)
static uint8 GetDepartureConditionalOrderMode(const Order *order, const Vehicle *v, DateTicksScaled eval_date)
{
if (order->GetConditionVariable() == OCV_UNCONDITIONALLY) return 1;
if (order->GetConditionVariable() == OCV_TIME_DATE) {
int value = GetTraceRestrictTimeDateValueFromDate(static_cast<TraceRestrictTimeDateValueField>(order->GetConditionValue()), eval_date);
return OrderConditionCompare(order->GetConditionComparator(), value, order->GetXData()) ? 1 : 2;
}
if (order->GetConditionVariable() == OCV_DISPATCH_SLOT) {
extern bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v, DateTicksScaled date_time, bool *predicted);
return EvaluateDispatchSlotConditionalOrder(order, v, eval_date, nullptr) ? 1 : 2;
}
return _settings_client.gui.departure_conditionals;
}
@ -306,7 +310,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
/* If the order is a conditional branch, handle it. */
if (order->IsType(OT_CONDITIONAL)) {
switch(GetDepartureConditionalOrderMode(order, start_date + date_only_scaled)) {
switch(GetDepartureConditionalOrderMode(order, v, start_date + date_only_scaled)) {
case 0: {
/* Give up */
break;
@ -472,7 +476,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
/* If the order is a conditional branch, handle it. */
if (order->IsType(OT_CONDITIONAL)) {
switch (GetDepartureConditionalOrderMode(order, c.scheduled_date != 0 ? c.scheduled_date : _scaled_date_ticks)) {
switch (GetDepartureConditionalOrderMode(order, least_order->v, c.scheduled_date != 0 ? c.scheduled_date : _scaled_date_ticks)) {
case 0: {
/* Give up */
break;
@ -716,7 +720,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
/* If the order is a conditional branch, handle it. */
if (order->IsType(OT_CONDITIONAL)) {
switch(GetDepartureConditionalOrderMode(order, least_order->expected_date)) {
switch(GetDepartureConditionalOrderMode(order, least_order->v, least_order->expected_date)) {
case 0: {
/* Give up */
break;

@ -3411,6 +3411,10 @@ STR_TRACE_RESTRICT_TIME_DAY_ITEM_SHORT :day
STR_TRACE_RESTRICT_TIME_MONTH_ITEM_SHORT :month
STR_TRACE_RESTRICT_TIMETABLE_LATENESS :lateness
STR_TRACE_RESTRICT_TIMETABLE_EARLINESS :earliness
STR_TRACE_RESTRICT_DISPATCH_SLOT_NEXT :next departure slot
STR_TRACE_RESTRICT_DISPATCH_SLOT_LAST :last departure slot
STR_TRACE_RESTRICT_DISPATCH_SLOT_SHORT_NEXT :next
STR_TRACE_RESTRICT_DISPATCH_SLOT_SHORT_LAST :last
STR_TRACE_RESTRICT_VALUE_CAPTION :{WHITE}Value
STR_TRACE_RESTRICT_CAPTION :{WHITE}Routefinding restriction
STR_TRACE_RESTRICT_CAPTION_SHARED :{WHITE}Routefinding restriction - shared by {COMMA} signals
@ -5549,6 +5553,7 @@ STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT :Waiting cargo a
STR_ORDER_CONDITIONAL_COUNTER_VALUE :Counter value
STR_ORDER_CONDITIONAL_TIME_DATE_VALUE :Current time/date
STR_ORDER_CONDITIONAL_TIMETABLE_STATE :Timetable state
STR_ORDER_CONDITIONAL_DISPATCH_SLOT :Dispatch slot
STR_ORDER_CONDITIONAL_VEHICLE_IN_SLOT :Vehicle in slot
@ -5576,6 +5581,8 @@ STR_ORDER_CONDITIONAL_SLOT_TOOLTIP :{BLACK}The trai
STR_ORDER_CONDITIONAL_COUNTER_TOOLTIP :{BLACK}The counter to check the value of
STR_ORDER_CONDITIONAL_TIME_DATE_TOOLTIP :{BLACK}The current time/date field to check the value of
STR_ORDER_CONDITIONAL_TIMETABLE_TOOLTIP :{BLACK}The timetable field to check the value of
STR_ORDER_CONDITIONAL_SCHED_SELECT_TOOLTIP :{BLACK}The dispatch schedule to use
STR_ORDER_CONDITIONAL_SCHED_TEST_TOOLTIP :{BLACK}The dispatch schedule condition to test
STR_ORDER_CONDITIONAL_VALUE_CAPT :{WHITE}Enter value to compare against
STR_ORDER_CONDITIONAL_VIA :{BLACK}Via
@ -5599,6 +5606,10 @@ STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_IN_SLOT :vehicle is in
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_NOT_IN_SLOT :vehicle is not in
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_IN_ACQUIRE_SLOT :vehicle is in/acquire
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_NOT_IN_ACQUIRE_SLOT :vehicle is not in/can't acquire
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_FIRST :is first slot
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_NOT_FIRST :is not first slot
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_LAST :is last slot
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_NOT_LAST :is not last slot
STR_ORDERS_SKIP_BUTTON :{BLACK}Skip
STR_ORDERS_SKIP_TOOLTIP :{BLACK}Skip the current order, and start the next. Ctrl+Click skips to the selected order
@ -5740,6 +5751,7 @@ STR_ORDER_CONDITIONAL_COUNTER :Jump to order {
STR_ORDER_CONDITIONAL_INVALID_COUNTER :Jump to order {COMMA} when value of {PUSH_COLOUR}{RED}{STRING}{POP_COLOUR} {STRING} {COMMA}
STR_ORDER_CONDITIONAL_TIME_HHMM :Jump to order {COMMA} when {STRING} {STRING} {TIME_HHMM}
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_RELEASE_SLOT :Release slot: {STRING1}
@ -7060,6 +7072,7 @@ STR_RED_INT :{RED}{NUM}
STR_WHITE_SIGN :{WHITE}{SIGN}
STR_TINY_BLACK_STATION :{TINY_FONT}{BLACK}{STATION}
STR_BLACK_STRING :{BLACK}{STRING}
STR_BLACK_STRING1 :{BLACK}{STRING1}
STR_BLACK_RAW_STRING :{BLACK}{RAW_STRING}
STR_ORANGE_STRING :{ORANGE}{STRING}
STR_LTBLUE_STRING :{LTBLUE}{STRING}

@ -38,6 +38,7 @@
#include "vehiclelist.h"
#include "tracerestrict.h"
#include "train.h"
#include "date_func.h"
#include "table/strings.h"
@ -1793,6 +1794,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case OCV_CARGO_ACCEPTANCE:
case OCV_CARGO_WAITING:
case OCV_SLOT_OCCUPANCY:
case OCV_DISPATCH_SLOT:
if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
break;
@ -1844,6 +1846,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case OCV_COUNTER_VALUE:
case OCV_TIME_DATE:
case OCV_TIMETABLE:
case OCV_DISPATCH_SLOT:
break;
default:
@ -1871,6 +1874,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
if (data >= OTCM_END) return CMD_ERROR;
break;
case OCV_DISPATCH_SLOT:
if (data >= OSDSCM_END) return CMD_ERROR;
break;
default:
return CMD_ERROR;
}
@ -2048,6 +2055,11 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
order->SetConditionValue(0);
break;
case OCV_DISPATCH_SLOT:
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
order->SetConditionValue(0);
order->GetXDataRef() = UINT16_MAX;
break;
case OCV_PERCENT:
order->SetConditionComparator(OCC_EQUALS);
@ -2088,6 +2100,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case OCV_CARGO_WAITING_AMOUNT:
case OCV_COUNTER_VALUE:
case OCV_DISPATCH_SLOT:
SB(order->GetXDataRef(), 0, 16, data);
break;
@ -2789,6 +2802,38 @@ static uint16 GetFreeStationPlatforms(StationID st_id)
return counter;
}
bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v, DateTicksScaled date_time, bool *predicted)
{
uint schedule_index = GB(order->GetXData(), 0, 16);
if (schedule_index >= v->orders->GetScheduledDispatchScheduleCount()) return false;
const DispatchSchedule &sched = v->orders->GetDispatchScheduleByIndex(schedule_index);
if (sched.GetScheduledDispatch().size() == 0) return false;
if (predicted != nullptr) *predicted = true;
int32 offset;
if (order->GetConditionValue() & 2) {
int32 last = sched.GetScheduledDispatchLastDispatch();
if (last < 0) {
last += sched.GetScheduledDispatchDuration() * (1 + (-last / sched.GetScheduledDispatchDuration()));
}
offset = last % sched.GetScheduledDispatchDuration();
} else {
extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
DateTicksScaled slot = GetScheduledDispatchTime(sched, _scaled_date_ticks);
offset = (slot - sched.GetScheduledDispatchStartTick()) % sched.GetScheduledDispatchDuration();
}
bool value;
if (order->GetConditionValue() & 1) {
value = (offset == (int)sched.GetScheduledDispatch().back());
} else {
value = (offset == (int)sched.GetScheduledDispatch().front());
}
return OrderConditionCompare(order->GetConditionComparator(), value, 0);
}
/** Gets the next 'real' station in the order list
* @param v the vehicle in question
* @param order the current (conditional) order
@ -2941,6 +2986,10 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
skip_order = OrderConditionCompare(occ, tt_value, order->GetXData());
break;
}
case OCV_DISPATCH_SLOT: {
skip_order = EvaluateDispatchSlotConditionalOrder(order, v, _scaled_date_ticks, nullptr);
break;
}
default: NOT_REACHED();
}

@ -659,6 +659,7 @@ static const OrderConditionVariable _order_conditional_variable[] = {
OCV_COUNTER_VALUE,
OCV_TIME_DATE,
OCV_TIMETABLE,
OCV_DISPATCH_SLOT,
OCV_PERCENT,
OCV_UNCONDITIONALLY,
};
@ -735,6 +736,30 @@ static const StringID _order_conditional_condition_is_in_slot_non_train[] = {
INVALID_STRING_ID,
};
static const StringID _order_conditional_condition_dispatch_slot_first[] = {
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_FIRST,
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_NOT_FIRST,
INVALID_STRING_ID,
};
static const StringID _order_conditional_condition_dispatch_slot_last[] = {
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_LAST,
STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_NOT_LAST,
INVALID_STRING_ID,
};
extern uint ConvertSpeedToDisplaySpeed(uint speed);
extern uint ConvertDisplaySpeedToSpeed(uint speed);
@ -780,6 +805,12 @@ static const StringID _order_timetable_dropdown[] = {
INVALID_STRING_ID
};
static const StringID _order_dispatch_slot_dropdown[] = {
STR_TRACE_RESTRICT_DISPATCH_SLOT_NEXT,
STR_TRACE_RESTRICT_DISPATCH_SLOT_LAST,
INVALID_STRING_ID
};
StringID OrderStringForVariable(const Vehicle *v, OrderConditionVariable ocv)
{
if (ocv == OCV_VEH_IN_SLOT && v->type != VEH_TRAIN) return STR_ORDER_CONDITIONAL_VEHICLE_IN_SLOT;
@ -1019,6 +1050,21 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SetDParam(2, STR_TRACE_RESTRICT_TIMETABLE_LATENESS + order->GetConditionValue());
SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + order->GetConditionComparator());
SetDParam(4, order->GetXData());
} else if (ocv == OCV_DISPATCH_SLOT) {
SetDParam(0, STR_ORDER_CONDITIONAL_DISPATCH_SLOT_DISPLAY);
if (GB(order->GetXData(), 0, 16) != UINT16_MAX) {
char buf[256];
int64 args_array[] = { GB(order->GetXData(), 0, 16) + 1 };
StringParameters tmp_params(args_array);
char *end = GetStringWithArgs(buf, STR_TIMETABLE_ASSIGN_SCHEDULE_ID, &tmp_params, lastof(buf));
_temp_special_strings[0].assign(buf, end);
SetDParam(2, SPECSTR_TEMP_START);
} else {
SetDParam(2, STR_TIMETABLE_ASSIGN_SCHEDULE_NONE);
}
SetDParam(3, STR_TRACE_RESTRICT_DISPATCH_SLOT_NEXT + (order->GetConditionValue() / 2));
SetDParam(4, STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_FIRST + ((order->GetConditionComparator() == OCC_IS_FALSE) ? 1 : 0) +
((order->GetConditionValue() % 2) ? 2 : 0));
} else {
OrderConditionComparator occ = order->GetConditionComparator();
SetDParam(0, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_ORDER_CONDITIONAL_TRUE_FALSE : STR_ORDER_CONDITIONAL_NUM);
@ -1287,9 +1333,11 @@ private:
DP_COND_TIME_DATE = 1, ///< Display dropdown for current time/date field
DP_COND_TIMETABLE = 2, ///< Display dropdown for timetable field
DP_COND_COUNTER = 3, ///< Display dropdown widget counters
DP_COND_SCHED_SELECT = 4, ///< Display dropdown for scheduled dispatch schedule selection
/* WID_O_SEL_COND_AUX2 */
DP_COND_AUX2_VIA = 0, ///< Display via button
DP_COND_AUX2_SCHED_TEST = 1, ///< Display dropdown for scheduled dispatch test selection
DP_ROW_CONDITIONAL = 2, ///< Display the conditional order buttons in the top row of the ship/airplane order window.
@ -1371,6 +1419,9 @@ private:
case OCV_VEH_IN_SLOT:
return v->type == VEH_TRAIN ? _order_conditional_condition_is_in_slot : _order_conditional_condition_is_in_slot_non_train;
case OCV_DISPATCH_SLOT:
return (order->GetConditionValue() % 2) == 0 ? _order_conditional_condition_dispatch_slot_first : _order_conditional_condition_dispatch_slot_last;
default:
return _order_conditional_condition;
}
@ -1965,6 +2016,7 @@ public:
bool is_counter = (ocv == OCV_COUNTER_VALUE);
bool is_time_date = (ocv == OCV_TIME_DATE);
bool is_timetable = (ocv == OCV_TIMETABLE);
bool is_sched_dispatch = (ocv == OCV_DISPATCH_SLOT);
if (is_cargo) {
if (order == nullptr || !CargoSpec::Get(order->GetConditionValue())->IsValid()) {
@ -1978,6 +2030,8 @@ public:
this->GetWidget<NWidgetCore>(WID_O_COND_SLOT)->widget_data = (slot_id != INVALID_TRACE_RESTRICT_SLOT_ID) ? STR_TRACE_RESTRICT_SLOT_NAME : STR_TRACE_RESTRICT_VARIABLE_UNDEFINED;
this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(DP_COND_VALUE_SLOT);
} else if (is_sched_dispatch) {
this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(SZSP_NONE);
} else {
this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(DP_COND_VALUE_NUMBER);
}
@ -2000,12 +2054,18 @@ public:
} else if (is_timetable) {
this->GetWidget<NWidgetCore>(WID_O_COND_TIMETABLE)->widget_data = STR_TRACE_RESTRICT_TIMETABLE_LATENESS + order->GetConditionValue();
aux_sel->SetDisplayedPlane(DP_COND_TIMETABLE);
} else if (is_sched_dispatch) {
this->GetWidget<NWidgetCore>(WID_O_COND_SCHED_SELECT)->widget_data = STR_BLACK_STRING1;
aux_sel->SetDisplayedPlane(DP_COND_SCHED_SELECT);
} else {
aux_sel->SetDisplayedPlane(SZSP_NONE);
}
if (ocv == OCV_CARGO_WAITING_AMOUNT) {
aux2_sel->SetDisplayedPlane(DP_COND_AUX2_VIA);
} else if (is_sched_dispatch) {
this->GetWidget<NWidgetCore>(WID_O_COND_SCHED_TEST)->widget_data = STR_TRACE_RESTRICT_DISPATCH_SLOT_SHORT_NEXT + (order->GetConditionValue() / 2);
aux2_sel->SetDisplayedPlane(DP_COND_AUX2_SCHED_TEST);
} else {
aux2_sel->SetDisplayedPlane(SZSP_NONE);
}
@ -2255,6 +2315,19 @@ public:
break;
}
case WID_O_COND_SCHED_SELECT: {
VehicleOrderID sel = this->OrderGetSel();
const Order *order = this->vehicle->GetOrder(sel);
if (order != nullptr && order->IsType(OT_CONDITIONAL) && GB(order->GetXData(), 0, 16) != UINT16_MAX) {
SetDParam(0, STR_TIMETABLE_ASSIGN_SCHEDULE_ID);
SetDParam(1, GB(order->GetXData(), 0, 16) + 1);
} else {
SetDParam(0, STR_TIMETABLE_ASSIGN_SCHEDULE_NONE);
}
break;
}
case WID_O_CAPTION:
SetDParam(0, this->vehicle->index);
break;
@ -2478,6 +2551,27 @@ public:
break;
}
case WID_O_COND_SCHED_SELECT: {
int selected = GB(this->vehicle->GetOrder(this->OrderGetSel())->GetXData(), 0, 16);
if (selected == UINT16_MAX) selected = -1;
uint count = this->vehicle->orders->GetScheduledDispatchScheduleCount();
DropDownList list;
for (uint i = 0; i < count; ++i) {
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_TIMETABLE_ASSIGN_SCHEDULE_ID, i, false);
item->SetParam(0, i + 1);
list.emplace_back(item);
}
if (!list.empty()) ShowDropDownList(this, std::move(list), selected, WID_O_COND_SCHED_SELECT, 0, true);
break;
}
case WID_O_COND_SCHED_TEST: {
ShowDropDownMenu(this, _order_dispatch_slot_dropdown, this->vehicle->GetOrder(this->OrderGetSel())->GetConditionValue() / 2,
WID_O_COND_SCHED_TEST, 0, 0, UINT_MAX);
break;
}
case WID_O_REVERSE: {
VehicleOrderID sel_ord = this->OrderGetSel();
const Order *order = this->vehicle->GetOrder(sel_ord);
@ -2527,6 +2621,9 @@ public:
_order_conditional_variable[i] == OCV_COUNTER_VALUE) && !_settings_client.gui.show_adv_tracerestrict_features) {
continue;
}
if ((_order_conditional_variable[i] == OCV_DISPATCH_SLOT) && this->vehicle->orders->GetScheduledDispatchScheduleCount() == 0) {
continue;
}
}
list.emplace_back(new DropDownListStringItem(OrderStringForVariable(this->vehicle, _order_conditional_variable[i]), _order_conditional_variable[i], false));
}
@ -2536,6 +2633,16 @@ public:
case WID_O_COND_COMPARATOR: {
const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
if (o->GetConditionVariable() == OCV_DISPATCH_SLOT) {
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_FIRST, 0x100, false));
list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_NOT_FIRST, 0x101, false));
list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_LAST, 0x102, false));
list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_COMPARATOR_DISPATCH_SLOT_IS_NOT_LAST, 0x103, false));
int selected = ((o->GetConditionValue() % 2) * 2) + ((o->GetConditionComparator() == OCC_IS_FALSE) ? 1 : 0);
ShowDropDownList(this, std::move(list), selected, WID_O_COND_COMPARATOR, 0, true);
break;
}
uint mask;
switch (o->GetConditionVariable()) {
case OCV_REQUIRES_SERVICE:
@ -2701,7 +2808,14 @@ public:
break;
case WID_O_COND_COMPARATOR:
this->ModifyOrder(this->OrderGetSel(), MOF_COND_COMPARATOR | index << 4);
if (index >= 0x100) {
const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
if (o == nullptr || o->GetConditionVariable() != OCV_DISPATCH_SLOT) return;
this->ModifyOrder(this->OrderGetSel(), MOF_COND_COMPARATOR | ((index & 1) ? OCC_IS_FALSE : OCC_IS_TRUE) << 4);
this->ModifyOrder(this->OrderGetSel(), MOF_COND_VALUE_2 | ((o->GetConditionValue() & 2) | ((index & 2) >> 1)) << 4);
} else {
this->ModifyOrder(this->OrderGetSel(), MOF_COND_COMPARATOR | index << 4);
}
break;
case WID_O_COND_CARGO:
@ -2728,6 +2842,18 @@ public:
this->ModifyOrder(this->OrderGetSel(), MOF_COND_VALUE_2 | index << 4);
break;
case WID_O_COND_SCHED_SELECT:
this->ModifyOrder(this->OrderGetSel(), MOF_COND_VALUE | index << 4);
break;
case WID_O_COND_SCHED_TEST: {
const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
if (o == nullptr) return;
index = (index * 2) | (o->GetConditionValue() & 1);
this->ModifyOrder(this->OrderGetSel(), MOF_COND_VALUE_2 | index << 4);
break;
}
case WID_O_RELEASE_SLOT:
this->ModifyOrder(this->OrderGetSel(), MOF_SLOT | index << 4);
break;
@ -2990,10 +3116,14 @@ static const NWidgetPart _nested_orders_train_widgets[] = {
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_TIMETABLE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COUNTER), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_COUNTER_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_SCHED_SELECT), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_SCHED_SELECT_TOOLTIP), SetResize(1, 0),
EndContainer(),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_AUX2),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_O_COND_AUX_VIA), SetMinimalSize(36, 12),
SetDataTip(STR_ORDER_CONDITIONAL_VIA, STR_ORDER_CONDITIONAL_VIA_TOOLTIP),
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(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),
@ -3100,10 +3230,14 @@ static const NWidgetPart _nested_orders_widgets[] = {
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_TIME_DATE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_TIMETABLE), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_TIMETABLE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_SCHED_SELECT), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_SCHED_SELECT_TOOLTIP), SetResize(1, 0),
EndContainer(),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_COND_AUX2),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_O_COND_AUX_VIA), SetMinimalSize(36, 12),
SetDataTip(STR_ORDER_CONDITIONAL_VIA, STR_ORDER_CONDITIONAL_VIA_TOOLTIP),
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(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),

@ -158,6 +158,7 @@ enum OrderConditionVariable {
OCV_COUNTER_VALUE, ///< Skip based on counter value
OCV_TIME_DATE, ///< Skip based on current time/date
OCV_TIMETABLE, ///< Skip based on timetable state
OCV_DISPATCH_SLOT, ///< Skip based on scheduled dispatch slot state
OCV_END
};
@ -229,6 +230,14 @@ enum OrderTimetableConditionMode {
OTCM_END
};
enum OrderScheduledDispatchSlotConditionMode {
OSDSCM_NEXT_FIRST = 0, ///< Test if next departure is first slot
OSDSCM_NEXT_LAST = 1, ///< Test if next departure is last slot
OSDSCM_LAST_FIRST = 2, ///< Test if last departure was first slot
OSDSCM_LAST_LAST = 3, ///< Test if last departure was last slot
OSDSCM_END
};
/**
* Enumeration for the data to set in #CmdChangeTimetable.
*/

@ -99,7 +99,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, 11, 11, "more_cond_orders", nullptr, nullptr, nullptr },
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 12, 12, "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 },

@ -393,6 +393,16 @@ CommandCost CmdScheduledDispatchRemoveSchedule(TileIndex tile, DoCommandFlag fla
} else if (idx > (int)schedule_index) {
o->SetDispatchScheduleIndex(idx - 1);
}
if (o->IsType(OT_CONDITIONAL) && o->GetConditionVariable() == OCV_DISPATCH_SLOT) {
uint16 dispatch_slot = GB(o->GetXData(), 0, 16);
if (dispatch_slot == UINT16_MAX) {
/* do nothing */
} else if (dispatch_slot == schedule_index) {
SB(o->GetXDataRef(), 0, 16, UINT16_MAX);
} else if (dispatch_slot > schedule_index) {
SB(o->GetXDataRef(), 0, 16, (uint16)(dispatch_slot - 1));
}
}
}
SchdispatchInvalidateWindows(v);
}

@ -163,6 +163,14 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
break;
}
case OCV_DISPATCH_SLOT: {
DateTicksScaled time = _scaled_date_ticks + sum;
if (!no_offset) time -= v->lateness_counter;
extern bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v, DateTicksScaled date_time, bool *predicted);
jump = EvaluateDispatchSlotConditionalOrder(order, v, time, &predicted);
break;
}
default:
return;
}

@ -40,7 +40,9 @@ enum OrderWidgets {
WID_O_COND_COUNTER, ///< Choose condition counter.
WID_O_COND_TIME_DATE, ///< Choose time/date value.
WID_O_COND_TIMETABLE, ///< Choose timetable value.
WID_O_COND_SCHED_SELECT, ///< Choose scheduled dispatch schedule.
WID_O_COND_AUX_VIA, ///< Condition via button.
WID_O_COND_SCHED_TEST, ///< Choose scheduled dispatch test.
WID_O_RELEASE_SLOT, ///< Choose slot to release.
WID_O_SEL_COND_VALUE, ///< Widget for conditional value or conditional cargo type.
WID_O_SEL_COND_AUX, ///< Widget for auxiliary conditional cargo type.

Loading…
Cancel
Save