Exemple #1
0
 public override void AddMessage(object Message)
 {
     MessageManager.AddMessage((AbstractMessage)Message);
 }
Exemple #2
0
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            TimeFactor = MainLoop.TimeFactor;
            // timer
            double RealTimeElapsed;
            double TimeElapsed;

            if (Program.CurrentRoute.SecondsSinceMidnight >= Game.StartupTime)
            {
                RealTimeElapsed = CPreciseTimer.GetElapsedTime();
                TimeElapsed     = RealTimeElapsed * (double)TimeFactor;
                if (loadComplete && !firstFrame)
                {
                    //Our current in-game time is equal to or greater than the startup time, but the first frame has not yet been processed
                    //Therefore, reset the timer to zero as time consuming texture loads may cause us to be late at the first station
                    RealTimeElapsed = 0.0;
                    TimeElapsed     = 0.0;
                    firstFrame      = true;
                }
            }
            else
            {
                RealTimeElapsed = 0.0;
                TimeElapsed     = Game.StartupTime - Program.CurrentRoute.SecondsSinceMidnight;
            }

            //We only want to update the simulation if we aren't in a menu
            if (Game.CurrentInterface == Game.InterfaceType.Normal)
            {
#if DEBUG
                //If we're in debug mode and a frame takes greater than a second to render, we can safely assume that VS has hit a breakpoint
                //Check this and the sim no longer barfs because the update time was too great
                if (RealTimeElapsed > 1)
                {
                    RealTimeElapsed = 0.0;
                    TimeElapsed     = 0.0;
                }
#endif
                TotalTimeElapsedForInfo          += RealTimeElapsed;
                TotalTimeElapsedForSectionUpdate += TimeElapsed;


                if (TotalTimeElapsedForSectionUpdate >= 1.0)
                {
                    if (Program.CurrentRoute.Sections.Length != 0)
                    {
                        Program.CurrentRoute.UpdateAllSections();
                    }
                    TotalTimeElapsedForSectionUpdate = 0.0;
                }

                // events

                // update simulation in chunks
                {
                    const double chunkTime = 1.0 / 2.0;
                    if (TimeElapsed <= chunkTime)
                    {
                        Program.CurrentRoute.SecondsSinceMidnight += TimeElapsed;
                        TrainManager.UpdateTrains(TimeElapsed);
                    }
                    else
                    {
                        const int maxChunks = 2;
                        int       chunks    = Math.Min((int)Math.Round(TimeElapsed / chunkTime), maxChunks);
                        double    time      = TimeElapsed / (double)chunks;
                        for (int i = 0; i < chunks; i++)
                        {
                            Program.CurrentRoute.SecondsSinceMidnight += time;
                            TrainManager.UpdateTrains(time);
                        }
                    }
                }
                Game.CurrentScore.Update(TimeElapsed);
                MessageManager.UpdateMessages();
                Game.UpdateScoreMessages(TimeElapsed);

                for (int i = 0; i < InputDevicePlugin.AvailablePluginInfos.Count; i++)
                {
                    if (InputDevicePlugin.AvailablePluginInfos[i].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable)
                    {
                        InputDevicePlugin.AvailablePlugins[i].OnUpdateFrame();
                    }
                }
            }
            RenderTimeElapsed     += TimeElapsed;
            RenderRealTimeElapsed += RealTimeElapsed;
        }
Exemple #3
0
            /// <summary>Updates the physics and controls for this train</summary>
            /// <param name="TimeElapsed">The time elapsed</param>
            private void UpdatePhysicsAndControls(double TimeElapsed)
            {
                if (TimeElapsed == 0.0 || TimeElapsed > 1000)
                {
                    //HACK: The physics engine really does not like update times above 1000ms
                    //This works around a bug experienced when jumping to a station on a steep hill
                    //causing exessive acceleration
                    return;
                }
                // move cars
                for (int i = 0; i < Cars.Length; i++)
                {
                    Cars[i].Move(Cars[i].CurrentSpeed * TimeElapsed);
                    if (State == TrainState.Disposed)
                    {
                        return;
                    }
                }
                // update station and doors
                UpdateStation(TimeElapsed);
                UpdateDoors(TimeElapsed);
                // delayed handles
                if (Plugin == null)
                {
                    Handles.Power.Safety          = Handles.Power.Driver;
                    Handles.Brake.Safety          = Handles.Brake.Driver;
                    Handles.EmergencyBrake.Safety = Handles.EmergencyBrake.Driver;
                }
                Handles.Power.Update();
                Handles.Brake.Update();
                Handles.Brake.Update();
                Handles.EmergencyBrake.Update();
                Handles.HoldBrake.Actual = Handles.HoldBrake.Driver;
                // update speeds
                UpdateSpeeds(TimeElapsed);
                // Update Run and Motor sounds
                for (int i = 0; i < Cars.Length; i++)
                {
                    Cars[i].UpdateRunSounds(TimeElapsed);
                    Cars[i].UpdateMotorSounds(TimeElapsed);
                }

                // safety system
                if (!Game.MinimalisticSimulation | !IsPlayerTrain)
                {
                    UpdateSafetySystem();
                }
                {
                    // breaker sound
                    bool breaker;
                    if (Cars[DriverCar].CarBrake is AutomaticAirBrake)
                    {
                        breaker = Handles.Reverser.Actual != 0 & Handles.Power.Safety >= 1 & Handles.Brake.Safety == (int)AirBrakeHandleState.Release & !Handles.EmergencyBrake.Safety & !Handles.HoldBrake.Actual;
                    }
                    else
                    {
                        breaker = Handles.Reverser.Actual != 0 & Handles.Power.Safety >= 1 & Handles.Brake.Safety == 0 & !Handles.EmergencyBrake.Safety & !Handles.HoldBrake.Actual;
                    }
                    Cars[DriverCar].Breaker.Update(breaker);
                }
                // passengers
                Passengers.Update(Specs.CurrentAverageAcceleration, TimeElapsed);
                // signals
                if (CurrentSectionLimit == 0.0)
                {
                    if (Handles.EmergencyBrake.Driver & CurrentSpeed > -0.03 & CurrentSpeed < 0.03)
                    {
                        CurrentSectionLimit = 6.94444444444444;
                        if (IsPlayerTrain)
                        {
                            string s = Translations.GetInterfaceString("message_signal_proceed");
                            double a = (3.6 * CurrentSectionLimit) * Interface.CurrentOptions.SpeedConversionFactor;
                            s = s.Replace("[speed]", a.ToString("0", CultureInfo.InvariantCulture));
                            s = s.Replace("[unit]", Game.UnitOfSpeed);
                            MessageManager.AddMessage(s, MessageDependency.None, GameMode.Normal, MessageColor.Red, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                        }
                    }
                }
                // infrequent updates
                InternalTimerTimeElapsed += TimeElapsed;
                if (InternalTimerTimeElapsed > 10.0)
                {
                    InternalTimerTimeElapsed -= 10.0;
                    Synchronize();
                }
            }
Exemple #4
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();
            }

            lock (BaseRenderer.GdiPlusLock)
            {
                Timetable.CreateTimetable();
            }
            //Check if any critical errors have occured during the route or train loading
            for (int i = 0; i < Interface.LogMessages.Count; i++)
            {
                if (Interface.LogMessages[i].Type == MessageType.Critical)
                {
                    MessageBox.Show("A critical error has occured:\n\n" + Interface.LogMessages[i].Text + "\n\nPlease inspect the error log file for further information.", "Load", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Close();
                }
            }
            Program.Renderer.Lighting.Initialize();
            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
            {
                Program.Renderer.TextureManager.UnloadAllTextures();
            }
            // camera
            Program.Renderer.InitializeVisibility();
            TrainManager.PlayerTrain.DriverBody = new DriverBody(TrainManager.PlayerTrain);
            Program.Renderer.CameraTrackFollower.UpdateAbsolute(0.0, true, false);
            Program.Renderer.CameraTrackFollower.UpdateAbsolute(-0.1, true, false);
            Program.Renderer.CameraTrackFollower.UpdateAbsolute(0.1, true, false);
            Program.Renderer.CameraTrackFollower.TriggerType = EventTriggerType.Camera;
            // starting time and track position
            Program.CurrentRoute.SecondsSinceMidnight = 0.0;
            Game.StartupTime = 0.0;
            int    PlayerFirstStationIndex = -1;
            double PlayerFirstStationPosition;
            int    os = -1;
            bool   f  = false;

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

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

                    for (int j = 0; j < Program.CurrentRoute.BufferTrackPositions.Length; j++)
                    {
                        if (PlayerFirstStationPosition > Program.CurrentRoute.BufferTrackPositions[j] && PlayerFirstStationPosition - TrainLength < Program.CurrentRoute.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 = Program.CurrentRoute.BufferTrackPositions[j] + TrainLength + 1;
                            //Update the station stop location
                            if (s >= 0)
                            {
                                Program.CurrentRoute.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition = PlayerFirstStationPosition;
                            }
                            else
                            {
                                Program.CurrentRoute.Stations[PlayerFirstStationIndex].DefaultTrackPosition = PlayerFirstStationPosition;
                            }
                            break;
                        }
                    }
                }
                else
                {
                    PlayerFirstStationPosition = Program.CurrentRoute.Stations[PlayerFirstStationIndex].DefaultTrackPosition;
                }
                if (Program.CurrentRoute.InitialStationTime != -1)
                {
                    Program.CurrentRoute.SecondsSinceMidnight = Program.CurrentRoute.InitialStationTime;
                    Game.StartupTime = Program.CurrentRoute.InitialStationTime;
                }
                else
                {
                    if (Program.CurrentRoute.Stations[PlayerFirstStationIndex].ArrivalTime < 0.0)
                    {
                        if (Program.CurrentRoute.Stations[PlayerFirstStationIndex].DepartureTime < 0.0)
                        {
                            Program.CurrentRoute.SecondsSinceMidnight = 0.0;
                            Game.StartupTime = 0.0;
                        }
                        else
                        {
                            Program.CurrentRoute.SecondsSinceMidnight = Program.CurrentRoute.Stations[PlayerFirstStationIndex].DepartureTime -
                                                                        Program.CurrentRoute.Stations[PlayerFirstStationIndex].StopTime;
                            Game.StartupTime = Program.CurrentRoute.Stations[PlayerFirstStationIndex].DepartureTime -
                                               Program.CurrentRoute.Stations[PlayerFirstStationIndex].StopTime;
                        }
                    }
                    else
                    {
                        Program.CurrentRoute.SecondsSinceMidnight = Program.CurrentRoute.Stations[PlayerFirstStationIndex].ArrivalTime;
                        Game.StartupTime = Program.CurrentRoute.Stations[PlayerFirstStationIndex].ArrivalTime;
                    }
                }
            }
            int    OtherFirstStationIndex    = -1;
            double OtherFirstStationPosition = 0.0;
            double OtherFirstStationTime     = 0.0;

            for (int i = 0; i < Program.CurrentRoute.Stations.Length; i++)
            {
                if (Program.CurrentRoute.Stations[i].StopMode == StationStopMode.AllStop | Program.CurrentRoute.Stations[i].StopMode == StationStopMode.PlayerPass & Program.CurrentRoute.Stations[i].Stops.Length != 0)
                {
                    OtherFirstStationIndex = i;
                    int s = Program.CurrentRoute.Stations[i].GetStopIndex(TrainManager.PlayerTrain.Cars.Length);
                    if (s >= 0)
                    {
                        OtherFirstStationPosition = Program.CurrentRoute.Stations[i].Stops[s].TrackPosition;
                    }
                    else
                    {
                        OtherFirstStationPosition = Program.CurrentRoute.Stations[i].DefaultTrackPosition;
                    }
                    if (Program.CurrentRoute.Stations[i].ArrivalTime < 0.0)
                    {
                        if (Program.CurrentRoute.Stations[i].DepartureTime < 0.0)
                        {
                            OtherFirstStationTime = 0.0;
                        }
                        else
                        {
                            OtherFirstStationTime = Program.CurrentRoute.Stations[i].DepartureTime - Program.CurrentRoute.Stations[i].StopTime;
                        }
                    }
                    else
                    {
                        OtherFirstStationTime = Program.CurrentRoute.Stations[i].ArrivalTime;
                    }
                    break;
                }
            }
            if (Program.CurrentRoute.PrecedingTrainTimeDeltas.Length != 0)
            {
                OtherFirstStationTime -= Program.CurrentRoute.PrecedingTrainTimeDeltas[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length - 1];
                if (OtherFirstStationTime < Program.CurrentRoute.SecondsSinceMidnight)
                {
                    Program.CurrentRoute.SecondsSinceMidnight = OtherFirstStationTime;
                }
            }
            // initialize trains
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                TrainManager.Trains[i].Initialize();
                int s = TrainManager.Trains[i].IsPlayerTrain ? PlayerFirstStationIndex : OtherFirstStationIndex;
                if (s >= 0)
                {
                    if (Program.CurrentRoute.Stations[s].OpenLeftDoors)
                    {
                        for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                        {
                            TrainManager.Trains[i].Cars[j].Doors[0].AnticipatedOpen = true;
                        }
                    }
                    if (Program.CurrentRoute.Stations[s].OpenRightDoors)
                    {
                        for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++)
                        {
                            TrainManager.Trains[i].Cars[j].Doors[1].AnticipatedOpen = true;
                        }
                    }
                }
                if (Program.CurrentRoute.Sections.Length != 0)
                {
                    Program.CurrentRoute.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);
                    TrainManager.Trains[i].Cars[j].Move(length);
                }
            }

            // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
            foreach (TrainManager.TrackFollowingObject Train in TrainManager.TFOs)              //Must not use var, as otherwise the wrong inferred type
            {
                Train.Initialize();

                foreach (var Car in Train.Cars)
                {
                    double length = Train.Cars[0].Length;
                    Car.Move(-length);
                    Car.Move(length);
                }
            }

            // score
            Game.CurrentScore.ArrivalStation   = PlayerFirstStationIndex + 1;
            Game.CurrentScore.DepartureStation = PlayerFirstStationIndex;
            Game.CurrentScore.Maximum          = 0;
            for (int i = 0; i < Program.CurrentRoute.Stations.Length; i++)
            {
                if (i != PlayerFirstStationIndex & Program.CurrentRoute.Stations[i].PlayerStops())
                {
                    if (i == 0 || Program.CurrentRoute.Stations[i - 1].Type != StationType.ChangeEnds && Program.CurrentRoute.Stations[i - 1].Type != StationType.Jump)
                    {
                        Game.CurrentScore.Maximum += Game.ScoreValueStationArrival;
                    }
                }
            }
            if (Game.CurrentScore.Maximum <= 0)
            {
                Game.CurrentScore.Maximum = Game.ScoreValueStationArrival;
            }
            // signals
            if (Program.CurrentRoute.Sections.Length > 0)
            {
                Program.CurrentRoute.UpdateAllSections();
            }
            // move train in position
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                double p;
                if (TrainManager.Trains[i].IsPlayerTrain)
                {
                    p = PlayerFirstStationPosition;
                }
                else if (TrainManager.Trains[i].State == TrainState.Bogus)
                {
                    p = Program.CurrentRoute.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);
                }
            }
            // timetable
            if (Program.CurrentRoute.Information.DefaultTimetableDescription.Length == 0)
            {
                Program.CurrentRoute.Information.DefaultTimetableDescription = Game.LogTrainName;
            }

            // initialize camera
            if (Program.Renderer.Camera.CurrentRestriction == CameraRestrictionMode.NotAvailable || Program.Renderer.Camera.CurrentRestriction == CameraRestrictionMode.Restricted3D)
            {
                Program.Renderer.Camera.CurrentMode = CameraViewMode.InteriorLookAhead;
            }
            //Place the initial camera in the driver car
            TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].UpdateCamera();
            Program.Renderer.CameraTrackFollower.UpdateAbsolute(-1.0, true, false);
            Program.Renderer.UpdateVisibility(Program.Renderer.CameraTrackFollower.TrackPosition + Program.Renderer.Camera.Alignment.Position.Z);
            Program.Renderer.Camera.SavedExterior = new CameraAlignment(new OpenBveApi.Math.Vector3(-2.5, 1.5, -15.0), 0.3, -0.2, 0.0, PlayerFirstStationPosition, 1.0);
            Program.Renderer.Camera.SavedTrack    = new CameraAlignment(new OpenBveApi.Math.Vector3(-3.0, 2.5, 0.0), 0.3, 0.0, 0.0, TrainManager.PlayerTrain.Cars[0].TrackPosition - 10.0, 1.0);
            // signalling sections
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                int s = TrainManager.Trains[i].CurrentSectionIndex;
                Program.CurrentRoute.Sections[s].Enter(TrainManager.Trains[i]);
            }
            if (Program.CurrentRoute.Sections.Length > 0)
            {
                Program.CurrentRoute.UpdateAllSections();
            }
            // fast-forward until start time
            {
                Game.MinimalisticSimulation = true;
                const double w = 0.25;
                double       u = Game.StartupTime - Program.CurrentRoute.SecondsSinceMidnight;
                if (u > 0)
                {
                    while (true)
                    {
                        double v = u < w ? u : w; u -= v;
                        Program.CurrentRoute.SecondsSinceMidnight += v;
                        TrainManager.UpdateTrains(v);
                        if (u <= 0.0)
                        {
                            break;
                        }
                        TotalTimeElapsedForSectionUpdate += v;
                        if (TotalTimeElapsedForSectionUpdate >= 1.0)
                        {
                            if (Program.CurrentRoute.Sections.Length > 0)
                            {
                                Program.CurrentRoute.UpdateAllSections();
                            }
                            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(Program.CurrentRoute.Stations[TrainManager.PlayerTrain.Station].TimetableDaytimeTexture, Program.CurrentRoute.Stations[TrainManager.PlayerTrain.Station].TimetableNighttimeTexture);
                if (Timetable.CustomObjectsUsed != 0 & Timetable.CustomTimetableAvailable && Interface.CurrentOptions.TimeTableStyle != TimeTableMode.AutoGenerated && Interface.CurrentOptions.TimeTableStyle != TimeTableMode.None)
                {
                    Program.Renderer.CurrentTimetable = DisplayedTimetable.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, Double.PositiveInfinity);
                if (TrainManager.PlayerTrain.Plugin != null && !TrainManager.PlayerTrain.Plugin.SupportsAI)
                {
                    MessageManager.AddMessage(Translations.GetInterfaceString("notification_aiunable"), MessageDependency.None, GameMode.Expert,
                                              OpenBveApi.Colors.MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                }
            }

            // warnings / errors
            if (Interface.LogMessages.Count != 0)
            {
                int filesNotFound = 0;
                int errors        = 0;
                int warnings      = 0;
                for (int i = 0; i < Interface.LogMessages.Count; i++)
                {
                    if (Interface.LogMessages[i].FileNotFound)
                    {
                        filesNotFound++;
                    }
                    else if (Interface.LogMessages[i].Type == MessageType.Error)
                    {
                        errors++;
                    }
                    else if (Interface.LogMessages[i].Type == MessageType.Warning)
                    {
                        warnings++;
                    }
                }
                string NotFound = null;
                string Messages;
                if (filesNotFound != 0)
                {
                    NotFound = filesNotFound.ToString() + " file(s) not found";
                    MessageManager.AddMessage(NotFound, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                }
                if (errors != 0 & warnings != 0)
                {
                    Messages = errors.ToString() + " error(s), " + warnings.ToString() + " warning(s)";
                    MessageManager.AddMessage(Messages, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                }
                else if (errors != 0)
                {
                    Messages = errors.ToString() + " error(s)";
                    MessageManager.AddMessage(Messages, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                }
                else
                {
                    Messages = warnings.ToString() + " warning(s)";
                    MessageManager.AddMessage(Messages, MessageDependency.None, GameMode.Expert, MessageColor.Magenta, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                }
                Program.CurrentRoute.Information.FilesNotFound     = NotFound;
                Program.CurrentRoute.Information.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)
                {
                    MessageManager.AddMessage(Loading.PluginError, MessageDependency.None, GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                    MessageManager.AddMessage(Translations.GetInterfaceString("errors_plugin_failure2"), MessageDependency.None, GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                }
            }
            loadComplete          = true;
            RenderRealTimeElapsed = 0.0;
            RenderTimeElapsed     = 0.0;
            World.InitializeCameraRestriction();
            Loading.SimulationSetup = true;
            switch (Interface.CurrentOptions.InitialViewpoint)
            {
            case 0:
                if (Game.InitialReversedConsist)
                {
                    /*
                     * HACK: The cab view has been created using the position of the initial driver car.
                     * Trigger a forced change to ensure that it is now correctly positioned in the consist
                     */
                    TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].ChangeCarSection(CarSectionType.Interior);
                }
                break;

            case 1:
                //Switch camera to exterior
                MainLoop.SaveCameraSettings();
                Program.Renderer.Camera.CurrentMode = CameraViewMode.Exterior;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(CarSectionType.Exterior);
                    //Make bogies visible
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0);
                }
                Program.Renderer.Camera.AlignmentDirection = new CameraAlignment();
                Program.Renderer.Camera.AlignmentSpeed     = new CameraAlignment();
                Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                break;

            case 2:
                //Switch camera to track
                MainLoop.SaveCameraSettings();
                Program.Renderer.Camera.CurrentMode = CameraViewMode.Track;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(CarSectionType.Exterior);
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0);
                }

                Program.Renderer.Camera.AlignmentDirection = new CameraAlignment();
                Program.Renderer.Camera.AlignmentSpeed     = new CameraAlignment();
                Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                break;

            case 3:
                //Switch camera to flyby
                MainLoop.SaveCameraSettings();
                Program.Renderer.Camera.CurrentMode = CameraViewMode.FlyBy;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(CarSectionType.Exterior);
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0);
                }

                Program.Renderer.Camera.AlignmentDirection = new CameraAlignment();
                Program.Renderer.Camera.AlignmentSpeed     = new CameraAlignment();
                Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                break;

            case 4:
                //Switch camera to flyby
                MainLoop.SaveCameraSettings();
                Program.Renderer.Camera.CurrentMode = CameraViewMode.FlyByZooming;
                MainLoop.RestoreCameraSettings();
                for (int j = 0; j < TrainManager.PlayerTrain.Cars.Length; j++)
                {
                    TrainManager.PlayerTrain.Cars[j].ChangeCarSection(CarSectionType.Exterior);
                    TrainManager.PlayerTrain.Cars[j].FrontBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].RearBogie.ChangeSection(0);
                    TrainManager.PlayerTrain.Cars[j].Coupler.ChangeSection(0);
                }

                Program.Renderer.Camera.AlignmentDirection = new CameraAlignment();
                Program.Renderer.Camera.AlignmentSpeed     = new CameraAlignment();
                Program.Renderer.UpdateViewport(ViewportChangeMode.NoChange);
                World.UpdateAbsoluteCamera(0.0);
                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                break;
            }
        }
Exemple #5
0
 /// <summary>May be called from a .Net plugin, in order to add a message to the in-game display</summary>
 /// <param name="Message">The message to display</param>
 /// <param name="Color">The color in which to display the message</param>
 /// <param name="Time">The time in seconds for which to display the message</param>
 internal void AddInterfaceMessage(string Message, MessageColor Color, double Time)
 {
     MessageManager.AddMessage(Message, MessageDependency.Plugin, GameMode.Expert, Color, Program.CurrentRoute.SecondsSinceMidnight + Time, null);
 }
Exemple #6
0
            /// <inheritdoc/>
            public override void Update(double TimeElapsed)
            {
                if (State == TrainState.Pending)
                {
                    // pending train
                    bool   forceIntroduction = !IsPlayerTrain && !Game.MinimalisticSimulation;
                    double time = 0.0;
                    if (!forceIntroduction)
                    {
                        for (int i = 0; i < Program.CurrentRoute.Stations.Length; i++)
                        {
                            if (Program.CurrentRoute.Stations[i].StopMode == StationStopMode.AllStop | Program.CurrentRoute.Stations[i].StopMode == StationStopMode.PlayerPass)
                            {
                                if (Program.CurrentRoute.Stations[i].ArrivalTime >= 0.0)
                                {
                                    time = Program.CurrentRoute.Stations[i].ArrivalTime;
                                }
                                else if (Program.CurrentRoute.Stations[i].DepartureTime >= 0.0)
                                {
                                    time = Program.CurrentRoute.Stations[i].DepartureTime - Program.CurrentRoute.Stations[i].StopTime;
                                }
                                break;
                            }
                        }
                        time -= TimetableDelta;
                    }
                    if (Program.CurrentRoute.SecondsSinceMidnight >= time | forceIntroduction)
                    {
                        bool introduce = true;
                        if (!forceIntroduction)
                        {
                            if (CurrentSectionIndex >= 0)
                            {
                                if (!Program.CurrentRoute.Sections[CurrentSectionIndex].IsFree())
                                {
                                    introduce = false;
                                }
                            }
                        }

                        if (this == PlayerTrain && Loading.SimulationSetup)
                        {
                            /* Loading has finished, but we still have an AI train in the current section
                             * This may be caused by an iffy RunInterval value, or simply by having no sections							 *
                             *
                             * We must introduce the player's train as otherwise the cab and loop sounds are missing
                             * NOTE: In this case, the signalling cannot prevent the player from colliding with
                             * the AI train
                             */

                            introduce = true;
                        }
                        if (introduce)
                        {
                            // train is introduced
                            State = TrainState.Available;
                            for (int j = 0; j < Cars.Length; j++)
                            {
                                if (Cars[j].CarSections.Length != 0)
                                {
                                    if (j == this.DriverCar && IsPlayerTrain && Interface.CurrentOptions.InitialViewpoint == 0)
                                    {
                                        this.Cars[j].ChangeCarSection(CarSectionType.Interior);
                                    }
                                    else
                                    {
                                        /*
                                         * HACK: Load in exterior mode first to ensure everything is cached
                                         * before switching immediately to not visible
                                         * https://github.com/leezer3/OpenBVE/issues/226
                                         * Stuff like the R142A really needs to downsize the textures supplied,
                                         * but we have no control over external factors....
                                         */
                                        this.Cars[j].ChangeCarSection(CarSectionType.Exterior);
                                        if (IsPlayerTrain && Interface.CurrentOptions.InitialViewpoint == 0)
                                        {
                                            this.Cars[j].ChangeCarSection(CarSectionType.NotVisible, true);
                                        }
                                    }
                                }
                                Cars[j].FrontBogie.ChangeSection(!IsPlayerTrain ? 0 : -1);
                                Cars[j].RearBogie.ChangeSection(!IsPlayerTrain ? 0 : -1);
                                Cars[j].Coupler.ChangeSection(!IsPlayerTrain ? 0 : -1);

                                if (Cars[j].Specs.IsMotorCar && Cars[j].Sounds.Loop != null)
                                {
                                    Cars[j].Sounds.Loop.Play(Cars[j], true);
                                }
                            }
                        }
                    }
                }
                else if (State == TrainState.Available)
                {
                    // available train
                    UpdatePhysicsAndControls(TimeElapsed);
                    if (CurrentSpeed > CurrentRouteLimit)
                    {
                        if (previousRouteLimit != CurrentRouteLimit || Interface.CurrentOptions.GameMode == GameMode.Arcade)
                        {
                            /*
                             * HACK: If the limit has changed, or we are in arcade mode, notify the player
                             *       This conforms to the original behaviour, but doesn't need to raise the message from the event.
                             */
                            MessageManager.AddMessage(Translations.GetInterfaceString("message_route_overspeed"), MessageDependency.RouteLimit, GameMode.Normal, MessageColor.Orange, Double.PositiveInfinity, null);
                        }
                    }
                    previousRouteLimit = CurrentRouteLimit;
                    if (Interface.CurrentOptions.GameMode == GameMode.Arcade)
                    {
                        if (CurrentSectionLimit == 0.0)
                        {
                            MessageManager.AddMessage(Translations.GetInterfaceString("message_signal_stop"), MessageDependency.PassedRedSignal, GameMode.Normal, MessageColor.Red, double.PositiveInfinity, null);
                        }
                        else if (CurrentSpeed > CurrentSectionLimit)
                        {
                            MessageManager.AddMessage(Translations.GetInterfaceString("message_signal_overspeed"), MessageDependency.SectionLimit, GameMode.Normal, MessageColor.Orange, Double.PositiveInfinity, null);
                        }
                    }
                    if (AI != null)
                    {
                        AI.Trigger(TimeElapsed);
                    }
                }
                else if (State == TrainState.Bogus)
                {
                    // bogus train
                    if (AI != null)
                    {
                        AI.Trigger(TimeElapsed);
                    }
                }
                //Trigger point sounds if appropriate
                for (int i = 0; i < Cars.Length; i++)
                {
                    CarSound c = null;
                    if (Cars[i].FrontAxle.PointSoundTriggered)
                    {
                        Cars[i].FrontAxle.PointSoundTriggered = false;
                        int bufferIndex = Cars[i].FrontAxle.RunIndex;
                        if (bufferIndex > Cars[i].FrontAxle.PointSounds.Length - 1)
                        {
                            //If the switch sound does not exist, return zero
                            //Required to handle legacy trains which don't have idx specific run sounds defined
                            bufferIndex = 0;
                        }
                        if (Cars[i].FrontAxle.PointSounds == null || Cars[i].FrontAxle.PointSounds.Length == 0)
                        {
                            //No point sounds defined at all
                            continue;
                        }
                        c = (CarSound)Cars[i].FrontAxle.PointSounds[bufferIndex];
                        if (c.Buffer == null)
                        {
                            c = (CarSound)Cars[i].FrontAxle.PointSounds[0];
                        }
                    }
                    if (c != null)
                    {
                        double spd   = Math.Abs(CurrentSpeed);
                        double pitch = spd / 12.5;
                        double gain  = pitch < 0.5 ? 2.0 * pitch : 1.0;
                        if (pitch > 0.2 && gain > 0.2)
                        {
                            c.Play(pitch, gain, Cars[i], false);
                        }
                    }
                }
            }
Exemple #7
0
 public override void AddMessage(string Message, object MessageDependancy, GameMode Mode, MessageColor MessageColor, double MessageTimeOut, string Key)
 {
     MessageManager.AddMessage(Message, (MessageDependency)MessageDependancy, Mode, MessageColor, MessageTimeOut, Key);
 }
Exemple #8
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 = Program.CurrentRoute.Stations[Train.Station].GetStopIndex(Train.NumberOfCars);
                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 = Program.CurrentRoute.Stations[i].Stops[n].TrackPosition;
                    tf = Program.CurrentRoute.Stations[i].Stops[n].ForwardTolerance;
                    tb = Program.CurrentRoute.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 (Program.CurrentRoute.Stations[i].StopsHere(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.CurrentSpeed) < 0.1 / 3.6 &
                                Math.Abs(Train.Specs.CurrentAverageAcceleration) < 0.1 / 3.6)
                            {
                                Train.AttemptToOpenDoors(i, tb, tf);
                            }
                        }
                        // detect arrival
                        if (Train.CurrentSpeed > -0.277777777777778 & Train.CurrentSpeed < 0.277777777777778)
                        {
                            bool left, right;
                            if (Program.CurrentRoute.Stations[i].OpenLeftDoors)
                            {
                                left = false;
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    if (Train.Cars[j].Doors[0].AnticipatedOpen)
                                    {
                                        left = true; break;
                                    }
                                }
                            }
                            else
                            {
                                left = true;
                            }
                            if (Program.CurrentRoute.Stations[i].OpenRightDoors)
                            {
                                right = false;
                                for (int j = 0; j < Train.Cars.Length; j++)
                                {
                                    if (Train.Cars[j].Doors[1].AnticipatedOpen)
                                    {
                                        right = true; break;
                                    }
                                }
                            }
                            else
                            {
                                right = true;
                            }
                            if (left & right)
                            {
                                // arrival
                                Train.StationState = TrainStopState.Boarding;
                                Train.SafetySystems.StationAdjust.Lit = false;
                                Train.Specs.DoorClosureAttempted      = false;
                                Train.SafetySystems.PassAlarm.Halt();
                                SoundBuffer buffer = (SoundBuffer)Program.CurrentRoute.Stations[i].ArrivalSoundBuffer;
                                if (buffer != null)
                                {
                                    OpenBveApi.Math.Vector3 pos = Program.CurrentRoute.Stations[i].SoundOrigin;
                                    Program.Sounds.PlaySound(buffer, 1.0, 1.0, pos, false);
                                }
                                Train.StationArrivalTime   = Program.CurrentRoute.SecondsSinceMidnight;
                                Train.StationDepartureTime = Program.CurrentRoute.Stations[i].DepartureTime - Train.TimetableDelta;
                                if (Train.StationDepartureTime - Program.CurrentRoute.SecondsSinceMidnight < Program.CurrentRoute.Stations[i].StopTime)
                                {
                                    Train.StationDepartureTime = Program.CurrentRoute.SecondsSinceMidnight + Program.CurrentRoute.Stations[i].StopTime;
                                }
                                Train.Passengers.PassengerRatio = Program.CurrentRoute.Stations[i].PassengerRatio;
                                UpdateTrainMassFromPassengerRatio(Train);
                                if (Train.IsPlayerTrain)
                                {
                                    double early = 0.0;
                                    if (Program.CurrentRoute.Stations[i].ArrivalTime >= 0.0)
                                    {
                                        early = (Program.CurrentRoute.Stations[i].ArrivalTime - Train.TimetableDelta) - Train.StationArrivalTime;
                                    }
                                    string s;
                                    if (early < -1.0)
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival_late");
                                    }
                                    else if (early > 1.0)
                                    {
                                        s = Translations.GetInterfaceString("message_station_arrival_early");
                                    }
                                    else
                                    {
                                        s = Translations.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 += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_overrun");
                                    }
                                    else if (Train.StationDistanceToStopPoint > 0.1)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_underrun");
                                    }
                                    double d = Math.Abs(Train.StationDistanceToStopPoint);
                                    string c = d.ToString("0.0", Culture);
                                    if (Program.CurrentRoute.Stations[i].Type == StationType.Terminal)
                                    {
                                        s += Translations.GetInterfaceString("message_delimiter") + Translations.GetInterfaceString("message_station_terminal");
                                    }
                                    s = s.Replace("[name]", Program.CurrentRoute.Stations[i].Name);
                                    s = s.Replace("[time]", b);
                                    s = s.Replace("[difference]", c);
                                    MessageManager.AddMessage(s, MessageDependency.StationArrival, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                                    if (Program.CurrentRoute.Stations[i].Type == StationType.Normal)
                                    {
                                        s = Translations.GetInterfaceString("message_station_deadline");
                                        MessageManager.AddMessage(s, MessageDependency.StationDeparture, GameMode.Normal, MessageColor.White, double.PositiveInfinity, null);
                                    }
                                    Timetable.UpdateCustomTimetable(Program.CurrentRoute.Stations[i].TimetableDaytimeTexture, Program.CurrentRoute.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].Doors.Length; k++)
                                    {
                                        Train.Cars[j].Doors[k].DoorLockDuration = 0.0;
                                        if (Program.CurrentRoute.Stations[i].OpenLeftDoors & Train.Cars[j].Doors[k].Direction == -1 | Program.CurrentRoute.Stations[i].OpenRightDoors & Train.Cars[j].Doors[k].Direction == 1)
                                        {
                                            double p = 0.005 * Program.CurrentRoute.Stations[i].PassengerRatio * Program.CurrentRoute.Stations[i].PassengerRatio * Program.CurrentRoute.Stations[i].PassengerRatio * Program.CurrentRoute.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].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].Doors[k].DoorLockDuration = (50.0 - 10.0 * p) / (17.0 - 16.0 * p);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (Train.SafetySystems.StationAdjust != null)
                                {
                                    Train.SafetySystems.StationAdjust.Update(tb, tf);
                                }
                            }
                        }
                    }
                }
                else if (Train.StationState == TrainStopState.Boarding)
                {
                    for (int j = 0; j < Train.Cars.Length; j++)
                    {
                        if (Train.Cars[j].GetDoorsState(Program.CurrentRoute.Stations[i].OpenLeftDoors, Program.CurrentRoute.Stations[i].OpenRightDoors) == (TrainDoorState.Opened | TrainDoorState.AllOpened))
                        {
                            //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.DoorCloseMode != DoorMode.Manual & Program.CurrentRoute.Stations[i].Type == StationType.Normal)
                            {
                                Train.AttemptToCloseDoors();

                                if (Train.Specs.DoorClosureAttempted)
                                {
                                    if (Program.CurrentRoute.Stations[i].OpenLeftDoors && !Train.Cars[j].Doors[0].AnticipatedReopen && Program.RandomNumberGenerator.NextDouble() < Program.CurrentRoute.Stations[i].ReopenDoor)
                                    {
                                        Train.Cars[j].Doors[0].ReopenLimit           = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].ReopenStationLimit);
                                        Train.Cars[j].Doors[0].ReopenCounter         = 0;
                                        Train.Cars[j].Doors[0].InterferingObjectRate = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].MaxInterferingObjectRate) * 0.01;
                                        if (Train.Cars[j].Doors[0].InterferingObjectRate * Train.Cars[j].Doors[0].Width >= Train.Cars[j].Doors[0].MaxTolerance)
                                        {
                                            Train.Cars[j].Doors[0].AnticipatedReopen = true;
                                        }
                                    }
                                    if (Program.CurrentRoute.Stations[i].OpenRightDoors && !Train.Cars[j].Doors[1].AnticipatedReopen && Program.RandomNumberGenerator.NextDouble() < Program.CurrentRoute.Stations[i].ReopenDoor)
                                    {
                                        Train.Cars[j].Doors[1].ReopenLimit           = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].ReopenStationLimit);
                                        Train.Cars[j].Doors[1].ReopenCounter         = 0;
                                        Train.Cars[j].Doors[1].InterferingObjectRate = Program.RandomNumberGenerator.Next(1, Program.CurrentRoute.Stations[i].MaxInterferingObjectRate) * 0.01;
                                        if (Train.Cars[j].Doors[1].InterferingObjectRate * Train.Cars[j].Doors[1].Width >= Train.Cars[j].Doors[1].MaxTolerance)
                                        {
                                            Train.Cars[j].Doors[1].AnticipatedReopen = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    // detect departure
                    bool left, right;
                    if (!Program.CurrentRoute.Stations[i].OpenLeftDoors & !Program.CurrentRoute.Stations[i].OpenRightDoors)
                    {
                        left  = true;
                        right = true;
                    }
                    else
                    {
                        if (Program.CurrentRoute.Stations[i].OpenLeftDoors)
                        {
                            left = false;
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                for (int k = 0; k < Train.Cars[j].Doors.Length; k++)
                                {
                                    if (Train.Cars[j].Doors[k].State != 0.0)
                                    {
                                        left = true; break;
                                    }
                                }
                                if (left)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            left = false;
                        }
                        if (Program.CurrentRoute.Stations[i].OpenRightDoors)
                        {
                            right = false;
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                for (int k = 0; k < Train.Cars[j].Doors.Length; k++)
                                {
                                    if (Train.Cars[j].Doors[k].State != 0.0)
                                    {
                                        right = true; break;
                                    }
                                }
                                if (right)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            right = false;
                        }
                    }
                    // departure sound
                    if (!Train.StationDepartureSoundPlayed)
                    {
                        SoundBuffer buffer = (SoundBuffer)Program.CurrentRoute.Stations[i].DepartureSoundBuffer;
                        if (buffer != null)
                        {
                            double dur = Program.Sounds.GetDuration(buffer);
                            if (Program.CurrentRoute.SecondsSinceMidnight >= Train.StationDepartureTime - dur)
                            {
                                if (!Game.MinimalisticSimulation)
                                {
                                    Program.Sounds.PlaySound(buffer, 1.0, 1.0, Program.CurrentRoute.Stations[i].SoundOrigin, false);
                                }
                                Train.StationDepartureSoundPlayed = true;
                            }
                        }
                    }
                    for (int j = 0; j < Train.Cars.Length; j++)
                    {
                        if (Train.Cars[j].Doors[0].AnticipatedReopen && Train.Cars[j].Doors[0].State == Train.Cars[j].Doors[0].InterferingObjectRate)
                        {
                            if (Train.Cars[j].Doors[0].NextReopenTime == 0.0)
                            {
                                Train.Cars[j].Doors[0].NextReopenTime = Program.CurrentRoute.SecondsSinceMidnight + Program.CurrentRoute.Stations[i].InterferenceInDoor;
                            }
                            else if (Train.Cars[j].Doors[0].ReopenCounter < Train.Cars[j].Doors[0].ReopenLimit)
                            {
                                if (Program.CurrentRoute.SecondsSinceMidnight >= Train.Cars[j].Doors[0].NextReopenTime)
                                {
                                    Train.Cars[j].OpenDoors(true, false);
                                }
                            }
                            else
                            {
                                Train.Cars[j].Doors[0].AnticipatedReopen = false;
                            }
                        }
                        if (Train.Cars[j].Doors[1].AnticipatedReopen && Train.Cars[j].Doors[1].State == Train.Cars[j].Doors[1].InterferingObjectRate)
                        {
                            if (Train.Cars[j].Doors[1].NextReopenTime == 0.0)
                            {
                                Train.Cars[j].Doors[1].NextReopenTime = Program.CurrentRoute.SecondsSinceMidnight + Program.CurrentRoute.Stations[i].InterferenceInDoor;
                            }
                            else if (Train.Cars[j].Doors[1].ReopenCounter < Train.Cars[j].Doors[1].ReopenLimit)
                            {
                                if (Program.CurrentRoute.SecondsSinceMidnight >= Train.Cars[j].Doors[1].NextReopenTime)
                                {
                                    Train.Cars[j].OpenDoors(false, true);
                                }
                            }
                            else
                            {
                                Train.Cars[j].Doors[1].AnticipatedReopen = false;
                            }
                        }
                    }
                    TrainDoorState doorState = Train.GetDoorsState(Program.CurrentRoute.Stations[i].OpenLeftDoors, Program.CurrentRoute.Stations[i].OpenRightDoors);
                    if (left | right)
                    {
                        /*
                         * Assume that passengers only board at a scheduled stop
                         * If the player has opened the doors somewhere else (lineside?)
                         * then passengers should not be boarding
                         */
                        if (doorState != TrainDoorState.AllClosed && Interface.CurrentOptions.LoadingSway)
                        {
                            // passengers boarding
                            for (int j = 0; j < Train.Cars.Length; j++)
                            {
                                if (!Train.Cars[j].EnableLoadingSway)
                                {
                                    continue;
                                }
                                double r = 2.0 * Program.CurrentRoute.Stations[i].PassengerRatio * TimeElapsed;
                                if (r >= Program.RandomNumberGenerator.NextDouble())
                                {
                                    int d =
                                        (int)Math.Floor(Program.RandomNumberGenerator.NextDouble() * (double)Train.Cars[j].Doors.Length);
                                    if (Train.Cars[j].Doors[d].State == 1.0)
                                    {
                                        Train.Cars[j].Specs.CurrentRollShakeDirection += (double)Train.Cars[j].Doors[d].Direction;
                                    }
                                }
                            }
                        }
                    }
                    if (Train.Specs.DoorCloseMode == DoorMode.Manual || doorState == TrainDoorState.None || doorState == (TrainDoorState.Closed | TrainDoorState.AllClosed) || (Program.CurrentRoute.Stations[Train.Station].Type == StationType.ChangeEnds || Program.CurrentRoute.Stations[Train.Station].Type == StationType.Jump))
                    {
                        if (left | right)
                        {
                            // departure message
                            if (Program.CurrentRoute.SecondsSinceMidnight > Train.StationDepartureTime && (Program.CurrentRoute.Stations[i].Type != StationType.Terminal || Train != PlayerTrain))
                            {
                                Train.StationState = TrainStopState.Completed;
                                switch (Program.CurrentRoute.Stations[i].Type)
                                {
                                case StationType.Normal:
                                    if (!Train.IsPlayerTrain)
                                    {
                                        break;                                                 // Only trigger messages for the player train
                                    }
                                    if (!Program.CurrentRoute.Stations[i].OpenLeftDoors & !Program.CurrentRoute.Stations[i].OpenRightDoors | Train.Specs.DoorCloseMode != DoorMode.Manual)
                                    {
                                        MessageManager.AddMessage(Translations.GetInterfaceString("message_station_depart"), MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                                    }
                                    else
                                    {
                                        MessageManager.AddMessage(Translations.GetInterfaceString("message_station_depart_closedoors"), MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                                    }
                                    break;

                                case StationType.ChangeEnds:
                                    // Change ends always jumps to the NEXT station
                                    JumpTrain(Train, i + 1);
                                    break;

                                case StationType.Jump:
                                    // Jumps to an arbritrary station as defined in the routefile
                                    JumpTrain(Train, Program.CurrentRoute.Stations[i].JumpIndex);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            Train.StationState = TrainStopState.Completed;
                            if (Train.IsPlayerTrain & Program.CurrentRoute.Stations[i].Type == StationType.Normal)
                            {
                                MessageManager.AddMessage(Translations.GetInterfaceString("message_station_depart"), MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 5.0, null);
                            }
                        }
                    }
                }
            }
            else
            {
                if (Train.StationState != TrainStopState.Jumping)
                {
                    Train.StationState = TrainStopState.Pending;
                }
            }
            // automatically close doors
            if (Train.Specs.DoorCloseMode != DoorMode.Manual & !Train.Specs.DoorClosureAttempted)
            {
                if (Train.Station == -1 | Train.StationState == TrainStopState.Completed)
                {
                    if ((Train.GetDoorsState(true, true) & TrainDoorState.AllClosed) == 0)
                    {
                        Train.CloseDoors(true, true);
                        Train.Specs.DoorClosureAttempted = true;
                    }
                }
            }
        }
Exemple #9
0
            /// <inheritdoc/>
            public override void RequestStop(RequestStop stopRequest)
            {
                if (stopRequest.MaxCars != 0 && NumberOfCars > stopRequest.MaxCars)
                {
                    //Check whether our train length is valid for this before doing anything else
                    Cars[DriverCar].Sounds.RequestStop[2].Play(Cars[DriverCar], false);
                    return;
                }
                if (Program.RandomNumberGenerator.Next(0, 100) <= stopRequest.Probability)
                {
                    //We have hit our probability roll
                    if (Program.CurrentRoute.Stations[stopRequest.StationIndex].StopMode == StationStopMode.AllRequestStop || (IsPlayerTrain && Program.CurrentRoute.Stations[stopRequest.StationIndex].StopMode == StationStopMode.PlayerRequestStop))
                    {
                        //If our train can stop at this station, set it's index accordingly
                        Station         = stopRequest.StationIndex;
                        NextStopSkipped = StopSkipMode.None;
                        //Play sound
                        Cars[DriverCar].Sounds.RequestStop[0].Play(Cars[DriverCar], false);
                    }
                    else
                    {
                        //We don't meet the conditions for this request stop
                        if (stopRequest.FullSpeed)
                        {
                            //Pass at linespeed, rather than braking as if for stop
                            NextStopSkipped = StopSkipMode.Linespeed;
                        }
                        else
                        {
                            NextStopSkipped = StopSkipMode.Decelerate;
                        }

                        //Play sound
                        Cars[DriverCar].Sounds.RequestStop[1].Play(Cars[DriverCar], false);
                        //If message is not empty, add it
                        if (!string.IsNullOrEmpty(stopRequest.PassMessage) && IsPlayerTrain)
                        {
                            MessageManager.AddMessage(stopRequest.PassMessage, MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                        }

                        return;
                    }

                    //Play sound
                    Cars[DriverCar].Sounds.RequestStop[0].Play(Cars[DriverCar], false);
                    //If message is not empty, add it
                    if (!string.IsNullOrEmpty(stopRequest.StopMessage) && IsPlayerTrain)
                    {
                        MessageManager.AddMessage(stopRequest.StopMessage, MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                    }
                }
                else
                {
                    Cars[DriverCar].Sounds.RequestStop[1].Play(Cars[DriverCar], false);
                    if (stopRequest.FullSpeed)
                    {
                        //Pass at linespeed, rather than braking as if for stop
                        NextStopSkipped = StopSkipMode.Linespeed;
                    }
                    else
                    {
                        NextStopSkipped = StopSkipMode.Decelerate;
                    }

                    //Play sound
                    Cars[DriverCar].Sounds.RequestStop[1].Play(Cars[DriverCar], false);
                    //If message is not empty, add it
                    if (!string.IsNullOrEmpty(stopRequest.PassMessage) && IsPlayerTrain)
                    {
                        MessageManager.AddMessage(stopRequest.PassMessage, MessageDependency.None, GameMode.Normal, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null);
                    }
                }
            }
Exemple #10
0
        /// <summary>Moves the camera to a point of interest</summary>
        /// <param name="Value">The value of the jump to perform:
        /// -1= Previous POI
        ///  0= Return to currently selected POI (From cab etc.)
        ///  1= Next POI</param>
        /// <param name="Relative">Whether the relative camera position should be retained</param>
        /// <returns>False if the previous / next POI would be outside those defined, true otherwise</returns>
        internal static bool ApplyPointOfInterest(int Value, bool Relative)
        {
            double t = 0.0;
            int    j = -1;

            if (Relative)
            {
                // relative
                if (Value < 0)
                {
                    // previous poi
                    t = double.NegativeInfinity;
                    for (int i = 0; i < Program.CurrentRoute.PointsOfInterest.Length; i++)
                    {
                        if (Program.CurrentRoute.PointsOfInterest[i].TrackPosition < Program.Renderer.CameraTrackFollower.TrackPosition)
                        {
                            if (Program.CurrentRoute.PointsOfInterest[i].TrackPosition > t)
                            {
                                t = Program.CurrentRoute.PointsOfInterest[i].TrackPosition;
                                j = i;
                            }
                        }
                    }
                }
                else if (Value > 0)
                {
                    // next poi
                    t = double.PositiveInfinity;
                    for (int i = 0; i < Program.CurrentRoute.PointsOfInterest.Length; i++)
                    {
                        if (Program.CurrentRoute.PointsOfInterest[i].TrackPosition > Program.Renderer.CameraTrackFollower.TrackPosition)
                        {
                            if (Program.CurrentRoute.PointsOfInterest[i].TrackPosition < t)
                            {
                                t = Program.CurrentRoute.PointsOfInterest[i].TrackPosition;
                                j = i;
                            }
                        }
                    }
                }
            }
            else
            {
                // absolute
                j = Value >= 0 & Value < Program.CurrentRoute.PointsOfInterest.Length ? Value : -1;
            }
            // process poi
            if (j < 0)
            {
                return(false);
            }
            Program.Renderer.CameraTrackFollower.UpdateAbsolute(t, true, false);
            Program.Renderer.Camera.Alignment.Position      = Program.CurrentRoute.PointsOfInterest[j].TrackOffset;
            Program.Renderer.Camera.Alignment.Yaw           = Program.CurrentRoute.PointsOfInterest[j].TrackYaw;
            Program.Renderer.Camera.Alignment.Pitch         = Program.CurrentRoute.PointsOfInterest[j].TrackPitch;
            Program.Renderer.Camera.Alignment.Roll          = Program.CurrentRoute.PointsOfInterest[j].TrackRoll;
            Program.Renderer.Camera.Alignment.TrackPosition = t;
            World.UpdateAbsoluteCamera(0.0);
            if (Program.CurrentRoute.PointsOfInterest[j].Text != null)
            {
                double n = 3.0 + 0.5 * Math.Sqrt((double)Program.CurrentRoute.PointsOfInterest[j].Text.Length);
                MessageManager.AddMessage(Program.CurrentRoute.PointsOfInterest[j].Text, MessageDependency.PointOfInterest, GameMode.Expert, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + n, null);
            }
            return(true);
        }
Exemple #11
0
 /// <summary>Called once a frame to update the messages displayed on-screen</summary>
 internal static void UpdateMessages()
 {
     MessageManager.UpdateMessages();
 }