From 904ff6757de3f6fec1d3f3716a1c105f92d04017 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 18 Jan 2022 18:51:24 +0000 Subject: [PATCH] Add slot support to road vehicles, ships and aircraft --- src/autoreplace_cmd.cpp | 13 ++--- src/base_consist.h | 2 +- src/group_gui.cpp | 4 +- src/lang/czech.txt | 2 +- src/lang/english.txt | 9 +++- src/lang/galician.txt | 2 +- src/lang/german.txt | 2 +- src/lang/korean.txt | 2 +- src/order_cmd.cpp | 57 ++++++++++++++------- src/order_gui.cpp | 75 ++++++++++++++++------------ src/order_type.h | 4 +- src/programmable_signals_gui.cpp | 4 +- src/saveload/afterload.cpp | 16 ++++++ src/saveload/extended_ver_sl.cpp | 5 +- src/saveload/extended_ver_sl.h | 1 + src/saveload/order_sl.cpp | 5 +- src/saveload/tracerestrict_sl.cpp | 1 + src/saveload/upstream/order_sl.cpp | 4 +- src/saveload/upstream/vehicle_sl.cpp | 4 +- src/saveload/vehicle_sl.cpp | 5 +- src/toolbar_gui.cpp | 4 +- src/tracerestrict.cpp | 32 ++++++++---- src/tracerestrict.h | 16 +++++- src/tracerestrict_gui.cpp | 52 +++++++++++++++---- src/train.h | 2 +- src/train_cmd.cpp | 4 +- src/vehicle.cpp | 6 +-- src/vehicle_base.h | 36 +++++++------ src/vehicle_gui.cpp | 11 ++-- 29 files changed, 248 insertions(+), 132 deletions(-) diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 7a28c9c7fe..b2bc2d8d33 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -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); } } diff --git a/src/base_consist.h b/src/base_consist.h index ebb5d594d7..e4fbb79544 100644 --- a/src/base_consist.h +++ b/src/base_consist.h @@ -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() {} diff --git a/src/group_gui.cpp b/src/group_gui.cpp index b255f338c6..41351f6a0c 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -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; } diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 846276dae8..504de34f25 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -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 diff --git a/src/lang/english.txt b/src/lang/english.txt index 9e5aa7c696..3615139f37 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -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 diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 1e657a7590..202050b099 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -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 diff --git a/src/lang/german.txt b/src/lang/german.txt index d04701ec13..022d2f6cc8 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -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 diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 0cd4962cb2..d89338b7d8 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -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}슬롯 이름 바꾸기 diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 8f5c60abf8..68731a5f8a 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -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); diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 05cd7d771c..ff4d02b82a 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -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(WID_O_COND_VARIABLE)->widget_data = STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv; - this->GetWidget(WID_O_COND_COMPARATOR)->widget_data = GetComparatorStrings(order)[order->GetConditionComparator()]; + this->GetWidget(WID_O_COND_VARIABLE)->widget_data = OrderStringForVariable(this->vehicle, ocv); + this->GetWidget(WID_O_COND_COMPARATOR)->widget_data = GetComparatorStrings(this->vehicle, order)[order->GetConditionComparator()]; this->GetWidget(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; } diff --git a/src/order_type.h b/src/order_type.h index 399d6ab641..56ebf6cfb9 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -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 diff --git a/src/programmable_signals_gui.cpp b/src/programmable_signals_gui.cpp index 5e1a94deed..bbcbbe5d58 100644 --- a/src/programmable_signals_gui.cpp +++ b/src/programmable_signals_gui.cpp @@ -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(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; diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index f065181a58..ebb769631b 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -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. */ diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index c8cc9b31b9..6423b4da7d 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -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" }, diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 63a6adf2d6..17450d9d6a 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -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 diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index e4846214cf..e42e830a58 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -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)), }; diff --git a/src/saveload/tracerestrict_sl.cpp b/src/saveload/tracerestrict_sl.cpp index c09ed95e69..c422e0b5bb 100644 --- a/src/saveload/tracerestrict_sl.cpp +++ b/src/saveload/tracerestrict_sl.cpp @@ -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)), }; /** diff --git a/src/saveload/upstream/order_sl.cpp b/src/saveload/upstream/order_sl.cpp index 661d6990cb..d7172da9ef 100644 --- a/src/saveload/upstream/order_sl.cpp +++ b/src/saveload/upstream/order_sl.cpp @@ -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), }; diff --git a/src/saveload/upstream/vehicle_sl.cpp b/src/saveload/upstream/vehicle_sl.cpp index a21ca05e3d..84219e22ac 100644 --- a/src/saveload/upstream/vehicle_sl.cpp +++ b/src/saveload/upstream/vehicle_sl.cpp @@ -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), diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 0c4de0e50d..d21356e51c 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -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), diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 871794b829..d464ff39ce 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -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; } diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 2e6fbb9955..40e0d8a399 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -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(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 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(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); diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 94b01220e3..cd064bb3d5 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -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 progsig_dependants; @@ -971,9 +984,10 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p static void ValidateSlotOccupants(std::function 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() diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index e6818a420e..8c7b11a435 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -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 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(WID_TRSL_CREATE_SLOT)->widget_data += this->vli.vtype; + this->GetWidget(WID_TRSL_DELETE_SLOT)->widget_data += this->vli.vtype; + this->GetWidget(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(&_slot_window_desc, num); } diff --git a/src/train.h b/src/train.h index f6b6c551c2..0001d4c70d 100644 --- a/src/train.h +++ b/src/train.h @@ -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 diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 55317bf2b7..ba58e291b3 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -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); } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 9149cd9f39..98d7605b94 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -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)); diff --git a/src/vehicle_base.h b/src/vehicle_base.h index dec317b7a1..703674040f 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -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. */ diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 43b9edc066..716a8fc1a2 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -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