choose a track */
| 2725 | |
| 2726 | /* choose a track */ |
| 2727 | static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck) |
| 2728 | { |
| 2729 | Track best_track = INVALID_TRACK; |
| 2730 | bool do_track_reservation = _settings_game.pf.reserve_paths || force_res; |
| 2731 | bool changed_signal = false; |
| 2732 | TileIndex final_dest = INVALID_TILE; |
| 2733 | |
| 2734 | assert((tracks & ~TRACK_BIT_MASK) == 0); |
| 2735 | |
| 2736 | if (got_reservation != nullptr) *got_reservation = false; |
| 2737 | |
| 2738 | /* Don't use tracks here as the setting to forbid 90 deg turns might have been switched between reservation and now. */ |
| 2739 | TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir)); |
| 2740 | /* Do we have a suitable reserved track? */ |
| 2741 | if (res_tracks != TRACK_BIT_NONE) return FindFirstTrack(res_tracks); |
| 2742 | |
| 2743 | /* Quick return in case only one possible track is available */ |
| 2744 | if (KillFirstBit(tracks) == TRACK_BIT_NONE) { |
| 2745 | Track track = FindFirstTrack(tracks); |
| 2746 | /* We need to check for signals only here, as a junction tile can't have signals. */ |
| 2747 | if (track != INVALID_TRACK && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) { |
| 2748 | do_track_reservation = true; |
| 2749 | changed_signal = true; |
| 2750 | SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir), SIGNAL_STATE_GREEN); |
| 2751 | } else if (!do_track_reservation) { |
| 2752 | return track; |
| 2753 | } |
| 2754 | best_track = track; |
| 2755 | } |
| 2756 | |
| 2757 | PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false); |
| 2758 | DiagDirection dest_enterdir = enterdir; |
| 2759 | if (do_track_reservation) { |
| 2760 | res_dest = ExtendTrainReservation(v, &tracks, &dest_enterdir); |
| 2761 | if (res_dest.tile == INVALID_TILE) { |
| 2762 | /* Reservation failed? */ |
| 2763 | if (mark_stuck) MarkTrainAsStuck(v); |
| 2764 | if (changed_signal) SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(best_track, enterdir), SIGNAL_STATE_RED); |
| 2765 | return FindFirstTrack(tracks); |
| 2766 | } |
| 2767 | if (res_dest.okay) { |
| 2768 | /* Got a valid reservation that ends at a safe target, quick exit. */ |
| 2769 | if (got_reservation != nullptr) *got_reservation = true; |
| 2770 | if (changed_signal) MarkTileDirtyByTile(tile); |
| 2771 | TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir())); |
| 2772 | return best_track; |
| 2773 | } |
| 2774 | |
| 2775 | /* Check if the train needs service here, so it has a chance to always find a depot. |
| 2776 | * Also check if the current order is a service order so we don't reserve a path to |
| 2777 | * the destination but instead to the next one if service isn't needed. */ |
| 2778 | CheckIfTrainNeedsService(v); |
| 2779 | if (v->current_order.IsType(OT_DUMMY) || v->current_order.IsType(OT_CONDITIONAL) || v->current_order.IsType(OT_GOTO_DEPOT)) ProcessOrders(v); |
| 2780 | } |
| 2781 | |
| 2782 | /* Save the current train order. The destructor will restore the old order on function exit. */ |
| 2783 | VehicleOrderSaver orders(v); |
| 2784 |
no test coverage detected