Add slot support to road vehicles, ships and aircraft

pull/362/head
Jonathan G Rennison 2 years ago
parent 0513961b2a
commit 904ff6757d

@ -429,12 +429,13 @@ CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, DoComma
if (old_head->type == VEH_TRAIN) {
Train::From(new_head)->speed_restriction = Train::From(old_head)->speed_restriction;
/* Transfer any acquired trace restrict slots to the new vehicle */
if (HasBit(Train::From(old_head)->flags, VRF_HAVE_SLOT)) {
TraceRestrictTransferVehicleOccupantInAllSlots(old_head->index, new_head->index);
ClrBit(Train::From(old_head)->flags, VRF_HAVE_SLOT);
SetBit(Train::From(new_head)->flags, VRF_HAVE_SLOT);
}
}
/* Transfer any acquired trace restrict slots to the new vehicle */
if (HasBit(old_head->vehicle_flags, VF_HAVE_SLOT)) {
TraceRestrictTransferVehicleOccupantInAllSlots(old_head->index, new_head->index);
ClrBit(old_head->vehicle_flags, VF_HAVE_SLOT);
SetBit(new_head->vehicle_flags, VF_HAVE_SLOT);
}
}

@ -31,7 +31,7 @@ struct BaseConsist {
VehicleOrderID cur_implicit_order_index;///< The index to the current implicit order
VehicleOrderID cur_timetable_order_index;///< The index to the current real (non-implicit) order used for timetable updates
uint16 vehicle_flags; ///< Used for gradual loading and other miscellaneous things (@see VehicleFlags enum)
uint32 vehicle_flags; ///< Used for gradual loading and other miscellaneous things (@see VehicleFlags enum)
virtual ~BaseConsist() {}

@ -1094,8 +1094,8 @@ public:
break;
case ADI_TRACERESTRICT_SLOT_MGMT: {
extern void ShowTraceRestrictSlotWindow(CompanyID company);
ShowTraceRestrictSlotWindow(this->owner);
extern void ShowTraceRestrictSlotWindow(CompanyID company, VehicleType vehtype);
ShowTraceRestrictSlotWindow(this->owner, this->vli.vtype);
break;
}

@ -3212,7 +3212,7 @@ STR_TRACE_RESTRICT_SLOT_CREATE_TOOLTIP :{BLACK}Kliknut
STR_TRACE_RESTRICT_SLOT_DELETE_TOOLTIP :{BLACK}Smazat vybraný slot
STR_TRACE_RESTRICT_SLOT_RENAME_TOOLTIP :{BLACK}Přejmenovat vybraný slot
STR_TRACE_RESTRICT_SLOT_SET_MAX_OCCUPANCY_TOOLTIP :{BLACK}Nastavit maximální obsazenost vybraného slotu
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Omezení směrování - Správa slotů
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Omezení směrování - Správa slotů ({STRING})
STR_TRACE_RESTRICT_SLOT_MANAGE :Spravovat sloty
STR_TRACE_RESTRICT_SLOT_MAX_OCCUPANCY :{TINY_FONT}{COMMA} / {COMMA}
STR_TRACE_RESTRICT_SLOT_RENAME_CAPTION :{BLACK}Přejmenovat slot

@ -3302,6 +3302,7 @@ STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT_ITEM :PBS reservation
STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE_ITEM :PBS reservation ending here: Acquire slot: {STRING1}{BLACK}{STRING}, or continue anyway
STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE_ITEM :PBS reservation ending here: Release slot: {STRING1}{BLACK}{STRING}
STR_TRACE_RESTRICT_SLOT_NAME :{TRSLOT}
STR_TRACE_RESTRICT_SLOT_NAME_PREFIXED :[{STRING}] {TRSLOT}
STR_TRACE_RESTRICT_SLOT_LIST_HEADER :{BLACK}Slot{CONSUME_ARG}{P "" s}: {LTBLUE}
STR_TRACE_RESTRICT_SLOT_LIST_SEPARATOR :{BLACK}, {LTBLUE}
STR_TRACE_RESTRICT_COUNTER_NAME :{TRCOUNTER}
@ -3367,7 +3368,7 @@ STR_TRACE_RESTRICT_SLOT_CREATE_TOOLTIP :{BLACK}Click to
STR_TRACE_RESTRICT_SLOT_DELETE_TOOLTIP :{BLACK}Delete the selected slot
STR_TRACE_RESTRICT_SLOT_RENAME_TOOLTIP :{BLACK}Rename the selected slot
STR_TRACE_RESTRICT_SLOT_SET_MAX_OCCUPANCY_TOOLTIP :{BLACK}Set the maximum occupancy of the selected slot
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Routing Restrictions - Slot Management
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Routing Restrictions - Slot Management ({STRING})
STR_TRACE_RESTRICT_SLOT_MANAGE :Manage slots
STR_TRACE_RESTRICT_SLOT_MAX_OCCUPANCY :{TINY_FONT}{COMMA} / {COMMA}
STR_TRACE_RESTRICT_SLOT_RENAME_CAPTION :{BLACK}Rename a slot
@ -5452,6 +5453,8 @@ 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_VEHICLE_IN_SLOT :Vehicle in slot
STR_ORDER_CONDITIONAL_REQUIRES_SERVICE_ORDER :Requires service {STRING}
STR_ORDER_CONDITIONAL_CARGO_WAITING_ORDER :Next station {STRING} {STRING} waiting
STR_ORDER_CONDITIONAL_ACCEPTANCE :Next station {STRING} {STRING}
@ -5495,6 +5498,10 @@ STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_IN_SLOT :train is in
STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_NOT_IN_SLOT :train is not in
STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_IN_ACQUIRE_SLOT :train is in/acquire
STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_NOT_IN_ACQUIRE_SLOT :train is not in/can't acquire
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_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

@ -6192,7 +6192,7 @@ STR_TRACE_RESTRICT_SLOT_CREATE_TOOLTIP :{BLACK}Fai clic
STR_TRACE_RESTRICT_SLOT_DELETE_TOOLTIP :{BLACK}Eliminar o slot seleccionado
STR_TRACE_RESTRICT_SLOT_RENAME_TOOLTIP :{BLACK}Renomear o slot seleccionado
STR_TRACE_RESTRICT_SLOT_SET_MAX_OCCUPANCY_TOOLTIP :{BLACK}Fixar a máxima ocupación do slot seleccionado
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Restrición de busca de rutas - Xestión dos slots
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Restrición de busca de rutas - Xestión dos slots ({STRING})
STR_TRACE_RESTRICT_SLOT_MANAGE :Xestionar slots
STR_TRACE_RESTRICT_SLOT_MAX_OCCUPANCY :{TINY_FONT}{COMMA} / {COMMA}
STR_TRACE_RESTRICT_SLOT_RENAME_CAPTION :{BLACK}Renomear un slot

@ -3190,7 +3190,7 @@ STR_TRACE_RESTRICT_SLOT_CREATE_TOOLTIP :{BLACK}Einen ne
STR_TRACE_RESTRICT_SLOT_DELETE_TOOLTIP :{BLACK}Den markierten Slot löschen
STR_TRACE_RESTRICT_SLOT_RENAME_TOOLTIP :{BLACK}Den markierten Slot umbenennen
STR_TRACE_RESTRICT_SLOT_SET_MAX_OCCUPANCY_TOOLTIP :{BLACK}Die maximale Kapazität des markierten Slots festlegen
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Routing-Beschränkungen - Slot-Verwaltung
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}Routing-Beschränkungen - Slot-Verwaltung ({STRING})
STR_TRACE_RESTRICT_SLOT_MANAGE :Verwalte Slots
STR_TRACE_RESTRICT_SLOT_MAX_OCCUPANCY :{TINY_FONT}{COMMA} / {COMMA}
STR_TRACE_RESTRICT_SLOT_RENAME_CAPTION :{BLACK}Slot umbenennen

@ -3363,7 +3363,7 @@ STR_TRACE_RESTRICT_SLOT_CREATE_TOOLTIP :{BLACK}슬롯
STR_TRACE_RESTRICT_SLOT_DELETE_TOOLTIP :{BLACK}선택한 슬롯을 삭제합니다
STR_TRACE_RESTRICT_SLOT_RENAME_TOOLTIP :{BLACK}선택한 슬롯의 이름을 변경합니다
STR_TRACE_RESTRICT_SLOT_SET_MAX_OCCUPANCY_TOOLTIP :{BLACK}선택한 슬롯의 최대 수용량을 설정합니다
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}경로 제한 - 슬롯 관리자
STR_TRACE_RESTRICT_SLOT_CAPTION :{WHITE}경로 제한 - 슬롯 관리자 ({STRING})
STR_TRACE_RESTRICT_SLOT_MANAGE :슬롯 관리
STR_TRACE_RESTRICT_SLOT_MAX_OCCUPANCY :{TINY_FONT}{COMMA} / {COMMA}
STR_TRACE_RESTRICT_SLOT_RENAME_CAPTION :{BLACK}슬롯 이름 바꾸기

@ -1116,10 +1116,12 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
if (occ >= OCC_END) return CMD_ERROR;
switch (new_order.GetConditionVariable()) {
case OCV_SLOT_OCCUPANCY:
case OCV_TRAIN_IN_SLOT: {
if (v->type != VEH_TRAIN) return CMD_ERROR;
case OCV_VEH_IN_SLOT: {
TraceRestrictSlotID slot = new_order.GetXData();
if (slot != INVALID_TRACE_RESTRICT_SLOT_ID && !TraceRestrictSlot::IsValidID(slot)) return CMD_ERROR;
if (slot != INVALID_TRACE_RESTRICT_SLOT_ID) {
if (!TraceRestrictSlot::IsValidID(slot)) return CMD_ERROR;
if (new_order.GetConditionVariable() == OCV_VEH_IN_SLOT && TraceRestrictSlot::Get(slot)->vehicle_type != v->type) return CMD_ERROR;
}
switch (occ) {
case OCC_IS_TRUE:
case OCC_IS_FALSE:
@ -1127,7 +1129,7 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
case OCC_EQUALS:
case OCC_NOT_EQUALS:
if (new_order.GetConditionVariable() != OCV_TRAIN_IN_SLOT) return CMD_ERROR;
if (new_order.GetConditionVariable() != OCV_VEH_IN_SLOT) return CMD_ERROR;
break;
default:
@ -1182,9 +1184,11 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
}
case OT_RELEASE_SLOT: {
if (v->type != VEH_TRAIN) return CMD_ERROR;
TraceRestrictSlotID slot = new_order.GetDestination();
if (slot != INVALID_TRACE_RESTRICT_SLOT_ID && !TraceRestrictSlot::IsValidID(slot)) return CMD_ERROR;
TraceRestrictSlotID data = new_order.GetDestination();
if (data != INVALID_TRACE_RESTRICT_SLOT_ID) {
const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(data);
if (slot == nullptr || slot->vehicle_type != v->type) return CMD_ERROR;
}
break;
}
@ -1767,8 +1771,6 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case MOF_COND_VARIABLE:
if (data == OCV_FREE_PLATFORMS && v->type != VEH_TRAIN) return CMD_ERROR;
if (data == OCV_SLOT_OCCUPANCY && v->type != VEH_TRAIN) return CMD_ERROR;
if (data == OCV_TRAIN_IN_SLOT && v->type != VEH_TRAIN) return CMD_ERROR;
if (data >= OCV_END) return CMD_ERROR;
break;
@ -1786,9 +1788,12 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
break;
case OCV_TRAIN_IN_SLOT:
case OCV_VEH_IN_SLOT: {
if (data != OCC_IS_TRUE && data != OCC_IS_FALSE && data != OCC_EQUALS && data != OCC_NOT_EQUALS) return CMD_ERROR;
const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(order->GetXData());
if (slot != nullptr && slot->vehicle_type != v->type) return CMD_ERROR;
break;
}
case OCV_TIMETABLE:
if (data == OCC_IS_TRUE || data == OCC_IS_FALSE || data == OCC_EQUALS || data == OCC_NOT_EQUALS) return CMD_ERROR;
@ -1814,10 +1819,14 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
break;
case OCV_SLOT_OCCUPANCY:
case OCV_TRAIN_IN_SLOT:
if (data != INVALID_TRACE_RESTRICT_SLOT_ID && !TraceRestrictSlot::IsValidID(data)) return CMD_ERROR;
break;
case OCV_VEH_IN_SLOT:
if (data != INVALID_TRACE_RESTRICT_SLOT_ID && !TraceRestrictSlot::IsValidID(data)) return CMD_ERROR;
if (data != INVALID_TRACE_RESTRICT_SLOT_ID && TraceRestrictSlot::Get(data)->vehicle_type != v->type) return CMD_ERROR;
break;
case OCV_CARGO_ACCEPTANCE:
case OCV_CARGO_WAITING:
if (!(data < NUM_CARGO && CargoSpec::Get(data)->IsValid())) return CMD_ERROR;
@ -1879,7 +1888,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
break;
case MOF_SLOT:
if (data != INVALID_TRACE_RESTRICT_SLOT_ID && !TraceRestrictSlot::IsValidID(data)) return CMD_ERROR;
if (data != INVALID_TRACE_RESTRICT_SLOT_ID) {
const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(data);
if (slot == nullptr || slot->vehicle_type != v->type) return CMD_ERROR;
}
break;
}
@ -1969,7 +1981,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
/* 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
|| 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);
bool old_var_was_slot = (order->GetConditionVariable() == OCV_SLOT_OCCUPANCY || order->GetConditionVariable() == OCV_VEH_IN_SLOT);
bool old_var_was_counter = (order->GetConditionVariable() == OCV_COUNTER_VALUE);
bool old_var_was_time = (order->GetConditionVariable() == OCV_TIME_DATE);
bool old_var_was_tt = (order->GetConditionVariable() == OCV_TIMETABLE);
@ -1983,8 +1995,12 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
break;
case OCV_SLOT_OCCUPANCY:
case OCV_TRAIN_IN_SLOT:
if (!old_var_was_slot) order->GetXDataRef() = INVALID_TRACE_RESTRICT_SLOT_ID;
case OCV_VEH_IN_SLOT:
if (!old_var_was_slot) {
order->GetXDataRef() = INVALID_TRACE_RESTRICT_SLOT_ID;
} else if (order->GetConditionVariable() == OCV_VEH_IN_SLOT && order->GetXData() != INVALID_TRACE_RESTRICT_SLOT_ID && TraceRestrictSlot::Get(order->GetXData())->vehicle_type != v->type) {
order->GetXDataRef() = INVALID_TRACE_RESTRICT_SLOT_ID;
}
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
break;
@ -2043,13 +2059,20 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case MOF_COND_VALUE:
switch (order->GetConditionVariable()) {
case OCV_SLOT_OCCUPANCY:
case OCV_TRAIN_IN_SLOT:
case OCV_CARGO_LOAD_PERCENTAGE:
case OCV_TIME_DATE:
case OCV_TIMETABLE:
order->GetXDataRef() = data;
break;
case OCV_VEH_IN_SLOT:
order->GetXDataRef() = data;
if (data != INVALID_TRACE_RESTRICT_SLOT_ID && TraceRestrictSlot::Get(data)->vehicle_type != v->type) {
if (order->GetConditionComparator() == OCC_EQUALS) order->SetConditionComparator(OCC_IS_TRUE);
if (order->GetConditionComparator() == OCC_NOT_EQUALS) order->SetConditionComparator(OCC_IS_FALSE);
}
break;
case OCV_CARGO_WAITING_AMOUNT:
case OCV_COUNTER_VALUE:
SB(order->GetXDataRef(), 0, 16, data);
@ -2811,7 +2834,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, boo
if (slot != nullptr) skip_order = OrderConditionCompare(occ, slot->occupants.size() >= slot->max_occupancy, value);
break;
}
case OCV_TRAIN_IN_SLOT: {
case OCV_VEH_IN_SLOT: {
TraceRestrictSlot* slot = TraceRestrictSlot::GetIfValid(order->GetXData());
if (slot != nullptr) {
bool occupant = slot->IsOccupant(v->index);

@ -65,7 +65,7 @@ static const StringID _cargo_type_unload_order_drowdown[] = {
};
static const uint32 _cargo_type_unload_order_drowdown_hidden_mask = 0x8; // 01000
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected);
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected, VehicleType vehtype, bool show_other_types);
DropDownList GetCounterDropDownList(Owner owner, TraceRestrictCounterID ctr_id, int &selected);
static bool ModifyOrder(const Vehicle *v, VehicleOrderID order_id, uint32 p2, bool error_msg = true)
@ -655,7 +655,7 @@ static const OrderConditionVariable _order_conditional_variable[] = {
OCV_CARGO_ACCEPTANCE,
OCV_FREE_PLATFORMS,
OCV_SLOT_OCCUPANCY,
OCV_TRAIN_IN_SLOT,
OCV_VEH_IN_SLOT,
OCV_COUNTER_VALUE,
OCV_TIME_DATE,
OCV_TIMETABLE,
@ -723,6 +723,18 @@ static const StringID _order_conditional_condition_is_in_slot[] = {
INVALID_STRING_ID,
};
static const StringID _order_conditional_condition_is_in_slot_non_train[] = {
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_IN_ACQUIRE_SLOT,
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_NOT_IN_ACQUIRE_SLOT,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_IN_SLOT,
STR_ORDER_CONDITIONAL_COMPARATOR_VEHICLE_NOT_IN_SLOT,
INVALID_STRING_ID,
};
extern uint ConvertSpeedToDisplaySpeed(uint speed);
extern uint ConvertDisplaySpeedToSpeed(uint speed);
@ -768,6 +780,12 @@ static const StringID _order_timetable_dropdown[] = {
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;
return STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv;
}
/**
* Draws an order in order or timetable GUI
* @param v Vehicle the order belongs to
@ -935,7 +953,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SetDParam(2, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED);
}
SetDParam(3, order->GetConditionComparator() == OCC_IS_TRUE ? STR_ORDER_CONDITIONAL_COMPARATOR_FULLY_OCCUPIED : STR_ORDER_CONDITIONAL_COMPARATOR_NOT_YET_FULLY_OCCUPIED);
} else if (ocv == OCV_TRAIN_IN_SLOT) {
} else if (ocv == OCV_VEH_IN_SLOT) {
if (TraceRestrictSlot::IsValidID(order->GetXData())) {
SetDParam(0, STR_ORDER_CONDITIONAL_IN_SLOT);
SetDParam(3, order->GetXData());
@ -945,17 +963,13 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
}
switch (order->GetConditionComparator()) {
case OCC_IS_TRUE:
SetDParam(2, STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_IN_SLOT);
break;
case OCC_IS_FALSE:
SetDParam(2, STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_NOT_IN_SLOT);
break;
case OCC_EQUALS:
SetDParam(2, STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_IN_ACQUIRE_SLOT);
break;
case OCC_NOT_EQUALS:
SetDParam(2, STR_ORDER_CONDITIONAL_COMPARATOR_TRAIN_NOT_IN_ACQUIRE_SLOT);
case OCC_NOT_EQUALS: {
const StringID *strs = v->type == VEH_TRAIN ? _order_conditional_condition_is_in_slot : _order_conditional_condition_is_in_slot_non_train;
SetDParam(2, strs[order->GetConditionComparator()]);
break;
}
default:
NOT_REACHED();
}
@ -1003,7 +1017,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
OrderConditionComparator occ = order->GetConditionComparator();
SetDParam(0, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_ORDER_CONDITIONAL_TRUE_FALSE : STR_ORDER_CONDITIONAL_NUM);
SetDParam(2, (ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_CARGO_WAITING || ocv == OCV_FREE_PLATFORMS)
? STR_ORDER_CONDITIONAL_NEXT_STATION : STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv);
? STR_ORDER_CONDITIONAL_NEXT_STATION : OrderStringForVariable(v, ocv));
uint value = order->GetConditionValue();
switch (ocv) {
@ -1324,7 +1338,7 @@ private:
* @param order the order to evaluate
* @return the StringIDs to display
*/
static const StringID *GetComparatorStrings(const Order *order)
static const StringID *GetComparatorStrings(const Vehicle *v, const Order *order)
{
if (order == nullptr) return _order_conditional_condition;
switch (order->GetConditionVariable()) {
@ -1338,8 +1352,8 @@ private:
case OCV_SLOT_OCCUPANCY:
return _order_conditional_condition_is_fully_occupied;
case OCV_TRAIN_IN_SLOT:
return _order_conditional_condition_is_in_slot;
case OCV_VEH_IN_SLOT:
return v->type == VEH_TRAIN ? _order_conditional_condition_is_in_slot : _order_conditional_condition_is_in_slot_non_train;
default:
return _order_conditional_condition;
@ -1647,11 +1661,10 @@ public:
case WID_O_COND_VARIABLE: {
Dimension d = {0, 0};
for (uint i = 0; i < lengthof(_order_conditional_variable); i++) {
if (this->vehicle->type != VEH_TRAIN && (_order_conditional_variable[i] == OCV_TRAIN_IN_SLOT ||
_order_conditional_variable[i] == OCV_SLOT_OCCUPANCY || _order_conditional_variable[i] == OCV_FREE_PLATFORMS)) {
if (this->vehicle->type != VEH_TRAIN && _order_conditional_variable[i] == OCV_FREE_PLATFORMS) {
continue;
}
d = maxdim(d, GetStringBoundingBox(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + _order_conditional_variable[i]));
d = maxdim(d, GetStringBoundingBox(OrderStringForVariable(this->vehicle, _order_conditional_variable[i])));
}
d.width += padding.width;
d.height += padding.height;
@ -1926,7 +1939,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_slot_occupancy = (ocv == OCV_SLOT_OCCUPANCY || ocv == OCV_VEH_IN_SLOT);
bool is_auxiliary_cargo = (ocv == OCV_CARGO_LOAD_PERCENTAGE || ocv == OCV_CARGO_WAITING_AMOUNT);
bool is_counter = (ocv == OCV_COUNTER_VALUE);
bool is_time_date = (ocv == OCV_TIME_DATE);
@ -1977,8 +1990,8 @@ public:
}
/* Set the strings for the dropdown boxes. */
this->GetWidget<NWidgetCore>(WID_O_COND_VARIABLE)->widget_data = STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv;
this->GetWidget<NWidgetCore>(WID_O_COND_COMPARATOR)->widget_data = GetComparatorStrings(order)[order->GetConditionComparator()];
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()];
this->GetWidget<NWidgetCore>(WID_O_COND_VALUE)->widget_data = (ocv == OCV_TIME_DATE && order->GetConditionValue() == TRTDVF_HOUR_MINUTE) ? STR_BLACK_TIME_HHMM : STR_BLACK_COMMA;
this->SetWidgetDisabledState(WID_O_COND_COMPARATOR, ocv == OCV_UNCONDITIONALLY || ocv == OCV_PERCENT);
this->SetWidgetDisabledState(WID_O_COND_VALUE, ocv == OCV_REQUIRES_SERVICE || ocv == OCV_UNCONDITIONALLY);
@ -2366,7 +2379,7 @@ public:
default: NOT_REACHED();
}
ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, sel, WID_O_GOTO,
0, (this->vehicle->type == VEH_TRAIN &&_settings_client.gui.show_adv_tracerestrict_features ? 0 : 0x10), 0, DDSF_LOST_FOCUS);
0, (_settings_client.gui.show_adv_tracerestrict_features ? 0 : 0x10), 0, DDSF_LOST_FOCUS);
}
break;
@ -2409,8 +2422,9 @@ public:
case WID_O_COND_SLOT: {
int selected;
TraceRestrictSlotID value = this->vehicle->GetOrder(this->OrderGetSel())->GetXData();
DropDownList list = GetSlotDropDownList(this->vehicle->owner, value, selected);
const Order *order = this->vehicle->GetOrder(this->OrderGetSel());
TraceRestrictSlotID value = order->GetXData();
DropDownList list = GetSlotDropDownList(this->vehicle->owner, value, selected, this->vehicle->type, order->GetConditionVariable() == OCV_SLOT_OCCUPANCY);
if (!list.empty()) ShowDropDownList(this, std::move(list), selected, WID_O_COND_SLOT, 0, true);
break;
}
@ -2476,17 +2490,16 @@ public:
const OrderConditionVariable ocv = this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable();
DropDownList list;
for (uint i = 0; i < lengthof(_order_conditional_variable); i++) {
if (this->vehicle->type != VEH_TRAIN && (_order_conditional_variable[i] == OCV_TRAIN_IN_SLOT || _order_conditional_variable[i] == OCV_SLOT_OCCUPANCY ||
_order_conditional_variable[i] == OCV_FREE_PLATFORMS)) {
if (this->vehicle->type != VEH_TRAIN && _order_conditional_variable[i] == OCV_FREE_PLATFORMS) {
continue;
}
if (ocv != _order_conditional_variable[i]) {
if ((_order_conditional_variable[i] == OCV_TRAIN_IN_SLOT || _order_conditional_variable[i] == OCV_SLOT_OCCUPANCY ||
if ((_order_conditional_variable[i] == OCV_VEH_IN_SLOT || _order_conditional_variable[i] == OCV_SLOT_OCCUPANCY ||
_order_conditional_variable[i] == OCV_COUNTER_VALUE) && !_settings_client.gui.show_adv_tracerestrict_features) {
continue;
}
}
list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + _order_conditional_variable[i], _order_conditional_variable[i], false));
list.emplace_back(new DropDownListStringItem(OrderStringForVariable(this->vehicle, _order_conditional_variable[i]), _order_conditional_variable[i], false));
}
ShowDropDownList(this, std::move(list), ocv, WID_O_COND_VARIABLE);
break;
@ -2503,7 +2516,7 @@ public:
mask = 0x3F;
break;
case OCV_TRAIN_IN_SLOT:
case OCV_VEH_IN_SLOT:
mask = 0x3C;
break;
@ -2515,7 +2528,7 @@ public:
mask = 0xC0;
break;
}
ShowDropDownMenu(this, GetComparatorStrings(o), o->GetConditionComparator(), WID_O_COND_COMPARATOR, 0, mask, 0, DDSF_LOST_FOCUS);
ShowDropDownMenu(this, GetComparatorStrings(this->vehicle, o), o->GetConditionComparator(), WID_O_COND_COMPARATOR, 0, mask, 0, DDSF_LOST_FOCUS);
break;
}
@ -2569,7 +2582,7 @@ public:
case WID_O_RELEASE_SLOT: {
int selected;
TraceRestrictSlotID value = this->vehicle->GetOrder(this->OrderGetSel())->GetDestination();
DropDownList list = GetSlotDropDownList(this->vehicle->owner, value, selected);
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, true);
break;
}

@ -151,8 +151,8 @@ enum OrderConditionVariable {
OCV_CARGO_ACCEPTANCE, ///< Skip if specified cargo is accepted at next station
OCV_FREE_PLATFORMS, ///< Skip based on free platforms at next station
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_SLOT_OCCUPANCY, ///< Test if vehicle slot is fully occupied
OCV_VEH_IN_SLOT, ///< Test if vehicle 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_COUNTER_VALUE, ///< Skip based on counter value

@ -28,7 +28,7 @@
#include "table/sprites.h"
#include "table/strings.h"
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected);
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected, VehicleType vehtype, bool show_other_types);
DropDownList GetCounterDropDownList(Owner owner, TraceRestrictCounterID ctr_id, int &selected);
enum ProgramWindowWidgets {
@ -367,7 +367,7 @@ public:
SignalSlotCondition *sc = static_cast<SignalSlotCondition*>(sif->condition);
int selected;
DropDownList list = GetSlotDropDownList(this->GetOwner(), sc->slot_id, selected);
DropDownList list = GetSlotDropDownList(this->GetOwner(), sc->slot_id, selected, VEH_TRAIN, true);
if (!list.empty()) ShowDropDownList(this, std::move(list), selected, PROGRAM_WIDGET_COND_SLOT, 0, true);
} break;

@ -4015,6 +4015,22 @@ bool AfterLoadGame()
}
}
if (SlXvIsFeaturePresent(XSLFI_TRACE_RESTRICT, 7, 12)) {
/* Move vehicle in slot flag */
for (Vehicle *v : Vehicle::Iterate()) {
if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, 2)) { /* was VRF_HAVE_SLOT */
SetBit(v->vehicle_flags, VF_HAVE_SLOT);
ClrBit(Train::From(v)->flags, 2);
} else {
ClrBit(v->vehicle_flags, VF_HAVE_SLOT);
}
}
} else if (SlXvIsFeatureMissing(XSLFI_TRACE_RESTRICT)) {
for (Vehicle *v : Vehicle::Iterate()) {
ClrBit(v->vehicle_flags, VF_HAVE_SLOT);
}
}
InitializeRoadGUI();
/* This needs to be done after conversion. */

@ -69,9 +69,9 @@ static uint32 saveLC(const SlxiSubChunkInfo *info, bool dry_run);
const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_VERSION_LABEL, XSCF_IGNORABLE_ALL, 1, 1, "version_label", saveVL, loadVL, nullptr },
{ XSLFI_TRACE_RESTRICT, XSCF_NULL, 12, 12, "tracerestrict", nullptr, nullptr, "TRRM,TRRP,TRRS" },
{ XSLFI_TRACE_RESTRICT, XSCF_NULL, 13, 13, "tracerestrict", nullptr, nullptr, "TRRM,TRRP,TRRS" },
{ XSLFI_TRACE_RESTRICT_OWNER, XSCF_NULL, 1, 1, "tracerestrict_owner", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_ORDRCND, XSCF_NULL, 3, 3, "tracerestrict_order_cond", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_ORDRCND, XSCF_NULL, 4, 4, "tracerestrict_order_cond", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_STATUSCND,XSCF_NULL, 1, 1, "tracerestrict_status_cond", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_REVERSE, XSCF_NULL, 1, 1, "tracerestrict_reverse", nullptr, nullptr, nullptr },
{ XSLFI_TRACE_RESTRICT_NEWSCTRL,XSCF_NULL, 1, 1, "tracerestrict_newsctrl", nullptr, nullptr, nullptr },
@ -114,6 +114,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 2, 2, "multiple_docks", nullptr, nullptr, nullptr },
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 7, 7, "timetable_extra", nullptr, nullptr, "ORDX" },
{ XSLFI_TRAIN_FLAGS_EXTRA, XSCF_NULL, 1, 1, "train_flags_extra", nullptr, nullptr, nullptr },
{ XSLFI_VEHICLE_FLAGS_EXTRA, XSCF_NULL, 1, 1, "veh_flags_extra", nullptr, nullptr, nullptr },
{ XSLFI_TRAIN_THROUGH_LOAD, XSCF_NULL, 2, 2, "train_through_load", nullptr, nullptr, nullptr },
{ XSLFI_ORDER_EXTRA_DATA, XSCF_NULL, 1, 1, "order_extra_data", nullptr, nullptr, nullptr },
{ XSLFI_WHOLE_MAP_CHUNK, XSCF_NULL, 2, 2, "whole_map_chunk", nullptr, nullptr, "WMAP" },

@ -68,6 +68,7 @@ enum SlXvFeatureIndex {
XSLFI_MULTIPLE_DOCKS, ///< Multiple docks
XSLFI_TIMETABLE_EXTRA, ///< Vehicle timetable extra fields
XSLFI_TRAIN_FLAGS_EXTRA, ///< Train flags field extra size
XSLFI_VEHICLE_FLAGS_EXTRA, ///< Vehicle flags field extra size
XSLFI_TRAIN_THROUGH_LOAD, ///< Train through load/unload
XSLFI_ORDER_EXTRA_DATA, ///< Order extra data field(s)
XSLFI_WHOLE_MAP_CHUNK, ///< Whole map chunk

@ -349,8 +349,9 @@ SaveLoadTable GetOrderBackupDescription()
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR_X(OrderBackup,timetable_start_subticks, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 2)),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_176, SLV_180),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_176, SLV_180),
SLE_CONDVAR_X(OrderBackup, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 0, 0)),
SLE_CONDVAR_X(OrderBackup, vehicle_flags, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 1)),
SLE_REF(OrderBackup, orders, REF_ORDER),
SLE_CONDNULL_X(18, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SCHEDULED_DISPATCH, 2, 2)),
};

@ -124,6 +124,7 @@ static const SaveLoad _trace_restrict_slot_desc[] = {
SLE_VAR(TraceRestrictSlot, max_occupancy, SLE_UINT32),
SLE_SSTR(TraceRestrictSlot, name, SLF_ALLOW_CONTROL),
SLE_VAR(TraceRestrictSlot, owner, SLE_UINT8),
SLE_CONDVAR_X(TraceRestrictSlot, vehicle_type, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TRACE_RESTRICT, 13)),
};
/**

@ -209,8 +209,8 @@ SaveLoadTable GetOrderBackupDescription()
SLE_CONDVAR(OrderBackup, current_order_time, SLE_UINT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_176, SLV_180),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_176, SLV_180),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION),
SLE_REF(OrderBackup, orders, REF_ORDER),
};

@ -152,8 +152,8 @@ public:
SLE_VAR(Vehicle, load_unload_ticks, SLE_UINT16),
SLEG_CONDVAR("cargo_paid_for", _cargo_paid_for, SLE_UINT16, SLV_45, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_40, SLV_180),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_40, SLV_180),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, profit_this_year, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
SLE_CONDVAR(Vehicle, profit_this_year, SLE_INT64, SLV_65, SL_MAX_VERSION),

@ -738,8 +738,9 @@ SaveLoadTable GetVehicleDescription(VehicleType vt)
SLE_VAR(Vehicle, load_unload_ticks, SLE_UINT16),
SLEG_CONDVAR( _cargo_paid_for, SLE_UINT16, SLV_45, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_40, SLV_180),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_40, SLV_180),
SLE_CONDVAR_X(Vehicle, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 0, 0)),
SLE_CONDVAR_X(Vehicle, vehicle_flags, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 1)),
SLE_CONDVAR(Vehicle, profit_this_year, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
SLE_CONDVAR(Vehicle, profit_this_year, SLE_INT64, SLV_65, SL_MAX_VERSION),

@ -2031,7 +2031,7 @@ struct MainToolbarWindow : Window {
EventState OnHotkey(int hotkey) override
{
extern void ShowTemplateReplaceWindow();
extern void ShowTraceRestrictSlotWindow(CompanyID company);
extern void ShowTraceRestrictSlotWindow(CompanyID company, VehicleType vehtype);
extern void ShowTraceRestrictCounterWindow(CompanyID company);
CallBackFunction cbf = CBF_NONE;
@ -2081,7 +2081,7 @@ struct MainToolbarWindow : Window {
case MTHK_LINK_GRAPH_LEGEND: ShowLinkGraphLegend(); break;
case MTHK_MESSAGE_HISTORY: ShowMessageHistory(); break;
case MTHK_TEMPLATE_REPLACEMENT: ShowTemplateReplaceWindow(); break;
case MTHK_TRAIN_SLOTS: ShowTraceRestrictSlotWindow(_local_company); break;
case MTHK_TRAIN_SLOTS: ShowTraceRestrictSlotWindow(_local_company, VEH_TRAIN); break;
case MTHK_TRAIN_COUNTERS: ShowTraceRestrictCounterWindow(_local_company); break;
default: return ES_NOT_HANDLED;
}

@ -643,7 +643,7 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
case TRIT_SLOT: {
if (!input.permitted_slot_operations) break;
TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(GetTraceRestrictValue(item));
if (slot == nullptr) break;
if (slot == nullptr || slot->vehicle_type != v->type) break;
switch (static_cast<TraceRestrictSlotCondOpField>(GetTraceRestrictCondOp(item))) {
case TRSCOF_ACQUIRE_WAIT:
if (input.permitted_slot_operations & TRPISP_ACQUIRE) {
@ -1113,6 +1113,12 @@ void SetTraceRestrictTypeAndNormalise(TraceRestrictItem &item, TraceRestrictItem
SetTraceRestrictCondOp(item, TRCO_IS);
SetTraceRestrictValueDefault(item, new_properties.value_type);
}
if (new_properties.value_type == TRVT_SLOT_INDEX || new_properties.value_type == TRVT_SLOT_INDEX_INT) {
if (!IsTraceRestrictTypeNonMatchingVehicleTypeSlot(GetTraceRestrictType(item))) {
const TraceRestrictSlot *slot = TraceRestrictSlot::GetIfValid(GetTraceRestrictValue(item));
if (slot != nullptr && slot->vehicle_type != VEH_TRAIN) SetTraceRestrictValue(item, INVALID_TRACE_RESTRICT_SLOT_ID);
}
}
if (GetTraceRestrictType(item) == TRIT_COND_LAST_STATION && GetTraceRestrictAuxField(item) != TROCAF_STATION) {
// if changing type from another order type to last visited station, reset value if not currently a station
SetTraceRestrictValueDefault(item, TRVT_ORDER);
@ -1893,7 +1899,7 @@ bool TraceRestrictSlot::Occupy(VehicleID id, bool force)
if (this->occupants.size() >= this->max_occupancy && !force) return false;
this->occupants.push_back(id);
slot_vehicle_index.emplace(id, this->index);
SetBit(Train::Get(id)->flags, VRF_HAVE_SLOT);
SetBit(Vehicle::Get(id)->vehicle_flags, VF_HAVE_SLOT);
SetWindowDirty(WC_VEHICLE_DETAILS, id);
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
this->UpdateSignals();
@ -1951,7 +1957,7 @@ void TraceRestrictSlot::DeIndex(VehicleID id)
if (is_first_in_range && next == range.second) {
/* Only one item, which we've just erased, clear the vehicle flag */
ClrBit(Train::Get(id)->flags, VRF_HAVE_SLOT);
ClrBit(Vehicle::Get(id)->vehicle_flags, VF_HAVE_SLOT);
}
break;
}
@ -1991,10 +1997,11 @@ void TraceRestrictSlot::ValidateSlotOccupants(std::function<void(const char *)>
for (const TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
for (VehicleID id : slot->occupants) {
const Train *t = Train::GetIfValid(id);
if (t) {
if (!t->IsFrontEngine()) CCLOG("Slot %u (%s) has non-front engine train: %s", slot->index, slot->name.c_str(), scope_dumper().VehicleInfo(t));
if (!HasBit(t->flags, VRF_HAVE_SLOT)) CCLOG("Slot %u (%s) has train without VRF_HAVE_SLOT: %s", slot->index, slot->name.c_str(), scope_dumper().VehicleInfo(t));
const Vehicle *v = Vehicle::GetIfValid(id);
if (v) {
if (v->type != slot->vehicle_type) CCLOG("Slot %u (%s) has wrong vehicle type (%u, %u): %s", slot->index, slot->name.c_str(), v->type, slot->vehicle_type, scope_dumper().VehicleInfo(v));
if (!v->IsPrimaryVehicle()) CCLOG("Slot %u (%s) has non-primary vehicle: %s", slot->index, slot->name.c_str(), scope_dumper().VehicleInfo(v));
if (!HasBit(v->vehicle_flags, VF_HAVE_SLOT)) CCLOG("Slot %u (%s) has vehicle without VF_HAVE_SLOT: %s", slot->index, slot->name.c_str(), scope_dumper().VehicleInfo(v));
} else {
CCLOG("Slot %u (%s) has non-existent vehicle ID: %u", slot->index, slot->name.c_str(), id);
}
@ -2080,7 +2087,7 @@ void TraceRestrictRemoveSlotID(TraceRestrictSlotID index)
bool changed_order = false;
for (Order *o : Order::Iterate()) {
if (o->IsType(OT_CONDITIONAL) &&
(o->GetConditionVariable() == OCV_SLOT_OCCUPANCY || o->GetConditionVariable() == OCV_TRAIN_IN_SLOT) &&
(o->GetConditionVariable() == OCV_SLOT_OCCUPANCY || o->GetConditionVariable() == OCV_VEH_IN_SLOT) &&
o->GetXData() == index) {
o->GetXDataRef() = INVALID_TRACE_RESTRICT_SLOT_ID;
changed_order = true;
@ -2118,7 +2125,8 @@ static bool IsUniqueSlotName(const char *name)
* Create a new slot.
* @param tile unused
* @param flags type of operation
* @param p1 unused
* @param p1 bitstuffed elements
* - p2 = (bit 0 - 2) - vehicle type
* @param p2 unused
* @param text new slot name
* @return the cost of this operation or an error
@ -2128,13 +2136,16 @@ CommandCost CmdCreateTraceRestrictSlot(TileIndex tile, DoCommandFlag flags, uint
if (!TraceRestrictSlot::CanAllocateItem()) return CMD_ERROR;
if (StrEmpty(text)) return CMD_ERROR;
VehicleType vehtype = Extract<VehicleType, 0, 3>(p1);
if (vehtype >= VEH_COMPANY_END) return CMD_ERROR;
size_t length = Utf8StringLength(text);
if (length <= 0) return CMD_ERROR;
if (length >= MAX_LENGTH_TRACE_RESTRICT_SLOT_NAME_CHARS) return CMD_ERROR;
if (!IsUniqueSlotName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
if (flags & DC_EXEC) {
TraceRestrictSlot *slot = new TraceRestrictSlot(_current_company);
TraceRestrictSlot *slot = new TraceRestrictSlot(_current_company, vehtype);
slot->name = text;
// update windows
@ -2241,6 +2252,7 @@ CommandCost CmdAddVehicleTraceRestrictSlot(TileIndex tile, DoCommandFlag flags,
Vehicle *v = Vehicle::GetIfValid(p2);
if (slot == nullptr || slot->owner != _current_company) return CMD_ERROR;
if (v == nullptr || v->owner != _current_company) return CMD_ERROR;
if (v->type != slot->vehicle_type || !v->IsPrimaryVehicle()) return CMD_ERROR;
if (flags & DC_EXEC) {
slot->Occupy(v->index, true);

@ -851,6 +851,18 @@ static inline bool IsTraceRestrictTypeAuxSubtype(TraceRestrictItemType type)
}
}
/** May this TraceRestrictItemType take a slot of a different (non-train) vehicle type */
static inline bool IsTraceRestrictTypeNonMatchingVehicleTypeSlot(TraceRestrictItemType type)
{
switch (type) {
case TRIT_COND_SLOT_OCCUPANCY:
return true;
default:
return false;
}
}
/** Get mapping ref ID from tile and track */
static inline TraceRestrictRefId MakeTraceRestrictRefId(TileIndex t, Track track)
{
@ -963,6 +975,7 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p
uint32 max_occupancy = 1;
std::string name;
Owner owner;
VehicleType vehicle_type;
std::vector<SignalReference> progsig_dependants;
@ -971,9 +984,10 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p
static void ValidateSlotOccupants(std::function<void(const char *)> log);
static void PreCleanPool();
TraceRestrictSlot(CompanyID owner = INVALID_COMPANY)
TraceRestrictSlot(CompanyID owner = INVALID_COMPANY, VehicleType type = VEH_TRAIN)
{
this->owner = owner;
this->vehicle_type = type;
}
~TraceRestrictSlot()

@ -621,15 +621,27 @@ static bool SlotNameSorter(const TraceRestrictSlot * const &a, const TraceRestri
return r < 0;
}
static VehicleType _slot_sort_veh_type;
/** Sort slots by their type then name */
static bool SlotVehTypeNameSorter(const TraceRestrictSlot * const &a, const TraceRestrictSlot * const &b)
{
if (a->vehicle_type == b->vehicle_type) return SlotNameSorter(a, b);
if (a->vehicle_type == _slot_sort_veh_type) return true;
if (b->vehicle_type == _slot_sort_veh_type) return false;
return a->vehicle_type < b->vehicle_type;
}
/**
* Get a DropDownList of the group list
*/
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected)
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected, VehicleType vehtype, bool show_other_types)
{
GUIList<const TraceRestrictSlot*> list;
DropDownList dlist;
for (const TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
if (!show_other_types && slot->vehicle_type != vehtype) continue;
if (slot->owner == owner) {
list.push_back(slot);
}
@ -638,16 +650,24 @@ DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &
if (list.size() == 0) return dlist;
list.ForceResort();
list.Sort(&SlotNameSorter);
_slot_sort_veh_type = vehtype;
list.Sort(show_other_types ? &SlotVehTypeNameSorter : &SlotNameSorter);
selected = -1;
for (size_t i = 0; i < list.size(); ++i) {
const TraceRestrictSlot *s = list[i];
if (slot_id == s->index) selected = slot_id;
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_TRACE_RESTRICT_SLOT_NAME, s->index, false);
item->SetParam(0, s->index);
dlist.emplace_back(item);
if (s->vehicle_type == vehtype) {
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_TRACE_RESTRICT_SLOT_NAME, s->index, false);
item->SetParam(0, s->index);
dlist.emplace_back(item);
} else {
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_TRACE_RESTRICT_SLOT_NAME_PREFIXED, s->index, false);
item->SetParam(0, STR_REPLACE_VEHICLE_TRAIN + s->vehicle_type);
item->SetParam(1, s->index);
dlist.emplace_back(item);
}
}
return dlist;
@ -1829,7 +1849,7 @@ public:
case TRVT_SLOT_INDEX: {
int selected;
DropDownList dlist = GetSlotDropDownList(this->GetOwner(), GetTraceRestrictValue(item), selected);
DropDownList dlist = GetSlotDropDownList(this->GetOwner(), GetTraceRestrictValue(item), selected, VEH_TRAIN, IsTraceRestrictTypeNonMatchingVehicleTypeSlot(GetTraceRestrictType(item)));
if (!dlist.empty()) ShowDropDownList(this, std::move(dlist), selected, TR_WIDGET_VALUE_DROPDOWN);
break;
}
@ -1865,7 +1885,7 @@ public:
switch (GetTraceRestrictTypeProperties(item).value_type) {
case TRVT_SLOT_INDEX_INT: {
int selected;
DropDownList dlist = GetSlotDropDownList(this->GetOwner(), GetTraceRestrictValue(item), selected);
DropDownList dlist = GetSlotDropDownList(this->GetOwner(), GetTraceRestrictValue(item), selected, VEH_TRAIN, IsTraceRestrictTypeNonMatchingVehicleTypeSlot(GetTraceRestrictType(item)));
if (!dlist.empty()) ShowDropDownList(this, std::move(dlist), selected, TR_WIDGET_LEFT_AUX_DROPDOWN);
break;
}
@ -2821,6 +2841,7 @@ private:
}
for (const TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
if (slot->vehicle_type != VEH_TRAIN && !IsTraceRestrictTypeNonMatchingVehicleTypeSlot(GetTraceRestrictType(item))) continue;
if (slot->owner == this->GetOwner()) {
this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN);
break;
@ -2847,6 +2868,7 @@ private:
this->EnableWidget(TR_WIDGET_VALUE_INT);
for (const TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
if (slot->vehicle_type != VEH_TRAIN && !IsTraceRestrictTypeNonMatchingVehicleTypeSlot(GetTraceRestrictType(item))) continue;
if (slot->owner == this->GetOwner()) {
this->EnableWidget(TR_WIDGET_LEFT_AUX_DROPDOWN);
break;
@ -3276,7 +3298,7 @@ private:
this->slots.clear();
for (const TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
if (slot->owner == owner) {
if (slot->owner == owner && slot->vehicle_type == this->vli.vtype) {
this->slots.push_back(slot);
}
}
@ -3393,6 +3415,10 @@ public:
this->slots.NeedResort();
this->BuildSlotList(vli.company);
this->GetWidget<NWidgetCore>(WID_TRSL_CREATE_SLOT)->widget_data += this->vli.vtype;
this->GetWidget<NWidgetCore>(WID_TRSL_DELETE_SLOT)->widget_data += this->vli.vtype;
this->GetWidget<NWidgetCore>(WID_TRSL_RENAME_SLOT)->widget_data += this->vli.vtype;
this->FinishInitNested(window_number);
this->owner = vli.company;
}
@ -3482,6 +3508,10 @@ public:
case WID_TRSL_FILTER_BY_CARGO:
SetDParam(0, this->cargo_filter_texts[this->cargo_filter_criteria]);
break;
case WID_TRSL_CAPTION:
SetDParam(0, STR_VEHICLE_TYPE_TRAINS + this->vli.vtype);
break;
}
}
@ -3699,7 +3729,7 @@ public:
if (this->slot_set_max_occupancy) {
if (!StrEmpty(str)) DoCommandP(0, this->slot_rename | (1 << 16), atoi(str), CMD_ALTER_TRACERESTRICT_SLOT | CMD_MSG(STR_TRACE_RESTRICT_ERROR_SLOT_CAN_T_SET_MAX_OCCUPANCY));
} else if (this->slot_rename == NEW_TRACE_RESTRICT_SLOT_ID) {
DoCommandP(0, 0, 0, CMD_CREATE_TRACERESTRICT_SLOT | CMD_MSG(STR_TRACE_RESTRICT_ERROR_SLOT_CAN_T_CREATE), nullptr, str);
DoCommandP(0, this->vli.vtype, 0, CMD_CREATE_TRACERESTRICT_SLOT | CMD_MSG(STR_TRACE_RESTRICT_ERROR_SLOT_CAN_T_CREATE), nullptr, str);
} else {
DoCommandP(0, this->slot_rename, 0, CMD_ALTER_TRACERESTRICT_SLOT | CMD_MSG(STR_TRACE_RESTRICT_ERROR_SLOT_CAN_T_RENAME), nullptr, str);
}
@ -3822,11 +3852,11 @@ static WindowDesc _slot_window_desc(
* Show the trace restrict slot window for the given company.
* @param company The company to show the window for.
*/
void ShowTraceRestrictSlotWindow(CompanyID company)
void ShowTraceRestrictSlotWindow(CompanyID company, VehicleType vehtype)
{
if (!Company::IsValidID(company)) return;
WindowNumber num = VehicleListIdentifier(VL_SLOT_LIST, VEH_TRAIN, company).Pack();
WindowNumber num = VehicleListIdentifier(VL_SLOT_LIST, vehtype, company).Pack();
AllocateWindowDescFront<TraceRestrictSlotWindow>(&_slot_window_desc, num);
}

@ -26,7 +26,7 @@ struct Train;
enum VehicleRailFlags {
VRF_REVERSING = 0,
VRF_WAITING_RESTRICTION = 1, ///< Train is waiting due to a routing restriction, only valid when VRF_TRAIN_STUCK is also set.
VRF_HAVE_SLOT = 2, ///< Train has 1 or more slots
/* gap, was VRF_HAVE_SLOT */
VRF_POWEREDWAGON = 3, ///< Wagon is powered.
VRF_REVERSE_DIRECTION = 4, ///< Reverse the visible direction of the vehicle.
VRF_HAS_HIT_RV = 5, ///< Train has hit road vehicle

@ -2148,9 +2148,9 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
DeleteVehicleOrders(src);
RemoveVehicleFromGroup(src);
src->unitnumber = 0;
if (HasBit(src->flags, VRF_HAVE_SLOT)) {
if (HasBit(src->vehicle_flags, VF_HAVE_SLOT)) {
TraceRestrictRemoveVehicleFromAllSlots(src->index);
ClrBit(src->flags, VRF_HAVE_SLOT);
ClrBit(src->vehicle_flags, VF_HAVE_SLOT);
}
OrderBackup::ClearVehicle(src);
}

@ -1137,9 +1137,9 @@ void Vehicle::PreDestructor()
}
}
if (this->type == VEH_TRAIN && HasBit(Train::From(this)->flags, VRF_HAVE_SLOT)) {
if (HasBit(this->vehicle_flags, VF_HAVE_SLOT)) {
TraceRestrictRemoveVehicleFromAllSlots(this->index);
ClrBit(Train::From(this)->flags, VRF_HAVE_SLOT);
ClrBit(this->vehicle_flags, VF_HAVE_SLOT);
}
if (this->type == VEH_TRAIN && HasBit(Train::From(this)->flags, VRF_PENDING_SPEED_RESTRICTION)) {
pending_speed_restriction_change_map.erase(this->index);
@ -4122,6 +4122,7 @@ void DumpVehicleFlagsGeneric(const Vehicle *v, T dump, U dump_header)
dump('x', "VF_LAST_LOAD_ST_SEP", HasBit(v->vehicle_flags, VF_LAST_LOAD_ST_SEP));
dump('s', "VF_TIMETABLE_SEPARATION", HasBit(v->vehicle_flags, VF_TIMETABLE_SEPARATION));
dump('a', "VF_AUTOMATE_TIMETABLE", HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE));
dump('Q', "VF_HAVE_SLOT", HasBit(v->vehicle_flags, VF_HAVE_SLOT));
dump_header("vcf:", "cached_veh_flags:");
dump('l', "VCF_LAST_VISUAL_EFFECT", HasBit(v->vcache.cached_veh_flags, VCF_LAST_VISUAL_EFFECT));
dump('z', "VCF_GV_ZERO_SLOPE_RESIST", HasBit(v->vcache.cached_veh_flags, VCF_GV_ZERO_SLOPE_RESIST));
@ -4144,7 +4145,6 @@ void DumpVehicleFlagsGeneric(const Vehicle *v, T dump, U dump_header)
dump_header("tf:", "train flags:");
dump('R', "VRF_REVERSING", HasBit(t->flags, VRF_REVERSING));
dump('W', "VRF_WAITING_RESTRICTION", HasBit(t->flags, VRF_WAITING_RESTRICTION));
dump('S', "VRF_HAVE_SLOT", HasBit(t->flags, VRF_HAVE_SLOT));
dump('P', "VRF_POWEREDWAGON", HasBit(t->flags, VRF_POWEREDWAGON));
dump('r', "VRF_REVERSE_DIRECTION", HasBit(t->flags, VRF_REVERSE_DIRECTION));
dump('h', "VRF_HAS_HIT_RV", HasBit(t->flags, VRF_HAS_HIT_RV));

@ -46,25 +46,23 @@ enum VehStatus {
/** Bit numbers in #Vehicle::vehicle_flags. */
enum VehicleFlags {
VF_LOADING_FINISHED, ///< Vehicle has finished loading.
VF_CARGO_UNLOADING, ///< Vehicle is unloading cargo.
VF_BUILT_AS_PROTOTYPE, ///< Vehicle is a prototype (accepted as exclusive preview).
VF_TIMETABLE_STARTED, ///< Whether the vehicle has started running on the timetable yet.
VF_AUTOFILL_TIMETABLE, ///< Whether the vehicle should fill in the timetable automatically.
VF_AUTOFILL_PRES_WAIT_TIME, ///< Whether non-destructive auto-fill should preserve waiting times
VF_STOP_LOADING, ///< Don't load anymore during the next load cycle.
VF_PATHFINDER_LOST, ///< Vehicle's pathfinder is lost.
VF_SERVINT_IS_CUSTOM, ///< Service interval is custom.
VF_SERVINT_IS_PERCENT, ///< Service interval is percent.
// Additional flags not in trunk are added at the end to avoid clashing with any new
// flags which get added in future trunk, and to avoid re-ordering flags which are in trunk already,
// as this breaks savegame compatibility.
VF_SEPARATION_ACTIVE = 11, ///< Whether timetable auto-separation is currently active
VF_SCHEDULED_DISPATCH = 12, ///< Whether the vehicle should follow a timetabled dispatching schedule
VF_LAST_LOAD_ST_SEP = 13, ///< Each vehicle of this chain has its last_loading_station field set separately
VF_TIMETABLE_SEPARATION = 14,///< Whether timetable auto-separation is enabled
VF_AUTOMATE_TIMETABLE = 15, ///< Whether the vehicle should manage the timetable automatically.
VF_LOADING_FINISHED = 0, ///< Vehicle has finished loading.
VF_CARGO_UNLOADING = 1, ///< Vehicle is unloading cargo.
VF_BUILT_AS_PROTOTYPE = 2, ///< Vehicle is a prototype (accepted as exclusive preview).
VF_TIMETABLE_STARTED = 3, ///< Whether the vehicle has started running on the timetable yet.
VF_AUTOFILL_TIMETABLE = 4, ///< Whether the vehicle should fill in the timetable automatically.
VF_AUTOFILL_PRES_WAIT_TIME = 5, ///< Whether non-destructive auto-fill should preserve waiting times
VF_STOP_LOADING = 6, ///< Don't load anymore during the next load cycle.
VF_PATHFINDER_LOST = 7, ///< Vehicle's pathfinder is lost.
VF_SERVINT_IS_CUSTOM = 8, ///< Service interval is custom.
VF_SERVINT_IS_PERCENT = 9, ///< Service interval is percent.
/* gap, above are common with upstream */
VF_SEPARATION_ACTIVE = 11, ///< Whether timetable auto-separation is currently active
VF_SCHEDULED_DISPATCH = 12, ///< Whether the vehicle should follow a timetabled dispatching schedule
VF_LAST_LOAD_ST_SEP = 13, ///< Each vehicle of this chain has its last_loading_station field set separately
VF_TIMETABLE_SEPARATION = 14, ///< Whether timetable auto-separation is enabled
VF_AUTOMATE_TIMETABLE = 15, ///< Whether the vehicle should manage the timetable automatically.
VF_HAVE_SLOT = 16, ///< Vehicle has 1 or more slots
};
/** Bit numbers used to indicate which of the #NewGRFCache values are valid. */

@ -463,10 +463,8 @@ DropDownList BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplac
list.emplace_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, disable));
list.emplace_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, disable));
}
if (this->vli.vtype == VEH_TRAIN && _settings_client.gui.show_adv_tracerestrict_features) {
list.emplace_back(new DropDownListStringItem(STR_TRACE_RESTRICT_SLOT_MANAGE, ADI_TRACERESTRICT_SLOT_MGMT, false));
}
if (_settings_client.gui.show_adv_tracerestrict_features) {
list.emplace_back(new DropDownListStringItem(STR_TRACE_RESTRICT_SLOT_MANAGE, ADI_TRACERESTRICT_SLOT_MGMT, false));
list.emplace_back(new DropDownListStringItem(STR_TRACE_RESTRICT_COUNTER_MANAGE, ADI_TRACERESTRICT_COUNTER_MGMT, false));
}
if (change_order_str != 0) {
@ -2431,8 +2429,8 @@ public:
break;
case ADI_TRACERESTRICT_SLOT_MGMT: {
extern void ShowTraceRestrictSlotWindow(CompanyID company);
ShowTraceRestrictSlotWindow(this->owner);
extern void ShowTraceRestrictSlotWindow(CompanyID company, VehicleType vehtype);
ShowTraceRestrictSlotWindow(this->owner, this->vli.vtype);
break;
}
@ -2822,8 +2820,7 @@ struct VehicleDetailsWindow : Window {
bool ShouldShowSlotsLine(const Vehicle *v) const
{
if (v->type != VEH_TRAIN) return false;
return HasBit(Train::From(v)->flags, VRF_HAVE_SLOT);
return HasBit(v->vehicle_flags, VF_HAVE_SLOT);
}
bool ShouldShowSpeedRestrictionLine(const Vehicle *v) const

Loading…
Cancel
Save