Codechange: make Track a scoped enum and TrackBits an EnumBitSet (#15684)

Helper methods to convert Track to TrackBits are removed as they are no longer necessary.
This commit is contained in:
Peter Nelson
2026-06-08 23:05:51 +01:00
committed by GitHub
parent 7e2bcaf792
commit c9cf141813
42 changed files with 607 additions and 687 deletions
+1 -1
View File
@@ -485,7 +485,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
* because of different owner of crossing and approaching train */
for (const auto tile : Map::Iterate()) {
if (IsTileType(tile, TileType::Railway) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
for (Track track : SetTrackBitIterator(GetTrackBits(tile))) {
for (Track track : GetTrackBits(tile)) {
if (IsSignalPresent(tile, SignalOnTrack(track))) AddTrackToSignalBuffer(tile, track, new_owner);
}
} else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
+40 -39
View File
@@ -87,35 +87,36 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override
{
switch (GetTileType(t)) {
case TileType::Railway:
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return {};
switch (GetRailTileType(t)) {
case RailTileType::Normal: case RailTileType::Signals:
case RailTileType::Normal:
case RailTileType::Signals:
return GetTrackBits(t);
default:
return TRACK_BIT_NONE;
return {};
}
break;
case TileType::TunnelBridge:
if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return {};
if (!HasRailCatenary(GetRailType(t))) return {};
if (override != nullptr && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
*override = GetTunnelBridgeDirection(t);
}
return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t));
return DiagDirToDiagTrack(GetTunnelBridgeDirection(t));
case TileType::Road:
if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
return GetCrossingRailBits(t);
if (!IsLevelCrossing(t)) return {};
if (!HasRailCatenary(GetRailType(t))) return {};
return GetCrossingRailTrack(t);
case TileType::Station:
if (!HasStationRail(t)) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
return TrackToTrackBits(GetRailStationTrack(t));
if (!HasStationRail(t)) return {};
if (!HasRailCatenary(GetRailType(t))) return {};
return GetRailStationTrack(t);
default:
return TRACK_BIT_NONE;
return {};
}
}
@@ -128,7 +129,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override
static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
{
/* Single track bits are never masked out. */
if (HasAtMostOneBit(tracks)) [[likely]] return tracks;
if (tracks.Count() <= 1) [[likely]] return tracks;
if (!IsPlainRailTile(t)) return tracks;
@@ -141,7 +142,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
TileIndex next_tile = TileAddByDiagDir(t, d);
RailType rt = GetTileRailType(next_tile);
if (rt == INVALID_RAILTYPE || !HasRailCatenary(rt) ||
((TrackdirBitsToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & DiagdirReachesTracks(d)) == TRACK_BIT_NONE &&
(!TrackdirBitsToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Any(DiagdirReachesTracks(d)) &&
(!HasStationTileRail(next_tile) || GetRailStationAxis(next_tile) != DiagDirToAxis(d) || !CanStationTileHaveWires(next_tile)))) {
neighbour_tdb |= DiagdirReachesTrackdirs(ReverseDiagDir(d));
}
@@ -154,24 +155,24 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
if (tracks == TRACK_BIT_CROSS || !TracksOverlap(tracks)) {
/* If the tracks form either a diagonal crossing or don't overlap, both
* trackdirs have to be marked to mask the corresponding track bit. */
mask = ~(TrackBits)((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_MASK);
mask = static_cast<TrackBits>(~((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_ALL.base()));
/* If that results in no masked tracks and it is not a diagonal crossing,
* require only one marked trackdir to mask. */
if (tracks != TRACK_BIT_CROSS && (mask & TRACK_BIT_MASK) == TRACK_BIT_MASK) mask = ~TrackdirBitsToTrackBits(neighbour_tdb);
if (tracks != TRACK_BIT_CROSS && mask == TRACK_BIT_ALL) mask = TrackdirBitsToTrackBits(neighbour_tdb).Flip(TRACK_BIT_ALL);
} else {
/* Require only one marked trackdir to mask the track. */
mask = ~TrackdirBitsToTrackBits(neighbour_tdb);
mask = TrackdirBitsToTrackBits(neighbour_tdb).Flip(TRACK_BIT_ALL);
/* If that results in an empty set, require both trackdirs for diagonal track. */
if ((tracks & mask) == TRACK_BIT_NONE) {
if ((neighbour_tdb & TRACKDIR_BIT_X_NE) == 0 || (neighbour_tdb & TRACKDIR_BIT_X_SW) == 0) mask |= TRACK_BIT_X;
if ((neighbour_tdb & TRACKDIR_BIT_Y_NW) == 0 || (neighbour_tdb & TRACKDIR_BIT_Y_SE) == 0) mask |= TRACK_BIT_Y;
if (!tracks.Any(mask)) {
if ((neighbour_tdb & TRACKDIR_BIT_X_NE) == 0 || (neighbour_tdb & TRACKDIR_BIT_X_SW) == 0) mask.Set(Track::X);
if ((neighbour_tdb & TRACKDIR_BIT_Y_NW) == 0 || (neighbour_tdb & TRACKDIR_BIT_Y_SE) == 0) mask.Set(Track::Y);
/* If that still is not enough, require both trackdirs for any track. */
if ((tracks & mask) == TRACK_BIT_NONE) mask = ~(TrackBits)((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_MASK);
if (!tracks.Any(mask)) mask = static_cast<TrackBits>(~((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_ALL.base()));
}
}
/* Mask the tracks only if at least one track bit would remain. */
return (tracks & mask) != TRACK_BIT_NONE ? tracks & mask : tracks;
return !tracks.Any(mask) ? tracks & mask : tracks;
}
/**
@@ -302,7 +303,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
track_config[TileSource::Home] = GetRailTrackBitsUniversal(ti->tile, &override_pcp);
wire_config[TileSource::Home] = MaskWireBits(ti->tile, track_config[TileSource::Home]);
/* If a track bit is present that is not in the main direction, the track is level */
is_flat[TileSource::Home] = ((track_config[TileSource::Home] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
is_flat[TileSource::Home] = track_config[TileSource::Home].Any({Track::Upper, Track::Lower, Track::Left, Track::Right});
AdjustTileh(ti->tile, &tileh[TileSource::Home]);
@@ -319,16 +320,16 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
tileh[TileSource::Neighbour] = GetTileSlope(neighbour);
track_config[TileSource::Neighbour] = GetRailTrackBitsUniversal(neighbour, nullptr);
wire_config[TileSource::Neighbour] = MaskWireBits(neighbour, track_config[TileSource::Neighbour]);
if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = TRACK_BIT_NONE;
if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = {};
/* Ignore station tiles that allow neither wires nor pylons. */
if (HasStationTileRail(neighbour) && !CanStationTileHavePylons(neighbour) && !CanStationTileHaveWires(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = TRACK_BIT_NONE;
if (HasStationTileRail(neighbour) && !CanStationTileHavePylons(neighbour) && !CanStationTileHaveWires(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = {};
/* If the neighboured tile does not smoothly connect to the current tile (because of a foundation),
* we have to draw all pillars on the current tile. */
if (elevation != GetPCPElevation(neighbour, ReverseDiagDir(i))) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = TRACK_BIT_NONE;
if (elevation != GetPCPElevation(neighbour, ReverseDiagDir(i))) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = {};
is_flat[TileSource::Neighbour] = ((track_config[TileSource::Neighbour] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
is_flat[TileSource::Neighbour] = track_config[TileSource::Neighbour].Any({Track::Upper, Track::Lower, Track::Left, Track::Right});
ppp_preferred[i] = DIRECTIONS_ALL; // We start with preferring everything (end-of-line in any direction)
ppp_allowed[i] = _allowed_ppp_on_pcp[i];
@@ -346,7 +347,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
/* We check whether the track in question (k) is present in the tile
* (TrackSourceTile) */
DiagDirection pcp_pos = i;
if (HasBit(wire_config[_track_source_tile[i][k]], _tracks_at_pcp[i][k])) {
if (wire_config[_track_source_tile[i][k]].Test(_tracks_at_pcp[i][k])) {
/* track found, if track is in the neighbour tile, adjust the number
* of the PCP for preferred/allowed determination*/
pcp_pos = (_track_source_tile[i][k] == TileSource::Home) ? i : ReverseDiagDir(i);
@@ -354,7 +355,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
ppp_preferred[i] &= _preferred_ppp_of_track_at_pcp[_tracks_at_pcp[i][k]][pcp_pos];
}
if (HasBit(track_config[_track_source_tile[i][k]], _tracks_at_pcp[i][k])) {
if (track_config[_track_source_tile[i][k]].Test(_tracks_at_pcp[i][k])) {
ppp_allowed[i].Reset(_disallowed_ppp_of_track_at_pcp[_tracks_at_pcp[i][k]][pcp_pos]);
}
}
@@ -371,7 +372,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
if (IsTileType(neighbour, TileType::Station) || IsTileType(neighbour, TileType::Road)) tileh[TileSource::Neighbour] = SLOPE_FLAT;
/* Read the foundations if they are present, and adjust the tileh */
if (track_config[TileSource::Neighbour] != TRACK_BIT_NONE && IsTileType(neighbour, TileType::Railway) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TileSource::Neighbour], track_config[TileSource::Neighbour]);
if (track_config[TileSource::Neighbour].Any() && IsTileType(neighbour, TileType::Railway) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TileSource::Neighbour], track_config[TileSource::Neighbour]);
if (IsBridgeTile(neighbour)) {
foundation = GetBridgeFoundation(tileh[TileSource::Neighbour], DiagDirToAxis(GetTunnelBridgeDirection(neighbour)));
}
@@ -423,7 +424,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
/* Don't build the pylon if it would be outside the tile */
if (!_owned_ppp_on_pcp[i].Test(temp)) {
/* We have a neighbour that will draw it, bail out */
if (track_config[TileSource::Neighbour] != TRACK_BIT_NONE) break;
if (track_config[TileSource::Neighbour].Any()) break;
continue; // No neighbour, go looking for a better position
}
@@ -453,15 +454,15 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
SpriteID wire_halftile = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, TCX_UPPER_HALFTILE) : wire_normal;
Track halftile_track;
switch (halftile_corner) {
case CORNER_W: halftile_track = TRACK_LEFT; break;
case CORNER_S: halftile_track = TRACK_LOWER; break;
case CORNER_E: halftile_track = TRACK_RIGHT; break;
case CORNER_N: halftile_track = TRACK_UPPER; break;
default: halftile_track = INVALID_TRACK; break;
case CORNER_W: halftile_track = Track::Left; break;
case CORNER_S: halftile_track = Track::Lower; break;
case CORNER_E: halftile_track = Track::Right; break;
case CORNER_N: halftile_track = Track::Upper; break;
default: halftile_track = Track::Invalid; break;
}
/* Drawing of pylons is finished, now draw the wires */
for (Track t : SetTrackBitIterator(wire_config[TileSource::Home])) {
for (Track t : wire_config[TileSource::Home]) {
SpriteID wire_base = (t == halftile_track) ? wire_halftile : wire_normal;
uint8_t pcp_config = pcp_status.Test(_pcp_positions[t][0]) +
(pcp_status.Test(_pcp_positions[t][1]) << 1);
@@ -469,7 +470,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
assert(pcp_config != 0); // We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that)
assert(!IsSteepSlope(tileh[TileSource::Home]));
const SortableSpriteStruct &sss = _rail_catenary_sprite_data[_rail_wires[tileh_selector][t][pcp_config]];
const SortableSpriteStruct &sss = _rail_catenary_sprite_data[_rail_wires[tileh_selector][to_underlying(t)][pcp_config]];
/*
* The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE.
+2 -2
View File
@@ -920,7 +920,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
case VehicleType::Train: {
Train *t = Train::From(v);
switch (variable - 0x80) {
case 0x62: return t->track;
case 0x62: return t->track.base();
case 0x66: return t->railtypes.GetNthSetBit(0).value_or(RailType::INVALID_RAILTYPE);
case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length;
case 0x74: return t->gcache.cached_power;
@@ -951,7 +951,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
case VehicleType::Ship: {
Ship *s = Ship::From(v);
switch (variable - 0x80) {
case 0x62: return s->state;
case 0x62: return s->state.base();
}
break;
}
+2 -2
View File
@@ -222,7 +222,7 @@ static uint32_t GetRailContinuationInfo(TileIndex tile)
for (i = 0; i < lengthof(x_dir); i++, dir++, diagdir++) {
TileIndex neighbour_tile = tile + TileOffsByDir(*dir);
TrackBits trackbits = TrackdirBitsToTrackBits(GetTileTrackStatus(neighbour_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs);
if (trackbits != TRACK_BIT_NONE) {
if (trackbits.Any()) {
/* If there is any track on the tile, set the bit in the second byte */
SetBit(res, i + 8);
@@ -233,7 +233,7 @@ static uint32_t GetRailContinuationInfo(TileIndex tile)
}
/* If any track reaches our exit direction, set the bit in the lower byte */
if (trackbits & DiagdirReachesTracks(*diagdir)) SetBit(res, i);
if (trackbits.Any(DiagdirReachesTracks(*diagdir))) SetBit(res, i);
}
}
+2 -2
View File
@@ -194,8 +194,8 @@ struct CFollowTrackT {
/* Mask already reserved trackdirs. */
this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
/* Mask out all trackdirs that conflict with the reservation. */
for (Track t : SetTrackBitIterator(TrackdirBitsToTrackBits(this->new_td_bits))) {
if (TracksOverlap(reserved | TrackToTrackBits(t))) this->new_td_bits &= ~TrackToTrackdirBits(t);
for (Track t : TrackdirBitsToTrackBits(this->new_td_bits)) {
if (TracksOverlap(reserved | t)) this->new_td_bits &= ~TrackToTrackdirBits(t);
}
if (this->new_td_bits == TRACKDIR_BIT_NONE) {
this->err = EC_RESERVED;
+1 -1
View File
@@ -23,7 +23,7 @@
* @param tile the tile to find the path from (should be next tile the ship is about to enter)
* @param path_found [out] Whether a path has been found (true) or has been guessed (false)
* @param path_cache Cache of a previously chosen path.
* @return the best trackdir for next turn or INVALID_TRACK if the path could not be found
* @return the best trackdir for next turn or Track::Invalid if the path could not be found
*/
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache);
+2 -2
View File
@@ -119,8 +119,8 @@ public:
inline int SwitchCost(TileIndex tile1, TileIndex tile2, DiagDirection exitdir)
{
if (IsPlainRailTile(tile1) && IsPlainRailTile(tile2)) {
bool t1 = KillFirstBit(GetTrackBits(tile1) & DiagdirReachesTracks(ReverseDiagDir(exitdir))) != TRACK_BIT_NONE;
bool t2 = KillFirstBit(GetTrackBits(tile2) & DiagdirReachesTracks(exitdir)) != TRACK_BIT_NONE;
bool t1 = (GetTrackBits(tile1) & DiagdirReachesTracks(ReverseDiagDir(exitdir))).Count() > 1;
bool t2 = (GetTrackBits(tile2) & DiagdirReachesTracks(exitdir)).Count() > 1;
if (t1 && t2) return Yapf().PfGetSettings().rail_doubleslip_penalty;
}
return 0;
+3 -3
View File
@@ -227,7 +227,7 @@ public:
if (target != nullptr) target->okay = true;
if (Yapf().CanUseGlobalCache(*this->res_dest_node)) {
YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
YapfNotifyTrackLayoutChange(INVALID_TILE, Track::Invalid);
}
return true;
@@ -628,7 +628,7 @@ bool YapfTrainCheckReverse(const Train *v)
}
}
if (moving_front->track == TRACK_BIT_WORMHOLE) {
if (moving_front->track == Track::Wormhole) {
/* front in tunnel / on bridge */
DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile);
@@ -643,7 +643,7 @@ bool YapfTrainCheckReverse(const Train *v)
reverse_penalty -= DistanceManhattan(cur_tile, tile) * YAPF_TILE_LENGTH;
}
if (moving_back->track == TRACK_BIT_WORMHOLE) {
if (moving_back->track == Track::Wormhole) {
/* back in tunnel / on bridge */
DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile_rev);
+2 -2
View File
@@ -165,7 +165,7 @@ public:
}
/**
* Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/INVALID_TRACK if none is available.
* Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/Track::Invalid if none is available.
* @param v The ship to get the direction for.
* @param tile The start tile.
* @param dir the start direction.
@@ -440,7 +440,7 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipP
Trackdir best_origin_dir = INVALID_TRACKDIR;
const TrackdirBits origin_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, path_found, path_cache, best_origin_dir);
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : Track::Invalid;
}
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
+9 -9
View File
@@ -18,7 +18,7 @@
/**
* Get the reserved trackbits for any tile, regardless of type.
* @param t the tile
* @return the reserved trackbits. TRACK_BIT_NONE on nothing reserved or
* @return the reserved trackbits, or empty on nothing reserved or
* a tile without rail.
*/
TrackBits GetReservedTrackbits(TileIndex t)
@@ -44,7 +44,7 @@ TrackBits GetReservedTrackbits(TileIndex t)
default:
break;
}
return TRACK_BIT_NONE;
return {};
}
/**
@@ -79,7 +79,7 @@ void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool
*/
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
{
assert(HasTrack(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs), t));
assert(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Test(t));
if (_settings_client.gui.show_track_reservation) {
/* show the reserved rail if needed */
@@ -124,7 +124,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
break;
case TileType::TunnelBridge:
if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && !GetTunnelBridgeReservationTrackBits(tile)) {
if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && GetTunnelBridgeReservationTrackBits(tile).None()) {
SetTunnelBridgeReservation(tile, true);
return true;
}
@@ -143,7 +143,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
*/
void UnreserveRailTrack(TileIndex tile, Track t)
{
assert(HasTrack(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs), t));
assert(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Test(t));
if (_settings_client.gui.show_track_reservation) {
if (IsBridgeTile(tile)) {
@@ -205,7 +205,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
/* Start track not reserved? This can happen if two trains
* are on the same tile. The reservation on the next tile
* is not ours in this case, so exit. */
if (!HasReservedTracks(tile, TrackToTrackBits(TrackdirToTrack(trackdir)))) return PBSTileInfo(tile, trackdir, false);
if (!HasReservedTracks(tile, TrackdirToTrack(trackdir))) return PBSTileInfo(tile, trackdir, false);
/* Do not disallow 90 deg turns as the setting might have changed between reserving and now. */
CFollowTrackRail ft(o, rts);
@@ -282,7 +282,7 @@ static void CheckTrainsOnTrack(FindTrainOnTrackInfo &info, TileIndex tile)
if (v->type != VehicleType::Train || v->vehstatus.Test(VehState::Crashed)) continue;
Train *t = Train::From(v);
if (t->track == TRACK_BIT_WORMHOLE || HasBit(static_cast<TrackBits>(t->track), TrackdirToTrack(info.res.trackdir))) {
if (t->track == Track::Wormhole || t->track.Test(TrackdirToTrack(info.res.trackdir))) {
t = t->First();
/* ALWAYS return the lowest ID (anti-desync!) */
@@ -307,7 +307,7 @@ PBSTileInfo FollowTrainReservation(const Train *consist, Vehicle **train_on_res)
TileIndex tile = moving_front->tile;
Trackdir trackdir = moving_front->GetVehicleTrackdir();
if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) return PBSTileInfo(tile, trackdir, false);
if (IsRailDepotTile(tile) && GetDepotReservationTrackBits(tile).None()) return PBSTileInfo(tile, trackdir, false);
FindTrainOnTrackInfo ftoti;
ftoti.res = FollowReservation(consist->owner, GetAllCompatibleRailTypes(consist->railtypes), tile, trackdir);
@@ -344,7 +344,7 @@ PBSTileInfo FollowTrainReservation(const Train *consist, Vehicle **train_on_res)
*/
Train *GetTrainForReservation(TileIndex tile, Track track)
{
assert(HasReservedTracks(tile, TrackToTrackBits(track)));
assert(HasReservedTracks(tile, track));
Trackdir trackdir = TrackToTrackdir(track);
RailTypes rts = GetRailTypeInfo(GetTileRailType(tile))->compatible_railtypes;
+1 -1
View File
@@ -57,7 +57,7 @@ Train *GetTrainForReservation(TileIndex tile, Track track);
*/
inline bool HasReservedTracks(TileIndex tile, TrackBits tracks)
{
return (GetReservedTrackbits(tile) & tracks) != TRACK_BIT_NONE;
return GetReservedTrackbits(tile).Any(tracks);
}
#endif /* PBS_H */
+1 -1
View File
@@ -452,7 +452,7 @@ inline Money RailClearCost(RailType railtype)
* Calculates the cost of rail conversion
* @param from The railtype we are converting from
* @param to The railtype we are converting to
* @return Cost per TrackBit
* @return Cost per Track
*/
inline Money RailConvertCost(RailType from, RailType to)
{
+219 -217
View File
@@ -227,8 +227,7 @@ static const uint8_t _track_sloped_sprites[14] = {
*/
static CommandCost EnsureNoTrainOnTrack(TileIndex tile, Track track)
{
TrackBits rail_bits = TrackToTrackBits(track);
return EnsureNoTrainOnTrackBits(tile, rail_bits);
return EnsureNoTrainOnTrackBits(tile, track);
}
/**
@@ -260,45 +259,45 @@ static CommandCost CheckTrackCombination(TileIndex tile, TrackBits to_build)
/** Valid TrackBits on a specific (non-steep)-slope without foundation */
static const TrackBits _valid_tracks_without_foundation[15] = {
TRACK_BIT_ALL,
TRACK_BIT_RIGHT,
TRACK_BIT_UPPER,
TRACK_BIT_X,
Track::Right,
Track::Upper,
Track::X,
TRACK_BIT_LEFT,
TRACK_BIT_NONE,
TRACK_BIT_Y,
TRACK_BIT_LOWER,
Track::Left,
{},
Track::Y,
Track::Lower,
TRACK_BIT_LOWER,
TRACK_BIT_Y,
TRACK_BIT_NONE,
TRACK_BIT_LEFT,
Track::Lower,
Track::Y,
{},
Track::Left,
TRACK_BIT_X,
TRACK_BIT_UPPER,
TRACK_BIT_RIGHT,
Track::X,
Track::Upper,
Track::Right,
};
/** Valid TrackBits on a specific (non-steep)-slope with leveled foundation */
static const TrackBits _valid_tracks_on_leveled_foundation[15] = {
TRACK_BIT_NONE,
TRACK_BIT_LEFT,
TRACK_BIT_LOWER,
TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_LEFT,
{},
Track::Left,
Track::Lower,
{Track::Y, Track::Lower, Track::Left},
TRACK_BIT_RIGHT,
Track::Right,
TRACK_BIT_ALL,
TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_RIGHT,
{Track::X, Track::Lower, Track::Right},
TRACK_BIT_ALL,
TRACK_BIT_UPPER,
TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_LEFT,
Track::Upper,
{Track::X, Track::Upper, Track::Left},
TRACK_BIT_ALL,
TRACK_BIT_ALL,
TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_RIGHT,
{Track::Y, Track::Upper, Track::Right},
TRACK_BIT_ALL,
TRACK_BIT_ALL,
TRACK_BIT_ALL
};
/**
@@ -310,12 +309,12 @@ static const TrackBits _valid_tracks_on_leveled_foundation[15] = {
*/
Foundation GetRailFoundation(Slope tileh, TrackBits bits)
{
if (bits == TRACK_BIT_NONE) return Foundation::None;
if (bits.None()) return Foundation::None;
if (IsSteepSlope(tileh)) {
/* Test for inclined foundations */
if (bits == TRACK_BIT_X) return Foundation::InclinedX;
if (bits == TRACK_BIT_Y) return Foundation::InclinedY;
if (bits == Track::X) return Foundation::InclinedX;
if (bits == Track::Y) return Foundation::InclinedY;
/* Get higher track */
Corner highest_corner = GetHighestSlopeCorner(tileh);
@@ -328,34 +327,34 @@ Foundation GetRailFoundation(Slope tileh, TrackBits bits)
if (TracksOverlap(bits | higher_track)) return Foundation::Invalid;
/* either lower track or both higher and lower track */
return ((bits & higher_track) != 0 ? Foundation::SteepBoth : Foundation::SteepLower);
return bits.Any(higher_track) ? Foundation::SteepBoth : Foundation::SteepLower;
} else {
if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return Foundation::None;
if (TrackBits{bits}.Reset(_valid_tracks_without_foundation[tileh]).None()) return Foundation::None;
bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
bool valid_on_leveled = TrackBits{bits}.Reset(_valid_tracks_on_leveled_foundation[tileh]).None();
Corner track_corner;
switch (bits) {
case TRACK_BIT_LEFT: track_corner = CORNER_W; break;
case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
switch (bits.base()) {
case TrackBits{Track::Left}.base(): track_corner = CORNER_W; break;
case TrackBits{Track::Lower}.base(): track_corner = CORNER_S; break;
case TrackBits{Track::Right}.base(): track_corner = CORNER_E; break;
case TrackBits{Track::Upper}.base(): track_corner = CORNER_N; break;
case TRACK_BIT_HORZ:
case TRACK_BIT_HORZ.base():
if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N);
if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S);
return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid);
case TRACK_BIT_VERT:
case TRACK_BIT_VERT.base():
if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W);
if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E);
return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid);
case TRACK_BIT_X:
case TrackBits{Track::X}.base():
if (IsSlopeWithOneCornerRaised(tileh)) return Foundation::InclinedX;
return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid);
case TRACK_BIT_Y:
case TrackBits{Track::Y}.base():
if (IsSlopeWithOneCornerRaised(tileh)) return Foundation::InclinedY;
return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid);
@@ -392,10 +391,10 @@ static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits ex
{
/* don't allow building on the lower side of a coast */
if (GetFloodingBehaviour(tile) != FloodingBehaviour::None) {
if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
if (!IsSteepSlope(tileh) && TrackBits{rail_bits}.Set(existing).Reset(_valid_tracks_on_leveled_foundation[tileh]).Any()) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
}
Foundation f_new = GetRailFoundation(tileh, rail_bits | existing);
Foundation f_new = GetRailFoundation(tileh, TrackBits{rail_bits}.Set(existing));
/* check track/slope combination */
if ((f_new == Foundation::Invalid) ||
@@ -429,7 +428,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
if (!ValParamRailType(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
Slope tileh = GetTileSlope(tile);
TrackBits trackbit = TrackToTrackBits(track);
TrackBits trackbit = track;
switch (GetTileType(tile)) {
case TileType::Railway: {
@@ -448,13 +447,13 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
if (HasSignals(tile) && TracksOverlap(GetTrackBits(tile) | TrackToTrackBits(track))) {
if (HasSignals(tile) && TracksOverlap(GetTrackBits(tile) | track)) {
/* If adding the new track causes any overlap, all signals must be removed first */
if (!auto_remove_signals) return CommandCost(STR_ERROR_MUST_REMOVE_SIGNALS_FIRST);
for (Track track_it = TRACK_BEGIN; track_it < TRACK_END; track_it++) {
if (HasTrack(tile, track_it) && HasSignalOnTrack(tile, track_it)) {
CommandCost ret_remove_signals = Command<Commands::RemoveSignal>::Do(flags, tile, track_it);
for (Track existing_track : GetTrackBits(tile)) {
if (HasSignalOnTrack(tile, existing_track)) {
CommandCost ret_remove_signals = Command<Commands::RemoveSignal>::Do(flags, tile, existing_track);
if (ret_remove_signals.Failed()) return ret_remove_signals;
cost.AddCost(ret_remove_signals.GetCost());
}
@@ -479,11 +478,11 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
TrackBits bits = GetTrackBits(tile);
SetTrackBits(tile, bits | trackbit);
/* Subtract old infrastructure count. */
uint pieces = CountBits(bits);
uint pieces = bits.Count();
if (TracksOverlap(bits)) pieces *= pieces;
Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] -= pieces;
/* Add new infrastructure count. */
pieces = CountBits(bits | trackbit);
pieces = (bits | trackbit).Count();
if (TracksOverlap(bits | trackbit)) pieces *= pieces;
Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] += pieces;
DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
@@ -518,8 +517,8 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
RoadBits road = GetRoadBits(tile, RoadTramType::Road);
RoadBits tram = GetRoadBits(tile, RoadTramType::Tram);
if ((track == TRACK_X && !(road | tram).Any(ROAD_X)) ||
(track == TRACK_Y && !(road | tram).Any(ROAD_Y))) {
if ((track == Track::X && !(road | tram).Any(ROAD_X)) ||
(track == Track::Y && !(road | tram).Any(ROAD_Y))) {
Owner road_owner = GetRoadOwner(tile, RoadTramType::Road);
Owner tram_owner = GetRoadOwner(tile, RoadTramType::Tram);
/* Disallow breaking end-of-line of someone else
@@ -540,7 +539,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
}
if (flags.Test(DoCommandFlag::Execute)) {
MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? Axis::Y : Axis::X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile));
MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == Track::X ? Axis::Y : Axis::X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile));
UpdateLevelCrossing(tile, false);
MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile));
Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR;
@@ -558,7 +557,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
}
}
if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) {
if (IsLevelCrossing(tile) && GetCrossingRailTrack(tile) == trackbit) {
return CommandCost(STR_ERROR_ALREADY_BUILT);
}
[[fallthrough]];
@@ -568,7 +567,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra
/* Will there be flat water on the lower halftile? */
bool water_ground = IsTileType(tile, TileType::Water) && IsSlopeWithOneCornerRaised(tileh);
CommandCost ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile);
CommandCost ret = CheckRailSlope(tileh, trackbit, {}, tile);
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
@@ -617,7 +616,6 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
bool crossing = false;
if (!ValParamTrackOrientation(track)) return CMD_ERROR;
TrackBits trackbit = TrackToTrackBits(track);
/* Need to read tile owner now because it may change when the rail is removed
* Also, in case of floods, _current_company != owner
@@ -629,7 +627,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
switch (GetTileType(tile)) {
case TileType::Road: {
if (!IsLevelCrossing(tile) || GetCrossingRailBits(tile) != trackbit) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
if (!IsLevelCrossing(tile) || GetCrossingRailTrack(tile) != track) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
if (_current_company != OWNER_WATER) {
CommandCost ret = CheckTileOwnership(tile);
@@ -646,7 +644,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
if (flags.Test(DoCommandFlag::Execute)) {
UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(tile, GetCrossingRoadAxis(tile));
if (HasReservedTracks(tile, trackbit)) {
if (HasReservedTracks(tile, track)) {
v = GetTrainForReservation(tile, track);
if (v != nullptr) FreeTrainTrackReservation(v);
}
@@ -674,8 +672,8 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
if (ret.Failed()) return ret;
present = GetTrackBits(tile);
if ((present & trackbit) == 0) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
if (present == (TRACK_BIT_X | TRACK_BIT_Y)) crossing = true;
if (!present.Test(track)) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
if (present == TRACK_BIT_CROSS) crossing = true;
cost.AddCost(RailClearCost(GetRailType(tile)));
@@ -685,7 +683,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
}
if (flags.Test(DoCommandFlag::Execute)) {
if (HasReservedTracks(tile, trackbit)) {
if (HasReservedTracks(tile, track)) {
v = GetTrainForReservation(tile, track);
if (v != nullptr) FreeTrainTrackReservation(v);
}
@@ -693,17 +691,17 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
owner = GetTileOwner(tile);
/* Subtract old infrastructure count. */
uint pieces = CountBits(present);
uint pieces = present.Count();
if (TracksOverlap(present)) pieces *= pieces;
Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= pieces;
/* Add new infrastructure count. */
present ^= trackbit;
pieces = CountBits(present);
present.Flip(track);
pieces = present.Count();
if (TracksOverlap(present)) pieces *= pieces;
Company::Get(owner)->infrastructure.rail[GetRailType(tile)] += pieces;
DirtyCompanyInfrastructureWindows(owner);
if (present == 0) {
if (present.None()) {
Slope tileh = GetTileSlope(tile);
/* If there is flat water on the lower halftile, convert the tile to shore so the water remains */
if (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh)) {
@@ -735,10 +733,10 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac
* are removing one of these pieces, we'll need to update signals for
* both directions explicitly, as after the track is removed it won't
* 'connect' with the other piece. */
AddTrackToSignalBuffer(tile, TRACK_X, owner);
AddTrackToSignalBuffer(tile, TRACK_Y, owner);
YapfNotifyTrackLayoutChange(tile, TRACK_X);
YapfNotifyTrackLayoutChange(tile, TRACK_Y);
AddTrackToSignalBuffer(tile, Track::X, owner);
AddTrackToSignalBuffer(tile, Track::Y, owner);
YapfNotifyTrackLayoutChange(tile, Track::X);
YapfNotifyTrackLayoutChange(tile, Track::Y);
} else {
AddTrackToSignalBuffer(tile, track, owner);
YapfNotifyTrackLayoutChange(tile, track);
@@ -772,13 +770,13 @@ bool FloodHalftile(TileIndex t)
TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh)));
TrackBits to_remove = lower_track & rail_bits;
if (to_remove != TRACK_BIT_NONE) {
if (to_remove.Any()) {
AutoRestoreBackup cur_company(_current_company, OWNER_WATER);
flooded = Command<Commands::RemoveRail>::Do(DoCommandFlag::Execute, t, FindFirstTrack(to_remove)).Succeeded();
if (!flooded) return flooded; // not yet floodable
rail_bits = rail_bits & ~to_remove;
if (rail_bits == TRACK_BIT_NONE) {
rail_bits.Reset(to_remove);
if (rail_bits.None()) {
MakeShore(t);
MarkTileDirtyByTile(t);
return flooded;
@@ -1111,7 +1109,7 @@ CommandCost CmdBuildSingleSignal(DoCommandFlags flags, TileIndex tile, Track tra
/* The new/changed signal could block our path. As this can lead to
* stale reservations, we clear the path reservation here and try
* to redo it later on. */
if (HasReservedTracks(tile, TrackToTrackBits(track))) {
if (HasReservedTracks(tile, track)) {
v = GetTrainForReservation(tile, track);
if (v != nullptr) FreeTrainTrackReservation(v);
}
@@ -1184,12 +1182,12 @@ CommandCost CmdBuildSingleSignal(DoCommandFlags flags, TileIndex tile, Track tra
if (IsPbsSignal(sigtype)) {
/* PBS signals should show red unless they are on reserved tiles without a train. */
uint mask = GetPresentSignals(tile) & SignalOnTrack(track);
SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((HasBit(GetRailReservationTrackBits(tile), track) && EnsureNoVehicleOnGround(tile).Succeeded() ? UINT_MAX : 0) & mask));
SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((GetRailReservationTrackBits(tile).Test(track) && EnsureNoVehicleOnGround(tile).Succeeded() ? UINT_MAX : 0) & mask));
}
MarkTileDirtyByTile(tile);
AddTrackToSignalBuffer(tile, track, _current_company);
YapfNotifyTrackLayoutChange(tile, track);
if (v != nullptr && v->track != TRACK_BIT_DEPOT) {
if (v != nullptr && v->track != Track::Depot) {
Train *moving_front = v->GetMovingFront();
/* Extend the train's path if it's not stopped or loading, or not at a safe position. */
if (!((v->vehstatus.Test(VehState::Stopped) && v->cur_speed == 0) || v->current_order.IsType(OT_LOADING)) ||
@@ -1482,7 +1480,7 @@ CommandCost CmdRemoveSingleSignal(DoCommandFlags flags, TileIndex tile, Track tr
/* Do it? */
if (flags.Test(DoCommandFlag::Execute)) {
Train *v = nullptr;
if (HasReservedTracks(tile, TrackToTrackBits(track))) {
if (HasReservedTracks(tile, track)) {
v = GetTrainForReservation(tile, track);
} else if (IsPbsSignal(GetSignalType(tile, track))) {
/* PBS signal, might be the end of a path reservation. */
@@ -1506,7 +1504,7 @@ CommandCost CmdRemoveSingleSignal(DoCommandFlags flags, TileIndex tile, Track tr
if (GetPresentSignals(tile) == 0) {
SetSignalStates(tile, 0);
SetHasSignals(tile, false);
SetSignalVariant(tile, INVALID_TRACK, SignalVariant::Electric); // remove any possible semaphores
SetSignalVariant(tile, Track::Invalid, SignalVariant::Electric); // remove any possible semaphores
}
AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
@@ -1608,7 +1606,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_
}
}
if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too
for (Track track : SetTrackBitIterator(GetReservedTrackbits(tile))) {
for (Track track : GetReservedTrackbits(tile)) {
Train *v = GetTrainForReservation(tile, track);
if (v != nullptr && !HasPowerOnRail(v->railtypes, totype)) {
/* No power on new rail type, reroute. */
@@ -1623,7 +1621,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_
uint num_pieces = IsLevelCrossingTile(tile) ? LEVELCROSSING_TRACKBIT_FACTOR : 1;
if (IsPlainRailTile(tile)) {
TrackBits bits = GetTrackBits(tile);
num_pieces = CountBits(bits);
num_pieces = bits.Count();
if (TracksOverlap(bits)) num_pieces *= num_pieces;
}
c->infrastructure.rail[type] -= num_pieces;
@@ -1660,12 +1658,12 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_
default: // RailTileType::Normal, RailTileType::Signals
if (flags.Test(DoCommandFlag::Execute)) {
/* notify YAPF about the track layout change */
for (Track track : SetTrackBitIterator(GetTrackBits(tile))) {
for (Track track : GetTrackBits(tile)) {
YapfNotifyTrackLayoutChange(tile, track);
}
}
found_convertible_track = true;
cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
cost.AddCost(RailConvertCost(type, totype) * GetTrackBits(tile).Count());
break;
}
break;
@@ -1821,7 +1819,7 @@ static CommandCost ClearTile_Rail(TileIndex tile, DoCommandFlags flags)
/* Is there flat water on the lower halftile that gets cleared expensively? */
bool water_ground = (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh));
for (Track track : SetTrackBitIterator(GetTrackBits(tile))) {
for (Track track : GetTrackBits(tile)) {
CommandCost ret = Command<Commands::RemoveRail>::Do(flags, tile, track);
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
@@ -1862,10 +1860,10 @@ static CommandCost ClearTile_Rail(TileIndex tile, DoCommandFlags flags)
static uint GetSafeSlopeZ(uint x, uint y, Track track)
{
switch (track) {
case TRACK_UPPER: x &= ~0xF; y &= ~0xF; break;
case TRACK_LOWER: x |= 0xF; y |= 0xF; break;
case TRACK_LEFT: x |= 0xF; y &= ~0xF; break;
case TRACK_RIGHT: x &= ~0xF; y |= 0xF; break;
case Track::Upper: x &= ~0xF; y &= ~0xF; break;
case Track::Lower: x |= 0xF; y |= 0xF; break;
case Track::Left: x |= 0xF; y &= ~0xF; break;
case Track::Right: x &= ~0xF; y |= 0xF; break;
default: break;
}
return GetSlopePixelZ(x, y);
@@ -2088,7 +2086,7 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn
/* Save halftile corner */
halftile_corner = (f == Foundation::SteepBoth ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
/* Draw lower part first */
track &= ~CornerToTrackBits(halftile_corner);
track.Reset(CornerToTrackBits(halftile_corner));
f = (f == Foundation::SteepBoth ? Foundation::SteepLower : Foundation::None);
}
@@ -2097,7 +2095,7 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn
/* Draw ground */
if (rgt == RailGroundType::HalfTileWater) {
if (track != TRACK_BIT_NONE || IsSteepSlope(ti->tileh)) {
if (track.Any() || IsSteepSlope(ti->tileh)) {
/* three-corner-raised slope or steep slope with track on upper part */
DrawShoreTile(ti->tileh);
} else {
@@ -2121,83 +2119,87 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn
bool no_combine = ti->tileh == SLOPE_FLAT && rti->flags.Test(RailTypeFlag::NoSpriteCombine);
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RailSpriteType::Overlay);
SpriteID ground = GetCustomRailSprite(rti, ti->tile, no_combine ? RailSpriteType::GroundComplete : RailSpriteType::Ground);
TrackBits pbs = _settings_client.gui.show_track_reservation ? GetRailReservationTrackBits(ti->tile) : TRACK_BIT_NONE;
TrackBits pbs = _settings_client.gui.show_track_reservation ? GetRailReservationTrackBits(ti->tile) : TrackBits{};
if (track == TRACK_BIT_NONE) {
if (track.None()) {
/* Half-tile foundation, no track here? */
} else if (no_combine) {
/* Use trackbits as direct index from ground sprite, subtract 1
* because there is no sprite for no bits. */
DrawGroundSprite(ground + track - 1, PAL_NONE);
DrawGroundSprite(ground + track.base() - 1, PAL_NONE);
/* Draw reserved track bits */
if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N);
if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S);
if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E);
if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W);
} else if (ti->tileh == SLOPE_NW && track == TRACK_BIT_Y) {
if (pbs.Test(Track::X)) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
if (pbs.Test(Track::Y)) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
if (pbs.Test(Track::Upper)) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N);
if (pbs.Test(Track::Lower)) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S);
if (pbs.Test(Track::Right)) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E);
if (pbs.Test(Track::Left)) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W);
} else if (ti->tileh == SLOPE_NW && track == Track::Y) {
DrawGroundSprite(ground + RTO_SLOPE_NW, PAL_NONE);
if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_NW, PALETTE_CRASH);
} else if (ti->tileh == SLOPE_NE && track == TRACK_BIT_X) {
if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_NW, PALETTE_CRASH);
} else if (ti->tileh == SLOPE_NE && track == Track::X) {
DrawGroundSprite(ground + RTO_SLOPE_NE, PAL_NONE);
if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_NE, PALETTE_CRASH);
} else if (ti->tileh == SLOPE_SE && track == TRACK_BIT_Y) {
if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_NE, PALETTE_CRASH);
} else if (ti->tileh == SLOPE_SE && track == Track::Y) {
DrawGroundSprite(ground + RTO_SLOPE_SE, PAL_NONE);
if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_SE, PALETTE_CRASH);
} else if (ti->tileh == SLOPE_SW && track == TRACK_BIT_X) {
if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_SE, PALETTE_CRASH);
} else if (ti->tileh == SLOPE_SW && track == Track::X) {
DrawGroundSprite(ground + RTO_SLOPE_SW, PAL_NONE);
if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_SW, PALETTE_CRASH);
if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_SW, PALETTE_CRASH);
} else {
switch (track) {
switch (track.base()) {
/* Draw single ground sprite when not overlapping. No track overlay
* is necessary for these sprites. */
case TRACK_BIT_X: DrawGroundSprite(ground + RTO_X, PAL_NONE); break;
case TRACK_BIT_Y: DrawGroundSprite(ground + RTO_Y, PAL_NONE); break;
case TRACK_BIT_UPPER: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); break;
case TRACK_BIT_LOWER: DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break;
case TRACK_BIT_RIGHT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); break;
case TRACK_BIT_LEFT: DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break;
case TRACK_BIT_CROSS: DrawGroundSprite(ground + RTO_CROSSING_XY, PAL_NONE); break;
case TRACK_BIT_HORZ: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N);
DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break;
case TRACK_BIT_VERT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E);
DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break;
case TrackBits{Track::X}.base(): DrawGroundSprite(ground + RTO_X, PAL_NONE); break;
case TrackBits{Track::Y}.base(): DrawGroundSprite(ground + RTO_Y, PAL_NONE); break;
case TrackBits{Track::Upper}.base(): DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); break;
case TrackBits{Track::Lower}.base(): DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break;
case TrackBits{Track::Right}.base(): DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); break;
case TrackBits{Track::Left}.base(): DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break;
case TRACK_BIT_CROSS.base(): DrawGroundSprite(ground + RTO_CROSSING_XY, PAL_NONE); break;
case TRACK_BIT_HORZ.base():
DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N);
DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S);
break;
case TRACK_BIT_VERT.base():
DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E);
DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W);
break;
default:
/* We're drawing a junction tile */
if ((track & TRACK_BIT_3WAY_NE) == 0) {
if (!track.Any(TRACK_BIT_3WAY_NE)) {
DrawGroundSprite(ground + RTO_JUNCTION_SW, PAL_NONE);
} else if ((track & TRACK_BIT_3WAY_SW) == 0) {
} else if (!track.Any(TRACK_BIT_3WAY_SW)) {
DrawGroundSprite(ground + RTO_JUNCTION_NE, PAL_NONE);
} else if ((track & TRACK_BIT_3WAY_NW) == 0) {
} else if (!track.Any(TRACK_BIT_3WAY_NW)) {
DrawGroundSprite(ground + RTO_JUNCTION_SE, PAL_NONE);
} else if ((track & TRACK_BIT_3WAY_SE) == 0) {
} else if (!track.Any(TRACK_BIT_3WAY_SE)) {
DrawGroundSprite(ground + RTO_JUNCTION_NW, PAL_NONE);
} else {
DrawGroundSprite(ground + RTO_JUNCTION_NSEW, PAL_NONE);
}
/* Mask out PBS bits as we shall draw them afterwards anyway. */
track &= ~pbs;
track.Reset(pbs);
/* Draw regular track bits */
if (track & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PAL_NONE);
if (track & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PAL_NONE);
if (track & TRACK_BIT_UPPER) DrawGroundSprite(overlay + RTO_N, PAL_NONE);
if (track & TRACK_BIT_LOWER) DrawGroundSprite(overlay + RTO_S, PAL_NONE);
if (track & TRACK_BIT_RIGHT) DrawGroundSprite(overlay + RTO_E, PAL_NONE);
if (track & TRACK_BIT_LEFT) DrawGroundSprite(overlay + RTO_W, PAL_NONE);
if (track.Test(Track::X)) DrawGroundSprite(overlay + RTO_X, PAL_NONE);
if (track.Test(Track::Y)) DrawGroundSprite(overlay + RTO_Y, PAL_NONE);
if (track.Test(Track::Upper)) DrawGroundSprite(overlay + RTO_N, PAL_NONE);
if (track.Test(Track::Lower)) DrawGroundSprite(overlay + RTO_S, PAL_NONE);
if (track.Test(Track::Right)) DrawGroundSprite(overlay + RTO_E, PAL_NONE);
if (track.Test(Track::Left)) DrawGroundSprite(overlay + RTO_W, PAL_NONE);
}
/* Draw reserved track bits */
if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N);
if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S);
if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E);
if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W);
if (pbs.Test(Track::X)) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH);
if (pbs.Test(Track::Y)) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH);
if (pbs.Test(Track::Upper)) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N);
if (pbs.Test(Track::Lower)) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S);
if (pbs.Test(Track::Right)) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E);
if (pbs.Test(Track::Left)) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W);
}
if (IsValidCorner(halftile_corner)) {
@@ -2223,12 +2225,12 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn
track = CornerToTrackBits(halftile_corner);
int offset;
switch (track) {
switch (FindFirstTrack(track)) {
default: NOT_REACHED();
case TRACK_BIT_UPPER: offset = RTO_N; break;
case TRACK_BIT_LOWER: offset = RTO_S; break;
case TRACK_BIT_RIGHT: offset = RTO_E; break;
case TRACK_BIT_LEFT: offset = RTO_W; break;
case Track::Upper: offset = RTO_N; break;
case Track::Lower: offset = RTO_S; break;
case Track::Right: offset = RTO_E; break;
case Track::Left: offset = RTO_W; break;
}
DrawTrackSprite(ground + offset, PAL_NONE, ti, fake_slope);
@@ -2250,10 +2252,10 @@ static int GetJunctionGroundSpriteOffset(TrackBits track)
/* If none of the tracks end up in the NE corner, return the ground sprite
* where the NE of the tile is not covered. Repeat for the other directions.
* What remains are junctions where all directions are covered. */
if ((track & TRACK_BIT_3WAY_NE) == 0) return 0;
if ((track & TRACK_BIT_3WAY_SW) == 0) return 1;
if ((track & TRACK_BIT_3WAY_NW) == 0) return 2;
if ((track & TRACK_BIT_3WAY_SE) == 0) return 3;
if (!track.Any(TRACK_BIT_3WAY_NE)) return 0;
if (!track.Any(TRACK_BIT_3WAY_SW)) return 1;
if (!track.Any(TRACK_BIT_3WAY_NW)) return 2;
if (!track.Any(TRACK_BIT_3WAY_SE)) return 3;
return 4;
}
@@ -2279,7 +2281,7 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track)
/* Save halftile corner */
halftile_corner = (f == Foundation::SteepBoth ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
/* Draw lower part first */
track &= ~CornerToTrackBits(halftile_corner);
track.Reset(CornerToTrackBits(halftile_corner));
f = (f == Foundation::SteepBoth ? Foundation::SteepLower : Foundation::None);
}
@@ -2292,7 +2294,7 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track)
bool junction = false;
/* Select the sprite to use. */
if (track == 0) {
if (track.None()) {
/* Clear ground (only track on halftile foundation) */
if (rgt == RailGroundType::HalfTileWater) {
if (IsSteepSlope(ti->tileh)) {
@@ -2315,19 +2317,19 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track)
image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
} else {
/* track on flat ground */
switch (track) {
switch (track.base()) {
/* single track, select combined track + ground sprite*/
case TRACK_BIT_Y: image = rti->base_sprites.track_y; break;
case TRACK_BIT_X: image = rti->base_sprites.track_y + 1; break;
case TRACK_BIT_UPPER: image = rti->base_sprites.track_y + 2; break;
case TRACK_BIT_LOWER: image = rti->base_sprites.track_y + 3; break;
case TRACK_BIT_RIGHT: image = rti->base_sprites.track_y + 4; break;
case TRACK_BIT_LEFT: image = rti->base_sprites.track_y + 5; break;
case TRACK_BIT_CROSS: image = rti->base_sprites.track_y + 6; break;
case TrackBits{Track::Y}.base(): image = rti->base_sprites.track_y; break;
case TrackBits{Track::X}.base(): image = rti->base_sprites.track_y + 1; break;
case TrackBits{Track::Upper}.base(): image = rti->base_sprites.track_y + 2; break;
case TrackBits{Track::Lower}.base(): image = rti->base_sprites.track_y + 3; break;
case TrackBits{Track::Right}.base(): image = rti->base_sprites.track_y + 4; break;
case TrackBits{Track::Left}.base(): image = rti->base_sprites.track_y + 5; break;
case TRACK_BIT_CROSS.base(): image = rti->base_sprites.track_y + 6; break;
/* double diagonal track, select combined track + ground sprite*/
case TRACK_BIT_HORZ: image = rti->base_sprites.track_ns; break;
case TRACK_BIT_VERT: image = rti->base_sprites.track_ns + 1; break;
case TRACK_BIT_HORZ.base(): image = rti->base_sprites.track_ns; break;
case TRACK_BIT_VERT.base(): image = rti->base_sprites.track_ns + 1; break;
/* junction, select only ground sprite, handle track sprite later */
default:
@@ -2355,36 +2357,36 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track)
/* Draw track pieces individually for junction tiles */
if (junction) {
if (track & TRACK_BIT_X) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
if (track & TRACK_BIT_Y) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE);
if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
if (track.Test(Track::X)) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
if (track.Test(Track::Y)) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE);
if (track.Test(Track::Upper)) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
if (track.Test(Track::Lower)) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
if (track.Test(Track::Left)) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
if (track.Test(Track::Right)) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
}
/* PBS debugging, draw reserved tracks darker */
if (_game_mode != GameMode::Menu && _settings_client.gui.show_track_reservation) {
/* Get reservation, but mask track on halftile slope */
TrackBits pbs = GetRailReservationTrackBits(ti->tile) & track;
if (pbs & TRACK_BIT_X) {
if (pbs.Test(Track::X)) {
if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) {
DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH);
} else {
DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH);
}
}
if (pbs & TRACK_BIT_Y) {
if (pbs.Test(Track::Y)) {
if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) {
DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH);
} else {
DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH);
}
}
if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_N ? -(int)TILE_HEIGHT : 0);
if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_S ? -(int)TILE_HEIGHT : 0);
if (pbs & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_W ? -(int)TILE_HEIGHT : 0);
if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_E ? -(int)TILE_HEIGHT : 0);
if (pbs.Test(Track::Upper)) DrawGroundSprite(rti->base_sprites.single_n, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_N ? -(int)TILE_HEIGHT : 0);
if (pbs.Test(Track::Lower)) DrawGroundSprite(rti->base_sprites.single_s, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_S ? -(int)TILE_HEIGHT : 0);
if (pbs.Test(Track::Left)) DrawGroundSprite(rti->base_sprites.single_w, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_W ? -(int)TILE_HEIGHT : 0);
if (pbs.Test(Track::Right)) DrawGroundSprite(rti->base_sprites.single_e, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_E ? -(int)TILE_HEIGHT : 0);
}
if (IsValidCorner(halftile_corner)) {
@@ -2415,31 +2417,31 @@ static void DrawSignals(TileIndex tile, TrackBits rails, const RailTypeInfo *rti
if (IsSignalPresent(tile, signalbit)) DrawSingleSignal(tile, rti, track, GetSingleSignalState(tile, signalbit), image, pos);
};
if (!(rails & TRACK_BIT_Y)) {
if (!(rails & TRACK_BIT_X)) {
if (rails & TRACK_BIT_LEFT) {
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, TRACK_LEFT);
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, TRACK_LEFT);
if (!rails.Test(Track::Y)) {
if (!rails.Test(Track::X)) {
if (rails.Test(Track::Left)) {
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, Track::Left);
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, Track::Left);
}
if (rails & TRACK_BIT_RIGHT) {
MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, TRACK_RIGHT);
MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, TRACK_RIGHT);
if (rails.Test(Track::Right)) {
MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, Track::Right);
MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, Track::Right);
}
if (rails & TRACK_BIT_UPPER) {
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, TRACK_UPPER);
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, TRACK_UPPER);
if (rails.Test(Track::Upper)) {
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, Track::Upper);
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, Track::Upper);
}
if (rails & TRACK_BIT_LOWER) {
MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, TRACK_LOWER);
MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, TRACK_LOWER);
if (rails.Test(Track::Lower)) {
MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, Track::Lower);
MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, Track::Lower);
}
} else {
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, TRACK_X);
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, TRACK_X);
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, Track::X);
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, Track::X);
}
} else {
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, TRACK_Y);
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, TRACK_Y);
MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, Track::Y);
MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, Track::Y);
}
}
@@ -2462,10 +2464,10 @@ static void DrawTile_Rail(TileInfo *ti)
if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails, rti);
if (IsBridgeAbove(ti->tile)) {
if ((rails & TRACK_BIT_3WAY_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
if ((rails & TRACK_BIT_3WAY_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
if ((rails & TRACK_BIT_3WAY_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
if ((rails & TRACK_BIT_3WAY_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
if (rails.Any(TRACK_BIT_3WAY_NE)) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
if (rails.Any(TRACK_BIT_3WAY_SE)) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
if (rails.Any(TRACK_BIT_3WAY_SW)) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
if (rails.Any(TRACK_BIT_3WAY_NW)) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
}
} else {
/* draw depot */
@@ -2718,7 +2720,7 @@ static void TileLoop_Rail(TileIndex tile)
static constexpr DiagDirectionIndexArray<TrackBits> dir_to_trackbits{TRACK_BIT_3WAY_NE, TRACK_BIT_3WAY_SE, TRACK_BIT_3WAY_SW, TRACK_BIT_3WAY_NW};
/* Track bit on this edge => no fence. */
if ((rail & dir_to_trackbits[d]) != TRACK_BIT_NONE) continue;
if (rail.Any(dir_to_trackbits[d])) continue;
TileIndex tile2 = tile + TileOffsByDiagDir(d);
@@ -2759,19 +2761,19 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [
/* Case of half tile slope with water. */
if (mode == TRANSPORT_WATER && IsPlainRail(tile) && GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(GetTileSlope(tile))) {
TrackBits tb = GetTrackBits(tile);
switch (tb) {
switch (tb.base()) {
default: NOT_REACHED();
case TRACK_BIT_UPPER: tb = TRACK_BIT_LOWER; break;
case TRACK_BIT_LOWER: tb = TRACK_BIT_UPPER; break;
case TRACK_BIT_LEFT: tb = TRACK_BIT_RIGHT; break;
case TRACK_BIT_RIGHT: tb = TRACK_BIT_LEFT; break;
case TrackBits{Track::Upper}.base(): tb = Track::Lower; break;
case TrackBits{Track::Lower}.base(): tb = Track::Upper; break;
case TrackBits{Track::Left}.base(): tb = Track::Right; break;
case TrackBits{Track::Right}.base(): tb = Track::Left; break;
}
return {TrackBitsToTrackdirBits(tb), TRACKDIR_BIT_NONE};
}
if (mode != TRANSPORT_RAIL) return {};
TrackBits trackbits = TRACK_BIT_NONE;
TrackBits trackbits{};
TrackdirBits red_signals = TRACKDIR_BIT_NONE;
switch (GetRailTileType(tile)) {
@@ -2792,8 +2794,8 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [
* the signal type. For signals that are only active from
* one side, we set the missing signals explicitly to
* `green'. Otherwise, they implicitly become `red'. */
if (!IsOnewaySignal(tile, TRACK_UPPER) || (a & SignalOnTrack(TRACK_UPPER)) == 0) b |= ~a & SignalOnTrack(TRACK_UPPER);
if (!IsOnewaySignal(tile, TRACK_LOWER) || (a & SignalOnTrack(TRACK_LOWER)) == 0) b |= ~a & SignalOnTrack(TRACK_LOWER);
if (!IsOnewaySignal(tile, Track::Upper) || (a & SignalOnTrack(Track::Upper)) == 0) b |= ~a & SignalOnTrack(Track::Upper);
if (!IsOnewaySignal(tile, Track::Lower) || (a & SignalOnTrack(Track::Lower)) == 0) b |= ~a & SignalOnTrack(Track::Lower);
if ((b & 0x8) == 0) red_signals |= (TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E);
if ((b & 0x4) == 0) red_signals |= (TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_UPPER_W);
@@ -2808,7 +2810,7 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [
if (side != DiagDirection::Invalid && side != dir) break;
trackbits = DiagDirToDiagTrackBits(dir);
trackbits = DiagDirToDiagTrack(dir);
break;
}
}
@@ -2891,11 +2893,11 @@ static void GetTileDesc_Rail(TileIndex tile, TileDesc &td)
SignalType primary_signal;
SignalType secondary_signal;
if (HasSignalOnTrack(tile, TRACK_UPPER)) {
primary_signal = GetSignalType(tile, TRACK_UPPER);
secondary_signal = HasSignalOnTrack(tile, TRACK_LOWER) ? GetSignalType(tile, TRACK_LOWER) : primary_signal;
if (HasSignalOnTrack(tile, Track::Upper)) {
primary_signal = GetSignalType(tile, Track::Upper);
secondary_signal = HasSignalOnTrack(tile, Track::Lower) ? GetSignalType(tile, Track::Lower) : primary_signal;
} else {
secondary_signal = primary_signal = GetSignalType(tile, TRACK_LOWER);
secondary_signal = primary_signal = GetSignalType(tile, Track::Lower);
}
td.str = signal_type[secondary_signal][primary_signal];
@@ -2929,7 +2931,7 @@ static void ChangeTileOwner_Rail(TileIndex tile, Owner old_owner, Owner new_owne
uint num_pieces = 1;
if (IsPlainRail(tile)) {
TrackBits bits = GetTrackBits(tile);
num_pieces = CountBits(bits);
num_pieces = bits.Count();
if (TracksOverlap(bits)) num_pieces *= num_pieces;
}
RailType rt = GetRailType(tile);
@@ -3024,13 +3026,13 @@ static VehicleEnterTileStates VehicleEnterTile_Rail(Vehicle *v, TileIndex tile,
/* Leave the depot. */
if ((v = v->GetMovingNext()) != nullptr) {
v->vehstatus.Reset(VehState::Hidden);
Train::From(v)->track = AxisToTrackBits(DiagDirToAxis(dir));
Train::From(v)->track = AxisToTrack(DiagDirToAxis(dir));
}
}
} else if (_fractcoords_enter[dir] == fract_coord) {
/* Entering depot. */
assert(DiagDirToDir(ReverseDiagDir(dir)) == v->GetMovingDirection());
Train::From(v)->track = TRACK_BIT_DEPOT;
Train::From(v)->track = Track::Depot;
v->vehstatus.Set(VehState::Hidden);
if (v->GetMovingNext() == nullptr) {
Train *consist = Train::From(v)->First();
@@ -3072,18 +3074,18 @@ static CommandCost TestAutoslopeOnRailTile(TileIndex tile, DoCommandFlags flags,
if (!_settings_game.construction.build_on_slopes || !AutoslopeEnabled()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
/* Is the slope-rail_bits combination valid in general? I.e. is it safe to call GetRailFoundation() ? */
if (CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile).Failed()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
if (CheckRailSlope(tileh_new, rail_bits, {}, tile).Failed()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK);
/* Get the slopes on top of the foundations */
z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), tileh_old);
z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), tileh_new);
Corner track_corner;
switch (rail_bits) {
case TRACK_BIT_LEFT: track_corner = CORNER_W; break;
case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
switch (rail_bits.base()) {
case TrackBits{Track::Left}.base(): track_corner = CORNER_W; break;
case TrackBits{Track::Lower}.base(): track_corner = CORNER_S; break;
case TrackBits{Track::Right}.base(): track_corner = CORNER_E; break;
case TrackBits{Track::Upper}.base(): track_corner = CORNER_N; break;
/* Surface slope must not be changed */
default:
@@ -3125,11 +3127,11 @@ static CommandCost TerraformTile_Rail(TileIndex tile, DoCommandFlags flags, int
/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
Corner allowed_corner;
switch (rail_bits) {
case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break;
case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break;
case TRACK_BIT_LEFT: allowed_corner = CORNER_E; break;
case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break;
switch (rail_bits.base()) {
case TrackBits{Track::Right}.base(): allowed_corner = CORNER_W; break;
case TrackBits{Track::Upper}.base(): allowed_corner = CORNER_S; break;
case TrackBits{Track::Left}.base(): allowed_corner = CORNER_E; break;
case TrackBits{Track::Lower}.base(): allowed_corner = CORNER_N; break;
default: return autoslope_result;
}
+9 -9
View File
@@ -123,16 +123,16 @@ static void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track)
{
if (GetRailTileType(tile) == RailTileType::Depot) return;
if (GetRailTileType(tile) == RailTileType::Signals && !_settings_client.gui.auto_remove_signals) return;
if ((GetTrackBits(tile) & DiagdirReachesTracks(dir)) == 0) return;
if (!GetTrackBits(tile).Any(DiagdirReachesTracks(dir))) return;
Command<Commands::BuildRail>::Post(tile, _cur_railtype, track, _settings_client.gui.auto_remove_signals);
}
/** Additional pieces of track to add at the entrance of a depot. */
static constexpr std::array<DiagDirectionIndexArray<Track>, 3> _place_depot_extra_track{{
{TRACK_LEFT, TRACK_UPPER, TRACK_UPPER, TRACK_RIGHT}, // First additional track for directions 0..3
{TRACK_X, TRACK_Y, TRACK_X, TRACK_Y}, // Second additional track
{TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT, TRACK_LOWER}, // Third additional track
{Track::Left, Track::Upper, Track::Upper, Track::Right}, // First additional track for directions 0..3
{Track::X, Track::Y, Track::X, Track::Y}, // Second additional track
{Track::Lower, Track::Left, Track::Right, Track::Lower}, // Third additional track
}};
/** Direction to check for existing track pieces. */
@@ -239,12 +239,12 @@ static void GenericPlaceSignals(TileIndex tile)
{
TrackBits trackbits = TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs);
if (trackbits & TRACK_BIT_VERT) { // N-S direction
trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT;
if (trackbits.Any(TRACK_BIT_VERT)) { // N-S direction
trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? Track::Right : Track::Left;
}
if (trackbits & TRACK_BIT_HORZ) { // E-W direction
trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER;
if (trackbits.Any(TRACK_BIT_HORZ)) { // E-W direction
trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? Track::Upper : Track::Lower;
}
Track track = FindFirstTrack(trackbits);
@@ -418,7 +418,7 @@ static void HandleAutodirPlacement()
*/
static void HandleAutoSignalPlacement()
{
Track track = (Track)GB(_thd.drawstyle, 0, 3); // 0..5
Track track = static_cast<Track>(_thd.drawstyle & HT_DIR_MASK); // 0..5
if ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT) { // one tile case
GenericPlaceSignals(TileVirtXY(_thd.selend.x, _thd.selend.y));
+17 -18
View File
@@ -136,7 +136,7 @@ inline void SetRailType(Tile t, RailType r)
inline TrackBits GetTrackBits(Tile tile)
{
assert(IsPlainRailTile(tile));
return (TrackBits)GB(tile.m5(), 0, 6);
return static_cast<TrackBits>(GB(tile.m5(), 0, 6));
}
/**
@@ -147,7 +147,7 @@ inline TrackBits GetTrackBits(Tile tile)
inline void SetTrackBits(Tile t, TrackBits b)
{
assert(IsPlainRailTile(t));
SB(t.m5(), 0, 6, b);
SB(t.m5(), 0, 6, b.base());
}
/**
@@ -159,7 +159,7 @@ inline void SetTrackBits(Tile t, TrackBits b)
*/
inline bool HasTrack(Tile tile, Track track)
{
return HasBit(GetTrackBits(tile), track);
return GetTrackBits(tile).Test(track);
}
/**
@@ -195,9 +195,9 @@ inline TrackBits GetRailReservationTrackBits(Tile t)
{
assert(IsPlainRailTile(t));
uint8_t track_b = GB(t.m2(), 8, 3);
Track track = (Track)(track_b - 1); // map array saves Track+1
if (track_b == 0) return TRACK_BIT_NONE;
return (TrackBits)(TrackToTrackBits(track) | (HasBit(t.m2(), 11) ? TrackToTrackBits(TrackToOppositeTrack(track)) : 0));
if (track_b == 0) return {};
Track track = static_cast<Track>(track_b - 1); // map array saves Track+1
return (HasBit(t.m2(), 11) ? TrackToOppositeTrack(track) : TrackBits{}) | track;
}
/**
@@ -212,7 +212,7 @@ inline void SetTrackReservation(Tile t, TrackBits b)
assert(!TracksOverlap(b));
Track track = RemoveFirstTrack(&b);
SB(t.m2(), 8, 3, IsValidTrack(track) ? to_underlying(track) + 1 : 0);
AssignBit(t.m2(), 11, b != TRACK_BIT_NONE);
AssignBit(t.m2(), 11, b.Any());
}
/**
@@ -225,10 +225,9 @@ inline void SetTrackReservation(Tile t, TrackBits b)
inline bool TryReserveTrack(Tile tile, Track t)
{
assert(HasTrack(tile, t));
TrackBits bits = TrackToTrackBits(t);
TrackBits res = GetRailReservationTrackBits(tile);
if ((res & bits) != TRACK_BIT_NONE) return false; // already reserved
res |= bits;
if (res.Test(t)) return false; // already reserved
res.Set(t);
if (TracksOverlap(res)) return false; // crossing reservation present
SetTrackReservation(tile, res);
return true;
@@ -244,7 +243,7 @@ inline void UnreserveTrack(Tile tile, Track t)
{
assert(HasTrack(tile, t));
TrackBits res = GetRailReservationTrackBits(tile);
res &= ~TrackToTrackBits(t);
res.Reset(t);
SetTrackReservation(tile, res);
}
@@ -280,7 +279,7 @@ inline void SetDepotReservation(Tile t, bool b)
*/
inline TrackBits GetDepotReservationTrackBits(Tile t)
{
return HasDepotReservation(t) ? TrackToTrackBits(GetRailDepotTrack(t)) : TRACK_BIT_NONE;
return HasDepotReservation(t) ? GetRailDepotTrack(t) : TrackBits{};
}
@@ -304,7 +303,7 @@ inline bool IsPbsSignal(SignalType s)
inline SignalType GetSignalType(Tile t, Track track)
{
assert(GetRailTileType(t) == RailTileType::Signals);
uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0;
uint8_t pos = (track == Track::Lower || track == Track::Right) ? 4 : 0;
return static_cast<SignalType>(GB(t.m2(), pos, 3));
}
@@ -318,7 +317,7 @@ inline SignalType GetSignalType(Tile t, Track track)
inline void SetSignalType(Tile t, Track track, SignalType s)
{
assert(GetRailTileType(t) == RailTileType::Signals);
uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0;
uint8_t pos = (track == Track::Lower || track == Track::Right) ? 4 : 0;
SB(t.m2(), pos, 3, to_underlying(s));
if (!IsValidTrack(track)) SB(t.m2(), 4, 3, to_underlying(s));
}
@@ -369,7 +368,7 @@ inline bool IsOnewaySignal(Tile t, Track track)
inline void CycleSignalSide(Tile t, Track track)
{
uint8_t sig;
uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 6;
uint8_t pos = (track == Track::Lower || track == Track::Right) ? 4 : 6;
sig = GB(t.m3(), pos, 2);
if (--sig == 0) sig = IsPbsSignal(GetSignalType(t, track)) ? 2 : 3;
@@ -385,7 +384,7 @@ inline void CycleSignalSide(Tile t, Track track)
*/
inline SignalVariant GetSignalVariant(Tile t, Track track)
{
uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3;
uint8_t pos = (track == Track::Lower || track == Track::Right) ? 7 : 3;
return static_cast<SignalVariant>(GB(t.m2(), pos, 1));
}
@@ -398,7 +397,7 @@ inline SignalVariant GetSignalVariant(Tile t, Track track)
*/
inline void SetSignalVariant(Tile t, Track track, SignalVariant v)
{
uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3;
uint8_t pos = (track == Track::Lower || track == Track::Right) ? 7 : 3;
SB(t.m2(), pos, 1, to_underlying(v));
if (!IsValidTrack(track)) SB(t.m2(), 7, 1, to_underlying(v));
}
@@ -630,7 +629,7 @@ inline void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r)
t.m2() = 0;
t.m3() = 0;
t.m4() = 0;
t.m5() = to_underlying(RailTileType::Normal) << 6 | b;
t.m5() = to_underlying(RailTileType::Normal) << 6 | b.base();
SB(t.m6(), 2, 6, 0);
t.m7() = 0;
t.m8() = r;
+1 -1
View File
@@ -46,7 +46,7 @@ static bool IsPossibleCrossing(const TileIndex tile, Axis ax)
{
return (IsTileType(tile, TileType::Railway) &&
GetRailTileType(tile) == RailTileType::Normal &&
GetTrackBits(tile) == AxisToTrackBits(OtherAxis(ax)) &&
GetTrackBits(tile) == AxisToTrack(OtherAxis(ax)) &&
std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT);
}
+28 -29
View File
@@ -494,12 +494,11 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie
/* A full diagonal road tile has two road bits. */
UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
Track railtrack = GetCrossingRailTrack(tile);
Track track = GetCrossingRailTrack(tile);
if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) {
TrackBits tracks = GetCrossingRailBits(tile);
bool reserved = HasCrossingReservation(tile);
MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
if (reserved) SetTrackReservation(tile, tracks);
MakeRailNormal(tile, GetTileOwner(tile), track, GetRailType(tile));
if (reserved) SetTrackReservation(tile, track);
/* Update rail count for level crossings. The plain track should still be accounted
* for, so only subtract the difference to the level crossing cost. */
@@ -512,7 +511,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie
SetRoadType(tile, rtt, INVALID_ROADTYPE);
}
MarkTileDirtyByTile(tile);
YapfNotifyTrackLayoutChange(tile, railtrack);
YapfNotifyTrackLayoutChange(tile, track);
}
return CommandCost(ExpensesType::Construction, RoadClearCost(existing_rt) * 2);
}
@@ -736,13 +735,13 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces,
}
Axis roaddir;
switch (GetTrackBits(tile)) {
case TRACK_BIT_X:
switch (GetTrackBits(tile).base()) {
case TrackBits{Track::X}.base():
if (pieces.Any(ROAD_X)) goto do_clear;
roaddir = Axis::Y;
break;
case TRACK_BIT_Y:
case TrackBits{Track::Y}.base():
if (pieces.Any(ROAD_Y)) goto do_clear;
roaddir = Axis::X;
break;
@@ -768,7 +767,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces,
}
/* Always add road to the roadtypes (can't draw without it) */
bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
bool reserved = GetRailReservationTrackBits(tile).Test(railtrack);
MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RoadTramType::Road ? rt : INVALID_ROADTYPE, (rtt == RoadTramType::Tram) ? rt : INVALID_ROADTYPE, town_id);
SetCrossingReservation(tile, reserved);
UpdateLevelCrossing(tile, false);
@@ -2121,22 +2120,22 @@ static bool ClickTile_Road(TileIndex tile)
/** Converts %RoadBits to %TrackBits. */
static const TrackBits _road_trackbits[16] = {
TRACK_BIT_NONE, // ROAD_NONE
TRACK_BIT_NONE, // RoadBit::NW
TRACK_BIT_NONE, // RoadBit::SW
TRACK_BIT_LEFT, // ROAD_W
TRACK_BIT_NONE, // RoadBit::SE
TRACK_BIT_Y, // ROAD_Y
TRACK_BIT_LOWER, // ROAD_S
TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | RoadBit::SW
TRACK_BIT_NONE, // RoadBit::NE
TRACK_BIT_UPPER, // ROAD_N
TRACK_BIT_X, // ROAD_X
TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | RoadBit::NW
TRACK_BIT_RIGHT, // ROAD_E
TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | RoadBit::NE
TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | RoadBit::SE
TRACK_BIT_ALL, // ROAD_ALL
{}, // ROAD_NONE
{}, // RoadBit::NW
{}, // RoadBit::SW
Track::Left, // ROAD_W
{}, // RoadBit::SE
Track::Y, // ROAD_Y
Track::Lower, // ROAD_S
{Track::Left, Track::Lower, Track::Y}, // ROAD_Y | RoadBit::SW
{}, // RoadBit::NE
Track::Upper, // ROAD_N
Track::X, // ROAD_X
{Track::Left, Track::Upper, Track::X}, // ROAD_X | RoadBit::NW
Track::Right, // ROAD_E
{Track::Right, Track::Upper, Track::Y}, // ROAD_Y | RoadBit::NE
{Track::Right, Track::Lower, Track::X}, // ROAD_X | RoadBit::SE
TRACK_BIT_ALL, // ROAD_ALL
};
/** @copydoc GetTileTrackStatusProc */
@@ -2146,7 +2145,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R
TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
switch (mode) {
case TRANSPORT_RAIL:
if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailTrack(tile));
break;
case TRANSPORT_ROAD: {
@@ -2161,7 +2160,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R
if (side != DiagDirection::Invalid && !DiagDirToRoadBits(side).Any(bits)) break;
uint multiplier = drd_to_multiplier[(rtt == RoadTramType::Tram) ? 0 : GetDisallowedRoadDirections(tile).base()];
if (!HasRoadWorks(tile)) trackdirbits = static_cast<TrackdirBits>(_road_trackbits[bits.base()] * multiplier);
if (!HasRoadWorks(tile)) trackdirbits = static_cast<TrackdirBits>(_road_trackbits[bits.base()].base() * multiplier);
break;
}
@@ -2170,7 +2169,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R
if (side != DiagDirection::Invalid && axis != DiagDirToAxis(side)) break;
trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis));
trackdirbits = TrackBitsToTrackdirBits(AxisToTrack(axis));
if (IsCrossingBarred(tile)) {
red_signals = trackdirbits;
if (TrainOnCrossing(tile)) break;
@@ -2192,7 +2191,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R
if (side != DiagDirection::Invalid && side != dir) break;
trackdirbits = TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir));
trackdirbits = TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir));
break;
}
}
+1 -12
View File
@@ -370,17 +370,6 @@ inline Track GetCrossingRailTrack(Tile tile)
return AxisToTrack(GetCrossingRailAxis(tile));
}
/**
* Get the rail track bits of a level crossing.
* @param tile The tile to query.
* @return The rail track bits.
*/
inline TrackBits GetCrossingRailBits(Tile tile)
{
return AxisToTrackBits(GetCrossingRailAxis(tile));
}
/**
* Get the reservation state of the rail crossing
* @param t the crossing tile
@@ -414,7 +403,7 @@ inline void SetCrossingReservation(Tile t, bool b)
*/
inline TrackBits GetCrossingReservationTrackBits(Tile t)
{
return HasCrossingReservation(t) ? GetCrossingRailBits(t) : TRACK_BIT_NONE;
return HasCrossingReservation(t) ? GetCrossingRailTrack(t) : TrackBits{};
}
/**
+1 -1
View File
@@ -290,7 +290,7 @@ protected: // These functions should not be called outside acceleration code.
TrackStatus ts = GetTileTrackStatus(this->tile, TRANSPORT_ROAD, GetRoadTramType(this->roadtype));
TrackBits trackbits = TrackdirBitsToTrackBits(ts.trackdirs);
return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y;
return trackbits == Track::X || trackbits == Track::Y;
}
/**
+1 -1
View File
@@ -796,7 +796,7 @@ static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
TrackBits trackbits = TrackdirBitsToTrackBits(ts.trackdirs);
/* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
if (!HasBit(ts.trackdirs, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (ts.signals != TRACKDIR_BIT_NONE)) return true;
if (!HasBit(ts.trackdirs, od->trackdir) || trackbits.Any({Track::Upper, Track::Lower, Track::Left, Track::Right}) || (ts.signals != TRACKDIR_BIT_NONE)) return true;
/* Are there more vehicles on the tile except the two vehicles involved in overtaking */
return HasVehicleOnTile(od->tile, [&](const Vehicle *v) {
+18 -18
View File
@@ -1235,7 +1235,7 @@ bool AfterLoadGame()
MakeRailNormal(
t,
GetTileOwner(t),
AxisToTrackBits(OtherAxis(axis)),
AxisToTrack(OtherAxis(axis)),
GetRailType(t)
);
} else {
@@ -1297,7 +1297,7 @@ bool AfterLoadGame()
continue;
}
if (v->type == VehicleType::Train) {
Train::From(v)->track = TRACK_BIT_WORMHOLE;
Train::From(v)->track = Track::Wormhole;
} else {
RoadVehicle::From(v)->state = RVSB_WORMHOLE;
}
@@ -1439,7 +1439,7 @@ bool AfterLoadGame()
}
}
YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
YapfNotifyTrackLayoutChange(INVALID_TILE, Track::Invalid);
if (IsSavegameVersionBefore(SLV_34)) {
for (Company *c : Company::Iterate()) ResetCompanyLivery(c);
@@ -2026,8 +2026,8 @@ bool AfterLoadGame()
case TileType::Railway:
if (HasSignals(t)) {
/* move the signal variant */
SetSignalVariant(t, TRACK_UPPER, HasBit(t.m2(), 2) ? SignalVariant::Semaphore : SignalVariant::Electric);
SetSignalVariant(t, TRACK_LOWER, HasBit(t.m2(), 6) ? SignalVariant::Semaphore : SignalVariant::Electric);
SetSignalVariant(t, Track::Upper, HasBit(t.m2(), 2) ? SignalVariant::Semaphore : SignalVariant::Electric);
SetSignalVariant(t, Track::Lower, HasBit(t.m2(), 6) ? SignalVariant::Semaphore : SignalVariant::Electric);
ClrBit(t.m2(), 2);
ClrBit(t.m2(), 6);
}
@@ -2036,7 +2036,7 @@ bool AfterLoadGame()
if (IsRailDepot(t)) {
SetDepotReservation(t, false);
} else {
SetTrackReservation(t, TRACK_BIT_NONE);
SetTrackReservation(t, {});
}
break;
@@ -2672,16 +2672,16 @@ bool AfterLoadGame()
v->vehstatus.Set(VehState::Hidden);
switch (v->type) {
case VehicleType::Train: Train::From(v)->track = TRACK_BIT_WORMHOLE; break;
case VehicleType::Road: RoadVehicle::From(v)->state = RVSB_WORMHOLE; break;
case VehicleType::Train: Train::From(v)->track = Track::Wormhole; break;
case VehicleType::Road: RoadVehicle::From(v)->state = RVSB_WORMHOLE; break;
default: NOT_REACHED();
}
} else {
v->vehstatus.Reset(VehState::Hidden);
switch (v->type) {
case VehicleType::Train: Train::From(v)->track = DiagDirToDiagTrackBits(vdir); break;
case VehicleType::Road: RoadVehicle::From(v)->state = DiagDirToDiagTrackdir(vdir); RoadVehicle::From(v)->frame = frame; break;
case VehicleType::Train: Train::From(v)->track = DiagDirToDiagTrack(vdir); break;
case VehicleType::Road: RoadVehicle::From(v)->state = DiagDirToDiagTrackdir(vdir); RoadVehicle::From(v)->frame = frame; break;
default: NOT_REACHED();
}
}
@@ -2757,7 +2757,7 @@ bool AfterLoadGame()
if (t->vehstatus.Test(VehState::Crashed)) break;
/* Only X/Y tracks can be sloped. */
if (t->track != TRACK_BIT_X && t->track != TRACK_BIT_Y) break;
if (t->track != Track::X && t->track != Track::Y) break;
t->gv_flags |= FixVehicleInclination(t, t->direction);
break;
@@ -2776,12 +2776,12 @@ bool AfterLoadGame()
TrackBits trackbits = TrackdirBitsToTrackBits(ts.trackdirs);
/* Only X/Y tracks can be sloped. */
if (trackbits != TRACK_BIT_X && trackbits != TRACK_BIT_Y) break;
if (trackbits != Track::X && trackbits != Track::Y) break;
Direction dir = rv->direction;
/* Test if we are reversing. */
Axis a = trackbits == TRACK_BIT_X ? Axis::X : Axis::Y;
Axis a = trackbits == Track::X ? Axis::X : Axis::Y;
if (AxisToDirection(a) != dir &&
AxisToDirection(a) != ReverseDir(dir)) {
/* When reversing, the road vehicle is on the edge of the tile,
@@ -2808,10 +2808,10 @@ bool AfterLoadGame()
if (v->type == VehicleType::Train && !v->vehstatus.Test(VehState::Crashed) &&
v->direction != DiagDirToDir(dir)) {
/* If the train has left the bridge, it shouldn't have
* track == TRACK_BIT_WORMHOLE - this could happen
* track == Track::Wormhole - this could happen
* when the train was reversed while on the last "tick"
* on the ramp before leaving the ramp to the bridge. */
Train::From(v)->track = DiagDirToDiagTrackBits(dir);
Train::From(v)->track = DiagDirToDiagTrack(dir);
}
}
@@ -2935,10 +2935,10 @@ bool AfterLoadGame()
if (!t->IsPrimaryVehicle()) continue;
/* Front not in depot -> consist not entering depot */
if (t->track != TRACK_BIT_DEPOT) continue;
if (t->track != Track::Depot) continue;
/* Back in depot -> consist completely in depot */
if (t->Last()->track == TRACK_BIT_DEPOT) continue;
for (Train *u = t; u->track == TRACK_BIT_DEPOT; u = u->Next()) {
if (t->Last()->track == Track::Depot) continue;
for (Train *u = t; u->track == Track::Depot; u = u->Next()) {
u->direction = ReverseDir(u->direction);
}
}
+1 -1
View File
@@ -144,7 +144,7 @@ void AfterLoadCompanyStats()
uint pieces = 1;
if (IsPlainRail(tile)) {
TrackBits bits = GetTrackBits(tile);
pieces = CountBits(bits);
pieces = bits.Count();
if (TracksOverlap(bits)) pieces *= pieces;
}
c->infrastructure.rail[GetRailType(tile)] += pieces;
+3 -3
View File
@@ -574,7 +574,7 @@ void FixupTrainLengths()
* so we need to move all vehicles forward to cover the difference to the
* old center, otherwise wagon spacing in trains would be broken upon load. */
for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
if (u->track == TRACK_BIT_DEPOT || u->vehstatus.Test(VehState::Crashed)) continue;
if (u->track == Track::Depot || u->vehstatus.Test(VehState::Crashed)) continue;
Train *next = u->Next();
@@ -627,12 +627,12 @@ void FixupTrainLengths()
}
/* If the next wagon is still in a depot, check if it shouldn't be outside already. */
if (next != nullptr && next->track == TRACK_BIT_DEPOT) {
if (next != nullptr && next->track == Track::Depot) {
int d = TicksToLeaveDepot(u);
if (d <= 0) {
/* Next vehicle should have left the depot already, show it and pull forward. */
next->vehstatus.Reset(VehState::Hidden);
next->track = TrackToTrackBits(GetRailDepotTrack(next->tile));
next->track = GetRailDepotTrack(next->tile);
for (int i = 0; i >= d; i--) TrainController(next, nullptr);
}
}
+2 -2
View File
@@ -68,12 +68,12 @@
/* Determine the reachable tracks from the shared edge */
TrackBits gtts1 = ::TrackdirBitsToTrackBits(::GetTileTrackStatus(t1, TRANSPORT_WATER, RoadTramType::Invalid, ReverseDiagDir(to_other_tile)).trackdirs) & ::DiagdirReachesTracks(to_other_tile);
if (gtts1 == TRACK_BIT_NONE) return false;
if (gtts1.None()) return false;
to_other_tile = ReverseDiagDir(to_other_tile);
TrackBits gtts2 = ::TrackdirBitsToTrackBits(::GetTileTrackStatus(t2, TRANSPORT_WATER, RoadTramType::Invalid, ReverseDiagDir(to_other_tile)).trackdirs) & ::DiagdirReachesTracks(to_other_tile);
return gtts2 != TRACK_BIT_NONE;
return gtts2.Any();
}
/* static */ bool ScriptMarine::BuildWaterDepot(TileIndex tile, TileIndex front)
+27 -27
View File
@@ -131,7 +131,7 @@
{
if (!IsRailStationTile(tile)) return RAILTRACK_INVALID;
return (RailTrack)::GetRailStationTrackBits(tile);
return static_cast<RailTrack>(::TrackBits{::GetRailStationTrack(tile)}.base());
}
/* static */ bool ScriptRail::BuildRailDepot(TileIndex tile, TileIndex front)
@@ -236,10 +236,10 @@
{
if (!IsRailTile(tile)) return RAILTRACK_INVALID;
if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
if (IsLevelCrossingTile(tile)) return ::GetCrossingRailBits(tile);
if (IsRailDepotTile(tile)) return ::TRACK_BIT_NONE;
return ::GetTrackBits(tile);
if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackBits{::GetRailStationTrack(tile)}.base();
if (IsLevelCrossingTile(tile)) return ::TrackBits{::GetCrossingRailTrack(tile)}.base();
if (IsRailDepotTile(tile)) return {};
return ::GetTrackBits(tile).base();
}
/* static */ bool ScriptRail::BuildRailTrack(TileIndex tile, RailTrack rail_track)
@@ -247,7 +247,7 @@
EnforceCompanyModeValid(false);
EnforcePrecondition(false, ::IsValidTile(tile));
EnforcePrecondition(false, rail_track != 0);
EnforcePrecondition(false, (static_cast<uint>(rail_track) & ~static_cast<uint>(::TRACK_BIT_ALL)) == 0);
EnforcePrecondition(false, (static_cast<uint>(rail_track) & ~static_cast<uint>(::TRACK_BIT_ALL.base())) == 0);
EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0);
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
@@ -293,18 +293,18 @@
static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to)
{
int diag_offset = abs(abs((int)::TileX(*to) - (int)::TileX(tile)) - abs((int)::TileY(*to) - (int)::TileY(tile)));
Track track = TRACK_BEGIN;
Track track = Track::Begin;
if (::TileY(from) == ::TileY(*to)) {
track = TRACK_X;
track = Track::X;
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
} else if (::TileX(from) == ::TileX(*to)) {
track = TRACK_Y;
track = Track::Y;
*to -= ScriptMap::GetMapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
} else if (::TileY(from) < ::TileY(tile)) {
if (::TileX(*to) < ::TileX(tile)) {
track = TRACK_UPPER;
track = Track::Upper;
} else {
track = TRACK_LEFT;
track = Track::Left;
}
if (diag_offset != 0) {
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
@@ -313,9 +313,9 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to)
}
} else if (::TileY(from) > ::TileY(tile)) {
if (::TileX(*to) < ::TileX(tile)) {
track = TRACK_RIGHT;
track = Track::Right;
} else {
track = TRACK_LOWER;
track = Track::Lower;
}
if (diag_offset != 0) {
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
@@ -324,9 +324,9 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to)
}
} else if (::TileX(from) < ::TileX(tile)) {
if (::TileY(*to) < ::TileY(tile)) {
track = TRACK_UPPER;
track = Track::Upper;
} else {
track = TRACK_RIGHT;
track = Track::Right;
}
if (diag_offset == 0) {
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
@@ -335,9 +335,9 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to)
}
} else if (::TileX(from) > ::TileX(tile)) {
if (::TileY(*to) < ::TileY(tile)) {
track = TRACK_LEFT;
track = Track::Left;
} else {
track = TRACK_LOWER;
track = Track::Lower;
}
if (diag_offset == 0) {
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
@@ -402,11 +402,11 @@ static const int NUM_TRACK_DIRECTIONS = 3; ///< The number of directions you can
* 2 it added.
*/
static const ScriptRailSignalData _possible_trackdirs[5][NUM_TRACK_DIRECTIONS] = {
{{TRACK_UPPER, TRACKDIR_UPPER_E, 0}, {TRACK_Y, TRACKDIR_Y_SE, 0}, {TRACK_LEFT, TRACKDIR_LEFT_S, 1}},
{{TRACK_RIGHT, TRACKDIR_RIGHT_S, 1}, {TRACK_X, TRACKDIR_X_SW, 1}, {TRACK_UPPER, TRACKDIR_UPPER_W, 1}},
{{INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}},
{{TRACK_LOWER, TRACKDIR_LOWER_E, 0}, {TRACK_X, TRACKDIR_X_NE, 0}, {TRACK_LEFT, TRACKDIR_LEFT_N, 0}},
{{TRACK_RIGHT, TRACKDIR_RIGHT_N, 0}, {TRACK_Y, TRACKDIR_Y_NW, 1}, {TRACK_LOWER, TRACKDIR_LOWER_W, 1}}
{{Track::Upper, TRACKDIR_UPPER_E, 0}, {Track::Y, TRACKDIR_Y_SE, 0}, {Track::Left, TRACKDIR_LEFT_S, 1}},
{{Track::Right, TRACKDIR_RIGHT_S, 1}, {Track::X, TRACKDIR_X_SW, 1}, {Track::Upper, TRACKDIR_UPPER_W, 1}},
{{Track::Invalid, INVALID_TRACKDIR, 0}, {Track::Invalid, INVALID_TRACKDIR, 0}, {Track::Invalid, INVALID_TRACKDIR, 0}},
{{Track::Lower, TRACKDIR_LOWER_E, 0}, {Track::X, TRACKDIR_X_NE, 0}, {Track::Left, TRACKDIR_LEFT_N, 0}},
{{Track::Right, TRACKDIR_RIGHT_N, 0}, {Track::Y, TRACKDIR_Y_NW, 1}, {Track::Lower, TRACKDIR_LOWER_W, 1}}
};
/* static */ ScriptRail::SignalType ScriptRail::GetSignalType(TileIndex tile, TileIndex front)
@@ -418,7 +418,7 @@ static const ScriptRailSignalData _possible_trackdirs[5][NUM_TRACK_DIRECTIONS] =
for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
const Track &track = _possible_trackdirs[data_index][i].track;
if (!(::TrackToTrackBits(track) & GetRailTracks(tile))) continue;
if (!static_cast<::TrackBits>(GetRailTracks(tile)).Test(track)) continue;
if (!HasSignalOnTrack(tile, track)) continue;
if (!HasSignalOnTrackdir(tile, _possible_trackdirs[data_index][i].trackdir)) continue;
SignalType st = (SignalType)::GetSignalType(tile, track);
@@ -446,13 +446,13 @@ static bool IsValidSignalType(int signal_type)
EnforcePrecondition(false, ::IsPlainRailTile(tile));
EnforcePrecondition(false, ::IsValidSignalType(signal));
Track track = INVALID_TRACK;
Track track = Track::Invalid;
uint signal_cycles = 0;
int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
const Track &t = _possible_trackdirs[data_index][i].track;
if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue;
if (!static_cast<::TrackBits>(GetRailTracks(tile)).Test(t)) continue;
track = t;
signal_cycles = _possible_trackdirs[data_index][i].signal_cycles;
break;
@@ -475,11 +475,11 @@ static bool IsValidSignalType(int signal_type)
EnforcePrecondition(false, ScriptMap::DistanceManhattan(tile, front) == 1)
EnforcePrecondition(false, GetSignalType(tile, front) != SIGNALTYPE_NONE);
Track track = INVALID_TRACK;
Track track = Track::Invalid;
int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
const Track &t = _possible_trackdirs[data_index][i].track;
if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue;
if (!static_cast<::TrackBits>(GetRailTracks(tile)).Test(t)) continue;
track = t;
break;
}
+6 -6
View File
@@ -53,12 +53,12 @@ public:
*/
enum RailTrack {
/* Note: these values represent part of the in-game TrackBits enum */
RAILTRACK_NE_SW = ::TRACK_BIT_X, ///< Track along the x-axis (north-east to south-west).
RAILTRACK_NW_SE = ::TRACK_BIT_Y, ///< Track along the y-axis (north-west to south-east).
RAILTRACK_NW_NE = ::TRACK_BIT_UPPER, ///< Track in the upper corner of the tile (north).
RAILTRACK_SW_SE = ::TRACK_BIT_LOWER, ///< Track in the lower corner of the tile (south).
RAILTRACK_NW_SW = ::TRACK_BIT_LEFT, ///< Track in the left corner of the tile (west).
RAILTRACK_NE_SE = ::TRACK_BIT_RIGHT, ///< Track in the right corner of the tile (east).
RAILTRACK_NE_SW = ::TrackBits{Track::X}.base(), ///< Track along the x-axis (north-east to south-west).
RAILTRACK_NW_SE = ::TrackBits{Track::Y}.base(), ///< Track along the y-axis (north-west to south-east).
RAILTRACK_NW_NE = ::TrackBits{Track::Upper}.base(), ///< Track in the upper corner of the tile (north).
RAILTRACK_SW_SE = ::TrackBits{Track::Lower}.base(), ///< Track in the lower corner of the tile (south).
RAILTRACK_NW_SW = ::TrackBits{Track::Left}.base(), ///< Track in the left corner of the tile (west).
RAILTRACK_NE_SE = ::TrackBits{Track::Right}.base(), ///< Track in the right corner of the tile (east).
RAILTRACK_INVALID = 0xFF, ///< Flag for an invalid track.
};
+1 -1
View File
@@ -50,7 +50,7 @@ struct Ship final : public SpecializedVehicle<Ship, VehicleType::Ship> {
int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed / 2; }
int GetCurrentMaxSpeed() const override { return std::min<int>(this->vcache.cached_max_speed, this->current_order.GetMaxSpeed() * 2); }
Money GetRunningCost() const override;
bool IsInDepot() const override { return this->state == TRACK_BIT_DEPOT; }
bool IsInDepot() const override { return this->state == Track::Depot; }
bool Tick() override;
void OnNewCalendarDay() override;
void OnNewEconomyDay() override;
+10 -10
View File
@@ -294,7 +294,7 @@ Trackdir Ship::GetVehicleTrackdir() const
return DiagDirToDiagTrackdir(GetShipDepotDirection(this->tile));
}
if (this->state == TRACK_BIT_WORMHOLE) {
if (this->state == Track::Wormhole) {
/* ship on aqueduct, so just use its direction and assume a diagonal track */
return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
}
@@ -391,7 +391,7 @@ static bool CheckShipStayInDepot(Ship *v)
v->direction = DiagDirToDir(TrackdirToExitdir(v->GetVehicleTrackdir()));
if (CheckReverseShip(v)) v->direction = ReverseDir(v->direction);
v->state = AxisToTrackBits(GetShipDepotAxis(v->tile));
v->state = AxisToTrack(GetShipDepotAxis(v->tile));
v->rotation = v->direction;
v->vehstatus.Reset(VehState::Hidden);
v->cur_speed = 0;
@@ -461,7 +461,7 @@ static void ShipArrivesAt(const Vehicle *v, Station *st)
* @param v Ship to navigate
* @param tile Tile, the ship is about to enter
* @param tracks Available track choices on \a tile
* @return Track to choose, or INVALID_TRACK when to reverse.
* @return Track to choose, or Track::Invalid when to reverse.
*/
static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
{
@@ -472,14 +472,14 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
/* No destination, don't invoke pathfinder. */
track = TrackBitsToTrack(v->state);
if (!IsDiagonalTrack(track)) track = TrackToOppositeTrack(track);
if (!HasBit(tracks, track)) track = FindFirstTrack(tracks);
if (!tracks.Test(track)) track = FindFirstTrack(tracks);
path_found = false;
} else {
/* Attempt to follow cached path. */
if (!v->path.empty()) {
track = TrackdirToTrack(v->path.back().trackdir);
if (HasBit(tracks, track)) {
if (tracks.Test(track)) {
v->path.pop_back();
/* HandlePathfindResult() is not called here because this is not a new pathfinder result. */
return track;
@@ -655,7 +655,7 @@ static void ShipController(Ship *v)
if (ShipMoveUpDownOnLock(v)) return;
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
if (v->state != TRACK_BIT_WORMHOLE) {
if (v->state != Track::Wormhole) {
/* Not on a bridge */
if (gp.old_tile == gp.new_tile) {
/* Staying in tile */
@@ -675,7 +675,7 @@ static void ShipController(Ship *v)
/* Test if continuing forward would lead to a dead-end, moving into the dock. */
const DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
const TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, RoadTramType::Invalid, exitdir).trackdirs) == TRACK_BIT_NONE) return ReverseShip(v);
if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, RoadTramType::Invalid, exitdir).trackdirs).None()) return ReverseShip(v);
} else if (v->dest_tile != INVALID_TILE) {
/* We have a target, let's see if we reached it... */
if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
@@ -715,7 +715,7 @@ static void ShipController(Ship *v)
const DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
assert(diagdir != DiagDirection::Invalid);
const TrackBits tracks = GetAvailShipTracks(gp.new_tile, diagdir);
if (tracks == TRACK_BIT_NONE) {
if (tracks.None()) {
Trackdir trackdir = INVALID_TRACKDIR;
CheckReverseShip(v, &trackdir);
if (trackdir == INVALID_TRACKDIR) return ReverseShip(v);
@@ -735,7 +735,7 @@ static void ShipController(Ship *v)
if (!vets.Test(VehicleEnterTileState::EnteredWormhole)) {
v->tile = gp.new_tile;
v->state = TrackToTrackBits(track);
v->state = track;
/* Update ship cache when the water class changes. Aqueducts are always canals. */
if (GetEffectiveWaterClass(gp.old_tile) != GetEffectiveWaterClass(gp.new_tile)) v->UpdateCache();
@@ -853,7 +853,7 @@ CommandCost CmdBuildShip(DoCommandFlags flags, TileIndex tile, const Engine *e,
v->reliability_spd_dec = e->reliability_spd_dec;
v->max_age = e->GetLifeLengthInDays();
v->state = TRACK_BIT_DEPOT;
v->state = Track::Depot;
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships);
v->date_of_last_service = TimerGameEconomy::date;
+11 -11
View File
@@ -35,7 +35,7 @@ static constexpr DiagDirectionIndexArray<TrackBits> _enterdir_to_trackbits{
TRACK_BIT_3WAY_NE,
TRACK_BIT_3WAY_SE,
TRACK_BIT_3WAY_SW,
TRACK_BIT_3WAY_NW
TRACK_BIT_3WAY_NW,
};
/** Accessible TrackdirBits from a given enter direction. */
@@ -200,7 +200,7 @@ static SmallSet<DiagDirection, SIG_GLOB_SIZE> _globset("_globset"); ///< set of
*/
static bool IsTrainAndNotInDepot(const Vehicle *v)
{
return v->type == VehicleType::Train && Train::From(v)->track != TRACK_BIT_DEPOT;
return v->type == VehicleType::Train && Train::From(v)->track != Track::Depot;
}
@@ -302,19 +302,19 @@ static SigFlags ExploreSegment(Owner owner)
assert(IsValidDiagDirection(enterdir));
TrackBits tracks = GetTrackBits(tile); // trackbits of tile
TrackBits tracks_masked = static_cast<TrackBits>(tracks & _enterdir_to_trackbits[enterdir]); // only accessible trackbits
TrackBits tracks_masked = tracks & _enterdir_to_trackbits[enterdir]; // only accessible trackbits
if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one accessible track, no need to check
tracks = tracks_masked;
/* If no train detected yet, and there is not no train -> there is a train -> set the flag */
if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train);
} else {
if (tracks_masked == TRACK_BIT_NONE) continue; // no accessible track
if (tracks_masked.None()) continue; // no accessible track
if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
}
/* Is this a track merge or split? */
if (!HasAtMostOneBit(tracks)) flags.Set(SigFlag::Split);
if (tracks.Count() > 1) flags.Set(SigFlag::Split);
if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
@@ -349,7 +349,7 @@ static SigFlags ExploreSegment(Owner owner)
}
for (DiagDirection dir = DiagDirection::Begin; dir < DiagDirection::End; dir++) { // test all possible exit directions
if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any accessible track?
if (dir != enterdir && tracks.Any(_enterdir_to_trackbits[dir])) { // any accessible track?
TileIndex newtile = tile + TileOffsByDiagDir(dir); // new tile to check
DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from
if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SigFlag::Full;
@@ -427,7 +427,7 @@ static void UpdateSignalsAroundSegment(SigFlags flags)
SignalState newstate = SignalState::Green;
/* Signal state of reserved path signals is handled by the reserve/unreserve process. */
if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
if (IsPbsSignal(sig) && GetRailReservationTrackBits(tile).Test(track)) continue;
/* determine whether the new state is red */
if (flags.Test(SigFlag::Train)) {
@@ -522,7 +522,7 @@ static SigSegState UpdateSignalsInBuffer(Owner owner)
case TileType::Station:
case TileType::Road:
if ((TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & _enterdir_to_trackbits[dir]) != TRACK_BIT_NONE) {
if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Any(_enterdir_to_trackbits[dir])) {
/* only add to set when there is some 'interesting' track */
_tbdset.Add(tile, dir);
_tbdset.Add(tile + TileOffsByDiagDir(dir), ReverseDiagDir(dir));
@@ -534,7 +534,7 @@ static SigSegState UpdateSignalsInBuffer(Owner owner)
/* jump to next tile */
tile = tile + TileOffsByDiagDir(dir);
dir = ReverseDiagDir(dir);
if ((TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & _enterdir_to_trackbits[dir]) != TRACK_BIT_NONE) {
if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Any(_enterdir_to_trackbits[dir])) {
_tbdset.Add(tile, dir);
break;
}
@@ -607,8 +607,8 @@ void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
_last_owner = owner;
_globset.Add(tile, _search_dir_1[track]);
_globset.Add(tile, _search_dir_2[track]);
_globset.Add(tile, _search_dir_1[to_underlying(track)]);
_globset.Add(tile, _search_dir_2[to_underlying(track)]);
if (_globset.Items() >= SIG_GLOB_UPDATE) {
/* too many items, force update */
+9 -9
View File
@@ -1050,9 +1050,9 @@ static CommandCost CheckFlatLandRailStation(TileIndex tile_cur, TileIndex north_
if (HasPowerOnRail(GetRailType(tile_cur), rt)) {
/* The existing track must align with the desired station axis. */
Track track = AxisToTrack(axis);
if (GetTrackBits(tile_cur) == TrackToTrackBits(track)) {
if (GetTrackBits(tile_cur) == track) {
/* Check for trains having a reservation for this tile. */
if (HasBit(GetRailReservationTrackBits(tile_cur), track)) {
if (GetRailReservationTrackBits(tile_cur).Test(track)) {
Train *v = GetTrainForReservation(tile_cur, track);
if (v != nullptr) {
affected_vehicles.push_back(v);
@@ -1810,7 +1810,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector<T *> &affected_st
DoClearSquare(tile);
DeleteNewGRFInspectWindow(GrfSpecFeature::Stations, tile.base());
if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), rt);
if (build_rail) MakeRailNormal(tile, owner, track, rt);
Company::Get(owner)->infrastructure.station--;
DirtyCompanyInfrastructureWindows(owner);
@@ -3690,12 +3690,12 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc &td)
/** @copydoc GetTileTrackStatusProc */
static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
{
TrackBits trackbits = TRACK_BIT_NONE;
TrackBits trackbits{};
switch (mode) {
case TRANSPORT_RAIL:
if (HasStationRail(tile) && !IsStationTileBlocked(tile)) {
trackbits = TrackToTrackBits(GetRailStationTrack(tile));
trackbits = GetRailStationTrack(tile);
}
break;
@@ -3704,9 +3704,9 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode
if (IsBuoy(tile)) {
trackbits = TRACK_BIT_ALL;
/* remove tracks that connect NE map edge */
if (TileX(tile) == 0) trackbits &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
if (TileX(tile) == 0) trackbits.Reset(TRACK_BIT_3WAY_NE);
/* remove tracks that connect NW map edge */
if (TileY(tile) == 0) trackbits &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
if (TileY(tile) == 0) trackbits.Reset({Track::Y, Track::Left, Track::Upper});
}
break;
@@ -3718,11 +3718,11 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode
if (IsBayRoadStopTile(tile)) {
DiagDirection dir = GetBayRoadStopDir(tile);
if (side != DiagDirection::Invalid && dir != side) break;
trackbits = DiagDirToDiagTrackBits(dir);
trackbits = DiagDirToDiagTrack(dir);
} else {
Axis axis = GetDriveThroughStopAxis(tile);
if (side != DiagDirection::Invalid && axis != DiagDirToAxis(side)) break;
trackbits = AxisToTrackBits(axis);
trackbits = AxisToTrack(axis);
}
}
break;
+1 -12
View File
@@ -517,17 +517,6 @@ inline Track GetRailStationTrack(Tile t)
return AxisToTrack(GetRailStationAxis(t));
}
/**
* Get the trackbits of a rail station tile.
* @param t Tile to query
* @pre HasStationRail(t)
* @return The trackbits of the rails on tile \a t.
*/
inline TrackBits GetRailStationTrackBits(Tile t)
{
return AxisToTrackBits(GetRailStationAxis(t));
}
/**
* Check if a tile is a valid continuation to a railstation tile.
* The tile \a test_tile is a valid continuation to \a station_tile, if all of the following are true:
@@ -582,7 +571,7 @@ inline void SetRailStationReservation(Tile t, bool b)
*/
inline TrackBits GetStationReservationTrackBits(Tile t)
{
return HasStationReservation(t) ? GetRailStationTrackBits(t) : TRACK_BIT_NONE;
return HasStationReservation(t) ? GetRailStationTrack(t) : TrackBits{};
}
/**
+5 -5
View File
@@ -212,10 +212,10 @@ static const TrackIndexArray<DiagDirectionIndexArray<Directions>> _disallowed_pp
/** This array stores which track bits can meet at a tile edge. */
static const DiagDirectionIndexArray<std::array<Track, NUM_TRACKS_AT_PCP>> _tracks_at_pcp{{{
{TRACK_X, TRACK_X, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT},
{TRACK_Y, TRACK_Y, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT},
{TRACK_X, TRACK_X, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT},
{TRACK_Y, TRACK_Y, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT},
{Track::X, Track::X, Track::Upper, Track::Lower, Track::Left, Track::Right},
{Track::Y, Track::Y, Track::Upper, Track::Lower, Track::Left, Track::Right},
{Track::X, Track::X, Track::Upper, Track::Lower, Track::Left, Track::Right},
{Track::Y, Track::Y, Track::Upper, Track::Lower, Track::Left, Track::Right},
}}};
/** Takes each of the 6 track bits from the array above and assigns it to the home tile or neighbour tile. */
@@ -493,7 +493,7 @@ enum RailCatenarySprite : uint8_t {
* d) both
* PCP exists.
*/
static const RailCatenarySprite _rail_wires[5][TRACK_END][4] = {
static const RailCatenarySprite _rail_wires[5][to_underlying(Track::End)][4] = {
{ // Tileh == 0
{INVALID_CATENARY, WIRE_X_FLAT_NE, WIRE_X_FLAT_SW, WIRE_X_FLAT_BOTH},
{INVALID_CATENARY, WIRE_Y_FLAT_SE, WIRE_Y_FLAT_NW, WIRE_Y_FLAT_BOTH},
+7 -7
View File
@@ -36,12 +36,12 @@ extern const TrackIndexArray<TrackdirBits> _track_crosses_trackdirs{
/** Maps a track to all tracks that make 90 deg turns with it. */
extern const TrackIndexArray<TrackBits> _track_crosses_tracks{
TRACK_BIT_Y, // TRACK_X
TRACK_BIT_X, // TRACK_Y
TRACK_BIT_VERT, // TRACK_UPPER
TRACK_BIT_VERT, // TRACK_LOWER
TRACK_BIT_HORZ, // TRACK_LEFT
TRACK_BIT_HORZ // TRACK_RIGHT
Track::Y, // Track::X
Track::X, // Track::Y
{Track::Left, Track::Right}, // Track::Upper
{Track::Left, Track::Right}, // Track::Lower
{Track::Upper, Track::Lower}, // Track::Left
{Track::Upper, Track::Lower}, // Track::Right
};
/** Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir. */
@@ -87,7 +87,7 @@ extern const DiagDirectionIndexArray<Trackdir> _dir_to_diag_trackdir{
/** Maps a single horizontal/vertical trackbit that is in a specific tile corner. */
extern const CornerIndexArray<TrackBits> _corner_to_trackbits{
TRACK_BIT_LEFT, TRACK_BIT_LOWER, TRACK_BIT_RIGHT, TRACK_BIT_UPPER,
Track::Left, Track::Lower, Track::Right, Track::Upper,
};
extern const TrackdirBits _uphill_trackdirs[] = {
+32 -79
View File
@@ -15,7 +15,6 @@
#include "direction_func.h"
#include "slope_func.h"
using SetTrackBitIterator = SetBitIterator<Track, TrackBits>;
using SetTrackdirBitIterator = SetBitIterator<Trackdir, TrackdirBits>;
/**
@@ -27,7 +26,7 @@ using SetTrackdirBitIterator = SetBitIterator<Trackdir, TrackdirBits>;
*/
inline bool IsValidTrack(Track track)
{
return track < TRACK_END;
return track < Track::End;
}
/**
@@ -56,8 +55,8 @@ inline bool IsValidTrackdir(Trackdir trackdir)
/**
* Convert an Axis to the corresponding Track
* Axis::X -> TRACK_X
* Axis::Y -> TRACK_Y
* Axis::X -> Track::X
* Axis::Y -> Track::Y
* Uses the fact that they share the same internal encoding
*
* @param a the axis to convert
@@ -69,27 +68,6 @@ inline Track AxisToTrack(Axis a)
return static_cast<Track>(to_underlying(a));
}
/**
* Maps a Track to the corresponding TrackBits value
* @param track the track to convert
* @return the converted TrackBits value of the track
*/
inline TrackBits TrackToTrackBits(Track track)
{
assert(IsValidTrack(track));
return (TrackBits)(1 << track);
}
/**
* Maps an Axis to the corresponding TrackBits value
* @param a the axis to convert
* @return the converted TrackBits value of the axis
*/
inline TrackBits AxisToTrackBits(Axis a)
{
return TrackToTrackBits(AxisToTrack(a));
}
/**
* Returns a single horizontal/vertical trackbit that is in a specific tile corner.
*
@@ -119,10 +97,10 @@ inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
*
* This function searches for the first bit in the TrackBits,
* remove this bit from the parameter and returns the found
* bit as Track value. It returns INVALID_TRACK if the
* parameter was TRACK_BIT_NONE. This
* is basically used in while-loops to get up to 6 possible
* tracks on a tile until the parameter becomes TRACK_BIT_NONE.
* bit as Track value. It returns Track::Invalid if the
* parameter was empty. This is basically used in while-loops
* to get up to 6 possible tracks on a tile until the parameter
* becomes empty.
*
* @param tracks The value with the TrackBits
* @return The first Track from the TrackBits value
@@ -130,13 +108,12 @@ inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
*/
inline Track RemoveFirstTrack(TrackBits *tracks)
{
if (*tracks != TRACK_BIT_NONE) {
assert((*tracks & ~TRACK_BIT_MASK) == TRACK_BIT_NONE);
Track first = (Track)FindFirstBit(*tracks);
ClrBit(*tracks, first);
return first;
}
return INVALID_TRACK;
if (tracks->None()) return Track::Invalid;
assert(!tracks->Any({Track::Wormhole, Track::Depot}));
Track first = tracks->GetNthSetBit(0).value();
tracks->Reset(first);
return first;
}
/**
@@ -165,18 +142,18 @@ inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
}
/**
* Returns first Track from TrackBits or INVALID_TRACK
* Returns first Track from TrackBits or Track::Invalid
*
* This function returns the first Track found in the TrackBits value as Track-value.
* It returns INVALID_TRACK if the parameter is TRACK_BIT_NONE.
* It returns Track::Invalid if the parameter is empty.
*
* @param tracks The TrackBits value
* @return The first Track found or INVALID_TRACK
* @return The first Track found or Track::Invalid
* @see RemoveFirstTrack
*/
inline Track FindFirstTrack(TrackBits tracks)
{
return (tracks != TRACK_BIT_NONE) ? (Track)FindFirstBit(tracks) : INVALID_TRACK;
return tracks.GetNthSetBit(0).value_or(Track::Invalid);
}
/**
@@ -192,8 +169,8 @@ inline Track FindFirstTrack(TrackBits tracks)
*/
inline Track TrackBitsToTrack(TrackBits tracks)
{
assert(tracks != TRACK_BIT_NONE && KillFirstBit(tracks & TRACK_BIT_MASK) == TRACK_BIT_NONE);
return static_cast<Track>(FindFirstBit(tracks & TRACK_BIT_MASK));
assert(tracks.Count() == 1 && !tracks.Any({Track::Wormhole, Track::Depot}));
return FindFirstTrack(tracks);
}
/**
@@ -222,8 +199,8 @@ inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
/**
* Find the opposite track to a given track.
*
* TRACK_LOWER -> TRACK_UPPER and vice versa, likewise for left/right.
* TRACK_X is mapped to TRACK_Y and reversed.
* Track::Lower -> Track::Upper and vice versa, likewise for left/right.
* Track::X is mapped to Track::Y and reversed.
*
* @param t the track to convert
* @return the opposite track
@@ -231,7 +208,7 @@ inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
inline Track TrackToOppositeTrack(Track t)
{
assert(IsValidTrack(t));
return (Track)(t ^ 1);
return static_cast<Track>(to_underlying(t) ^ 1);
}
/**
@@ -262,7 +239,7 @@ inline Trackdir ReverseTrackdir(Trackdir trackdir)
inline Track TrackdirToTrack(Trackdir trackdir)
{
assert(IsValidTrackdir(trackdir));
return (Track)(trackdir & 0x7);
return static_cast<Track>(trackdir & 0x7);
}
/**
@@ -307,7 +284,7 @@ inline TrackdirBits TrackToTrackdirBits(Track track)
*/
inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
{
return (TrackBits)((bits | (bits >> 8)) & TRACK_BIT_MASK);
return static_cast<TrackBits>((bits | (bits >> 8)) & TRACK_BIT_ALL.base());
}
/**
@@ -318,19 +295,7 @@ inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
*/
inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
{
return static_cast<TrackdirBits>(bits * 0x101);
}
/**
* Checks whether a TrackBits has a given Track.
* @param tracks The track bits.
* @param track The track to check.
* @return \c true iff \c track is in \c tracks.
*/
inline bool HasTrack(TrackBits tracks, Track track)
{
assert(IsValidTrack(track));
return HasBit(tracks, track);
return static_cast<TrackdirBits>(bits.base() * 0x101);
}
/**
@@ -404,7 +369,7 @@ inline DiagDirection TrackdirToExitdir(Trackdir trackdir)
*
* For the diagonal tracks the resulting track direction are clear for a given
* DiagDirection. It either matches the direction or it returns INVALID_TRACKDIR,
* as a TRACK_X cannot be applied with DIAG_SE.
* as a Track::X cannot be applied with DIAG_SE.
* For the straight tracks the resulting track direction will be the
* direction which the DiagDirection is pointing. But this will be INVALID_TRACKDIR
* if the DiagDirection is pointing 'away' the track.
@@ -430,7 +395,7 @@ inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
* For the straight tracks this returns the track direction which results if
* you follow the DiagDirection and then turn by 45 deg left or right on the
* next tile. The new direction on the new track will be the returning Trackdir
* value. If the parameters makes no sense like the track TRACK_UPPER and the
* value. If the parameters makes no sense like the track Track::Upper and the
* direction DiagDirection::NE (target track cannot be reached) this function returns
* INVALID_TRACKDIR.
*
@@ -473,18 +438,6 @@ inline Track DiagDirToDiagTrack(DiagDirection diagdir)
return static_cast<Track>(to_underlying(diagdir) & 1);
}
/**
* Maps a DiagDirection to the associated diagonal TrackBits.
*
* @param diagdir The direction
* @return The resulting TrackBits
*/
inline TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
{
assert(IsValidDiagDirection(diagdir));
return TrackToTrackBits(DiagDirToDiagTrack(diagdir));
}
/**
* Maps a (4-way) direction to the diagonal trackdir that runs in that
* direction.
@@ -577,7 +530,7 @@ inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
inline bool IsDiagonalTrack(Track track)
{
assert(IsValidTrack(track));
return (track == TRACK_X) || (track == TRACK_Y);
return (track == Track::X) || (track == Track::Y);
}
/**
@@ -603,7 +556,7 @@ inline bool IsDiagonalTrackdir(Trackdir trackdir)
inline bool TracksOverlap(TrackBits bits)
{
/* With no, or only one track, there is no overlap */
if (bits == TRACK_BIT_NONE || KillFirstBit(bits) == TRACK_BIT_NONE) return false;
if (bits.Count() <= 1) return false;
/* We know that there are at least two tracks present. When there are more
* than 2 tracks, they will surely overlap. When there are two, they will
* always overlap unless they are lower & upper or right & left. */
@@ -619,8 +572,8 @@ inline bool TracksOverlap(TrackBits bits)
*/
inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
{
if (HasBit(tracks, track)) return true;
return TracksOverlap(tracks | TrackToTrackBits(track));
if (tracks.Test(track)) return true;
return TracksOverlap(tracks | track);
}
/**
@@ -671,7 +624,7 @@ inline bool IsUphillTrackdir(Slope slope, Trackdir dir)
*/
inline DiagDirection VehicleExitDir(Direction direction, TrackBits track)
{
static constexpr DiagDirectionIndexArray<TrackBits> state_dir_table{TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER};
static const DiagDirectionIndexArray<TrackBits> state_dir_table{Track::Right, Track::Lower, Track::Left, Track::Upper};
DiagDirection diagdir = DirToDiagDir(direction);
+26 -36
View File
@@ -16,50 +16,40 @@
* These are used to specify a single track.
* Can be translated to a trackbit with TrackToTrackbit
*/
enum Track : uint8_t {
TRACK_BEGIN = 0, ///< Used for iterations
TRACK_X = 0, ///< Track along the x-axis (north-east to south-west)
TRACK_Y = 1, ///< Track along the y-axis (north-west to south-east)
TRACK_UPPER = 2, ///< Track in the upper corner of the tile (north)
TRACK_LOWER = 3, ///< Track in the lower corner of the tile (south)
TRACK_LEFT = 4, ///< Track in the left corner of the tile (west)
TRACK_RIGHT = 5, ///< Track in the right corner of the tile (east)
TRACK_END, ///< Used for iterations
INVALID_TRACK = 0xFF, ///< Flag for an invalid track
};
enum class Track : uint8_t {
Begin = 0, ///< Used for iterations
X = 0, ///< Track along the x-axis (north-east to south-west)
Y = 1, ///< Track along the y-axis (north-west to south-east)
Upper = 2, ///< Track in the upper corner of the tile (north)
Lower = 3, ///< Track in the lower corner of the tile (south)
Left = 4, ///< Track in the left corner of the tile (west)
Right = 5, ///< Track in the right corner of the tile (east)
End, ///< End marker (of regular track bits)
/** Allow incrementing of Track variables */
DECLARE_INCREMENT_DECREMENT_OPERATORS(Track)
Wormhole = 6, ///< Special flag indicating vehicle is inside a bridge or tunnel.
Depot = 7, ///< Special flag indicating a vehicle is inside a depot.
Invalid = 0xFF, ///< Flag for an invalid track
};
/**
* Array with \c Track as index.
* @tparam T the type contained within the array.
*/
template <typename T>
using TrackIndexArray = EnumIndexArray<T, Track, TRACK_END>;
using TrackIndexArray = EnumIndexArray<T, Track, Track::End>;
/** Bitfield corresponding to Track */
enum TrackBits : uint8_t {
TRACK_BIT_NONE = 0U, ///< No track
TRACK_BIT_X = 1U << TRACK_X, ///< X-axis track
TRACK_BIT_Y = 1U << TRACK_Y, ///< Y-axis track
TRACK_BIT_UPPER = 1U << TRACK_UPPER, ///< Upper track
TRACK_BIT_LOWER = 1U << TRACK_LOWER, ///< Lower track
TRACK_BIT_LEFT = 1U << TRACK_LEFT, ///< Left track
TRACK_BIT_RIGHT = 1U << TRACK_RIGHT, ///< Right track
TRACK_BIT_CROSS = TRACK_BIT_X | TRACK_BIT_Y, ///< X-Y-axis cross
TRACK_BIT_HORZ = TRACK_BIT_UPPER | TRACK_BIT_LOWER, ///< Upper and lower track
TRACK_BIT_VERT = TRACK_BIT_LEFT | TRACK_BIT_RIGHT, ///< Left and right track
TRACK_BIT_3WAY_NE = TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT,///< "Arrow" to the north-east
TRACK_BIT_3WAY_SE = TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_RIGHT,///< "Arrow" to the south-east
TRACK_BIT_3WAY_SW = TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_LEFT, ///< "Arrow" to the south-west
TRACK_BIT_3WAY_NW = TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_LEFT, ///< "Arrow" to the north-west
TRACK_BIT_ALL = TRACK_BIT_CROSS | TRACK_BIT_HORZ | TRACK_BIT_VERT, ///< All possible tracks
TRACK_BIT_MASK = 0x3FU, ///< Bitmask for the first 6 bits
TRACK_BIT_WORMHOLE = 0x40U, ///< Bitflag for a wormhole (used for tunnels)
TRACK_BIT_DEPOT = 0x80U, ///< Bitflag for a depot
};
DECLARE_ENUM_AS_BIT_SET(TrackBits)
/** Bitset of \c Track elements. */
using TrackBits = EnumBitSet<Track, uint8_t>;
static constexpr TrackBits TRACK_BIT_CROSS = {Track::X, Track::Y}; ///< X-Y-axis cross
static constexpr TrackBits TRACK_BIT_HORZ = {Track::Upper, Track::Lower}; ///< Upper and lower track
static constexpr TrackBits TRACK_BIT_VERT = {Track::Left, Track::Right}; ///< Left and right track
static constexpr TrackBits TRACK_BIT_3WAY_NE = {Track::X, Track::Upper, Track::Right}; ///< "Arrow" to the north-east
static constexpr TrackBits TRACK_BIT_3WAY_SE = {Track::Y, Track::Lower, Track::Right}; ///< "Arrow" to the south-east
static constexpr TrackBits TRACK_BIT_3WAY_SW = {Track::X, Track::Lower, Track::Left}; ///< "Arrow" to the south-west
static constexpr TrackBits TRACK_BIT_3WAY_NW = {Track::Y, Track::Upper, Track::Left}; ///< "Arrow" to the north-west
static constexpr TrackBits TRACK_BIT_ALL = {Track::X, Track::Y, Track::Upper, Track::Lower, Track::Left, Track::Right}; ///< All possible tracks
/**
* Enumeration for tracks and directions.
+3 -3
View File
@@ -128,7 +128,7 @@ struct Train final : public GroundVehicle<Train, VehicleType::Train> {
Money GetRunningCost() const override;
int GetCursorImageOffset() const;
int GetDisplayImageWidth(Point *offset = nullptr) const;
bool IsInDepot() const override { return this->track == TRACK_BIT_DEPOT; }
bool IsInDepot() const override { return this->track == Track::Depot; }
bool Tick() override;
void OnNewCalendarDay() override;
void OnNewEconomyDay() override;
@@ -272,7 +272,7 @@ protected: // These functions should not be called outside acceleration code.
inline uint8_t GetAirDragArea() const
{
/* Air drag is higher in tunnels due to the limited cross-section. */
return (this->track == TRACK_BIT_WORMHOLE && this->vehstatus.Test(VehState::Hidden)) ? 28 : 14;
return (this->track == Track::Wormhole && this->vehstatus.Test(VehState::Hidden)) ? 28 : 14;
}
/**
@@ -348,7 +348,7 @@ protected: // These functions should not be called outside acceleration code.
inline bool TileMayHaveSlopedTrack() const
{
/* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */
return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
return this->track == Track::X || this->track == Track::Y;
}
/**
+72 -72
View File
@@ -82,10 +82,10 @@ void CheckTrainsLengths()
for (const Train *v : Train::Iterate()) {
if (v->First() == v && !v->vehstatus.Test(VehState::Crashed)) {
for (const Train *u = v->GetMovingFront(), *w = v->GetMovingNext(); w != nullptr; u = w, w = w->GetMovingNext()) {
if (u->track != TRACK_BIT_DEPOT) {
if ((w->track != TRACK_BIT_DEPOT &&
if (u->track != Track::Depot) {
if ((w->track != Track::Depot &&
std::max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->CalcNextVehicleOffset()) ||
(w->track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) {
(w->track == Track::Depot && TicksToLeaveDepot(u) <= 0)) {
ShowErrorMessage(GetEncodedString(STR_BROKEN_VEHICLE_LENGTH, v->index, v->owner), {}, WarningLevel::Critical);
if (!_networking && first) {
@@ -417,14 +417,14 @@ int Train::GetCurrentMaxSpeed() const
}
for (const Train *u = this; u != nullptr; u = u->Next()) {
if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == TRACK_BIT_DEPOT) {
if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == Track::Depot) {
constexpr int DEPOT_SPEED_LIMIT = 61;
max_speed = std::min(max_speed, DEPOT_SPEED_LIMIT);
break;
}
/* Vehicle is on the middle part of a bridge. */
if (u->track == TRACK_BIT_WORMHOLE && !u->vehstatus.Test(VehState::Hidden)) {
if (u->track == Track::Wormhole && !u->vehstatus.Test(VehState::Hidden)) {
max_speed = std::min<int>(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed);
}
}
@@ -687,7 +687,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlags flags, TileIndex tile, const
v->y_pos = y;
v->z_pos = GetSlopePixelZ(x, y, true);
v->owner = _current_company;
v->track = TRACK_BIT_DEPOT;
v->track = Track::Depot;
v->vehstatus = {VehState::Hidden, VehState::DefaultPalette};
v->SetWagon();
@@ -762,7 +762,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v)
u->x_pos = v->x_pos;
u->y_pos = v->y_pos;
u->z_pos = v->z_pos;
u->track = TRACK_BIT_DEPOT;
u->track = Track::Depot;
u->vehstatus = v->vehstatus;
u->vehstatus.Reset(VehState::Stopped);
u->spritenum = v->spritenum + 1;
@@ -820,7 +820,7 @@ CommandCost CmdBuildRailVehicle(DoCommandFlags flags, TileIndex tile, const Engi
v->x_pos = x;
v->y_pos = y;
v->z_pos = GetSlopePixelZ(x, y, true);
v->track = TRACK_BIT_DEPOT;
v->track = Track::Depot;
v->vehstatus = {VehState::Hidden, VehState::Stopped, VehState::DefaultPalette};
v->spritenum = rvi->image_index;
v->cargo_type = e->GetDefaultCargoType();
@@ -1652,17 +1652,17 @@ static void UpdateStatusAfterSwap(Train *v, bool reverse = true)
if (reverse) v->direction = ReverseDir(v->direction);
/* Call the proper EnterTile function unless we are in a wormhole. */
if (v->track != TRACK_BIT_WORMHOLE) {
if (v->track != Track::Wormhole) {
VehicleEnterTile(v, v->tile, v->x_pos, v->y_pos);
} else {
/* VehicleEnterTile_TunnelBridge() sets TRACK_BIT_WORMHOLE when the vehicle
/* VehicleEnterTile_TunnelBridge() sets Track::Wormhole when the vehicle
* is on the last bit of the bridge head (frame == TILE_SIZE - 1).
* If we were swapped with such a vehicle, we have set TRACK_BIT_WORMHOLE,
* If we were swapped with such a vehicle, we have set Track::Wormhole,
* when we shouldn't have. Check if this is the case. */
TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
if (IsTileType(vt, TileType::TunnelBridge)) {
VehicleEnterTile(v, vt, v->x_pos, v->y_pos);
if (v->track != TRACK_BIT_WORMHOLE && IsBridgeTile(v->tile)) {
if (v->track != Track::Wormhole && IsBridgeTile(v->tile)) {
/* We have just left the wormhole, possibly set the
* "goingdown" bit. UpdateInclination() can be used
* because we are at the border of the tile. */
@@ -1969,7 +1969,7 @@ static void AdvanceWagonsAfterSwap(Train *moving_front)
{
/* first of all, fix the situation when the train was entering a depot */
Train *dep = moving_front; // last vehicle in front of just left depot
while (dep->GetMovingNext() != nullptr && (dep->track == TRACK_BIT_DEPOT || dep->GetMovingNext()->track != TRACK_BIT_DEPOT)) {
while (dep->GetMovingNext() != nullptr && (dep->track == Track::Depot || dep->GetMovingNext()->track != Track::Depot)) {
dep = dep->GetMovingNext(); // find first vehicle outside of a depot, with next vehicle inside a depot
}
@@ -1981,7 +1981,7 @@ static void AdvanceWagonsAfterSwap(Train *moving_front)
if (d <= 0) {
leave->vehstatus.Reset(VehState::Hidden); // move it out of the depot
leave->track = TrackToTrackBits(GetRailDepotTrack(leave->tile));
leave->track = GetRailDepotTrack(leave->tile);
for (int i = 0; i >= d; i--) TrainController(leave, nullptr); // maybe move it, and maybe let another wagon leave
}
} else {
@@ -2021,7 +2021,7 @@ static void AdvanceWagonsAfterSwap(Train *moving_front)
static bool IsWholeTrainInsideDepot(const Train *v)
{
for (const Train *u = v; u != nullptr; u = u->Next()) {
if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
if (u->track != Track::Depot || u->tile != v->tile) return false;
}
return true;
}
@@ -2090,7 +2090,7 @@ static void ReverseTrainDirection(Train *consist)
if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing);
/* If we are inside a depot after reversing, don't bother with path reserving. */
if (moving_front->track == TRACK_BIT_DEPOT) {
if (moving_front->track == Track::Depot) {
/* Can't be stuck here as inside a depot is always a safe tile. */
if (consist->flags.Test(VehicleRailFlag::Stuck)) SetWindowWidgetDirty(WindowClass::VehicleView, consist->index, WID_VV_START_STOP);
consist->flags.Reset(VehicleRailFlag::Stuck);
@@ -2217,7 +2217,7 @@ static TrainForceProceeding DetermineNextTrainForceProceeding(const Train *t)
TileIndex next_tile = TileAddByDiagDir(moving_front->tile, TrackdirToExitdir(moving_front->GetVehicleTrackdir()));
if (next_tile == INVALID_TILE || !IsTileType(next_tile, TileType::Railway) || !HasSignals(next_tile)) return TFP_STUCK;
TrackBits new_tracks = DiagdirReachesTracks(TrackdirToExitdir(moving_front->GetVehicleTrackdir())) & GetTrackBits(next_tile);
return new_tracks != TRACK_BIT_NONE && HasSignalOnTrack(next_tile, FindFirstTrack(new_tracks)) ? TFP_SIGNAL : TFP_STUCK;
return new_tracks.Any() && HasSignalOnTrack(next_tile, FindFirstTrack(new_tracks)) ? TFP_SIGNAL : TFP_STUCK;
}
/**
@@ -2297,7 +2297,7 @@ static void CheckNextTrainTile(Train *consist)
const Train *moving_front = consist->GetMovingFront();
/* Exit if we are inside a depot. */
if (moving_front->track == TRACK_BIT_DEPOT) return;
if (moving_front->track == Track::Depot) return;
switch (consist->current_order.GetType()) {
/* Exit if we reached our destination depot. */
@@ -2338,7 +2338,7 @@ static void CheckNextTrainTile(Train *consist)
/* If the next tile is a PBS signal, try to make a reservation. */
TrackBits tracks = TrackdirBitsToTrackBits(ft.new_td_bits);
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.old_td));
tracks.Reset(TrackCrossesTracks(TrackdirToTrack(ft.old_td)));
}
ChooseTrainTrack(consist, ft.new_tile, ft.exitdir, tracks, false, nullptr, false);
}
@@ -2355,7 +2355,7 @@ static bool CheckTrainStayInDepot(Train *v)
{
/* bail out if not all wagons are in the same depot or not in a depot at all */
for (const Train *u = v; u != nullptr; u = u->Next()) {
if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
if (u->track != Track::Depot || u->tile != v->tile) return false;
}
/* if the train got no power, then keep it in the depot */
@@ -2412,7 +2412,7 @@ static bool CheckTrainStayInDepot(Train *v)
v->PlayLeaveStationSound();
SetWindowClassesDirty(WindowClass::TrainList);
v->track = AxisToTrackBits(DiagDirToAxis(DirToDiagDir(v->direction)));
v->track = AxisToTrack(DiagDirToAxis(DirToDiagDir(v->direction)));
v->vehstatus.Reset(VehState::Hidden);
v->cur_speed = 0;
@@ -2485,14 +2485,14 @@ void FreeTrainTrackReservation(const Train *consist)
/* Can't be holding a reservation if we enter a depot. */
if (IsRailDepotTile(tile) && TrackdirToExitdir(td) != GetRailDepotDirection(tile)) return;
if (moving_front->track == TRACK_BIT_DEPOT) {
if (moving_front->track == Track::Depot) {
/* Front engine is in a depot. We enter if some part is not in the depot. */
for (const Train *u = consist; u != nullptr; u = u->Next()) {
if (u->track != TRACK_BIT_DEPOT || u->tile != consist->tile) return;
if (u->track != Track::Depot || u->tile != consist->tile) return;
}
}
/* Don't free reservation if it's not ours. */
if (TracksOverlap(GetReservedTrackbits(tile) | TrackToTrackBits(TrackdirToTrack(td)))) return;
if (TracksOverlap(GetReservedTrackbits(tile) | TrackdirToTrack(td))) return;
CFollowTrackRail ft(consist, GetAllCompatibleRailTypes(consist->railtypes));
while (ft.Follow(tile, td)) {
@@ -2778,22 +2778,22 @@ public:
/* choose a track */
static Track ChooseTrainTrack(Train *consist, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
{
Track best_track = INVALID_TRACK;
Track best_track = Track::Invalid;
bool do_track_reservation = _settings_game.pf.reserve_paths || force_res;
bool changed_signal = false;
TileIndex final_dest = INVALID_TILE;
assert((tracks & ~TRACK_BIT_MASK) == 0);
assert(tracks == (tracks & TRACK_BIT_ALL));
if (got_reservation != nullptr) *got_reservation = false;
/* Don't use tracks here as the setting to forbid 90 deg turns might have been switched between reservation and now. */
TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir));
TrackBits res_tracks = GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir);
/* Do we have a suitable reserved track? */
if (res_tracks != TRACK_BIT_NONE) return FindFirstTrack(res_tracks);
if (res_tracks.Any()) return FindFirstTrack(res_tracks);
/* Quick return in case only one possible track is available */
if (KillFirstBit(tracks) == TRACK_BIT_NONE) {
if (tracks.Count() == 1) {
Track track = FindFirstTrack(tracks);
/* We need to check for signals only here, as a junction tile can't have signals. */
if (IsValidTrack(track) && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) {
@@ -2897,7 +2897,7 @@ static Track ChooseTrainTrack(Train *consist, TileIndex tile, DiagDirection ente
TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir);
TrackBits reachable = TrackdirBitsToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & DiagdirReachesTracks(exitdir);
if (Rail90DegTurnDisallowed(GetTileRailType(res_dest.tile), GetTileRailType(next_tile))) {
reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir));
reachable.Reset(TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir)));
}
/* Get next order with destination. */
@@ -2959,7 +2959,7 @@ bool TryPathReserve(Train *consist, bool mark_as_stuck, bool first_tile_okay)
/* We have to handle depots specially as the track follower won't look
* at the depot tile itself but starts from the next tile. If we are still
* inside the depot, a depot reservation can never be ours. */
if (moving_front->track == TRACK_BIT_DEPOT) {
if (moving_front->track == Track::Depot) {
if (HasDepotReservation(moving_front->tile)) {
if (mark_as_stuck) MarkTrainAsStuck(consist);
return false;
@@ -2990,7 +2990,7 @@ bool TryPathReserve(Train *consist, bool mark_as_stuck, bool first_tile_okay)
}
/* If we are in a depot, tentatively reserve the depot. */
if (moving_front->track == TRACK_BIT_DEPOT) {
if (moving_front->track == Track::Depot) {
SetDepotReservation(moving_front->tile, true);
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(moving_front->tile);
}
@@ -2999,14 +2999,14 @@ bool TryPathReserve(Train *consist, bool mark_as_stuck, bool first_tile_okay)
TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir);
TrackBits reachable = TrackdirBitsToTrackBits(GetTileTrackStatus(new_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs & DiagdirReachesTrackdirs(exitdir));
if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir));
if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable.Reset(TrackCrossesTracks(TrackdirToTrack(origin.trackdir)));
bool res_made = false;
ChooseTrainTrack(consist, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck);
if (!res_made) {
/* Free the depot reservation as well. */
if (moving_front->track == TRACK_BIT_DEPOT) SetDepotReservation(moving_front->tile, false);
if (moving_front->track == Track::Depot) SetDepotReservation(moving_front->tile, false);
return false;
}
@@ -3027,12 +3027,12 @@ static bool CheckReverseTrain(const Train *consist)
{
const Train *moving_front = consist->GetMovingFront();
if (_settings_game.difficulty.train_flip_reverse_allowed == TrainFlipReversingAllowed::EndOfLineOnly ||
moving_front->track == TRACK_BIT_DEPOT || moving_front->track == TRACK_BIT_WORMHOLE ||
moving_front->track == Track::Depot || moving_front->track == Track::Wormhole ||
!IsDiagonalDirection(moving_front->GetMovingDirection())) {
return false;
}
assert(moving_front->track != TRACK_BIT_NONE);
assert(moving_front->track.Any());
return YapfTrainCheckReverse(consist);
}
@@ -3188,11 +3188,11 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
void Train::ReserveTrackUnderConsist() const
{
for (const Train *u = this; u != nullptr; u = u->Next()) {
switch (u->track) {
case TRACK_BIT_WORMHOLE:
switch (u->track.base()) {
case TrackBits{Track::Wormhole}.base():
TryReserveRailTrack(u->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(u->tile)));
break;
case TRACK_BIT_DEPOT:
case TrackBits{Track::Depot}.base():
break;
default:
TryReserveRailTrack(u->tile, TrackBitsToTrack(u->track));
@@ -3277,7 +3277,7 @@ static uint CheckTrainCollision(Vehicle *v, Train *moving_front)
if (v->type != VehicleType::Train) return 0;
/* We can't crash into trains in a depot. */
if (Train::From(v)->track == TRACK_BIT_DEPOT) return 0;
if (Train::From(v)->track == Track::Depot) return 0;
/* Do not crash into trains of another company. */
if (v->owner != moving_front->First()->owner) return 0;
@@ -3319,14 +3319,14 @@ static uint CheckTrainCollision(Vehicle *v, Train *moving_front)
static bool CheckTrainCollision(Train *moving_front)
{
/* can't collide in depot */
if (moving_front->track == TRACK_BIT_DEPOT) return false;
if (moving_front->track == Track::Depot) return false;
assert(moving_front->track == TRACK_BIT_WORMHOLE || TileVirtXY(moving_front->x_pos, moving_front->y_pos) == moving_front->tile);
assert(moving_front->track == Track::Wormhole || TileVirtXY(moving_front->x_pos, moving_front->y_pos) == moving_front->tile);
uint num_victims = 0;
/* find colliding vehicles */
if (moving_front->track == TRACK_BIT_WORMHOLE) {
if (moving_front->track == Track::Wormhole) {
for (Vehicle *u : VehiclesOnTile(moving_front->tile)) {
num_victims += CheckTrainCollision(u, moving_front);
}
@@ -3368,11 +3368,11 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
bool update_signals_crossing = false; // will we update signals or crossing state?
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
if (v->track != TRACK_BIT_WORMHOLE) {
if (v->track != Track::Wormhole) {
/* Not inside tunnel */
if (gp.old_tile == gp.new_tile) {
/* Staying in the old tile */
if (v->track == TRACK_BIT_DEPOT) {
if (v->track == Track::Depot) {
/* Inside depot */
gp.x = v->x_pos;
gp.y = v->y_pos;
@@ -3410,10 +3410,10 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
if (Rail90DegTurnDisallowed(GetTileRailType(gp.old_tile), GetTileRailType(gp.new_tile)) && prev == nullptr) {
/* We allow wagons to make 90 deg turns, because forbid_90_deg
* can be switched on halfway a turn */
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
bits.Reset(TrackCrossesTracks(FindFirstTrack(v->track)));
}
if (bits == TRACK_BIT_NONE) goto invalid_rail;
if (bits.None()) goto invalid_rail;
/* Check if the new tile constrains tracks that are compatible
* with the current train, if not, bail out. */
@@ -3423,8 +3423,8 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
if (v->IsMovingFront()) {
/* Currently the locomotive is active. Determine which one of the
* available tracks to choose */
chosen_track = TrackToTrackBits(ChooseTrainTrack(first, gp.new_tile, enterdir, bits, false, nullptr, true));
assert(chosen_track & (bits | GetReservedTrackbits(gp.new_tile)));
chosen_track = ChooseTrainTrack(first, gp.new_tile, enterdir, bits, false, nullptr, true);
assert(chosen_track.Any(bits | GetReservedTrackbits(gp.new_tile)));
if (first->force_proceed != TFP_NONE && IsPlainRailTile(gp.new_tile) && HasSignals(gp.new_tile)) {
/* For each signal we find decrease the counter by one.
@@ -3443,7 +3443,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
}
/* Check if it's a red signal and that force proceed is not clicked. */
if ((red_signals & chosen_track) && first->force_proceed == TFP_NONE) {
if (red_signals.Any(chosen_track) && first->force_proceed == TFP_NONE) {
/* In front of a red signal */
Trackdir i = FindFirstTrackdir(trackdirbits);
@@ -3471,7 +3471,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
const Train *t = Train::From(u);
/* not front engine of a train, inside wormhole or depot, crashed */
if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return false;
if (!t->IsFrontEngine() || t->track.Any({Track::Wormhole, Track::Depot})) return false;
if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return false;
@@ -3497,7 +3497,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
/* The wagon is active, simply follow the prev vehicle. */
if (prev->tile == gp.new_tile) {
/* Choose the same track as prev */
if (prev->track == TRACK_BIT_WORMHOLE) {
if (prev->track == Track::Wormhole) {
/* Vehicles entering tunnels enter the wormhole earlier than for bridges.
* However, just choose the track into the wormhole. */
assert(IsTunnel(prev->tile));
@@ -3514,10 +3514,10 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
* Is also the train just reversing, the wagon inside the tunnel is 'on' the tile of the opposite tunnel entry.
*/
static const DiagDirectionIndexArray<DiagDirectionIndexArray<TrackBits>> _connecting_track{{{
{TRACK_BIT_X, TRACK_BIT_LOWER, TRACK_BIT_NONE, TRACK_BIT_LEFT },
{TRACK_BIT_UPPER, TRACK_BIT_Y, TRACK_BIT_LEFT, TRACK_BIT_NONE },
{TRACK_BIT_NONE, TRACK_BIT_RIGHT, TRACK_BIT_X, TRACK_BIT_UPPER},
{TRACK_BIT_RIGHT, TRACK_BIT_NONE, TRACK_BIT_LOWER, TRACK_BIT_Y }
{{{Track::X, Track::Lower, {}, Track::Left }}},
{{{Track::Upper, Track::Y, Track::Left, {} }}},
{{{{}, Track::Right, Track::X, Track::Upper}}},
{{{Track::Right, {}, Track::Lower, Track::Y }}}
}}};
DiagDirection exitdir = DiagdirBetweenTiles(gp.new_tile, prev->tile);
assert(IsValidDiagDirection(exitdir));
@@ -3553,7 +3553,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
}
v->track = chosen_track;
assert(v->track);
assert(v->track.Any());
}
/* We need to update signal status, but after the vehicle position hash
@@ -3720,9 +3720,9 @@ static void DeleteLastWagon(Train *v)
delete v;
v = nullptr; // make sure nobody will try to read 'v' anymore
if (trackbits == TRACK_BIT_WORMHOLE) {
if (trackbits == Track::Wormhole) {
/* Vehicle is inside a wormhole, v->track contains no useful value then. */
trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(tile));
trackbits = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
}
Track track = TrackBitsToTrack(trackbits);
@@ -3730,21 +3730,21 @@ static void DeleteLastWagon(Train *v)
UnreserveRailTrack(tile, track);
/* If there are still crashed vehicles on the tile, give the track reservation to them */
TrackBits remaining_trackbits = TRACK_BIT_NONE;
TrackBits remaining_trackbits{};
for (const Vehicle *u : VehiclesOnTile(tile)) {
if (u->type != VehicleType::Train || !u->vehstatus.Test(VehState::Crashed)) continue;
TrackBits train_tbits = Train::From(u)->track;
if (train_tbits == TRACK_BIT_WORMHOLE) {
if (train_tbits == Track::Wormhole) {
/* Vehicle is inside a wormhole, u->track contains no useful value then. */
remaining_trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile));
} else if (train_tbits != TRACK_BIT_DEPOT) {
remaining_trackbits |= train_tbits;
remaining_trackbits.Set(DiagDirToDiagTrack(GetTunnelBridgeDirection(u->tile)));
} else if (train_tbits != Track::Depot) {
remaining_trackbits.Set(train_tbits);
}
}
/* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */
assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1);
for (Track t : SetTrackBitIterator(remaining_trackbits)) TryReserveRailTrack(tile, t);
assert(Track::Begin == Track::X && to_underlying(Track::Y) == to_underlying(Track::Begin) + 1);
for (Track t : remaining_trackbits) TryReserveRailTrack(tile, t);
}
/* check if the wagon was on a road/rail-crossing */
@@ -3782,7 +3782,7 @@ static void ChangeTrainDirRandomly(Train *v)
/* Refrain from updating the z position of the vehicle when on
* a bridge, because UpdateInclination() will put the vehicle under
* the bridge in that case */
if (v->track != TRACK_BIT_WORMHOLE) {
if (v->track != Track::Wormhole) {
v->UpdatePosition();
v->UpdateInclination(false, true);
} else {
@@ -3902,7 +3902,7 @@ static bool TrainApproachingLineEnd(Train *moving_front, bool signal, bool rever
static bool TrainCanLeaveTile(const Train *moving_front)
{
/* Exit if inside a tunnel/bridge or a depot */
if (moving_front->track == TRACK_BIT_WORMHOLE || moving_front->track == TRACK_BIT_DEPOT) return false;
if (moving_front->track == Track::Wormhole || moving_front->track == Track::Depot) return false;
TileIndex tile = moving_front->tile;
@@ -3990,11 +3990,11 @@ static bool TrainCheckIfLineEnds(Train *moving_front, bool reverse)
/* mask unreachable track bits if we are forbidden to do 90deg turns */
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
if (Rail90DegTurnDisallowed(GetTileRailType(moving_front->tile), GetTileRailType(tile))) {
bits &= ~TrackCrossesTracks(FindFirstTrack(moving_front->track));
bits.Reset(TrackCrossesTracks(FindFirstTrack(moving_front->track)));
}
/* no suitable trackbits at all || unusable rail (wrong type or owner) */
if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(consist, tile, true)) {
if (bits.None() || !CheckCompatibleRail(consist, tile, true)) {
return TrainApproachingLineEnd(moving_front, false, reverse);
}
@@ -4300,12 +4300,12 @@ Trackdir Train::GetVehicleTrackdir() const
{
if (this->vehstatus.Test(VehState::Crashed)) return INVALID_TRACKDIR;
if (this->track == TRACK_BIT_DEPOT) {
if (this->track == Track::Depot) {
/* We'll assume the train is facing outwards */
return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot
}
if (this->track == TRACK_BIT_WORMHOLE) {
if (this->track == Track::Wormhole) {
/* train in tunnel or on bridge, so just use its direction and assume a diagonal track */
return DiagDirToDiagTrackdir(DirToDiagDir(this->GetMovingDirection()));
}
+11 -11
View File
@@ -1857,7 +1857,7 @@ static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType
DiagDirection dir = GetTunnelBridgeDirection(tile);
if (side != DiagDirection::Invalid && side != ReverseDiagDir(dir)) return {};
return {TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE};
return {TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir)), TRACKDIR_BIT_NONE};
}
/** @copydoc ChangeTileOwnerProc */
@@ -1974,7 +1974,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
if (v->type == VehicleType::Train) {
Train *t = Train::From(v);
if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
if (t->track != Track::Wormhole && dir == vdir) {
if (t->IsMovingFront() && frame == TUNNEL_SOUND_FRAME) {
if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == EngineClass::Steam) {
SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
@@ -1983,7 +1983,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
}
if (frame == _tunnel_visibility_frame[dir]) {
t->tile = tile;
t->track = TRACK_BIT_WORMHOLE;
t->track = Track::Wormhole;
t->vehstatus.Set(VehState::Hidden);
return VehicleEnterTileState::EnteredWormhole;
}
@@ -1992,8 +1992,8 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
/* We're at the tunnel exit ?? */
t->tile = tile;
t->track = DiagDirToDiagTrackBits(vdir);
assert(t->track);
t->track = DiagDirToDiagTrack(vdir);
assert(t->track.Any());
t->vehstatus.Reset(VehState::Hidden);
return VehicleEnterTileState::EnteredWormhole;
}
@@ -2039,7 +2039,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
switch (v->type) {
case VehicleType::Train: {
Train *t = Train::From(v);
t->track = TRACK_BIT_WORMHOLE;
t->track = Track::Wormhole;
PrepareToEnterBridge(t);
break;
}
@@ -2052,7 +2052,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
}
case VehicleType::Ship:
Ship::From(v)->state = TRACK_BIT_WORMHOLE;
Ship::From(v)->state = Track::Wormhole;
break;
default: NOT_REACHED();
@@ -2063,8 +2063,8 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
switch (v->type) {
case VehicleType::Train: {
Train *t = Train::From(v);
if (t->track == TRACK_BIT_WORMHOLE) {
t->track = DiagDirToDiagTrackBits(vdir);
if (t->track == Track::Wormhole) {
t->track = DiagDirToDiagTrack(vdir);
return VehicleEnterTileState::EnteredWormhole;
}
break;
@@ -2082,8 +2082,8 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
case VehicleType::Ship: {
Ship *ship = Ship::From(v);
if (ship->state == TRACK_BIT_WORMHOLE) {
ship->state = DiagDirToDiagTrackBits(vdir);
if (ship->state == Track::Wormhole) {
ship->state = DiagDirToDiagTrack(vdir);
return VehicleEnterTileState::EnteredWormhole;
}
break;
+1 -1
View File
@@ -116,7 +116,7 @@ inline void SetTunnelBridgeReservation(Tile t, bool b)
*/
inline TrackBits GetTunnelBridgeReservationTrackBits(Tile t)
{
return HasTunnelBridgeReservation(t) ? DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)) : TRACK_BIT_NONE;
return HasTunnelBridgeReservation(t) ? DiagDirToDiagTrack(GetTunnelBridgeDirection(t)) : TrackBits{};
}
#endif /* TUNNELBRIDGE_MAP_H */
+1 -1
View File
@@ -1587,7 +1587,7 @@ void VehicleEnterDepot(Vehicle *v)
case VehicleType::Ship: {
SetWindowClassesDirty(WindowClass::ShipList);
Ship *ship = Ship::From(v);
ship->state = TRACK_BIT_DEPOT;
ship->state = Track::Depot;
ship->UpdateCache();
ship->UpdateViewport(true, true);
SetWindowDirty(WindowClass::VehicleDepot, v->tile);
+12 -13
View File
@@ -186,7 +186,7 @@ bool IsPossibleDockingTile(Tile t)
case TileType::Railway:
case TileType::Station:
case TileType::TunnelBridge:
return TrackdirBitsToTrackBits(GetTileTrackStatus(t, TRANSPORT_WATER, RoadTramType::Invalid).trackdirs) != TRACK_BIT_NONE;
return TrackdirBitsToTrackBits(GetTileTrackStatus(t, TRANSPORT_WATER, RoadTramType::Invalid).trackdirs).Any();
default:
return false;
@@ -1254,11 +1254,11 @@ static void DoDryUp(TileIndex tile)
assert(GetRailGroundType(tile) == RailGroundType::HalfTileWater);
RailGroundType new_ground;
switch (GetTrackBits(tile)) {
case TRACK_BIT_UPPER: new_ground = RailGroundType::FenceHoriz1; break;
case TRACK_BIT_LOWER: new_ground = RailGroundType::FenceHoriz2; break;
case TRACK_BIT_LEFT: new_ground = RailGroundType::FenceVert1; break;
case TRACK_BIT_RIGHT: new_ground = RailGroundType::FenceVert2; break;
switch (TrackBitsToTrack(GetTrackBits(tile))) {
case Track::Upper: new_ground = RailGroundType::FenceHoriz1; break;
case Track::Lower: new_ground = RailGroundType::FenceHoriz2; break;
case Track::Left: new_ground = RailGroundType::FenceVert1; break;
case Track::Right: new_ground = RailGroundType::FenceVert2; break;
default: NOT_REACHED();
}
SetRailGroundType(tile, new_ground);
@@ -1382,27 +1382,26 @@ void ConvertGroundTilesIntoWaterTiles()
/** @copydoc GetTileTrackStatusProc */
static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, [[maybe_unused]] RoadTramType sub_mode, [[maybe_unused]] DiagDirection side)
{
static const TrackBits coast_tracks[] = {TRACK_BIT_NONE, TRACK_BIT_RIGHT, TRACK_BIT_UPPER, TRACK_BIT_NONE, TRACK_BIT_LEFT, TRACK_BIT_NONE, TRACK_BIT_NONE,
TRACK_BIT_NONE, TRACK_BIT_LOWER, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE};
static const TrackBits coast_tracks[] = {{}, Track::Right, Track::Upper, {}, Track::Left, {}, {}, {}, Track::Lower, {}, {}, {}, {}, {}, {}, {}};
TrackBits ts;
if (mode != TRANSPORT_WATER) return {};
switch (GetWaterTileType(tile)) {
case WaterTileType::Clear: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
case WaterTileType::Clear: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TrackBits{}; break;
case WaterTileType::Coast: ts = coast_tracks[GetTileSlope(tile) & 0xF]; break;
case WaterTileType::Lock: ts = DiagDirToDiagTrackBits(GetLockDirection(tile)); break;
case WaterTileType::Depot: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
case WaterTileType::Lock: ts = DiagDirToDiagTrack(GetLockDirection(tile)); break;
case WaterTileType::Depot: ts = AxisToTrack(GetShipDepotAxis(tile)); break;
default: return {};
}
if (TileX(tile) == 0) {
/* NE border: remove tracks that connects NE tile edge */
ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
ts.Reset({Track::X, Track::Upper, Track::Right});
}
if (TileY(tile) == 0) {
/* NW border: remove tracks that connects NW tile edge */
ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
ts.Reset({Track::Y, Track::Left, Track::Upper});
}
return {TrackBitsToTrackdirBits(ts), TRACKDIR_BIT_NONE};
}
+5 -6
View File
@@ -111,11 +111,10 @@ Axis GetAxisForNewRailWaypoint(TileIndex tile)
/* Non-plain rail type, no valid axis for waypoints. */
if (!IsTileType(tile, TileType::Railway) || GetRailTileType(tile) != RailTileType::Normal) return Axis::Invalid;
switch (GetTrackBits(tile)) {
case TRACK_BIT_X: return Axis::X;
case TRACK_BIT_Y: return Axis::Y;
default: return Axis::Invalid;
}
TrackBits bits = GetTrackBits(tile);
if (bits == Track::X) return Axis::X;
if (bits == Track::Y) return Axis::Y;
return Axis::Invalid;
}
/**
@@ -325,7 +324,7 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi
uint8_t old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0;
if (!HasStationTileRail(tile)) c->infrastructure.station++;
bool reserved = IsTileType(tile, TileType::Railway) ?
HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis)) :
GetRailReservationTrackBits(tile).Test(AxisToTrack(axis)) :
HasStationReservation(tile);
MakeRailWaypoint(tile, wp->owner, wp->index, axis, *it, GetRailType(tile));
SetCustomStationSpecIndex(tile, *specindex);