From 7ab28f604556fe213851a40c430544c66db8551e Mon Sep 17 00:00:00 2001 From: J0anJosep Date: Sat, 20 Mar 2021 19:50:19 +0100 Subject: [PATCH] Add: Code dealing with extended rail depot platforms. --- src/depot.cpp | 33 ++++- src/pathfinder/follow_track.hpp | 47 ++++-- src/pathfinder/yapf/yapf_costrail.hpp | 4 +- src/pbs.cpp | 22 +-- src/platform.cpp | 205 ++++++++++++++++++++++++++ src/platform_func.h | 35 +++++ src/platform_type.h | 1 + src/train_cmd.cpp | 20 ++- 8 files changed, 332 insertions(+), 35 deletions(-) diff --git a/src/depot.cpp b/src/depot.cpp index 01b8d4e3b3..b498acfa90 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -18,6 +18,7 @@ #include "command_func.h" #include "vehicle_base.h" #include "viewport_kdtree.h" +#include "platform_func.h" #include "safeguards.h" @@ -212,6 +213,30 @@ void Depot::AfterAddRemove(TileArea ta, bool adding) InvalidateWindowData(WC_SELECT_DEPOT, veh_type); } +/** + * Check whether a tile is a destination tile, such as the starting tiles of + * rail platforms (and not the middle tiles of the platforms). + * @param dep The depot being checked + * @param tile The tile being checked + * @return Whether the tile is of the given depot. + */ +bool IsDepotDestTile(Depot *dep, TileIndex tile) +{ + assert(IsDepotTile(tile)); + assert(GetDepotIndex(tile) == dep->index); + + switch (dep->veh_type) { + case VEH_TRAIN: + assert(IsRailDepotTile(tile)); + return !IsExtendedRailDepot(tile) || IsAnyStartPlatformTile(tile); + case VEH_ROAD: + case VEH_SHIP: + case VEH_AIRCRAFT: + return true; + default: NOT_REACHED(); + } +} + /** * Rescan depot_tiles. Done after AfterAddRemove and SaveLoad. * Updates the tiles of the depot and its railtypes/roadtypes... @@ -225,7 +250,7 @@ void Depot::RescanDepotTiles() for (TileIndex tile : this->ta) { if (!IsDepotTile(tile)) continue; if (GetDepotIndex(tile) != this->index) continue; - this->depot_tiles.push_back(tile); + if (IsDepotDestTile(this, tile)) this->depot_tiles.push_back(tile); switch (veh_type) { case VEH_ROAD: this->r_types.road_types |= GetPresentRoadTypes(tile); @@ -268,8 +293,12 @@ void UpdateExtendedDepotReservation(Vehicle *v, bool reserve) SetDepotReservation(v->tile, res_type); break; - case VEH_TRAIN: + case VEH_TRAIN: { + DiagDirection dir = GetRailDepotDirection(v->tile); + SetDepotReservation(GetPlatformExtremeTile(v->tile, dir), res_type); + SetDepotReservation(GetPlatformExtremeTile(v->tile, ReverseDiagDir(dir)), res_type); break; + } case VEH_AIRCRAFT: break; diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index ed9e24a240..2bdd6dffad 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -47,7 +47,8 @@ struct CFollowTrackT bool m_is_tunnel; ///< last turn passed tunnel bool m_is_bridge; ///< last turn passed bridge ramp bool m_is_station; ///< last turn passed station - int m_tiles_skipped; ///< number of skipped tunnel or station tiles + bool m_is_extended_depot; ///< last turn passed depot + int m_tiles_skipped; ///< number of skipped tunnel, depot or station tiles ErrorCode m_err; RailTypes m_railtypes; @@ -81,7 +82,7 @@ struct CFollowTrackT m_new_tile = INVALID_TILE; m_new_td_bits = TRACKDIR_BIT_NONE; m_exitdir = INVALID_DIAGDIR; - m_is_station = m_is_bridge = m_is_tunnel = false; + m_is_station = m_is_bridge = m_is_tunnel = m_is_extended_depot = false; m_tiles_skipped = 0; m_err = EC_NONE; m_railtypes = railtype_override; @@ -171,11 +172,11 @@ struct CFollowTrackT { if (!DoTrackMasking()) return true; - if (m_is_station) { - /* Check skipped station tiles as well. */ + if (m_is_station || m_is_extended_depot) { + /* Check skipped station and depot tiles as well. */ TileIndexDiff diff = TileOffsByDiagDir(m_exitdir); for (TileIndex tile = m_new_tile - diff * m_tiles_skipped; tile != m_new_tile; tile += diff) { - if (HasStationReservation(tile)) { + if ((m_is_station && HasStationReservation(tile)) || (m_is_extended_depot && HasDepotReservation(tile))) { m_new_td_bits = TRACKDIR_BIT_NONE; m_err = EC_RESERVED; return false; @@ -201,7 +202,7 @@ protected: /** Follow the m_exitdir from m_old_tile and fill m_new_tile and m_tiles_skipped */ inline void FollowTileExit() { - m_is_station = m_is_bridge = m_is_tunnel = false; + m_is_station = m_is_bridge = m_is_tunnel = m_is_extended_depot = false; m_tiles_skipped = 0; /* extra handling for tunnels and bridges in our direction */ @@ -225,9 +226,13 @@ protected: /* normal or station tile, do one step */ m_new_tile = TileAddByDiagDir(m_old_tile, m_exitdir); - /* special handling for stations */ - if (IsRailTT() && HasStationTileRail(m_new_tile)) { - m_is_station = true; + /* special handling for stations and multi-tile depots */ + if (IsRailTT()) { + if (HasStationTileRail(m_new_tile)) { + m_is_station = true; + } else if (IsExtendedRailDepotTile(m_new_tile)) { + m_is_extended_depot = true; + } } else if (IsRoadTT() && IsStationRoadStopTile(m_new_tile)) { m_is_station = true; } @@ -369,13 +374,14 @@ protected: } } - /* special handling for rail stations - get to the end of platform */ - if (IsRailTT() && m_is_station) { + /* special handling for rail platforms - get to the end of platform */ + if (IsRailTT() && (m_is_station || m_is_extended_depot)) { /* Entered a platform. */ - assert(HasStationTileRail(m_new_tile)); + assert(HasStationTileRail(m_new_tile) || IsExtendedRailDepotTile(m_new_tile)); /* How big step we must do to get to the last platform tile? */ m_tiles_skipped = GetPlatformLength(m_new_tile, TrackdirToExitdir(m_old_td)) - 1; /* Move to the platform end. */ + TileIndexDiff diff = TileOffsByDiagDir(m_exitdir); diff *= m_tiles_skipped; m_new_tile = TileAdd(m_new_tile, diff); @@ -390,14 +396,27 @@ protected: { /* rail and road depots cause reversing */ if (!IsWaterTT() && IsDepotTypeTile(m_old_tile, TT())) { - DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(m_old_tile) : GetRoadDepotDirection(m_old_tile); + DiagDirection exitdir; + switch (TT()) { + case TRANSPORT_AIR: + return false; + case TRANSPORT_RAIL: + if (IsExtendedRailDepot(m_old_tile)) return false; + exitdir = GetRailDepotDirection(m_old_tile); + break; + case TRANSPORT_ROAD: + exitdir = GetRoadDepotDirection(m_old_tile); + break; + default: NOT_REACHED(); + } + if (exitdir != m_exitdir) { /* reverse */ m_new_tile = m_old_tile; m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(m_old_td)); m_exitdir = exitdir; m_tiles_skipped = 0; - m_is_tunnel = m_is_bridge = m_is_station = false; + m_is_tunnel = m_is_bridge = m_is_station = m_is_extended_depot = false; return true; } } diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 2a5bc290d6..af7cf5de24 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -439,7 +439,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th /* Waypoint is also a good reason to finish. */ end_segment_reason |= ESRB_WAYPOINT; - } else if (tf->m_is_station) { + } else if (tf->m_is_station || tf->m_is_extended_depot) { /* Station penalties. */ uint platform_length = tf->m_tiles_skipped + 1; /* We don't know yet if the station is our target or not. Act like @@ -592,7 +592,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th /* Platform-length penalty. */ if ((end_segment_reason & ESRB_STATION) != ESRB_NONE) { - assert(HasStationTileRail(n.GetLastTile())); + assert(HasStationTileRail(n.GetLastTile()) || IsExtendedRailDepotTile(n.GetLastTile())); uint platform_length = GetPlatformLength(n.GetLastTile(), ReverseDiagDir(TrackdirToExitdir(n.GetLastTrackdir()))); /* Reduce the extra cost caused by passing-platform penalty (each platform receives it in the segment cost). */ extra_cost -= Yapf().PfGetSettings().rail_station_penalty * platform_length; diff --git a/src/pbs.cpp b/src/pbs.cpp index 6cc6a33aa2..27a366ff91 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -12,6 +12,8 @@ #include "vehicle_func.h" #include "newgrf_station.h" #include "pathfinder/follow_track.hpp" +#include "platform_func.h" +#include "depot_map.h" #include "safeguards.h" @@ -180,12 +182,12 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra /* No reservation --> path end found */ if (reserved == TRACKDIR_BIT_NONE) { - if (ft.m_is_station) { + if (ft.m_is_station || ft.m_is_extended_depot) { /* Check skipped station tiles as well, maybe our reservation ends inside the station. */ TileIndexDiff diff = TileOffsByDiagDir(ft.m_exitdir); while (ft.m_tiles_skipped-- > 0) { ft.m_new_tile -= diff; - if (HasStationReservation(ft.m_new_tile)) { + if ((ft.m_is_station && HasStationReservation(ft.m_new_tile)) || (ft.m_is_extended_depot && HasDepotReservation(ft.m_new_tile))) { tile = ft.m_new_tile; trackdir = DiagDirToDiagTrackdir(ft.m_exitdir); break; @@ -278,14 +280,14 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res) if (train_on_res != nullptr) { FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum); if (ftoti.best != nullptr) *train_on_res = ftoti.best->First(); - if (*train_on_res == nullptr && IsRailStationTile(ftoti.res.tile)) { - /* The target tile is a rail station. The track follower + if (*train_on_res == nullptr && (IsRailStationTile(ftoti.res.tile) || IsExtendedRailDepotTile(ftoti.res.tile))) { + /* The target tile is a rail station or extended depot. The track follower * has stopped on the last platform tile where we haven't * found a train. Also check all previous platform tiles * for a possible train. */ TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir))); - for (TileIndex st_tile = ftoti.res.tile + diff; *train_on_res == nullptr && IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) { - FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum); + for (TileIndex pt_tile = ftoti.res.tile + diff; *train_on_res == nullptr && IsCompatiblePlatformTile(pt_tile, ftoti.res.tile); pt_tile += diff) { + FindVehicleOnPos(pt_tile, &ftoti, FindTrainOnTrackEnum); if (ftoti.best != nullptr) *train_on_res = ftoti.best->First(); } } @@ -326,11 +328,11 @@ Train *GetTrainForReservation(TileIndex tile, Track track) FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum); if (ftoti.best != nullptr) return ftoti.best; - /* Special case for stations: check the whole platform for a vehicle. */ - if (IsRailStationTile(ftoti.res.tile)) { + /* Special case for stations and extended depots: check the whole platform for a vehicle. */ + if (IsRailStationTile(ftoti.res.tile) || IsExtendedRailDepotTile(ftoti.res.tile)) { TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir))); - for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) { - FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum); + for (TileIndex pt_tile = ftoti.res.tile + diff; IsCompatiblePlatformTile(pt_tile, ftoti.res.tile); pt_tile += diff) { + FindVehicleOnPos(pt_tile, &ftoti, FindTrainOnTrackEnum); if (ftoti.best != nullptr) return ftoti.best; } } diff --git a/src/platform.cpp b/src/platform.cpp index 103d5a29f2..6878ad4344 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -11,6 +11,9 @@ #include "station_map.h" #include "platform_func.h" #include "viewport_func.h" +#include "depot_base.h" +#include "vehicle_base.h" +#include "engine_base.h" /** * Set the reservation for a complete station platform. @@ -34,6 +37,29 @@ void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool } while (IsCompatibleTrainStationTile(tile, start)); } + +/** + * Set the reservation for a complete depot platform. + * @pre IsExtendedRailDepotTile(start) + * @param start starting tile of the platform + * @param dir the direction in which to follow the platform + * @param b the state the reservation should be set to + */ +void SetRailDepotPlatformReservation(TileIndex start, DiagDirection dir, bool b) +{ + TileIndex tile = start; + TileIndexDiff diff = TileOffsByDiagDir(dir); + + assert(IsExtendedRailDepotTile(start)); + assert(GetRailDepotTrack(start) == DiagDirToDiagTrack(dir)); + + do { + SetDepotReservation(tile, b); + MarkTileDirtyByTile(tile); + tile = TileAdd(tile, diff); + } while (IsCompatibleTrainDepotTile(tile, start)); +} + /** * Set the reservation for a complete platform in a given direction. * @param start starting tile of the platform @@ -49,6 +75,32 @@ void SetPlatformReservation(TileIndex start, DiagDirection dir, bool b) case PT_RAIL_WAYPOINT: SetRailStationReservation(start, b); return; + case PT_RAIL_DEPOT: + SetRailDepotPlatformReservation(start, dir, b); + return; + default: NOT_REACHED(); + } +} + +/** + * Set the reservation for a complete platform. + * @param start A tile of the platform + * @param b the state the reservation should be set to + */ +void SetPlatformReservation(TileIndex start, bool b) +{ + DiagDirection dir; + switch (GetPlatformType(start)) { + case PT_RAIL_STATION: + NOT_REACHED(); + case PT_RAIL_WAYPOINT: + NOT_REACHED(); + case PT_RAIL_DEPOT: + assert(IsExtendedRailDepotTile(start)); + dir = GetRailDepotDirection(start); + SetRailDepotPlatformReservation(start, dir, b); + SetRailDepotPlatformReservation(start, ReverseDiagDir(dir), b); + return; default: NOT_REACHED(); } } @@ -103,6 +155,57 @@ uint GetRailStationPlatformLength(TileIndex tile, DiagDirection dir) return length; } +/** + * Get the length of a rail depot platform. + * @pre IsDepotTypeTile(tile, TRANSPORT_RAIL) + * @param tile Tile to check + * @return The length of the platform in tile length. + */ +uint GetRailDepotPlatformLength(TileIndex tile) +{ + assert(IsExtendedRailDepotTile(tile)); + + TileIndexDiff delta = (GetRailDepotTrack(tile) == TRACK_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); + + TileIndex t = tile; + uint len = 0; + do { + t -= delta; + len++; + } while (IsCompatibleTrainDepotTile(t, tile)); + + t = tile; + do { + t += delta; + len++; + } while (IsCompatibleTrainDepotTile(t, tile)); + + return len - 1; +} + + +/** + * Get the length of a rail depot platform in a given direction. + * @pre IsRailDepotTile(tile) + * @param tile Tile to check + * @param dir Direction to check + * @return The length of the platform in tile length in the given direction. + */ +uint GetRailDepotPlatformLength(TileIndex tile, DiagDirection dir) +{ + TileIndex start_tile = tile; + uint length = 0; + assert(IsExtendedRailDepotTile(tile)); + assert(dir < DIAGDIR_END); + + do { + length++; + tile += TileOffsByDiagDir(dir); + } while (IsCompatibleTrainDepotTile(tile, start_tile)); + + return length; +} + /** * Get the length of a platform. * @param tile Tile to check @@ -115,6 +218,8 @@ uint GetPlatformLength(TileIndex tile) return GetRailStationPlatformLength(tile); case PT_RAIL_WAYPOINT: return 1; + case PT_RAIL_DEPOT: + return GetRailDepotPlatformLength(tile); default: NOT_REACHED(); } } @@ -133,6 +238,106 @@ uint GetPlatformLength(TileIndex tile, DiagDirection dir) return GetRailStationPlatformLength(tile, dir); case PT_RAIL_WAYPOINT: return 1; + case PT_RAIL_DEPOT: + return GetRailDepotPlatformLength(tile, dir); default: NOT_REACHED(); } } + +/** + * Get a tile where a rail station platform begins or ends. + * @pre IsRailStationTile(tile) + * @param tile Tile to check + * @param dir The diagonal direction to check + * @return The last tile of the platform seen from tile with direction dir. + */ +TileIndex GetRailStationExtreme(TileIndex tile, DiagDirection dir) +{ + assert(IsRailStationTile(tile)); + assert(GetRailStationAxis(tile) == DiagDirToAxis(dir)); + TileIndexDiff delta = TileOffsByDiagDir(dir); + + TileIndex t = tile; + do { + t -= delta; + } while (IsCompatibleTrainStationTile(t, tile)); + + return t + delta; +} + +/** + * Get a tile where a depot platform begins or ends. + * @pre IsExtendedDepotTile(tile) + * @param tile Tile to check + * @param dir The diagonal direction to check + * @return The last tile of the platform seen from tile with direction dir. + */ +TileIndex GetRailDepotExtreme(TileIndex tile, DiagDirection dir) +{ + assert(IsExtendedDepotTile(tile)); + assert(GetRailDepotTrack(tile) == DiagDirToDiagTrack(dir)); + TileIndexDiff delta = TileOffsByDiagDir(dir); + + TileIndex t = tile; + do { + t -= delta; + } while (IsCompatibleTrainDepotTile(t, tile)); + + return t + delta; +} + +/** + * Get a tile where a platform begins or ends. + * @param tile Tile to check + * @param dir Direction to check + * @return The last tile of the platform seen from tile with direction dir. + */ +TileIndex GetPlatformExtremeTile(TileIndex tile, DiagDirection dir) +{ + switch (GetPlatformType(tile)) { + case PT_RAIL_STATION: + return GetRailStationExtreme(tile, dir); + case PT_RAIL_WAYPOINT: + return tile; + case PT_RAIL_DEPOT: + return GetRailDepotExtreme(tile, dir); + default: NOT_REACHED(); + } +} + +/** + * Get the tiles belonging to a platform. + * @param tile Tile of a platform + * @return the tile area of the platform + */ +TileArea GetPlatformTileArea(TileIndex tile) +{ + switch (GetPlatformType(tile)) { + case PT_RAIL_STATION: { + assert(IsRailStationTile(tile)); + DiagDirection dir = AxisToDiagDir(GetRailStationAxis(tile)); + return TileArea(GetRailStationExtreme(tile, dir), GetRailStationExtreme(tile, ReverseDiagDir(dir))); + } + case PT_RAIL_WAYPOINT: + return TileArea(tile); + case PT_RAIL_DEPOT: { + assert(IsExtendedRailDepotTile(tile)); + DiagDirection dir = GetRailDepotDirection(tile); + return TileArea(GetRailDepotExtreme(tile, dir), GetRailDepotExtreme(tile, ReverseDiagDir(dir))); + } + default: NOT_REACHED(); + } +} + + +/** + * Check whether this tile is an extreme of a platform. + * @param tile Tile to check + * @return Whether the tile is the extreme of a platform. + */ +bool IsAnyStartPlatformTile(TileIndex tile) +{ + assert(IsExtendedRailDepotTile(tile)); + DiagDirection dir = GetRailDepotDirection(tile); + return tile == GetPlatformExtremeTile(tile, dir) || tile == GetPlatformExtremeTile(tile, ReverseDiagDir(dir)); +} diff --git a/src/platform_func.h b/src/platform_func.h index 5b1275d3ef..30a2dae280 100644 --- a/src/platform_func.h +++ b/src/platform_func.h @@ -11,6 +11,7 @@ #define PLATFORM_FUNC_H #include "station_map.h" +#include "depot_map.h" #include "platform_type.h" /** @@ -35,6 +36,27 @@ static inline bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex s GetStationIndex(test_tile) == GetStationIndex(station_tile); } +/** + * Check if a tile is a valid continuation to an extended rail depot tile. + * The tile \a test_tile is a valid continuation to \a depot_tile, if all of the following are true: + * \li \a test_tile is an extended depot tile + * \li \a test_tile and \a depot_tile have the same rail type + * \li the tracks on \a test_tile and \a depot_tile are in the same direction + * \li both tiles belong to the same depot + * @param test_tile Tile to test + * @param depot_tile Depot tile to compare with + * @pre IsExtendedRailDepotTile(depot_tile) + * @return true if the two tiles are compatible + */ +static inline bool IsCompatibleTrainDepotTile(TileIndex test_tile, TileIndex depot_tile) +{ + assert(IsExtendedRailDepotTile(depot_tile)); + return IsExtendedRailDepotTile(test_tile) && + GetRailType(test_tile) == GetRailType(depot_tile) && + GetRailDepotTrack(test_tile) == GetRailDepotTrack(depot_tile) && + GetDepotIndex(test_tile) == GetDepotIndex(depot_tile); +} + /** * Returns the type of platform of a given tile. * @param tile Tile to check @@ -47,6 +69,9 @@ static inline PlatformType GetPlatformType(TileIndex tile) if (IsRailStation(tile)) return PT_RAIL_STATION; if (IsRailWaypoint(tile)) return PT_RAIL_WAYPOINT; break; + case MP_RAILWAY: + if (IsExtendedRailDepotTile(tile)) return PT_RAIL_DEPOT; + break; default: break; } @@ -74,6 +99,8 @@ static inline bool HasPlatformReservation(TileIndex tile) case PT_RAIL_STATION: case PT_RAIL_WAYPOINT: return HasStationReservation(tile); + case PT_RAIL_DEPOT: + return HasDepotReservation(tile); default: NOT_REACHED(); } } @@ -92,13 +119,21 @@ static inline bool IsCompatiblePlatformTile(TileIndex test_tile, TileIndex orig_ return IsCompatibleTrainStationTile(test_tile, orig_tile); case PT_RAIL_WAYPOINT: return test_tile == orig_tile; + case PT_RAIL_DEPOT: + return IsCompatibleTrainDepotTile(test_tile, orig_tile); default: NOT_REACHED(); } } void SetPlatformReservation(TileIndex start, DiagDirection dir, bool b); +void SetPlatformReservation(TileIndex start, bool b); uint GetPlatformLength(TileIndex tile); uint GetPlatformLength(TileIndex tile, DiagDirection dir); +TileIndex GetPlatformExtremeTile(TileIndex tile, DiagDirection dir); +TileArea GetPlatformTileArea(TileIndex tile); + +bool IsAnyStartPlatformTile(TileIndex tile); + #endif /* PLATFORM_FUNC_H */ diff --git a/src/platform_type.h b/src/platform_type.h index a2a48c90b3..27765d92c7 100644 --- a/src/platform_type.h +++ b/src/platform_type.h @@ -15,6 +15,7 @@ enum PlatformType { PT_RAIL_STATION, PT_RAIL_WAYPOINT, + PT_RAIL_DEPOT, PT_END, INVALID_PLATFORM_TYPE = PT_END, }; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 52bc2c839b..5680a31ff5 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -40,6 +40,7 @@ #include "timer/timer_game_economy.h" #include "depot_base.h" #include "platform_func.h" +#include "depot_map.h" #include "table/strings.h" #include "table/train_sprites.h" @@ -2419,7 +2420,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->IsInDepot() || u->tile != v->tile) return false; } /* if the train got no power, then keep it in the depot */ @@ -2523,7 +2524,7 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_ } } } - } else if (IsRailStationTile(tile)) { + } else if (IsRailStationTile(tile) || IsExtendedRailDepotTile(tile)) { TileIndex new_tile = TileAddByDiagDir(tile, dir); /* If the new tile is not a further tile of the same station, we * clear the reservation for the whole platform. */ @@ -2546,8 +2547,9 @@ void FreeTrainTrackReservation(const Train *v) TileIndex tile = v->tile; Trackdir td = v->GetVehicleTrackdir(); - bool free_tile = !(IsRailStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)); + bool free_tile = !(IsRailStationTile(v->tile) || IsExtendedRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)); StationID station_id = IsRailStationTile(v->tile) ? GetStationIndex(v->tile) : INVALID_STATION; + DepotID depot_id = IsExtendedRailDepotTile(v->tile) ? GetDepotIndex(v->tile) : INVALID_DEPOT; /* Can't be holding a reservation if we enter a depot. */ if (IsStandardRailDepotTile(tile) && TrackdirToExitdir(td) != GetRailDepotDirection(tile)) return; @@ -2590,7 +2592,7 @@ void FreeTrainTrackReservation(const Train *v) } /* Don't free first station/bridge/tunnel if we are on it. */ - if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td); + if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !(ft.m_is_extended_depot && GetDepotIndex(ft.m_new_tile) == depot_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td); free_tile = true; } @@ -2649,7 +2651,7 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, } /* Station, depot or waypoint are a possible target. */ - bool target_seen = ft.m_is_station || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile)); + bool target_seen = ft.m_is_station || ft.m_is_extended_depot || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile)); if (target_seen || KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) { /* Choice found or possible target encountered. * On finding a possible target, we need to stop and let the pathfinder handle the @@ -4358,9 +4360,13 @@ Trackdir Train::GetVehicleTrackdir() const { if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR; - if (this->track == TRACK_BIT_DEPOT) { + if (this->IsInDepot()) { /* We'll assume the train is facing outwards */ - return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot + if (this->track == TRACK_BIT_DEPOT) + return DiagDirToDiagTrackdir(DirToDiagDir(this->direction)); // Train in depot + Track track = FindFirstTrack(this->track & ~TRACK_BIT_DEPOT); + assert(IsValidTrack(track)); + return TrackDirectionToTrackdir(track, this->direction); } if (this->track == TRACK_BIT_WORMHOLE) {