diff --git a/src/pathfinder/pathfinder_func.h b/src/pathfinder/pathfinder_func.h index 444b100ce7..781d356458 100644 --- a/src/pathfinder/pathfinder_func.h +++ b/src/pathfinder/pathfinder_func.h @@ -12,6 +12,7 @@ #include "../tile_cmd.h" #include "../waypoint_base.h" +#include "../depot_base.h" /** * Calculates the tile of given station that is closest to a given tile @@ -47,6 +48,37 @@ inline TileIndex CalcClosestStationTile(StationID station, TileIndex tile, Stati return TileXY(x, y); } +/** + * Calculates the tile of a depot that is closest to a given tile. + * @param depot_id The depot to calculate the distance to. + * @param tile The tile from where to calculate the distance. + * @return The closest depot tile to the given tile. + */ +static inline TileIndex CalcClosestDepotTile(DepotID depot_id, TileIndex tile) +{ + assert(Depot::IsValidID(depot_id)); + const Depot *dep = Depot::Get(depot_id); + + /* If tile area is empty, use the xy tile. */ + if (dep->ta.tile == INVALID_TILE) { + assert(dep->xy != INVALID_TILE); + return dep->xy; + } + + TileIndex best_tile = INVALID_TILE; + uint best_distance = UINT_MAX; + + for (auto const &depot_tile : dep->depot_tiles) { + uint new_distance = DistanceManhattan(depot_tile, tile); + if (new_distance < best_distance) { + best_tile = depot_tile; + best_distance = new_distance; + } + } + + return best_tile; +} + /** * Wrapper around GetTileTrackStatus() and TrackStatusToTrackdirBits(), as for * single tram bits GetTileTrackStatus() returns 0. The reason for this is diff --git a/src/pathfinder/yapf/yapf_destrail.hpp b/src/pathfinder/yapf/yapf_destrail.hpp index f39a8a2c4b..f6b871ea2c 100644 --- a/src/pathfinder/yapf/yapf_destrail.hpp +++ b/src/pathfinder/yapf/yapf_destrail.hpp @@ -118,6 +118,7 @@ protected: TileIndex m_destTile; TrackdirBits m_destTrackdirs; StationID m_dest_station_id; + DepotID m_dest_depot_id; bool m_any_depot; /** to access inherited path finder */ @@ -149,14 +150,25 @@ public: break; case OT_GOTO_DEPOT: + m_dest_station_id = INVALID_STATION; + if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) { m_any_depot = true; + m_dest_depot_id = INVALID_DEPOT; + m_destTile = v->dest_tile; + m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0)); + } else { + m_dest_depot_id = v->current_order.GetDestination(); + assert(Depot::IsValidID(m_dest_depot_id)); + m_destTile = CalcClosestDepotTile(m_dest_depot_id, v->tile); + m_destTrackdirs = INVALID_TRACKDIR_BIT; } - [[fallthrough]]; + break; default: m_destTile = v->dest_tile; m_dest_station_id = INVALID_STATION; + m_dest_depot_id = INVALID_DEPOT; m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0)); break; } @@ -176,6 +188,10 @@ public: return HasStationTileRail(tile) && (GetStationIndex(tile) == m_dest_station_id) && (GetRailStationTrack(tile) == TrackdirToTrack(td)); + } else if (m_dest_depot_id != INVALID_DEPOT) { + return IsRailDepotTile(tile) + && (GetDepotIndex(tile) == m_dest_depot_id) + && (GetRailDepotTrack(tile) == TrackdirToTrack(td)); } if (m_any_depot) { diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index 209b64b52a..910751f227 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -234,7 +234,9 @@ protected: TileIndex m_destTile; TrackdirBits m_destTrackdirs; StationID m_dest_station; + DepotID m_dest_depot; StationType m_station_type; + bool m_bus; bool m_non_artic; public: @@ -252,8 +254,14 @@ public: m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_station_type); m_non_artic = !v->HasArticulatedPart(); m_destTrackdirs = INVALID_TRACKDIR_BIT; + } else if (v->current_order.IsType(OT_GOTO_DEPOT)) { + m_dest_station = INVALID_STATION; + m_dest_depot = v->current_order.GetDestination(); + m_destTile = CalcClosestDepotTile(m_dest_depot, v->tile); + m_destTrackdirs = INVALID_TRACKDIR_BIT; } else { m_dest_station = INVALID_STATION; + m_dest_depot = INVALID_DEPOT; m_destTile = v->dest_tile; m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype))); } @@ -287,6 +295,11 @@ public: (m_non_artic || IsDriveThroughStopTile(tile)); } + if (m_dest_depot != INVALID_DEPOT) { + return IsRoadDepotTile(tile) && + GetDepotIndex(tile) == m_dest_depot; + } + return tile == m_destTile && HasTrackdir(m_destTrackdirs, trackdir); }