Implement 'full load primary' for station orders From: Michał Mirosław --- src/ai/api/ai_order.cpp | 34 ++++++++++++++++++++++++++++--- src/economy.cpp | 16 +++++++++------ src/lang/english.txt | 5 +++++ src/order_base.h | 18 ++++++++++++++++- src/order_cmd.cpp | 15 ++++++-------- src/order_gui.cpp | 45 ++++++++++++++++++++++++++++------------- src/order_type.h | 18 +++++++++-------- src/saveload/afterload.cpp | 48 ++++++++++++++++++++------------------------ src/saveload/order_sl.cpp | 33 ++++++++++++++++++++++++++++-- src/saveload/saveload.cpp | 2 +- src/vehicle.cpp | 32 ++++++++++++++++++++++++++++- src/vehicle_base.h | 2 ++ 12 files changed, 196 insertions(+), 72 deletions(-) diff --git a/src/ai/api/ai_order.cpp b/src/ai/api/ai_order.cpp index fba80ec..81d44aa 100644 --- a/src/ai/api/ai_order.cpp +++ b/src/ai/api/ai_order.cpp @@ -224,7 +224,20 @@ static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition or break; case OT_GOTO_STATION: - order_flags |= (AIOrderFlags)(order->GetLoadType() << 5); + switch (order->GetLoadType()) { + case OLF_FULL_LOAD: + order_flags |= AIOF_FULL_LOAD; + break; + case OLF_NO_LOAD: + order_flags |= AIOF_NO_LOAD; + break; + case OLF_FULL_LOAD_ANY: + case OLF_FULL_LOAD_PRIMARY: + order_flags |= AIOF_FULL_LOAD_ANY; + break; + default: + break; + } order_flags |= (AIOrderFlags)(order->GetUnloadType() << 2); break; @@ -437,7 +450,8 @@ static void _DoCommandReturnSetOrderFlags(class AIInstance *instance) EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position)); EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_position), order_flags)); - const Order *order = Vehicle::Get(vehicle_id)->GetOrder(order_position); + const Vehicle *v = Vehicle::Get(vehicle_id); + const Order *order = v->GetOrder(order_position); AIOrderFlags current = GetOrderFlags(vehicle_id, order_position); @@ -460,7 +474,21 @@ static void _DoCommandReturnSetOrderFlags(class AIInstance *instance) return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags); } if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) { - return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags); + OrderLoadFlags olf; + if (order_flags & AIOF_NO_LOAD) { + olf = OLF_NO_LOAD; + } else switch (order_flags & AIOF_LOAD_FLAGS) { + case AIOF_FULL_LOAD: + olf = OLF_FULL_LOAD; + break; + case AIOF_FULL_LOAD_ANY: + olf = v->type != VEH_AIRCRAFT ? OLF_FULL_LOAD_ANY : OLF_FULL_LOAD_PRIMARY; + break; + default: + olf = OLF_LOAD_IF_POSSIBLE; + break; + } + return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (olf << 4) | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags); } break; diff --git a/src/economy.cpp b/src/economy.cpp index 0e574f5..8c31040 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1219,7 +1219,7 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left) } /* Do not pick up goods when we have no-load set. */ - if (u->current_order.GetLoadType() & OLFB_NO_LOAD) continue; + if (u->current_order.GetLoadType() == OLF_NO_LOAD) continue; /* update stats */ int t; @@ -1319,11 +1319,15 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left) } else { bool finished_loading = true; if (v->current_order.GetLoadType() & OLFB_FULL_LOAD) { - if (v->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) { - /* if the aircraft carries passengers and is NOT full, then - * continue loading, no matter how much mail is in */ - if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap > v->cargo.Count()) || - (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos + /* Full and not full means some wagons were not fully loaded, yet. */ + cargo_full &= ~cargo_not_full; + + if (v->current_order.GetLoadType() == OLF_FULL_LOAD_PRIMARY) { + if ((cargo_full & v->GetPrimaryCargoMask()) == 0) { + finished_loading = false; + } + } else if (v->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) { + if (cargo_full == 0) { finished_loading = false; } } else if (cargo_not_full != 0) { diff --git a/src/lang/english.txt b/src/lang/english.txt index 1204202..7df501e 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3017,6 +3017,7 @@ STR_ORDER_TOGGLE_FULL_LOAD :{BLACK}Full loa STR_ORDER_DROP_LOAD_IF_POSSIBLE :Load if available STR_ORDER_DROP_FULL_LOAD_ALL :Full load all cargo STR_ORDER_DROP_FULL_LOAD_ANY :Full load any cargo +STR_ORDER_DROP_FULL_LOAD_PRIMARY :Full load primary cargo STR_ORDER_DROP_NO_LOADING :No loading STR_ORDER_TOOLTIP_FULL_LOAD :{BLACK}Change the loading behaviour of the highlighted order @@ -3095,18 +3096,22 @@ STR_ORDER_STOP_ORDER :(Stop) STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING} STR_ORDER_FULL_LOAD :(Full load) +STR_ORDER_FULL_LOAD_PRIMARY :(Full load primary cargo) STR_ORDER_FULL_LOAD_ANY :(Full load any cargo) STR_ORDER_NO_LOAD :(No loading) STR_ORDER_UNLOAD :(Unload and take cargo) STR_ORDER_UNLOAD_FULL_LOAD :(Unload and wait for full load) +STR_ORDER_UNLOAD_FULL_LOAD_PRIMARY :(Unload and wait for primary full load) STR_ORDER_UNLOAD_FULL_LOAD_ANY :(Unload and wait for any full load) STR_ORDER_UNLOAD_NO_LOAD :(Unload and leave empty) STR_ORDER_TRANSFER :(Transfer and take cargo) STR_ORDER_TRANSFER_FULL_LOAD :(Transfer and wait for full load) +STR_ORDER_TRANSFER_FULL_LOAD_PRIMARY :(Transfer and wait for primary full load) STR_ORDER_TRANSFER_FULL_LOAD_ANY :(Transfer and wait for any full load) STR_ORDER_TRANSFER_NO_LOAD :(Transfer and leave empty) STR_ORDER_NO_UNLOAD :(No unload and take cargo) STR_ORDER_NO_UNLOAD_FULL_LOAD :(No unload and wait for full load) +STR_ORDER_NO_UNLOAD_FULL_LOAD_PRIMARY :(No unload and wait for primary full load) STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :(No unload and wait for any full load) STR_ORDER_STOP_LOCATION_NEAR_END :[near end] diff --git a/src/order_base.h b/src/order_base.h index e75733a..36a250c 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -250,7 +250,9 @@ public: * Converts this order from an old savegame's version; * it moves all bits to the new location. */ - void ConvertFromOldSavegame(); + void ConvertFromOldSavegame_pre93(); + void ConvertFromOldSavegame_93(); + void ConvertFromOldSavegame_94to131(); }; /** Shared order list linking together the linked list of orders and the list @@ -425,4 +427,18 @@ public: #define FOR_ALL_ORDER_LISTS_FROM(var, start) FOR_ALL_ITEMS_FROM(OrderList, orderlist_index, var, start) #define FOR_ALL_ORDER_LISTS(var) FOR_ALL_ORDER_LISTS_FROM(var, 0) +static inline bool IsOrderLoadTypeValid(unsigned data) +{ + switch (data) { + case OLF_LOAD_IF_POSSIBLE: + case OLF_FULL_LOAD: + case OLF_FULL_LOAD_ANY: + case OLF_FULL_LOAD_PRIMARY: + case OLF_NO_LOAD: + return true; + default: + return false; + } +} + #endif /* ORDER_H */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 9172657..617d6d1 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -475,13 +475,10 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR; /* No load and no unload are mutual exclusive. */ - if ((new_order.GetLoadType() & OLFB_NO_LOAD) && (new_order.GetUnloadType() & OUFB_NO_UNLOAD)) return CMD_ERROR; + if ((new_order.GetLoadType() == OLF_NO_LOAD) && (new_order.GetUnloadType() & OUFB_NO_UNLOAD)) return CMD_ERROR; /* Filter invalid load/unload types. */ - switch (new_order.GetLoadType()) { - case OLF_LOAD_IF_POSSIBLE: case OLFB_FULL_LOAD: case OLF_FULL_LOAD_ANY: case OLFB_NO_LOAD: break; - default: return CMD_ERROR; - } + if (!IsOrderLoadTypeValid(new_order.GetLoadType())) return CMD_ERROR; switch (new_order.GetUnloadType()) { case OUF_UNLOAD_IF_POSSIBLE: case OUFB_UNLOAD: case OUFB_TRANSFER: case OUFB_NO_UNLOAD: break; default: return CMD_ERROR; @@ -952,7 +949,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 break; case MOF_LOAD: - if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR; + if (!IsOrderLoadTypeValid(data)) return CMD_ERROR; if (data == order->GetLoadType()) return CMD_ERROR; break; @@ -1011,14 +1008,14 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 case MOF_UNLOAD: order->SetUnloadType((OrderUnloadFlags)data); - if ((data & OUFB_NO_UNLOAD) != 0 && (order->GetLoadType() & OLFB_NO_LOAD) != 0) { - order->SetLoadType((OrderLoadFlags)(order->GetLoadType() & ~OLFB_NO_LOAD)); + if ((data & OUFB_NO_UNLOAD) != 0 && (order->GetLoadType() == OLF_NO_LOAD)) { + order->SetLoadType(OLF_LOAD_IF_POSSIBLE); } break; case MOF_LOAD: order->SetLoadType((OrderLoadFlags)data); - if ((data & OLFB_NO_LOAD) != 0 && (order->GetUnloadType() & OUFB_NO_UNLOAD) != 0) { + if ((data == OLF_NO_LOAD) && (order->GetUnloadType() & OUFB_NO_UNLOAD) != 0) { /* No load + no unload isn't compatible */ order->SetUnloadType((OrderUnloadFlags)(order->GetUnloadType() & ~OUFB_NO_UNLOAD)); } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 608ac3d..d795f0f 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -59,36 +59,41 @@ enum OrderWindowWidgets { ORDER_WIDGET_SHARED_ORDER_LIST, }; +/** Index OrderLoadFlags into _station_load_types[unload][] */ +static const int _station_load_type_index[16] = { + 0, 4, -1, -1, // OLF_LOAD_IF_POSSIBLE, OLF_NO_LOAD, x, x + -1, 3, 2, 1, // x, OLF_FULL_LOAD_ANY, OLF_FULL_LOAD_PRIMARY, OLF_FULL_LOAD + -1, -1, -1, -1, // x, x, x, x + -1, -1, -1, -1, // x, x, x, x +}; + /** Order load types that could be given to station orders. */ static const StringID _station_load_types[][5] = { { STR_EMPTY, - INVALID_STRING_ID, STR_ORDER_FULL_LOAD, + STR_ORDER_FULL_LOAD_PRIMARY, STR_ORDER_FULL_LOAD_ANY, STR_ORDER_NO_LOAD, }, { STR_ORDER_UNLOAD, - INVALID_STRING_ID, STR_ORDER_UNLOAD_FULL_LOAD, + STR_ORDER_UNLOAD_FULL_LOAD_PRIMARY, STR_ORDER_UNLOAD_FULL_LOAD_ANY, STR_ORDER_UNLOAD_NO_LOAD, }, { STR_ORDER_TRANSFER, - INVALID_STRING_ID, STR_ORDER_TRANSFER_FULL_LOAD, + STR_ORDER_TRANSFER_FULL_LOAD_PRIMARY, STR_ORDER_TRANSFER_FULL_LOAD_ANY, STR_ORDER_TRANSFER_NO_LOAD, }, { /* Unload and transfer do not work together. */ INVALID_STRING_ID, - INVALID_STRING_ID, - INVALID_STRING_ID, - INVALID_STRING_ID, }, { STR_ORDER_NO_UNLOAD, - INVALID_STRING_ID, STR_ORDER_NO_UNLOAD_FULL_LOAD, + STR_ORDER_NO_UNLOAD_FULL_LOAD_PRIMARY, STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY, INVALID_STRING_ID, } @@ -104,12 +109,19 @@ static const StringID _order_non_stop_drowdown[] = { static const StringID _order_full_load_drowdown[] = { STR_ORDER_DROP_LOAD_IF_POSSIBLE, - STR_EMPTY, STR_ORDER_DROP_FULL_LOAD_ALL, + STR_ORDER_DROP_FULL_LOAD_PRIMARY, STR_ORDER_DROP_FULL_LOAD_ANY, STR_ORDER_DROP_NO_LOADING, INVALID_STRING_ID }; +static const OrderLoadFlags _order_full_load_menu_value[] = { + OLF_LOAD_IF_POSSIBLE, + OLF_FULL_LOAD, + OLF_FULL_LOAD_PRIMARY, + OLF_FULL_LOAD_ANY, + OLF_NO_LOAD, +}; static const StringID _order_unload_drowdown[] = { STR_ORDER_DROP_UNLOAD_IF_ACCEPTED, @@ -226,7 +238,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetTimetableParams(6, 7, order->wait_time); } } else { - SetDParam(3, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) ? STR_EMPTY : _station_load_types[unload][load]); + SetDParam(3, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) ? STR_EMPTY : _station_load_types[unload][_station_load_type_index[load]]); if (v->type == VEH_TRAIN && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) { SetDParam(5, order->GetStopLocation() + STR_ORDER_STOP_LOCATION_NEAR_END); } @@ -384,7 +396,7 @@ static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile) (facil = FACIL_TRUCK_STOP, 1); if (st->facilities & facil) { order.MakeGoToStation(st_index); - if (_ctrl_pressed) order.SetLoadType(OLF_FULL_LOAD_ANY); + if (_ctrl_pressed) order.SetLoadType(order.vehicle->type != VEH_AIRCRAFT ? OLF_FULL_LOAD_ANY : OLF_FULL_LOAD_PRIMARY); if (_settings_client.gui.new_nonstop && (v->type == VEH_TRAIN || v->type == VEH_ROAD)) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); order.SetStopLocation(v->type == VEH_TRAIN ? (OrderStopLocation)(_settings_client.gui.stop_location) : OSL_PLATFORM_FAR_END); return order; @@ -548,11 +560,16 @@ private: VehicleOrderID sel_ord = this->OrderGetSel(); const Order *order = this->vehicle->GetOrder(sel_ord); - if (order == NULL || order->GetLoadType() == load_type) return; + if (order == NULL) return; if (load_type < 0) { - load_type = order->GetLoadType() == OLF_LOAD_IF_POSSIBLE ? OLF_FULL_LOAD_ANY : OLF_LOAD_IF_POSSIBLE; + int full_load = this->vehicle->type != VEH_AIRCRAFT ? OLF_FULL_LOAD_ANY : OLF_FULL_LOAD_PRIMARY; + load_type = order->GetLoadType() == OLF_LOAD_IF_POSSIBLE ? full_load : OLF_LOAD_IF_POSSIBLE; + } else { + load_type = _order_full_load_menu_value[load_type]; + if (order->GetLoadType() == load_type) return; } + DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 16), MOF_LOAD | (load_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); } @@ -860,7 +877,7 @@ public: this->EnableWidget(ORDER_WIDGET_NON_STOP); this->SetWidgetLoweredState(ORDER_WIDGET_NON_STOP, order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); } - this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY); + this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY || order->GetLoadType() == OLF_FULL_LOAD_PRIMARY); this->SetWidgetLoweredState(ORDER_WIDGET_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD); break; @@ -1075,7 +1092,7 @@ public: if (GetWidget(widget)->ButtonHit(pt)) { this->OrderClick_FullLoad(-1); } else { - ShowDropDownMenu(this, _order_full_load_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), ORDER_WIDGET_FULL_LOAD, 0, 2); + ShowDropDownMenu(this, _order_full_load_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), ORDER_WIDGET_FULL_LOAD, 0, 0); } break; diff --git a/src/order_type.h b/src/order_type.h index 38b5581..a9e2274 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -46,7 +46,7 @@ typedef SimpleTinyEnumT OrderTypeByte; /** - * Flags related to the unloading order. + * Flags related to the unloading order (4 bits). */ enum OrderUnloadFlags { OUF_UNLOAD_IF_POSSIBLE = 0, ///< Unload all cargo that the station accepts. @@ -56,13 +56,15 @@ enum OrderUnloadFlags { }; /** - * Flags related to the loading order. + * Flags related to the loading order (4 bits). */ enum OrderLoadFlags { - OLF_LOAD_IF_POSSIBLE = 0, ///< Load as long as there is cargo that fits in the train. - OLFB_FULL_LOAD = 1 << 1, ///< Full load the complete the consist. - OLF_FULL_LOAD_ANY = 3, ///< Full load the a single cargo of the consist. - OLFB_NO_LOAD = 4, ///< Do not load anything. + OLF_LOAD_IF_POSSIBLE = 0, ///< Load as long as there is cargo that fits in the train. + OLF_NO_LOAD = 1, ///< Do not load anything. + OLFB_FULL_LOAD = 1 << 2, ///< Full load any cargo if the consist (category flag). + OLF_FULL_LOAD = OLFB_FULL_LOAD|3, ///< Full load complete consist. + OLF_FULL_LOAD_PRIMARY = OLFB_FULL_LOAD|2, ///< Full load primary (major) cargo of the consist. + OLF_FULL_LOAD_ANY = OLFB_FULL_LOAD|1, ///< Full load any single cargo of the consist. }; /** @@ -139,8 +141,8 @@ enum OrderConditionComparator { enum ModifyOrderFlags { MOF_NON_STOP, ///< Passes an OrderNonStopFlags. MOF_STOP_LOCATION, ///< Passes an OrderStopLocation. - MOF_UNLOAD, ///< Passes an OrderUnloadType. - MOF_LOAD, ///< Passes an OrderLoadType + MOF_UNLOAD, ///< Passes an OrderUnloadFlags. + MOF_LOAD, ///< Passes an OrderLoadFlags. MOF_DEPOT_ACTION, ///< Selects the OrderDepotAction MOF_COND_VARIABLE, ///< A conditional variable changes. MOF_COND_COMPARATOR, ///< A comparator changes. diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index beba40d..f08031b 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1444,38 +1444,34 @@ bool AfterLoadGame() } - if (CheckSavegameVersion(93)) { - /* Rework of orders. */ + if (CheckSavegameVersion(132)) { + void (Order::*ConvertFromOldSavegame)(); Order *order; - FOR_ALL_ORDERS(order) order->ConvertFromOldSavegame(); - Vehicle *v; - FOR_ALL_VEHICLES(v) { - if (v->orders.list != NULL && v->orders.list->GetFirstOrder() != NULL && v->orders.list->GetFirstOrder()->IsType(OT_NOTHING)) { - v->orders.list->FreeChain(); - v->orders.list = NULL; - } - v->current_order.ConvertFromOldSavegame(); - if (v->type == VEH_ROAD && v->IsPrimaryVehicle() && v->FirstShared() == v) { - FOR_VEHICLE_ORDERS(v, order) order->SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); - } - } - } else if (CheckSavegameVersion(94)) { - /* Unload and transfer are now mutual exclusive. */ - Order *order; - FOR_ALL_ORDERS(order) { - if ((order->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) { - order->SetUnloadType(OUFB_TRANSFER); - order->SetLoadType(OLFB_NO_LOAD); + if (CheckSavegameVersion(93)) { + ConvertFromOldSavegame = &Order::ConvertFromOldSavegame_pre93; + + FOR_ALL_VEHICLES(v) { + if (v->orders.list != NULL && v->orders.list->GetFirstOrder() != NULL && v->orders.list->GetFirstOrder()->IsType(OT_NOTHING)) { + v->orders.list->FreeChain(); + v->orders.list = NULL; + } } + } else if (CheckSavegameVersion(94)) { + ConvertFromOldSavegame = &Order::ConvertFromOldSavegame_93; + } else { + ConvertFromOldSavegame = &Order::ConvertFromOldSavegame_94to131; } - Vehicle *v; - FOR_ALL_VEHICLES(v) { - if ((v->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) { - v->current_order.SetUnloadType(OUFB_TRANSFER); - v->current_order.SetLoadType(OLFB_NO_LOAD); + FOR_ALL_ORDERS(order) (order->*ConvertFromOldSavegame)(); + FOR_ALL_VEHICLES(v) (v->current_order.*ConvertFromOldSavegame)(); + + if (CheckSavegameVersion(93)) { + FOR_ALL_ROADVEHICLES(v) { + if (v->IsPrimaryVehicle() && v->FirstShared() == v) { + FOR_VEHICLE_ORDERS(v, order) order->SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + } } } } diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index 05e7ece..705d517 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -15,7 +15,7 @@ #include "saveload.h" -void Order::ConvertFromOldSavegame() +void Order::ConvertFromOldSavegame_pre93() { uint8 old_flags = this->flags; this->flags = 0; @@ -37,12 +37,12 @@ void Order::ConvertFromOldSavegame() if (this->GetType() != OT_GOTO_DEPOT) { /* Then the load flags */ if ((old_flags & 2) != 0) { // OFB_UNLOAD - this->SetLoadType(OLFB_NO_LOAD); + this->SetLoadType(OLF_NO_LOAD); } else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD this->SetLoadType(OLF_LOAD_IF_POSSIBLE); } else { /* old OTTD versions stored full_load_any in config file - assume it was enabled when loading */ - this->SetLoadType(_settings_client.gui.sg_full_load_any || CheckSavegameVersion(22) ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD); + this->SetLoadType(_settings_client.gui.sg_full_load_any || CheckSavegameVersion(22) ? OLF_FULL_LOAD_ANY : OLF_FULL_LOAD); } if (this->IsType(OT_GOTO_STATION)) this->SetStopLocation(OSL_PLATFORM_FAR_END); @@ -66,6 +66,33 @@ void Order::ConvertFromOldSavegame() } } +void Order::ConvertFromOldSavegame_94to131() +{ + const OrderLoadFlags full_loads[4] = { + OLF_LOAD_IF_POSSIBLE, OLF_LOAD_IF_POSSIBLE /* invalid */, + OLF_FULL_LOAD, OLF_FULL_LOAD_ANY + }; + + uint olt = this->GetLoadType(); + + if (olt & 4) { // OLFB_NO_LOAD + this->SetLoadType(OLF_NO_LOAD); + } else { // OLFB_FULL_LOAD, OLF_FULL_LOAD_ANY + this->SetLoadType(full_loads[olt & 3]); + } +} + +void Order::ConvertFromOldSavegame_93() +{ + this->ConvertFromOldSavegame_94to131(); + + /* Unload and transfer are now mutual exclusive. */ + if ((this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) { + this->SetUnloadType(OUFB_TRANSFER); + this->SetLoadType(OLF_NO_LOAD); + } +} + /** Unpacks a order from savegames with version 4 and lower * @param packed packed order * @return unpacked order diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index d00aefd..b501885 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -47,7 +47,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 131; +extern const uint16 SAVEGAME_VERSION = 132; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 9e0e7b8..c91b9e7 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -906,7 +906,7 @@ uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour) max += v->cargo_cap; if (v->cargo_cap != 0 && colour != NULL) { unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0; - loading |= !(u->current_order.GetLoadType() & OLFB_NO_LOAD) && st->goods[v->cargo_type].days_since_pickup != 255; + loading |= (u->current_order.GetLoadType() != OLF_NO_LOAD) && st->goods[v->cargo_type].days_since_pickup != 255; cars++; } } @@ -1778,3 +1778,33 @@ bool CanVehicleUseStation(const Vehicle *v, const Station *st) return CanVehicleUseStation(v->engine_type, st); } + +uint32 Vehicle::GetPrimaryCargoMask() const +{ + Vehicle *v; + uint32 cargo_cap[NUM_CARGO]; + + memset(cargo_cap, 0, sizeof(cargo_cap)); + + FOR_ALL_VEHICLES_IN_CHAIN(v, this->First()) { + if (v->cargo_type < lengthof(cargo_cap)) { + cargo_cap[v->cargo_type] += v->cargo_cap; + } + } + + uint32 max = 0; + uint32 mask = 0; + + for (CargoID c = 0; c < lengthof(cargo_cap); ++c) { + if (cargo_cap[c] > max) { + max = cargo_cap[c]; + mask = 1 << c; + } else if (cargo_cap[c] == max) { + mask |= 1 << c; + } + } + + /* TODO: should cache this */ + return mask; +} + diff --git a/src/vehicle_base.h b/src/vehicle_base.h index f01a6e9..bbbc320 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -572,10 +572,12 @@ public: } bool IsEngineCountable() const; + uint32 GetPrimaryCargoMask() const; }; #define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start) #define FOR_ALL_VEHICLES(var) FOR_ALL_VEHICLES_FROM(var, 0) +#define FOR_ALL_VEHICLES_IN_CHAIN(var, first) for (var = (first); var != NULL; var = var->Next()) /** * Class defining several overloaded accessors so we don't