コード例 #1
0
 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;
     }
 }
コード例 #2
0
        // 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;
                }
            }
        }
コード例 #3
0
        //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();
        }
コード例 #5
0
        //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;
        }