Codechange: Make order load/unload flags value types. (#14861)

Order Load and Unload flags have complex logic to ensure that invalid combinations aren't used. In fact, apart from FullLoad and FullLoadAny, all mixed combinations are invalid.

Simplify logic by removing the use of bit values and treat each option as a value.
This commit is contained in:
Peter Nelson
2025-12-06 18:30:31 +00:00
committed by dP
parent bca73de42e
commit e3e0f88e7a
14 changed files with 160 additions and 117 deletions

View File

@@ -425,14 +425,14 @@ void VehicleCargoList::AgeCargo()
* @param accepted If the cargo will be accepted at the station.
* @param current_station ID of the station.
* @param next_station ID of the station the vehicle will go to next.
* @param order_flags OrderUnloadFlags that will apply to the unload operation.
* @param unload_type OrderUnloadType that will apply to the unload operation.
* @param ge GoodsEntry for getting the flows.
* @param cargo The cargo type of the cargo.
* @param payment Payment object for registering transfers.
* @param current_tile Current tile the cargo handling is happening on.
* return If any cargo will be unloaded.
*/
bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, OrderUnloadType unload_type, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
{
this->AssertCountConsistency();
assert(this->action_counts[MTA_LOAD] == 0);
@@ -444,9 +444,9 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span
static const FlowStatMap EMPTY_FLOW_STAT_MAP = {};
const FlowStatMap &flows = ge->HasData() ? ge->GetData().flows : EMPTY_FLOW_STAT_MAP;
bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
bool force_keep = unload_type == OrderUnloadType::NoUnload;
bool force_unload = unload_type == OrderUnloadType::Unload;
bool force_transfer = unload_type == OrderUnloadType::Transfer || unload_type == OrderUnloadType::Unload;
assert(this->count > 0 || it == this->packets.end());
while (sum < this->count) {
CargoPacket *cp = *it;

View File

@@ -469,7 +469,7 @@ public:
void InvalidateCache();
bool Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile);
bool Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, OrderUnloadType unload_type, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile);
/**
* Marks all cargo in the vehicle as to be kept. This is mostly useful for

View File

@@ -1283,7 +1283,7 @@ void PrepareUnload(Vehicle *front_v)
std::vector<StationID> next_station;
front_v->GetNextStoppingStation(next_station);
if (front_v->orders == nullptr || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
if (front_v->orders == nullptr || front_v->current_order.GetUnloadType() != OrderUnloadType::NoUnload) {
Station *st = Station::Get(front_v->last_station_visited);
for (Vehicle *v = front_v; v != nullptr; v = v->Next()) {
const GoodsEntry *ge = &st->goods[v->cargo_type];
@@ -1532,7 +1532,7 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
/* Add new capacity to consist capacity and reserve cargo */
IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station,
is_auto_refit || (v->First()->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0));
is_auto_refit || v->First()->current_order.IsFullLoadOrder()));
cur_company.Restore();
}
@@ -1635,7 +1635,7 @@ static void LoadUnloadVehicle(Vehicle *front)
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CARGO_AUTO_REFIT;
CargoArray consist_capleft{};
if (_settings_game.order.improved_load && use_autorefit ?
front->cargo_payment == nullptr : (front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0) {
front->cargo_payment == nullptr : (front->current_order.IsFullLoadOrder())) {
ReserveConsist(st, front,
(use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : nullptr,
next_station);
@@ -1676,14 +1676,14 @@ static void LoadUnloadVehicle(Vehicle *front)
GoodsEntry *ge = &st->goods[v->cargo_type];
if (v->vehicle_flags.Test(VehicleFlag::CargoUnloading) && (front->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
if (v->vehicle_flags.Test(VehicleFlag::CargoUnloading) && front->current_order.GetUnloadType() != OrderUnloadType::NoUnload) {
uint cargo_count = v->cargo.UnloadCount();
uint amount_unloaded = _settings_game.order.gradual_loading ? std::min(cargo_count, GetLoadAmount(v)) : cargo_count;
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
if (!ge->status.Test(GoodsEntry::State::Acceptance) && v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER) > 0) {
/* The station does not accept our goods anymore. */
if (front->current_order.GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) {
if (front->current_order.GetUnloadType() == OrderUnloadType::Transfer || front->current_order.GetUnloadType() == OrderUnloadType::Unload) {
/* Transfer instead of delivering. */
v->cargo.Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(
v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER));
@@ -1741,7 +1741,7 @@ static void LoadUnloadVehicle(Vehicle *front)
}
/* Do not pick up goods when we have no-load set or loading is stopped. */
if (front->current_order.GetLoadType() & OLFB_NO_LOAD || front->vehicle_flags.Test(VehicleFlag::StopLoading)) continue;
if (front->current_order.GetLoadType() == OrderLoadType::NoLoad || front->vehicle_flags.Test(VehicleFlag::StopLoading)) continue;
/* This order has a refit, if this is the first vehicle part carrying cargo and the whole vehicle is empty, try refitting. */
if (front->current_order.IsRefit() && artic_part == 1) {
@@ -1865,7 +1865,7 @@ static void LoadUnloadVehicle(Vehicle *front)
}
/* We loaded less cargo than possible for all cargo types and it's not full
* load and we're not supposed to wait any longer: stop loading. */
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !front->current_order.IsFullLoadOrder() &&
front->current_order_time >= std::max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0)) {
front->vehicle_flags.Set(VehicleFlag::StopLoading);
}
@@ -1874,8 +1874,8 @@ static void LoadUnloadVehicle(Vehicle *front)
} else {
UpdateLoadUnloadTicks(front, st, 20); // We need the ticks for link refreshing.
bool finished_loading = true;
if (front->current_order.GetLoadType() & OLFB_FULL_LOAD) {
if (front->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
if (front->current_order.IsFullLoadOrder()) {
if (front->current_order.GetLoadType() == OrderLoadType::FullLoadAny) {
/* if the aircraft carries passengers and is NOT full, then
* continue loading, no matter how much mail is in */
if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CargoClass::Passengers) && front->cargo_cap > front->cargo.StoredCount()) ||

View File

@@ -2816,13 +2816,13 @@ int WhoCanServiceIndustry(Industry *ind)
* may have a different cargo type.
*/
for (const Order &o : v->Orders()) {
if (o.IsType(OT_GOTO_STATION) && !(o.GetUnloadType() & OUFB_TRANSFER)) {
if (o.IsType(OT_GOTO_STATION) && o.GetUnloadType() != OrderUnloadType::Transfer) {
/* Vehicle visits a station to load or unload */
Station *st = Station::Get(o.GetDestination().ToStationID());
assert(st != nullptr);
/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
if ((o.GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
if (o.GetUnloadType() == OrderUnloadType::Unload && !c_accepts) break;
if (ind->stations_near.find(st) != ind->stations_near.end()) {
if (v->owner == _local_company) return 2; // Company services industry

View File

@@ -203,7 +203,7 @@ void LinkRefresher::RefreshStats(VehicleOrderID cur, VehicleOrderID next)
}
/* A link is at least partly restricted if a vehicle can't load at its source. */
EdgeUpdateMode restricted_mode = (orders[cur].GetLoadType() & OLFB_NO_LOAD) == 0 ?
EdgeUpdateMode restricted_mode = orders[cur].GetLoadType() != OrderLoadType::NoLoad ?
EdgeUpdateMode::Unrestricted : EdgeUpdateMode::Restricted;
/* This estimates the travel time of the link as the time needed
* to travel between the stations at half the max speed of the consist.

View File

@@ -1020,7 +1020,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
}
const Order &order = v->First()->current_order;
bool not_loading = (order.GetUnloadType() & OUFB_NO_UNLOAD) && (order.GetLoadType() & OLFB_NO_LOAD);
bool not_loading = order.GetUnloadType() == OrderUnloadType::NoUnload && order.GetLoadType() == OrderLoadType::NoLoad;
bool in_motion = !order.IsType(OT_LOADING) || not_loading;
uint totalsets = static_cast<uint>(in_motion ? group.loaded.size() : group.loading.size());

View File

@@ -128,10 +128,20 @@ public:
void SetRefit(CargoType cargo);
/**
* Is this order a OrderLoadType::FullLoad or OrderLoadType::FullLoadAny?
* @return true iff the order is a full load or full load any order.
*/
inline bool IsFullLoadOrder() const
{
OrderLoadType type = GetLoadType();
return type == OrderLoadType::FullLoad || type == OrderLoadType::FullLoadAny;
}
/** How must the consist be loaded? */
inline OrderLoadFlags GetLoadType() const { return (OrderLoadFlags)GB(this->flags, 4, 3); }
inline OrderLoadType GetLoadType() const { return static_cast<OrderLoadType>(GB(this->flags, 4, 3)); }
/** How must the consist be unloaded? */
inline OrderUnloadFlags GetUnloadType() const { return (OrderUnloadFlags)GB(this->flags, 0, 3); }
inline OrderUnloadType GetUnloadType() const { return static_cast<OrderUnloadType>(GB(this->flags, 0, 3)); }
/** At which stations must we stop? */
inline OrderNonStopFlags GetNonStopType() const { return static_cast<OrderNonStopFlags>(GB(this->type, 6, 2)); }
/** Where must we stop at the platform? */
@@ -150,9 +160,9 @@ public:
inline uint16_t GetConditionValue() const { return GB(this->dest.value, 0, 11); }
/** Set how the consist must be loaded. */
inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 3, load_type); }
inline void SetLoadType(OrderLoadType load_type) { SB(this->flags, 4, 3, to_underlying(load_type)); }
/** Set how the consist must be unloaded. */
inline void SetUnloadType(OrderUnloadFlags unload_type) { SB(this->flags, 0, 3, unload_type); }
inline void SetUnloadType(OrderUnloadType unload_type) { SB(this->flags, 0, 3, to_underlying(unload_type)); }
/** Set whether we must stop at stations or not. */
inline void SetNonStopType(OrderNonStopFlags non_stop_type) { SB(this->type, 6, 2, non_stop_type.base()); }
/** Set where we must stop at the platform. */

View File

@@ -183,8 +183,8 @@ uint16_t Order::MapOldOrder() const
uint16_t order = this->GetType();
switch (this->GetType()) {
case OT_GOTO_STATION:
if (this->GetUnloadType() & OUFB_UNLOAD) SetBit(order, 5);
if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
if (this->GetUnloadType() == OrderUnloadType::Unload) SetBit(order, 5);
if (this->IsFullLoadOrder()) SetBit(order, 6);
if (this->GetNonStopType().Test(OrderNonStopFlag::NoIntermediate)) SetBit(order, 7);
order |= GB(this->GetDestination().value, 0, 8) << 8;
break;
@@ -194,9 +194,9 @@ uint16_t Order::MapOldOrder() const
order |= GB(this->GetDestination().value, 0, 8) << 8;
break;
case OT_LOADING:
if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
if (this->IsFullLoadOrder()) SetBit(order, 6);
/* If both "no load" and "no unload" are set, return nothing order instead */
if ((this->GetLoadType() & OLFB_NO_LOAD) && (this->GetUnloadType() & OUFB_NO_UNLOAD)) {
if (this->GetLoadType() == OrderLoadType::NoLoad && this->GetUnloadType() == OrderUnloadType::NoUnload) {
order = OT_NOTHING;
}
break;
@@ -402,7 +402,7 @@ void OrderList::GetNextStoppingStation(std::vector<StationID> &next_station, con
/* Don't return a next stop if the vehicle has to unload everything. */
if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) &&
orders[next].GetDestination() == v->last_station_visited &&
(orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
(orders[next].GetUnloadType() == OrderUnloadType::Transfer || orders[next].GetUnloadType() == OrderUnloadType::Unload))) {
return;
}
} while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited);
@@ -652,12 +652,12 @@ CommandCost CmdInsertOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID s
/* Filter invalid load/unload types. */
switch (new_order.GetLoadType()) {
case OLF_LOAD_IF_POSSIBLE:
case OLFB_NO_LOAD:
case OrderLoadType::LoadIfPossible:
case OrderLoadType::NoLoad:
break;
case OLFB_FULL_LOAD:
case OLF_FULL_LOAD_ANY:
case OrderLoadType::FullLoad:
case OrderLoadType::FullLoadAny:
if (v->HasUnbunchingOrder()) return CommandCost(STR_ERROR_UNBUNCHING_NO_FULL_LOAD);
break;
@@ -665,8 +665,14 @@ CommandCost CmdInsertOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID s
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;
case OrderUnloadType::UnloadIfPossible:
case OrderUnloadType::Unload:
case OrderUnloadType::Transfer:
case OrderUnloadType::NoUnload:
break;
default:
return CMD_ERROR;
}
/* Filter invalid stop locations */
@@ -955,7 +961,7 @@ static void CancelLoadingDueToDeletedOrder(Vehicle *v)
v->current_order.SetNonStopType({});
/* When full loading, "cancel" that order so the vehicle doesn't
* stay indefinitely at this station anymore. */
if (v->current_order.GetLoadType() & OLFB_FULL_LOAD) v->current_order.SetLoadType(OLF_LOAD_IF_POSSIBLE);
if (v->current_order.IsFullLoadOrder()) v->current_order.SetLoadType(OrderLoadType::LoadIfPossible);
}
/**
@@ -1219,20 +1225,46 @@ CommandCost CmdModifyOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID s
if (data >= to_underlying(OrderStopLocation::End)) return CMD_ERROR;
break;
case MOF_UNLOAD:
case MOF_UNLOAD: {
if (order->GetNonStopType().Test(OrderNonStopFlag::NoDestination)) return CMD_ERROR;
if ((data & ~(OUFB_UNLOAD | OUFB_TRANSFER | OUFB_NO_UNLOAD)) != 0) return CMD_ERROR;
/* Unload and no-unload are mutual exclusive and so are transfer and no unload. */
if (data != 0 && ((data & (OUFB_UNLOAD | OUFB_TRANSFER)) != 0) == ((data & OUFB_NO_UNLOAD) != 0)) return CMD_ERROR;
if (data == order->GetUnloadType()) return CMD_ERROR;
break;
case MOF_LOAD:
if (order->GetNonStopType().Test(OrderNonStopFlag::NoDestination)) return CMD_ERROR;
if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR;
if (data == order->GetLoadType()) return CMD_ERROR;
if ((data & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY)) && v->HasUnbunchingOrder()) return CommandCost(STR_ERROR_UNBUNCHING_NO_FULL_LOAD);
OrderUnloadType unload_type = static_cast<OrderUnloadType>(data);
if (unload_type == order->GetUnloadType()) return CMD_ERROR;
/* Test for invalid types. */
switch (unload_type) {
case OrderUnloadType::UnloadIfPossible:
case OrderUnloadType::Unload:
case OrderUnloadType::Transfer:
case OrderUnloadType::NoUnload:
break;
default: return CMD_ERROR;
}
break;
}
case MOF_LOAD: {
if (order->GetNonStopType().Test(OrderNonStopFlag::NoDestination)) return CMD_ERROR;
OrderLoadType load_type = static_cast<OrderLoadType>(data);
if (load_type == order->GetLoadType()) return CMD_ERROR;
/* Test for invalid types. */
switch (load_type) {
case OrderLoadType::LoadIfPossible:
case OrderLoadType::NoLoad:
break;
case OrderLoadType::FullLoad:
case OrderLoadType::FullLoadAny:
if (v->HasUnbunchingOrder()) return CommandCost(STR_ERROR_UNBUNCHING_NO_FULL_LOAD);
break;
default: return CMD_ERROR;
}
break;
}
case MOF_DEPOT_ACTION: {
OrderDepotAction depot_action = static_cast<OrderDepotAction>(data);
@@ -1300,8 +1332,8 @@ CommandCost CmdModifyOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID s
order->SetNonStopType(static_cast<OrderNonStopFlags>(data));
if (order->GetNonStopType().Test(OrderNonStopFlag::NoDestination)) {
order->SetRefit(CARGO_NO_REFIT);
order->SetLoadType(OLF_LOAD_IF_POSSIBLE);
order->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
order->SetLoadType(OrderLoadType::LoadIfPossible);
order->SetUnloadType(OrderUnloadType::UnloadIfPossible);
}
break;
@@ -1310,12 +1342,12 @@ CommandCost CmdModifyOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID s
break;
case MOF_UNLOAD:
order->SetUnloadType((OrderUnloadFlags)data);
order->SetUnloadType(static_cast<OrderUnloadType>(data));
break;
case MOF_LOAD:
order->SetLoadType((OrderLoadFlags)data);
if (data & OLFB_NO_LOAD) order->SetRefit(CARGO_NO_REFIT);
order->SetLoadType(static_cast<OrderLoadType>(data));
if (order->GetLoadType() == OrderLoadType::NoLoad) order->SetRefit(CARGO_NO_REFIT);
break;
case MOF_DEPOT_ACTION: {
@@ -1613,7 +1645,7 @@ CommandCost CmdOrderRefit(DoCommandFlags flags, VehicleID veh, VehicleOrderID or
/* Automatic refit cargo is only supported for goto station orders. */
if (cargo == CARGO_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
if (order->GetLoadType() & OLFB_NO_LOAD) return CMD_ERROR;
if (order->GetLoadType() == OrderLoadType::NoLoad) return CMD_ERROR;
if (flags.Test(DoCommandFlag::Execute)) {
order->SetRefit(cargo);
@@ -2153,8 +2185,8 @@ bool Order::CanLoadOrUnload() const
{
return (this->IsType(OT_GOTO_STATION) || this->IsType(OT_IMPLICIT)) &&
!this->GetNonStopType().Test(OrderNonStopFlag::NoDestination) &&
((this->GetLoadType() & OLFB_NO_LOAD) == 0 ||
(this->GetUnloadType() & OUFB_NO_UNLOAD) == 0);
(this->GetLoadType() != OrderLoadType::NoLoad ||
this->GetUnloadType() != OrderUnloadType::NoUnload);
}
/**
@@ -2165,6 +2197,7 @@ bool Order::CanLoadOrUnload() const
*/
bool Order::CanLeaveWithCargo(bool has_cargo) const
{
return (this->GetLoadType() & OLFB_NO_LOAD) == 0 || (has_cargo &&
(this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == 0);
return this->GetLoadType() != OrderLoadType::NoLoad || (has_cargo &&
this->GetUnloadType() != OrderUnloadType::Unload &&
this->GetUnloadType() != OrderUnloadType::Transfer);
}

View File

@@ -257,8 +257,8 @@ void DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_
break;
case OT_GOTO_STATION: {
OrderLoadFlags load = order->GetLoadType();
OrderUnloadFlags unload = order->GetUnloadType();
OrderLoadType load = order->GetLoadType();
OrderUnloadType unload = order->GetUnloadType();
bool valid_station = CanVehicleUseStation(v, Station::Get(order->GetDestination().ToStationID()));
line = GetString(valid_station ? STR_ORDER_GO_TO_STATION : STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION, STR_ORDER_GO_TO + (v->IsGroundVehicle() ? order->GetNonStopType() : OrderNonStopFlags{}).base(), order->GetDestination());
@@ -271,7 +271,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_
} else {
/* Show non-stop, refit and stop location only in the order window. */
if (!order->GetNonStopType().Test(OrderNonStopFlag::NoDestination)) {
StringID str = _station_load_types[order->IsRefit()][unload][load];
StringID str = _station_load_types[order->IsRefit()][to_underlying(unload)][to_underlying(load)];
if (str != INVALID_STRING_ID) {
if (order->IsRefit()) {
line += GetString(str, order->IsAutoRefit() ? STR_ORDER_AUTO_REFIT_ANY : CargoSpec::Get(order->GetRefitCargo())->name);
@@ -449,7 +449,7 @@ static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
}
if (st->facilities.Any(facil)) {
order.MakeGoToStation(st->index);
if (_ctrl_pressed) order.SetLoadType(OLF_FULL_LOAD_ANY);
if (_ctrl_pressed) order.SetLoadType(OrderLoadType::FullLoadAny);
if (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) order.SetNonStopType(OrderNonStopFlag::NoIntermediate);
order.SetStopLocation(v->type == VEH_TRAIN ? (OrderStopLocation)(_settings_client.gui.stop_location) : OrderStopLocation::FarEnd);
return order;
@@ -614,7 +614,7 @@ private:
* @param load_type Load flag to apply. If matches existing load type, toggles to default of 'load if possible'.
* @param toggle If we toggle or not (used for hotkey behavior)
*/
void OrderClick_FullLoad(OrderLoadFlags load_type, bool toggle = false)
void OrderClick_FullLoad(OrderLoadType load_type, bool toggle = false)
{
VehicleOrderID sel_ord = this->OrderGetSel();
const Order *order = this->vehicle->GetOrder(sel_ord);
@@ -622,11 +622,11 @@ private:
if (order == nullptr) return;
if (toggle && order->GetLoadType() == load_type) {
load_type = OLF_LOAD_IF_POSSIBLE; // reset to 'default'
load_type = OrderLoadType::LoadIfPossible; // reset to 'default'
}
if (order->GetLoadType() == load_type) return; // If we still match, do nothing
Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, load_type);
Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, to_underlying(load_type));
}
/**
@@ -662,7 +662,7 @@ private:
* @param unload_type Unload flag to apply. If matches existing unload type, toggles to default of 'unload if possible'.
* @param toggle If we toggle or not (used for hotkey behavior)
*/
void OrderClick_Unload(OrderUnloadFlags unload_type, bool toggle = false)
void OrderClick_Unload(OrderUnloadType unload_type, bool toggle = false)
{
VehicleOrderID sel_ord = this->OrderGetSel();
const Order *order = this->vehicle->GetOrder(sel_ord);
@@ -670,15 +670,15 @@ private:
if (order == nullptr) return;
if (toggle && order->GetUnloadType() == unload_type) {
unload_type = OUF_UNLOAD_IF_POSSIBLE;
unload_type = OrderUnloadType::UnloadIfPossible;
}
if (order->GetUnloadType() == unload_type) return; // If we still match, do nothing
Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_UNLOAD, unload_type);
Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_UNLOAD, to_underlying(unload_type));
/* Transfer and unload orders with leave empty as default */
if (unload_type == OUFB_TRANSFER || unload_type == OUFB_UNLOAD) {
Command<CMD_MODIFY_ORDER>::Post(this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, OLFB_NO_LOAD);
if (unload_type == OrderUnloadType::Transfer || unload_type == OrderUnloadType::Unload) {
Command<CMD_MODIFY_ORDER>::Post(this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, to_underlying(OrderLoadType::NoLoad));
this->SetWidgetDirty(WID_O_FULL_LOAD);
}
}
@@ -995,13 +995,13 @@ public:
this->EnableWidget(WID_O_NON_STOP);
this->SetWidgetLoweredState(WID_O_NON_STOP, order->GetNonStopType().Test(OrderNonStopFlag::NoIntermediate));
}
this->SetWidgetLoweredState(WID_O_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY);
this->SetWidgetLoweredState(WID_O_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD);
this->SetWidgetLoweredState(WID_O_FULL_LOAD, order->GetLoadType() == OrderLoadType::FullLoadAny);
this->SetWidgetLoweredState(WID_O_UNLOAD, order->GetUnloadType() == OrderUnloadType::Unload);
/* Can only do refitting when stopping at the destination and loading cargo.
* Also enable the button if a refit is already set to allow clearing it. */
this->SetWidgetDisabledState(WID_O_REFIT_DROPDOWN,
order->GetLoadType() == OLFB_NO_LOAD || order->GetNonStopType().Test(OrderNonStopFlag::NoDestination) ||
order->GetLoadType() == OrderLoadType::NoLoad || order->GetNonStopType().Test(OrderNonStopFlag::NoDestination) ||
((!this->can_do_refit || !this->can_do_autorefit) && !order->IsRefit()));
break;
@@ -1276,17 +1276,17 @@ public:
case WID_O_FULL_LOAD:
if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
this->OrderClick_FullLoad(OLF_FULL_LOAD_ANY, true);
this->OrderClick_FullLoad(OrderLoadType::FullLoadAny, true);
} else {
ShowDropDownMenu(this, _order_full_load_dropdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), WID_O_FULL_LOAD, 0, 2);
ShowDropDownMenu(this, _order_full_load_dropdown, to_underlying(this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType()), WID_O_FULL_LOAD, 0, 2);
}
break;
case WID_O_UNLOAD:
if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
this->OrderClick_Unload(OUFB_UNLOAD, true);
this->OrderClick_Unload(OrderUnloadType::Unload, true);
} else {
ShowDropDownMenu(this, _order_unload_dropdown, this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType(), WID_O_UNLOAD, 0, 8);
ShowDropDownMenu(this, _order_unload_dropdown, to_underlying(this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType()), WID_O_UNLOAD, 0, 8);
}
break;
@@ -1373,11 +1373,11 @@ public:
break;
case WID_O_FULL_LOAD:
this->OrderClick_FullLoad((OrderLoadFlags)index);
this->OrderClick_FullLoad(static_cast<OrderLoadType>(index));
break;
case WID_O_UNLOAD:
this->OrderClick_Unload((OrderUnloadFlags)index);
this->OrderClick_Unload(static_cast<OrderUnloadType>(index));
break;
case WID_O_GOTO:
@@ -1450,13 +1450,13 @@ public:
case OHK_DELETE: this->OrderClick_Delete(); break;
case OHK_GOTO: this->OrderClick_Goto(OPOS_GOTO); break;
case OHK_NONSTOP: this->OrderClick_Nonstop(std::nullopt); break;
case OHK_FULLLOAD: this->OrderClick_FullLoad(OLF_FULL_LOAD_ANY, true); break;
case OHK_UNLOAD: this->OrderClick_Unload(OUFB_UNLOAD, true); break;
case OHK_FULLLOAD: this->OrderClick_FullLoad(OrderLoadType::FullLoadAny, true); break;
case OHK_UNLOAD: this->OrderClick_Unload(OrderUnloadType::Unload, true); break;
case OHK_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break;
case OHK_ALWAYS_SERVICE: this->OrderClick_Service(std::nullopt); break;
case OHK_TRANSFER: this->OrderClick_Unload(OUFB_TRANSFER, true); break;
case OHK_NO_UNLOAD: this->OrderClick_Unload(OUFB_NO_UNLOAD, true); break;
case OHK_NO_LOAD: this->OrderClick_FullLoad(OLFB_NO_LOAD, true); break;
case OHK_TRANSFER: this->OrderClick_Unload(OrderUnloadType::Transfer, true); break;
case OHK_NO_UNLOAD: this->OrderClick_Unload(OrderUnloadType::NoUnload, true); break;
case OHK_NO_LOAD: this->OrderClick_FullLoad(OrderLoadType::NoLoad, true); break;
default: return ES_NOT_HANDLED;
}
return ES_HANDLED;

View File

@@ -62,23 +62,23 @@ enum OrderType : uint8_t {
};
/**
* Flags related to the unloading order.
* Unloading order types.
*/
enum OrderUnloadFlags : uint8_t {
OUF_UNLOAD_IF_POSSIBLE = 0, ///< Unload all cargo that the station accepts.
OUFB_UNLOAD = 1 << 0, ///< Force unloading all cargo onto the platform, possibly not getting paid.
OUFB_TRANSFER = 1 << 1, ///< Transfer all cargo onto the platform.
OUFB_NO_UNLOAD = 1 << 2, ///< Totally no unloading will be done.
enum class OrderUnloadType : uint8_t {
UnloadIfPossible = 0, ///< Unload all cargo that the station accepts.
Unload = 1, ///< Force unloading all cargo onto the platform, possibly not getting paid.
Transfer = 2, ///< Transfer all cargo onto the platform.
NoUnload = 4, ///< Totally no unloading will be done.
};
/**
* Flags related to the loading order.
* Loading order types.
*/
enum OrderLoadFlags : uint8_t {
OLF_LOAD_IF_POSSIBLE = 0, ///< Load as long as there is cargo that fits in the train.
OLFB_FULL_LOAD = 1 << 1, ///< Full load all cargoes of the consist.
OLF_FULL_LOAD_ANY = 3, ///< Full load a single cargo of the consist.
OLFB_NO_LOAD = 4, ///< Do not load anything.
enum class OrderLoadType : uint8_t {
LoadIfPossible = 0, ///< Load as long as there is cargo that fits in the train.
FullLoad = 2, ///< Full load all cargoes of the consist.
FullLoadAny = 3, ///< Full load a single cargo of the consist.
NoLoad = 4, ///< Do not load anything.
};
/**

View File

@@ -1830,17 +1830,17 @@ bool AfterLoadGame()
/* Unload and transfer are now mutual exclusive. */
for (OrderList *orderlist : OrderList::Iterate()) {
for (Order &order : orderlist->GetOrders()) {
if ((order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) {
order.SetUnloadType(OUFB_TRANSFER);
order.SetLoadType(OLFB_NO_LOAD);
if (order.GetUnloadType() == OrderUnloadType{3}) { // 3 used to mean transfer and don't load.
order.SetUnloadType(OrderUnloadType::Transfer);
order.SetLoadType(OrderLoadType::NoLoad);
}
}
}
for (Vehicle *v : Vehicle::Iterate()) {
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);
if (v->current_order.GetUnloadType() == OrderUnloadType{3}) { // 3 used to mean transfer and don't load.
v->current_order.SetUnloadType(OrderUnloadType::Transfer);
v->current_order.SetLoadType(OrderLoadType::NoLoad);
}
}
} else if (IsSavegameVersionBefore(SLV_DEPOT_UNBUNCHING)) {

View File

@@ -45,23 +45,23 @@ 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(OrderLoadType::NoLoad);
} else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD
this->SetLoadType(OLF_LOAD_IF_POSSIBLE);
this->SetLoadType(OrderLoadType::LoadIfPossible);
} 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 || IsSavegameVersionBefore(SLV_22) ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD);
this->SetLoadType(_settings_client.gui.sg_full_load_any || IsSavegameVersionBefore(SLV_22) ? OrderLoadType::FullLoadAny : OrderLoadType::FullLoad);
}
if (this->IsType(OT_GOTO_STATION)) this->SetStopLocation(OrderStopLocation::FarEnd);
/* Finally fix the unload flags */
if ((old_flags & 1) != 0) { // OFB_TRANSFER
this->SetUnloadType(OUFB_TRANSFER);
this->SetUnloadType(OrderUnloadType::Transfer);
} else if ((old_flags & 2) != 0) { // OFB_UNLOAD
this->SetUnloadType(OUFB_UNLOAD);
this->SetUnloadType(OrderUnloadType::Unload);
} else {
this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
this->SetUnloadType(OrderUnloadType::UnloadIfPossible);
}
} else {
/* Then the depot action flags */

View File

@@ -315,8 +315,8 @@ static ScriptOrder::OrderPosition RealOrderPositionToScriptOrderPosition(Vehicle
break;
case OT_GOTO_STATION:
order_flags |= (ScriptOrderFlags)(order->GetLoadType() << 5);
order_flags |= (ScriptOrderFlags)(order->GetUnloadType() << 2);
order_flags |= static_cast<ScriptOrderFlags>(to_underlying(order->GetLoadType()) << 5);
order_flags |= static_cast<ScriptOrderFlags>(to_underlying(order->GetUnloadType()) << 2);
break;
default: break;
@@ -511,8 +511,8 @@ static ScriptOrder::OrderPosition RealOrderPositionToScriptOrderPosition(Vehicle
case OT_GOTO_STATION:
order.MakeGoToStation(::GetStationIndex(destination));
order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3));
order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3));
order.SetLoadType(static_cast<OrderLoadType>(GB(order_flags, 5, 3)));
order.SetUnloadType(static_cast<OrderUnloadType>(GB(order_flags, 2, 3)));
order.SetStopLocation(OrderStopLocation::FarEnd);
break;

View File

@@ -1472,8 +1472,8 @@ uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
const Station *st = Station::GetIfValid(front->last_station_visited);
assert(colour == nullptr || (st != nullptr && is_loading));
bool order_no_load = is_loading && (front->current_order.GetLoadType() & OLFB_NO_LOAD);
bool order_full_load = is_loading && (front->current_order.GetLoadType() & OLFB_FULL_LOAD);
bool order_no_load = is_loading && front->current_order.GetLoadType() == OrderLoadType::NoLoad;
bool order_full_load = is_loading && front->current_order.IsFullLoadOrder();
/* Count up max and used */
for (const Vehicle *v = front; v != nullptr; v = v->Next()) {
@@ -2286,8 +2286,8 @@ void Vehicle::BeginLoading()
if (this->last_loading_station != StationID::Invalid() &&
this->last_loading_station != this->last_station_visited &&
((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
(this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0)) {
(this->current_order.GetLoadType() != OrderLoadType::NoLoad ||
this->current_order.GetUnloadType() != OrderUnloadType::NoUnload)) {
IncreaseStats(Station::Get(this->last_loading_station), this, this->last_station_visited, travel_time);
}
@@ -2334,8 +2334,8 @@ void Vehicle::LeaveStation()
/* Only update the timetable if the vehicle was supposed to stop here. */
if (this->current_order.GetNonStopType().Any()) UpdateVehicleTimetable(this, false);
if ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
(this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
if (this->current_order.GetLoadType() != OrderLoadType::NoLoad ||
this->current_order.GetUnloadType() != OrderUnloadType::NoUnload) {
if (this->current_order.CanLeaveWithCargo(this->last_loading_station != StationID::Invalid())) {
/* Refresh next hop stats to make sure we've done that at least once
* during the stop and that refit_cap == cargo_cap for each vehicle in
@@ -2442,7 +2442,7 @@ void Vehicle::HandleLoading(bool mode)
bool Vehicle::HasFullLoadOrder() const
{
return std::ranges::any_of(this->Orders(), [](const Order &o) {
return o.IsType(OT_GOTO_STATION) && o.GetLoadType() & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY);
return o.IsType(OT_GOTO_STATION) && o.IsFullLoadOrder();
});
}