GetStopIndex() static private method

static private GetStopIndex ( int StationIndex, int Cars ) : int
StationIndex int
Cars int
return int
Beispiel #1
0
        /// <summary>This method is called once the route and train data have been preprocessed, in order to physically setup the simulation</summary>
        private void SetupSimulation()
        {
            if (Loading.Cancel)
            {
                Close();
            }
            Timetable.CreateTimetable();
            //Check if any critical errors have occured during the route or train loading
            for (int i = 0; i < Interface.MessageCount; i++)
            {
                if (Interface.Messages[i].Type == Interface.MessageType.Critical)
                {
                    MessageBox.Show("A critical error has occured:\n\n" + Interface.Messages[i].Text + "\n\nPlease inspect the error log file for further information.", "Load", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Close();
                }
            }
            Renderer.InitializeLighting();
            Game.LogRouteName = System.IO.Path.GetFileName(MainLoop.currentResult.RouteFile);
            Game.LogTrainName = System.IO.Path.GetFileName(MainLoop.currentResult.TrainFolder);
            Game.LogDateTime  = DateTime.Now;

            if (Interface.CurrentOptions.LoadInAdvance)
            {
                Textures.LoadAllTextures();
            }
            else
            {
                Textures.UnloadAllTextures();
            }
            // camera
            ObjectManager.InitializeVisibility();
            World.CameraTrackFollower.Update(0.0, true, false);
            World.CameraTrackFollower.Update(-0.1, true, false);
            World.CameraTrackFollower.Update(0.1, true, false);
            World.CameraTrackFollower.TriggerType = TrackManager.EventTriggerType.Camera;
            // starting time and track position
            Game.SecondsSinceMidnight = 0.0;
            Game.StartupTime          = 0.0;
            int    PlayerFirstStationIndex = -1;
            double PlayerFirstStationPosition;
            int    os = -1;
            bool   f  = false;

            for (int i = 0; i < Game.Stations.Length; i++)
            {
                if (!String.IsNullOrEmpty(Game.InitialStationName))
                {
                    if (Game.InitialStationName.ToLowerInvariant() == Game.Stations[i].Name.ToLowerInvariant())
                    {
                        PlayerFirstStationIndex = i;
                    }
                }
                if (Game.Stations[i].StopMode == StationStopMode.AllStop | Game.Stations[i].StopMode == StationStopMode.PlayerStop & Game.Stations[i].Stops.Length != 0)
                {
                    if (f == false)
                    {
                        os = i;
                        f  = true;
                    }
                }
            }
            if (PlayerFirstStationIndex == -1)
            {
                PlayerFirstStationIndex = os;
            }
            {
                int s = Game.GetStopIndex(PlayerFirstStationIndex, TrainManager.PlayerTrain.Cars.Length);
                if (s >= 0)
                {
                    PlayerFirstStationPosition = Game.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition;

                    double TrainLength = 0.0;
                    for (int c = 0; c < TrainManager.Trains[TrainManager.PlayerTrain.TrainIndex].Cars.Length; c++)
                    {
                        TrainLength += TrainManager.Trains[TrainManager.PlayerTrain.TrainIndex].Cars[c].Length;
                    }

                    for (int j = 0; j < Game.BufferTrackPositions.Length; j++)
                    {
                        if (PlayerFirstStationPosition > Game.BufferTrackPositions[j] && PlayerFirstStationPosition - TrainLength < Game.BufferTrackPositions[j])
                        {
                            /*
                             * HACK: The initial start position for the player train is stuck on a set of buffers
                             * This means we have to make some one the fly adjustments to the first station stop position
                             */

                            //Set the start position to be the buffer position plus the train length plus 1m
                            PlayerFirstStationPosition = Game.BufferTrackPositions[j] + TrainLength + 1;
                            //Update the station stop location
                            if (s >= 0)
                            {
                                Game.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition = PlayerFirstStationPosition;
                            }
                            else
                            {
                                Game.Stations[PlayerFirstStationIndex].DefaultTrackPosition = PlayerFirstStationPosition;
                            }
                            break;
                        }
                    }
                }
                else
                {
                    PlayerFirstStationPosition = Game.Stations[PlayerFirstStationIndex].DefaultTrackPosition;
                }
                if (Game.InitialStationTime != -1)
                {
                    Game.SecondsSinceMidnight = Game.InitialStationTime;
                    Game.StartupTime          = Game.InitialStationTime;
                }
                else
                {
                    if (Game.Stations[PlayerFirstStationIndex].ArrivalTime < 0.0)
                    {
                        if (Game.Stations[PlayerFirstStationIndex].DepartureTime < 0.0)
                        {
                            Game.SecondsSinceMidnight = 0.0;
                            Game.StartupTime          = 0.0;
                        }
                        else
                        {
                            Game.SecondsSinceMidnight = Game.Stations[PlayerFirstStationIndex].DepartureTime -
                                                        Game.Stations[PlayerFirstStationIndex].StopTime;
                            Game.StartupTime = Game.Stations[PlayerFirstStationIndex].DepartureTime -
                                               Game.Stations[PlayerFirstStationIndex].StopTime;
                        }
                    }
                    else
                    {
                        Game.SecondsSinceMidnight = Game.Stations[PlayerFirstStationIndex].ArrivalTime;
                        Game.StartupTime          = Game.Stations[PlayerFirstStationIndex].ArrivalTime;
                    }
                }
            }
            int    OtherFirstStationIndex    = -1;
            double OtherFirstStationPosition = 0.0;
            double OtherFirstStationTime     = 0.0;

            for (int i = 0; i < Game.Stations.Length; i++)
            {
                if (Game.Stations[i].StopMode == StationStopMode.AllStop | Game.Stations[i].StopMode == StationStopMode.PlayerPass & Game.Stations[i].Stops.Length != 0)
                {
                    OtherFirstStationIndex = i;
                    int s = Game.GetStopIndex(i, TrainManager.PlayerTrain.Cars.Length);
                    if (s >= 0)
                    {
                        OtherFirstStationPosition = Game.Stations[i].Stops[s].TrackPosition;
                    }
                    else
                    {
                        OtherFirstStationPosition = Game.Stations[i].DefaultTrackPosition;
                    }
                    if (Game.Stations[i].ArrivalTime < 0.0)
                    {
                        if (Game.Stations[i].DepartureTime < 0.0)
                        {
                            OtherFirstStationTime = 0.0;
                        }
                        else
                        {
                            OtherFirstStationTime = Game.Stations[i].DepartureTime - Game.Stations[i].StopTime;
                        }
                    }
                    else
                    {
                        OtherFirstStationTime = Game.Stations[i].ArrivalTime;
                    }
                    break;
                }
            }
            if (Game.PrecedingTrainTimeDeltas.Length != 0)
            {
                OtherFirstStationTime -= Game.PrecedingTrainTimeDeltas[Game.PrecedingTrainTimeDeltas.Length - 1];
                if (OtherFirstStationTime < Game.SecondsSinceMidnight)
                {
                    Game.SecondsSinceMidnight = OtherFirstStationTime;
                }
            }
            // initialize trains
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                TrainManager.Trains[i].Initialize();
                int s = i == TrainManager.PlayerTrain.TrainIndex ? PlayerFirstStationIndex : OtherFirstStationIndex;
                if (s >= 0)
                {
                    if (Game.Stations[s].OpenLeftDoors)
                    {
                        for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                        {
                            TrainManager.Trains[i].Cars[j].Doors[0].AnticipatedOpen = true;
                        }
                    }
                    if (Game.Stations[s].OpenRightDoors)
                    {
                        for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                        {
                            TrainManager.Trains[i].Cars[j].Doors[1].AnticipatedOpen = true;
                        }
                    }
                }
                if (Game.Sections.Length != 0)
                {
                    Game.Sections[0].Enter(TrainManager.Trains[i]);
                }
                for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                {
                    double length = TrainManager.Trains[i].Cars[0].Length;
                    TrainManager.Trains[i].Cars[j].Move(-length, 0.01);
                    TrainManager.Trains[i].Cars[j].Move(length, 0.01);
                }
            }
            // score
            Game.CurrentScore.ArrivalStation   = PlayerFirstStationIndex + 1;
            Game.CurrentScore.DepartureStation = PlayerFirstStationIndex;
            Game.CurrentScore.Maximum          = 0;
            for (int i = 0; i < Game.Stations.Length; i++)
            {
                if (i != PlayerFirstStationIndex & Game.PlayerStopsAtStation(i))
                {
                    if (i == 0 || Game.Stations[i - 1].Type != StationType.ChangeEnds)
                    {
                        Game.CurrentScore.Maximum += Game.ScoreValueStationArrival;
                    }
                }
            }
            if (Game.CurrentScore.Maximum <= 0)
            {
                Game.CurrentScore.Maximum = Game.ScoreValueStationArrival;
            }
            // signals
            if (Game.Sections.Length > 0)
            {
                Game.UpdateSection(Game.Sections.Length - 1);
            }
            // move train in position
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                double p;
                if (i == TrainManager.PlayerTrain.TrainIndex)
                {
                    p = PlayerFirstStationPosition;
                }
                else if (TrainManager.Trains[i].State == TrainManager.TrainState.Bogus)
                {
                    p = Game.BogusPretrainInstructions[0].TrackPosition;
                    TrainManager.Trains[i].AI = new Game.BogusPretrainAI(TrainManager.Trains[i]);
                }
                else
                {
                    p = OtherFirstStationPosition;
                }
                for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                {
                    TrainManager.Trains[i].Cars[j].Move(p, 0.01);
                }
            }
            // timetable
            if (Timetable.DefaultTimetableDescription.Length == 0)
            {
                Timetable.DefaultTimetableDescription = Game.LogTrainName;
            }

            // initialize camera
            if (World.CameraRestriction == World.CameraRestrictionMode.NotAvailable)
            {
                World.CameraMode = World.CameraViewMode.InteriorLookAhead;
            }
            //Place the initial camera in the driver car
            TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].UpdateCamera();
            World.CameraTrackFollower.Update(-1.0, true, false);
            ObjectManager.UpdateVisibility(World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z);
            World.CameraSavedExterior = new World.CameraAlignment(new OpenBveApi.Math.Vector3(-2.5, 1.5, -15.0), 0.3, -0.2, 0.0, PlayerFirstStationPosition, 1.0);
            World.CameraSavedTrack    = new World.CameraAlignment(new OpenBveApi.Math.Vector3(-3.0, 2.5, 0.0), 0.3, 0.0, 0.0, TrainManager.PlayerTrain.Cars[0].FrontAxle.Follower.TrackPosition - 10.0, 1.0);
            // signalling sections
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                int s = TrainManager.Trains[i].CurrentSectionIndex;
                Game.Sections[s].Enter(TrainManager.Trains[i]);
            }
            if (Game.Sections.Length > 0)
            {
                Game.UpdateSection(Game.Sections.Length - 1);
            }
            // fast-forward until start time
            {
                Game.MinimalisticSimulation = true;
                const double w = 0.25;
                double       u = Game.StartupTime - Game.SecondsSinceMidnight;
                if (u > 0)
                {
                    while (true)
                    {
                        double v = u < w ? u : w; u -= v;
                        Game.SecondsSinceMidnight += v;
                        TrainManager.UpdateTrains(v);
                        if (u <= 0.0)
                        {
                            break;
                        }
                        TotalTimeElapsedForSectionUpdate += v;
                        if (TotalTimeElapsedForSectionUpdate >= 1.0)
                        {
                            if (Game.Sections.Length > 0)
                            {
                                Game.UpdateSection(Game.Sections.Length - 1);
                            }
                            TotalTimeElapsedForSectionUpdate = 0.0;
                        }
                    }
                }
                Game.MinimalisticSimulation = false;
            }
            // animated objects
            ObjectManager.UpdateAnimatedWorldObjects(0.0, true);
            TrainManager.UpdateTrainObjects(0.0, true);
            //HACK: This function calls a single update on all objects attached to the player's train
            //      but ignores any specified damping so that all needles etc. are in the correct place
            //      for the first frame, rather than spinning wildly to get to the starting point.
            TrainManager.PlayerTrain.UpdateCabObjects();
            // timetable
            if (TrainManager.PlayerTrain.Station >= 0)
            {
                Timetable.UpdateCustomTimetable(Game.Stations[TrainManager.PlayerTrain.Station].TimetableDaytimeTexture, Game.Stations[TrainManager.PlayerTrain.Station].TimetableNighttimeTexture);
                if (Timetable.CustomObjectsUsed != 0 & Timetable.CustomTimetableAvailable && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.AutoGenerated && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.None)
                {
                    Timetable.CurrentTimetable = Timetable.TimetableState.Custom;
                }
            }
            //Create AI driver for the player train if specified via the commmand line
            if (Game.InitialAIDriver == true)
            {
                TrainManager.PlayerTrain.AI = new Game.SimpleHumanDriverAI(TrainManager.PlayerTrain);
                if (TrainManager.PlayerTrain.Plugin != null && !TrainManager.PlayerTrain.Plugin.SupportsAI)
                {
                    Game.AddMessage(Interface.GetInterfaceString("notification_aiunable"), MessageManager.MessageDependency.None, Interface.GameMode.Expert,
                                    OpenBveApi.Colors.MessageColor.White, Game.SecondsSinceMidnight + 10.0, null);
                }
            }

            // warnings / errors
            if (Interface.MessageCount != 0)
            {
                int filesNotFound = 0;
                int errors        = 0;
                int warnings      = 0;
                for (int i = 0; i < Interface.MessageCount; i++)
                {
                    if (Interface.Messages[i].FileNotFound)
                    {
                        filesNotFound++;
                    }
                    else if (Interface.Messages[i].Type == Interface.MessageType.Error)
                    {
                        errors++;
                    }
                    else if (Interface.Messages[i].Type == Interface.MessageType.Warning)
                    {
                        warnings++;
                    }
                }
                string NotFound = null;
                string Messages = null;
                if (filesNotFound != 0)
                {
                    NotFound = filesNotFound.ToString() + " file(s) not found";
                    Game.AddMessage(NotFound, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null);
                }
                if (errors != 0 & warnings != 0)
                {
                    Messages = errors.ToString() + " error(s), " + warnings.ToString() + " warning(s)";
                    Game.AddMessage(Messages, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null);
                }
                else if (errors != 0)
                {
                    Messages = errors.ToString() + " error(s)";
                    Game.AddMessage(Messages, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null);
                }
                else
                {
                    Messages = warnings.ToString() + " warning(s)";
                    Game.AddMessage(Messages, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null);
                }
                Game.RouteInformation.FilesNotFound     = NotFound;
                Game.RouteInformation.ErrorsAndWarnings = Messages;
                //Print the plugin error encountered (If any) for 10s
                //This must be done after the simulation has init, as otherwise the timeout doesn't work
                if (Loading.PluginError != null)
                {
                    Game.AddMessage(Loading.PluginError, MessageManager.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Game.SecondsSinceMidnight + 5.0, null);
                    Game.AddMessage(Interface.GetInterfaceString("errors_plugin_failure2"), MessageManager.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Game.SecondsSinceMidnight + 5.0, null);
                }
            }
            loadComplete          = true;
            RenderRealTimeElapsed = 0.0;
            RenderTimeElapsed     = 0.0;
            World.InitializeCameraRestriction();
            Loading.SimulationSetup = true;
            switch (Game.InitialViewpoint)
            {
            case 1:
                //Switch camera to exterior
                MainLoop.SaveCameraSettings();
                World.CameraMode = World.CameraViewMode.Exterior;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior);
                }
                //Make bogies visible
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                }
                World.CameraAlignmentDirection = new World.CameraAlignment();
                World.CameraAlignmentSpeed     = new World.CameraAlignment();
                MainLoop.UpdateViewport(MainLoop.ViewPortChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                World.UpdateViewingDistances();
                break;

            case 2:
                //Switch camera to track
                MainLoop.SaveCameraSettings();
                World.CameraMode = World.CameraViewMode.Track;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior);
                }

                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                }

                World.CameraAlignmentDirection = new World.CameraAlignment();
                World.CameraAlignmentSpeed     = new World.CameraAlignment();
                MainLoop.UpdateViewport(MainLoop.ViewPortChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                World.UpdateViewingDistances();
                break;

            case 3:
                //Switch camera to flyby
                MainLoop.SaveCameraSettings();
                World.CameraMode = World.CameraViewMode.FlyBy;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior);
                }

                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                }

                World.CameraAlignmentDirection = new World.CameraAlignment();
                World.CameraAlignmentSpeed     = new World.CameraAlignment();
                MainLoop.UpdateViewport(MainLoop.ViewPortChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                World.UpdateViewingDistances();
                break;

            case 4:
                //Switch camera to flyby
                MainLoop.SaveCameraSettings();
                World.CameraMode = World.CameraViewMode.FlyByZooming;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(TrainManager.CarSectionType.Exterior);
                }

                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                }

                World.CameraAlignmentDirection = new World.CameraAlignment();
                World.CameraAlignmentSpeed     = new World.CameraAlignment();
                MainLoop.UpdateViewport(MainLoop.ViewPortChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                World.UpdateViewingDistances();
                break;
            }
        }
Beispiel #2
0
            /// <summary>This method should be called once a frame to update the player's score</summary>
            /// <param name="TimeElapsed">The time elapsed since this function was last called</param>
            internal void Update(double TimeElapsed)
            {
                // doors
                {
                    bool leftopen  = false;
                    bool rightopen = false;
                    for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                    {
                        for (int k = 0; k < TrainManager.PlayerTrain.Cars[j].Doors.Length; k++)
                        {
                            if (TrainManager.PlayerTrain.Cars[j].Doors[k].State != 0.0)
                            {
                                if (TrainManager.PlayerTrain.Cars[j].Doors[k].Direction == -1)
                                {
                                    leftopen = true;
                                }
                                else if (TrainManager.PlayerTrain.Cars[j].Doors[k].Direction == 1)
                                {
                                    rightopen = true;
                                }
                            }
                        }
                    }
                    bool bad;
                    if (leftopen | rightopen)
                    {
                        bad = true;
                        int j = TrainManager.PlayerTrain.Station;
                        if (j >= 0)
                        {
                            int p = Game.GetStopIndex(j, TrainManager.PlayerTrain.Cars.Length);
                            if (p >= 0)
                            {
                                if (Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) < 0.1)
                                {
                                    if (leftopen == Stations[j].OpenLeftDoors & rightopen == Stations[j].OpenRightDoors)
                                    {
                                        bad = false;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        bad = false;
                    }
                    if (bad)
                    {
                        OpenedDoorsCounter += (Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) + 0.25) * TimeElapsed;
                    }
                    else if (OpenedDoorsCounter != 0.0)
                    {
                        int x = (int)Math.Ceiling(ScoreFactorOpenedDoors * OpenedDoorsCounter);
                        this.CurrentValue += x;
                        if (x != 0)
                        {
                            AddScore(x, ScoreTextToken.DoorsOpened, 5.0);
                        }
                        OpenedDoorsCounter = 0.0;
                    }
                }
                // overspeed
                double nr = TrainManager.PlayerTrain.CurrentRouteLimit;
                double ns = TrainManager.PlayerTrain.CurrentSectionLimit;
                double n  = nr < ns ? nr : ns;
                double a  = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) - 0.277777777777778;

                if (a > n)
                {
                    OverspeedCounter += (a - n) * TimeElapsed;
                }
                else if (OverspeedCounter != 0.0)
                {
                    int x = (int)Math.Ceiling(ScoreFactorOverspeed * OverspeedCounter);
                    this.CurrentValue += x;
                    if (x != 0)
                    {
                        AddScore(x, ScoreTextToken.Overspeed, 5.0);
                    }
                    OverspeedCounter = 0.0;
                }
                // toppling
                {
                    bool q = false;
                    for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                    {
                        if (TrainManager.PlayerTrain.Cars[j].Topples)
                        {
                            q = true;
                            break;
                        }
                    }
                    if (q)
                    {
                        TopplingCounter += TimeElapsed;
                    }
                    else if (TopplingCounter != 0.0)
                    {
                        int x = (int)Math.Ceiling(ScoreFactorToppling * TopplingCounter);
                        this.CurrentValue += x;
                        if (x != 0)
                        {
                            AddScore(x, ScoreTextToken.Toppling, 5.0);
                        }
                        TopplingCounter = 0.0;
                    }
                }
                // derailment
                if (!Derailed)
                {
                    bool q = false;
                    for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                    {
                        if (TrainManager.PlayerTrain.Cars[j].Derailed)
                        {
                            q = true;
                            break;
                        }
                    }
                    if (q)
                    {
                        int x = ScoreValueDerailment;
                        if (this.CurrentValue > 0)
                        {
                            x -= this.CurrentValue;
                        }
                        this.CurrentValue += x;
                        if (x != 0)
                        {
                            AddScore(x, ScoreTextToken.Derailed, 5.0);
                        }
                        Derailed = true;
                    }
                }
                // red signal
                {
                    if (TrainManager.PlayerTrain.CurrentSectionLimit == 0.0)
                    {
                        if (!RedSignal)
                        {
                            int x = ScoreValueRedSignal;
                            this.CurrentValue += x;
                            if (x != 0)
                            {
                                AddScore(x, ScoreTextToken.PassedRedSignal, 5.0);
                            }
                            RedSignal = true;
                        }
                    }
                    else
                    {
                        RedSignal = false;
                    }
                }
                // arrival
                {
                    int j = TrainManager.PlayerTrain.Station;
                    if (j >= 0 & j < Stations.Length)
                    {
                        if (j >= ArrivalStation & TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Boarding)
                        {
                            if (j == 0 || Stations[j - 1].Type != StationType.ChangeEnds)
                            {
                                // arrival
                                int xa = ScoreValueStationArrival;
                                this.CurrentValue += xa;
                                if (xa != 0)
                                {
                                    AddScore(xa, ScoreTextToken.ArrivedAtStation, 10.0);
                                }
                                // early/late
                                int xb;
                                if (Stations[j].ArrivalTime >= 0)
                                {
                                    double d = SecondsSinceMidnight - Stations[j].ArrivalTime;
                                    if (d >= -5.0 & d <= 0.0)
                                    {
                                        xb = ScoreValueStationPerfectTime;
                                        this.CurrentValue += xb;
                                        AddScore(xb, ScoreTextToken.PerfectTimeBonus, 10.0);
                                    }
                                    else if (d > 0.0)
                                    {
                                        xb = (int)Math.Ceiling(ScoreFactorStationLate * (d - 1.0));
                                        this.CurrentValue += xb;
                                        if (xb != 0)
                                        {
                                            AddScore(xb, ScoreTextToken.Late, 10.0);
                                        }
                                    }
                                    else
                                    {
                                        xb = 0;
                                    }
                                }
                                else
                                {
                                    xb = 0;
                                }
                                // position
                                int xc;
                                int p = Game.GetStopIndex(j, TrainManager.PlayerTrain.Cars.Length);
                                if (p >= 0)
                                {
                                    double d = TrainManager.PlayerTrain.StationDistanceToStopPoint;
                                    double r;
                                    if (d >= 0)
                                    {
                                        double t = Stations[j].Stops[p].BackwardTolerance;
                                        r = (Math.Sqrt(d * d + 1.0) - 1.0) / (Math.Sqrt(t * t + 1.0) - 1.0);
                                    }
                                    else
                                    {
                                        double t = Stations[j].Stops[p].ForwardTolerance;
                                        r = (Math.Sqrt(d * d + 1.0) - 1.0) / (Math.Sqrt(t * t + 1.0) - 1.0);
                                    }
                                    if (r < 0.01)
                                    {
                                        xc = ScoreValueStationPerfectStop;
                                        this.CurrentValue += xc;
                                        AddScore(xc, ScoreTextToken.PerfectStopBonus, 10.0);
                                    }
                                    else
                                    {
                                        if (r > 1.0)
                                        {
                                            r = 1.0;
                                        }
                                        r  = (r - 0.01) * 1.01010101010101;
                                        xc = (int)Math.Ceiling(ScoreFactorStationStop * r);
                                        this.CurrentValue += xc;
                                        if (xc != 0)
                                        {
                                            AddScore(xc, ScoreTextToken.Stop, 10.0);
                                        }
                                    }
                                }
                                else
                                {
                                    xc = 0;
                                }
                                // sum
                                if (Interface.CurrentOptions.GameMode == Interface.GameMode.Arcade)
                                {
                                    int xs = xa + xb + xc;
                                    AddScore("", 10.0);
                                    AddScore(xs, ScoreTextToken.Total, 10.0, false);
                                    AddScore(" ", 10.0);
                                }
                                // evaluation
                                if (Interface.CurrentOptions.GameMode == Interface.GameMode.Arcade)
                                {
                                    if (Stations[j].Type == StationType.Terminal)
                                    {
                                        double y = (double)this.CurrentValue / (double)Maximum;
                                        if (y < 0.0)
                                        {
                                            y = 0.0;
                                        }
                                        if (y > 1.0)
                                        {
                                            y = 1.0;
                                        }
                                        int k = (int)Math.Floor(y * (double)Translations.RatingsCount);
                                        if (k >= Translations.RatingsCount)
                                        {
                                            k = Translations.RatingsCount - 1;
                                        }
                                        System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                                        AddScore(Translations.GetInterfaceString("score_rating"), 20.0);
                                        AddScore(Translations.GetInterfaceString("rating_" + k.ToString(Culture)) + " (" + (100.0 * y).ToString("0.00", Culture) + "%)", 20.0);
                                    }
                                }
                            }
                            // finalize
                            DepartureStation = j;
                            ArrivalStation   = j + 1;
                        }
                    }
                }
                // departure
                {
                    int j = TrainManager.PlayerTrain.Station;
                    if (j >= 0 & j < Stations.Length & j == DepartureStation)
                    {
                        bool q;
                        if (Stations[j].OpenLeftDoors | Stations[j].OpenRightDoors)
                        {
                            q = TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Completed;
                        }
                        else
                        {
                            q = TrainManager.PlayerTrain.StationState != TrainManager.TrainStopState.Pending & (TrainManager.PlayerTrain.Specs.CurrentAverageSpeed <-1.5 | TrainManager.PlayerTrain.Specs.CurrentAverageSpeed> 1.5);
                        }
                        if (q)
                        {
                            double r = TrainManager.PlayerTrain.StationDepartureTime - SecondsSinceMidnight;
                            if (r > 0.0)
                            {
                                int x = (int)Math.Ceiling(ScoreFactorStationDeparture * r);
                                this.CurrentValue += x;
                                if (x != 0)
                                {
                                    AddScore(x, ScoreTextToken.PrematureDeparture, 5.0);
                                }
                            }
                            DepartureStation = -1;
                        }
                    }
                }
                // passengers
                if (TrainManager.PlayerTrain.Passengers.FallenOver & PassengerTimer == 0.0)
                {
                    int x = ScoreValuePassengerDiscomfort;
                    this.CurrentValue += x;
                    AddScore(x, ScoreTextToken.PassengerDiscomfort, 5.0);
                    PassengerTimer = 5.0;
                }
                else
                {
                    PassengerTimer -= TimeElapsed;
                    if (PassengerTimer <= 0.0)
                    {
                        if (TrainManager.PlayerTrain.Passengers.FallenOver)
                        {
                            PassengerTimer = 5.0;
                        }
                        else
                        {
                            PassengerTimer = 0.0;
                        }
                    }
                }
            }
Beispiel #3
0
        /// <summary>Jumps a train to a new station</summary>
        /// <param name="train">The train</param>
        /// <param name="stationIndex">The zero-based index of the station</param>
        internal static void JumpTrain(Train train, int stationIndex)
        {
            if (train == PlayerTrain)
            {
                for (int i = 0; i < ObjectManager.AnimatedWorldObjects.Length; i++)
                {
                    var obj = ObjectManager.AnimatedWorldObjects[i] as ObjectManager.TrackFollowingObject;
                    if (obj != null)
                    {
                        //Track followers should be reset if we jump between stations
                        obj.FrontAxleFollower.TrackPosition = ObjectManager.AnimatedWorldObjects[i].TrackPosition + obj.FrontAxlePosition;
                        obj.FrontAxleFollower.TrackPosition = ObjectManager.AnimatedWorldObjects[i].TrackPosition + obj.RearAxlePosition;
                        obj.FrontAxleFollower.UpdateWorldCoordinates(false);
                        obj.RearAxleFollower.UpdateWorldCoordinates(false);
                    }
                }
            }
            train.StationState = TrainStopState.Jumping;
            int stopIndex = Game.GetStopIndex(stationIndex, train.Cars.Length);

            if (stopIndex >= 0)
            {
                if (train == PlayerTrain)
                {
                    if (train.Plugin != null)
                    {
                        train.Plugin.BeginJump((OpenBveApi.Runtime.InitializationModes)Game.TrainStart);
                    }
                }
                for (int h = 0; h < train.Cars.Length; h++)
                {
                    train.Cars[h].Specs.CurrentSpeed = 0.0;
                }
                double d = Game.Stations[stationIndex].Stops[stopIndex].TrackPosition - train.Cars[0].FrontAxle.Follower.TrackPosition + train.Cars[0].FrontAxle.Position - 0.5 * train.Cars[0].Length;
                if (train == PlayerTrain)
                {
                    TrackManager.SuppressSoundEvents = true;
                }
                while (d != 0.0)
                {
                    double x;
                    if (Math.Abs(d) > 1.0)
                    {
                        x = (double)Math.Sign(d);
                    }
                    else
                    {
                        x = d;
                    }
                    for (int h = 0; h < train.Cars.Length; h++)
                    {
                        train.Cars[h].Move(x, 0.0);
                    }
                    if (Math.Abs(d) >= 1.0)
                    {
                        d -= x;
                    }
                    else
                    {
                        break;
                    }
                }
                if (train == PlayerTrain)
                {
                    TrainManager.UnderailTrains();
                    TrackManager.SuppressSoundEvents = false;
                }
                if (train.Handles.EmergencyBrake.Driver)
                {
                    train.ApplyNotch(0, false, 0, true);
                }
                else
                {
                    train.ApplyNotch(0, false, train.Handles.Brake.MaximumNotch, false);
                    train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                }
                if (Game.Sections.Length > 0)
                {
                    Game.UpdateSection(Game.Sections.Length - 1);
                }
                if (train == PlayerTrain)
                {
                    if (Game.CurrentScore.ArrivalStation <= stationIndex)
                    {
                        Game.CurrentScore.ArrivalStation = stationIndex + 1;
                    }
                }
                if (train == PlayerTrain)
                {
                    if (Game.Stations[stationIndex].ArrivalTime >= 0.0)
                    {
                        Game.SecondsSinceMidnight = Game.Stations[stationIndex].ArrivalTime;
                    }
                    else if (Game.Stations[stationIndex].DepartureTime >= 0.0)
                    {
                        Game.SecondsSinceMidnight = Game.Stations[stationIndex].DepartureTime - Game.Stations[stationIndex].StopTime;
                    }
                }
                for (int i = 0; i < train.Cars.Length; i++)
                {
                    train.Cars[i].Doors[0].AnticipatedOpen = Game.Stations[stationIndex].OpenLeftDoors;
                    train.Cars[i].Doors[1].AnticipatedOpen = Game.Stations[stationIndex].OpenRightDoors;
                }
                if (train == PlayerTrain)
                {
                    Game.CurrentScore.DepartureStation = stationIndex;
                    Game.CurrentInterface = Game.InterfaceType.Normal;
                    //Game.Messages = new Game.Message[] { };
                }
                ObjectManager.UpdateAnimatedWorldObjects(0.0, true);
                TrainManager.UpdateTrainObjects(0.0, true);
                if (train == PlayerTrain)
                {
                    if (train.Plugin != null)
                    {
                        train.Plugin.EndJump();
                    }
                }
                train.StationState = TrainStopState.Pending;
            }
        }
Beispiel #4
0
        /// <summary>Is called once a frame to update the station state for the given train</summary>
        /// <param name="Train">The train</param>
        /// <param name="TimeElapsed">The frame time elapsed</param>
        private static void UpdateTrainStation(Train Train, double TimeElapsed)
        {
            if (Train.Station >= 0)
            {
                int    i = Train.Station;
                int    n = Game.GetStopIndex(Train.Station, Train.Cars.Length);
                double tf, tb;
                if (n >= 0)
                {
                    double p0 = Train.Cars[0].FrontAxle.Follower.TrackPosition - Train.Cars[0].FrontAxle.Position + 0.5 * Train.Cars[0].Length;
                    double p1 = Game.Stations[i].Stops[n].TrackPosition;
                    tf = Game.Stations[i].Stops[n].ForwardTolerance;
                    tb = Game.Stations[i].Stops[n].BackwardTolerance;
                    Train.StationDistanceToStopPoint = p1 - p0;
                }
                else
                {
                    Train.StationDistanceToStopPoint = 0.0;
                    tf = 5.0;
                    tb = 5.0;
                }
                if (Train.StationState == TrainStopState.Pending)
                {
                    Train.StationDepartureSoundPlayed = false;
                    if (Game.StopsAtStation(i, Train))
                    {
                        Train.StationDepartureSoundPlayed = false;
                        //Check whether all doors are controlled by the driver
                        if (Train.Specs.DoorOpenMode != DoorMode.Manual)
                        {
                            //Check that we are not moving
                            if (Math.Abs(Train.Specs.CurrentAverageSpeed) < 0.1 / 3.6 &
                                Math.Abs(Train.Specs.CurrentAverageAcceleration) < 0.1 / 3.6)
                            {
                                //Check the interlock state for the doors
                                switch (Train.Specs.DoorInterlockState)
                                {
                                case DoorInterlockStates.Unlocked:
                                    if (Game.Stations[i].OpenLeftDoors || Game.Stations[i].OpenRightDoors)
                                    {
                                        AttemptToOpenDoors(Train, i, tb, tf);
                                    }
                                    break;

                                case DoorInterlockStates.Left:
                                    if (Game.Stations[i].OpenLeftDoors && !Game.Stations[i].OpenRightDoors)
                                    {
                                        AttemptToOpenDoors(Train, i, tb, tf);
                                    }
                                    break;

                                case DoorInterlockStates.Right:
                                    if (!Game.Stations[i].OpenLeftDoors && Game.Stations[i].OpenRightDoors)
                                    {
                                        AttemptToOpenDoors(Train, i, tb, tf);
                                    }
                                    break;

                                case DoorInterlockStates.Locked:
                                    //All doors are currently locked, do nothing
                                    break;
                                }
                            }
                        }
                        // detect arrival
                        if (Train.Specs.CurrentAverageSpeed > -0.277777777777778 & Train.Specs.CurrentAverageSpeed < 0.277777777777778)
                        {
                            bool left, right;
                            if (Game.Stations[i].OpenLeftDoors)
                            {
                                left = false;
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    if (Train.Cars[j].Specs.AnticipatedLeftDoorsOpened)
                                    {
                                        left = true; break;
                                    }
                                }
                            }
                            else
                            {
                                left = true;
                            }
                            if (Game.Stations[i].OpenRightDoors)
                            {
                                right = false;
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    if (Train.Cars[j].Specs.AnticipatedRightDoorsOpened)
                                    {
                                        right = true; break;
                                    }
                                }
                            }
                            else
                            {
                                right = true;
                            }
                            if (left & right)
                            {
                                // arrival
                                Train.StationState  = TrainStopState.Boarding;
                                Train.StationAdjust = false;
                                Train.Specs.DoorClosureAttempted = false;
                                Sounds.StopSound(Train.Cars[Train.DriverCar].Sounds.Halt.Source);
                                Sounds.SoundBuffer buffer = Game.Stations[i].ArrivalSoundBuffer;
                                if (buffer != null)
                                {
                                    OpenBveApi.Math.Vector3 pos = Game.Stations[i].SoundOrigin;
                                    Sounds.PlaySound(buffer, 1.0, 1.0, pos, false);
                                }
                                Train.StationArrivalTime   = Game.SecondsSinceMidnight;
                                Train.StationDepartureTime = Game.Stations[i].DepartureTime - Train.TimetableDelta;
                                if (Train.StationDepartureTime - Game.SecondsSinceMidnight < Game.Stations[i].StopTime)
                                {
                                    Train.StationDepartureTime = Game.SecondsSinceMidnight + Game.Stations[i].StopTime;
                                }
                                Train.Passengers.PassengerRatio = Game.Stations[i].PassengerRatio;
                                UpdateTrainMassFromPassengerRatio(Train);
                                if (Train == PlayerTrain)
                                {
                                    double early = 0.0;
                                    if (Game.Stations[i].ArrivalTime >= 0.0)
                                    {
                                        early = (Game.Stations[i].ArrivalTime - Train.TimetableDelta) - Train.StationArrivalTime;
                                    }
                                    string s;
                                    if (early < -1.0)
                                    {
                                        s = Interface.GetInterfaceString("message_station_arrival_late");
                                    }
                                    else if (early > 1.0)
                                    {
                                        s = Interface.GetInterfaceString("message_station_arrival_early");
                                    }
                                    else
                                    {
                                        s = Interface.GetInterfaceString("message_station_arrival");
                                    }
                                    System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                                    TimeSpan a = TimeSpan.FromSeconds(Math.Abs(early));
                                    string   b = a.Hours.ToString("00", Culture) + ":" + a.Minutes.ToString("00", Culture) + ":" + a.Seconds.ToString("00", Culture);
                                    if (Train.StationDistanceToStopPoint < -0.1)
                                    {
                                        s += Interface.GetInterfaceString("message_delimiter") + Interface.GetInterfaceString("message_station_overrun");
                                    }
                                    else if (Train.StationDistanceToStopPoint > 0.1)
                                    {
                                        s += Interface.GetInterfaceString("message_delimiter") + Interface.GetInterfaceString("message_station_underrun");
                                    }
                                    double d = Math.Abs(Train.StationDistanceToStopPoint);
                                    string c = d.ToString("0.0", Culture);
                                    if (Game.Stations[i].StationType == Game.StationType.Terminal)
                                    {
                                        s += Interface.GetInterfaceString("message_delimiter") + Interface.GetInterfaceString("message_station_terminal");
                                    }
                                    s = s.Replace("[name]", Game.Stations[i].Name);
                                    s = s.Replace("[time]", b);
                                    s = s.Replace("[difference]", c);
                                    Game.AddMessage(s, MessageManager.MessageDependency.StationArrival, Interface.GameMode.Normal, MessageColor.White, Game.SecondsSinceMidnight + 10.0, null);
                                    if (Game.Stations[i].StationType == Game.StationType.Normal)
                                    {
                                        s = Interface.GetInterfaceString("message_station_deadline");
                                        Game.AddMessage(s, MessageManager.MessageDependency.StationDeparture, Interface.GameMode.Normal, MessageColor.White, double.PositiveInfinity, null);
                                    }
                                    Timetable.UpdateCustomTimetable(Game.Stations[i].TimetableDaytimeTexture, Game.Stations[i].TimetableNighttimeTexture);
                                }
                                // schedule door locks (passengers stuck between the doors)
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++)
                                    {
                                        Train.Cars[j].Specs.Doors[k].DoorLockDuration = 0.0;
                                        if (Game.Stations[i].OpenLeftDoors & Train.Cars[j].Specs.Doors[k].Direction == -1 | Game.Stations[i].OpenRightDoors & Train.Cars[j].Specs.Doors[k].Direction == 1)
                                        {
                                            double p = 0.005 * Game.Stations[i].PassengerRatio * Game.Stations[i].PassengerRatio * Game.Stations[i].PassengerRatio * Game.Stations[i].PassengerRatio;
                                            if (Program.RandomNumberGenerator.NextDouble() < p)
                                            {
                                                /*
                                                 * -- door lock at state --
                                                 * minimum: 0.2 (nearly closed)
                                                 * maximum: 0.8 (nearly opened)
                                                 * */
                                                Train.Cars[j].Specs.Doors[k].DoorLockState = 0.2 + 0.6 * Program.RandomNumberGenerator.NextDouble();

                                                /* -- waiting time --
                                                 * minimum: 2.9 s
                                                 * maximum: 40.0 s
                                                 * average: 7.6 s
                                                 * */
                                                p = Program.RandomNumberGenerator.NextDouble();
                                                Train.Cars[j].Specs.Doors[k].DoorLockDuration = (50.0 - 10.0 * p) / (17.0 - 16.0 * p);
                                            }
                                        }
                                    }
                                }
                            }
                            else if (Train.Specs.CurrentAverageSpeed > -0.277777777777778 & Train.Specs.CurrentAverageSpeed < 0.277777777777778)
                            {
                                // correct stop position
                                if (!Train.StationAdjust & (Train.StationDistanceToStopPoint > tb | Train.StationDistanceToStopPoint < -tf))
                                {
                                    Sounds.SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.Adjust.Buffer;
                                    if (buffer != null)
                                    {
                                        OpenBveApi.Math.Vector3 pos = Train.Cars[Train.DriverCar].Sounds.Adjust.Position;
                                        Sounds.PlaySound(buffer, 1.0, 1.0, pos, Train, Train.DriverCar, false);
                                    }
                                    if (Train == TrainManager.PlayerTrain)
                                    {
                                        Game.AddMessage(Interface.GetInterfaceString("message_station_correct"), MessageManager.MessageDependency.None, Interface.GameMode.Normal, MessageColor.Orange, Game.SecondsSinceMidnight + 5.0, null);
                                    }
                                    Train.StationAdjust = true;
                                }
                            }
                            else
                            {
                                Train.StationAdjust = false;
                            }
                        }
                    }
                }
                else if (Train.StationState == TrainStopState.Boarding)
                {
                    //Check whether all doors are controlled by the driver, and whether this is a non-standard station type
                    //e.g. Change ends
                    if (Train.Specs.DoorOpenMode != DoorMode.Manual & Game.Stations[i].StationType == Game.StationType.Normal)
                    {
                        //Check the interlock state for the doors
                        switch (Train.Specs.DoorInterlockState)
                        {
                        case DoorInterlockStates.Unlocked:
                            AttemptToCloseDoors(Train);
                            break;

                        case DoorInterlockStates.Left:
                            if (Game.Stations[i].OpenLeftDoors)
                            {
                                AttemptToCloseDoors(Train);
                            }
                            break;

                        case DoorInterlockStates.Right:
                            if (Game.Stations[i].OpenRightDoors)
                            {
                                AttemptToCloseDoors(Train);
                            }
                            break;

                        case DoorInterlockStates.Locked:
                            //All doors are currently locked, do nothing
                            break;
                        }
                    }
                    // detect departure
                    bool left, right;
                    if (!Game.Stations[i].OpenLeftDoors & !Game.Stations[i].OpenRightDoors)
                    {
                        left  = true;
                        right = true;
                    }
                    else
                    {
                        if (Game.Stations[i].OpenLeftDoors)
                        {
                            left = false;
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++)
                                {
                                    if (Train.Cars[j].Specs.Doors[k].State != 0.0)
                                    {
                                        left = true; break;
                                    }
                                }
                                if (left)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            left = false;
                        }
                        if (Game.Stations[i].OpenRightDoors)
                        {
                            right = false;
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                for (int k = 0; k < Train.Cars[j].Specs.Doors.Length; k++)
                                {
                                    if (Train.Cars[j].Specs.Doors[k].State != 0.0)
                                    {
                                        right = true; break;
                                    }
                                }
                                if (right)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            right = false;
                        }
                    }
                    if (left | right)
                    {
                        // departure message
                        if (Game.SecondsSinceMidnight > Train.StationDepartureTime && (Game.Stations[i].StationType != Game.StationType.Terminal || Train != PlayerTrain))
                        {
                            Train.StationState = TrainStopState.Completed;
                            if (Train == PlayerTrain & Game.Stations[i].StationType == Game.StationType.Normal)
                            {
                                if (!Game.Stations[i].OpenLeftDoors & !Game.Stations[i].OpenRightDoors | Train.Specs.DoorCloseMode != DoorMode.Manual)
                                {
                                    Game.AddMessage(Interface.GetInterfaceString("message_station_depart"), MessageManager.MessageDependency.None, Interface.GameMode.Normal, MessageColor.White, Game.SecondsSinceMidnight + 5.0, null);
                                }
                                else
                                {
                                    Game.AddMessage(Interface.GetInterfaceString("message_station_depart_closedoors"), MessageManager.MessageDependency.None, Interface.GameMode.Normal, MessageColor.White, Game.SecondsSinceMidnight + 5.0, null);
                                }
                            }
                            else if (Game.Stations[i].StationType == Game.StationType.ChangeEnds)
                            {
                                //Game.AddMessage("CHANGE ENDS", MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 5.0);
                                JumpTrain(Train, i + 1);
                            }
                        }
                        if (Interface.CurrentOptions.LoadingSway)
                        {
                            // passengers boarding
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                double r = 2.0 * Game.Stations[i].PassengerRatio * TimeElapsed;
                                if (r >= Program.RandomNumberGenerator.NextDouble())
                                {
                                    int d =
                                        (int)Math.Floor(Program.RandomNumberGenerator.NextDouble() * (double)Train.Cars[j].Specs.Doors.Length);
                                    if (Train.Cars[j].Specs.Doors[d].State == 1.0)
                                    {
                                        Train.Cars[j].Specs.CurrentRollShakeDirection += (double)Train.Cars[j].Specs.Doors[d].Direction;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        Train.StationState = TrainStopState.Completed;
                        if (Train == PlayerTrain & Game.Stations[i].StationType == Game.StationType.Normal)
                        {
                            Game.AddMessage(Interface.GetInterfaceString("message_station_depart"), MessageManager.MessageDependency.None, Interface.GameMode.Normal, MessageColor.White, Game.SecondsSinceMidnight + 5.0, null);
                        }
                    }
                    // departure sound
                    if (!Train.StationDepartureSoundPlayed)
                    {
                        Sounds.SoundBuffer buffer = Game.Stations[i].DepartureSoundBuffer;
                        if (buffer != null)
                        {
                            double dur = Sounds.GetDuration(buffer);
                            if (Game.SecondsSinceMidnight >= Train.StationDepartureTime - dur)
                            {
                                Sounds.PlaySound(buffer, 1.0, 1.0, Game.Stations[i].SoundOrigin, false);
                                Train.StationDepartureSoundPlayed = true;
                            }
                        }
                    }
                }
            }
            else
            {
                Train.StationState = TrainStopState.Pending;
            }
            // automatically close doors
            if (Train.Specs.DoorCloseMode != DoorMode.Manual & Train.Specs.DoorInterlockState != DoorInterlockStates.Locked & !Train.Specs.DoorClosureAttempted)
            {
                if (Train.Station == -1 | Train.StationState == TrainStopState.Completed)
                {
                    if ((GetDoorsState(Train, true, true) & TrainDoorState.AllClosed) == 0)
                    {
                        CloseTrainDoors(Train, true, true);
                        Train.Specs.DoorClosureAttempted = true;
                    }
                }
            }
        }
        /// <summary>Renders all default HUD elements</summary>
        /// <param name="Element">The HUD element these are to be rendererd onto</param>
        /// <param name="TimeElapsed">The time elapsed</param>
        private static void RenderHUDElement(Interface.HudElement Element, double TimeElapsed)
        {
            TrainManager.TrainDoorState      LeftDoors  = TrainManager.GetDoorsState(TrainManager.PlayerTrain, true, false);
            TrainManager.TrainDoorState      RightDoors = TrainManager.GetDoorsState(TrainManager.PlayerTrain, false, true);
            System.Globalization.CultureInfo Culture    = System.Globalization.CultureInfo.InvariantCulture;
            string Command = Element.Subject.ToLowerInvariant();
            // default
            double w, h;

            if (Element.CenterMiddle.BackgroundTexture != null)
            {
                if (Textures.LoadTexture(Element.CenterMiddle.BackgroundTexture, Textures.OpenGlTextureWrapMode.ClampClamp))
                {
                    w = (double)Element.CenterMiddle.BackgroundTexture.Width;
                    h = (double)Element.CenterMiddle.BackgroundTexture.Height;
                }
                else
                {
                    w = 0.0; h = 0.0;
                }
            }
            else
            {
                w = 0.0; h = 0.0;
            }
            double x = Element.Alignment.X < 0 ? 0.0 : Element.Alignment.X == 0 ? 0.5 * (Screen.Width - w) : Screen.Width - w;
            double y = Element.Alignment.Y < 0 ? 0.0 : Element.Alignment.Y == 0 ? 0.5 * (Screen.Height - h) : Screen.Height - h;

            x += Element.Position.X;
            y += Element.Position.Y;
            // command
            const double speed = 1.0;
            MessageColor sc    = MessageColor.None;
            string       t;

            switch (Command)
            {
            case "reverser":
                if (TrainManager.PlayerTrain.Handles.Reverser.Driver < 0)
                {
                    sc = MessageColor.Orange;
                    if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 2)
                    {
                        t = TrainManager.PlayerTrain.ReverserDescriptions[2];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleBackward;
                    }
                }
                else if (TrainManager.PlayerTrain.Handles.Reverser.Driver > 0)
                {
                    sc = MessageColor.Blue;
                    if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 0)
                    {
                        t = TrainManager.PlayerTrain.ReverserDescriptions[0];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleForward;
                    }
                }
                else
                {
                    sc = MessageColor.Gray;
                    if (TrainManager.PlayerTrain.ReverserDescriptions != null && TrainManager.PlayerTrain.ReverserDescriptions.Length > 1)
                    {
                        t = TrainManager.PlayerTrain.ReverserDescriptions[1];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleNeutral;
                    }
                }
                Element.TransitionState = 0.0;
                break;

            case "power":
                if (TrainManager.PlayerTrain.Handles.SingleHandle)
                {
                    return;
                }
                if (TrainManager.PlayerTrain.Handles.Power.Driver == 0)
                {
                    sc = MessageColor.Gray;
                    if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.PowerNotchDescriptions.Length > 0)
                    {
                        t = TrainManager.PlayerTrain.PowerNotchDescriptions[0];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandlePowerNull;
                    }
                }
                else
                {
                    sc = MessageColor.Blue;
                    if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.Handles.Power.Driver < TrainManager.PlayerTrain.PowerNotchDescriptions.Length)
                    {
                        t = TrainManager.PlayerTrain.PowerNotchDescriptions[TrainManager.PlayerTrain.Handles.Power.Driver];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandlePower + TrainManager.PlayerTrain.Handles.Power.Driver.ToString(Culture);
                    }
                }
                Element.TransitionState = 0.0;
                break;

            case "brake":
                if (TrainManager.PlayerTrain.Handles.SingleHandle)
                {
                    return;
                }
                if (TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].Specs.BrakeType == TrainManager.CarBrakeType.AutomaticAirBrake)
                {
                    if (TrainManager.PlayerTrain.Handles.EmergencyBrake.Driver)
                    {
                        sc = MessageColor.Red;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 0)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[0];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleEmergency;
                        }
                    }
                    else if (TrainManager.PlayerTrain.Handles.AirBrake.Handle.Driver == TrainManager.AirBrakeHandleState.Release)
                    {
                        sc = MessageColor.Gray;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleRelease;
                        }
                    }
                    else if (TrainManager.PlayerTrain.Handles.AirBrake.Handle.Driver == TrainManager.AirBrakeHandleState.Lap)
                    {
                        sc = MessageColor.Blue;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 2)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[2];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleLap;
                        }
                    }
                    else
                    {
                        sc = MessageColor.Orange;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 3)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[3];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleService;
                        }
                    }
                }
                else
                {
                    if (TrainManager.PlayerTrain.Handles.EmergencyBrake.Driver)
                    {
                        sc = MessageColor.Red;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 0)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[0];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleEmergency;
                        }
                    }
                    else if (TrainManager.PlayerTrain.Handles.HoldBrake.Driver)
                    {
                        sc = MessageColor.Green;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 2)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[2];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleHoldBrake;
                        }
                    }
                    else if (TrainManager.PlayerTrain.Handles.Brake.Driver == 0)
                    {
                        sc = MessageColor.Gray;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1)
                        {
                            t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleBrakeNull;
                        }
                    }
                    else
                    {
                        sc = MessageColor.Orange;
                        if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && ((TrainManager.PlayerTrain.Handles.HasHoldBrake && TrainManager.PlayerTrain.Handles.Brake.Driver + 2 < TrainManager.PlayerTrain.BrakeNotchDescriptions.Length) || (!TrainManager.PlayerTrain.Handles.HasHoldBrake && TrainManager.PlayerTrain.Handles.Brake.Driver + 1 < TrainManager.PlayerTrain.BrakeNotchDescriptions.Length)))
                        {
                            t = TrainManager.PlayerTrain.Handles.HasHoldBrake ? TrainManager.PlayerTrain.BrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.Brake.Driver + 2] : TrainManager.PlayerTrain.BrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.Brake.Driver + 1];
                        }
                        else
                        {
                            t = Interface.QuickReferences.HandleBrake + TrainManager.PlayerTrain.Handles.Brake.Driver.ToString(Culture);
                        }
                    }
                }
                Element.TransitionState = 0.0;
                break;

            case "locobrake":
                if (!TrainManager.PlayerTrain.Handles.HasLocoBrake)
                {
                    return;
                }
                if (TrainManager.PlayerTrain.Handles.LocoBrake.Driver == 0)
                {
                    sc = MessageColor.Gray;
                    if (TrainManager.PlayerTrain.LocoBrakeNotchDescriptions != null && TrainManager.PlayerTrain.LocoBrakeNotchDescriptions.Length > 1)
                    {
                        t = TrainManager.PlayerTrain.LocoBrakeNotchDescriptions[1];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleBrakeNull;
                    }
                }
                else
                {
                    sc = MessageColor.Orange;
                    if (TrainManager.PlayerTrain.LocoBrakeNotchDescriptions != null && TrainManager.PlayerTrain.Handles.LocoBrake.Driver < TrainManager.PlayerTrain.LocoBrakeNotchDescriptions.Length)
                    {
                        t = TrainManager.PlayerTrain.LocoBrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.LocoBrake.Driver];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleLocoBrake + TrainManager.PlayerTrain.Handles.LocoBrake.Driver.ToString(Culture);
                    }
                }
                Element.TransitionState = 0.0;
                break;

            case "single":
                if (!TrainManager.PlayerTrain.Handles.SingleHandle)
                {
                    return;
                }
                if (TrainManager.PlayerTrain.Handles.EmergencyBrake.Driver)
                {
                    sc = MessageColor.Red;
                    if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 0)
                    {
                        t = TrainManager.PlayerTrain.BrakeNotchDescriptions[0];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleEmergency;
                    }
                }
                else if (TrainManager.PlayerTrain.Handles.HoldBrake.Driver)
                {
                    sc = MessageColor.Green;
                    if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.BrakeNotchDescriptions.Length > 1)
                    {
                        t = TrainManager.PlayerTrain.BrakeNotchDescriptions[1];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleHoldBrake;
                    }
                }
                else if (TrainManager.PlayerTrain.Handles.Brake.Driver > 0)
                {
                    sc = MessageColor.Orange;
                    if (TrainManager.PlayerTrain.BrakeNotchDescriptions != null && TrainManager.PlayerTrain.Handles.Brake.Driver + 3 < TrainManager.PlayerTrain.BrakeNotchDescriptions.Length)
                    {
                        t = TrainManager.PlayerTrain.BrakeNotchDescriptions[TrainManager.PlayerTrain.Handles.Brake.Driver + 3];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandleBrake + TrainManager.PlayerTrain.Handles.Brake.Driver.ToString(Culture);
                    }
                }
                else if (TrainManager.PlayerTrain.Handles.Power.Driver > 0)
                {
                    sc = MessageColor.Blue;
                    if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.Handles.Power.Driver < TrainManager.PlayerTrain.PowerNotchDescriptions.Length)
                    {
                        t = TrainManager.PlayerTrain.PowerNotchDescriptions[TrainManager.PlayerTrain.Handles.Power.Driver];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandlePower + TrainManager.PlayerTrain.Handles.Power.Driver.ToString(Culture);
                    }
                }
                else
                {
                    sc = MessageColor.Gray;
                    if (TrainManager.PlayerTrain.PowerNotchDescriptions != null && TrainManager.PlayerTrain.PowerNotchDescriptions.Length > 0)
                    {
                        t = TrainManager.PlayerTrain.PowerNotchDescriptions[0];
                    }
                    else
                    {
                        t = Interface.QuickReferences.HandlePowerNull;
                    }
                }
                Element.TransitionState = 0.0;
                break;

            case "doorsleft":
            case "doorsright":
            {
                if ((LeftDoors & TrainManager.TrainDoorState.AllClosed) == 0 | (RightDoors & TrainManager.TrainDoorState.AllClosed) == 0)
                {
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else
                {
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                }
                TrainManager.TrainDoorState Doors = Command == "doorsleft" ? LeftDoors : RightDoors;
                if ((Doors & TrainManager.TrainDoorState.Mixed) != 0)
                {
                    sc = MessageColor.Orange;
                }
                else if ((Doors & TrainManager.TrainDoorState.AllClosed) != 0)
                {
                    sc = MessageColor.Gray;
                }
                else if (TrainManager.PlayerTrain.Specs.DoorCloseMode == TrainManager.DoorMode.Manual)
                {
                    sc = MessageColor.Green;
                }
                else
                {
                    sc = MessageColor.Blue;
                }
                t = Command == "doorsleft" ? Interface.QuickReferences.DoorsLeft : Interface.QuickReferences.DoorsRight;
            } break;

            case "stopleft":
            case "stopright":
            case "stopnone":
            {
                int s = TrainManager.PlayerTrain.Station;
                if (s >= 0 && Game.PlayerStopsAtStation(s) && Interface.CurrentOptions.GameMode != Interface.GameMode.Expert)
                {
                    bool cond;
                    if (Command == "stopleft")
                    {
                        cond = Game.Stations[s].OpenLeftDoors;
                    }
                    else if (Command == "stopright")
                    {
                        cond = Game.Stations[s].OpenRightDoors;
                    }
                    else
                    {
                        cond = !Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors;
                    }
                    if (TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Pending & cond)
                    {
                        Element.TransitionState -= speed * TimeElapsed;
                        if (Element.TransitionState < 0.0)
                        {
                            Element.TransitionState = 0.0;
                        }
                    }
                    else
                    {
                        Element.TransitionState += speed * TimeElapsed;
                        if (Element.TransitionState > 1.0)
                        {
                            Element.TransitionState = 1.0;
                        }
                    }
                }
                else
                {
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                }
                t = Element.Text;
            } break;

            case "stoplefttick":
            case "stoprighttick":
            case "stopnonetick":
            {
                int s = TrainManager.PlayerTrain.Station;
                if (s >= 0 && Game.PlayerStopsAtStation(s) && Interface.CurrentOptions.GameMode != Interface.GameMode.Expert)
                {
                    int c = Game.GetStopIndex(s, TrainManager.PlayerTrain.Cars.Length);
                    if (c >= 0)
                    {
                        bool cond;
                        if (Command == "stoplefttick")
                        {
                            cond = Game.Stations[s].OpenLeftDoors;
                        }
                        else if (Command == "stoprighttick")
                        {
                            cond = Game.Stations[s].OpenRightDoors;
                        }
                        else
                        {
                            cond = !Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors;
                        }
                        if (TrainManager.PlayerTrain.StationState == TrainManager.TrainStopState.Pending & cond)
                        {
                            Element.TransitionState -= speed * TimeElapsed;
                            if (Element.TransitionState < 0.0)
                            {
                                Element.TransitionState = 0.0;
                            }
                        }
                        else
                        {
                            Element.TransitionState += speed * TimeElapsed;
                            if (Element.TransitionState > 1.0)
                            {
                                Element.TransitionState = 1.0;
                            }
                        }
                        double d = TrainManager.PlayerTrain.StationDistanceToStopPoint;
                        double r;
                        if (d > 0.0)
                        {
                            r = d / Game.Stations[s].Stops[c].BackwardTolerance;
                        }
                        else
                        {
                            r = d / Game.Stations[s].Stops[c].ForwardTolerance;
                        }
                        if (r < -1.0)
                        {
                            r = -1.0;
                        }
                        if (r > 1.0)
                        {
                            r = 1.0;
                        }
                        y -= r * (double)Element.Value1;
                    }
                    else
                    {
                        Element.TransitionState += speed * TimeElapsed;
                        if (Element.TransitionState > 1.0)
                        {
                            Element.TransitionState = 1.0;
                        }
                    }
                }
                else
                {
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                }
                t = Element.Text;
            } break;

            case "clock":
            {
                int hours   = (int)Math.Floor(Game.SecondsSinceMidnight);
                int seconds = hours % 60; hours /= 60;
                int minutes = hours % 60; hours /= 60;
                hours %= 24;
                t      = hours.ToString(Culture).PadLeft(2, '0') + ":" + minutes.ToString(Culture).PadLeft(2, '0') + ":" + seconds.ToString(Culture).PadLeft(2, '0');
                if (OptionClock)
                {
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else
                {
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                }
            } break;

            case "gradient":
                if (OptionGradient == GradientDisplayMode.Percentage)
                {
                    if (World.CameraTrackFollower.Pitch != 0)
                    {
                        double pc = World.CameraTrackFollower.Pitch;
                        t = Math.Abs(pc).ToString("0.00", Culture) + "%" + (Math.Abs(pc) == pc ? " ↗" : " ↘");
                    }
                    else
                    {
                        t = "Level";
                    }
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else if (OptionGradient == GradientDisplayMode.UnitOfChange)
                {
                    if (World.CameraTrackFollower.Pitch != 0)
                    {
                        double gr = 1000 / World.CameraTrackFollower.Pitch;
                        t = "1 in " + Math.Abs(gr).ToString("0", Culture) + (Math.Abs(gr) == gr ? " ↗" : " ↘");
                    }
                    else
                    {
                        t = "Level";
                    }
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else
                {
                    if (World.CameraTrackFollower.Pitch != 0)
                    {
                        double gr = 1000 / World.CameraTrackFollower.Pitch;
                        t = "1 in " + Math.Abs(gr).ToString("0", Culture) + (Math.Abs(gr) == gr ? " ↗" : " ↘");
                    }
                    else
                    {
                        t = "Level";
                    }
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                } break;

            case "speed":
                if (OptionSpeed == SpeedDisplayMode.Kmph)
                {
                    double kmph = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) * 3.6;
                    t = kmph.ToString("0.00", Culture) + " km/h";
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else if (OptionSpeed == SpeedDisplayMode.Mph)
                {
                    double mph = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) * 2.2369362920544;
                    t = mph.ToString("0.00", Culture) + " mph";
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else
                {
                    double mph = Math.Abs(TrainManager.PlayerTrain.Specs.CurrentAverageSpeed) * 2.2369362920544;
                    t = mph.ToString("0.00", Culture) + " mph";
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                } break;

            case "fps":
                int fps = (int)Math.Round(Game.InfoFrameRate);
                t = fps.ToString(Culture) + " fps";
                if (OptionFrameRates)
                {
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else
                {
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                } break;

            case "ai":
                t = "A.I.";
                if (TrainManager.PlayerTrain.AI != null)
                {
                    Element.TransitionState -= speed * TimeElapsed;
                    if (Element.TransitionState < 0.0)
                    {
                        Element.TransitionState = 0.0;
                    }
                }
                else
                {
                    Element.TransitionState += speed * TimeElapsed;
                    if (Element.TransitionState > 1.0)
                    {
                        Element.TransitionState = 1.0;
                    }
                } break;

            case "score":
                if (Interface.CurrentOptions.GameMode == Interface.GameMode.Arcade)
                {
                    t = Game.CurrentScore.CurrentValue.ToString(Culture) + " / " + Game.CurrentScore.Maximum.ToString(Culture);
                    if (Game.CurrentScore.CurrentValue < 0)
                    {
                        sc = MessageColor.Red;
                    }
                    else if (Game.CurrentScore.CurrentValue > 0)
                    {
                        sc = MessageColor.Green;
                    }
                    else
                    {
                        sc = MessageColor.Gray;
                    }
                    Element.TransitionState = 0.0;
                }
                else
                {
                    Element.TransitionState = 1.0;
                    t = "";
                } break;

            default:
                t = Element.Text;
                break;
            }
            // transitions
            float alpha = 1.0f;

            if ((Element.Transition & Interface.HudTransition.Move) != 0)
            {
                double s = Element.TransitionState;
                x += Element.TransitionVector.X * s * s;
                y += Element.TransitionVector.Y * s * s;
            }
            if ((Element.Transition & Interface.HudTransition.Fade) != 0)
            {
                alpha = (float)(1.0 - Element.TransitionState);
            }
            else if (Element.Transition == Interface.HudTransition.None)
            {
                alpha = (float)(1.0 - Element.TransitionState);
            }
            // render
            if (alpha != 0.0f)
            {
                // background
                if (Element.Subject == "reverser")
                {
                    w = Math.Max(w, TrainManager.PlayerTrain.MaxReverserWidth);
                    //X-Pos doesn't need to be changed
                }
                if (Element.Subject == "power")
                {
                    w = Math.Max(w, TrainManager.PlayerTrain.MaxPowerNotchWidth);
                    if (TrainManager.PlayerTrain.MaxReverserWidth > 48)
                    {
                        x += (TrainManager.PlayerTrain.MaxReverserWidth - 48);
                    }
                }
                if (Element.Subject == "brake")
                {
                    w = Math.Max(w, TrainManager.PlayerTrain.MaxBrakeNotchWidth);
                    if (TrainManager.PlayerTrain.MaxReverserWidth > 48)
                    {
                        x += (TrainManager.PlayerTrain.MaxReverserWidth - 48);
                    }
                    if (TrainManager.PlayerTrain.MaxPowerNotchWidth > 48)
                    {
                        x += (TrainManager.PlayerTrain.MaxPowerNotchWidth - 48);
                    }
                }
                if (Element.Subject == "single")
                {
                    w = Math.Max(Math.Max(w, TrainManager.PlayerTrain.MaxPowerNotchWidth), TrainManager.PlayerTrain.MaxBrakeNotchWidth);
                    if (TrainManager.PlayerTrain.MaxReverserWidth > 48)
                    {
                        x += (TrainManager.PlayerTrain.MaxReverserWidth - 48);
                    }
                }
                if (Element.CenterMiddle.BackgroundTexture != null)
                {
                    if (Textures.LoadTexture(Element.CenterMiddle.BackgroundTexture, Textures.OpenGlTextureWrapMode.ClampClamp))
                    {
                        float r, g, b, a;
                        CreateBackColor(Element.BackgroundColor, sc, out r, out g, out b, out a);
                        GL.Color4(r, g, b, a * alpha);
                        RenderOverlayTexture(Element.CenterMiddle.BackgroundTexture, x, y, x + w, y + h);
                    }
                }
                {                 // text
                    System.Drawing.Size size = MeasureString(Element.Font, t);
                    float  u = size.Width;
                    float  v = size.Height;
                    double p = Math.Round(Element.TextAlignment.X < 0 ? x : Element.TextAlignment.X == 0 ? x + 0.5 * (w - u) : x + w - u);
                    double q = Math.Round(Element.TextAlignment.Y < 0 ? y : Element.TextAlignment.Y == 0 ? y + 0.5 * (h - v) : y + h - v);
                    p += Element.TextPosition.X;
                    q += Element.TextPosition.Y;
                    float r, g, b, a;
                    CreateTextColor(Element.TextColor, sc, out r, out g, out b, out a);
                    DrawString(Element.Font, t, new System.Drawing.Point((int)p, (int)q), TextAlignment.TopLeft, new Color128(r, g, b, a * alpha), Element.TextShadow);
                }
                // overlay
                if (Element.CenterMiddle.OverlayTexture != null)
                {
                    if (Textures.LoadTexture(Element.CenterMiddle.OverlayTexture, Textures.OpenGlTextureWrapMode.ClampClamp))
                    {
                        float r, g, b, a;
                        CreateBackColor(Element.OverlayColor, sc, out r, out g, out b, out a);
                        GL.Color4(r, g, b, a * alpha);
                        RenderOverlayTexture(Element.CenterMiddle.OverlayTexture, x, y, x + w, y + h);
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>This method is called once the route and train data have been preprocessed, in order to physically setup the simulation</summary>
        private void SetupSimulation()
        {
            if (Loading.Cancel)
            {
                Close();
            }
            Timetable.CreateTimetable();
            //Check if any critical errors have occured during the route or train loading
            for (int i = 0; i < Interface.MessageCount; i++)
            {
                if (Interface.Messages[i].Type == Interface.MessageType.Critical)
                {
                    MessageBox.Show("A critical error has occured:\n\n" + Interface.Messages[i].Text + "\n\nPlease inspect the error log file for further information.", "Load", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Close();
                }
            }
            Renderer.InitializeLighting();
            Game.LogRouteName = System.IO.Path.GetFileName(MainLoop.currentResult.RouteFile);
            Game.LogTrainName = System.IO.Path.GetFileName(MainLoop.currentResult.TrainFolder);
            Game.LogDateTime  = DateTime.Now;

            if (Interface.CurrentOptions.LoadInAdvance)
            {
                Textures.LoadAllTextures();
            }
            else
            {
                Textures.UnloadAllTextures();
            }
            // camera
            ObjectManager.InitializeVisibility();
            TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, 0.0, true, false);
            TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, -0.1, true, false);
            TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, 0.1, true, false);
            World.CameraTrackFollower.TriggerType = TrackManager.EventTriggerType.Camera;
            // starting time and track position
            Game.SecondsSinceMidnight = 0.0;
            Game.StartupTime          = 0.0;
            int    PlayerFirstStationIndex    = -1;
            double PlayerFirstStationPosition = 0.0;

            for (int i = 0; i < Game.Stations.Length; i++)
            {
                if (Game.Stations[i].StopMode == Game.StationStopMode.AllStop | Game.Stations[i].StopMode == Game.StationStopMode.PlayerStop & Game.Stations[i].Stops.Length != 0)
                {
                    PlayerFirstStationIndex = i;
                    int s = Game.GetStopIndex(i, TrainManager.PlayerTrain.Cars.Length);
                    if (s >= 0)
                    {
                        PlayerFirstStationPosition = Game.Stations[i].Stops[s].TrackPosition;

                        double TrainLength = 0.0;
                        for (int c = 0; c < TrainManager.Trains[TrainManager.PlayerTrain.TrainIndex].Cars.Length; c++)
                        {
                            TrainLength += TrainManager.Trains[TrainManager.PlayerTrain.TrainIndex].Cars[c].Length;
                        }

                        for (int j = 0; j < Game.BufferTrackPositions.Length; j++)
                        {
                            if (PlayerFirstStationPosition > Game.BufferTrackPositions[j] && PlayerFirstStationPosition - TrainLength < Game.BufferTrackPositions[j])
                            {
                                /*
                                 * HACK: The initial start position for the player train is stuck on a set of buffers
                                 * This means we have to make some one the fly adjustments to the first station stop position
                                 */

                                //Set the start position to be the buffer position plus the train length plus 1m
                                PlayerFirstStationPosition = Game.BufferTrackPositions[j] + TrainLength + 1;
                                //Update the station stop location
                                if (s >= 0)
                                {
                                    Game.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition = PlayerFirstStationPosition;
                                }
                                else
                                {
                                    Game.Stations[PlayerFirstStationIndex].DefaultTrackPosition = PlayerFirstStationPosition;
                                }
                                break;
                            }
                        }
                    }
                    else
                    {
                        PlayerFirstStationPosition = Game.Stations[i].DefaultTrackPosition;
                    }
                    if (Game.Stations[i].ArrivalTime < 0.0)
                    {
                        if (Game.Stations[i].DepartureTime < 0.0)
                        {
                            Game.SecondsSinceMidnight = 0.0;
                            Game.StartupTime          = 0.0;
                        }
                        else
                        {
                            Game.SecondsSinceMidnight = Game.Stations[i].DepartureTime - Game.Stations[i].StopTime;
                            Game.StartupTime          = Game.Stations[i].DepartureTime - Game.Stations[i].StopTime;
                        }
                    }
                    else
                    {
                        Game.SecondsSinceMidnight = Game.Stations[i].ArrivalTime;
                        Game.StartupTime          = Game.Stations[i].ArrivalTime;
                    }
                    break;
                }
            }
            int    OtherFirstStationIndex    = -1;
            double OtherFirstStationPosition = 0.0;
            double OtherFirstStationTime     = 0.0;

            for (int i = 0; i < Game.Stations.Length; i++)
            {
                if (Game.Stations[i].StopMode == Game.StationStopMode.AllStop | Game.Stations[i].StopMode == Game.StationStopMode.PlayerPass & Game.Stations[i].Stops.Length != 0)
                {
                    OtherFirstStationIndex = i;
                    int s = Game.GetStopIndex(i, TrainManager.PlayerTrain.Cars.Length);
                    if (s >= 0)
                    {
                        OtherFirstStationPosition = Game.Stations[i].Stops[s].TrackPosition;
                    }
                    else
                    {
                        OtherFirstStationPosition = Game.Stations[i].DefaultTrackPosition;
                    }
                    if (Game.Stations[i].ArrivalTime < 0.0)
                    {
                        if (Game.Stations[i].DepartureTime < 0.0)
                        {
                            OtherFirstStationTime = 0.0;
                        }
                        else
                        {
                            OtherFirstStationTime = Game.Stations[i].DepartureTime - Game.Stations[i].StopTime;
                        }
                    }
                    else
                    {
                        OtherFirstStationTime = Game.Stations[i].ArrivalTime;
                    }
                    break;
                }
            }
            if (Game.PrecedingTrainTimeDeltas.Length != 0)
            {
                OtherFirstStationTime -= Game.PrecedingTrainTimeDeltas[Game.PrecedingTrainTimeDeltas.Length - 1];
                if (OtherFirstStationTime < Game.SecondsSinceMidnight)
                {
                    Game.SecondsSinceMidnight = OtherFirstStationTime;
                }
            }
            // initialize trains
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                TrainManager.InitializeTrain(TrainManager.Trains[i]);
                int s = i == TrainManager.PlayerTrain.TrainIndex ? PlayerFirstStationIndex : OtherFirstStationIndex;
                if (s >= 0)
                {
                    if (Game.Stations[s].OpenLeftDoors)
                    {
                        for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                        {
                            TrainManager.Trains[i].Cars[j].Specs.AnticipatedLeftDoorsOpened = true;
                        }
                    }
                    if (Game.Stations[s].OpenRightDoors)
                    {
                        for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                        {
                            TrainManager.Trains[i].Cars[j].Specs.AnticipatedRightDoorsOpened = true;
                        }
                    }
                }
                if (Game.Sections.Length != 0)
                {
                    Game.Sections[0].Enter(TrainManager.Trains[i]);
                }
                for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                {
                    double length = TrainManager.Trains[i].Cars[0].Length;
                    TrainManager.MoveCar(TrainManager.Trains[i], j, -length, 0.01);
                    TrainManager.MoveCar(TrainManager.Trains[i], j, length, 0.01);
                }
            }
            // score
            Game.CurrentScore.ArrivalStation   = PlayerFirstStationIndex + 1;
            Game.CurrentScore.DepartureStation = PlayerFirstStationIndex;
            Game.CurrentScore.Maximum          = 0;
            for (int i = 0; i < Game.Stations.Length; i++)
            {
                if (i != PlayerFirstStationIndex & Game.PlayerStopsAtStation(i))
                {
                    if (i == 0 || Game.Stations[i - 1].StationType != Game.StationType.ChangeEnds)
                    {
                        Game.CurrentScore.Maximum += Game.ScoreValueStationArrival;
                    }
                }
            }
            if (Game.CurrentScore.Maximum <= 0)
            {
                Game.CurrentScore.Maximum = Game.ScoreValueStationArrival;
            }
            // signals
            if (Game.Sections.Length > 0)
            {
                Game.UpdateSection(Game.Sections.Length - 1);
            }
            // move train in position
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                double p;
                if (i == TrainManager.PlayerTrain.TrainIndex)
                {
                    p = PlayerFirstStationPosition;
                }
                else if (TrainManager.Trains[i].State == TrainManager.TrainState.Bogus)
                {
                    p = Game.BogusPretrainInstructions[0].TrackPosition;
                    TrainManager.Trains[i].AI = new Game.BogusPretrainAI(TrainManager.Trains[i]);
                }
                else
                {
                    p = OtherFirstStationPosition;
                }
                for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                {
                    TrainManager.MoveCar(TrainManager.Trains[i], j, p, 0.01);
                }
            }
            // timetable
            if (Timetable.DefaultTimetableDescription.Length == 0)
            {
                Timetable.DefaultTimetableDescription = Game.LogTrainName;
            }

            // initialize camera
            if (World.CameraRestriction == World.CameraRestrictionMode.NotAvailable)
            {
                World.CameraMode = World.CameraViewMode.InteriorLookAhead;
            }
            //Place the initial camera in the driver car
            TrainManager.UpdateCamera(TrainManager.PlayerTrain, TrainManager.PlayerTrain.DriverCar);
            TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, -1.0, true, false);
            ObjectManager.UpdateVisibility(World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z);
            World.CameraSavedInterior = new World.CameraAlignment();
            World.CameraSavedExterior = new World.CameraAlignment(new OpenBveApi.Math.Vector3(-2.5, 1.5, -15.0), 0.3, -0.2, 0.0, PlayerFirstStationPosition, 1.0);
            World.CameraSavedTrack    = new World.CameraAlignment(new OpenBveApi.Math.Vector3(-3.0, 2.5, 0.0), 0.3, 0.0, 0.0, TrainManager.PlayerTrain.Cars[0].FrontAxle.Follower.TrackPosition - 10.0, 1.0);
            // signalling sections
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                int s = TrainManager.Trains[i].CurrentSectionIndex;
                Game.Sections[s].Enter(TrainManager.Trains[i]);
            }
            if (Game.Sections.Length > 0)
            {
                Game.UpdateSection(Game.Sections.Length - 1);
            }
            // fast-forward until start time
            {
                Game.MinimalisticSimulation = true;
                const double w = 0.25;
                double       u = Game.StartupTime - Game.SecondsSinceMidnight;
                if (u > 0)
                {
                    while (true)
                    {
                        double v = u < w ? u : w; u -= v;
                        Game.SecondsSinceMidnight += v;
                        TrainManager.UpdateTrains(v);
                        if (u <= 0.0)
                        {
                            break;
                        }
                        TotalTimeElapsedForSectionUpdate += v;
                        if (TotalTimeElapsedForSectionUpdate >= 1.0)
                        {
                            if (Game.Sections.Length > 0)
                            {
                                Game.UpdateSection(Game.Sections.Length - 1);
                            }
                            TotalTimeElapsedForSectionUpdate = 0.0;
                        }
                    }
                }
                Game.MinimalisticSimulation = false;
            }
            // animated objects
            ObjectManager.UpdateAnimatedWorldObjects(0.0, true);
            TrainManager.UpdateTrainObjects(0.0, true);
            // timetable
            if (TrainManager.PlayerTrain.Station >= 0)
            {
                Timetable.UpdateCustomTimetable(Game.Stations[TrainManager.PlayerTrain.Station].TimetableDaytimeTexture, Game.Stations[TrainManager.PlayerTrain.Station].TimetableNighttimeTexture);
                if (Timetable.CustomObjectsUsed != 0 & Timetable.CustomTimetableAvailable && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.AutoGenerated && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.None)
                {
                    Timetable.CurrentTimetable = Timetable.TimetableState.Custom;
                }
            }

            // warnings / errors
            if (Interface.MessageCount != 0)
            {
                int filesNotFound = 0;
                int errors        = 0;
                int warnings      = 0;
                for (int i = 0; i < Interface.MessageCount; i++)
                {
                    if (Interface.Messages[i].FileNotFound)
                    {
                        filesNotFound++;
                    }
                    else if (Interface.Messages[i].Type == Interface.MessageType.Error)
                    {
                        errors++;
                    }
                    else if (Interface.Messages[i].Type == Interface.MessageType.Warning)
                    {
                        warnings++;
                    }
                }
                string NotFound = null;
                string Messages = null;
                if (filesNotFound != 0)
                {
                    NotFound = filesNotFound.ToString() + " file(s) not found";
                    Game.AddDebugMessage(NotFound, 10.0);
                }
                if (errors != 0 & warnings != 0)
                {
                    Messages = errors.ToString() + " error(s), " + warnings.ToString() + " warning(s)";
                    Game.AddDebugMessage(Messages, 10.0);
                }
                else if (errors != 0)
                {
                    Messages = errors.ToString() + " error(s)";
                    Game.AddDebugMessage(Messages, 10.0);
                }
                else
                {
                    Messages = warnings.ToString() + " warning(s)";
                    Game.AddDebugMessage(Messages, 10.0);
                }
                Game.RouteInformation.FilesNotFound     = NotFound;
                Game.RouteInformation.ErrorsAndWarnings = Messages;
                //Print the plugin error encountered (If any) for 10s
                //This must be done after the simulation has init, as otherwise the timeout doesn't work
                if (Loading.PluginError != null)
                {
                    Game.AddMessage(Loading.PluginError, Game.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Game.SecondsSinceMidnight + 5.0);
                    Game.AddMessage(Interface.GetInterfaceString("errors_plugin_failure2"), Game.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Game.SecondsSinceMidnight + 5.0);
                }
            }
            loadComplete          = true;
            RenderRealTimeElapsed = 0.0;
            RenderTimeElapsed     = 0.0;
            World.InitializeCameraRestriction();
        }
Beispiel #7
0
            /// <summary>Called every frame to update the plugin.</summary>
            internal void UpdatePlugin()
            {
                if (Train.Cars == null || Train.Cars.Length == 0)
                {
                    return;
                }

                /*
                 * Prepare the vehicle state.
                 * */
                double location = this.Train.Cars[0].FrontAxle.Follower.TrackPosition - this.Train.Cars[0].FrontAxle.Position + 0.5 * this.Train.Cars[0].Length;
                //Curve Radius, Cant and Pitch Added
                double CurrentRadius = this.Train.Cars[0].FrontAxle.Follower.CurveRadius;
                double CurrentCant   = this.Train.Cars[0].FrontAxle.Follower.CurveCant;
                double CurrentPitch  = this.Train.Cars[0].FrontAxle.Follower.Pitch;

                //If the list of stations has not been loaded, do so
                if (!StationsLoaded)
                {
                    currentRouteStations = new List <Station>();
                    int s = 0;
                    foreach (Game.Station selectedStation in Game.Stations)
                    {
                        double stopPosition = -1;
                        int    stopIdx      = Game.GetStopIndex(s, Train.Cars.Length);
                        if (selectedStation.Stops.Length != 0)
                        {
                            stopPosition = selectedStation.Stops[stopIdx].TrackPosition;
                        }
                        Station i = new Station(selectedStation, stopPosition);
                        currentRouteStations.Add(i);
                        s++;
                    }
                    StationsLoaded = true;
                }
                //End of additions
                double       speed       = this.Train.Cars[this.Train.DriverCar].Specs.CurrentPerceivedSpeed;
                double       bcPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.BrakeCylinderCurrentPressure;
                double       mrPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.MainReservoirCurrentPressure;
                double       erPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.EqualizingReservoirCurrentPressure;
                double       bpPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.BrakePipeCurrentPressure;
                double       sapPressure = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.StraightAirPipeCurrentPressure;
                VehicleState vehicle     = new VehicleState(location, new Speed(speed), bcPressure, mrPressure, erPressure, bpPressure, sapPressure, CurrentRadius, CurrentCant, CurrentPitch);

                /*
                 * Prepare the preceding vehicle state.
                 * */
                double bestLocation = double.MaxValue;
                double bestSpeed    = 0.0;
                PrecedingVehicleState precedingVehicle;

                try
                {
                    for (int i = 0; i < TrainManager.Trains.Length; i++)
                    {
                        if (TrainManager.Trains[i] != this.Train & TrainManager.Trains[i].State == TrainManager.TrainState.Available & Train.Cars.Length > 0)
                        {
                            int    c = TrainManager.Trains[i].Cars.Length - 1;
                            double z = TrainManager.Trains[i].Cars[c].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[c].RearAxle.Position - 0.5 * TrainManager.Trains[i].Cars[c].Length;
                            if (z >= location & z < bestLocation)
                            {
                                bestLocation = z;
                                bestSpeed    = TrainManager.Trains[i].Specs.CurrentAverageSpeed;
                            }
                        }
                    }
                    precedingVehicle = bestLocation != double.MaxValue ? new PrecedingVehicleState(bestLocation, bestLocation - location, new Speed(bestSpeed)) : null;
                }
                catch
                {
                    precedingVehicle = null;
                }

                /*
                 * Get the driver handles.
                 * */
                Handles handles = GetHandles();

                /*
                 * Update the plugin.
                 * */
                double totalTime   = Game.SecondsSinceMidnight;
                double elapsedTime = Game.SecondsSinceMidnight - LastTime;

                /*
                 * Set the current camera view mode
                 * Could probably do away with the CurrentCameraViewMode and use a direct cast??
                 *
                 */
                CurrentCameraViewMode = (CameraViewMode)World.CameraMode;
                ElapseData data = new ElapseData(vehicle, precedingVehicle, handles, (DoorInterlockStates)this.Train.Specs.DoorInterlockState, new Time(totalTime), new Time(elapsedTime), currentRouteStations, CurrentCameraViewMode, Interface.CurrentLanguageCode, this.Train.Destination);

                LastTime = Game.SecondsSinceMidnight;
                Elapse(data);
                this.PluginMessage = data.DebugMessage;
                this.Train.Specs.DoorInterlockState = (TrainManager.DoorInterlockStates)data.DoorInterlockState;
                DisableTimeAcceleration             = data.DisableTimeAcceleration;

                /*
                 * Set the virtual handles.
                 * */
                this.PluginValid = true;
                SetHandles(data.Handles, true);
                this.Train.Destination = data.Destination;
            }