* Turn a train around. * @param v %Train to turn around. */
| 1983 | * @param v %Train to turn around. |
| 1984 | */ |
| 1985 | void ReverseTrainDirection(Train *v) |
| 1986 | { |
| 1987 | if (IsRailDepotTile(v->tile)) { |
| 1988 | if (IsWholeTrainInsideDepot(v)) return; |
| 1989 | InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
| 1990 | } |
| 1991 | |
| 1992 | /* Clear path reservation in front if train is not stuck. */ |
| 1993 | if (!v->flags.Test(VehicleRailFlag::Stuck)) FreeTrainTrackReservation(v); |
| 1994 | |
| 1995 | /* Check if we were approaching a rail/road-crossing */ |
| 1996 | TileIndex crossing = TrainApproachingCrossingTile(v); |
| 1997 | |
| 1998 | /* count number of vehicles */ |
| 1999 | int r = CountVehiclesInChain(v) - 1; // number of vehicles - 1 |
| 2000 | |
| 2001 | AdvanceWagonsBeforeSwap(v); |
| 2002 | |
| 2003 | /* swap start<>end, start+1<>end-1, ... */ |
| 2004 | int l = 0; |
| 2005 | do { |
| 2006 | ReverseTrainSwapVeh(v, l++, r--); |
| 2007 | } while (l <= r); |
| 2008 | |
| 2009 | AdvanceWagonsAfterSwap(v); |
| 2010 | |
| 2011 | if (IsRailDepotTile(v->tile)) { |
| 2012 | InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
| 2013 | } |
| 2014 | |
| 2015 | v->flags.Flip(VehicleRailFlag::Reversed); |
| 2016 | v->flags.Reset(VehicleRailFlag::Reversing); |
| 2017 | |
| 2018 | /* recalculate cached data */ |
| 2019 | v->ConsistChanged(CCF_TRACK); |
| 2020 | |
| 2021 | /* update all images */ |
| 2022 | for (Train *u = v; u != nullptr; u = u->Next()) u->UpdateViewport(false, false); |
| 2023 | |
| 2024 | /* update crossing we were approaching */ |
| 2025 | if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing); |
| 2026 | |
| 2027 | /* maybe we are approaching crossing now, after reversal */ |
| 2028 | crossing = TrainApproachingCrossingTile(v); |
| 2029 | if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing); |
| 2030 | |
| 2031 | /* If we are inside a depot after reversing, don't bother with path reserving. */ |
| 2032 | if (v->track == TRACK_BIT_DEPOT) { |
| 2033 | /* Can't be stuck here as inside a depot is always a safe tile. */ |
| 2034 | if (v->flags.Test(VehicleRailFlag::Stuck)) SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); |
| 2035 | v->flags.Reset(VehicleRailFlag::Stuck); |
| 2036 | return; |
| 2037 | } |
| 2038 | |
| 2039 | /* VehicleExitDir does not always produce the desired dir for depots and |
| 2040 | * tunnels/bridges that is needed for UpdateSignalsOnSegment. */ |
| 2041 | DiagDirection dir = VehicleExitDir(v->direction, v->track); |
| 2042 | if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR; |
no test coverage detected