public static bool Prefix(DieselLocoSimulation __instance, float delta) { var engineTemp = __instance.engineTemp.value; var state = ExtraState.Instance(__instance); SimulateFanThermostats(engineTemp, state); var energyInKJ = RawPowerInWatts(__instance) * delta / __instance.timeMult / 1000; var heating = energyInKJ / WaterHeatCapacity / CoolantCapacity; if (__instance.engineOn) { __instance.engineTemp.AddNextValue(heating); } var airflowFraction = state.runningFans == 1 ? 0.75f : state.runningFans == 2 ? 1f : 0.01f; var airflow = airflowFraction * CoolingAirflow; var temperatureDelta = __instance.engineTemp.value - AmbientTemperature; var cooling = airflow * temperatureDelta * Main.settings.dieselCoolingMultiplier * delta / __instance.timeMult; __instance.engineTemp.AddNextValue(-cooling); // Main.DebugLog(TrainCar.Resolve(__instance.gameObject), () => $"power={RawPowerInWatts(__instance)} W, heating={heating / delta * __instance.timeMult} *C/s, cooling={cooling / delta * __instance.timeMult} *C/s, engineTemp={engineTemp}, nextTemp={__instance.engineTemp.nextValue}, runningFans={state.runningFans}"); return(false); }
public static float RawPowerInWatts(DieselLocoSimulation sim) { var atIdle = sim.GetComponent <LocoControllerDiesel>().reverser == 0f || sim.throttle.value == 0; var motivePower = atIdle ? 0f : EngineMaxPower *OutputPower(sim.engineRPM.value); return(motivePower + IdleUsage); }
public static ExtraState Instance(DieselLocoSimulation sim) { if (!states.TryGetValue(sim, out var state)) { states[sim] = state = new ExtraState(sim); } return(state); }
public static bool Prefix(DieselLocoSimulation __instance, float delta) { if (!__instance.engineOn || __instance.oil.value <= 0.0) { return(false); } var oilUsage = RawPowerInWatts(__instance) * OilConsumption * Main.settings.dieselOilConsumptionMultiplier * delta / __instance.timeMult; __instance.oil.AddNextValue(-oilUsage); // Main.DebugLog(TrainCar.Resolve(__instance.gameObject), () => $"oil={__instance.oil.value} / {__instance.oil.max}, oilConsumption={oilUsage / (delta / __instance.timeMult) * 3600} Lph, timeToExhaust={__instance.oil.value/(oilUsage/(delta/__instance.timeMult))} s"); return(false); }
public static bool Prefix(DieselLocoSimulation __instance, float delta) { if (!__instance.engineOn) { return(false); } var fuelUsage = DieselFuelUsage(RawPowerInWatts(__instance) * (delta / __instance.timeMult)) * Main.settings.dieselFuelConsumptionMultiplier; __instance.TotalFuelConsumed += fuelUsage; __instance.fuel.AddNextValue(-fuelUsage); // Main.DebugLog(TrainCar.Resolve(__instance.gameObject), () => $"fuel={__instance.fuel.value} / {__instance.fuel.max}, fuelConsumption={fuelUsage / (delta / __instance.timeMult) * 3600} Lph, timeToExhaust={__instance.fuel.value/(fuelUsage/(delta/__instance.timeMult))} s"); return(false); }
public static bool Prefix(DieselLocoSimulation __instance, float delta) { var sand = __instance.sand; var sandFlow = __instance.sandFlow; if ((__instance.sandOn && sand.value > 0.0 && sandFlow.value < sandFlow.max) || ((!__instance.sandOn || sand.value == 0.0) && sandFlow.value > sandFlow.min)) { sandFlow.AddNextValue((!__instance.sandOn || sand.value <= 0.0 ? -1f : 1f) * 10f * delta); } if (sandFlow.value <= 0.0 || sand.value <= 0.0) { return(false); } sand.AddNextValue(-sandFlow.value * SandingRate * delta / __instance.timeMult); return(false); }
public static bool Prefix(DieselLocoSimulation __instance) { // var loco = TrainCar.Resolve(__instance.gameObject); if (PausePhysicsHandler.PhysicsHandlingInProcess) { return(false); } var throttleVelo = __instance.throttleToTargetDiff.value; var nextRPM = Mathf.SmoothDamp( current: __instance.engineRPM.value, target: TargetRPM(__instance.throttle.value), currentVelocity: ref throttleVelo, smoothTime: 1f, maxSpeed: 1f); __instance.throttleToTargetDiff.SetNextValue(throttleVelo); __instance.engineRPM.SetNextValue(nextRPM); // Main.DebugLog(loco, $"{loco.ID}: throttle={__instance.throttle.value}, RPM={__instance.engineRPM.value}, velo={throttleVelo}"); var state = ExtraState.Instance(__instance); state.CheckTransition(); var speedMetersPerSecond = __instance.speed.value / 3.6f; var powerOutput = (state.InTransition() || __instance.throttle.value == 0f) ? 0f : EngineMaxPower *TransmissionEfficiency *OutputPower(__instance.engineRPM.value); var target = powerOutput / Mathf.Max(1f, speedMetersPerSecond); state.tractiveEffort = Mathf.SmoothDamp( state.tractiveEffort, target, ref state.tractiveEffortVelo, 0.5f); // Main.DebugLog(loco, () => $"engineRPM={__instance.engineRPM.value}, speed={speedMetersPerSecond}, target={target}, TE={state.tractiveEffort}"); return(false); }
public static LocoAI GetLocoAI(TrainCar car) { LocoAI locoAI; if (!locosAI.TryGetValue(car.logicCar.ID, out locoAI)) { DieselLocoSimulation dieselSim = car.GetComponent <DieselLocoSimulation>(); if (dieselSim != null) { if (!dieselSim.engineOn) { throw new CommandException("Engine off"); } } else { ShunterLocoSimulation shunterSim = car.GetComponent <ShunterLocoSimulation>(); if (shunterSim != null) { if (!shunterSim.engineOn) { throw new CommandException("Engine off"); } } else { throw new CommandException("Loco not compatible"); } } LocoControllerShunter shunterController = car.GetComponent <LocoControllerShunter>(); ILocomotiveRemoteControl remote = car.GetComponent <ILocomotiveRemoteControl>(); locoAI = new LocoAI(remote); locosAI.Add(car.logicCar.ID, locoAI); } return(locoAI); }
public static void Postfix(DieselLocoSimulation __instance) { var car = TrainCar.Resolve(__instance.gameObject); car.brakeSystem.compressorProductionRate = (1 + (__instance.engineRPM.value * 825f / 275f)) * BaseRate; }
public ExtraState(DieselLocoSimulation sim) { this.sim = sim; }
public static void Postfix(DieselLocoSimulation __instance) { __instance.sand.max = __instance.sand.value = SandCapacity; }