diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index 1b85c8d4ec671..8df9f114e3fa9 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -402,6 +402,8 @@ class CYapfFollowRoadT Node &best_next_node = *pNode; assert(best_next_node.GetTile() == tile); next_trackdir = best_next_node.GetTrackdir(); + path_cache.origin_td = next_trackdir; + path_cache.origin_tile = tile; /* remove last element for the special case when tile == dest_tile */ if (path_found && !path_cache.empty() && tile == v->dest_tile) { path_cache.td.pop_back(); diff --git a/src/roadveh.h b/src/roadveh.h index 028af9decb71a..f5d5390336554 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -83,6 +83,8 @@ void RoadVehUpdateCache(RoadVehicle *v, bool same_length = false); void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type); struct RoadVehPathCache { + Trackdir origin_td = INVALID_TRACKDIR; + TileIndex origin_tile = INVALID_TILE; std::deque td; std::deque tile; @@ -96,6 +98,8 @@ struct RoadVehPathCache { inline void clear() { + this->origin_td = INVALID_TRACKDIR; + this->origin_tile = INVALID_TILE; this->td.clear(); this->tile.clear(); } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 261af7042bceb..3e1c190a53b51 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -968,6 +968,9 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection /* Attempt to follow cached path. */ if (!v->path.empty()) { if (v->path.tile.front() != tile) { + if (IsValidTile(v->path.origin_tile) && v->path.origin_tile == tile && HasBit(trackdirs, v->path.origin_td)) { + return_track(v->path.origin_td); + } /* Vehicle didn't expect a choice here, invalidate its path. */ v->path.clear(); } else { @@ -977,6 +980,8 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection v->path.td.pop_front(); v->path.tile.pop_front(); return_track(trackdir); + } else if (IsValidTile(v->path.origin_tile) && v->path.origin_tile == tile && HasBit(trackdirs, v->path.origin_td)) { + return_track(v->path.origin_td); } /* Vehicle expected a choice which is no longer available. */ diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index c617348d7337c..2179dcbddc0a7 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3133,6 +3133,13 @@ bool AfterLoadGame() } } + if (IsSavegameVersionBefore(SLV_FIX_ROADVEH_PATH_CACHE_ORIGIN)) { + for (RoadVehicle *rv : RoadVehicle::Iterate()) { + rv->path.origin_td = INVALID_TRACKDIR; + rv->path.origin_tile = INVALID_TILE; + } + } + /* Compute station catchment areas. This is needed here in case UpdateStationAcceptance is called below. */ Station::RecomputeCatchmentForAll(); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 58a2919326a68..25858532138f2 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -321,6 +321,7 @@ enum SaveLoadVersion : uint16 { SLV_END_PATCHPACKS = 286, ///< 286 Last known patchpack to use a version just above ours. SLV_GS_INDUSTRY_CONTROL, ///< 287 PR#7912 and PR#8115 GS industry control. + SLV_FIX_ROADVEH_PATH_CACHE_ORIGIN, ///< 288 PR#7822 Cache the origin tile/td of a road vehicle pathfinder search. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 321ad53a693ec..3f95e2aa6f958 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -746,6 +746,8 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_VAR(RoadVehicle, overtaking_ctr, SLE_UINT8), SLE_VAR(RoadVehicle, crashed_ctr, SLE_UINT16), SLE_VAR(RoadVehicle, reverse_ctr, SLE_UINT8), + SLE_CONDVAR(RoadVehicle, path.origin_td, SLE_UINT8, SLV_FIX_ROADVEH_PATH_CACHE_ORIGIN, SL_MAX_VERSION), + SLE_CONDVAR(RoadVehicle, path.origin_tile, SLE_UINT32, SLV_FIX_ROADVEH_PATH_CACHE_ORIGIN, SL_MAX_VERSION), SLE_CONDDEQUE(RoadVehicle, path.td, SLE_UINT8, SLV_ROADVEH_PATH_CACHE, SL_MAX_VERSION), SLE_CONDDEQUE(RoadVehicle, path.tile, SLE_UINT32, SLV_ROADVEH_PATH_CACHE, SL_MAX_VERSION),