internal static void Write(string fileName, Train train) { StringBuilder builder = new StringBuilder(); CultureInfo culture = CultureInfo.InvariantCulture; const int n = 15; MotorCar firstMotorCar = train.Cars.OfType <MotorCar>().First(); TrailerCar firstTrailerCar = train.Cars.OfType <TrailerCar>().FirstOrDefault(); builder.AppendLine("OPENBVE" + currentVersion); builder.AppendLine("#ACCELERATION"); for (int i = firstMotorCar.Acceleration.Entries.Count - 1; i >= train.Handle.PowerNotches; i--) { firstMotorCar.Acceleration.Entries.RemoveAt(i); } foreach (Acceleration.Entry entry in firstMotorCar.Acceleration.Entries) { builder.Append(entry.A0.ToString(culture) + ","); builder.Append(entry.A1.ToString(culture) + ","); builder.Append(entry.V1.ToString(culture) + ","); builder.Append(entry.V2.ToString(culture) + ","); builder.AppendLine(entry.E.ToString(culture)); } builder.AppendLine("#PERFORMANCE"); builder.AppendLine($"{firstMotorCar.Performance.Deceleration.ToString(culture).PadRight(n, ' ')}; Deceleration"); builder.AppendLine($"{firstMotorCar.Performance.CoefficientOfStaticFriction.ToString(culture).PadRight(n, ' ')}; CoefficientOfStaticFriction"); builder.AppendLine($"{"0".PadRight(n, ' ')}; Reserved (not used)"); builder.AppendLine($"{firstMotorCar.Performance.CoefficientOfRollingResistance.ToString(culture).PadRight(n, ' ')}; CoefficientOfRollingResistance"); builder.AppendLine($"{firstMotorCar.Performance.AerodynamicDragCoefficient.ToString(culture).PadRight(n, ' ')}; AerodynamicDragCoefficient"); builder.AppendLine("#DELAY"); builder.AppendLine($"{string.Join(",", firstMotorCar.Delay.DelayPower.Select(d => d.Up.ToString(culture))).PadRight(n, ' ')}; DelayPowerUp"); builder.AppendLine($"{string.Join(",", firstMotorCar.Delay.DelayPower.Select(d => d.Down.ToString(culture))).PadRight(n, ' ')}; DelayPowerDown"); builder.AppendLine($"{string.Join(",", firstMotorCar.Delay.DelayBrake.Select(d => d.Up.ToString(culture))).PadRight(n, ' ')}; DelayBrakeUp"); builder.AppendLine($"{string.Join(",", firstMotorCar.Delay.DelayBrake.Select(d => d.Down.ToString(culture))).PadRight(n, ' ')}; DelayBrakeDown"); builder.AppendLine($"{string.Join(",", firstMotorCar.Delay.DelayLocoBrake.Select(d => d.Up.ToString(culture))).PadRight(n, ' ')}; DelayLocoBrakeUp (1.5.3.4+)"); builder.AppendLine($"{string.Join(",", firstMotorCar.Delay.DelayLocoBrake.Select(d => d.Down.ToString(culture))).PadRight(n, ' ')}; DelayLocoBrakeDown (1.5.3.4+)"); builder.AppendLine("#MOVE"); builder.AppendLine($"{firstMotorCar.Move.JerkPowerUp.ToString(culture).PadRight(n, ' ')}; JerkPowerUp"); builder.AppendLine($"{firstMotorCar.Move.JerkPowerDown.ToString(culture).PadRight(n, ' ')}; JerkPowerDown"); builder.AppendLine($"{firstMotorCar.Move.JerkBrakeUp.ToString(culture).PadRight(n, ' ')}; JerkBrakeUp"); builder.AppendLine($"{firstMotorCar.Move.JerkBrakeDown.ToString(culture).PadRight(n, ' ')}; JerkBrakeDown"); builder.AppendLine($"{firstMotorCar.Move.BrakeCylinderUp.ToString(culture).PadRight(n, ' ')}; BrakeCylinderUp"); builder.AppendLine($"{firstMotorCar.Move.BrakeCylinderDown.ToString(culture).PadRight(n, ' ')}; BrakeCylinderDown"); builder.AppendLine("#BRAKE"); builder.AppendLine($"{((int)firstMotorCar.Brake.BrakeType).ToString(culture).PadRight(n, ' ')}; BrakeType"); builder.AppendLine($"{((int)firstMotorCar.Brake.BrakeControlSystem).ToString(culture).PadRight(n, ' ')}; BrakeControlSystem"); builder.AppendLine($"{firstMotorCar.Brake.BrakeControlSpeed.ToString(culture).PadRight(n, ' ')}; BrakeControlSpeed"); builder.AppendLine($"{((int)firstMotorCar.Brake.LocoBrakeType).ToString(culture).PadRight(n, ' ')}; LocoBrakeType (1.5.3.4+)"); builder.AppendLine("#PRESSURE"); builder.AppendLine($"{firstMotorCar.Pressure.BrakeCylinderServiceMaximumPressure.ToString(culture).PadRight(n, ' ')}; BrakeCylinderServiceMaximumPressure"); builder.AppendLine($"{firstMotorCar.Pressure.BrakeCylinderEmergencyMaximumPressure.ToString(culture).PadRight(n, ' ')}; BrakeCylinderEmergencyMaximumPressure"); builder.AppendLine($"{firstMotorCar.Pressure.MainReservoirMinimumPressure.ToString(culture).PadRight(n, ' ')}; MainReservoirMinimumPressure"); builder.AppendLine($"{firstMotorCar.Pressure.MainReservoirMaximumPressure.ToString(culture).PadRight(n, ' ')}; MainReservoirMaximumPressure"); builder.AppendLine($"{firstMotorCar.Pressure.BrakePipeNormalPressure.ToString(culture).PadRight(n, ' ')}; BrakePipeNormalPressure"); builder.AppendLine("#HANDLE"); builder.AppendLine($"{((int)train.Handle.HandleType).ToString(culture).PadRight(n, ' ')}; HandleType"); builder.AppendLine($"{train.Handle.PowerNotches.ToString(culture).PadRight(n, ' ')}; PowerNotches"); builder.AppendLine($"{train.Handle.BrakeNotches.ToString(culture).PadRight(n, ' ')}; BrakeNotches"); builder.AppendLine($"{train.Handle.PowerNotchReduceSteps.ToString(culture).PadRight(n, ' ')}; PowerNotchReduceSteps"); builder.AppendLine($"{((int)train.Handle.HandleBehaviour).ToString(culture).PadRight(n, ' ')}; EbHandleBehaviour (1.5.3.3+)"); builder.AppendLine($"{train.Handle.LocoBrakeNotches.ToString(culture).PadRight(n, ' ')}; LocoBrakeNotches (1.5.3.4+)"); builder.AppendLine($"{((int)train.Handle.LocoBrake).ToString(culture).PadRight(n, ' ')}; LocoBrakeType (1.5.3.4+)"); builder.AppendLine($"{train.Handle.DriverPowerNotches.ToString(culture).PadRight(n, ' ')}; DriverPowerNotches (1.5.3.11+)"); builder.AppendLine($"{train.Handle.DriverBrakeNotches.ToString(culture).PadRight(n, ' ')}; DriverBrakeNotches (1.5.3.11+)"); builder.AppendLine("#CAB"); builder.AppendLine($"{train.Cab.PositionX.ToString(culture).PadRight(n, ' ')}; X"); builder.AppendLine($"{train.Cab.PositionY.ToString(culture).PadRight(n, ' ')}; Y"); builder.AppendLine($"{train.Cab.PositionZ.ToString(culture).PadRight(n, ' ')}; Z"); builder.AppendLine($"{train.Cab.DriverCar.ToString(culture).PadRight(n, ' ')}; DriverCar"); builder.AppendLine("#CAR"); builder.AppendLine($"{firstMotorCar.Mass.ToString(culture).PadRight(n, ' ')}; MotorCarMass"); builder.AppendLine($"{train.Cars.Count(c => c is MotorCar).ToString(culture).PadRight(n, ' ')}; NumberOfMotorCars"); builder.AppendLine($"{(firstTrailerCar ?? new TrailerCar()).Mass.ToString(culture).PadRight(n, ' ')}; TrailerCarMass"); builder.AppendLine($"{train.Cars.Count(c => c is TrailerCar).ToString(culture).PadRight(n, ' ')}; NumberOfTrailerCars"); builder.AppendLine($"{firstMotorCar.Length.ToString(culture).PadRight(n, ' ')}; LengthOfACar"); builder.AppendLine($"{(train.Cars.First() is MotorCar ? "1" : "0").PadRight(n, ' ')}; FrontCarIsAMotorCar"); builder.AppendLine($"{firstMotorCar.Width.ToString(culture).PadRight(n, ' ')}; WidthOfACar"); builder.AppendLine($"{firstMotorCar.Height.ToString(culture).PadRight(n, ' ')}; HeightOfACar"); builder.AppendLine($"{firstMotorCar.CenterOfGravityHeight.ToString(culture).PadRight(n, ' ')}; CenterOfGravityHeight"); builder.AppendLine($"{firstMotorCar.ExposedFrontalArea.ToString(culture).PadRight(n, ' ')}; ExposedFrontalArea"); builder.AppendLine($"{firstMotorCar.UnexposedFrontalArea.ToString(culture).PadRight(n, ' ')}; UnexposedFrontalArea"); builder.AppendLine("#DEVICE"); builder.AppendLine($"{((int)train.Device.Ats).ToString(culture).PadRight(n, ' ')}; Ats"); builder.AppendLine($"{((int)train.Device.Atc).ToString(culture).PadRight(n, ' ')}; Atc"); builder.AppendLine($"{(train.Device.Eb ? "1" : "0").PadRight(n, ' ')}; Eb"); builder.AppendLine($"{(train.Device.ConstSpeed ? "1" : "0").PadRight(n, ' ')}; ConstSpeed"); builder.AppendLine($"{(train.Device.HoldBrake ? "1" : "0").PadRight(n, ' ')}; HoldBrake"); builder.AppendLine($"{((int)train.Device.ReAdhesionDevice).ToString(culture).PadRight(n, ' ')}; ReAdhesionDevice"); builder.AppendLine($"{train.Device.LoadCompensatingDevice.ToString(culture).PadRight(n, ' ')}; Reserved (not used)"); builder.AppendLine($"{((int)train.Device.PassAlarm).ToString(culture).PadRight(n, ' ')}; PassAlarm"); builder.AppendLine($"{((int)train.Device.DoorOpenMode).ToString(culture).PadRight(n, ' ')}; DoorOpenMode"); builder.AppendLine($"{((int)train.Device.DoorCloseMode).ToString(culture).PadRight(n, ' ')}; DoorCloseMode"); builder.AppendLine($"{train.Device.DoorWidth.ToString(culture).PadRight(n, ' ')}; DoorWidth"); builder.AppendLine($"{train.Device.DoorMaxTolerance.ToString(culture).PadRight(n, ' ')}; DoorMaxTolerance"); for (int i = 0; i < 4; i++) { BVEMotorSoundTableEntry[] entries = new BVEMotorSoundTableEntry[0]; switch (i) { case 0: builder.AppendLine("#MOTOR_P1"); entries = Motor.Track.TrackToEntries(firstMotorCar.Motor.Tracks[(int)Motor.TrackInfo.Power1]); break; case 1: builder.AppendLine("#MOTOR_P2"); entries = Motor.Track.TrackToEntries(firstMotorCar.Motor.Tracks[(int)Motor.TrackInfo.Power2]); break; case 2: builder.AppendLine("#MOTOR_B1"); entries = Motor.Track.TrackToEntries(firstMotorCar.Motor.Tracks[(int)Motor.TrackInfo.Brake1]); break; case 3: builder.AppendLine("#MOTOR_B2"); entries = Motor.Track.TrackToEntries(firstMotorCar.Motor.Tracks[(int)Motor.TrackInfo.Brake2]); break; } int k; for (k = entries.Length - 1; k >= 0; k--) { if (entries[k].SoundIndex >= 0) { break; } } k = Math.Min(k + 2, entries.Length); Array.Resize(ref entries, k); for (int j = 0; j < entries.Length; j++) { builder.Append(entries[j].SoundIndex.ToString(culture) + ","); builder.Append(entries[j].Pitch.ToString(culture) + ","); builder.AppendLine(entries[j].Gain.ToString(culture)); } } File.WriteAllText(fileName, builder.ToString(), new UTF8Encoding(true)); }
internal static void Parse(string fileName, out Train train) { train = new Train(); CultureInfo culture = CultureInfo.InvariantCulture; string[] lines = File.ReadAllLines(fileName, TextEncoding.GetSystemEncodingFromFile(fileName)); for (int i = 0; i < lines.Length; i++) { int j = lines[i].IndexOf(';'); if (j >= 0) { lines[i] = lines[i].Substring(0, j).Trim(); } else { lines[i] = lines[i].Trim(); } } bool ver1220000 = false; foreach (string line in lines) { if (line.Length != 0) { string s = line.ToLowerInvariant(); switch (s) { case "bve1200000": case "bve1210000": case "bve1220000": ver1220000 = true; break; case "bve2000000": case "openbve": //No action break; default: if (s.ToLowerInvariant().StartsWith("openbve")) { string tt = s.Substring(7, s.Length - 7); int v; if (int.TryParse(tt, NumberStyles.Float, culture, out v)) { if (v > currentVersion) { Interface.AddMessage(MessageType.Warning, false, $"The train.dat {fileName} was created with a newer version of openBVE. Please check for an update."); } } else { Interface.AddMessage(MessageType.Error, false, $"The train.dat version {lines[0].ToLowerInvariant()} is invalid in {fileName}"); } } break; } break; } } Acceleration acceleration = new Acceleration(); Performance performance = new Performance(); Delay delay = new Delay(); Move move = new Move(); Brake brake = new Brake(); Pressure pressure = new Pressure(); Motor motor = new Motor(); double motorCarMass = 40.0; int numberOfMotorCars = 1; double trailerCarMass = 40.0; int numberOfTrailerCars = 1; double lengthOfACar = 20.0; bool frontCarIsAMotorCar = false; double widthOfACar = 2.6; double heightOfACar = 3.2; double centerOfGravityHeight = 1.5; double exposedFrontalArea = 5.0; double unexposedFrontalArea = 1.6; for (int i = 0; i < lines.Length; i++) { int n = 0; switch (lines[i].ToLowerInvariant()) { case "#acceleration": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { if (n == acceleration.Entries.Count) { acceleration.Entries.Add(new Acceleration.Entry()); } string u = lines[i] + ","; int m = 0; while (true) { int j = u.IndexOf(','); if (j == -1) { break; } string s = u.Substring(0, j).Trim(); u = u.Substring(j + 1); double a; if (double.TryParse(s, NumberStyles.Float, culture, out a)) { switch (m) { case 0: acceleration.Entries[n].A0 = Math.Max(a, 0.0); break; case 1: acceleration.Entries[n].A1 = Math.Max(a, 0.0); break; case 2: acceleration.Entries[n].V1 = Math.Max(a, 0.0); break; case 3: acceleration.Entries[n].V2 = Math.Max(a, 0.0); if (acceleration.Entries[n].V2 < acceleration.Entries[n].V1) { double x = acceleration.Entries[n].V1; acceleration.Entries[n].V1 = acceleration.Entries[n].V2; acceleration.Entries[n].V2 = x; } break; case 4: if (ver1220000) { if (a <= 0.0) { acceleration.Entries[n].E = 1.0; } else { const double c = 1.23315173118822; acceleration.Entries[n].E = 1.0 - Math.Log(a) * acceleration.Entries[n].V2 * c; if (acceleration.Entries[n].E > 4.0) { acceleration.Entries[n].E = 4.0; } } } else { acceleration.Entries[n].E = a; } break; } } m++; } i++; n++; } i--; break; case "#performance": case "#deceleration": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { switch (n) { case 0: if (a >= 0.0) { performance.Deceleration = a; } break; case 1: if (a >= 0.0) { performance.CoefficientOfStaticFriction = a; } break; case 3: if (a >= 0.0) { performance.CoefficientOfRollingResistance = a; } break; case 4: if (a >= 0.0) { performance.AerodynamicDragCoefficient = a; } break; } } i++; n++; } i--; break; case "#delay": i++; double[] delayPowerUp = delay.DelayPower.Select(x => x.Up).ToArray(); double[] delayPowerDown = delay.DelayPower.Select(x => x.Down).ToArray(); double[] delayBrakeUp = delay.DelayBrake.Select(x => x.Up).ToArray(); double[] delayBrakeDown = delay.DelayBrake.Select(x => x.Down).ToArray(); double[] delayLocoBrakeUp = delay.DelayLocoBrake.Select(x => x.Up).ToArray(); double[] delayLocoBrakeDown = delay.DelayLocoBrake.Select(x => x.Down).ToArray(); delay.DelayPower.Clear(); delay.DelayBrake.Clear(); delay.DelayLocoBrake.Clear(); while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { switch (n) { case 0: if (a >= 0.0) { delayPowerUp = new[] { a }; } break; case 1: if (a >= 0.0) { delayPowerDown = new[] { a }; } break; case 2: if (a >= 0.0) { delayBrakeUp = new[] { a }; } break; case 3: if (a >= 0.0) { delayBrakeDown = new[] { a }; } break; } } else if (lines[i].IndexOf(',') != -1) { switch (n) { case 0: delayPowerUp = lines[i].Split(',').Select(x => double.Parse(x, culture)).ToArray(); break; case 1: delayPowerDown = lines[i].Split(',').Select(x => double.Parse(x, culture)).ToArray(); break; case 2: delayBrakeUp = lines[i].Split(',').Select(x => double.Parse(x, culture)).ToArray(); break; case 3: delayBrakeDown = lines[i].Split(',').Select(x => double.Parse(x, culture)).ToArray(); break; case 4: delayLocoBrakeUp = lines[i].Split(',').Select(x => double.Parse(x, culture)).ToArray(); break; case 5: delayLocoBrakeDown = lines[i].Split(',').Select(x => double.Parse(x, culture)).ToArray(); break; } } i++; n++; } for (int j = 0; j < Math.Max(delayPowerUp.Length, delayPowerDown.Length); j++) { Delay.Entry entry = new Delay.Entry(); if (j < delayPowerUp.Length) { entry.Up = delayPowerUp[j]; } if (j < delayPowerDown.Length) { entry.Down = delayPowerDown[j]; } delay.DelayPower.Add(entry); } for (int j = 0; j < Math.Max(delayBrakeUp.Length, delayBrakeDown.Length); j++) { Delay.Entry entry = new Delay.Entry(); if (j < delayBrakeUp.Length) { entry.Up = delayBrakeUp[j]; } if (j < delayBrakeDown.Length) { entry.Down = delayBrakeDown[j]; } delay.DelayBrake.Add(entry); } for (int j = 0; j < Math.Max(delayLocoBrakeUp.Length, delayLocoBrakeDown.Length); j++) { Delay.Entry entry = new Delay.Entry(); if (j < delayLocoBrakeUp.Length) { entry.Up = delayLocoBrakeUp[j]; } if (j < delayLocoBrakeDown.Length) { entry.Down = delayLocoBrakeDown[j]; } delay.DelayLocoBrake.Add(entry); } i--; break; case "#move": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { switch (n) { case 0: if (a >= 0.0) { move.JerkPowerUp = a; } break; case 1: if (a >= 0.0) { move.JerkPowerDown = a; } break; case 2: if (a >= 0.0) { move.JerkBrakeUp = a; } break; case 3: if (a >= 0.0) { move.JerkBrakeDown = a; } break; case 4: if (a >= 0.0) { move.BrakeCylinderUp = a; } break; case 5: if (a >= 0.0) { move.BrakeCylinderDown = a; } break; } } i++; n++; } i--; break; case "#brake": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { int b = (int)Math.Round(a); switch (n) { case 0: if (b >= 0 & b <= 2) { brake.BrakeType = (BrakeSystemType)b; } break; case 1: if (b >= 0 & b <= 2) { brake.BrakeControlSystem = (EletropneumaticBrakeType)b; } break; case 2: if (a >= 0.0) { brake.BrakeControlSpeed = a; } break; case 3: if (a <= 0 && a > 3) { brake.LocoBrakeType = (Brake.LocoBrakeTypes)b; } break; } } i++; n++; } i--; break; case "#pressure": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { switch (n) { case 0: if (a > 0.0) { pressure.BrakeCylinderServiceMaximumPressure = a; } break; case 1: if (a > 0.0) { pressure.BrakeCylinderEmergencyMaximumPressure = a; } break; case 2: if (a > 0.0) { pressure.MainReservoirMinimumPressure = a; } break; case 3: if (a > 0.0) { pressure.MainReservoirMaximumPressure = a; } break; case 4: if (a > 0.0) { pressure.BrakePipeNormalPressure = a; } break; } } i++; n++; } i--; break; case "#handle": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { int b = (int)Math.Round(a); switch (n) { case 0: if (b == 0 | b == 1) { train.Handle.HandleType = (Handle.HandleTypes)b; } break; case 1: if (b > 0) { train.Handle.PowerNotches = b; } break; case 2: if (b > 0) { train.Handle.BrakeNotches = b; } break; case 3: if (b >= 0) { train.Handle.PowerNotchReduceSteps = b; } break; case 4: if (a >= 0 && a < 4) { train.Handle.HandleBehaviour = (EbHandleBehaviour)b; } break; case 5: if (b > 0) { train.Handle.LocoBrakeNotches = b; } break; case 6: if (a <= 0 && a > 3) { train.Handle.LocoBrake = (LocoBrakeType)b; } break; case 7: if (b > 0) { train.Handle.DriverPowerNotches = b; } break; case 8: if (b > 0) { train.Handle.DriverBrakeNotches = b; } break; } } i++; n++; } i--; break; case "#cockpit": case "#cab": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { switch (n) { case 0: train.Cab.PositionX = a; break; case 1: train.Cab.PositionY = a; break; case 2: train.Cab.PositionZ = a; break; case 3: train.Cab.DriverCar = (int)Math.Round(a); break; } } i++; n++; } i--; break; case "#car": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { int b = (int)Math.Round(a); switch (n) { case 0: if (a > 0.0) { motorCarMass = a; } break; case 1: if (b >= 1) { numberOfMotorCars = b; } break; case 2: if (a > 0.0) { trailerCarMass = a; } break; case 3: if (b >= 0) { numberOfTrailerCars = b; } break; case 4: if (b > 0.0) { lengthOfACar = a; } break; case 5: frontCarIsAMotorCar = a == 1.0; break; case 6: if (a > 0.0) { widthOfACar = a; } break; case 7: if (a > 0.0) { heightOfACar = a; } break; case 8: centerOfGravityHeight = a; break; case 9: if (a > 0.0) { exposedFrontalArea = a; } break; case 10: if (a > 0.0) { unexposedFrontalArea = a; } break; } } i++; n++; } i--; break; case "#device": i++; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { double a; if (double.TryParse(lines[i], NumberStyles.Float, culture, out a)) { int b = (int)Math.Round(a); switch (n) { case 0: if (b >= -1 & b <= 1) { train.Device.Ats = (AtsModes)b; } break; case 1: if (b >= 0 & b <= 2) { train.Device.Atc = (AtcModes)b; } break; case 2: train.Device.Eb = a == 1.0; break; case 3: train.Device.ConstSpeed = a == 1.0; break; case 4: train.Device.HoldBrake = a == 1.0; break; case 5: if (b >= -1 & b <= 3) { train.Device.ReAdhesionDevice = (ReadhesionDeviceType)b; } break; case 6: train.Device.LoadCompensatingDevice = a; break; case 7: if (b >= 0 & b <= 2) { train.Device.PassAlarm = (PassAlarmType)b; } break; case 8: if (b >= 0 & b <= 2) { train.Device.DoorOpenMode = (DoorMode)b; } break; case 9: if (b >= 0 & b <= 2) { train.Device.DoorCloseMode = (DoorMode)b; } break; case 10: if (a >= 0.0) { train.Device.DoorWidth = a; } break; case 11: if (a >= 0.0) { train.Device.DoorMaxTolerance = a; } break; } } i++; n++; } i--; break; case "#motor_p1": case "#motor_p2": case "#motor_b1": case "#motor_b2": { string section = lines[i].ToLowerInvariant(); i++; BVEMotorSoundTableEntry[] entries = new BVEMotorSoundTableEntry[800]; while (i < lines.Length && !lines[i].StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { if (n == entries.Length) { Array.Resize(ref entries, entries.Length << 1); } string u = lines[i] + ","; int k = 0; while (true) { int j = u.IndexOf(','); if (j == -1) { break; } string s = u.Substring(0, j).Trim(); u = u.Substring(j + 1); double a; if (double.TryParse(s, NumberStyles.Float, culture, out a)) { int b = (int)Math.Round(a); switch (k) { case 0: entries[n].SoundIndex = b >= 0 ? b : -1; break; case 1: entries[n].Pitch = (float)Math.Max(a, 0.0); break; case 2: entries[n].Gain = (float)Math.Max(a, 0.0); break; } } k++; } i++; n++; } Array.Resize(ref entries, n); i--; switch (section) { case "#motor_p1": motor.Tracks[(int)Motor.TrackInfo.Power1] = Motor.Track.EntriesToTrack(entries); break; case "#motor_p2": motor.Tracks[(int)Motor.TrackInfo.Power2] = Motor.Track.EntriesToTrack(entries); break; case "#motor_b1": motor.Tracks[(int)Motor.TrackInfo.Brake1] = Motor.Track.EntriesToTrack(entries); break; case "#motor_b2": motor.Tracks[(int)Motor.TrackInfo.Brake2] = Motor.Track.EntriesToTrack(entries); break; } } break; } } int numberOfCars = numberOfMotorCars + numberOfTrailerCars; bool[] isMotorCars = new bool[numberOfCars]; if (numberOfMotorCars == 1) { if (frontCarIsAMotorCar | numberOfTrailerCars == 0) { isMotorCars[0] = true; } else { isMotorCars[numberOfCars - 1] = true; } } else if (numberOfMotorCars == 2) { if (frontCarIsAMotorCar | numberOfTrailerCars == 0) { isMotorCars[0] = true; isMotorCars[numberOfCars - 1] = true; } else if (numberOfTrailerCars == 1) { isMotorCars[1] = true; isMotorCars[2] = true; } else { int i = (int)Math.Ceiling(0.25 * (numberOfCars - 1)); int j = (int)Math.Floor(0.75 * (numberOfCars - 1)); isMotorCars[i] = true; isMotorCars[j] = true; } } else if (numberOfMotorCars > 0) { if (frontCarIsAMotorCar) { isMotorCars[0] = true; double t = 1.0 + numberOfTrailerCars / (double)(numberOfMotorCars - 1); double r = 0.0; double x = 0.0; while (true) { double y = x + t - r; x = Math.Ceiling(y); r = x - y; int i = (int)x; if (i >= numberOfCars) { break; } isMotorCars[i] = true; } } else { isMotorCars[1] = true; double t = 1.0 + (numberOfTrailerCars - 1) / (double)(numberOfMotorCars - 1); double r = 0.0; double x = 1.0; while (true) { double y = x + t - r; x = Math.Ceiling(y); r = x - y; int i = (int)x; if (i >= numberOfCars) { break; } isMotorCars[i] = true; } } } foreach (bool isMotorCar in isMotorCars) { Car car = isMotorCar ? (Car) new MotorCar() : new TrailerCar(); car.Mass = isMotorCar ? motorCarMass : trailerCarMass; car.Length = lengthOfACar; car.Width = widthOfACar; car.Height = heightOfACar; car.CenterOfGravityHeight = centerOfGravityHeight; car.ExposedFrontalArea = exposedFrontalArea; car.UnexposedFrontalArea = unexposedFrontalArea; car.Performance = (Performance)performance.Clone(); car.Delay = (Delay)delay.Clone(); car.Move = (Move)move.Clone(); car.Brake = (Brake)brake.Clone(); car.Pressure = (Pressure)pressure.Clone(); if (isMotorCar) { ((MotorCar)car).Acceleration = (Acceleration)acceleration.Clone(); ((MotorCar)car).Motor = (Motor)motor.Clone(); } train.Cars.Add(car); } for (int i = 0; i < numberOfCars - 1; i++) { train.Couplers.Add(new Models.Trains.Coupler()); } }