MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / ChooseTrainTrack

Function ChooseTrainTrack

src/train_cmd.cpp:2727–2889  ·  view source on GitHub ↗

choose a track */

Source from the content-addressed store, hash-verified

2725
2726/* choose a track */
2727static 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

Callers 3

CheckNextTrainTileFunction · 0.85
TryPathReserveFunction · 0.85
TrainControllerFunction · 0.85

Calls 15

GetReservedTrackbitsFunction · 0.85
DiagdirReachesTracksFunction · 0.85
FindFirstTrackFunction · 0.85
KillFirstBitFunction · 0.85
HasPbsSignalOnTrackdirFunction · 0.85
TrackEnterdirToTrackdirFunction · 0.85
SetSignalStateByTrackdirFunction · 0.85
ExtendTrainReservationFunction · 0.85
MarkTrainAsStuckFunction · 0.85
TryReserveRailTrackFunction · 0.85
TrackdirToTrackFunction · 0.85
CheckIfTrainNeedsServiceFunction · 0.85

Tested by

no test coverage detected