void FixPressure(FloatCurve curve, double topLayer)
        {
            List<double[]> list = ReadCurve(curve); /* Avoid Bad Curves ==> */ if (list.Count < 2) { UnityEngine.Debug.Log("SigmaLog: This pressure curve has " + (list.Count == 0 ? "no keys" : "just one key") + ". I don't know what you expect me to do with that."); return; }

            double maxAltitude = list.Last()[0];

            bool smoothEnd = list.Last()[1] == 0 && list.Count > 2;
            double smoothRange = list.Last()[0] - list[list.Count - 2][0];
            if (smoothEnd) list.RemoveAt(list.Count - 1);

            if (topLayer > maxAltitude)
            {
                Extend(list, topLayer);
                maxAltitude = list.Last()[0];
            }

            if (topLayer < maxAltitude)
            {
                Trim(list, topLayer);
            }

            if (smoothEnd)
            {
                Smooth(list, smoothRange);
            }

            curve.Load(WriteCurve(list));
        }
示例#2
0
        public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult, Vector3 previousTorque, float maxTorque, float maxAoA)
        {
            if(DefaultLiftCurve == null)
            {
                DefaultLiftCurve = new FloatCurve();
                DefaultLiftCurve.Add(0, .1f);
                DefaultLiftCurve.Add(8, .45f);
                DefaultLiftCurve.Add(19, 1);
                DefaultLiftCurve.Add(23, .9f);
                DefaultLiftCurve.Add(29, 0.85f);
                DefaultLiftCurve.Add(35, 0.65f);
                DefaultLiftCurve.Add(65, .6f);
                DefaultLiftCurve.Add(90, .7f);
            }

            if(DefaultDragCurve == null)
            {
                DefaultDragCurve = new FloatCurve();
                DefaultDragCurve.Add(0, 0.00225f);
                DefaultDragCurve.Add(5, .0035f);
                DefaultDragCurve.Add(15, .015f);
                DefaultDragCurve.Add(29, .025f);
                DefaultDragCurve.Add(55, .3f);
                DefaultDragCurve.Add(90, .5f);
            }

            FloatCurve liftCurve = DefaultLiftCurve;
            FloatCurve dragCurve = DefaultDragCurve;

            return DoAeroForces(ml, targetPosition, liftArea, steerMult, previousTorque, maxTorque, maxAoA, liftCurve, dragCurve);
        }
 public FloatCurve ProcessNodeAsFloatCurve(ConfigNode node)
 {
     FloatCurve resultCurve = new FloatCurve();
     ConfigNode[] moduleNodeArray = node.GetNodes(nodeName);
     debugMessage("ProcessNodeAsFloatCurve: moduleNodeArray.length " + moduleNodeArray.Length);
     for (int k = 0; k < moduleNodeArray.Length; k++)
     {
         debugMessage("found node");
         string[] valueArray = moduleNodeArray[k].GetValues(valueName);
         debugMessage("found " + valueArray.Length + " values");
         for (int l = 0; l < valueArray.Length; l++)
         {
             string[] splitString = valueArray[l].Split(' ');
             try
             {
                 Vector2 v2 = new Vector2(float.Parse(splitString[0]), float.Parse(splitString[1]));
                 resultCurve.Add(v2.x, v2.y, 0, 0);
             }
             catch
             {
                 Debug.Log("Error parsing vector2");
             }
         }
     }
     return resultCurve;
 }
 public HeatShieldType(ConfigNode node)
 {
     name = node.GetStringValue("name");
     heatCurve = node.GetFloatCurve("heatCurve");
     resourceMult = node.GetFloatValue("resourceMult", resourceMult);
     ablationMult = node.GetFloatValue("ablationMult", ablationMult);
     massMult = node.GetFloatValue("massMult", massMult);
 }
 public SSTUSolarPanelStatic()
 {
     //the default stock temperatureEfficiencyCurve
     this.temperatureEfficCurve = new FloatCurve ();
     this.temperatureEfficCurve.Add (4f, 1.2f, 0f, -0.0005725837f);
     this.temperatureEfficCurve.Add (300f, 1f, -0.0008277721f, -0.0008277721f);
     this.temperatureEfficCurve.Add (1200f, 0.1f, -0.0003626566f, -0.0003626566f);
     this.temperatureEfficCurve.Add (2500f, 0.01f, 0f, 0f);
 }
示例#6
0
 public void Load(ConfigNode node)
 {
     if (node.HasValue("scope"))
         scope = node.GetValue("scope").ToLower();
     if (node.HasNode("reliabilityCurve"))
     {
         reliabilityCurve = new FloatCurve();
         reliabilityCurve.Load(node.GetNode("reliabilityCurve"));
     }
 }
 public override void OnLoad(ConfigNode node)
 {
     base.OnLoad(node);
     if (node.HasNode("cycle"))
     {
         cycle = new FloatCurve();
         cycle.Load(node.GetNode("cycle"));
     }
     else
         cycle = null;
 }
        public override void OnStart(StartState state)
        {
            base.OnStart(state);
            intake = FindIntake();

            if (machCurve == null)
            {
                Debug.LogError("ERROR: ModuleB9AnimateIntake on part " + part.name + ": machCurve is null!");
                machCurve = new FloatCurve();
                machCurve.Add(0f, 0f);
            }
        }
示例#9
0
        internal void add(float time, Vector2 xy)
        {
            if (curveX == null) {
                curveX = new FloatCurve();
            }
            curveX.Add(time, xy.x);

            if (curveY == null) {
                curveY = new FloatCurve();
            }
            curveY.Add(time, xy.y);
        }
示例#10
0
 public float EvaluateTempDiffCurve(float vel)
 {
     if(protoTempCurve != null)
     {
         tempAdditionFromVelocity = new FloatCurve();
         foreach(CurveData data in protoTempCurve)
         {
             tempAdditionFromVelocity.Add(data.x, data.y, data.dy_dx, data.dy_dx);
         }
         protoTempCurve = null;
     }
     return tempAdditionFromVelocity.Evaluate(vel);
 }
 public override void OnStart(StartState state)
 {
     base.OnStart(state);
     Part prefab = this.part.partInfo.partPrefab;
     foreach (PartModule pm in prefab.Modules)
     {
         TestFlightReliability_EngineCycle modulePrefab = pm as TestFlightReliability_EngineCycle;
         if (modulePrefab != null && modulePrefab.Configuration == configuration)
         {
             cycle = modulePrefab.cycle;
         }
     }
 }
示例#12
0
 public float EvaluateVelCpCurve(float vel)
 {
     if (protoVelCpCurve != null)
     {
         velCpCurve = new FloatCurve();
         foreach (CurveData data in protoVelCpCurve)
         {
             velCpCurve.Add(data.x, data.y, data.dy_dx, data.dy_dx);
         }
         protoTempCurve = null;
     }
     return velCpCurve.Evaluate(vel);
 }
示例#13
0
        public override void CreateEngine()
        {
            rfSolver = new SolverRF();
            if(!useAtmCurve)
                atmCurve = null;
            if(!useVelCurve)
                velCurve = null;
            if (!useThrustCurve)
                thrustCurve = null;

            // FIXME quick temp hax
            if (useAtmCurve)
            {
                if (maxEngineTemp == 0d)
                    maxEngineTemp = 2000d;
                if (chamberNominalTemp == 0d)
                    chamberNominalTemp = 950d;
            }
            else
            {
                if (maxEngineTemp == 0d)
                    maxEngineTemp = 3600d;
                if (chamberNominalTemp == 0d)
                    chamberNominalTemp = 3400d;
                if (tempGaugeMin == 0.8d)
                    tempGaugeMin = 0.95d;
            }
            double thrustVariation = varyThrust * RFSettings.Instance.varyThrust;
            chamberNominalTemp *= (1d - thrustVariation);

            rfSolver.InitializeOverallEngineData(
                minFuelFlow,
                maxFuelFlow,
                atmosphereCurve,
                atmCurve,
                velCurve,
                throttleResponseRate,
                chamberNominalTemp,
                machLimit,
                machHeatMult,
                flowMultMin,
                flowMultCap,
                flowMultCapSharpness,
                multFlow,
                thrustVariation,
                (float)part.name.GetHashCode());

            rfSolver.SetScale(scale);

            engineSolver = rfSolver;
        }
 public override void OnAwake()
 {
     base.OnAwake();
     if (thrustModifier == null)
     {
         thrustModifier = new FloatCurve();
         thrustModifier.Add(0f, 1f);
     }
     if (cycle == null)
     {
         cycle = new FloatCurve();
         cycle.Add(0f, 1f);
     }
 }
		public void FixedUpdate() {
            if (HighLogic.LoadedSceneIsFlight && _attached_engine != null && _attached_reactor != null && _attached_engine.isOperational)
            {
                double max_power = _attached_reactor.MaximumChargedPower;
                if (_attached_reactor is InterstellarFusionReactor) max_power *= 0.9;
                double dilution_factor = 15000.0;
                double joules_per_amu = _attached_reactor.CurrentMeVPerChargedProduct * 1e6 * GameConstants.ELECTRON_CHARGE / dilution_factor;
                double isp = Math.Sqrt(joules_per_amu * 2.0 / GameConstants.ATOMIC_MASS_UNIT) / GameConstants.STANDARD_GRAVITY;
                FloatCurve new_isp = new FloatCurve();
                new_isp.Add(0, (float)isp, 0, 0);
                _attached_engine.atmosphereCurve = new_isp;

                double charged_power_received = consumeFNResource(max_power * TimeWarp.fixedDeltaTime * _attached_engine.currentThrottle, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES) / TimeWarp.fixedDeltaTime;
                consumeFNResource(charged_power_received * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT);

                double megajoules_received = consumeFNResource(charged_power_received * TimeWarp.fixedDeltaTime * 0.01, FNResourceManager.FNRESOURCE_MEGAJOULES)/TimeWarp.fixedDeltaTime;
                double megajoules_ratio = megajoules_received / charged_power_received / 0.01;
                megajoules_ratio = (double.IsNaN(megajoules_ratio) || double.IsInfinity(megajoules_ratio)) ? 0 : megajoules_ratio;

                double atmo_thrust_factor = Math.Min(1.0,Math.Max(1.0 - Math.Pow(vessel.atmDensity,0.2),0));

                double exchanger_thrust_divisor = 1;
                if (radius > _attached_reactor.getRadius())
                {
                    exchanger_thrust_divisor = _attached_reactor.getRadius() * _attached_reactor.getRadius() / radius / radius;
                } else
                {
                    exchanger_thrust_divisor = radius * radius / _attached_reactor.getRadius() / _attached_reactor.getRadius();
                }

                double engineMaxThrust = 0.000000001;
                float power_ratio;
                if (max_power > 0)
                {
                    power_ratio = (float)(charged_power_received / max_power);
                    engineMaxThrust = Math.Max(2000.0 * charged_power_received*megajoules_ratio*atmo_thrust_factor*exchanger_thrust_divisor / isp / GameConstants.STANDARD_GRAVITY / _attached_engine.currentThrottle, 0.000000001);
                }

                if (!double.IsInfinity(engineMaxThrust) && !double.IsNaN(engineMaxThrust))
                {
                    _attached_engine.maxThrust = (float)engineMaxThrust;
                } else
                {
                    _attached_engine.maxThrust = 0.000000001f;
                }
            } else if (_attached_engine != null)
            {
                _attached_engine.maxThrust = 0.000000001f;
            }
		}
示例#16
0
        // CONSTRUCTORS
        public TechLevel()
        {
            atmosphereCurve = new FloatCurve();
            velocityCurve = new FloatCurve();
            TWR = -1;
            thrustMultiplier = -1;
            massMultiplier = -1;
            minThrottleMultiplier = -1;
            gimbalRange = -1f;
            techRequired = "";
            costMult = 1f;

            LoadGlobals();
        }
示例#17
0
        public TechLevel(TechLevel t)
        {
            atmosphereCurve = t.atmosphereCurve;
            velocityCurve = t.velocityCurve;
            TWR = t.TWR;
            thrustMultiplier = t.thrustMultiplier;
            massMultiplier = t.massMultiplier;
            gimbalRange = t.gimbalRange;
            techRequired = t.techRequired;
            minThrottleMultiplier = t.minThrottleMultiplier;
            costMult = t.costMult;

            LoadGlobals();
        }
示例#18
0
 public float EvaluateTempDiffCurve(float vel)
 {
     if(protoTempCurve != null)
     {
         tempAdditionFromVelocity = new FloatCurve();
         Debug.Log("Building Temperature Curve Object...");
         foreach(CurveData data in protoTempCurve)
         {
             tempAdditionFromVelocity.Add(data.x, data.y, data.dy_dx, data.dy_dx);
         }
         protoTempCurve = null;
     }
     return tempAdditionFromVelocity.Evaluate(vel);
 }
示例#19
0
 public override void OnAwake()
 {
     base.OnAwake();
     if (heatCurve == null)
     {
         heatCurve = new FloatCurve();
         heatCurve.Add(0, 0.00002f);//very minimal initial ablation factor
         heatCurve.Add(50, 0.00005f);//ramp it up fairly quickly though
         heatCurve.Add(150, 0.00015f);
         heatCurve.Add(500, 0.00050f);
         heatCurve.Add(750, 0.00075f);
         heatCurve.Add(1000, 0.00100f);
         heatCurve.Add(2000, 0.00400f);
         heatCurve.Add(3000, 0.00800f);//generally, things will explode before this point
         heatCurve.Add(10000, 0.05000f);//but just in case, continue the curve up to insane levels
     }
 }
		public void FixedUpdate() 
        {
            if (HighLogic.LoadedSceneIsFlight)
            {
                if (!active)
                {
                    base.OnFixedUpdate();
                }

                if (solarPanel != null)
                {
                    double inv_square_mult = Math.Pow(Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2) / Math.Pow(Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2);
                    FloatCurve satcurve = new FloatCurve();
                    satcurve.Add(0.0f, (float)inv_square_mult);
                    solarPanel.powerCurve = satcurve;

                    float solar_rate = solarPanel.flowRate * TimeWarp.fixedDeltaTime;
                    float clamper = PluginHelper.IsSolarPanelHeatingClamped 
                        ? (float)Math.Min(Math.Max((Math.Sqrt(inv_square_mult) - 1.5), 0.0), 1.0) 
                        : 1.0f;
                    float heat_rate =  clamper * solar_rate * 0.5f / 1000.0f;

                    if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.98 && solarPanel.panelState == ModuleDeployableSolarPanel.panelStates.EXTENDED && solarPanel.sunTracking)
                    {
                        solarPanel.Retract();
                        if (FlightGlobals.ActiveVessel == vessel)
                            ScreenMessages.PostScreenMessage("Warning Dangerous Overheating Detected: Solar Panel retraction occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER);

                        return;
                    }

                    List<PartResource> prl = part.GetConnectedResources("ElectricCharge").ToList();
                    double current_charge = prl.Sum(pr => pr.amount);
                    double max_charge = prl.Sum(pr => pr.maxAmount);

                    var solar_supply = current_charge >= max_charge ? solar_rate / 1000.0f : 0;
                    var solar_maxSupply = solar_rate / 1000.0f;

                    supplyFNResourceFixedMax(solar_supply, solar_maxSupply, FNResourceManager.FNRESOURCE_MEGAJOULES);
                    wasteheat_production_f = supplyFNResource(heat_rate, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime * 1000.0f;
                }
            }
		}
示例#21
0
 public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach)
 {
     float flowModifier = 1.0f;
     if (atmChangeFlow)
     {
         flowModifier = (float)(atmDensity / 1.225);
         if (atmCurve != null)
         {
             flowModifier = atmCurve.Evaluate(flowModifier);
         }
     }
     if (velCurve != null)
     {
         flowModifier = flowModifier * velCurve.Evaluate(machNumber);
         maxMach = velCurve.maxTime;
     }
     if (flowModifier < float.Epsilon)
     {
         flowModifier = float.Epsilon;
     }
     return flowModifier;
 }
		public override void OnFixedUpdate() {
			base.OnFixedUpdate ();
			if (solarPanel != null) {
				float solar_rate = solarPanel.flowRate*TimeWarp.fixedDeltaTime;
				float heat_rate = solar_rate * 0.5f/1000.0f;

                double inv_square_mult = Math.Pow(Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2) / Math.Pow(Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2);
                FloatCurve satcurve = new FloatCurve();
                satcurve.Add(0.0f, (float)inv_square_mult);
                solarPanel.powerCurve = satcurve;

				if (getResourceBarRatio (FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.98 && solarPanel.panelState == ModuleDeployableSolarPanel.panelStates.EXTENDED && solarPanel.sunTracking) {
					solarPanel.Retract ();
					if (FlightGlobals.ActiveVessel == vessel) {
						ScreenMessages.PostScreenMessage ("Warning Dangerous Overheating Detected: Solar Panel retraction occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER);
					}
					return;
				}

				wasteheat_production_f = supplyFNResource(heat_rate,FNResourceManager.FNRESOURCE_WASTEHEAT)/TimeWarp.fixedDeltaTime*1000.0f;
			}


		}
        public override void OnStart(PartModule.StartState state)
        {
            base.OnStart(state);
            engine = part.GetComponent<ModuleEnginesFX>();

            Propellant fuelPropellant = new Propellant();
            foreach (Propellant prop in engine.propellants)
            {

                if (prop.name != "ElectricCharge")
                    fuelPropellant = prop;
            }

            ThrustCurve = new FloatCurve();
            ThrustCurve.Add(0f, engine.maxThrust);
            ThrustCurve.Add(minPressure, minThrust);

            AtmoCurve = new FloatCurve();
            AtmoCurve.Add(0f, engine.atmosphereCurve.Evaluate(0f));

            float rate = FindFlowRate (engine.maxThrust,engine.atmosphereCurve.Evaluate(0f),fuelPropellant);

            AtmoCurve.Add(1f,FindIsp(minThrust,rate,fuelPropellant));
        }
        public override void OnStart(PartModule.StartState state)
        {
            try
            {
                Debug.Log("[KSPI]: Start ElectricEngineControllerFX");

                if (state != StartState.Editor)
                {
                    if (vessel.FindPartModulesImplementing <FNGenerator>().Any(m => m.isHighPower) == false)
                    {
                        if (powerThrustMultiplier == 1 && powerThrustMultiplierWithoutReactors > 0)
                        {
                            powerThrustMultiplier = powerThrustMultiplierWithoutReactors;
                        }

                        if (powerReqMult == 1 && powerReqMultWithoutReactor > 0)
                        {
                            powerReqMult = powerReqMultWithoutReactor;
                        }
                    }
                }

                ScaleParameters();

                // initialise resources
                this.resources_to_supply = new[] { ResourceManager.FNRESOURCE_WASTEHEAT };
                base.OnStart(state);

                AttachToEngine();
                DetermineTechLevel();
                powerCapacityModifier = PowerCapacityModifier;

                _initializationCountdown = 10;
                _ispFloatCurve           = new FloatCurve();
                _ispFloatCurve.Add(0, (float)baseISP);
                _speedOfLight          = GameConstants.speedOfLight * PluginHelper.SpeedOfLightMult;
                _hasGearTechnology     = String.IsNullOrEmpty(gearsTechReq) || PluginHelper.UpgradeAvailable(gearsTechReq);
                _modifiedEngineBaseIsp = baseISP * PluginHelper.ElectricEngineIspMult;
                _hasrequiredupgrade    = this.HasTechsRequiredToUpgrade();

                if (_hasrequiredupgrade && (isupgraded || state == StartState.Editor))
                {
                    upgradePartModule();
                }

                UpdateEngineTypeString();

                _resourceBuffers = new ResourceBuffers();
                _resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_WASTEHEAT, wasteHeatMultiplier, 2.0e+4, true));
                _resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, (double)(decimal)this.part.mass);
                _resourceBuffers.Init(this.part);

                InitializePropellantMode();

                SetupPropellants(true);

                _attachedEngine.maxThrust = (float)maximumThrustFromPower;
            }
            catch (Exception e)
            {
                Debug.LogError("[KSPI]: Error OnStart ElectricEngineControllerFX " + e.Message);
            }
            Debug.Log("[KSPI]: End Initializing ElectricEngineControllerFX");
        }
 protected void UpdateFloatCurve(FloatCurve curve)
 {
     floatMod.curve = curve;
     UpdateModifierPanel();
 }
示例#26
0
        public static EngineSim New(PartSim theEngine,
                                    ModuleEngines engineMod,
                                    double atmosphere,
                                    float machNumber,
                                    bool vectoredThrust,
                                    bool fullThrust,
                                    LogMsg log)
        {
            float            maxFuelFlow                = engineMod.maxFuelFlow;
            float            minFuelFlow                = engineMod.minFuelFlow;
            float            thrustPercentage           = engineMod.thrustPercentage;
            List <Transform> thrustTransforms           = engineMod.thrustTransforms;
            List <float>     thrustTransformMultipliers = engineMod.thrustTransformMultipliers;
            Vector3          vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null,
                                                               vectoredThrust ? thrustTransformMultipliers : null,
                                                               log);
            FloatCurve        atmosphereCurve  = engineMod.atmosphereCurve;
            bool              atmChangeFlow    = engineMod.atmChangeFlow;
            FloatCurve        atmCurve         = engineMod.useAtmCurve ? engineMod.atmCurve : null;
            FloatCurve        velCurve         = engineMod.useVelCurve ? engineMod.velCurve : null;
            FloatCurve        thrustCurve      = engineMod.useThrustCurve ? engineMod.thrustCurve : null;
            float             currentThrottle  = engineMod.currentThrottle;
            float             IspG             = engineMod.g;
            bool              throttleLocked   = engineMod.throttleLocked || fullThrust;
            List <Propellant> propellants      = engineMod.propellants;
            float             thrustCurveRatio = engineMod.thrustCurveRatio;
            bool              active           = engineMod.isOperational;
            float             resultingThrust  = engineMod.resultingThrust;
            bool              isFlamedOut      = engineMod.flameout;

            EngineSim engineSim = pool.Borrow();

            engineSim.isp          = 0.0;
            engineSim.maxMach      = 0.0f;
            engineSim.actualThrust = 0.0;
            engineSim.partSim      = theEngine;
            engineSim.isActive     = active;
            engineSim.thrustVec    = vecThrust;
            engineSim.isFlamedOut  = isFlamedOut;
            engineSim.resourceConsumptions.Reset();
            engineSim.resourceFlowModes.Reset();
            engineSim.appliedForces.Clear();

            double flowRate = 0.0;

            if (engineSim.partSim.hasVessel)
            {
                if (log != null)
                {
                    log.AppendLine("hasVessel is true");
                }

                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, thrustCurve, thrustCurveRatio, ref engineSim.maxMach);
                engineSim.isp          = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust       = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0;
                if (log != null)
                {
                    log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                }

                if (throttleLocked)
                {
                    if (log != null)
                    {
                        log.AppendLine("throttleLocked is true, using thrust for flowRate");
                    }
                    flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                }
                else
                {
                    if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
                    {
                        // TODO: This bit doesn't work for RF engines
                        if (log != null)
                        {
                            log.AppendLine("throttled up and not landed, using actualThrust for flowRate");
                        }
                        flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
                    }
                    else
                    {
                        if (log != null)
                        {
                            log.AppendLine("throttled down or landed, using thrust for flowRate");
                        }
                        flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                    }
                }
            }
            else
            {
                if (log != null)
                {
                    log.buf.AppendLine("hasVessel is false");
                }
                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, thrustCurve, thrustCurveRatio, ref engineSim.maxMach);
                engineSim.isp          = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust       = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = 0d;
                if (log != null)
                {
                    log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                    log.AppendLine("no vessel, using thrust for flowRate");
                }

                flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
            }

            if (log != null)
            {
                log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);
            }

            float flowMass = 0f;

            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];
                if (!propellant.ignoreForIsp)
                {
                    flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
                }
            }

            if (log != null)
            {
                log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);
            }

            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];

                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                {
                    continue;
                }

                double consumptionRate = propellant.ratio * flowRate / flowMass;
                if (log != null)
                {
                    log.buf.AppendFormat(
                        "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
                        ResourceContainer.GetResourceName(propellant.id),
                        theEngine.name,
                        theEngine.partId,
                        consumptionRate);
                }
                engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
                engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode());
            }

            for (int i = 0; i < thrustTransforms.Count; i++)
            {
                Transform thrustTransform = thrustTransforms[i];
                Vector3d  direction       = thrustTransform.forward.normalized;
                Vector3d  position        = thrustTransform.position;

                AppliedForce appliedForce = AppliedForce.New(direction * engineSim.thrust * thrustTransformMultipliers[i], position);
                engineSim.appliedForces.Add(appliedForce);
            }

            return(engineSim);
        }
示例#27
0
 // Default constructor
 public FloatCurveParser()
 {
     this.curve = null;
 }
示例#28
0
            internal NumericInput(ConfigNode node, InternalProp internalProp)
            {
                if (!node.HasValue("switchTransform"))
                {
                    throw new Exception("USERINPUTSET missing switchTransform");
                }

                // XNOR!
                if (!(node.HasValue("increment") ^ node.HasNode("incrementCurve")))
                {
                    throw new Exception("USERINPUTSET missing increment or incrementCurve, or it has both");
                }

                if (node.HasValue("increment") && !float.TryParse(node.GetValue("increment"), out increment))
                {
                    throw new Exception("USERINPUTSET bad increment");
                }
                else if (node.HasNode("incrementCurve"))
                {
                    ConfigNode incNode = node.GetNode("incrementCurve");
                    string[]   keys    = incNode.GetValues("key");
                    incrementCurve = new FloatCurve();
                    for (int i = 0; i < keys.Length; ++i)
                    {
                        string[] values = keys[i].Split(' ');
                        if (values.Length == 2)
                        {
                            incrementCurve.Add(float.Parse(values[0]), float.Parse(values[1]));
                        }
                        else if (values.Length == 4)
                        {
                            incrementCurve.Add(float.Parse(values[0]), float.Parse(values[1]), float.Parse(values[2]), float.Parse(values[3]));
                        }
                        else
                        {
                            JUtil.LogErrorMessage(this, "Found a curve key with {0} entries?!?", values.Length);
                        }
                    }
                    pressAndHold = true;
                }

                if (node.HasValue("reverse"))
                {
                    bool.TryParse(node.GetValue("reverse"), out reverse);
                }

                if (node.HasValue("animationName"))
                {
                    animationName = node.GetValue("animationName").Trim();
                }

                float switchSoundVolume = 0.5f;

                if (node.HasValue("switchSoundVolume") && !float.TryParse("switchSoundVolume", out switchSoundVolume))
                {
                    switchSoundVolume = 0.5f;
                }

                if (node.HasValue("switchSound"))
                {
                    audioOutput = JUtil.SetupIVASound(internalProp, node.GetValue("switchSound").Trim(), switchSoundVolume, false);
                }

                if (node.HasValue("customSpeed") && !float.TryParse("customSpeed", out customSpeed))
                {
                    customSpeed = 1.0f;
                }

                if (!string.IsNullOrEmpty(animationName))
                {
                    // Set up the animation
                    Animation[] animators = internalProp.FindModelAnimators(animationName);
                    if (animators.Length > 0)
                    {
                        anim = animators[0];
                    }
                    else
                    {
                        JUtil.LogErrorMessage(this, "Could not find animation \"{0}\" on prop \"{1}\"",
                                              animationName, internalProp.name);
                        return;
                    }
                    anim[animationName].wrapMode = WrapMode.Once;

                    if (reverse)
                    {
                        anim[animationName].speed          = float.MaxValue;
                        anim[animationName].normalizedTime = 0.0f;
                    }
                    else
                    {
                        anim[animationName].speed          = float.MinValue;
                        anim[animationName].normalizedTime = 1.0f;
                    }
                    anim.Play(animationName);
                }

                string switchTransform = node.GetValue("switchTransform");

                if (incrementCurve != null)
                {
                    SmarterButton.CreateButton(internalProp, switchTransform, TimedClick, TimedRelease);
                }
                else
                {
                    SmarterButton.CreateButton(internalProp, switchTransform, Click, TimedRelease);
                }
            }
示例#29
0
        private void updateMeshEmissives(float progress, bool useLoop)
        {
            float      p = progress / (useLoop ? animationLoopTime : animationOnTime);
            FloatCurve rCurve = useLoop?emissiveOnRedCurve : emissiveLoopRedCurve, bCurve = useLoop?emissiveOnBlueCurve:emissiveLoopBlueCurve, gCurve = useLoop?emissiveOnGreenCurve:emissiveOnBlueCurve;

            color.r = rCurve.Evaluate(p);
            color.b = bCurve.Evaluate(p);
            color.g = gCurve.Evaluate(p);
            int len = emissiveRenderers.Count;

            for (int i = 0; i < len; i++)
            {
                if (emissiveRenderers[i] != null)
                {
                    emissiveRenderers[i].GetPropertyBlock(matProps);
                    matProps.SetColor(shaderEmissiveID, color);
                    emissiveRenderers[i].SetPropertyBlock(matProps);
                }
            }
        }
示例#30
0
        public PartStats(Part part)
        {
            this.mass = part.mass;

            if (part.partInfo.variant != null)
            {
                kRnDVariants       = KRnD.getVariants(part);
                currentVariant     = part.partInfo.variant.Name;
                currentVariantMass = part.partInfo.variant.Mass;
                variantBaseMass    = part.baseVariant.Mass;
            }
            if (kRnDVariants != null)
            {
                hasVariants = true;
            }
            else
            {
                currentVariantMass = 0;
                variantBaseMass    = 0;
                hasVariants        = false;
            }
            this.skinMaxTemp = part.skinMaxTemp;
            this.intMaxTemp  = part.maxTemp;

            // There should only be one or the other, engines or RCS:
            List <ModuleEngines> engineModules = KRnD.getEngineModules(part);
            ModuleRCS            rcsModule     = KRnD.getRcsModule(part);

            if (engineModules != null)
            {
                this.maxFuelFlows     = new List <float>();
                this.atmosphereCurves = new List <FloatCurve>();

                for (int i = 0; i < engineModules.Count; i++)
                {
                    ModuleEngines engineModule = engineModules[i];

                    this.maxFuelFlows.Add(engineModule.maxFuelFlow);

                    FloatCurve atmosphereCurve = new FloatCurve();
                    for (int i5 = 0; i5 < engineModule.atmosphereCurve.Curve.length; i5++)
                    {
                        Keyframe frame = engineModule.atmosphereCurve.Curve[i5];
                        atmosphereCurve.Add(frame.time, frame.value);
                    }
                    this.atmosphereCurves.Add(atmosphereCurve);
                }
            }
            else if (rcsModule)
            {
                this.maxFuelFlows     = new List <float>();
                this.atmosphereCurves = new List <FloatCurve>();

                this.maxFuelFlows.Add(rcsModule.thrusterPower);
                FloatCurve atmosphereCurve = new FloatCurve();
                for (int i = 0; i < rcsModule.atmosphereCurve.Curve.length; i++)
                {
                    Keyframe frame = rcsModule.atmosphereCurve.Curve[i];
                    atmosphereCurve.Add(frame.time, frame.value);
                }
                this.atmosphereCurves.Add(atmosphereCurve);
            }

            ModuleReactionWheel reactionWheel = KRnD.getReactionWheelModule(part);

            if (reactionWheel)
            {
                this.torque = reactionWheel.RollTorque; // There is also pitch- and yaw-torque, but they should all be the same
            }

            // WIP
            //ModuleDataTransmitter dataTransmitter = KRnD.getDataTransmitterModule(part);
            //if (dataTransmitter)
            //{
            //    this.antPower = dataTransmitter.antennaPower;
            //}

            ModuleResourceHarvester resourceHarvester = KRnD.getResourceHarvesterModule(part);

            if (resourceHarvester)
            {
                this.harvester = resourceHarvester.Efficiency;
            }

            ModuleActiveRadiator activeRadiator = KRnD.getActiveRadiatorModule(part);

            if (activeRadiator)
            {
                this.radiatorEfficiency = activeRadiator.maxEnergyTransfer;
            }

            ModuleDeployableSolarPanel solarPanel = KRnD.getSolarPanelModule(part);

            if (solarPanel)
            {
                this.chargeRate = solarPanel.chargeRate;
            }

            ModuleWheelBase landingLeg = KRnD.getLandingLegModule(part);

            if (landingLeg)
            {
                this.crashTolerance = part.crashTolerance; // Every part has a crash tolerance, but we only want to improve landing legs.
            }

            PartResource electricCharge = KRnD.getChargeResource(part);

            if (electricCharge != null)
            {
                this.batteryCharge = electricCharge.maxAmount;
            }

            ModuleGenerator generator = KRnD.getGeneratorModule(part);

            if (generator != null)
            {
                generatorEfficiency = new Dictionary <String, double>();
                for (int i = 0; i < generator.resHandler.outputResources.Count; i++)
                {
                    ModuleResource outputResource = generator.resHandler.outputResources[i];

                    generatorEfficiency.Add(outputResource.name, outputResource.rate);
                }
            }

            PartModule fissionGenerator = KRnD.getFissionGeneratorModule(part);

            if (fissionGenerator != null)
            {
                fissionPowerGeneration = KRnD.getGenericModuleValue(fissionGenerator, "PowerGeneration");
            }

            // There might be different converter-modules in the same part with different names (eg for Fuel, Monopropellant, etc):
            List <ModuleResourceConverter> converterList = KRnD.getConverterModules(part);

            if (converterList != null)
            {
                converterEfficiency = new Dictionary <String, Dictionary <String, double> >();
                for (int i = 0; i < converterList.Count; i++)
                {
                    ModuleResourceConverter converter = converterList[i];

                    Dictionary <String, double> thisConverterEfficiency = new Dictionary <String, double>();
                    for (int i2 = 0; i2 < converter.outputList.Count; i2++)
                    {
                        ResourceRatio resourceRatio = converter.outputList[i2];

                        thisConverterEfficiency.Add(resourceRatio.ResourceName, resourceRatio.Ratio);
                    }
                    converterEfficiency.Add(converter.ConverterName, thisConverterEfficiency);
                }
            }

            ModuleParachute parachute = KRnD.getParachuteModule(part);

            if (parachute)
            {
                this.chuteMaxTemp = parachute.chuteMaxTemp;
            }

            ModuleProceduralFairing fairing = KRnD.getFairingModule(part);

            if (fairing)
            {
                this.fairingAreaMass = fairing.UnitAreaMass;
            }

            List <PartResource> fuelResources = KRnD.getFuelResources(part);

            if (fuelResources != null)
            {
                fuelCapacities    = new Dictionary <string, double>();
                fuelCapacitiesSum = 0;
                for (int i = 0; i < fuelResources.Count; i++)
                {
                    PartResource fuelResource = fuelResources[i];

                    fuelCapacities.Add(fuelResource.resourceName, fuelResource.maxAmount);
                    fuelCapacitiesSum += fuelResource.maxAmount;
                }
            }
        }
示例#31
0
        public void BuildNewDragModel(double newS, FloatCurve newCd, FloatCurve newClPotential, FloatCurve newClViscous, FloatCurve newCm, Vector3 newCoD, double newMajorMinorAxisRatio, double newCosCutoffAngle, double newTaperCrossSectionArea, double newYmaxForce, double newXZmaxForce)
        {
            S                          = newS;
            CdCurve                    = newCd;
            ClPotentialCurve           = newClPotential;
            ClViscousCurve             = newClViscous;
            CmCurve                    = newCm;
            CenterOfDrag               = newCoD;
            majorMinorAxisRatio        = newMajorMinorAxisRatio;
            cosAngleCutoff             = newCosCutoffAngle;
            taperCrossSectionAreaRatio = newTaperCrossSectionArea / S;
            SPlusAttachArea            = S;

            YmaxForce  = newYmaxForce;
            XZmaxForce = newXZmaxForce;

            UpdateUpVector(true);
        }
 public override void OnLoad(ConfigNode node)
 {
     base.OnLoad(node);
     if (node.HasNode("baseIgnitionChance"))
     {
         Log("IgnitionFail: Loading baseIgnitionChance curve");
         baseIgnitionChance = new FloatCurve();
         baseIgnitionChance.Load(node.GetNode("baseIgnitionChance"));
     }
     else
         baseIgnitionChance = null;
     if (node.HasNode("pressureCurve"))
     {
         Log("IgnitionFail: Loading pressure curve");
         pressureCurve = new FloatCurve();
         pressureCurve.Load(node.GetNode("pressureCurve"));
     }
     else
         pressureCurve = null;
 }
        public static void UpdateCurrentActiveBody(int index, CelestialBody body)
        {
            if (index != prevBodyIndex)
            {
                prevBodyIndex = index;
                currentBodyVisc = bodyAtmosphereConfiguration[prevBodyIndex];
                currentBody = body;

                prandtlMeyerMach = null;
                prandtlMeyerAngle = null;
            }
        }
        public override void OnFixedUpdate()
        {
            ModuleEngines curEngineT = (ModuleEngines)this.part.Modules ["ModuleEngines"];

            float throttle = curEngineT.currentThrottle;

            if (radhazard && throttle > 0 && rad_safety_features) {
                curEngineT.Events ["Shutdown"].Invoke ();
                curEngineT.currentThrottle = 0;
                curEngineT.requestedThrottle = 0;
                ScreenMessages.PostScreenMessage("Engines throttled down as they presently pose a radiation hazard!", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                foreach (FXGroup fx_group in part.fxGroups) {
                    fx_group.setActive (false);
                }
            }

            System.Random rand = new System.Random (new System.DateTime().Millisecond);

            List<Vessel> vessels = FlightGlobals.Vessels;
            List<Vessel> vessels_to_remove = new List<Vessel> ();
            List<ProtoCrewMember> crew_to_remove = new List<ProtoCrewMember> ();
            double death_prob = 1.0 - 1.0 * TimeWarp.fixedDeltaTime;
            if (radhazard && throttle > 0 && !rad_safety_features) {
                foreach (Vessel vess in vessels) {
                    float distance = (float)Vector3d.Distance (vessel.transform.position, vess.transform.position);
                    if (distance < 2000 && vess != this.vessel && vess.GetCrewCount() > 0) {
                        float inv_sq_dist = distance / 50.0f;
                        float inv_sq_mult = 1.0f / inv_sq_dist / inv_sq_dist;
                        List<ProtoCrewMember> vessel_crew = vess.GetVesselCrew ();
                        foreach (ProtoCrewMember crew_member in vessel_crew) {
                            if (UnityEngine.Random.value >= death_prob*inv_sq_mult) {
                                if(!vess.isEVA) {
                                    //Part part = vess.Parts.Find(p => p.protoModuleCrew.Contains(crew_member));
                                    //part.RemoveCrewmember (crew_member);
                                    //crew_member.Die ();
                                    ScreenMessages.PostScreenMessage(crew_member.name + " was killed by Neutron Radiation!", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                                    crew_to_remove.Add (crew_member);
                                }else{
                                    //vess.rootPart.Die();
                                    ScreenMessages.PostScreenMessage(crew_member.name + " was killed by Neutron Radiation!", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                                    vessels_to_remove.Add (vess);
                                }
                            }
                        }
                    }
                }

                foreach (Vessel vess in vessels_to_remove) {
                    vess.rootPart.Die ();
                }

                foreach (ProtoCrewMember crew_member in crew_to_remove) {
                    Vessel vess = FlightGlobals.Vessels.Find (p => p.GetVesselCrew ().Contains (crew_member));
                    Part part = vess.Parts.Find(p => p.protoModuleCrew.Contains(crew_member));
                    part.RemoveCrewmember (crew_member);
                    crew_member.Die ();
                }
            }

            if (throttle > 0) {
                curEngineT.propellants [1].ratio = (float) (standard_megajoule_rate / throttle / throttle);
                curEngineT.propellants [2].ratio = (float) (standard_deut_rate / throttle / throttle);
                curEngineT.propellants [3].ratio = (float) (standard_lith_rate / throttle / throttle);
                FloatCurve newISP = new FloatCurve();
                newISP.Add (0, (float)(minISP / throttle));
                curEngineT.atmosphereCurve = newISP;
            }
        }
 protected void UpdateRedCurve(FloatCurve curve)
 {
     colorMod.rCurve = curve;
     UpdateModifierPanel();
 }
 public override void UpdateCurves(FloatCurve newCurve, string tag)
 {
     base.UpdateCurves(newCurve, tag);
 }
示例#37
0
 // Default constructor
 public FloatCurveParser(FloatCurve curve)
 {
     this.curve = curve;
 }
示例#38
0
        public override void OnLoad(ConfigNode node)
        {
            base.OnLoad(node);

            // Manually reload ignitions if not in editor
            if (!HighLogic.LoadedSceneIsEditor)
            {
                node.TryGetValue("ignited", ref ignited);
            }
            int pCount = propellants.Count;

            // thrust curve
            useThrustCurve = false;
            if (node.HasNode("thrustCurve") && node.HasValue("curveResource"))
            {
                if (node.GetValue("curveResource") != curveResource)
                {
                    Debug.LogError("*RFE* ERROR: curveResource doesn't match node's!");
                    curveResource = node.GetValue("curveResource");
                }
                if (thrustCurve == null)
                {
                    Debug.LogError("*RFE* ERROR: have curve node but thrustCurve is null!");
                    thrustCurve = new FloatCurve();
                    thrustCurve.Load(node.GetNode("thrustCurve"));
                }

                if (curveResource != string.Empty)
                {
                    for (int i = 0; i < pCount; ++i)
                    {
                        if (propellants[i].name.Equals(curveResource))
                        {
                            curveProp = i;
                            break;
                        }
                    }
                    if (curveProp != -1)
                    {
                        useThrustCurve = true;
                    }
                }

                Fields["thrustPercentage"].guiActive = Fields["thrustPercentage"].guiActiveEditor = (minFuelFlow != maxFuelFlow);
            }

            // Set from propellants
            bool instantThrottle = false;

            for (int i = 0; i < pCount; ++i)
            {
                if (RFSettings.Instance.instantThrottleProps.Contains(propellants[i].name))
                {
                    instantThrottle = true;
                }
                // any other stuff
            }

            // FIXME calculating throttle change rate
            if (!instantThrottle)
            {
                if (throttleResponseRate <= 0f)
                {
                    throttleResponseRate = (float)(RFSettings.Instance.throttlingRate / Math.Log(Math.Max(RFSettings.Instance.throttlingClamp, Math.Sqrt(part.mass * maxThrust * maxThrust))));
                }
            }
            else
            {
                throttleResponseRate = 1000000f;
            }

            minThrottle = minFuelFlow / maxFuelFlow;

            // set fields
            Fields["thrustCurveDisplay"].guiActive = useThrustCurve;
            CreateEngine();

            if (ullageSet == null)
            {
                ullageSet = new Ullage.UllageSet(this);
            }

            // Get thrust axis (only on create prefabs)
            if (part.partInfo == null || part.partInfo.partPrefab == null)
            {
                thrustAxis = Vector3.zero;
                foreach (Transform t in part.FindModelTransforms(thrustVectorTransformName))
                {
                    thrustAxis -= t.forward;
                }
                thrustAxis = thrustAxis.normalized;
            }
            ullageSet.SetThrustAxis(thrustAxis);

            // ullage
            if (node.HasNode("Ullage"))
            {
                ullageSet.Load(node.GetNode("Ullage"));
            }
            if (node.HasValue("pressureFed"))
            {
                bool.TryParse(node.GetValue("pressureFed"), out pressureFed);
                Debug.Log(this.name + ".pressureFed = " + this.pressureFed);
            }
            ullageSet.SetUllageEnabled(ullage);

            // load ignition resources
            if (node.HasNode("IGNITOR_RESOURCE"))
            {
                ignitionResources.Clear();
            }
            foreach (ConfigNode n in node.GetNodes("IGNITOR_RESOURCE"))
            {
                ModuleResource res = new ModuleResource();
                res.Load(n);
                ignitionResources.Add(res);
            }
        }
示例#39
0
        public void OverriddenStart()
        {
            var range = (UI_FloatRange)this.Fields["CurrentSafetyOverride"].uiControlEditor;

            range.minValue = 0f;
            range.maxValue = MaximumTemperature;

            range          = (UI_FloatRange)this.Fields["CurrentSafetyOverride"].uiControlFlight;
            range.minValue = 0f;
            range.maxValue = MaximumTemperature;

            throttleCurve = new FloatCurve();
            throttleCurve.Add(0, 0, 0, 0);
            throttleCurve.Add(50, 20, 0, 0);
            throttleCurve.Add(100, 100, 0, 0);

            Actions["TogglePanelAction"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Action_TogglePanelAction");

            Events["ShowReactorControl"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Event_ShowReactorControl");
            Events["RepairReactor"].guiName      = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Event_RepairReactor");

            Fields["CurrentSafetyOverride"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CurrentSafetyOverride");
            Fields["CurrentPowerPercent"].guiName   = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CurrentPowerPercent");
            Fields["ReactorOutput"].guiName         = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_ReactorOutput");
            Fields["ThermalTransfer"].guiName       = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_ThermalTransfer");
            Fields["CoreTemp"].guiName   = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CoreTemp");
            Fields["CoreStatus"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CoreStatus");
            Fields["FuelStatus"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_FuelStatus");

            if (base.ModuleIsActive())
            {
                activeFlag = true;
            }
            else
            {
                activeFlag = false;
            }

            if (FirstLoad)
            {
                this.CurrentSafetyOverride = this.CriticalTemperature;
                FirstLoad = false;
            }

            if (HighLogic.LoadedScene != GameScenes.EDITOR)
            {
                core = this.GetComponent <ModuleCoreHeatNoCatchup>();



                SetupCore();
                SetupResourceRatios();

                if (OverheatAnimation != "")
                {
                    overheatStates = Utils.SetUpAnimation(OverheatAnimation, this.part);
                }

                if (FollowThrottle)
                {
                    reactorEngine = this.GetComponent <FissionEngine>();
                }
            }
            else
            {
                //this.CurrentSafetyOverride = this.NominalTemperature;
            }
        }
 public void estimateEditorPerformance() {
     bool attached_reactor_upgraded = false;
     FloatCurve atmospherecurve = new FloatCurve();
     float thrust = 0;
     if (myAttachedReactor != null) {
         if (myAttachedReactor is IUpgradeableModule) {
             IUpgradeableModule upmod = myAttachedReactor as IUpgradeableModule;
             if (upmod.HasTechsRequiredToUpgrade()) {
                 attached_reactor_upgraded = true;
             }
         }
         maxISP = (float)(Math.Sqrt((double)myAttachedReactor.CoreTemperature) * isp_temp_rat * ispMultiplier);
         minISP = maxISP * 0.4f;
         atmospherecurve.Add(0, maxISP, 0, 0);
         atmospherecurve.Add(1, minISP, 0, 0);
         thrust = (float)(2 * myAttachedReactor.MaximumPower * 1000 / g0 / maxISP);
         myAttachedEngine.maxThrust = thrust;
         myAttachedEngine.atmosphereCurve = atmospherecurve;
     } else {
         atmospherecurve.Add(0, 0.00001f, 0, 0);
         myAttachedEngine.maxThrust = thrust;
         myAttachedEngine.atmosphereCurve = atmospherecurve;
     }
 }
        private void InitializeParticlesHydrogenCubeM()
        {
            if (ParticlesHydrogenCubePerMeter != null)
            {
                return;
            }

            ParticlesHydrogenCubePerMeter = new FloatCurve();

            ParticlesHydrogenCubePerMeter.Add(0, 0);
            ParticlesHydrogenCubePerMeter.Add(72.5f, 1.747e+9f);
            ParticlesHydrogenCubePerMeter.Add(73.0f, 2.872e+9f);
            ParticlesHydrogenCubePerMeter.Add(73.5f, 5.154e+9f);
            ParticlesHydrogenCubePerMeter.Add(74.0f, 1.009e+10f);
            ParticlesHydrogenCubePerMeter.Add(74.5f, 2.138e+10f);
            ParticlesHydrogenCubePerMeter.Add(75.0f, 4.836e+10f);
            ParticlesHydrogenCubePerMeter.Add(75.5f, 1.144e+11f);
            ParticlesHydrogenCubePerMeter.Add(76.0f, 2.760e+11f);
            ParticlesHydrogenCubePerMeter.Add(76.5f, 6.612e+11f);
            ParticlesHydrogenCubePerMeter.Add(77.0f, 1.531e+12f);
            ParticlesHydrogenCubePerMeter.Add(77.5f, 3.351e+12f);
            ParticlesHydrogenCubePerMeter.Add(78.0f, 6.813e+12f);
            ParticlesHydrogenCubePerMeter.Add(78.5f, 1.274e+13f);
            ParticlesHydrogenCubePerMeter.Add(79.0f, 2.180e+13f);
            ParticlesHydrogenCubePerMeter.Add(79.5f, 3.420e+13f);
            ParticlesHydrogenCubePerMeter.Add(80.0f, 4.945e+13f);
            ParticlesHydrogenCubePerMeter.Add(80.5f, 6.637e+13f);
            ParticlesHydrogenCubePerMeter.Add(81.0f, 8.346e+13f);
            ParticlesHydrogenCubePerMeter.Add(81.5f, 9.920e+13f);
            ParticlesHydrogenCubePerMeter.Add(82.0f, 1.124e+14f);
            ParticlesHydrogenCubePerMeter.Add(82.5f, 1.225e+14f);
            ParticlesHydrogenCubePerMeter.Add(83.0f, 1.292e+14f);
            ParticlesHydrogenCubePerMeter.Add(83.5f, 1.328e+14f);
            ParticlesHydrogenCubePerMeter.Add(84.0f, 1.335e+14f);
            ParticlesHydrogenCubePerMeter.Add(84.5f, 1.320e+14f);
            ParticlesHydrogenCubePerMeter.Add(85.0f, 1.287e+14f);
            ParticlesHydrogenCubePerMeter.Add(85.5f, 1.241e+14f);
            ParticlesHydrogenCubePerMeter.Add(86.0f, 1.187e+14f);
            ParticlesHydrogenCubePerMeter.Add(87, 1.066e+13f);
            ParticlesHydrogenCubePerMeter.Add(88, 9.426e+13f);
            ParticlesHydrogenCubePerMeter.Add(89, 8.257e+13f);
            ParticlesHydrogenCubePerMeter.Add(90, 7.203e+13f);
            ParticlesHydrogenCubePerMeter.Add(91, 6.276e+13f);
            ParticlesHydrogenCubePerMeter.Add(92, 5.474e+13f);
            ParticlesHydrogenCubePerMeter.Add(93, 4.786e+13f);
            ParticlesHydrogenCubePerMeter.Add(94, 4.198e+13f);
            ParticlesHydrogenCubePerMeter.Add(95, 3.698e+13f);
            ParticlesHydrogenCubePerMeter.Add(96, 3.272e+13f);
            ParticlesHydrogenCubePerMeter.Add(97, 2.909e+13f);
            ParticlesHydrogenCubePerMeter.Add(98, 2.598e+13f);
            ParticlesHydrogenCubePerMeter.Add(99, 2.332e+13f);
            ParticlesHydrogenCubePerMeter.Add(100, 2.101e+13f);
            ParticlesHydrogenCubePerMeter.Add(101, 1.901e+13f);
            ParticlesHydrogenCubePerMeter.Add(102, 1.726e+13f);
            ParticlesHydrogenCubePerMeter.Add(103, 1.572e+13f);
            ParticlesHydrogenCubePerMeter.Add(104, 1.435e+13f);
            ParticlesHydrogenCubePerMeter.Add(105, 1.313e+13f);
            ParticlesHydrogenCubePerMeter.Add(106, 1.203e+13f);
            ParticlesHydrogenCubePerMeter.Add(107, 1.104e+13f);
            ParticlesHydrogenCubePerMeter.Add(108, 1.013e+13f);
            ParticlesHydrogenCubePerMeter.Add(109, 9.299e+13f);
            ParticlesHydrogenCubePerMeter.Add(110, 8.534e+12f);
            ParticlesHydrogenCubePerMeter.Add(111, 7.827e+12f);
            ParticlesHydrogenCubePerMeter.Add(112, 7.173e+12f);
            ParticlesHydrogenCubePerMeter.Add(113, 6.569e+12f);
            ParticlesHydrogenCubePerMeter.Add(114, 6.012e+12f);
            ParticlesHydrogenCubePerMeter.Add(115, 5.500e+12f);
            ParticlesHydrogenCubePerMeter.Add(120, 3.551e+12f);
            ParticlesHydrogenCubePerMeter.Add(125, 2.477e+12f);
            ParticlesHydrogenCubePerMeter.Add(130, 1.805e+12f);
            ParticlesHydrogenCubePerMeter.Add(140, 1.029e+12f);
            ParticlesHydrogenCubePerMeter.Add(150, 6.468e+11f);
            ParticlesHydrogenCubePerMeter.Add(160, 4.485e+11f);
            ParticlesHydrogenCubePerMeter.Add(170, 3.400e+11f);
            ParticlesHydrogenCubePerMeter.Add(180, 2.774e+11f);
            ParticlesHydrogenCubePerMeter.Add(190, 2.394e+11f);
            ParticlesHydrogenCubePerMeter.Add(200, 2.154e+11f);
            ParticlesHydrogenCubePerMeter.Add(210, 1.995e+11f);
            ParticlesHydrogenCubePerMeter.Add(220, 1.887e+11f);
            ParticlesHydrogenCubePerMeter.Add(230, 1.809e+11f);
            ParticlesHydrogenCubePerMeter.Add(240, 1.752e+11f);
            ParticlesHydrogenCubePerMeter.Add(250, 1.707e+11f);
            ParticlesHydrogenCubePerMeter.Add(300, 1.569e+11f);
            ParticlesHydrogenCubePerMeter.Add(350, 1.477e+11f);
            ParticlesHydrogenCubePerMeter.Add(400, 1.399e+11f);
            ParticlesHydrogenCubePerMeter.Add(450, 1.327e+11f);
            ParticlesHydrogenCubePerMeter.Add(500, 1.260e+11f);
            ParticlesHydrogenCubePerMeter.Add(550, 1.198e+11f);
            ParticlesHydrogenCubePerMeter.Add(600, 1.139e+11f);
            ParticlesHydrogenCubePerMeter.Add(650, 1.085e+11f);
            ParticlesHydrogenCubePerMeter.Add(700, 1.033e+11f);
            ParticlesHydrogenCubePerMeter.Add(750, 9.848e+10f);
            ParticlesHydrogenCubePerMeter.Add(800, 9.393e+10f);
            ParticlesHydrogenCubePerMeter.Add(850, 8.965e+10f);
            ParticlesHydrogenCubePerMeter.Add(900, 8.562e+10f);
            ParticlesHydrogenCubePerMeter.Add(950, 8.182e+10f);
            ParticlesHydrogenCubePerMeter.Add(1000, 7.824e+10f);
        }
示例#42
0
        public SolarPanel(ConfigNode node, InterestedVessel vessel, ProtoPartModuleSnapshot modulesnapshot, ProtoPartSnapshot partsnapshot)
        {
            if (node == null)
            {
                Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. node is null.");
                return;
            }
            if (vessel == null)
            {
                Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. vessel is null.");
                return;
            }
            if (modulesnapshot == null)
            {
                Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. modulesnapshot is null.");
                return;
            }
            if (partsnapshot == null)
            {
                Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. partsnapshot is null.");
                return;
            }
            this.vessel     = vessel;
            this.PartModule = modulesnapshot;

            if (node.HasValue("type"))
            {
                panelType = (ModuleDeployableSolarPanel.PanelType)System.Enum.Parse(typeof(ModuleDeployableSolarPanel.PanelType), node.GetValue("type"));
            }
            node.TryGetValue("chargeRate", ref chargeRate);
            node.TryGetValue("sunAOA", ref this.sunAOA);
            node.TryGetValue("flowRate", ref this.flowRate);
            node.TryGetValue("flowMult", ref this.flowMult);
            node.TryGetValue("efficiencyMult", ref this.efficiencyMult);
            if (node.HasValue("deployState"))
            {
                deployState = (ModuleDeployablePart.DeployState)System.Enum.Parse(typeof(ModuleDeployablePart.DeployState), node.GetValue("deployState"));
            }
            if (deployState != ModuleDeployablePart.DeployState.EXTENDED)
            {
                sunAOA   = 0f;
                flowRate = 0f;
            }

            AvailablePart avPart = PartLoader.getPartInfoByName(partsnapshot.partName);
            Part          part   = null;

            if (avPart != null)
            {
                part = avPart.partPrefab;
            }
            if (part == null)
            {
                Debug.Log("[UnloadedResources]: SolarPanel - Unable to Find Part: " + partsnapshot.partName);
                return;
            }

            if (part.Modules == null)
            {
                Debug.Log("[UnloadedResources]: SolarPanel -No defined Modules Part: " + partsnapshot.partName);
                return;
            }
            for (int i = 0; i < part.Modules.Count; ++i)
            {
                if (part.Modules[i] == null)
                {
                    continue;
                }
                if (part.Modules[i].moduleName == "ModuleDeployableSolarPanel" || part.Modules[i].moduleName == "KopernicusSolarPanel")
                {
                    ModuleDeployableSolarPanel panelModule = (ModuleDeployableSolarPanel)part.Modules[i];
                    solarNormal = panelModule.part.FindModelTransform(panelModule.secondaryTransformName).forward;
                    pivotAxis   = panelModule.part.FindModelTransform(panelModule.pivotName).up;
                    sunTracking = panelModule.isTracking && panelModule.trackingMode == ModuleDeployablePart.TrackingMode.SUN;
                    usesCurve   = panelModule.useCurve;
                    tempCurve   = panelModule.temperatureEfficCurve;
                    temperature = (float)partsnapshot.temperature;
                    powerCurve  = panelModule.powerCurve;
                    position    = partsnapshot.position;
                    orientation = partsnapshot.rotation;
                    break;
                }
            }
            this.moduleType = UnloadedResources.ModuleType.Producer;
        }
示例#43
0
        public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult,
                                           Vector3 previousTorque, float maxTorque, float maxAoA, FloatCurve liftCurve, FloatCurve dragCurve)
        {
            Rigidbody rb         = ml.part.rb;
            double    airDensity = ml.vessel.atmDensity;
            double    airSpeed   = ml.vessel.srfSpeed;
            Vector3d  velocity   = ml.vessel.srf_velocity;

            //temp values
            Vector3 CoL            = new Vector3(0, 0, -1f);
            float   liftMultiplier = BDArmorySettings.GLOBAL_LIFT_MULTIPLIER;
            float   dragMultiplier = BDArmorySettings.GLOBAL_DRAG_MULTIPLIER;


            //lift
            float AoA = Mathf.Clamp(Vector3.Angle(ml.transform.forward, velocity.normalized), 0, 90);

            if (AoA > 0)
            {
                double  liftForce      = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * liftMultiplier * liftCurve.Evaluate(AoA);
                Vector3 forceDirection = Vector3.ProjectOnPlane(-velocity, ml.transform.forward).normalized;
                rb.AddForceAtPosition((float)liftForce * forceDirection,
                                      ml.transform.TransformPoint(ml.part.CoMOffset + CoL));
            }

            //drag
            if (airSpeed > 0)
            {
                double dragForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * dragMultiplier * dragCurve.Evaluate(AoA);
                rb.AddForceAtPosition((float)dragForce * -velocity.normalized,
                                      ml.transform.TransformPoint(ml.part.CoMOffset + CoL));
            }


            //guidance
            if (airSpeed > 1)
            {
                Vector3 targetDirection;
                float   targetAngle;
                if (AoA < maxAoA)
                {
                    targetDirection = (targetPosition - ml.transform.position);
                    targetAngle     = Vector3.Angle(velocity.normalized, targetDirection) * 4;
                }
                else
                {
                    targetDirection = velocity.normalized;
                    targetAngle     = AoA;
                }

                Vector3 torqueDirection = -Vector3.Cross(targetDirection, velocity.normalized).normalized;
                torqueDirection = ml.transform.InverseTransformDirection(torqueDirection);

                float   torque      = Mathf.Clamp(targetAngle * steerMult, 0, maxTorque);
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, torqueDirection * torque, 1),
                                                             Vector3.forward);

                rb.AddRelativeTorque(finalTorque);

                return(finalTorque);
            }
            else
            {
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, Vector3.zero, 0.25f),
                                                             Vector3.forward);
                rb.AddRelativeTorque(finalTorque);
                return(finalTorque);
            }
        }
示例#44
0
        private void ExportGenericData(YAMLMappingNode node, IReadOnlyDictionary <uint, string> tos)
        {
            StreamedClip streamedClip = MuscleClip.Clip.StreamedClip;
            DenseClip    denseClip    = MuscleClip.Clip.DenseClip;
            ConstantClip constantClip = MuscleClip.Clip.ConstantClip;

            IReadOnlyList <StreamedFrame>      frames       = streamedClip.GenerateFrames();
            Dictionary <uint, Vector3Curve>    translations = new Dictionary <uint, Vector3Curve>();
            Dictionary <uint, QuaternionCurve> rotations    = new Dictionary <uint, QuaternionCurve>();
            Dictionary <uint, Vector3Curve>    scales       = new Dictionary <uint, Vector3Curve>();
            Dictionary <uint, Vector3Curve>    eulers       = new Dictionary <uint, Vector3Curve>();
            Dictionary <uint, FloatCurve>      floats       = new Dictionary <uint, FloatCurve>();

            int frameCount = Math.Max(denseClip.FrameCount - 1, frames.Count - 2);

            float[] frameCurvesValue = new float[streamedClip.CurveCount];
            for (int frame = 0, streamFrame = 1; frame < frameCount; frame++, streamFrame++)
            {
                bool          isAdd = true;
                float         time;
                StreamedFrame streamedFrame = null;
                if (streamFrame < frames.Count)
                {
                    streamedFrame = frames[streamFrame];
                    time          = streamedFrame.Time;
                }
                else
                {
                    time = (float)frame / SampleRate;
                }
                // number of stream curves which has key in current frame
                int streamFrameCurveCount = streamFrame < frames.Count ? streamedFrame.Curves.Count : 0;
                // total amount of curves which has key in current frame
                int frameCurveCount = streamFrameCurveCount + (int)denseClip.CurveCount + constantClip.Constants.Count;
                int streamOffset    = (int)streamedClip.CurveCount - streamFrameCurveCount;
                for (int curve = 0; curve < frameCurveCount;)
                {
                    int curveIndex;
                    IReadOnlyList <float> curvesValue;
                    int offset;

                    if (streamFrame < frames.Count && curve < streamedFrame.Curves.Count)
                    {
#warning TODO: read TCB and convert to in/out slope
#warning TODO: write only few values
                        for (int key = 0; key < streamedFrame.Curves.Count; key++)
                        {
                            frameCurvesValue[key] = streamedFrame.Curves[key].Value;
                        }
                        curveIndex  = streamedFrame.Curves[curve].Index;
                        curvesValue = frameCurvesValue;
                        offset      = 0;
                    }
                    else if (curve < streamFrameCurveCount + denseClip.CurveCount)
                    {
                        curveIndex  = curve + streamOffset;
                        curvesValue = denseClip.SampleArray;
                        offset      = streamFrameCurveCount - frame * (int)denseClip.CurveCount;
                    }
                    else
                    {
                        curveIndex  = curve + streamOffset;
                        curvesValue = constantClip.Constants;
                        offset      = streamFrameCurveCount + (int)denseClip.CurveCount;
                        isAdd       = frame == 0 || frame == frameCount - 1;
                    }

                    GenericBinding binding  = ClipBindingConstant.FindBinding(curveIndex);
                    uint           pathHash = binding.Path;

                    string path;
                    if (pathHash == 0)
                    {
                        curve++;
                        continue;
                    }
                    if (!tos.TryGetValue(pathHash, out path))
                    {
                        path = "dummy" + pathHash;
                        //Logger.Log(LogType.Debug, LogCategory.Export, $"Can't find path '{binding.Path}' in TOS for {ToLogString()}");
                    }

                    switch (binding.BindingType)
                    {
                    case BindingType.Translation:
                        float x = curvesValue[curve++ - offset];
                        float y = curvesValue[curve++ - offset];
                        float z = curvesValue[curve++ - offset];
                        float w = 0;
                        if (isAdd)
                        {
                            Vector3f trans = new Vector3f(x, y, z);

                            Vector3Curve transCurve;
                            if (!translations.TryGetValue(pathHash, out transCurve))
                            {
                                transCurve             = new Vector3Curve(AssetsFile, path);
                                translations[pathHash] = transCurve;
                            }

                            KeyframeTpl <Vector3f> transKey = new KeyframeTpl <Vector3f>(AssetsFile, time, trans);
                            transCurve.Curve.Curve.Add(transKey);
                        }
                        break;

                    case BindingType.Rotation:
                        x = curvesValue[curve++ - offset];
                        y = curvesValue[curve++ - offset];
                        z = curvesValue[curve++ - offset];
                        w = curvesValue[curve++ - offset];
                        if (isAdd)
                        {
                            Quaternionf rot = new Quaternionf(x, y, z, w);

                            QuaternionCurve rotCurve;
                            if (!rotations.TryGetValue(pathHash, out rotCurve))
                            {
                                rotCurve            = new QuaternionCurve(AssetsFile, path);
                                rotations[pathHash] = rotCurve;
                            }

                            KeyframeTpl <Quaternionf> rotKey = new KeyframeTpl <Quaternionf>(AssetsFile, time, rot);
                            rotCurve.Curve.Curve.Add(rotKey);
                        }
                        break;

                    case BindingType.Scaling:
                        x = curvesValue[curve++ - offset];
                        y = curvesValue[curve++ - offset];
                        z = curvesValue[curve++ - offset];
                        if (isAdd)
                        {
                            Vector3f scale = new Vector3f(x, y, z);

                            Vector3Curve scaleCurve;
                            if (!scales.TryGetValue(pathHash, out scaleCurve))
                            {
                                scaleCurve       = new Vector3Curve(AssetsFile, path);
                                scales[pathHash] = scaleCurve;
                            }

                            KeyframeTpl <Vector3f> scaleKey = new KeyframeTpl <Vector3f>(AssetsFile, time, scale);
                            scaleCurve.Curve.Curve.Add(scaleKey);
                        }
                        break;

                    case BindingType.EulerRotation:
                        x = curvesValue[curve++ - offset];
                        y = curvesValue[curve++ - offset];
                        z = curvesValue[curve++ - offset];
                        if (isAdd)
                        {
                            Vector3f euler = new Vector3f(x, y, z);

                            Vector3Curve eulerCurve;
                            if (!eulers.TryGetValue(pathHash, out eulerCurve))
                            {
                                eulerCurve       = new Vector3Curve(AssetsFile, path);
                                eulers[pathHash] = eulerCurve;
                            }

                            KeyframeTpl <Vector3f> eulerKey = new KeyframeTpl <Vector3f>(AssetsFile, time, euler);
                            eulerCurve.Curve.Curve.Add(eulerKey);
                        }
                        break;

                    case BindingType.Floats:
                        float value = curvesValue[curve++ - offset];
                        if (isAdd)
                        {
                            Float @float = new Float(value);

                            FloatCurve floatCurve;
                            if (!floats.TryGetValue(pathHash, out floatCurve))
                            {
                                floatCurve       = new FloatCurve(AssetsFile, path);
                                floats[pathHash] = floatCurve;
                            }

                            KeyframeTpl <Float> floatKey = new KeyframeTpl <Float>(AssetsFile, time, @float);
                            floatCurve.Curve.Curve.Add(floatKey);
                        }
                        break;

                    default:
#warning TODO: ???
                        curve++;
                        //throw new NotImplementedException(binding.BindingType.ToString());
                        break;
                    }
                }
            }

            node.Add("m_RotationCurves", rotations.Values.ExportYAML());
            node.Add("m_CompressedRotationCurves", YAMLMappingNode.Empty);
            node.Add("m_EulerCurves", eulers.Values.ExportYAML());
            node.Add("m_PositionCurves", translations.Values.ExportYAML());
            node.Add("m_ScaleCurves", scales.Values.ExportYAML());
            node.Add("m_FloatCurves", floats.Values.ExportYAML());
        }
示例#45
0
        public override void OnFixedUpdate()
        {
            temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K";

            if (curEngineT == null)
            {
                return;
            }

            throttle = curEngineT.currentThrottle > MinThrottleRatio ? curEngineT.currentThrottle : 0;

            if (throttle > 0)
            {
                if (vessel.atmDensity > maxAtmosphereDensity)
                {
                    ShutDown("Inertial Fusion cannot operate in atmosphere!");
                }

                if (radhazard && rad_safety_features)
                {
                    ShutDown("Engines throttled down as they presently pose a radiation hazard");
                }
            }

            KillKerbalsWithRadiation(throttle);

            if (throttle > 0)
            {
                // Calculate Fusion Ratio
                enginePowerRequirement = CurrentPowerRequirement;

                var recievedPower = CheatOptions.InfiniteElectricity
                    ? enginePowerRequirement
                    : consumeFNResourcePerSecond(enginePowerRequirement, ResourceManager.FNRESOURCE_MEGAJOULES);

                var plasma_ratio = recievedPower / enginePowerRequirement;
                fusionRatio = plasma_ratio >= 1 ? 1 : plasma_ratio > 0.75 ? Math.Pow(plasma_ratio, 6) : 0;

                laserWasteheat = recievedPower * (1 - LaserEfficiency);

                // The Aborbed wasteheat from Fusion
                var rateMultplier        = minISP / SelectedIsp;
                var neutronbsorbionBonus = 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - minISP) / (MaxIsp - minISP)));
                absorbedWasteheat = FusionWasteHeat * wasteHeatMultiplier * fusionRatio * throttle * neutronbsorbionBonus;

                // Lasers produce Wasteheat
                if (!CheatOptions.IgnoreMaxTemperature)
                {
                    supplyFNResourcePerSecond(laserWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT);
                    supplyFNResourcePerSecond(absorbedWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT);
                }

                // change ratio propellants Hydrogen/Fusion
                curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio = (float)(standard_deuterium_rate / rateMultplier);
                curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio   = (float)(standard_tritium_rate / rateMultplier);

                // Update ISP
                var currentIsp = SelectedIsp;
                var newISP     = new FloatCurve();
                newISP.Add(0, currentIsp);
                newISP.Add(1, 0);
                curEngineT.atmosphereCurve = newISP;

                // Update FuelFlow
                var maxFuelFlow = fusionRatio * MaximumThrust / currentIsp / PluginHelper.GravityConstant;
                curEngineT.maxFuelFlow = (float)maxFuelFlow;
                curEngineT.maxThrust   = MaximumThrust;

                maximumThrust = MaximumThrust;

                if (!curEngineT.getFlameoutState && plasma_ratio < 0.75 && recievedPower > 0)
                {
                    curEngineT.status = "Insufficient Electricity";
                }
            }
            else
            {
                enginePowerRequirement = 0;
                absorbedWasteheat      = 0;
                laserWasteheat         = 0;
                fusionRatio            = 0;

                var currentIsp = SelectedIsp;
                var newISP     = new FloatCurve();
                newISP.Add(0, currentIsp);
                newISP.Add(1, 0);
                curEngineT.atmosphereCurve = newISP;
                curEngineT.maxThrust       = MaximumThrust;
                var rateMultplier = minISP / SelectedIsp;

                var maxFuelFlow = MaximumThrust / currentIsp / PluginHelper.GravityConstant;
                curEngineT.maxFuelFlow = (float)maxFuelFlow;
                curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio = (float)(standard_deuterium_rate / rateMultplier);
                curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio   = (float)(standard_tritium_rate / rateMultplier);
            }

            coldBathTemp          = FNRadiator.getAverageRadiatorTemperatureForVessel(vessel);
            maxTempatureRadiators = FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel);
            radiatorPerformance   = Math.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001);
            partEmissiveConstant  = part.emissiveConstant;
        }
示例#46
0
 // Build the curve from the data found in the node
 void IParserEventSubscriber.Apply(ConfigNode node)
 {
     curve = new FloatCurve();
     curve.Load(node);
 }
示例#47
0
 public EngineBaseData(ModuleEnginesFX fx, FloatCurve isp, float thrust)
 {
     engineFX  = fx;
     maxThrust = thrust;
     ispCurve  = isp;
 }
示例#48
0
 public void UpdateCurve(FloatCurve curve)
 {
     // update the curve
     currentModWinForCurve.UpdateCurves(curve, currentCurveTag);
 }
示例#49
0
        public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, FloatCurve thrustCurve, float thrustCurveRatio, ref float maxMach)
        {
            float flowModifier = 1.0f;

            if (atmChangeFlow)
            {
                flowModifier = (float)(atmDensity / 1.225);
                if (atmCurve != null)
                {
                    flowModifier = atmCurve.Evaluate(flowModifier);
                }
            }
            if (velCurve != null)
            {
                flowModifier = flowModifier * velCurve.Evaluate(machNumber);
                maxMach      = velCurve.maxTime;
            }
            if (thrustCurve != null)
            {
                flowModifier = flowModifier * thrustCurve.Evaluate(thrustCurveRatio);
            }
            if (flowModifier < float.Epsilon)
            {
                flowModifier = float.Epsilon;
            }
            return(flowModifier);
        }
示例#50
0
        public string partName;          //for debugging

        public FuelNode(Part part, bool dVLinearThrust)
        {
            bool physicallySignificant = (part.physicalSignificance != Part.PhysicalSignificance.NONE);

            if (part.HasModule <ModuleLandingGear>() || part.HasModule <LaunchClamp>())
            {
                //Landing gear set physicalSignificance = NONE when they enter the flight scene
                //Launch clamp mass should be ignored.
                physicallySignificant = false;
            }
            if (physicallySignificant)
            {
                dryMass = part.mass;
            }

            inverseStage = part.inverseStage;
            isFuelLine   = (part is FuelLine);
            isSepratron  = part.IsSepratron();
            partName     = part.partInfo.name;

            //note which resources this part has stored
            foreach (PartResource r in part.Resources)
            {
                if (r.info.density > 0 && r.name != "IntakeAir")
                {
                    resources[r.info.id] = (float)r.amount;
                }
                resourcesUnobtainableFromParent.Add(r.info.id);
            }

            //record relevant engine stats
            ModuleEngines engine = part.Modules.OfType <ModuleEngines>().FirstOrDefault();

            if (engine != null)
            {
                //Only count engines that either are ignited or will ignite in the future:
                if (HighLogic.LoadedSceneIsEditor || inverseStage < Staging.CurrentStage || engine.getIgnitionState)
                {
                    //if an engine has been activated early, pretend it is in the current stage:
                    if (engine.getIgnitionState && inverseStage < Staging.CurrentStage)
                    {
                        inverseStage = Staging.CurrentStage;
                    }

                    isEngine = true;

                    // If we take into account the engine rotation
                    if (dVLinearThrust)
                    {
                        Vector3 thrust = Vector3d.zero;
                        foreach (var t in engine.thrustTransforms)
                        {
                            thrust -= t.forward / engine.thrustTransforms.Count;
                        }

                        Vector3 fwd = HighLogic.LoadedScene == GameScenes.EDITOR ? Vector3d.up : (HighLogic.LoadedScene == GameScenes.SPH ? Vector3d.forward : (Vector3d)engine.part.vessel.GetTransform().up);
                        fwdThrustRatio = Vector3.Dot(fwd, thrust);
                    }

                    maxThrust = engine.thrustPercentage / 100f * engine.maxThrust;

                    if (part.Modules.Contains("ModuleEngineConfigs") || part.Modules.Contains("ModuleHybridEngine") || part.Modules.Contains("ModuleHybridEngines"))
                    {
                        correctThrust = true;
                        if (HighLogic.LoadedSceneIsFlight && engine.realIsp > 0.0f)
                        {
                            maxThrust = maxThrust * engine.atmosphereCurve.Evaluate(0) / engine.realIsp; //engine.atmosphereCurve.Evaluate((float)FlightGlobals.ActiveVessel.atmDensity);
                        }
                    }
                    else
                    {
                        correctThrust = false;
                    }
                    ispCurve = engine.atmosphereCurve;

                    propellantSumRatioTimesDensity = engine.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id));
                    propellantRatios = engine.propellants.Where(prop => PartResourceLibrary.Instance.GetDefinition(prop.id).density > 0 && prop.name != "IntakeAir").ToDictionary(prop => prop.id, prop => prop.ratio);
                }
            }


            // And do the same for ModuleEnginesFX :(
            ModuleEnginesFX enginefx = part.Modules.OfType <ModuleEnginesFX>().Where(e => e.isEnabled).FirstOrDefault();

            if (enginefx != null)
            {
                //Only count engines that either are ignited or will ignite in the future:
                if (HighLogic.LoadedSceneIsEditor || inverseStage < Staging.CurrentStage || enginefx.getIgnitionState)
                {
                    //if an engine has been activated early, pretend it is in the current stage:
                    if (enginefx.getIgnitionState && inverseStage < Staging.CurrentStage)
                    {
                        inverseStage = Staging.CurrentStage;
                    }

                    isEngine = true;

                    // If we take into account the engine rotation
                    if (dVLinearThrust)
                    {
                        Vector3 thrust = Vector3d.zero;
                        foreach (var t in enginefx.thrustTransforms)
                        {
                            thrust -= t.forward / enginefx.thrustTransforms.Count;
                        }

                        Vector3 fwd = HighLogic.LoadedScene == GameScenes.EDITOR ? Vector3d.up : (HighLogic.LoadedScene == GameScenes.SPH ? Vector3d.forward : (Vector3d)enginefx.part.vessel.GetTransform().up);
                        fwdThrustRatio = Vector3.Dot(fwd, thrust);
                    }

                    maxThrust = enginefx.thrustPercentage / 100f * enginefx.maxThrust;

                    if (part.Modules.Contains("ModuleEngineConfigs") || part.Modules.Contains("ModuleHybridEngine") || part.Modules.Contains("ModuleHybridEngines"))
                    {
                        correctThrust = true;
                        if (HighLogic.LoadedSceneIsFlight && enginefx.realIsp > 0.0f)
                        {
                            maxThrust = maxThrust * enginefx.atmosphereCurve.Evaluate(0) / enginefx.realIsp; //engine.atmosphereCurve.Evaluate((float)FlightGlobals.ActiveVessel.atmDensity);
                        }
                    }
                    else
                    {
                        correctThrust = false;
                    }
                    ispCurve = enginefx.atmosphereCurve;

                    propellantSumRatioTimesDensity = enginefx.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id));
                    propellantRatios = enginefx.propellants.Where(prop => PartResourceLibrary.Instance.GetDefinition(prop.id).density > 0 && prop.name != "IntakeAir").ToDictionary(prop => prop.id, prop => prop.ratio);
                }
            }



            //figure out when this part gets decoupled. We do this by looking through this part and all this part's ancestors
            //and noting which one gets decoupled earliest (i.e., has the highest inverseStage). Some parts never get decoupled
            //and these are assigned decoupledInStage = -1.
            decoupledInStage = -1;
            Part p = part;

            while (true)
            {
                if (p.IsDecoupler() || p.IsLaunchClamp())
                {
                    if (p.inverseStage > decoupledInStage)
                    {
                        decoupledInStage = p.inverseStage;
                    }
                }
                if (p.parent == null)
                {
                    break;
                }
                else
                {
                    p = p.parent;
                }
            }
        }
示例#51
0
        public static float GetAirSpeed(Vessel vessel)
        {
            FloatCurve windCurve = GetPlanetWindCurve(vessel.mainBody);

            return(windCurve.Evaluate((float)vessel.altitude) + (float)vessel.srf_velocity.magnitude);
        }
示例#52
0
        private void UpdateThrustDependentCalcs()
        {
            PartResource solidFuel = part.Resources["SolidFuel"];

            double solidFuelMassG;

            if (solidFuel == null)
            {
                solidFuelMassG = UsingME ? 7.454 : 30.75;
            }
            else
            {
                solidFuelMassG = solidFuel.amount * solidFuel.info.density * Engine.g;
            }

            FloatCurve atmosphereCurve = Engine.atmosphereCurve;

            if (!UsingME)
            {
                //float burnTime0 = burnTimeME = (float)(atmosphereCurve.Evaluate(0) * solidFuelMassG / thrust);
                //float burnTime1 = (float)(atmosphereCurve.Evaluate(1) * solidFuelMassG / thrust);

                fuelRate = thrust / (atmosphereCurve.Evaluate(0f) * Engine.g);
                if (solidFuel != null)
                {
                    UpdateBurnTime();
                    thrustASL = string.Format("{0:F1}", fuelRate * atmosphereCurve.Evaluate(1f) * Engine.g);
                }
                //burnTime = string.Format("{0:F1}s ({1:F1}s Vac)", burnTime1, burnTime0);
                //fuelRate = solidFuelMassG / burnTime0;
            }
            else
            {
                thrust = (float)(atmosphereCurve.Evaluate(0) * solidFuelMassG / burnTimeME);
                if (thrust > maxThrust)
                {
                    burnTimeME = (float)Math.Ceiling(atmosphereCurve.Evaluate(0) * solidFuelMassG / maxThrust);
                    thrust     = (float)(atmosphereCurve.Evaluate(0) * solidFuelMassG / burnTimeME);
                }

                float thrust0 = Engine.maxThrust = thrust;
                float thrust1 = (float)(atmosphereCurve.Evaluate(1) * solidFuelMassG / burnTimeME);

                thrustME = thrust0.ToStringSI(unit: "N", exponent: 3) + " Vac / " + thrust1.ToStringSI(unit: "N", exponent: 3) + " ASL";
                srbISP   = string.Format("{1:F0}s Vac / {0:F0}s ASL", atmosphereCurve.Evaluate(1), atmosphereCurve.Evaluate(0));
                fuelRate = (float)solidFuelMassG / (burnTimeME * Engine.g);
            }

            // This equation is much easier. From StretchySRBs
            if (useOldHeatEquation)
            {
                heatProduction = (float)Math.Round((200f + 5200f / Math.Pow((burnTimeME + 20f), 0.75f)) * 0.5f);
            }
            // My equation.
            else
            {
                heatProduction = heatPerThrust * Mathf.Sqrt(thrust) / (1 + part.mass);
            }

            // ReSharper disable once InconsistentNaming
            // Rescale the bell.
            float bellScale1m = selectedBell.chokeEndRatio / selectedBell.bellChokeDiameter;

            bellScale = bellScale1m * Mathf.Sqrt(thrust / thrust1m);

            UpdateEngineAndBellScale();
        }
 protected void UpdateBlueCurve(FloatCurve curve)
 {
     colorMod.bCurve = curve;
     UpdateModifierPanel();
 }
示例#54
0
        private void updateLights(float progress, bool useLoop)
        {
            float p = progress / (useLoop ? animationLoopTime : animationOnTime);

            if (float.IsNaN(p))
            {
                p = 0;
            }
            FloatCurve rCurve = useLoop ? lightLoopRedCurve : lightOnRedCurve, bCurve = useLoop ? lightLoopBlueCurve : lightOnBlueCurve, gCurve = useLoop ? lightLoopGreenCurve : lightOnGreenCurve;

            color.r = rCurve.Evaluate(p);
            color.b = bCurve.Evaluate(p);
            color.g = gCurve.Evaluate(p);
            foreach (LightData tr in lightTransforms)
            {
                tr.setColor(color);
            }
        }
        public override void OnFixedUpdate()
        {
            temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K";

            if (curEngineT == null) return;

            float throttle = curEngineT.currentThrottle;

            //double atmo_thrust_factor = Math.Min(1.0, Math.Max(1.0 - Math.Pow(vessel.atmDensity, 0.2), 0));

            if (throttle > 0)
            {
                if (vessel.atmDensity > maxAtmosphereDensity)
                    ShutDown("Inertial Fusion cannot operate in atmosphere!");

                if (radhazard && rad_safety_features)
                    ShutDown("Engines throttled down as they presently pose a radiation hazard");
            }

            KillKerbalsWithRadiation(throttle);

            coldBathTemp = (float)FNRadiator.getAverageRadiatorTemperatureForVessel(vessel);
            maxTempatureRadiators = (float)FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel);

            if (throttle > 0)
            {
                // Calculate Fusion Ratio
                var recievedPower = consumeFNResource(powerRequirement * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
                var plasma_ratio = recievedPower / (powerRequirement * TimeWarp.fixedDeltaTime);
                var fusionRatio = plasma_ratio >= 1 ? 1 : plasma_ratio > 0.75 ? Mathf.Pow((float)plasma_ratio, 6.0f) : 0;

                // Lasers produce Wasteheat
                supplyFNResource(recievedPower * (1 - efficiency), FNResourceManager.FNRESOURCE_WASTEHEAT);

                // The Aborbed wasteheat from Fusion
                supplyFNResource(FusionWasteHeat * wasteHeatMultiplier * fusionRatio * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT);

                // change ratio propellants Hydrogen/Fusion
                curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Deuterium).ratio = (float)(standard_deuterium_rate / throttle / throttle);
                curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Tritium).ratio = (float)(standard_tritium_rate / throttle / throttle);

                // Update ISP
                FloatCurve newISP = new FloatCurve();
                var currentIsp = Math.Max(minISP * fusionRatio / throttle, minISP / 10);
                newISP.Add(0, (float)currentIsp);
                curEngineT.atmosphereCurve = newISP;

                // Update FuelFlow
                var maxFuelFlow = fusionRatio * MaximumThrust / currentIsp / PluginHelper.GravityConstant;
                curEngineT.maxFuelFlow = (float)maxFuelFlow;

                if (!curEngineT.getFlameoutState)
                {
                    if (plasma_ratio < 0.75 && recievedPower > 0)
                        curEngineT.status = "Insufficient Electricity";
                }
            }
            else
            {
                FloatCurve newISP = new FloatCurve();
                newISP.Add(0, (float)minISP);
                curEngineT.atmosphereCurve = newISP;

                var maxFuelFlow = MaximumThrust / minISP / PluginHelper.GravityConstant;
                curEngineT.maxFuelFlow = (float)maxFuelFlow;
            }

            radiatorPerformance = (float)Math.Max(1 - (float)(coldBathTemp / maxTempatureRadiators), 0.000001);
            partEmissiveConstant = (float)part.emissiveConstant;
        }
 protected void UpdateGreenCurve(FloatCurve curve)
 {
     colorMod.gCurve = curve;
     UpdateModifierPanel();
 }
 public override void Startup()
 {
     base.Startup();
     // We don't want this getting triggered as a random failure
     core.DisableFailure("TestFlightFailure_IgnitionFail");
     Part prefab = this.part.partInfo.partPrefab;
     foreach (PartModule pm in prefab.Modules)
     {
         TestFlightFailure_IgnitionFail modulePrefab = pm as TestFlightFailure_IgnitionFail;
         if (modulePrefab != null && modulePrefab.Configuration == configuration)
         {
             if ((object)modulePrefab.baseIgnitionChance != null)
             {
                 Log("IgnitionFail: Loading baseIgnitionChance from prefab");
                 baseIgnitionChance = modulePrefab.baseIgnitionChance;
             }
             if ((object)modulePrefab.pressureCurve != null)
             {
                 Log("IgnitionFail: Loading pressureCurve from prefab");
                 pressureCurve = modulePrefab.pressureCurve;
             }
         }
     }
 }
 protected void UpdateAlphaCurve(FloatCurve curve)
 {
     colorMod.aCurve = curve;
     UpdateModifierPanel();
 }
示例#59
0
        public FuelNode(Part part)
        {
            bool physicallySignificant = (part.physicalSignificance != Part.PhysicalSignificance.NONE);
            if (part.HasModule<ModuleLandingGear>() || part.HasModule<LaunchClamp>())
            {
                //Landing gear set physicalSignificance = NONE when they enter the flight scene
                //Launch clamp mass should be ignored.
                physicallySignificant = false;
            }
            if (physicallySignificant) dryMass = part.mass;

            inverseStage = part.inverseStage;
            isFuelLine = (part is FuelLine);
            isSepratron = part.IsSepratron();
            partName = part.partInfo.name;

            //note which resources this part has stored
            foreach (PartResource r in part.Resources)
            {
                if (r.info.name != "ElectricCharge") resources[r.info.id] = (float)r.amount;
                resourcesUnobtainableFromParent.Add(r.info.id);
            }

            //record relevant engine stats
            ModuleEngines engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
            if (engine != null)
            {
                //Only count engines that either are ignited or will ignite in the future:
                if (HighLogic.LoadedSceneIsEditor || inverseStage < Staging.CurrentStage || engine.getIgnitionState)
                {
                    //if an engine has been activated early, pretend it is in the current stage:
                    if (engine.getIgnitionState && inverseStage < Staging.CurrentStage) inverseStage = Staging.CurrentStage;

                    isEngine = true;

                    maxThrust = engine.maxThrust;
                    ispCurve = engine.atmosphereCurve;

                    propellantSumRatioTimesDensity = engine.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id));
                    propellantRatios = engine.propellants.Where(prop => prop.name != "ElectricCharge").ToDictionary(prop => prop.id, prop => prop.ratio);
                }
            }

            //figure out when this part gets decoupled. We do this by looking through this part and all this part's ancestors
            //and noting which one gets decoupled earliest (i.e., has the highest inverseStage). Some parts never get decoupled
            //and these are assigned decoupledInStage = -1.
            decoupledInStage = -1;
            Part p = part;
            while (true)
            {
                if (p.IsDecoupler())
                {
                    if (p.inverseStage > decoupledInStage) decoupledInStage = p.inverseStage;
                }
                if (p.parent == null) break;
                else p = p.parent;
            }
        }
        // FixedUpdate is also called in the Editor
        public void FixedUpdate()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            if (_attached_engine == null)
            {
                return;
            }

            if (_attached_reactor != null && _attached_reactor.ChargedParticlePropulsionEfficiency > 0)
            {
                if (_attached_reactor.Part != this.part)
                {
                    resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass);
                    resourceBuffers.UpdateBuffers();
                }

                _max_charged_particles_power = _attached_reactor.MaximumChargedPower * exchanger_thrust_divisor * _attached_reactor.ChargedParticlePropulsionEfficiency;
                _charged_particles_requested = _attached_engine.isOperational && _attached_engine.currentThrottle > 0 ? _max_charged_particles_power : 0;
                _charged_particles_received  = consumeFNResourcePerSecond(_charged_particles_requested, ResourceManager.FNRESOURCE_CHARGED_PARTICLES);

                // convert reactor product into propellants when possible
                var chargedParticleRatio = _attached_reactor.MaximumChargedPower > 0 ? _charged_particles_received / _attached_reactor.MaximumChargedPower : 0;

                // update Isp
                var 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 / PluginHelper.GravityConstant;
                var calculatedConsumptionInTon   = max_engine_thrust_at_max_isp / maximum_isp / PluginHelper.GravityConstant;

                // generate addition propellant from reactor fuel consumption
                _attached_reactor.UseProductForPropulsion(chargedParticleRatio, calculatedConsumptionInTon);

                calculatedConsumptionPerSecond = calculatedConsumptionInTon * 1000;

                if (!CheatOptions.IgnoreMaxTemperature)
                {
                    if (_attached_engine.isOperational && _attached_engine.currentThrottle > 0)
                    {
                        consumeFNResourcePerSecond(_charged_particles_received, ResourceManager.FNRESOURCE_WASTEHEAT);
                        _previous_charged_particles_received = _charged_particles_received;
                    }
                    else if (_previous_charged_particles_received > 0)
                    {
                        consumeFNResourcePerSecond(_previous_charged_particles_received, ResourceManager.FNRESOURCE_WASTEHEAT);
                        _previous_charged_particles_received = 0;
                    }
                    else
                    {
                        _charged_particles_received          = 0;
                        _previous_charged_particles_received = 0;
                    }
                }

                // 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(Math.Max(powerBufferMax - powerBufferStore, 0), minimumEnginePower);
                _requestedElectricPower = minimumEnginePower + neededBufferPower;

                _recievedElectricPower = CheatOptions.InfiniteElectricity
                    ? _requestedElectricPower
                    : consumeFNResourcePerSecond(_requestedElectricPower, ResourceManager.FNRESOURCE_MEGAJOULES);

                // 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 atmoIspFactor = 1;

                _engineMaxThrust = 0;
                if (_max_charged_particles_power > 0)
                {
                    var enginethrust_from_recieved_particles = powerThrustModifier * _charged_particles_received * scaledPowerFactor / currentIsp / PluginHelper.GravityConstant;

                    var effective_thrust = Math.Max(enginethrust_from_recieved_particles - (radius * radius * vessel.atmDensity * 100), 0);

                    var max_theoretical_thrust = powerThrustModifier * _max_charged_particles_power / currentIsp / PluginHelper.GravityConstant;

                    atmoIspFactor = max_theoretical_thrust > 0 ? effective_thrust / max_theoretical_thrust : 0;

                    _engineMaxThrust = _attached_engine.currentThrottle > 0
                        ? Math.Max(effective_thrust, 0.000000001)
                        : Math.Max(max_theoretical_thrust, 0.000000001);
                }

                // set isp
                FloatCurve newAtmosphereCurve = new FloatCurve();
                newAtmosphereCurve.Add(0, (float)(currentIsp * scaledPowerFactor * atmoIspFactor), 0, 0);
                _attached_engine.atmosphereCurve = newAtmosphereCurve;

                var max_fuel_flow_rate = !double.IsInfinity(_engineMaxThrust) && !double.IsNaN(_engineMaxThrust) && currentIsp > 0
                    ? _engineMaxThrust / currentIsp / PluginHelper.GravityConstant / (_attached_engine.currentThrottle > 0 ? _attached_engine.currentThrottle : 1)
                    : 0;

                // set maximum flow
                _attached_engine.maxFuelFlow    = Math.Max((float)max_fuel_flow_rate, 0.0000000001f);
                _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.99)
                {
                    _attached_engine.status = "offline";
                }
                else if (megajoulesRatio < 0.75 && _requestedElectricPower > 0)
                {
                    _attached_engine.status = "Insufficient Electricity";
                }
                else if (atmoIspFactor < 0.01)
                {
                    _attached_engine.status = "Too dense atmospherere";
                }
            }
            else
            {
                _attached_engine.maxFuelFlow = 0.0000000001f;
                _recievedElectricPower       = 0;
                _charged_particles_requested = 0;
                _charged_particles_received  = 0;
                _engineMaxThrust             = 0;
            }
        }