/// <summary>This method is called once the route and train data have been preprocessed, in order to physically setup the simulation</summary> private void SetupSimulation() { if (Loading.Cancel) { Close(); } Timetable.CreateTimetable(); //Check if any critical errors have occured during the route or train loading for (int i = 0; i < Interface.MessageCount; i++) { if (Interface.Messages[i].Type == Interface.MessageType.Critical) { MessageBox.Show("A critical error has occured:\n\n" + Interface.Messages[i].Text + "\n\nPlease inspect the error log file for further information.", "Load", MessageBoxButtons.OK, MessageBoxIcon.Hand); Close(); } } Renderer.InitializeLighting(); Game.LogRouteName = System.IO.Path.GetFileName(MainLoop.currentResult.RouteFile); Game.LogTrainName = System.IO.Path.GetFileName(MainLoop.currentResult.TrainFolder); Game.LogDateTime = DateTime.Now; if (Interface.CurrentOptions.LoadInAdvance) { Textures.LoadAllTextures(); } else { Textures.UnloadAllTextures(); } // camera ObjectManager.InitializeVisibility(); TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, 0.0, true, false); TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, -0.1, true, false); TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, 0.1, true, false); World.CameraTrackFollower.TriggerType = TrackManager.EventTriggerType.Camera; // starting time and track position Game.SecondsSinceMidnight = 0.0; Game.StartupTime = 0.0; int PlayerFirstStationIndex = -1; double PlayerFirstStationPosition = 0.0; int os = -1; bool f = false; for (int i = 0; i < Game.Stations.Length; i++) { if (!String.IsNullOrEmpty(Game.InitialStationName)) { if (Game.InitialStationName.ToLowerInvariant() == Game.Stations[i].Name.ToLowerInvariant()) { PlayerFirstStationIndex = i; } } if (Game.Stations[i].StopMode == Game.StationStopMode.AllStop | Game.Stations[i].StopMode == Game.StationStopMode.PlayerStop & Game.Stations[i].Stops.Length != 0) { if (f == false) { os = i; f = true; } } } if (PlayerFirstStationIndex == -1) { PlayerFirstStationIndex = os; } { int s = Game.GetStopIndex(PlayerFirstStationIndex, TrainManager.PlayerTrain.Cars.Length); if (s >= 0) { PlayerFirstStationPosition = Game.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition; double TrainLength = 0.0; for (int c = 0; c < TrainManager.Trains[TrainManager.PlayerTrain.TrainIndex].Cars.Length; c++) { TrainLength += TrainManager.Trains[TrainManager.PlayerTrain.TrainIndex].Cars[c].Length; } for (int j = 0; j < Game.BufferTrackPositions.Length; j++) { if (PlayerFirstStationPosition > Game.BufferTrackPositions[j] && PlayerFirstStationPosition - TrainLength < Game.BufferTrackPositions[j]) { /* * HACK: The initial start position for the player train is stuck on a set of buffers * This means we have to make some one the fly adjustments to the first station stop position */ //Set the start position to be the buffer position plus the train length plus 1m PlayerFirstStationPosition = Game.BufferTrackPositions[j] + TrainLength + 1; //Update the station stop location if (s >= 0) { Game.Stations[PlayerFirstStationIndex].Stops[s].TrackPosition = PlayerFirstStationPosition; } else { Game.Stations[PlayerFirstStationIndex].DefaultTrackPosition = PlayerFirstStationPosition; } break; } } } else { PlayerFirstStationPosition = Game.Stations[PlayerFirstStationIndex].DefaultTrackPosition; } if (Game.InitialStationTime != -1) { Game.SecondsSinceMidnight = Game.InitialStationTime; Game.StartupTime = Game.InitialStationTime; } else { if (Game.Stations[PlayerFirstStationIndex].ArrivalTime < 0.0) { if (Game.Stations[PlayerFirstStationIndex].DepartureTime < 0.0) { Game.SecondsSinceMidnight = 0.0; Game.StartupTime = 0.0; } else { Game.SecondsSinceMidnight = Game.Stations[PlayerFirstStationIndex].DepartureTime - Game.Stations[PlayerFirstStationIndex].StopTime; Game.StartupTime = Game.Stations[PlayerFirstStationIndex].DepartureTime - Game.Stations[PlayerFirstStationIndex].StopTime; } } else { Game.SecondsSinceMidnight = Game.Stations[PlayerFirstStationIndex].ArrivalTime; Game.StartupTime = Game.Stations[PlayerFirstStationIndex].ArrivalTime; } } } int OtherFirstStationIndex = -1; double OtherFirstStationPosition = 0.0; double OtherFirstStationTime = 0.0; for (int i = 0; i < Game.Stations.Length; i++) { if (Game.Stations[i].StopMode == Game.StationStopMode.AllStop | Game.Stations[i].StopMode == Game.StationStopMode.PlayerPass & Game.Stations[i].Stops.Length != 0) { OtherFirstStationIndex = i; int s = Game.GetStopIndex(i, TrainManager.PlayerTrain.Cars.Length); if (s >= 0) { OtherFirstStationPosition = Game.Stations[i].Stops[s].TrackPosition; } else { OtherFirstStationPosition = Game.Stations[i].DefaultTrackPosition; } if (Game.Stations[i].ArrivalTime < 0.0) { if (Game.Stations[i].DepartureTime < 0.0) { OtherFirstStationTime = 0.0; } else { OtherFirstStationTime = Game.Stations[i].DepartureTime - Game.Stations[i].StopTime; } } else { OtherFirstStationTime = Game.Stations[i].ArrivalTime; } break; } } if (Game.PrecedingTrainTimeDeltas.Length != 0) { OtherFirstStationTime -= Game.PrecedingTrainTimeDeltas[Game.PrecedingTrainTimeDeltas.Length - 1]; if (OtherFirstStationTime < Game.SecondsSinceMidnight) { Game.SecondsSinceMidnight = OtherFirstStationTime; } } // initialize trains for (int i = 0; i < TrainManager.Trains.Length; i++) { TrainManager.InitializeTrain(TrainManager.Trains[i]); int s = i == TrainManager.PlayerTrain.TrainIndex ? PlayerFirstStationIndex : OtherFirstStationIndex; if (s >= 0) { if (Game.Stations[s].OpenLeftDoors) { for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { TrainManager.Trains[i].Cars[j].Specs.AnticipatedLeftDoorsOpened = true; } } if (Game.Stations[s].OpenRightDoors) { for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { TrainManager.Trains[i].Cars[j].Specs.AnticipatedRightDoorsOpened = true; } } } if (Game.Sections.Length != 0) { Game.Sections[0].Enter(TrainManager.Trains[i]); } for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { double length = TrainManager.Trains[i].Cars[0].Length; TrainManager.MoveCar(TrainManager.Trains[i], j, -length, 0.01); TrainManager.MoveCar(TrainManager.Trains[i], j, length, 0.01); } } // score Game.CurrentScore.ArrivalStation = PlayerFirstStationIndex + 1; Game.CurrentScore.DepartureStation = PlayerFirstStationIndex; Game.CurrentScore.Maximum = 0; for (int i = 0; i < Game.Stations.Length; i++) { if (i != PlayerFirstStationIndex & Game.PlayerStopsAtStation(i)) { if (i == 0 || Game.Stations[i - 1].StationType != Game.StationType.ChangeEnds) { Game.CurrentScore.Maximum += Game.ScoreValueStationArrival; } } } if (Game.CurrentScore.Maximum <= 0) { Game.CurrentScore.Maximum = Game.ScoreValueStationArrival; } // signals if (Game.Sections.Length > 0) { Game.UpdateSection(Game.Sections.Length - 1); } // move train in position for (int i = 0; i < TrainManager.Trains.Length; i++) { double p; if (i == TrainManager.PlayerTrain.TrainIndex) { p = PlayerFirstStationPosition; } else if (TrainManager.Trains[i].State == TrainManager.TrainState.Bogus) { p = Game.BogusPretrainInstructions[0].TrackPosition; TrainManager.Trains[i].AI = new Game.BogusPretrainAI(TrainManager.Trains[i]); } else { p = OtherFirstStationPosition; } for (int j = 0; j < TrainManager.Trains[i].Cars.Length; j++) { TrainManager.MoveCar(TrainManager.Trains[i], j, p, 0.01); } } // timetable if (Timetable.DefaultTimetableDescription.Length == 0) { Timetable.DefaultTimetableDescription = Game.LogTrainName; } // initialize camera if (World.CameraRestriction == World.CameraRestrictionMode.NotAvailable) { World.CameraMode = World.CameraViewMode.InteriorLookAhead; } //Place the initial camera in the driver car TrainManager.UpdateCamera(TrainManager.PlayerTrain, TrainManager.PlayerTrain.DriverCar); TrackManager.UpdateTrackFollower(ref World.CameraTrackFollower, -1.0, true, false); ObjectManager.UpdateVisibility(World.CameraTrackFollower.TrackPosition + World.CameraCurrentAlignment.Position.Z); World.CameraSavedInterior = new World.CameraAlignment(); World.CameraSavedExterior = new World.CameraAlignment(new OpenBveApi.Math.Vector3(-2.5, 1.5, -15.0), 0.3, -0.2, 0.0, PlayerFirstStationPosition, 1.0); World.CameraSavedTrack = new World.CameraAlignment(new OpenBveApi.Math.Vector3(-3.0, 2.5, 0.0), 0.3, 0.0, 0.0, TrainManager.PlayerTrain.Cars[0].FrontAxle.Follower.TrackPosition - 10.0, 1.0); // signalling sections for (int i = 0; i < TrainManager.Trains.Length; i++) { int s = TrainManager.Trains[i].CurrentSectionIndex; Game.Sections[s].Enter(TrainManager.Trains[i]); } if (Game.Sections.Length > 0) { Game.UpdateSection(Game.Sections.Length - 1); } // fast-forward until start time { Game.MinimalisticSimulation = true; const double w = 0.25; double u = Game.StartupTime - Game.SecondsSinceMidnight; if (u > 0) { while (true) { double v = u < w ? u : w; u -= v; Game.SecondsSinceMidnight += v; TrainManager.UpdateTrains(v); if (u <= 0.0) { break; } TotalTimeElapsedForSectionUpdate += v; if (TotalTimeElapsedForSectionUpdate >= 1.0) { if (Game.Sections.Length > 0) { Game.UpdateSection(Game.Sections.Length - 1); } TotalTimeElapsedForSectionUpdate = 0.0; } } } Game.MinimalisticSimulation = false; } // animated objects ObjectManager.UpdateAnimatedWorldObjects(0.0, true); TrainManager.UpdateTrainObjects(0.0, true); //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.UpdateCabObjects(TrainManager.PlayerTrain); // timetable if (TrainManager.PlayerTrain.Station >= 0) { Timetable.UpdateCustomTimetable(Game.Stations[TrainManager.PlayerTrain.Station].TimetableDaytimeTexture, Game.Stations[TrainManager.PlayerTrain.Station].TimetableNighttimeTexture); if (Timetable.CustomObjectsUsed != 0 & Timetable.CustomTimetableAvailable && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.AutoGenerated && Interface.CurrentOptions.TimeTableStyle != Interface.TimeTableMode.None) { Timetable.CurrentTimetable = Timetable.TimetableState.Custom; } } //Create AI driver for the player train if specified via the commmand line if (Game.InitialAIDriver == true) { TrainManager.PlayerTrain.AI = new Game.SimpleHumanDriverAI(TrainManager.PlayerTrain); if (TrainManager.PlayerTrain.Plugin != null && !TrainManager.PlayerTrain.Plugin.SupportsAI) { Game.AddMessage(Interface.GetInterfaceString("notification_aiunable"), MessageManager.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.White, Game.SecondsSinceMidnight + 10.0, null); } } // warnings / errors if (Interface.MessageCount != 0) { int filesNotFound = 0; int errors = 0; int warnings = 0; for (int i = 0; i < Interface.MessageCount; i++) { if (Interface.Messages[i].FileNotFound) { filesNotFound++; } else if (Interface.Messages[i].Type == Interface.MessageType.Error) { errors++; } else if (Interface.Messages[i].Type == Interface.MessageType.Warning) { warnings++; } } string NotFound = null; string Messages = null; if (filesNotFound != 0) { NotFound = filesNotFound.ToString() + " file(s) not found"; Game.AddMessage(NotFound, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null); } if (errors != 0 & warnings != 0) { Messages = errors.ToString() + " error(s), " + warnings.ToString() + " warning(s)"; Game.AddMessage(Messages, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null); } else if (errors != 0) { Messages = errors.ToString() + " error(s)"; Game.AddMessage(Messages, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null); } else { Messages = warnings.ToString() + " warning(s)"; Game.AddMessage(Messages, MessageManager.MessageDependency.None, Interface.GameMode.Expert, MessageColor.Magenta, Game.SecondsSinceMidnight + 10.0, null); } Game.RouteInformation.FilesNotFound = NotFound; Game.RouteInformation.ErrorsAndWarnings = Messages; //Print the plugin error encountered (If any) for 10s //This must be done after the simulation has init, as otherwise the timeout doesn't work if (Loading.PluginError != null) { Game.AddMessage(Loading.PluginError, MessageManager.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Game.SecondsSinceMidnight + 5.0, null); Game.AddMessage(Interface.GetInterfaceString("errors_plugin_failure2"), MessageManager.MessageDependency.None, Interface.GameMode.Expert, OpenBveApi.Colors.MessageColor.Red, Game.SecondsSinceMidnight + 5.0, null); } } loadComplete = true; RenderRealTimeElapsed = 0.0; RenderTimeElapsed = 0.0; World.InitializeCameraRestriction(); }