* Try to reserve a path to a safe position. * * @param v The vehicle * @param mark_as_stuck Should the train be marked as stuck on a failed reservation? * @param first_tile_okay True if no path should be reserved if the current tile is a safe position. * @return True if a path could be reserved. */
| 2897 | * @return True if a path could be reserved. |
| 2898 | */ |
| 2899 | bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay) |
| 2900 | { |
| 2901 | assert(v->IsFrontEngine()); |
| 2902 | |
| 2903 | /* We have to handle depots specially as the track follower won't look |
| 2904 | * at the depot tile itself but starts from the next tile. If we are still |
| 2905 | * inside the depot, a depot reservation can never be ours. */ |
| 2906 | if (v->track == TRACK_BIT_DEPOT) { |
| 2907 | if (HasDepotReservation(v->tile)) { |
| 2908 | if (mark_as_stuck) MarkTrainAsStuck(v); |
| 2909 | return false; |
| 2910 | } else { |
| 2911 | /* Depot not reserved, but the next tile might be. */ |
| 2912 | TileIndex next_tile = TileAddByDiagDir(v->tile, GetRailDepotDirection(v->tile)); |
| 2913 | if (HasReservedTracks(next_tile, DiagdirReachesTracks(GetRailDepotDirection(v->tile)))) return false; |
| 2914 | } |
| 2915 | } |
| 2916 | |
| 2917 | Vehicle *other_train = nullptr; |
| 2918 | PBSTileInfo origin = FollowTrainReservation(v, &other_train); |
| 2919 | /* The path we are driving on is already blocked by some other train. |
| 2920 | * This can only happen in certain situations when mixing path and |
| 2921 | * block signals or when changing tracks and/or signals. |
| 2922 | * Exit here as doing any further reservations will probably just |
| 2923 | * make matters worse. */ |
| 2924 | if (other_train != nullptr && other_train->index != v->index) { |
| 2925 | if (mark_as_stuck) MarkTrainAsStuck(v); |
| 2926 | return false; |
| 2927 | } |
| 2928 | /* If we have a reserved path and the path ends at a safe tile, we are finished already. */ |
| 2929 | if (origin.okay && (v->tile != origin.tile || first_tile_okay)) { |
| 2930 | /* Can't be stuck then. */ |
| 2931 | if (v->flags.Test(VehicleRailFlag::Stuck)) SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); |
| 2932 | v->flags.Reset(VehicleRailFlag::Stuck); |
| 2933 | return true; |
| 2934 | } |
| 2935 | |
| 2936 | /* If we are in a depot, tentatively reserve the depot. */ |
| 2937 | if (v->track == TRACK_BIT_DEPOT) { |
| 2938 | SetDepotReservation(v->tile, true); |
| 2939 | if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile); |
| 2940 | } |
| 2941 | |
| 2942 | DiagDirection exitdir = TrackdirToExitdir(origin.trackdir); |
| 2943 | TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir); |
| 2944 | TrackBits reachable = TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(GetTileTrackStatus(new_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTrackdirs(exitdir)); |
| 2945 | |
| 2946 | if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir)); |
| 2947 | |
| 2948 | bool res_made = false; |
| 2949 | ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck); |
| 2950 | |
| 2951 | if (!res_made) { |
| 2952 | /* Free the depot reservation as well. */ |
| 2953 | if (v->track == TRACK_BIT_DEPOT) SetDepotReservation(v->tile, false); |
| 2954 | return false; |
| 2955 | } |
| 2956 |
no test coverage detected