public MSTSSteamLocomotiveViewer(Viewer viewer, MSTSSteamLocomotive car) : base(viewer, car) { // Now all the particle drawers have been setup, assign them textures based // on what emitters we know about. string steamTexture = viewer.Simulator.BasePath + @"\GLOBAL\TEXTURES\smokemain.ace"; foreach (var emitter in ParticleDrawers) { if (emitter.Key.ToLowerInvariant() == "cylindersfx") { Cylinders.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "cylinders2fx") { Cylinders2.AddRange(emitter.Value); car.Cylinder2SteamEffects = true; } // Not used in either MSTS or OR else if (emitter.Key.ToLowerInvariant() == "drainpipefx") // Drainpipe was not used in MSTS, and has no control { Drainpipe.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "injectors1fx") { Injectors1.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "injectors2fx") { Injectors2.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "compressorfx") { Compressor.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "generatorfx") { Generator.AddRange(emitter.Value); car.GeneratorSteamEffects = true; } else if (emitter.Key.ToLowerInvariant() == "safetyvalvesfx") { SafetyValves.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "stackfx") { Stack.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "whistlefx") { Whistle.AddRange(emitter.Value); } foreach (var drawer in emitter.Value) { drawer.Initialize(steamTexture); } } }
void RecordSteamPerformance() { MSTSSteamLocomotive steamloco = (MSTSSteamLocomotive)Viewer.PlayerLocomotive; float SteamspeedMpH = MpS.ToMpH(steamloco.SpeedMpS); if (SteamspeedMpH >= previousLoggedSteamSpeedMpH + 5) // Add a new record every time speed increases by 5 mph { previousLoggedSteamSpeedMpH = (float)(int)SteamspeedMpH; // Keep speed records close to whole numbers Logger.Data(MpS.FromMpS(Viewer.PlayerLocomotive.SpeedMpS, false).ToString("F0")); Logger.Data(S.ToM(steamloco.SteamPerformanceTimeS).ToString("F1")); Logger.Data(Viewer.PlayerLocomotive.ThrottlePercent.ToString("F0")); Logger.Data(Viewer.PlayerTrain.MUReverserPercent.ToString("F0")); Logger.Data(N.ToLbf(Viewer.PlayerLocomotive.MotiveForceN).ToString("F0")); Logger.Data(steamloco.IndicatedHorsePowerHP.ToString("F0")); Logger.Data(steamloco.DrawBarPullLbsF.ToString("F0")); Logger.Data(steamloco.DrawbarHorsePowerHP.ToString("F0")); Logger.Data(N.ToLbf(steamloco.LocomotiveCouplerForceN).ToString("F0")); Logger.Data(N.ToLbf(steamloco.LocoTenderFrictionForceN).ToString("F0")); Logger.Data(N.ToLbf(steamloco.TotalFrictionForceN).ToString("F0")); Logger.Data(Kg.ToTUK(steamloco.TrainLoadKg).ToString("F0")); Logger.Data(steamloco.BoilerPressurePSI.ToString("F0")); Logger.Data(steamloco.LogSteamChestPressurePSI.ToString("F0")); Logger.Data(steamloco.LogInitialPressurePSI.ToString("F0")); Logger.Data(steamloco.LogCutoffPressurePSI.ToString("F0")); Logger.Data(steamloco.LogReleasePressurePSI.ToString("F0")); Logger.Data(steamloco.LogBackPressurePSI.ToString("F0")); Logger.Data(steamloco.MeanEffectivePressurePSI.ToString("F0")); Logger.Data(steamloco.CurrentSuperheatTempF.ToString("F0")); Logger.Data(pS.TopH(steamloco.CylinderSteamUsageLBpS).ToString("F0")); Logger.Data(pS.TopH(steamloco.WaterConsumptionLbpS).ToString("F0")); Logger.Data(Kg.ToLb(pS.TopH(steamloco.FuelBurnRateSmoothedKGpS)).ToString("F0")); Logger.Data(steamloco.SuperheaterSteamUsageFactor.ToString("F2")); Logger.Data(steamloco.CumulativeCylinderSteamConsumptionLbs.ToString("F0")); Logger.Data(steamloco.CumulativeWaterConsumptionLbs.ToString("F0")); Logger.Data(steamloco.CutoffPressureDropRatio.ToString("F2")); Logger.Data(steamloco.HPCylinderMEPPSI.ToString("F0")); Logger.Data(steamloco.LogLPInitialPressurePSI.ToString("F0")); Logger.Data(steamloco.LogLPCutoffPressurePSI.ToString("F0")); Logger.Data(steamloco.LogLPReleasePressurePSI.ToString("F0")); Logger.Data(steamloco.LogLPBackPressurePSI.ToString("F0")); Logger.Data(steamloco.CutoffPressureDropRatio.ToString("F2")); Logger.Data(steamloco.LPCylinderMEPPSI.ToString("F0")); Logger.End(); } }
private void RecordSteamPerformance() { MSTSSteamLocomotive steamloco = viewer.PlayerLocomotive as MSTSSteamLocomotive; double steamspeedMpH = Speed.MeterPerSecond.ToMpH(steamloco.SpeedMpS); if (steamspeedMpH >= previousLoggedSteamSpeedMpH + 5) // Add a new record every time speed increases by 5 mph { previousLoggedSteamSpeedMpH = (int)steamspeedMpH; // Keep speed records close to whole numbers dataLog.Data($"{Speed.MeterPerSecond.FromMpS(steamloco.SpeedMpS, false):F0}"); dataLog.Data($"{Time.Second.ToM(steamloco.SteamPerformanceTimeS):F1}"); dataLog.Data($"{steamloco.ThrottlePercent:F0}"); dataLog.Data($"{steamloco.Train.MUReverserPercent:F0}"); dataLog.Data($"{Dynamics.Force.ToLbf(steamloco.MotiveForceN):F0}"); dataLog.Data($"{steamloco.IndicatedHorsePowerHP:F0}"); dataLog.Data($"{steamloco.DrawBarPullLbsF:F0}"); dataLog.Data($"{steamloco.DrawbarHorsePowerHP:F0}"); dataLog.Data($"{Dynamics.Force.ToLbf(steamloco.LocomotiveCouplerForceN):F0}"); dataLog.Data($"{Dynamics.Force.ToLbf(steamloco.LocoTenderFrictionForceN):F0}"); dataLog.Data($"{Dynamics.Force.ToLbf(steamloco.TotalFrictionForceN):F0}"); dataLog.Data($"{Mass.Kilogram.ToTonsUK(steamloco.TrainLoadKg):F0}"); dataLog.Data($"{steamloco.BoilerPressurePSI:F0}"); dataLog.Data($"{steamloco.LogSteamChestPressurePSI:F0}"); dataLog.Data($"{steamloco.LogInitialPressurePSI:F0}"); dataLog.Data($"{steamloco.LogCutoffPressurePSI:F0}"); dataLog.Data($"{steamloco.LogReleasePressurePSI:F0}"); dataLog.Data($"{steamloco.LogBackPressurePSI:F0}"); dataLog.Data($"{steamloco.MeanEffectivePressurePSI:F0}"); dataLog.Data($"{steamloco.CurrentSuperheatTempF:F0}"); dataLog.Data($"{Frequency.Periodic.ToHours(steamloco.CylinderSteamUsageLBpS):F0}"); dataLog.Data($"{Frequency.Periodic.ToHours(steamloco.WaterConsumptionLbpS):F0}"); dataLog.Data($"{Mass.Kilogram.ToLb(Frequency.Periodic.ToHours(steamloco.FuelBurnRateSmoothedKGpS)):F0}"); dataLog.Data($"{steamloco.SuperheaterSteamUsageFactor:F2}"); dataLog.Data($"{steamloco.CumulativeCylinderSteamConsumptionLbs:F0}"); dataLog.Data($"{steamloco.CumulativeWaterConsumptionLbs:F0}"); dataLog.Data($"{steamloco.CutoffPressureDropRatio:F0}"); dataLog.Data($"{steamloco.HPCylinderMEPPSI:F0}"); dataLog.Data($"{steamloco.LogLPInitialPressurePSI:F0}"); dataLog.Data($"{steamloco.LogLPCutoffPressurePSI:F0}"); dataLog.Data($"{steamloco.LogLPReleasePressurePSI:F0}"); dataLog.Data($"{steamloco.LogLPBackPressurePSI:F0}"); dataLog.Data($"{steamloco.CutoffPressureDropRatio:F0}"); dataLog.Data($"{steamloco.LPCylinderMEPPSI:F0}"); dataLog.EndLine(); } }
void RecordSteamPowerCurve() { MSTSSteamLocomotive loco = (MSTSSteamLocomotive)Viewer.PlayerLocomotive; float speedMpH = MpS.ToMpH(loco.SpeedMpS); if (speedMpH >= previousLoggedSpeedMpH + 1) // Add a new record every time speed increases by 1 mph { previousLoggedSpeedMpH = (float)(int)speedMpH; // Keep speed records close to whole numbers Logger.Data(speedMpH.ToString("F1")); float power = W.ToHp(loco.MotiveForceN * loco.SpeedMpS); Logger.Data(power.ToString("F1")); Logger.Data((Viewer.PlayerLocomotive as MSTSSteamLocomotive).ThrottlePercent.ToString("F0")); Logger.Data((Viewer.PlayerLocomotive as MSTSSteamLocomotive).Train.MUReverserPercent.ToString("F0")); Logger.End(); } }
private void RecordSteamPowerCurve() { MSTSSteamLocomotive steamloco = viewer.PlayerLocomotive as MSTSSteamLocomotive; double speedMpH = Speed.MeterPerSecond.ToMpH(steamloco.SpeedMpS); if (speedMpH >= previousLoggedSpeedMpH + 1) // Add a new record every time speed increases by 1 mph { previousLoggedSpeedMpH = (int)speedMpH; // Keep speed records close to whole numbers dataLog.Data($"{speedMpH:F1}"); double power = Dynamics.Power.ToHp(steamloco.MotiveForceN * steamloco.SpeedMpS); dataLog.Data($"{power:F1}"); dataLog.Data($"{steamloco.ThrottlePercent:F0}"); dataLog.Data($"{steamloco.Train.MUReverserPercent:F0}"); dataLog.EndLine(); } }
/// <summary> /// Retrieve a formatted list <see cref="ListLabel"/>s to be displayed as an in-browser Track Monitor. /// </summary> /// <param name="viewer">The Viewer to read train data from.</param> /// <returns>A list of <see cref="ListLabel"/>s, one per row of the popup.</returns> public static IEnumerable <ListLabel> TrainDrivingDisplayList(this Viewer viewer, bool normalTextMode = true) { bool useMetric = viewer.MilepostUnitsMetric; var labels = new List <ListLabel>(); void AddLabel(ListLabel label) { CheckLabel(ref label, normalTextMode); labels.Add(label); } void AddSeparator() => AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Sprtr"), }); TrainCar trainCar = viewer.PlayerLocomotive; Train train = trainCar.Train; string trainBrakeStatus = trainCar.GetTrainBrakeStatus(); string dynamicBrakeStatus = trainCar.GetDynamicBrakeStatus(); string engineBrakeStatus = trainCar.GetEngineBrakeStatus(); MSTSLocomotive locomotive = (MSTSLocomotive)trainCar; string locomotiveStatus = locomotive.GetStatus(); bool combinedControlType = locomotive.CombinedControlType == MSTSLocomotive.CombinedControl.ThrottleDynamic; bool showMUReverser = Math.Abs(train.MUReverserPercent) != 100f; bool showRetainers = train.RetainerSetting != RetainerSetting.Exhaust; bool stretched = train.Cars.Count > 1 && train.NPull == train.Cars.Count - 1; bool bunched = !stretched && train.Cars.Count > 1 && train.NPush == train.Cars.Count - 1; Train.TrainInfo trainInfo = train.GetTrainInfo(); // First Block // Client and server may have a time difference. AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Time"), LastCol = FormatStrings.FormatTime(viewer.Simulator.ClockTime + (MultiPlayer.MPManager.IsClient() ? MultiPlayer.MPManager.Instance().serverTimeDifference : 0)), }); if (viewer.Simulator.IsReplaying) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Replay"), LastCol = FormatStrings.FormatTime(viewer.Log.ReplayEndsAt - viewer.Simulator.ClockTime), }); } Color speedColor; if (locomotive.SpeedMpS < trainInfo.allowedSpeedMpS - 1f) { speedColor = Color.White; } else if (locomotive.SpeedMpS < trainInfo.allowedSpeedMpS) { speedColor = Color.PaleGreen; } else if (locomotive.SpeedMpS < trainInfo.allowedSpeedMpS + 5f) { speedColor = Color.Orange; } else { speedColor = Color.OrangeRed; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Speed"), LastCol = $"{FormatStrings.FormatSpeedDisplay(locomotive.SpeedMpS, useMetric)}{ColorCode[speedColor]}", }); // Gradient info if (normalTextMode) { float gradient = -trainInfo.currentElevationPercent; const float minSlope = 0.00015f; string gradientIndicator; if (gradient < -minSlope) { gradientIndicator = $"{gradient:F1}%{Symbols.GradientDown}{ColorCode[Color.LightSkyBlue]}"; } else if (gradient > minSlope) { gradientIndicator = $"{gradient:F1}%{Symbols.GradientUp}{ColorCode[Color.Yellow]}"; } else { gradientIndicator = $"{gradient:F1}%"; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Gradient"), LastCol = gradientIndicator, }); } // Separator AddSeparator(); // Second block // Direction { UserCommand?reverserCommand = GetPressedKey(UserCommand.ControlBackwards, UserCommand.ControlForwards); string reverserKey; bool moving = Math.Abs(trainCar.SpeedMpS) > 1; bool nonSteamEnd = trainCar.EngineType != TrainCar.EngineTypes.Steam && trainCar.Direction == Direction.N && (trainCar.ThrottlePercent >= 1 || moving); bool steamEnd = locomotive is MSTSSteamLocomotive steamLocomotive2 && steamLocomotive2.CutoffController.MaximumValue == Math.Abs(train.MUReverserPercent / 100); if (reverserCommand != null && (nonSteamEnd || steamEnd)) { reverserKey = Symbols.End + ColorCode[Color.Yellow]; } else if (reverserCommand == UserCommand.ControlBackwards) { reverserKey = Symbols.ArrowDown + ColorCode[Color.Yellow]; } else if (reverserCommand == UserCommand.ControlForwards) { reverserKey = Symbols.ArrowUp + ColorCode[Color.Yellow]; } else { reverserKey = ""; } string reverserIndicator = showMUReverser ? $"{Round(Math.Abs(train.MUReverserPercent))}% " : ""; AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString(locomotive.EngineType == TrainCar.EngineTypes.Steam ? "Reverser" : "Direction"), LastCol = $"{reverserIndicator}{FormatStrings.Catalog.GetParticularString("Reverser", GetStringAttribute.GetPrettyName(locomotive.Direction))}", KeyPressed = reverserKey, SymbolCol = reverserKey, }); } // Throttle { UserCommand?throttleCommand = GetPressedKey(UserCommand.ControlThrottleDecrease, UserCommand.ControlThrottleIncrease); string throttleKey; bool upperLimit = throttleCommand == UserCommand.ControlThrottleIncrease && locomotive.ThrottleController.MaximumValue == trainCar.ThrottlePercent / 100; bool lowerLimit = throttleCommand == UserCommand.ControlThrottleDecrease && trainCar.ThrottlePercent == 0; if (locomotive.DynamicBrakePercent < 1 && (upperLimit || lowerLimit)) { throttleKey = Symbols.End + ColorCode[Color.Yellow]; } else if (locomotive.DynamicBrakePercent > -1) { throttleKey = Symbols.EndLower + ColorCode[Color.Yellow]; } else if (throttleCommand == UserCommand.ControlThrottleIncrease) { throttleKey = Symbols.ArrowUp + ColorCode[Color.Yellow]; } else if (throttleCommand == UserCommand.ControlThrottleDecrease) { throttleKey = Symbols.ArrowDown + ColorCode[Color.Yellow]; } else { throttleKey = ""; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString(locomotive is MSTSSteamLocomotive ? "Regulator" : "Throttle"), LastCol = $"{Round(locomotive.ThrottlePercent)}%", KeyPressed = throttleKey, SymbolCol = throttleKey, }); } // Cylinder Cocks if (locomotive is MSTSSteamLocomotive steamLocomotive) { string cocksIndicator, cocksKey; if (steamLocomotive.CylinderCocksAreOpen) { cocksIndicator = Viewer.Catalog.GetString("Open") + ColorCode[Color.Orange]; cocksKey = Symbols.ArrowToRight + ColorCode[Color.Yellow]; } else { cocksIndicator = Viewer.Catalog.GetString("Closed") + ColorCode[Color.White]; cocksKey = ""; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Cylinder cocks"), LastCol = cocksIndicator, KeyPressed = cocksKey, SymbolCol = cocksKey, }); } // Sander if (locomotive.GetSanderOn()) { bool sanderBlocked = locomotive.AbsSpeedMpS > locomotive.SanderSpeedOfMpS; string sanderKey = Symbols.ArrowToRight + ColorCode[Color.Yellow]; AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Sander"), LastCol = sanderBlocked ? Viewer.Catalog.GetString("Blocked") + ColorCode[Color.OrangeRed] : Viewer.Catalog.GetString("On") + ColorCode[Color.Orange], KeyPressed = sanderKey, SymbolCol = sanderKey, }); } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Sander"), LastCol = Viewer.Catalog.GetString("Off"), KeyPressed = "", SymbolCol = "", }); } AddSeparator(); // Train Brake multi-lines // TODO: A better algorithm //var brakeStatus = Owner.Viewer.PlayerLocomotive.GetTrainBrakeStatus(); //steam loco string brakeInfoValue = ""; int index = 0; if (trainBrakeStatus.Contains(Viewer.Catalog.GetString("EQ"))) { string brakeKey; switch (GetPressedKey(UserCommand.ControlTrainBrakeDecrease, UserCommand.ControlTrainBrakeIncrease)) { case UserCommand.ControlTrainBrakeDecrease: brakeKey = Symbols.ArrowDown + ColorCode[Color.Yellow]; break; case UserCommand.ControlTrainBrakeIncrease: brakeKey = Symbols.ArrowUp + ColorCode[Color.Yellow]; break; default: brakeKey = ""; break; } brakeInfoValue = trainBrakeStatus.Substring(0, trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("EQ"))).TrimEnd(); AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Train brake"), LastCol = $"{brakeInfoValue}{ColorCode[Color.Cyan]}", KeyPressed = brakeKey, SymbolCol = brakeKey, }); index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("EQ")); brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("BC")) - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); if (trainBrakeStatus.Contains(Viewer.Catalog.GetString("EOT"))) { int indexOffset = Viewer.Catalog.GetString("EOT").Length + 1; index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("BC")); brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("EOT")) - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("EOT")) + indexOffset; brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.Length - index).TrimStart(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); } else { index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("BC")); brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.Length - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); } } else if (trainBrakeStatus.Contains(Viewer.Catalog.GetString("Lead"))) { int indexOffset = Viewer.Catalog.GetString("Lead").Length + 1; brakeInfoValue = trainBrakeStatus.Substring(0, trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("Lead"))).TrimEnd(); AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Train brake"), LastCol = $"{brakeInfoValue}{ColorCode[Color.Cyan]}", }); index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("Lead")) + indexOffset; if (trainBrakeStatus.Contains(Viewer.Catalog.GetString("EOT"))) { brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("EOT")) - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("EOT")) + indexOffset; brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.Length - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); } else { brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.Length - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); } } else if (trainBrakeStatus.Contains(Viewer.Catalog.GetString("BC"))) { brakeInfoValue = trainBrakeStatus.Substring(0, trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("BC"))).TrimEnd(); AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Train brake"), LastCol = $"{brakeInfoValue}{ColorCode[Color.Cyan]}", }); index = trainBrakeStatus.IndexOf(Viewer.Catalog.GetString("BC")); brakeInfoValue = trainBrakeStatus.Substring(index, trainBrakeStatus.Length - index).TrimEnd(); AddLabel(new ListLabel { LastCol = brakeInfoValue, }); } if (showRetainers) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Retainers"), LastCol = $"{train.RetainerPercent} {Viewer.Catalog.GetString(GetStringAttribute.GetPrettyName(train.RetainerSetting))}", }); } if (engineBrakeStatus.Contains(Viewer.Catalog.GetString("BC"))) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Engine brake"), LastCol = engineBrakeStatus.Substring(0, engineBrakeStatus.IndexOf("BC")) + ColorCode[Color.Cyan], }); index = engineBrakeStatus.IndexOf(Viewer.Catalog.GetString("BC")); brakeInfoValue = engineBrakeStatus.Substring(index, engineBrakeStatus.Length - index).TrimEnd(); AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString(""), LastCol = $"{brakeInfoValue}{ColorCode[Color.White]}", }); } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Engine brake"), LastCol = $"{engineBrakeStatus}{ColorCode[Color.Cyan]}", }); } if (dynamicBrakeStatus != null && locomotive.IsLeadLocomotive()) { if (locomotive.DynamicBrakePercent >= 0) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Dynamic brake"), LastCol = locomotive.DynamicBrake ? dynamicBrakeStatus : Viewer.Catalog.GetString("Setup") + ColorCode[Color.Cyan], }); } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Dynamic brake"), LastCol = Viewer.Catalog.GetString("Off"), }); } } AddSeparator(); if (locomotiveStatus != null) { foreach (string data in locomotiveStatus.Split('\n').Where((string d) => !string.IsNullOrWhiteSpace(d))) { string[] parts = data.Split(new string[] { " = " }, 2, StringSplitOptions.None); string keyPart = parts[0]; string valuePart = parts?[1]; if (Viewer.Catalog.GetString(keyPart).StartsWith(Viewer.Catalog.GetString("Boiler pressure"))) { MSTSSteamLocomotive steamLocomotive2 = (MSTSSteamLocomotive)locomotive; float bandUpper = steamLocomotive2.PreviousBoilerHeatOutBTUpS * 1.025f; // find upper bandwidth point float bandLower = steamLocomotive2.PreviousBoilerHeatOutBTUpS * 0.975f; // find lower bandwidth point - gives a total 5% bandwidth string heatIndicator; if (steamLocomotive2.BoilerHeatInBTUpS > bandLower && steamLocomotive2.BoilerHeatInBTUpS < bandUpper) { heatIndicator = $"{Symbols.SmallDiamond}{ColorCode[Color.White]}"; } else if (steamLocomotive2.BoilerHeatInBTUpS < bandLower) { heatIndicator = $"{Symbols.SmallArrowDown}{ColorCode[Color.Cyan]}"; } else if (steamLocomotive2.BoilerHeatInBTUpS > bandUpper) { heatIndicator = $"{Symbols.SmallArrowUp}{ColorCode[Color.Orange]}"; } else { heatIndicator = ColorCode[Color.White]; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Boiler pressure"), LastCol = Viewer.Catalog.GetString(valuePart), SymbolCol = heatIndicator, }); } else if (!normalTextMode && Viewer.Catalog.GetString(parts[0]).StartsWith(Viewer.Catalog.GetString("Fuel levels"))) { AddLabel(new ListLabel { FirstCol = keyPart.EndsWith("?") || keyPart.EndsWith("!") ? Viewer.Catalog.GetString(keyPart.Substring(0, keyPart.Length - 3)) : Viewer.Catalog.GetString(keyPart), LastCol = valuePart.Length > 1 ? Viewer.Catalog.GetString(valuePart.Replace(" ", string.Empty)) : "", }); } else if (keyPart.StartsWith(Viewer.Catalog.GetString("Gear"))) { string gearKey; switch (GetPressedKey(UserCommand.ControlGearDown, UserCommand.ControlGearUp)) { case UserCommand.ControlGearDown: gearKey = Symbols.ArrowDown + ColorCode[Color.Yellow]; break; case UserCommand.ControlGearUp: gearKey = Symbols.ArrowUp + ColorCode[Color.Yellow]; break; default: gearKey = ""; break; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString(keyPart), LastCol = valuePart != null ? Viewer.Catalog.GetString(valuePart) : "", KeyPressed = gearKey, SymbolCol = gearKey, }); } else if (parts.Contains(Viewer.Catalog.GetString("Pantographs"))) { string pantoKey; switch (GetPressedKey(UserCommand.ControlPantograph1)) { case UserCommand.ControlPantograph1: string arrow = parts[1].StartsWith(Viewer.Catalog.GetString("Up")) ? Symbols.ArrowUp : Symbols.ArrowDown; pantoKey = arrow + ColorCode[Color.Yellow]; break; default: pantoKey = ""; break; } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString(keyPart), LastCol = valuePart != null ? Viewer.Catalog.GetString(valuePart) : "", KeyPressed = pantoKey, SymbolCol = pantoKey, }); } else if (parts.Contains(Viewer.Catalog.GetString("Engine"))) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString(keyPart), LastCol = valuePart != null ? $"{Viewer.Catalog.GetString(valuePart)}{ColorCode[Color.White]}" : "", }); } else { AddLabel(new ListLabel { FirstCol = keyPart.EndsWith("?") || keyPart.EndsWith("!") ? Viewer.Catalog.GetString(keyPart.Substring(0, keyPart.Length - 3)) : Viewer.Catalog.GetString(keyPart), LastCol = valuePart != null ? Viewer.Catalog.GetString(valuePart) : "", }); } } } AddSeparator(); if (normalTextMode) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("FPS"), LastCol = $"{Math.Floor(viewer.RenderProcess.FrameRate.SmoothedValue)}", }); } // Messages // Autopilot bool autopilot = locomotive.Train.TrainType == Train.TRAINTYPE.AI_PLAYERHOSTING; AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Autopilot"), LastCol = autopilot ? Viewer.Catalog.GetString("On") + ColorCode[Color.Yellow] : Viewer.Catalog.GetString("Off"), }); // Grate limit if (locomotive is MSTSSteamLocomotive steamLocomotive1) { if (steamLocomotive1.IsGrateLimit && steamLocomotive1.GrateCombustionRateLBpFt2 > steamLocomotive1.GrateLimitLBpFt2) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Grate limit"), LastCol = Viewer.Catalog.GetString("Exceeded") + ColorCode[Color.OrangeRed], }); } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Grate limit") + ColorCode[Color.Black], LastCol = Viewer.Catalog.GetString("Normal") + ColorCode[Color.Black], }); } } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Grate limit") + ColorCode[Color.Black], LastCol = Viewer.Catalog.GetString("-") + ColorCode[Color.Black], }); } // Wheel if (train.IsWheelSlip) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Wheel"), LastCol = Viewer.Catalog.GetString("slip") + ColorCode[Color.OrangeRed], }); } else if (train.IsWheelSlipWarninq) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Wheel"), LastCol = Viewer.Catalog.GetString("slip warning") + ColorCode[Color.Yellow], }); } else if (train.IsBrakeSkid) { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Wheel"), LastCol = Viewer.Catalog.GetString("skid") + ColorCode[Color.OrangeRed], }); } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Wheel") + ColorCode[Color.Black], LastCol = Viewer.Catalog.GetString("Normal") + ColorCode[Color.Black], }); } // Doors var wagon = (MSTSWagon)locomotive; if (wagon.DoorLeftOpen || wagon.DoorRightOpen) { var status = new List <string>(); bool flipped = locomotive.GetCabFlipped(); if (wagon.DoorLeftOpen) { status.Add(Viewer.Catalog.GetString(Viewer.Catalog.GetString(flipped ? "Right" : "Left"))); } if (wagon.DoorRightOpen) { status.Add(Viewer.Catalog.GetString(Viewer.Catalog.GetString(flipped ? "Left" : "Right"))); } AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Doors open"), LastCol = string.Join(" ", status) + ColorCode[locomotive.AbsSpeedMpS > 0.1f ? Color.OrangeRed : Color.Yellow], }); } else { AddLabel(new ListLabel { FirstCol = Viewer.Catalog.GetString("Doors open") + ColorCode[Color.Black], LastCol = Viewer.Catalog.GetString("Closed") + ColorCode[Color.Black], }); } AddLabel(new ListLabel()); return(labels); }
public static TrainCar Load(Simulator simulator, string wagFilePath, bool initialize = true) { GenericWAGFile wagFile = SharedGenericWAGFileManager.Get(wagFilePath); TrainCar car; if (wagFile.OpenRails != null && wagFile.OpenRails.DLL != null) { // wag file specifies an external DLL try { // TODO search the path list string wagFolder = Path.GetDirectoryName(wagFilePath); string dllPath = FindTrainCarPlugin(wagFolder, wagFile.OpenRails.DLL); Assembly customDLL = Assembly.LoadFrom(dllPath); object[] args = new object[] { wagFilePath }; car = (TrainCar)customDLL.CreateInstance("ORTS.CustomCar", true, BindingFlags.CreateInstance, null, args, null, null); return(car); } catch (Exception error) { Trace.WriteLine(new FileLoadException(wagFile.OpenRails.DLL, error)); // on error, fall through and try loading without the custom dll } } if (!wagFile.IsEngine) { // its an ordinary MSTS wagon car = new MSTSWagon(simulator, wagFilePath); } else { // its an ordinary MSTS engine of some type. if (wagFile.Engine.Type == null) { throw new InvalidDataException(wagFilePath + "\r\n\r\nEngine type missing"); } switch (wagFile.Engine.Type.ToLower()) { // TODO complete parsing of proper car types case "electric": car = new MSTSElectricLocomotive(simulator, wagFilePath); break; case "steam": car = new MSTSSteamLocomotive(simulator, wagFilePath); break; case "diesel": car = new MSTSDieselLocomotive(simulator, wagFilePath); break; case "control": car = new MSTSControlTrailerCar(simulator, wagFilePath); break; default: throw new InvalidDataException(wagFilePath + "\r\n\r\nUnknown engine type: " + wagFile.Engine.Type); } } MSTSWagon wagon = car as MSTSWagon; if (car != null) { wagon.Load(); if (initialize) { wagon.Initialize(); } } return(car); }
public MSTSSteamLocomotiveViewer(Viewer viewer, MSTSSteamLocomotive car) : base(viewer, car) { // Now all the particle drawers have been setup, assign them textures based // on what emitters we know about. string steamTexture = viewer.Simulator.RouteFolder.ContentFolder.TextureFile("smokemain.ace"); foreach (var emitter in ParticleDrawers) { if (emitter.Key.ToLowerInvariant() == "cylindersfx") { Cylinders.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "cylinders2fx") { Cylinders2.AddRange(emitter.Value); car.Cylinder2SteamEffects = true; } else if (emitter.Key.ToLowerInvariant() == "blowdownfx") { Blowdown.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "drainpipefx") // Drainpipe was not used in MSTS, and has no control set up for it { Drainpipe.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "injectors1fx") { Injectors1.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "injectors2fx") { Injectors2.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "smallejectorfx") { SmallEjector.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "largeejectorfx") { LargeEjector.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "compressorfx") { Compressor.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "generatorfx") { Generator.AddRange(emitter.Value); car.GeneratorSteamEffects = true; } else if (emitter.Key.ToLowerInvariant() == "safetyvalvesfx") { SafetyValves.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "stackfx") { Stack.AddRange(emitter.Value); } else if (emitter.Key.ToLowerInvariant() == "whistlefx") { Whistle.AddRange(emitter.Value); } foreach (var drawer in emitter.Value) { drawer.Initialize(steamTexture); } } }