/// <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)); } } }
/// <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); } } } } }
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++; } }
/// <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); } } } }
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()); } } } } }