示例#1
0
        /// <summary>Called when the train passes a beacon.</summary>
        /// <param name="type">The beacon type.</param>
        /// <param name="sectionIndex">The section the beacon is attached to, or -1 for the next red signal.</param>
        /// <param name="optional">Optional data attached to the beacon.</param>
        public void UpdateBeacon(int type, int sectionIndex, int optional)
        {
            if (type == 21 && Train.IsPlayerTrain && Train.Cars[Train.DriverCar].Windscreen != null)
            {
                //Legacy rain beacon, so let's pass to the windscreen as well as the plugin
                Train.Cars[Train.DriverCar].Windscreen.SetRainIntensity(optional);
            }

            SignalData signal;

            if (sectionIndex == -1)
            {
                sectionIndex = this.Train.CurrentSectionIndex + 1;
                while (sectionIndex < TrainManagerBase.CurrentRoute.Sections.Length)
                {
                    signal = TrainManagerBase.CurrentRoute.Sections[sectionIndex].GetPluginSignal(this.Train);
                    if (signal.Aspect == 0)
                    {
                        break;
                    }
                    sectionIndex++;
                }

                if (sectionIndex >= TrainManagerBase.CurrentRoute.Sections.Length)
                {
                    signal = new SignalData(-1, double.MaxValue);
                }
            }

            if (sectionIndex >= 0)
            {
                signal = sectionIndex < TrainManagerBase.CurrentRoute.Sections.Length ? TrainManagerBase.CurrentRoute.Sections[sectionIndex].GetPluginSignal(this.Train) : new SignalData(0, double.MaxValue);
            }
            else
            {
                signal = new SignalData(-1, double.MaxValue);
            }
            SetBeacon(new BeaconData(type, optional, signal));
            for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++)
            {
                if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
                {
                    ITrainInputDevice trainInputDevice = (ITrainInputDevice)InputDevicePlugin.AvailablePlugins[j];
                    trainInputDevice.SetBeacon(new BeaconData(type, optional, signal));
                }
            }
        }
示例#2
0
        /// <summary>Called to update the aspects of the section. This invokes a call to SetSignal only if a change in aspect occured or when changing section boundaries.</summary>
        /// <param name="data">The sections to submit to the plugin.</param>
        public void UpdateSignals(SignalData[] data)
        {
            if (data.Length != 0)
            {
                bool update;
                if (this.Train.CurrentSectionIndex != this.LastSection)
                {
                    update = true;
                }
                else if (data.Length != this.LastAspects.Length)
                {
                    update = true;
                }
                else
                {
                    update = false;
                    for (int i = 0; i < data.Length; i++)
                    {
                        if (data[i].Aspect != this.LastAspects[i])
                        {
                            update = true;
                            break;
                        }
                    }
                }

                if (update)
                {
                    SetSignal(data);
                    this.LastAspects = new int[data.Length];
                    for (int i = 0; i < data.Length; i++)
                    {
                        this.LastAspects[i] = data[i].Aspect;
                    }
                    for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++)
                    {
                        if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
                        {
                            ITrainInputDevice trainInputDevice = (ITrainInputDevice)InputDevicePlugin.AvailablePlugins[j];
                            trainInputDevice.SetSignal(data);
                        }
                    }
                }
            }
        }
示例#3
0
        private static void LoadEverythingThreaded()
        {
            string RailwayFolder = GetRailwayFolder(CurrentRouteFile);
            string ObjectFolder  = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Object");
            string SoundFolder   = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Sound");

            Game.Reset(true);
            Game.MinimalisticSimulation = true;
            // screen
            Program.Renderer.Camera.CurrentMode = CameraViewMode.Interior;

            bool loaded = false;

            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Route loading plugins available.");
            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableObjectPluginCount + " Object loading plugins available.");
            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Sound loading plugins available.");
            for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
            {
                if (Program.CurrentHost.Plugins[i].Route != null && Program.CurrentHost.Plugins[i].Route.CanLoadRoute(CurrentRouteFile))
                {
                    object Route = (object)Program.CurrentRoute;                     //must cast to allow us to use the ref keyword.
                    if (Program.CurrentHost.Plugins[i].Route.LoadRoute(CurrentRouteFile, CurrentRouteEncoding, CurrentTrainFolder, ObjectFolder, SoundFolder, false, ref Route))
                    {
                        Program.CurrentRoute = (CurrentRoute)Route;
                        Program.CurrentRoute.UpdateLighting();

                        loaded = true;
                        break;
                    }
                    var currentError = Translations.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", System.IO.Path.GetFileName(CurrentRouteFile));
                    MessageBox.Show(currentError, @"OpenBVE", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Interface.AddMessage(MessageType.Critical, false, "The route and train loader encountered the following critical error: " + Program.CurrentHost.Plugins[i].Route.LastException.Message);
                    CrashHandler.LoadingCrash(Program.CurrentHost.Plugins[i].Route.LastException.Message, false);
                    Program.RestartArguments = " ";
                    Cancel = true;
                    return;
                }
            }

            TrainManager.Derailments  = Interface.CurrentOptions.Derailments;
            TrainManager.Toppling     = Interface.CurrentOptions.Toppling;
            TrainManager.CurrentRoute = Program.CurrentRoute;
            if (!loaded)
            {
                throw new Exception("No plugins capable of loading routefile " + CurrentRouteFile + " were found.");
            }
            Thread createIllustrations = new Thread(Program.CurrentRoute.Information.LoadInformation)
            {
                IsBackground = true
            };

            createIllustrations.Start();
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Program.CurrentRoute.Atmosphere.CalculateSeaLevelConstants();
            if (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
            {
                double t = Program.CurrentRoute.BogusPreTrainInstructions[0].Time;
                double p = Program.CurrentRoute.BogusPreTrainInstructions[0].TrackPosition;
                for (int i = 1; i < Program.CurrentRoute.BogusPreTrainInstructions.Length; i++)
                {
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].Time > t)
                    {
                        t = Program.CurrentRoute.BogusPreTrainInstructions[i].Time;
                    }
                    else
                    {
                        t += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].Time = t;
                    }
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition > p)
                    {
                        p = Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition;
                    }
                    else
                    {
                        p += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition = p;
                    }
                }
            }
            Program.Renderer.CameraTrackFollower = new TrackFollower(Program.CurrentHost)
            {
                Train = null, Car = null
            };
            if (Program.CurrentRoute.Stations.Length == 1)
            {
                //Log the fact that only a single station is present, as this is probably not right
                Program.FileSystem.AppendToLogFile("The processed route file only contains a single station.");
            }
            Program.FileSystem.AppendToLogFile("Route file loaded successfully.");
            // initialize trains
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Program.TrainManager.Trains = new TrainBase[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
            for (int k = 0; k < Program.TrainManager.Trains.Length; k++)
            {
                if (k == Program.TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
                {
                    Program.TrainManager.Trains[k] = new TrainBase(TrainState.Bogus);
                }
                else
                {
                    Program.TrainManager.Trains[k] = new TrainBase(TrainState.Pending);
                }
            }
            TrainManager.PlayerTrain = Program.TrainManager.Trains[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length];



            // load trains
            for (int k = 0; k < Program.TrainManager.Trains.Length; k++)
            {
                AbstractTrain currentTrain = Program.TrainManager.Trains[k];
                for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
                {
                    if (Program.CurrentHost.Plugins[i].Train != null && Program.CurrentHost.Plugins[i].Train.CanLoadTrain(CurrentTrainFolder))
                    {
                        Program.CurrentHost.Plugins[i].Train.LoadTrain(CurrentTrainEncoding, CurrentTrainFolder, ref currentTrain, ref Interface.CurrentControls);
                        break;
                    }
                }
                Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance);
                // configure other properties
                if (currentTrain.IsPlayerTrain)
                {
                    currentTrain.TimetableDelta = 0.0;
                    if (Game.InitialReversedConsist)
                    {
                        currentTrain.Reverse();
                        TrainManager.PlayerTrain.CameraCar         = currentTrain.DriverCar;
                        Program.Renderer.Camera.CurrentRestriction = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].CameraRestrictionMode;
                    }
                }
                else if (currentTrain.State != TrainState.Bogus)
                {
                    TrainBase train = currentTrain as TrainBase;
                    currentTrain.AI             = new Game.SimpleHumanDriverAI(train, Interface.CurrentOptions.PrecedingTrainSpeedLimit);
                    currentTrain.TimetableDelta = Program.CurrentRoute.PrecedingTrainTimeDeltas[k];
                    train.Specs.DoorOpenMode    = DoorMode.Manual;
                    train.Specs.DoorCloseMode   = DoorMode.Manual;
                }
            }
            // finished created objects
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Array.Resize(ref ObjectManager.AnimatedWorldObjects, ObjectManager.AnimatedWorldObjectsUsed);
            // update sections
            if (Program.CurrentRoute.Sections.Length > 0)
            {
                Program.CurrentRoute.UpdateAllSections();
            }
            // load plugin


            CurrentTrain = 0;
            for (int i = 0; i < Program.TrainManager.Trains.Length; i++)
            {
                if (Program.TrainManager.Trains[i].State != TrainState.Bogus)
                {
                    if (Program.TrainManager.Trains[i].IsPlayerTrain)
                    {
                        if (!Program.TrainManager.Trains[i].LoadCustomPlugin(Program.TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding))
                        {
                            Program.TrainManager.Trains[i].LoadDefaultPlugin(Program.TrainManager.Trains[i].TrainFolder);
                        }
                    }
                    else
                    {
                        Program.TrainManager.Trains[i].LoadDefaultPlugin(Program.TrainManager.Trains[i].TrainFolder);
                    }
                    for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++)
                    {
                        if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
                        {
                            ITrainInputDevice trainInputDevice = (ITrainInputDevice)InputDevicePlugin.AvailablePlugins[j];
                            trainInputDevice.SetVehicleSpecs(Program.TrainManager.Trains[i].vehicleSpecs());
                        }
                    }
                }
                CurrentTrain++;
            }
        }
示例#4
0
文件: Doors.cs 项目: zbx1425/OpenBVE
        /// <summary>Is called once a frame, to update the door states of the train</summary>
        /// <param name="TimeElapsed">The frame time elapsed</param>
        public void UpdateDoors(double TimeElapsed)
        {
            DoorStates oldState = DoorStates.None;
            DoorStates newState = DoorStates.None;

            for (int i = 0; i < Cars.Length; i++)
            {
                bool   ld = Cars[i].Doors[0].AnticipatedOpen;
                bool   rd = Cars[i].Doors[1].AnticipatedOpen;
                double os = Cars[i].Specs.DoorOpenFrequency;
                double cs = Cars[i].Specs.DoorCloseFrequency;

                for (int j = 0; j < Cars[i].Doors.Length; j++)
                {
                    if (Cars[i].Doors[j].Direction == -1 | Cars[i].Doors[j].Direction == 1)
                    {
                        bool shouldBeOpen = Cars[i].Doors[j].Direction == -1 ? ld : rd;
                        if (Cars[i].Doors[j].State > 0.0)
                        {
                            if (Cars[i].Doors[j].Direction == -1)
                            {
                                oldState |= DoorStates.Left;
                            }
                            else
                            {
                                oldState |= DoorStates.Right;
                            }
                        }

                        if (shouldBeOpen)
                        {
                            // open
                            Cars[i].Doors[j].State += os * TimeElapsed;
                            if (Cars[i].Doors[j].State > 1.0)
                            {
                                Cars[i].Doors[j].State = 1.0;
                            }
                        }
                        else
                        {
                            // close
                            if (Cars[i].Doors[j].DoorLockDuration > 0.0)
                            {
                                if (Cars[i].Doors[j].State > Cars[i].Doors[j].DoorLockState)
                                {
                                    Cars[i].Doors[j].State -= cs * TimeElapsed;
                                }

                                if (Cars[i].Doors[j].State < Cars[i].Doors[j].DoorLockState)
                                {
                                    Cars[i].Doors[j].State = Cars[i].Doors[j].DoorLockState;
                                }

                                Cars[i].Doors[j].DoorLockDuration -= TimeElapsed;
                                if (Cars[i].Doors[j].DoorLockDuration < 0.0)
                                {
                                    Cars[i].Doors[j].DoorLockDuration = 0.0;
                                }
                            }
                            else
                            {
                                Cars[i].Doors[j].State -= cs * TimeElapsed;
                            }

                            if (Cars[i].Doors[j].AnticipatedReopen && Cars[i].Doors[j].State < Cars[i].Doors[j].InterferingObjectRate)
                            {
                                Cars[i].Doors[j].State = Cars[i].Doors[j].InterferingObjectRate;
                            }

                            if (Cars[i].Doors[j].State < 0.0)
                            {
                                Cars[i].Doors[j].State = 0.0;
                            }
                        }

                        if (Cars[i].Doors[j].State > 0.0)
                        {
                            if (Cars[i].Doors[j].Direction == -1)
                            {
                                newState |= DoorStates.Left;
                            }
                            else
                            {
                                newState |= DoorStates.Right;
                            }
                        }
                    }
                }
            }

            if (SafetySystems.PilotLamp != null)
            {
                SafetySystems.PilotLamp.Update(newState);
            }

            if (oldState != newState)
            {
                if (Plugin != null)
                {
                    Plugin.DoorChange(oldState, newState);
                }
                for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++)
                {
                    if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
                    {
                        ITrainInputDevice trainInputDevice = (ITrainInputDevice)InputDevicePlugin.AvailablePlugins[j];
                        trainInputDevice.DoorChange(oldState, newState);
                    }
                }
            }
        }
示例#5
0
        private static void LoadEverythingThreaded()
        {
            string RailwayFolder = GetRailwayFolder(CurrentRouteFile);
            string ObjectFolder  = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Object");
            string SoundFolder   = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Sound");

            Game.Reset(true);
            Game.MinimalisticSimulation = true;
            // screen
            Program.Renderer.Camera.CurrentMode = CameraViewMode.Interior;

            Program.CurrentRoute.TrackFollowingObjects = TrainManager.TFOs;
            bool loaded = false;

            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Route loading plugins available.");
            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableObjectPluginCount + " Object loading plugins available.");
            Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Sound loading plugins available.");
            for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
            {
                if (Program.CurrentHost.Plugins[i].Route != null && Program.CurrentHost.Plugins[i].Route.CanLoadRoute(CurrentRouteFile))
                {
                    object Route = (object)Program.CurrentRoute;                     //must cast to allow us to use the ref keyword.
                    if (Program.CurrentHost.Plugins[i].Route.LoadRoute(CurrentRouteFile, CurrentRouteEncoding, CurrentTrainFolder, ObjectFolder, SoundFolder, false, ref Route))
                    {
                        Program.CurrentRoute = (CurrentRoute)Route;
                        Program.Renderer.Lighting.OptionAmbientColor  = Program.CurrentRoute.Atmosphere.AmbientLightColor;
                        Program.Renderer.Lighting.OptionDiffuseColor  = Program.CurrentRoute.Atmosphere.DiffuseLightColor;
                        Program.Renderer.Lighting.OptionLightPosition = Program.CurrentRoute.Atmosphere.LightPosition;
                        loaded = true;
                        break;
                    }
                    var currentError = Translations.GetInterfaceString("errors_critical_file");
                    currentError = currentError.Replace("[file]", System.IO.Path.GetFileName(CurrentRouteFile));
                    MessageBox.Show(currentError, @"OpenBVE", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    Interface.AddMessage(MessageType.Critical, false, "The route and train loader encountered the following critical error: " + Program.CurrentHost.Plugins[i].Route.LastException.Message);
                    CrashHandler.LoadingCrash(Program.CurrentHost.Plugins[i].Route.LastException.Message, false);
                    Program.RestartArguments = " ";
                    Cancel = true;
                    return;
                }
            }

            TrainManager.TFOs = Program.CurrentRoute.TrackFollowingObjects;
            if (!loaded)
            {
                throw new Exception("No plugins capable of loading routefile " + CurrentRouteFile + " were found.");
            }
            Thread createIllustrations = new Thread(Program.CurrentRoute.Information.LoadInformation)
            {
                IsBackground = true
            };

            createIllustrations.Start();
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Program.CurrentRoute.Atmosphere.CalculateSeaLevelConstants();
            if (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
            {
                double t = Program.CurrentRoute.BogusPreTrainInstructions[0].Time;
                double p = Program.CurrentRoute.BogusPreTrainInstructions[0].TrackPosition;
                for (int i = 1; i < Program.CurrentRoute.BogusPreTrainInstructions.Length; i++)
                {
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].Time > t)
                    {
                        t = Program.CurrentRoute.BogusPreTrainInstructions[i].Time;
                    }
                    else
                    {
                        t += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].Time = t;
                    }
                    if (Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition > p)
                    {
                        p = Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition;
                    }
                    else
                    {
                        p += 1.0;
                        Program.CurrentRoute.BogusPreTrainInstructions[i].TrackPosition = p;
                    }
                }
            }
            Program.Renderer.CameraTrackFollower = new TrackFollower(Program.CurrentHost)
            {
                Train = null, Car = null
            };
            if (Program.CurrentRoute.Stations.Length == 1)
            {
                //Log the fact that only a single station is present, as this is probably not right
                Program.FileSystem.AppendToLogFile("The processed route file only contains a single station.");
            }
            Program.FileSystem.AppendToLogFile("Route file loaded successfully.");
            // initialize trains
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            TrainManager.Trains = new TrainManager.Train[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                if (k == TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
                {
                    TrainManager.Trains[k] = new TrainManager.Train(TrainState.Bogus);
                }
                else
                {
                    TrainManager.Trains[k] = new TrainManager.Train(TrainState.Pending);
                }
            }
            TrainManager.PlayerTrain = TrainManager.Trains[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length];

            UnifiedObject[] CarObjects     = null;
            UnifiedObject[] BogieObjects   = null;
            UnifiedObject[] CouplerObjects = null;

            // load trains
            double TrainProgressMaximum = 0.7 + 0.3 * (double)TrainManager.Trains.Length;

            for (int k = 0; k < TrainManager.Trains.Length; k++)
            {
                //Sleep for 20ms to allow route loading locks to release
                Thread.Sleep(20);
                if (TrainManager.Trains[k].State == TrainState.Bogus)
                {
                    // bogus train
                    string TrainData = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility", "PreTrain"), "train.dat");
                    TrainDatParser.ParseTrainData(TrainData, System.Text.Encoding.UTF8, TrainManager.Trains[k]);
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainManager.Trains[k].InitializeCarSounds();
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.3 / TrainProgressMaximum;
                    TrainProgressCurrentSum   += TrainProgressCurrentWeight;
                }
                else
                {
                    TrainManager.Trains[k].TrainFolder = CurrentTrainFolder;
                    // real train
                    if (TrainManager.Trains[k].IsPlayerTrain)
                    {
                        Program.FileSystem.AppendToLogFile("Loading player train: " + TrainManager.Trains[k].TrainFolder);
                    }
                    else
                    {
                        Program.FileSystem.AppendToLogFile("Loading AI train: " + TrainManager.Trains[k].TrainFolder);
                    }
                    TrainProgressCurrentWeight = 0.1 / TrainProgressMaximum;
                    string TrainData = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.dat");
                    TrainDatParser.ParseTrainData(TrainData, CurrentTrainEncoding, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    TrainProgressCurrentWeight = 0.2 / TrainProgressMaximum;
                    SoundCfgParser.ParseSoundConfig(TrainManager.Trains[k].TrainFolder, TrainManager.Trains[k]);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    // door open/close speed
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        if (TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency <= 0.0)
                        {
                            if (TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration;
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].OpenSound.Buffer);
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].OpenSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 0.8;
                            }
                            else
                            {
                                TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency = 0.8;
                            }
                        }
                        if (TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency <= 0.0)
                        {
                            if (TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer != null & TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration;
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                double a = TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8;
                            }
                            else if (TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer != null)
                            {
                                Program.Sounds.LoadBuffer(TrainManager.Trains[k].Cars[i].Doors[0].CloseSound.Buffer);
                                double b = TrainManager.Trains[k].Cars[i].Doors[1].CloseSound.Buffer.Duration;
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8;
                            }
                            else
                            {
                                TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency = 0.8;
                            }
                        }
                        const double f = 0.015;
                        const double g = 2.75;
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                        TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenFrequency  /= TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch;
                        TrainManager.Trains[k].Cars[i].Specs.DoorCloseFrequency /= TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch;

                        /*
                         * Remove the following two lines, then the pitch at which doors play
                         * takes their randomized opening and closing times into account.
                         * */
                        TrainManager.Trains[k].Cars[i].Specs.DoorOpenPitch  = 1.0;
                        TrainManager.Trains[k].Cars[i].Specs.DoorClosePitch = 1.0;
                    }
                }
                // add panel section
                if (TrainManager.Trains[k].IsPlayerTrain)
                {
                    TrainProgressCurrentWeight = 0.7 / TrainProgressMaximum;
                    TrainManager.Trains[k].ParsePanelConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding);
                    TrainProgressCurrentSum += TrainProgressCurrentWeight;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    Program.FileSystem.AppendToLogFile("Train panel loaded sucessfully.");
                }
                // add exterior section
                if (TrainManager.Trains[k].State != TrainState.Bogus)
                {
                    bool   LoadObjects         = false;
                    bool[] VisibleFromInterior = new bool[TrainManager.Trains[k].Cars.Length];
                    if (CarObjects == null)
                    {
                        CarObjects     = new UnifiedObject[TrainManager.Trains[k].Cars.Length];
                        BogieObjects   = new UnifiedObject[TrainManager.Trains[k].Cars.Length * 2];
                        CouplerObjects = new UnifiedObject[TrainManager.Trains[k].Cars.Length];
                        LoadObjects    = true;
                    }
                    string tXml = OpenBveApi.Path.CombineFile(TrainManager.Trains[k].TrainFolder, "train.xml");
                    if (System.IO.File.Exists(tXml))
                    {
                        TrainXmlParser.Parse(tXml, TrainManager.Trains[k], ref CarObjects, ref BogieObjects, ref CouplerObjects, ref VisibleFromInterior);
                    }
                    else
                    {
                        ExtensionsCfgParser.ParseExtensionsConfig(TrainManager.Trains[k].TrainFolder, CurrentTrainEncoding, ref CarObjects, ref BogieObjects, ref CouplerObjects, ref VisibleFromInterior, TrainManager.Trains[k], LoadObjects);
                    }
                    TrainManager.PlayerTrain.CameraCar = TrainManager.Trains[k].DriverCar;
                    System.Threading.Thread.Sleep(1); if (Cancel)
                    {
                        return;
                    }
                    //Stores the current array index of the bogie object to add
                    //Required as there are two bogies per car, and we're using a simple linear array....
                    int currentBogieObject = 0;
                    for (int i = 0; i < TrainManager.Trains[k].Cars.Length; i++)
                    {
                        if (CarObjects[i] == null)
                        {
                            // load default exterior object
                            string       file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                            StaticObject so;
                            Program.CurrentHost.LoadStaticObject(file, System.Text.Encoding.UTF8, false, out so);
                            if (so == null)
                            {
                                CarObjects[i] = null;
                            }
                            else
                            {
                                StaticObject c = (StaticObject)so.Clone();                                 //Clone as otherwise the cached object doesn't scale right
                                c.ApplyScale(TrainManager.Trains[k].Cars[i].Width, TrainManager.Trains[k].Cars[i].Height, TrainManager.Trains[k].Cars[i].Length);
                                CarObjects[i] = c;
                            }
                        }
                        if (CarObjects[i] != null)
                        {
                            // add object
                            TrainManager.Trains[k].Cars[i].LoadCarSections(CarObjects[i], VisibleFromInterior[i]);
                        }

                        if (CouplerObjects[i] != null)
                        {
                            TrainManager.Trains[k].Cars[i].Coupler.LoadCarSections(CouplerObjects[i], VisibleFromInterior[i]);
                        }
                        //Load bogie objects
                        if (BogieObjects[currentBogieObject] != null)
                        {
                            TrainManager.Trains[k].Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject], VisibleFromInterior[i]);
                        }
                        currentBogieObject++;
                        if (BogieObjects[currentBogieObject] != null)
                        {
                            TrainManager.Trains[k].Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject], VisibleFromInterior[i]);
                        }
                        currentBogieObject++;
                    }
                }
                // place cars
                TrainManager.Trains[k].PlaceCars(0.0);

                // configure other properties
                if (TrainManager.Trains[k].IsPlayerTrain)
                {
                    TrainManager.Trains[k].TimetableDelta = 0.0;
                    if (Game.InitialReversedConsist)
                    {
                        TrainManager.Trains[k].Reverse();
                        TrainManager.PlayerTrain.CameraCar         = TrainManager.Trains[k].DriverCar;
                        Program.Renderer.Camera.CurrentRestriction = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar].CameraRestrictionMode;
                    }
                }
                else if (TrainManager.Trains[k].State != TrainState.Bogus)
                {
                    TrainManager.Trains[k].AI                  = new Game.SimpleHumanDriverAI(TrainManager.Trains[k], Interface.CurrentOptions.PrecedingTrainSpeedLimit);
                    TrainManager.Trains[k].TimetableDelta      = Program.CurrentRoute.PrecedingTrainTimeDeltas[k];
                    TrainManager.Trains[k].Specs.DoorOpenMode  = DoorMode.Manual;
                    TrainManager.Trains[k].Specs.DoorCloseMode = DoorMode.Manual;
                }
            }

            /*
             * HACK: Store the TrainManager.Trains reference in the RouteManager also
             *		 Note that this may change when the TrainManager is separated from the lump
             *       Remember not to modify via this ref
             */
            // ReSharper disable once CoVariantArrayConversion
            Program.CurrentRoute.Trains = TrainManager.Trains;
            TrainProgress = 1.0;
            // finished created objects
            System.Threading.Thread.Sleep(1); if (Cancel)
            {
                return;
            }
            Array.Resize(ref ObjectManager.AnimatedWorldObjects, ObjectManager.AnimatedWorldObjectsUsed);
            // update sections
            if (Program.CurrentRoute.Sections.Length > 0)
            {
                Program.CurrentRoute.UpdateAllSections();
            }
            // load plugin
            for (int i = 0; i < TrainManager.Trains.Length; i++)
            {
                if (TrainManager.Trains[i].State != TrainState.Bogus)
                {
                    if (TrainManager.Trains[i].IsPlayerTrain)
                    {
                        if (!TrainManager.Trains[i].LoadCustomPlugin(TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding))
                        {
                            TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder);
                        }
                    }
                    else
                    {
                        TrainManager.Trains[i].LoadDefaultPlugin(TrainManager.Trains[i].TrainFolder);
                    }
                    for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++)
                    {
                        if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
                        {
                            ITrainInputDevice trainInputDevice = (ITrainInputDevice)InputDevicePlugin.AvailablePlugins[j];
                            trainInputDevice.SetVehicleSpecs(TrainManager.Trains[i].vehicleSpecs());
                        }
                    }
                }
            }
        }