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

Function TrainController

src/train_cmd.cpp:3289–3612  ·  view source on GitHub ↗

* Move a vehicle chain one movement stop forwards. * @param v First vehicle to move. * @param nomove Stop moving this and all following vehicles. * @param reverse Set to false to not execute the vehicle reversing. This does not change any other logic. * @return True if the vehicle could be moved forward, false otherwise. */

Source from the content-addressed store, hash-verified

3287 * @return True if the vehicle could be moved forward, false otherwise.
3288 */
3289bool TrainController(Train *v, Vehicle *nomove, bool reverse)
3290{
3291 Train *first = v->First();
3292 Train *prev;
3293 bool direction_changed = false; // has direction of any part changed?
3294
3295 /* For every vehicle after and including the given vehicle */
3296 for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) {
3297 DiagDirection enterdir = DIAGDIR_BEGIN;
3298 bool update_signals_crossing = false; // will we update signals or crossing state?
3299
3300 GetNewVehiclePosResult gp = GetNewVehiclePos(v);
3301 if (v->track != TRACK_BIT_WORMHOLE) {
3302 /* Not inside tunnel */
3303 if (gp.old_tile == gp.new_tile) {
3304 /* Staying in the old tile */
3305 if (v->track == TRACK_BIT_DEPOT) {
3306 /* Inside depot */
3307 gp.x = v->x_pos;
3308 gp.y = v->y_pos;
3309 } else {
3310 /* Not inside depot */
3311
3312 /* Reverse when we are at the end of the track already, do not move to the new position */
3313 if (v->IsFrontEngine() && !TrainCheckIfLineEnds(v, reverse)) return false;
3314
3315 auto vets = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
3316 if (vets.Test(VehicleEnterTileState::CannotEnter)) {
3317 goto invalid_rail;
3318 }
3319 if (vets.Test(VehicleEnterTileState::EnteredStation)) {
3320 /* The new position is the end of the platform */
3321 TrainEnterStation(v, GetStationIndex(gp.new_tile));
3322 }
3323 }
3324 } else {
3325 /* A new tile is about to be entered. */
3326
3327 /* Determine what direction we're entering the new tile from */
3328 enterdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
3329 assert(IsValidDiagDirection(enterdir));
3330
3331 /* Get the status of the tracks in the new tile and mask
3332 * away the bits that aren't reachable. */
3333 TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir));
3334 TrackdirBits reachable_trackdirs = DiagdirReachesTrackdirs(enterdir);
3335
3336 TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts) & reachable_trackdirs;
3337 TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs);
3338
3339 TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
3340 if (Rail90DegTurnDisallowed(GetTileRailType(gp.old_tile), GetTileRailType(gp.new_tile)) && prev == nullptr) {
3341 /* We allow wagons to make 90 deg turns, because forbid_90_deg
3342 * can be switched on halfway a turn */
3343 bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
3344 }
3345
3346 if (bits == TRACK_BIT_NONE) goto invalid_rail;

Callers 4

AdvanceWagonsBeforeSwapFunction · 0.85
AdvanceWagonsAfterSwapFunction · 0.85
TrainLocoHandlerFunction · 0.85
FixupTrainLengthsFunction · 0.85

Calls 15

GetNewVehiclePosFunction · 0.85
TrainCheckIfLineEndsFunction · 0.85
VehicleEnterTileFunction · 0.85
TrainEnterStationFunction · 0.85
GetStationIndexFunction · 0.85
DiagdirBetweenTilesFunction · 0.85
IsValidDiagDirectionFunction · 0.85
GetTileTrackStatusFunction · 0.85
ReverseDiagDirFunction · 0.85
DiagdirReachesTrackdirsFunction · 0.85
TrackdirBitsToTrackBitsFunction · 0.85

Tested by

no test coverage detected