Codechange: make GroundVehicleFlag(s) a scoped enum/EnumBitSet (#15754)

This commit is contained in:
Peter Nelson
2026-06-21 08:50:45 +01:00
committed by GitHub
parent 7bd9fbc733
commit a57eb70e05
10 changed files with 61 additions and 80 deletions
+13 -22
View File
@@ -50,13 +50,6 @@ struct GroundVehicleCache {
auto operator<=>(const GroundVehicleCache &) const = default;
};
/** Ground vehicle flags. */
enum GroundVehicleFlags : uint8_t {
GVF_GOINGUP_BIT = 0, ///< Vehicle is currently going uphill. (Cached track information for acceleration)
GVF_GOINGDOWN_BIT = 1, ///< Vehicle is currently going downhill. (Cached track information for acceleration)
GVF_SUPPRESS_IMPLICIT_ORDERS = 2, ///< Disable insertion and removal of automatic orders until the vehicle completes the real order.
};
/**
* Base class for all vehicles that move through ground.
*
@@ -81,7 +74,7 @@ enum GroundVehicleFlags : uint8_t {
template <class T, VehicleType Type>
struct GroundVehicle : public SpecializedVehicle<T, Type> {
GroundVehicleCache gcache{}; ///< Cache of often calculated values.
uint16_t gv_flags = 0; ///< @see GroundVehicleFlags.
GroundVehicleFlags gv_flags{}; ///< @see GroundVehicleFlags.
typedef GroundVehicle<T, Type> GroundVehicleBase; ///< Our type
@@ -105,8 +98,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
{
/* Crashed vehicles aren't going up or down */
for (T *v = T::From(this); v != nullptr; v = v->Next()) {
ClrBit(v->gv_flags, GVF_GOINGUP_BIT);
ClrBit(v->gv_flags, GVF_GOINGDOWN_BIT);
v->gv_flags.Reset({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown});
}
return this->Vehicle::Crash(flooded);
}
@@ -120,9 +112,9 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
int64_t incl = 0;
for (const T *u = T::From(this); u != nullptr; u = u->Next()) {
if (HasBit(u->gv_flags, GVF_GOINGUP_BIT)) {
if (u->gv_flags.Test(GroundVehicleFlag::GoingUp)) {
incl += u->gcache.cached_slope_resistance;
} else if (HasBit(u->gv_flags, GVF_GOINGDOWN_BIT)) {
} else if (u->gv_flags.Test(GroundVehicleFlag::GoingDown)) {
incl -= u->gcache.cached_slope_resistance;
}
}
@@ -139,8 +131,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
inline void UpdateZPositionAndInclination()
{
this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos, true);
ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
this->gv_flags.Reset({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown});
if (T::From(this)->TileMayHaveSlopedTrack()) {
/* To check whether the current tile is sloped, and in which
@@ -150,7 +141,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
int middle_z = GetSlopePixelZ((this->x_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), (this->y_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), true);
if (middle_z != this->z_pos) {
SetBit(this->gv_flags, (middle_z > this->z_pos) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
this->gv_flags.Set((middle_z > this->z_pos) ? GroundVehicleFlag::GoingUp : GroundVehicleFlag::GoingDown);
}
}
}
@@ -166,7 +157,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
#if 0
/* The following code does this: */
if (HasBit(this->gv_flags, GVF_GOINGUP_BIT)) {
if (this->gv_flags.Test(GroundVehicleFlag::GoingUp)) {
switch (this->GetMovingDirection()) {
case Direction::NE:
this->z_pos += (this->x_pos & 1) ^ 1; break;
@@ -178,7 +169,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
this->z_pos += (this->y_pos & 1); break;
default: break;
}
} else if (HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
} else if (this->gv_flags.Test(GroundVehicleFlag::GoingDown)) {
switch (this->GetMovingDirection()) {
case Direction::NE:
this->z_pos -= (this->x_pos & 1) ^ 1; break;
@@ -196,12 +187,12 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
* code is full of conditional jumps. */
#endif
/* Vehicle's Z position can change only if it has GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set.
/* Vehicle's Z position can change only if it has GroundVehicleFlag::GoingUp or GroundVehicleFlag::GoingDown set.
* Furthermore, if this function is called once every time the vehicle's position changes,
* we know the Z position changes by +/-1 at certain moments - when x_pos, y_pos is odd/even,
* depending on orientation of the slope and vehicle's direction */
if (HasBit(this->gv_flags, GVF_GOINGUP_BIT) || HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
if (this->gv_flags.Any({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown})) {
if (T::From(this)->HasToUseGetSlopePixelZ()) {
/* In some cases, we have to use GetSlopePixelZ() */
this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos, true);
@@ -217,10 +208,10 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
/* We need only the least significant bit */
d &= 1;
d ^= (int8_t)(dir == DiagDirection::NW || dir == DiagDirection::NE);
/* Subtraction instead of addition because we are testing for GVF_GOINGUP_BIT.
* GVF_GOINGUP_BIT is used because it's bit 0, so simple AND can be used,
/* Subtraction instead of addition because we are testing for GroundVehicleFlag::GoingUp.
* GroundVehicleFlag::GoingUp is used because it's bit 0, so simple AND can be used,
* without any shift */
this->z_pos += HasBit(this->gv_flags, GVF_GOINGUP_BIT) ? d : -d;
this->z_pos += this->gv_flags.Test(GroundVehicleFlag::GoingUp) ? d : -d;
}
assert(this->z_pos == GetSlopePixelZ(this->x_pos, this->y_pos, true));
+2 -4
View File
@@ -877,8 +877,7 @@ void InsertOrder(Vehicle *v, Order &&new_o, VehicleOrderID sel_ord)
/* We are inserting an order just before the current implicit order.
* We do not know whether we will reach current implicit or the newly inserted order first.
* So, disable creation of implicit orders until we are on track again. */
uint16_t &gv_flags = u->GetGroundVehicleFlags();
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
u->GetGroundVehicleFlags().Set(GroundVehicleFlag::SuppressImplicitOrders);
}
if (sel_ord <= u->cur_implicit_order_index) {
uint cur = u->cur_implicit_order_index + 1;
@@ -2051,8 +2050,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
/* Disable creation of implicit orders.
* When inserting them we do not know that we would have to make the conditional orders point to them. */
if (v->IsGroundVehicle()) {
uint16_t &gv_flags = v->GetGroundVehicleFlags();
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
v->GetGroundVehicleFlags().Set(GroundVehicleFlag::SuppressImplicitOrders);
}
} else {
UpdateVehicleTimetable(v, true);
+1 -1
View File
@@ -305,7 +305,7 @@ protected: // These functions should not be called outside acceleration code.
const RoadVehicle *rv = this->First();
/* Check if this vehicle is in the same direction as the road under.
* We already know it has either GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set. */
* We already know it has either GroundVehicleFlag::GoingUp or GroundVehicleFlag::GoingDown set. */
if (rv->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir(static_cast<Trackdir>(rv->state))) {
/* If the first vehicle is reversing, this vehicle may be reversing too
+1 -1
View File
@@ -1700,7 +1700,7 @@ static void CheckIfRoadVehNeedsService(RoadVehicle *v)
return;
}
SetBit(v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
v->gv_flags.Set(GroundVehicleFlag::SuppressImplicitOrders);
v->current_order.MakeGoToDepot(depot, OrderDepotTypeFlag::Service);
v->SetDestTile(rfdd.tile);
SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
+6 -8
View File
@@ -474,7 +474,7 @@ static void FixOwnerOfRailTrack(Tile t)
* @param dir vehicle's direction, or # Direction::Invalid if it can be ignored
* @return inclination bits to set
*/
static uint FixVehicleInclination(Vehicle *v, Direction dir)
static GroundVehicleFlags FixVehicleInclination(Vehicle *v, Direction dir)
{
/* Compute place where this vehicle entered the tile */
int entry_x = v->x_pos;
@@ -495,13 +495,13 @@ static uint FixVehicleInclination(Vehicle *v, Direction dir)
uint8_t middle_z = GetSlopePixelZ(middle_x, middle_y, true);
/* middle_z == entry_z, no height change. */
if (middle_z == entry_z) return 0;
if (middle_z == entry_z) return {};
/* middle_z < entry_z, we are going downwards. */
if (middle_z < entry_z) return 1U << GVF_GOINGDOWN_BIT;
if (middle_z < entry_z) return GroundVehicleFlag::GoingDown;
/* middle_z > entry_z, we are going upwards. */
return 1U << GVF_GOINGUP_BIT;
return GroundVehicleFlag::GoingUp;
}
/**
@@ -2750,8 +2750,7 @@ bool AfterLoadGame()
t->flags.Reset(VehicleRailFlag{2});
/* Clear both bits first. */
ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
ClrBit(t->gv_flags, GVF_GOINGDOWN_BIT);
t->gv_flags.Reset({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown});
/* Crashed vehicles can't be going up/down. */
if (t->vehstatus.Test(VehState::Crashed)) break;
@@ -2764,8 +2763,7 @@ bool AfterLoadGame()
}
case VehicleType::Road: {
RoadVehicle *rv = RoadVehicle::From(v);
ClrBit(rv->gv_flags, GVF_GOINGUP_BIT);
ClrBit(rv->gv_flags, GVF_GOINGDOWN_BIT);
rv->gv_flags.Reset({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown});
/* Crashed vehicles can't be going up/down. */
if (rv->vehstatus.Test(VehState::Crashed)) break;
+14 -27
View File
@@ -1613,32 +1613,20 @@ static void MarkTrainAsStuck(Train *consist)
/**
* Swap the two up/down flags in two ways:
* - Swap values of \a swap_flag1 and \a swap_flag2, and
* - If going up previously (#GVF_GOINGUP_BIT set), the #GVF_GOINGDOWN_BIT is set, and vice versa.
* - If going up previously (#GroundVehicleFlag::GoingUp set), the #GroundVehicleFlag::GoingDown is set, and vice versa.
* @param[in,out] swap_flag1 First train flag.
* @param[in,out] swap_flag2 Second train flag.
*/
static void SwapTrainFlags(uint16_t *swap_flag1, uint16_t *swap_flag2)
static void SwapTrainFlags(GroundVehicleFlags *swap_flag1, GroundVehicleFlags *swap_flag2)
{
uint16_t flag1 = *swap_flag1;
uint16_t flag2 = *swap_flag2;
/* Clear the flags */
ClrBit(*swap_flag1, GVF_GOINGUP_BIT);
ClrBit(*swap_flag1, GVF_GOINGDOWN_BIT);
ClrBit(*swap_flag2, GVF_GOINGUP_BIT);
ClrBit(*swap_flag2, GVF_GOINGDOWN_BIT);
GroundVehicleFlags flag1 = *swap_flag1;
GroundVehicleFlags flag2 = *swap_flag2;
/* Reverse the rail-flags (if needed) */
if (HasBit(flag1, GVF_GOINGUP_BIT)) {
SetBit(*swap_flag2, GVF_GOINGDOWN_BIT);
} else if (HasBit(flag1, GVF_GOINGDOWN_BIT)) {
SetBit(*swap_flag2, GVF_GOINGUP_BIT);
}
if (HasBit(flag2, GVF_GOINGUP_BIT)) {
SetBit(*swap_flag1, GVF_GOINGDOWN_BIT);
} else if (HasBit(flag2, GVF_GOINGDOWN_BIT)) {
SetBit(*swap_flag1, GVF_GOINGUP_BIT);
}
swap_flag2->Set(GroundVehicleFlag::GoingDown, flag1.Test(GroundVehicleFlag::GoingUp));
swap_flag2->Set(GroundVehicleFlag::GoingUp, flag1.Test(GroundVehicleFlag::GoingDown));
swap_flag1->Set(GroundVehicleFlag::GoingDown, flag2.Test(GroundVehicleFlag::GoingUp));
swap_flag1->Set(GroundVehicleFlag::GoingUp, flag2.Test(GroundVehicleFlag::GoingDown));
}
/**
@@ -1710,7 +1698,7 @@ static void ReverseTrainSwapVeh(Train *v, int l, int r)
SwapTrainFlags(&a->gv_flags, &b->gv_flags);
} else {
/* Swap GVF_GOINGUP_BIT/GVF_GOINGDOWN_BIT.
/* Swap GroundVehicleFlag::GoingUp/GroundVehicleFlag::GoingDown.
* This is a little bit redundant way, a->gv_flags will
* be (re)set twice, but it reduces code duplication */
SwapTrainFlags(&a->gv_flags, &a->gv_flags);
@@ -2051,9 +2039,8 @@ static void ReverseTrainDirection(Train *consist)
for (Train *u = consist; u != nullptr; u = u->Next()) {
/* Invert going up/down */
if (HasBit(u->gv_flags, GVF_GOINGUP_BIT) || HasBit(u->gv_flags, GVF_GOINGDOWN_BIT)) {
ToggleBit(u->gv_flags, GVF_GOINGDOWN_BIT);
ToggleBit(u->gv_flags, GVF_GOINGUP_BIT);
if (u->gv_flags.Any({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown})) {
u->gv_flags.Flip({GroundVehicleFlag::GoingUp, GroundVehicleFlag::GoingDown});
}
UpdateStatusAfterSwap(u, false);
}
@@ -2698,7 +2685,7 @@ public:
old_dest_tile(_v->dest_tile),
old_last_station_visited(_v->last_station_visited),
index(_v->cur_real_order_index),
suppress_implicit_orders(HasBit(_v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)),
suppress_implicit_orders(_v->gv_flags.Test(GroundVehicleFlag::SuppressImplicitOrders)),
restored(false)
{
}
@@ -2711,7 +2698,7 @@ public:
this->v->current_order = this->old_order;
this->v->dest_tile = this->old_dest_tile;
this->v->last_station_visited = this->old_last_station_visited;
AssignBit(this->v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS, suppress_implicit_orders);
this->v->gv_flags.Set(GroundVehicleFlag::SuppressImplicitOrders, suppress_implicit_orders);
this->restored = true;
}
@@ -4245,7 +4232,7 @@ static void CheckIfTrainNeedsService(Train *v)
return;
}
SetBit(v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
v->gv_flags.Set(GroundVehicleFlag::SuppressImplicitOrders);
v->current_order.MakeGoToDepot(depot, OrderDepotTypeFlag::Service, OrderNonStopFlag::NonStop, OrderDepotActionFlag::NearestDepot);
v->dest_tile = tfdd.tile;
SetWindowWidgetDirty(WindowClass::VehicleView, v->index, WID_VV_START_STOP);
+3 -3
View File
@@ -1930,11 +1930,11 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner
template <typename T>
static void PrepareToEnterBridge(T *gv)
{
if (HasBit(gv->gv_flags, GVF_GOINGUP_BIT)) {
if (gv->gv_flags.Test(GroundVehicleFlag::GoingUp)) {
gv->z_pos++;
ClrBit(gv->gv_flags, GVF_GOINGUP_BIT);
gv->gv_flags.Reset(GroundVehicleFlag::GoingUp);
} else {
ClrBit(gv->gv_flags, GVF_GOINGDOWN_BIT);
gv->gv_flags.Reset(GroundVehicleFlag::GoingDown);
}
}
+9 -12
View File
@@ -2189,10 +2189,10 @@ PaletteID GetVehiclePalette(const Vehicle *v)
void Vehicle::DeleteUnreachedImplicitOrders()
{
if (this->IsGroundVehicle()) {
uint16_t &gv_flags = this->GetGroundVehicleFlags();
if (HasBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)) {
GroundVehicleFlags &gv_flags = this->GetGroundVehicleFlags();
if (gv_flags.Test(GroundVehicleFlag::SuppressImplicitOrders)) {
/* Do not delete orders, only skip them */
ClrBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
gv_flags.Reset(GroundVehicleFlag::SuppressImplicitOrders);
this->cur_implicit_order_index = this->cur_real_order_index;
InvalidateVehicleOrder(this, 0);
return;
@@ -2253,7 +2253,7 @@ void Vehicle::BeginLoading()
if (this->IsGroundVehicle() &&
(in_list == nullptr || !in_list->IsType(OT_IMPLICIT) ||
in_list->GetDestination() != this->last_station_visited)) {
bool suppress_implicit_orders = HasBit(this->GetGroundVehicleFlags(), GVF_SUPPRESS_IMPLICIT_ORDERS);
bool suppress_implicit_orders = this->GetGroundVehicleFlags().Test(GroundVehicleFlag::SuppressImplicitOrders);
/* Do not create consecutive duplicates of implicit orders */
const Order *prev_order = this->cur_implicit_order_index > 0 ? this->GetOrder(this->cur_implicit_order_index - 1) : (this->GetNumOrders() > 1 ? this->GetLastOrder() : nullptr);
if (prev_order == nullptr ||
@@ -2320,8 +2320,7 @@ void Vehicle::BeginLoading()
/* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
* Reenable it for this vehicle */
uint16_t &gv_flags = this->GetGroundVehicleFlags();
ClrBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
this->GetGroundVehicleFlags().Reset(GroundVehicleFlag::SuppressImplicitOrders);
}
}
}
@@ -2631,8 +2630,7 @@ CommandCost Vehicle::SendToDepot(DoCommandFlags flags, DepotCommandFlags command
if (this->current_order.GetDepotOrderType().Test(OrderDepotTypeFlag::PartOfOrders)) this->IncrementRealOrderIndex();
if (this->IsGroundVehicle()) {
uint16_t &gv_flags = this->GetGroundVehicleFlags();
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
this->GetGroundVehicleFlags().Set(GroundVehicleFlag::SuppressImplicitOrders);
}
this->current_order.MakeDummy();
@@ -2649,8 +2647,7 @@ CommandCost Vehicle::SendToDepot(DoCommandFlags flags, DepotCommandFlags command
if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
uint16_t &gv_flags = this->GetGroundVehicleFlags();
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
this->GetGroundVehicleFlags().Set(GroundVehicleFlag::SuppressImplicitOrders);
}
this->SetDestTile(closest_depot.location);
@@ -3238,7 +3235,7 @@ const GroundVehicleCache *Vehicle::GetGroundVehicleCache() const
* @pre The vehicle is a #GroundVehicle.
* @return #GroundVehicleFlags of the vehicle.
*/
uint16_t &Vehicle::GetGroundVehicleFlags()
GroundVehicleFlags &Vehicle::GetGroundVehicleFlags()
{
assert(this->IsGroundVehicle());
if (this->type == VehicleType::Train) {
@@ -3253,7 +3250,7 @@ uint16_t &Vehicle::GetGroundVehicleFlags()
* @pre The vehicle is a #GroundVehicle.
* @return #GroundVehicleFlags of the vehicle.
*/
const uint16_t &Vehicle::GetGroundVehicleFlags() const
const GroundVehicleFlags &Vehicle::GetGroundVehicleFlags() const
{
assert(this->IsGroundVehicle());
if (this->type == VehicleType::Train) {
+2 -2
View File
@@ -337,8 +337,8 @@ public:
GroundVehicleCache *GetGroundVehicleCache();
const GroundVehicleCache *GetGroundVehicleCache() const;
uint16_t &GetGroundVehicleFlags();
const uint16_t &GetGroundVehicleFlags() const;
GroundVehicleFlags &GetGroundVehicleFlags();
const GroundVehicleFlags &GetGroundVehicleFlags() const;
void DeleteUnreachedImplicitOrders();
+10
View File
@@ -102,4 +102,14 @@ using VehicleRandomTriggers = EnumBitSet<VehicleRandomTrigger, uint8_t>;
template <typename T, VehicleType Tend = VehicleType::CompanyEnd>
using VehicleTypeIndexArray = EnumIndexArray<T, VehicleType, Tend>;
/** Ground vehicle flags. */
enum class GroundVehicleFlag : uint8_t {
GoingUp = 0, ///< Vehicle is currently going uphill. (Cached track information for acceleration)
GoingDown = 1, ///< Vehicle is currently going downhill. (Cached track information for acceleration)
SuppressImplicitOrders = 2, ///< Disable insertion and removal of automatic orders until the vehicle completes the real order.
};
/** Bitset of \c GroundVehicleFlag elements. */
using GroundVehicleFlags = EnumBitSet<GroundVehicleFlag, uint16_t>;
#endif /* VEHICLE_TYPE_H */