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