public static void Postfix(LocoControllerBase __instance, float __result) { if (!AppUtil.IsPaused) { tractiveEffortProvider.SetValue(__instance.train, new Force(__result, Newton)); indicatedPowerProvider.SetValue(__instance.train, new Force(__result, Newton) * new Velocity(__instance.GetSpeedKmH(), KilometersPerHour)); } }
public static void Postfix(LocoControllerBase __instance, float __result) { if (!AppUtil.IsPaused) { tractiveEffortProvider.SetValue(__instance.train, __result); indicatedPowerProvider.SetValue(__instance.train, __result * __instance.GetSpeedKmH() / 3.6f); } }
static void Postfix(LocoControllerBase __instance) { if (__instance is LocoControllerShunter) { ShunterLocoSimulation sim = (ShunterLocoSimulation)Helper.Get(__instance, "sim"); LocoControllerShunter_Awake_Patch.dict.Remove(sim); } }
/// <summary> /// Handle player car change events /// </summary> /// <param name="obj">New car (can be null if leaving a car)</param> private static void PlayerManager_CarChanged(TrainCar obj) { if (obj != null) { LocoControllerBase loco; try { loco = obj.GetComponent <LocoControllerBase>(); } catch (Exception ex) { WarnMessage($"Car lacks loco. Error: {ex.Message}"); return; } if (Main.settings.KeylessEntryAutostart) { //Keyless entry only for the diesel locos if (loco is LocoControllerDiesel || loco is LocoControllerShunter) { var l1 = loco as LocoControllerDiesel; var l2 = loco as LocoControllerShunter; if (l1 != null) { l1.SetEngineRunning(true); } if (l2 != null) { l2.SetEngineRunning(true); } LogMessage("Started current loco"); } } CurrentLoco = loco; } else { //Shuts down a loco if it's not being used if (CurrentLoco != null) { if (ShouldPerformAutoShutdown(CurrentLoco)) { LogMessage("Shutting down current loco"); var Shunter = CurrentLoco as LocoControllerShunter; var Diesel = CurrentLoco as LocoControllerDiesel; if (Shunter != null) { Shunter.SetEngineRunning(false); } if (Diesel != null) { Diesel.SetEngineRunning(false); } } } CurrentLoco = null; } }
/// <summary> /// Stop the mod /// </summary> public static void Stop() { if (init) { PlayerManager.CarChanged -= PlayerManager_CarChanged; init = false; CurrentLoco = null; LogMessage($"Mod stopped"); } }
// Need to know when we have grabbed a Locomotive Remote // Actual Grab Handlers static void OnItemGrabbedRight(InventoryItemSpec iis) { LocomotiveRemoteController lrc = iis?.GetComponent <LocomotiveRemoteController>(); if (lrc != null) { LocoControllerBase locoController = (LocoControllerBase)typeof(LocomotiveRemoteController).GetField("pairedLocomotive", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(lrc); remoteCar = locoController?.GetComponent <TrainCar>(); } }
private static void Postfix(LocoControllerBase __instance, ref float __result) { if (NetworkManager.IsClient() && __instance.train.rb.isKinematic) { NetworkTrainPosSync networking = __instance.GetComponent <NetworkTrainPosSync>(); if (networking) { __result = networking.velocity.magnitude * 3.6f; } } }
public static void ExportLocoControllerCurves(CommandArg[] args) { if (Terminal.IssuedError) { return; } string name = args[0].String; if (Enum.TryParse(name, out TrainCarType carType)) { GameObject prefab = CarTypes.GetCarPrefab(carType); if (!prefab) { Debug.LogError($"CarType {name} has missing prefab"); return; } LocoControllerBase locoController = prefab.GetComponent <LocoControllerBase>(); if (!locoController) { Debug.LogWarning($"CarType {name} prefab does not have a loco controller"); return; } var props = new JObject(); // brake & traction JObject brakeCurve = ComponentsToJson.AnimationCurve(locoController.brakePowerCurve); props.Add("brakePowerCurve", brakeCurve); if (locoController is LocoControllerDiesel lcd) { var tractionCurve = ComponentsToJson.AnimationCurve(lcd.tractionTorqueCurve); props.Add("tractionTorqueCurve", tractionCurve); } else if (locoController is LocoControllerSteam lcs) { var tractionCurve = ComponentsToJson.AnimationCurve(lcs.tractionTorqueCurve); props.Add("tractionTorqueCurve", tractionCurve); } else if (locoController is LocoControllerShunter lcShunt) { var tractionCurve = ComponentsToJson.AnimationCurve(lcShunt.tractionTorqueCurve); props.Add("tractionTorqueCurve", tractionCurve); } // driving force props.Add("drivingForce", ComponentsToJson.DrivingForce(locoController.drivingForce)); GameObjectDumper.SendJsonToFile(name, "loco_curves", props); } }
static void Postfix(LocoControllerBase __instance, float nextTargetIndependentBrake) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (Main.remoteCar) { targetCar = Main.remoteCar; trainset = targetCar.trainset; } else if (PlayerManager.Car != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } for (int i = 0; i < trainset.cars.Count; i++) { TrainCar car = trainset.cars[i]; if (targetCar.Equals(car)) { continue; } if (car.carType == TrainCarType.LocoShunter) { LocoControllerShunter locoController = car.GetComponent <LocoControllerShunter>(); if (locoController) { locoController.SetIndependentBrake(nextTargetIndependentBrake); } } else if (car.carType == TrainCarType.LocoDiesel) { LocoControllerDiesel locoController = car.GetComponent <LocoControllerDiesel>(); if (locoController) { locoController.SetIndependentBrake(nextTargetIndependentBrake); } } } }
/// <summary> /// Determines whether this locomotive is eligible for automatic shutdown on player exit /// </summary> /// <param name="Loco">Locomotive</param> /// <returns>true, if should be shut down</returns> private static bool ShouldPerformAutoShutdown(LocoControllerBase Loco) { var s = Main.settings.ShutdownOptions; if (s == null) { s = new AutomaticShutdownOptions(); } //Don't do anything if this object is not present if (Loco == null) { WarnMessage("ShouldPerformAutoShutdown argument is <null> but should not be"); return(false); } //Don't shut down if cars are coupled if (s.NoCarsCoupled && (Loco.GetNumberOfCarsInFront() > 0 || Loco.GetNumberOfCarsInRear() > 0)) { return(false); } //Don't shut down if a coupler is in range if (s.NoCarsInCouplingRange && Loco.IsCouplerInRange(LocoControllerBase.COUPLING_RANGE)) { return(false); } //Don't shut down if rolling if (s.MustBeStationary && Math.Abs(Loco.GetSpeedKmH()) >= 1.0f) { return(false); } //Don't shut down if the reverser is not centered if (s.ReverserCentered && Math.Abs(Loco.reverser) >= 0.1f) { return(false); } //Don't shut down if independent brake not at least 90% applied if (s.IndependentBrakesApplied && Loco.independentBrake < 0.9f) { return(false); } //Don't shut down if remote controlled if (s.RemoteControlDisconnected && Loco.IsRemoteControlled()) { return(false); } //All checks passed return(true); }
static void Postfix(LocoControllerBase __instance) { // use switch on fireman's side of cab instead of reverser for steam loco if (__instance.train.carType == TrainCarType.LocoSteamHeavy) { return; } LocoLights locoLights = __instance.train.transform.gameObject.GetComponent <LocoLights>(); if (locoLights == null) { return; } locoLights.SetDirection(__instance.reverser); }
static void Postfix(LocoControllerBase __instance, float nextTargetIndependentBrake) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (PlayerManager.Car != null && PlayerManager.Car.trainset != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } List <TrainCar> trainsetCars = trainset.cars; for (int i = 0; i < trainsetCars.Count; i++) { TrainCar car = trainsetCars[i]; if (targetCar.Equals(car)) { continue; } if (car.carType == TrainCarType.LocoSteamHeavy) { LocoControllerSteam steamController = car.GetComponent <LocoControllerSteam>(); if (steamController) { steamController.SetIndependentBrake(nextTargetIndependentBrake); } } } }
static void Postfix(LocoControllerDiesel __instance, float position) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (Main.remoteCar) { targetCar = Main.remoteCar; trainset = targetCar.trainset; } else if (PlayerManager.Car != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } List <TrainCar> trainsetCars = trainset.cars; for (int i = 0; i < trainsetCars.Count; i++) { TrainCar car = trainsetCars[i]; if (targetCar.Equals(car)) { continue; } LocoControllerBase locoController = null; if (car.carType == TrainCarType.LocoShunter) { locoController = car.GetComponent <LocoControllerShunter>(); } else if (car.carType == TrainCarType.LocoDiesel) { locoController = car.GetComponent <LocoControllerDiesel>(); } if (locoController != null) { if (GetCarsBehind(targetCar).Contains(car)) { if (GetCarsInFrontOf(car).Contains(targetCar)) { locoController.SetReverser(position); } else { locoController.SetReverser(position * -1f); } } else if (GetCarsInFrontOf(targetCar).Contains(car)) { if (GetCarsBehind(car).Contains(targetCar)) { locoController.SetReverser(position); } else { locoController.SetReverser(position * -1f); } } } } }
public LocoBase([NotNull] LocoControllerBase inner) { _inner = inner; }
protected override void Init() { base.Init(); _controller = GetComponent <LocoControllerBase>(); }
static void OnUpdate(UnityModManager.ModEntry mod, float delta) { // Can we set/unset UnityModManager.ModEntry.OnUpdate dynamically instead? if (!mod.Enabled) { return; } if (!listenersSetup) { // Gotta wait until we are loaded until registering the listeners if (LoadingScreenManager.IsLoading || !WorldStreamingInit.IsLoaded || !InventoryStartingItems.itemsLoaded) { return; } Grabber grab = PlayerManager.PlayerTransform.GetComponentInChildren <Grabber>(); grab.Grabbed += OnItemGrabbedRightNonVR; grab.Released += OnItemUngrabbedRightNonVR; SingletonBehaviour <Inventory> .Instance.ItemAddedToInventory += OnItemAddedToInventory; mod.Logger.Log("Listeners have been set up."); listenersSetup = true; } // For some reason the axis defaults to 50% on loss of focus. Stop any inputs when that happens hasFocusPrev = hasFocus; hasFocus = Application.isFocused; if (hasFocus) { // Get remote or local loco LocoControllerBase locoController = null; if (HoldingLocoRoCo != null) { // Go get some private fields from the currently held locomotive remote bool isPoweredOn = (bool)typeof(LocomotiveRemoteController).GetField("isPoweredOn", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(HoldingLocoRoCo);; float lostSignalSecondsLeft = (float)typeof(LocomotiveRemoteController).GetField("lostSignalSecondsLeft", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(HoldingLocoRoCo); // Implement the logic for understanding if the pairedLocomotive is valid. // This is normally done in the LocomotiveRemoteController.Transmit method but is easier to do it here so we can re-use the analogue input logic. if (isPoweredOn && lostSignalSecondsLeft == 0f) { locoController = (LocoControllerBase)typeof(LocomotiveRemoteController).GetField("pairedLocomotive", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(HoldingLocoRoCo); } } else { locoController = PlayerManager.Car?.GetComponent <LocoControllerBase>(); } // Do the actual updating if (locoController != null) { throttleInput.SetItem(config.Throttle, locoController.SetThrottle); reverserInput.SetItem(config.Reverser, locoController.SetReverser); trainBrakeInput.SetItem(config.TrainBrake, locoController.SetBrake); independentBrakeInput.SetItem(config.IndependentBrake, locoController.SetIndependentBrake); if (locoController.GetType().Name.Equals("LocoControllerSteam")) { // All the steam loco stuff really doesnt like being set // Visuals dont update but the logic is correct ;( LocoControllerSteam locoControllerSteam = locoController as LocoControllerSteam; // Whistle resets every sim tick so just override it WhistleInput.SetItem(config.Whistle, locoControllerSteam.SetWhistle, 0f); fireDoorInput.SetItem(config.FireDoor, locoControllerSteam.SetFireDoorOpen); InjectorInput.SetItem(config.Injector, locoControllerSteam.SetInjector); DraftInput.SetItem(config.Draft, locoControllerSteam.SetDraft); BlowerInput.SetItem(config.Blower, locoControllerSteam.SetBlower); SanderValveInput.SetItem(config.SanderValve, locoControllerSteam.SetSanderValve); SteamReleaseInput.SetItem(config.SteamRelease, locoControllerSteam.SetSteamReleaser); WaterDumpInput.SetItem(config.WaterDump, locoControllerSteam.SetWaterDump); } } } }
static void Postfix(LocoControllerBase __instance, float __result) { tractiveEffortProvider.SetValue(__instance.train, __result); }
public void ListenToTrainInputEvents() { if (!loco.IsLoco && isAlreadyListening) { return; } if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen to base loco controller"); } baseController = loco.GetComponent <LocoControllerBase>(); if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen throttle change on base loco controller"); } baseController.ThrottleUpdated += OnTrainThrottleChanged; if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen brake change on base loco controller"); } baseController.BrakeUpdated += OnTrainBrakeChanged; if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen indepBrake change on base loco controller"); } baseController.IndependentBrakeUpdated += OnTrainIndependentBrakeChanged; if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen reverser change on base loco controller"); } baseController.ReverserUpdated += OnTrainReverserStateChanged; if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen sander change on base loco controller"); } baseController.SandersUpdated += OnTrainSanderChanged; if (loco.logicCar != null) { Main.Log($"[{loco.ID}] Listen to specific train events"); } switch (loco.carType) { case TrainCarType.LocoShunter: ShunterDashboardControls shunterDashboard = loco.interior.GetComponentInChildren <ShunterDashboardControls>(); FuseBoxPowerController fuseBox = shunterDashboard.fuseBoxPowerController; for (int i = 0; i < fuseBox.sideFusesObj.Length; i++) { ToggleSwitchBase sideFuse = fuseBox.sideFusesObj[i].GetComponent <ToggleSwitchBase>(); switch (i) { case 0: sideFuse.ValueChanged += OnTrainSideFuse_1Changed; break; case 1: sideFuse.ValueChanged += OnTrainSideFuse_2Changed; break; } } fuseBox.mainFuseObj.GetComponent <ToggleSwitchBase>().ValueChanged += OnTrainMainFuseChanged; shunterDashboard.hornObj.GetComponent <ControlImplBase>().ValueChanged += ShunterHornUsed; SingletonBehaviour <CoroutineManager> .Instance.Run(RotaryAmplitudeCheckerStartListen(fuseBox)); break; } isAlreadyListening = true; }
private void OnGUI() { Color defaultColor = GUI.color; if (Instance == null) { return; } GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); // row spacer GUILayout.BeginVertical(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.MaxWidth(1920)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); // row spacer end // row last GUILayout.BeginVertical(); // stats box GUILayout.BeginVertical(GUI.skin.box, GUILayout.Width(200)); if (Instance.MasterLoco != null) { GUILayout.BeginHorizontal(); GUILayout.Label($"Master [{Instance.MasterLoco.ID}]", GUILayout.Width(150)); GUILayout.EndHorizontal(); LocoControllerBase masterBase = Instance.MasterLoco.GetComponent <LocoControllerBase>(); GUILayout.BeginHorizontal(); GUILayout.Label("Throttle", GUILayout.Width(150)); GUILayout.Label(masterBase.throttle.ToString("n2")); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label($"Reverser [{((masterBase.reverser > 0) ? "FWD" : (masterBase.reverser < 0) ? "BWD" : "NTR")}]", GUILayout.Width(150)); GUILayout.Label(masterBase.reverser.ToString("n2")); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Speed", GUILayout.Width(150)); GUILayout.Label(masterBase.GetSpeedKmH().ToString("n2")); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Speed (FWD)", GUILayout.Width(150)); GUILayout.Label(masterBase.GetForwardSpeed().ToString("n2")); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Brake", GUILayout.Width(150)); GUILayout.Label(masterBase.brake.ToString("n2")); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Brake Ind.", GUILayout.Width(150)); GUILayout.Label(masterBase.independentBrake.ToString("n2")); GUILayout.EndHorizontal(); } GUILayout.EndVertical(); // stats box end GUILayout.EndVertical(); // row last end GUILayout.EndHorizontal(); // column spacer GUILayout.BeginHorizontal(); GUILayout.BeginVertical(GUILayout.ExpandHeight(true), GUILayout.MaxHeight(1080)); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); // column spacer end GUILayout.BeginHorizontal(); GUILayout.Label("DV TS", GUILayout.Width(30)); if (Instance.MasterLoco != null && Instance.MasterLoco.trainset.cars != null) { for (int i = 0; i < Instance.MasterLoco.trainset.cars.Count; i++) { int index = Instance.MasterLoco.trainset.cars.Count - 1 - i; GUILayout.BeginVertical(GUI.skin.box, GUILayout.Width(100)); if (Instance.MasterLoco.trainset.cars[index] == Instance.MasterLoco) { GUI.color = Color.yellow; } else { if (Instance.MasterLoco.trainset.cars[index].IsLoco) { } else if (Instance.MasterLoco.trainset.cars[index] == Instance.MasterLoco.trainset.firstCar) { GUI.color = Color.green; } else if (Instance.MasterLoco.trainset.cars[index] == Instance.MasterLoco.trainset.lastCar) { GUI.color = Color.red; } else { GUI.color = Color.gray; } } GUILayout.Label(Instance.MasterLoco.trainset.cars[index].ID); GUI.color = defaultColor; GUILayout.EndVertical(); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("CBX TS", GUILayout.Width(30)); if (sortedTrainSet != null && sortedTrainSet.cars != null) { for (int i = 0; i < sortedTrainSet.cars.Count; i++) { int index = sortedTrainSet.cars.Count - 1 - i; GUILayout.BeginVertical(GUI.skin.box, GUILayout.Width(100)); if (sortedTrainSet.cars[index].trainCar == Instance.MasterLoco) { GUI.color = Color.yellow; } else { if (sortedTrainSet.cars[index].trainCar.IsLoco) { } else if (sortedTrainSet.cars[index].trainCar == sortedTrainSet.cars.First().trainCar) { GUI.color = Color.green; } else if (sortedTrainSet.cars[index].trainCar == sortedTrainSet.cars.Last().trainCar) { GUI.color = Color.red; } else { GUI.color = Color.gray; } } GUILayout.Label($"{sortedTrainSet.cars[index].trainCar.ID} {((sortedTrainSet.cars[index].trainCar == Instance.MasterLoco) ? "[M]":"")}"); GUILayout.Label((sortedTrainSet.cars[index].forward) ? "FWD" : "BWD"); GUI.color = defaultColor; GUILayout.EndVertical(); } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); }
private static float GetWheelSpeedKmH(LocoControllerBase loco) { if (loco.GetComponent <WheelRotationViaAnimation>() is var wrva && wrva != null) { return(Mathf.Abs(wrva.rotationSpeed * wrva.wheelCircumference * 3.6f)); }