private void LockGimbal() { if (this.part.Modules.Contains <ModuleGimbal>() && engine.GetCurrentThrust() < 1f) { this.part.Modules.GetModule <ModuleGimbal>().gimbalActive = false; } else if (this.part.Modules.Contains <ModuleGimbal>() && engine.GetCurrentThrust() > 1f) { this.part.Modules.GetModule <ModuleGimbal>().gimbalActive = true; } }
// main block of code runs every physics frame only in flight scene public void FixedUpdate() { if (HighLogic.LoadedSceneIsFlight) { State = operational; // received power code receiver.Directional(this.part, counter, true, PowerLimiter, SurfaceArea, Efficiency, true, true, State, out State, out ReceivingFrom, out double received_power, out counter); this.part.GetConnectedResourceTotals(engine.propellants[0].id, out double amount, out _); if (amount <= 0.5d) { received_power = 0f; State = engineOff; } if (received_power > 0f) { ReceivedPower = (float)Math.Round(received_power, 1); } else { ReceivedPower = 0f; } // code related to engine module float currentisp = engine.realIsp; // getting propellant resource definition PropellantName = engine.propellants[0].displayName; string propellantname = engine.propellants[0].name; float shc = PartResourceLibrary.Instance.GetDefinition(propellantname).specificHeatCapacity * 1.5f / 1000f; // in kJ kg^-1 K^-1 float density = PartResourceLibrary.Instance.GetDefinition(propellantname).density * 1000; // in kg/l // calculate thrust based on power received float Thrust = (float)(received_power * 0.2f / (shc * 8600f)) * 9.8f * currentisp; // in kN Thrust = (Thrust < 20f) ? 0f : Thrust; // minimum thrust (min received power) below this there isnt enough heat to exceed metal's boiling point // propellant loss Loss = (float)((received_power / Efficiency) * (1 - Efficiency) * 0.2f / (shc * 2600f * density)); // units/s (l/s) Loss = (engine.GetCurrentThrust() > 1f) ? Loss : 0f; this.part.RequestResource(propellantname, (double)Loss * Time.fixedDeltaTime); // adding heat to part's skin double heatModifier = HighLogic.CurrentGame.Parameters.CustomParams <BPSettings>().PercentHeat; // in kW this.part.AddThermalFlux(received_power * (1 - Efficiency) * 0.8 * (heatModifier / 100)); // adjust thrust limiter, based on what max thrust should be as calculated percentThrust = Thrust * thrustMult / engine.maxThrust; engine.thrustPercentage = Mathf.Clamp((float)Math.Round(percentThrust * 100, 2), 0f, 100f); this.vessel.GetConnectedResourceTotals(EChash, out double ECamount, out double maxAmount); if (ECamount / maxAmount < 0.01f) { engine.thrustPercentage = 0f; } } }
//This method runs every physics frame //============================================================================================================================================ private void FixedUpdate() { //We can reduce compute times by testing only engines from a list rather than every part on the ship if (PartCount != FlightGlobals.ActiveVessel.parts.Count ()) { //Make a new list of Engines if the Part Count has changed since last frame ActiveEngines.Clear (); foreach (Part Engine in FlightGlobals.ActiveVessel.parts) { if (Engine.Modules.Contains ("ModuleEngines") | Engine.Modules.Contains ("ModuleEnginesFX")) { ActiveEngines.Add (Engine); } } //Set Part count to current count PartCount = FlightGlobals.ActiveVessel.parts.Count (); } //Find Global Variables CurrentMach = Convert.ToSingle(FlightGlobals.ActiveVessel.mach); CurrentAtm = Convert.ToSingle (FlightGlobals.ActiveVessel.atmDensity); //Perform calculations for each engine foreach (Part SingleEngine in ActiveEngines) { //ModuleEngines //------------------------------------------------------------------------------------------------------------------------------ if (SingleEngine.Modules.Contains ("ModuleEngines")) { ModuleEngines ME1 = new ModuleEngines (); ModuleEngines ME2 = new ModuleEngines (); ME1 = SingleEngine.FindModulesImplementing<ModuleEngines> ().First (); ME2 = SingleEngine.FindModulesImplementing<ModuleEngines> ().Last (); //Do Calculations for Module 1 if it is operational if (ME1.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (ME1.useAtmCurve == true && ME1.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((ME1.velCurve.Evaluate (CurrentMach) * ME1.atmCurve.Evaluate (CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((ME1.GetMaxThrust () * (ME1.thrustPercentage / 100)) * (ME1.velCurve.Evaluate (CurrentMach)) * (ME1.atmCurve.Evaluate (CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((ME1.GetMaxThrust () * (ME1.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + ME1.GetCurrentThrust (); } else { TotalCapableThrust = TotalCapableThrust + (ME1.GetMaxThrust () * (ME1.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + ME1.GetCurrentThrust (); } } //If Module 2 is different from 1 (by engineID) do calculations for Module 2 if it is operational if (ME1.engineID != ME2.engineID) { if (ME2.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (ME2.useAtmCurve == true && ME2.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((ME2.velCurve.Evaluate (CurrentMach) * ME2.atmCurve.Evaluate (CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((ME2.GetMaxThrust () * (ME2.thrustPercentage / 100)) * (ME2.velCurve.Evaluate (CurrentMach)) * (ME2.atmCurve.Evaluate (CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((ME2.GetMaxThrust () * (ME2.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + ME2.GetCurrentThrust (); } else { TotalCapableThrust = TotalCapableThrust + (ME2.GetMaxThrust () * (ME2.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + ME2.GetCurrentThrust (); } } } } //ModuleEnginesFX //------------------------------------------------------------------------------------------------------------------------------ if (SingleEngine.Modules.Contains ("ModuleEnginesFX")) { ModuleEnginesFX MEFX1 = new ModuleEnginesFX (); ModuleEnginesFX MEFX2 = new ModuleEnginesFX (); MEFX1 = SingleEngine.FindModulesImplementing<ModuleEnginesFX> ().First (); MEFX2 = SingleEngine.FindModulesImplementing<ModuleEnginesFX> ().Last (); //Do Calculations for Module 1 if it is operational if (MEFX1.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (MEFX1.useAtmCurve == true && MEFX1.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((MEFX1.velCurve.Evaluate (CurrentMach) * MEFX1.atmCurve.Evaluate (CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((MEFX1.GetMaxThrust () * (MEFX1.thrustPercentage / 100)) * (MEFX1.velCurve.Evaluate (CurrentMach)) * (MEFX1.atmCurve.Evaluate (CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((MEFX1.GetMaxThrust () * (MEFX1.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + MEFX1.GetCurrentThrust (); } else { TotalCapableThrust = TotalCapableThrust + (MEFX1.GetMaxThrust () * (MEFX1.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + MEFX1.GetCurrentThrust (); } } //If Module 2 is different from 1 (by engineID) do calculations for Module 2 if it is operational if (MEFX1.engineID != MEFX2.engineID) { if (MEFX2.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (MEFX2.useAtmCurve == true && MEFX2.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((MEFX2.velCurve.Evaluate (CurrentMach) * MEFX2.atmCurve.Evaluate (CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((MEFX2.GetMaxThrust () * (MEFX2.thrustPercentage / 100)) * (MEFX2.velCurve.Evaluate (CurrentMach)) * (MEFX2.atmCurve.Evaluate (CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((MEFX2.GetMaxThrust () * (MEFX2.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + MEFX2.GetCurrentThrust (); } else { TotalCapableThrust = TotalCapableThrust + (MEFX2.GetMaxThrust () * (MEFX2.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + MEFX2.GetCurrentThrust (); } } } } } //Prevent Divide by 0 Errors if (TotalCapableThrust == 0) { TotalCapableThrust = 0.0001f; } //Not truly a percentage, gauge works between 0 and 1, NOT 0 and 100 ThrustPercentage = ((TotalCurrentThrust / TotalCapableThrust)); if (UseSplitNeedle == false) { //Gently Fade the alpha channel of the stock gauge so we can see TIM if it is near/behind if (FlightUIController.fetch.thr.rawValue >= ThrustPercentage) { StockGaugeColor.a = Mathf.Max (Mathf.Min (((((FlightUIController.fetch.thr.rawValue - ThrustPercentage) - 0.015f) * 2.3f) + StockGaugeColorAlpha), 1.0f), StockGaugeColorAlpha); } if (FlightUIController.fetch.thr.rawValue <= ThrustPercentage) { StockGaugeColor.a = Mathf.Max (Mathf.Min (((((FlightUIController.fetch.thr.rawValue - ThrustPercentage) + 0.015f) * -2.3f) + StockGaugeColorAlpha), 1.0f), StockGaugeColorAlpha); } StockGauge.transform.GetChild (0).renderer.material.color = StockGaugeColor; TIMGauge.transform.GetChild (0).renderer.material.color = TIMGaugeColor; //Render the StockGauge after TIM so that it shows in front of TIM StockGauge.transform.GetChild (0).renderer.material.renderQueue = TIMGauge.transform.GetChild (0).renderer.material.renderQueue + 1; } //Set Gauge to Calculated Value TIMGauge.setValue (ThrustPercentage); //Reset Thrust Values Each Compute Cycle TotalCapableThrust = 0; TotalCurrentThrust = 0; }
public override void OnFixedUpdate() { base.OnFixedUpdate(); if (_attached_engine == null) { return; } if (_attached_engine.currentThrottle > 0 && !exhaustAllowed) { string message = AttachedReactor.MayExhaustInLowSpaceHomeworld ? Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_PostMsg1") //"Engine halted - Radioactive exhaust not allowed towards or inside homeworld atmosphere" : Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_PostMsg2"); //"Engine halted - Radioactive exhaust not allowed towards or near homeworld atmosphere" ScreenMessages.PostScreenMessage(message, 5, ScreenMessageStyle.UPPER_CENTER); vessel.ctrlState.mainThrottle = 0; // Return to realtime if (vessel.packed) { TimeWarp.SetRate(0, true); } } _chargedParticleMaximumPercentageUsage = _attached_reactor != null ? _attached_reactor.ChargedParticlePropulsionEfficiency : 0; if (_chargedParticleMaximumPercentageUsage > 0) { if (_attached_reactor.Part != this.part) { resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, this.part.mass); resourceBuffers.UpdateBuffers(); } maximumChargedPower = _attached_reactor.MaximumChargedPower; var currentMaximumChargedPower = maximum_isp == minimum_isp ? maximumChargedPower * _attached_engine.currentThrottle : maximumChargedPower; _max_charged_particles_power = currentMaximumChargedPower * exchanger_thrust_divisor * _attached_reactor.ChargedParticlePropulsionEfficiency; _charged_particles_requested = exhaustAllowed && _attached_engine.isOperational && _attached_engine.currentThrottle > 0 ? _max_charged_particles_power : 0; _charged_particles_received = _charged_particles_requested > 0 ? consumeFNResourcePerSecond(_charged_particles_requested, ResourceSettings.Config.ChargedParticleInMegawatt) : 0; // update Isp currentIsp = !_attached_engine.isOperational || _attached_engine.currentThrottle == 0 ? maximum_isp : Math.Min(maximum_isp, minimum_isp / Math.Pow(_attached_engine.currentThrottle, throtleExponent)); var powerThrustModifier = GameConstants.BaseThrustPowerMultiplier * powerThrustMultiplier; var max_engine_thrust_at_max_isp = powerThrustModifier * _charged_particles_received / maximum_isp / GameConstants.STANDARD_GRAVITY; var calculatedConsumptionInTon = max_engine_thrust_at_max_isp / maximum_isp / GameConstants.STANDARD_GRAVITY; UpdatePropellantBuffer(calculatedConsumptionInTon); // convert reactor product into propellants when possible and generate addition propellant from reactor fuel consumption chargedParticleRatio = currentMaximumChargedPower > 0 ? _charged_particles_received / currentMaximumChargedPower : 0; _attached_reactor.UseProductForPropulsion(chargedParticleRatio, calculatedConsumptionInTon); calculatedConsumptionPerSecond = calculatedConsumptionInTon * 1000; if (!CheatOptions.IgnoreMaxTemperature) { if (_attached_engine.isOperational && _attached_engine.currentThrottle > 0) { wasteheatConsumption = _charged_particles_received > _previous_charged_particles_received ? _charged_particles_received + (_charged_particles_received - _previous_charged_particles_received) : _charged_particles_received - (_previous_charged_particles_received - _charged_particles_received); _previous_charged_particles_received = _charged_particles_received; } //else if (_previous_charged_particles_received > 0) //{ // wasteheatConsumption = _previous_charged_particles_received; // _previous_charged_particles_received = 0; //} else { wasteheatConsumption = 0; _charged_particles_received = 0; _previous_charged_particles_received = 0; } consumeFNResourcePerSecond(wasteheatConsumption, ResourceSettings.Config.WasteHeatInMegawatt); } if (_charged_particles_received == 0) { _chargedParticleMaximumPercentageUsage = 0; UpdateRunningEffect(); UpdatePowerEffect(); } // calculate power cost var ispPowerCostMultiplier = 1 + max_power_multiplier - Math.Log10(currentIsp / minimum_isp); var minimumEnginePower = _attached_reactor.MagneticNozzlePowerMult * _charged_particles_received * ispPowerCostMultiplier * 0.005 * Math.Max(_attached_reactor_distance, 1); var neededBufferPower = Math.Min(getResourceAvailability(ResourceSettings.Config.ElectricPowerInMegawatt), Math.Min(Math.Max(powerBufferMax - powerBufferStore, 0), minimumEnginePower)); _requestedElectricPower = minimumEnginePower + neededBufferPower; _recievedElectricPower = CheatOptions.InfiniteElectricity || _requestedElectricPower == 0 ? _requestedElectricPower : consumeFNResourcePerSecond(_requestedElectricPower, ResourceSettings.Config.ElectricPowerInMegawatt); // adjust power buffer var powerSurplus = _recievedElectricPower - minimumEnginePower; if (powerSurplus < 0) { var powerFromBuffer = Math.Min(-powerSurplus, powerBufferStore); _recievedElectricPower += powerFromBuffer; powerBufferStore -= powerFromBuffer; } else { powerBufferStore += powerSurplus; } // calculate Power factor megajoulesRatio = Math.Min(_recievedElectricPower / minimumEnginePower, 1); megajoulesRatio = (double.IsNaN(megajoulesRatio) || double.IsInfinity(megajoulesRatio)) ? 0 : megajoulesRatio; var scaledPowerFactor = Math.Pow(megajoulesRatio, 0.5); double effectiveThrustRatio = 1; _engineMaxThrust = 0; if (_max_charged_particles_power > 0) { var max_thrust = powerThrustModifier * _charged_particles_received * scaledPowerFactor / currentIsp / GameConstants.STANDARD_GRAVITY; var effective_thrust = Math.Max(max_thrust - (radius * radius * vessel.atmDensity * 100), 0); effectiveThrustRatio = max_thrust > 0 ? effective_thrust / max_thrust : 0; _engineMaxThrust = _attached_engine.currentThrottle > 0 ? Math.Max(effective_thrust, 1e-9) : Math.Max(max_thrust, 1e-9); } // set isp FloatCurve newAtmosphereCurve = new FloatCurve(); engineIsp = _attached_engine.currentThrottle > 0 ? (currentIsp * scaledPowerFactor * effectiveThrustRatio) : currentIsp; newAtmosphereCurve.Add(0, (float)engineIsp, 0, 0); _attached_engine.atmosphereCurve = newAtmosphereCurve; var max_effective_fuel_flow_rate = !double.IsInfinity(_engineMaxThrust) && !double.IsNaN(_engineMaxThrust) && currentIsp > 0 ? _engineMaxThrust / currentIsp / GameConstants.STANDARD_GRAVITY / (_attached_engine.currentThrottle > 0 ? _attached_engine.currentThrottle : 1) : 0; max_theoretical_thrust = powerThrustModifier * maximumChargedPower * _chargedParticleMaximumPercentageUsage / currentIsp / GameConstants.STANDARD_GRAVITY; max_theoratical_fuel_flow_rate = max_theoretical_thrust / currentIsp / GameConstants.STANDARD_GRAVITY; // set maximum flow engineFuelFlow = _attached_engine.currentThrottle > 0 ? Math.Max((float)max_effective_fuel_flow_rate, 1e-9f) : (float)max_theoratical_fuel_flow_rate; _attached_engine.maxFuelFlow = engineFuelFlow; _attached_engine.useThrustCurve = false; // This whole thing may be inefficient, but it should clear up some confusion for people. if (_attached_engine.getFlameoutState) { return; } if (_attached_engine.currentThrottle < 0.01) { _attached_engine.status = Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_statu1");//"offline" } else if (megajoulesRatio < 0.75 && _requestedElectricPower > 0) { _attached_engine.status = Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_statu2");//"Insufficient Electricity" } else if (effectiveThrustRatio < 0.01 && vessel.atmDensity > 0) { _attached_engine.status = Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_statu3");//"Too dense atmospherere" } } else { _chargedParticleMaximumPercentageUsage = 0; _attached_engine.maxFuelFlow = 0.0000000001f; _recievedElectricPower = 0; _charged_particles_requested = 0; _charged_particles_received = 0; _engineMaxThrust = 0; } currentThrust = _attached_engine.GetCurrentThrust(); }
//This method runs every physics frame //============================================================================================================================================ private void FixedUpdate() { //We can reduce compute times by testing only engines from a list rather than every part on the ship if (PartCount != FlightGlobals.ActiveVessel.parts.Count()) { //Make a new list of Engines if the Part Count has changed since last frame ActiveEngines.Clear(); foreach (Part Engine in FlightGlobals.ActiveVessel.parts) { if (Engine.Modules.Contains("ModuleEngines") | Engine.Modules.Contains("ModuleEnginesFX")) { ActiveEngines.Add(Engine); } } //Set Part count to current count PartCount = FlightGlobals.ActiveVessel.parts.Count(); } //Find Global Variables CurrentMach = Convert.ToSingle(FlightGlobals.ActiveVessel.mach); CurrentAtm = Convert.ToSingle(FlightGlobals.ActiveVessel.atmDensity); //Perform calculations for each engine foreach (Part SingleEngine in ActiveEngines) { //ModuleEngines //------------------------------------------------------------------------------------------------------------------------------ if (SingleEngine.Modules.Contains("ModuleEngines")) { ModuleEngines ME1 = new ModuleEngines(); ModuleEngines ME2 = new ModuleEngines(); ME1 = SingleEngine.FindModulesImplementing <ModuleEngines> ().First(); ME2 = SingleEngine.FindModulesImplementing <ModuleEngines> ().Last(); //Do Calculations for Module 1 if it is operational if (ME1.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (ME1.useAtmCurve == true && ME1.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((ME1.velCurve.Evaluate(CurrentMach) * ME1.atmCurve.Evaluate(CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((ME1.GetMaxThrust() * (ME1.thrustPercentage / 100)) * (ME1.velCurve.Evaluate(CurrentMach)) * (ME1.atmCurve.Evaluate(CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((ME1.GetMaxThrust() * (ME1.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + ME1.GetCurrentThrust(); } else { TotalCapableThrust = TotalCapableThrust + (ME1.GetMaxThrust() * (ME1.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + ME1.GetCurrentThrust(); } } //If Module 2 is different from 1 (by engineID) do calculations for Module 2 if it is operational if (ME1.engineID != ME2.engineID) { if (ME2.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (ME2.useAtmCurve == true && ME2.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((ME2.velCurve.Evaluate(CurrentMach) * ME2.atmCurve.Evaluate(CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((ME2.GetMaxThrust() * (ME2.thrustPercentage / 100)) * (ME2.velCurve.Evaluate(CurrentMach)) * (ME2.atmCurve.Evaluate(CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((ME2.GetMaxThrust() * (ME2.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + ME2.GetCurrentThrust(); } else { TotalCapableThrust = TotalCapableThrust + (ME2.GetMaxThrust() * (ME2.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + ME2.GetCurrentThrust(); } } } } //ModuleEnginesFX //------------------------------------------------------------------------------------------------------------------------------ if (SingleEngine.Modules.Contains("ModuleEnginesFX")) { ModuleEnginesFX MEFX1 = new ModuleEnginesFX(); ModuleEnginesFX MEFX2 = new ModuleEnginesFX(); MEFX1 = SingleEngine.FindModulesImplementing <ModuleEnginesFX> ().First(); MEFX2 = SingleEngine.FindModulesImplementing <ModuleEnginesFX> ().Last(); //Do Calculations for Module 1 if it is operational if (MEFX1.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (MEFX1.useAtmCurve == true && MEFX1.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((MEFX1.velCurve.Evaluate(CurrentMach) * MEFX1.atmCurve.Evaluate(CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((MEFX1.GetMaxThrust() * (MEFX1.thrustPercentage / 100)) * (MEFX1.velCurve.Evaluate(CurrentMach)) * (MEFX1.atmCurve.Evaluate(CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((MEFX1.GetMaxThrust() * (MEFX1.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + MEFX1.GetCurrentThrust(); } else { TotalCapableThrust = TotalCapableThrust + (MEFX1.GetMaxThrust() * (MEFX1.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + MEFX1.GetCurrentThrust(); } } //If Module 2 is different from 1 (by engineID) do calculations for Module 2 if it is operational if (MEFX1.engineID != MEFX2.engineID) { if (MEFX2.isOperational == true) { //Jet engines use Atmosphere & Velocity Curves to modify performance at different altitudes/speeds. Use these calculations for those engines, otherwise use base values from part cfg. if (MEFX2.useAtmCurve == true && MEFX2.useVelCurve == true) { //If the Thrust Multiplier from VelCurve * AtmCurve is more than 1, evaluate the curves and determine max thrust for that scenario. Otherwise, use the base method and assume Max Thrust from cfg file. if ((MEFX2.velCurve.Evaluate(CurrentMach) * MEFX2.atmCurve.Evaluate(CurrentAtm)) > 1) { TotalCapableThrust = TotalCapableThrust + ((MEFX2.GetMaxThrust() * (MEFX2.thrustPercentage / 100)) * (MEFX2.velCurve.Evaluate(CurrentMach)) * (MEFX2.atmCurve.Evaluate(CurrentAtm))); } else { TotalCapableThrust = TotalCapableThrust + ((MEFX2.GetMaxThrust() * (MEFX2.thrustPercentage / 100))); } TotalCurrentThrust = TotalCurrentThrust + MEFX2.GetCurrentThrust(); } else { TotalCapableThrust = TotalCapableThrust + (MEFX2.GetMaxThrust() * (MEFX2.thrustPercentage / 100)); TotalCurrentThrust = TotalCurrentThrust + MEFX2.GetCurrentThrust(); } } } } } //Prevent Divide by 0 Errors if (TotalCapableThrust == 0) { TotalCapableThrust = 0.0001f; } //Not truly a percentage, gauge works between 0 and 1, NOT 0 and 100 ThrustPercentage = ((TotalCurrentThrust / TotalCapableThrust)); if (UseSplitNeedle == false) { //Gently Fade the alpha channel of the stock gauge so we can see TIM if it is near/behind if (FlightUIController.fetch.thr.rawValue >= ThrustPercentage) { StockGaugeColor.a = Mathf.Max(Mathf.Min(((((FlightUIController.fetch.thr.rawValue - ThrustPercentage) - 0.015f) * 2.3f) + StockGaugeColorAlpha), 1.0f), StockGaugeColorAlpha); } if (FlightUIController.fetch.thr.rawValue <= ThrustPercentage) { StockGaugeColor.a = Mathf.Max(Mathf.Min(((((FlightUIController.fetch.thr.rawValue - ThrustPercentage) + 0.015f) * -2.3f) + StockGaugeColorAlpha), 1.0f), StockGaugeColorAlpha); } StockGauge.transform.GetChild(0).renderer.material.color = StockGaugeColor; TIMGauge.transform.GetChild(0).renderer.material.color = TIMGaugeColor; //Render the StockGauge after TIM so that it shows in front of TIM StockGauge.transform.GetChild(0).renderer.material.renderQueue = TIMGauge.transform.GetChild(0).renderer.material.renderQueue + 1; } //Set Gauge to Calculated Value TIMGauge.setValue(ThrustPercentage); //Reset Thrust Values Each Compute Cycle TotalCapableThrust = 0; TotalCurrentThrust = 0; }