Beispiel #1
0
        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;
            }
        }
        public static void GenerateCrossFlowDragCurve()
        {
            if (crossFlowDragMachCurve != null)
            {
                return;
            }

            crossFlowDragMachCurve = new FloatCurve();
            crossFlowDragMachCurve.Add(0, 1.2f, 0, 0);
            crossFlowDragMachCurve.Add(0.3f, 1.2f, 0, 0);
            crossFlowDragMachCurve.Add(0.7f, 1.5f, 0, 0);
            crossFlowDragMachCurve.Add(0.85f, 1.41f, 0, 0);
            crossFlowDragMachCurve.Add(0.95f, 2.1f, 0, 0);
            crossFlowDragMachCurve.Add(1f, 2f, -2f, -2f);
            crossFlowDragMachCurve.Add(1.3f, 1.6f, -0.5f, -0.5f);
            crossFlowDragMachCurve.Add(2f, 1.4f, -0.1f, -0.1f);
            crossFlowDragMachCurve.Add(5f, 1.25f, -0.02f, -0.02f);
            crossFlowDragMachCurve.Add(10f, 1.2f, 0, 0);

            crossFlowDragReynoldsCurve = new FloatCurve();
            crossFlowDragReynoldsCurve.Add(10000, 1f, 0, 0);
            crossFlowDragReynoldsCurve.Add(100000, 1.0083333333333333333333333333333f, 0, 0);
            crossFlowDragReynoldsCurve.Add(180000, 1.0083333333333333333333333333333f, 0, 0);
            crossFlowDragReynoldsCurve.Add(250000, 0.66666666666666666666666666666667f);
            crossFlowDragReynoldsCurve.Add(300000, 0.25f, -5E-07f, -5E-07f);
            crossFlowDragReynoldsCurve.Add(500000, 0.20833333333333333333333333333333f, 0, 0);
            crossFlowDragReynoldsCurve.Add(1000000, 0.33333333333333333333333333333333f, 7E-8f, 7E-8f);
            crossFlowDragReynoldsCurve.Add(10000000, 0.58333333333333333333333333333333f, 0, 0);
        }
Beispiel #3
0
  // pseudo-ctor
  public override void OnStart(StartState state)
  {
    switch(type)
    {
      case "temperature": Fields["Status"].guiName = "Temperature"; break;
      case "radiation": Fields["Status"].guiName = "Radiation"; break;
    }


    if (Lib.SceneIsGame() && type == "radiation")
    {
      Animation[] anim = this.part.FindModelAnimators("pinanim");
      if (anim.Length > 0)
      {
        pinanim = anim[0];
        pinanim["pinanim"].normalizedTime = 0.0f;
        pinanim["pinanim"].speed = 0.00001f;
        pinanim.Play();

        pinfc = new FloatCurve();
        pinfc.Add(0.0f, 0.0f);
        pinfc.Add((float)Settings.CosmicRadiation, 0.33f);
        pinfc.Add((float)Settings.StormRadiation, 0.66f);
        pinfc.Add((float)Settings.BeltRadiation, 1.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));
        }
Beispiel #5
0
  // pseudo-ctor
  public override void OnStart(StartState state)
  {
    switch(type)
    {
      case "temperature": Fields["Status"].guiName = "Temperature"; break;
      case "radiation": Fields["Status"].guiName = "Radiation"; break;
      case "solar_flux": Fields["Status"].guiName = "Solar flux"; break;
      case "albedo_flux": Fields["Status"].guiName = "Albedo flux"; break;
      case "body_flux": Fields["Status"].guiName = "Body flux"; break;
    }


    if (Lib.SceneIsGame() && type == "radiation")
    {
      Animation[] anim = this.part.FindModelAnimators("pinanim");
      if (anim.Length > 0)
      {
        pinanim = anim[0];
        pinanim["pinanim"].normalizedTime = 0.0f;
        pinanim["pinanim"].speed = 0.00001f;
        pinanim.Play();

        pinfc = new FloatCurve();
        pinfc.Add(0.0f, 0.0f);
        pinfc.Add(0.005f, 0.33f);
        pinfc.Add(1.0f, 0.66f);
        pinfc.Add(11.0f, 1.0f);
      }
    }
  }
        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, 0);
                DefaultLiftCurve.Add(8, .35f);
                //	DefaultLiftCurve.Add(19, 1);
                //	DefaultLiftCurve.Add(23, .9f);
                DefaultLiftCurve.Add(30, 1.5f);
                DefaultLiftCurve.Add(65, .6f);
                DefaultLiftCurve.Add(90, .7f);
            }

            if (DefaultDragCurve == null)
            {
                DefaultDragCurve = new FloatCurve();
                DefaultDragCurve.Add(0, 0.00215f);
                DefaultDragCurve.Add(5, .00285f);
                DefaultDragCurve.Add(15, .007f);
                DefaultDragCurve.Add(29, .01f);
                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));
        }
Beispiel #7
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, 0);
                DefaultLiftCurve.Add(8, .35f);
            //	DefaultLiftCurve.Add(19, 1);
            //	DefaultLiftCurve.Add(23, .9f);
                DefaultLiftCurve.Add(30, 1.5f);
                DefaultLiftCurve.Add(65, .6f);
                DefaultLiftCurve.Add(90, .7f);
            }

            if(DefaultDragCurve == null)
            {
                DefaultDragCurve = new FloatCurve();
                DefaultDragCurve.Add(0, 0.00215f);
                DefaultDragCurve.Add(5, .00285f);
                DefaultDragCurve.Add(15, .007f);
                DefaultDragCurve.Add(29, .01f);
                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 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) * PluginHelper.IspCoreTempMult * GetIspPropellantModifier());
                minISP = maxISP * 0.4f;
                atmospherecurve.Add(0, maxISP, 0, 0);
                atmospherecurve.Add(1, minISP, 0, 0);

                thrust = (float)(myAttachedReactor.MaximumPower * GetPowerTrustModifier() * GetHeatTrustModifier() / PluginHelper.GravityConstant / maxISP);
                myAttachedEngine.maxThrust       = thrust;
                myAttachedEngine.atmosphereCurve = atmospherecurve;
            }
            else
            {
                atmospherecurve.Add(0, 0.00001f, 0, 0);
                myAttachedEngine.maxThrust       = thrust;
                myAttachedEngine.atmosphereCurve = atmospherecurve;
            }
        }
        public override void OnStart(PartModule.StartState state)
        {
            base.OnStart(state);

            heatStates = Utils.SetUpAnimation(HeatAnimation, part);


            heatTransform = part.FindModelTransform(HeatTransformName);

            foreach (AnimationState heatState in heatStates)
            {
                heatState.AddMixingTransform(heatTransform);
                heatState.blendMode = AnimationBlendMode.Blend;
                heatState.layer     = 15;
                heatState.weight    = 1.0f;
                heatState.enabled   = true;
            }

            WindCurve = new FloatCurve();
            WindCurve.Add(0f, 0.5f);
            WindCurve.Add(1000f, 20f);
            WindCurve.Add(200000f, 0f);


            if (!TrackSun)
            {
                base.trackingSpeed = 0f;
            }

            part.force_activate();
        }
Beispiel #10
0
        private void initializeCurves()
        {
            // init curves, points are not accurate
            sinkRateCurve.Add(50, -1000);
            sinkRateCurve.Add(2500, -5000);
            sinkRatePullUpCurve.Add(50, -1500);
            sinkRatePullUpCurve.Add(100, -1600);
            sinkRatePullUpCurve.Add(2500, -7000);

            terrainCurve.Add(0, -4000);
            terrainCurve.Add(1400, -4600);
            terrainCurve.Add(1900, -7500);
            terrainCurve.Add(2100, -10000);
            terrainPullUpCurve.Add(0, -1500);
            terrainPullUpCurve.Add(1200, -3400);
            terrainPullUpCurve.Add(1350, -4000);
            terrainPullUpCurve.Add(1600, -6000);
            terrainBCurve.Add(0, -2000);
            terrainBCurve.Add(800, -2900);
            terrainPullUpBCurve.Add(0, -2400);
            terrainPullUpBCurve.Add(750, -3100);

            dontSinkCurve.Add(0, -0.1f);
            dontSinkCurve.Add(1500, -150);

            tooLowTerrainCurve.Add(0, 1.0f);
            tooLowTerrainCurve.Add(1.2f, 1.0f);
            tooLowTerrainCurve.Add(1.5f, 2.0f);

            bankAngleCurve.Add(5, 10);
            bankAngleCurve.Add(30, 10);
            bankAngleCurve.Add(150, 40);
            bankAngleCurve.Add(2450, 55);
        }
Beispiel #11
0
        public void Load(ConfigNode node)
        {
            node.TryGetValue("Name", ref Name);
            node.TryGetValue("Title", ref Title);
            node.TryGetValue("ResourceName", ref ResourceName);
            node.TryGetValue("Discovers", ref Discovers);
            node.TryGetValue("Identifies", ref Identifies);
            node.TryGetValue("Wavelength", ref Wavelength);
            node.TryGetValue("Sensitivity", ref Sensitivity);

            // Configure the default curve
            AtmosphereEffect = new FloatCurve();
            AtmosphereEffect.Add(0f, 1f);
            AtmosphereEffect.Add(70000f, 5f);
            AtmosphereEffect.Add(500000f, 0f);
            ConfigNode floatCurveNode = new ConfigNode();

            if (node.TryGetNode("AtmosphereEffect", ref floatCurveNode))
            {
                AtmosphereEffect.Load(floatCurveNode);
            }

            Wavelength *= 1E-9;
            Title       = Localizer.Format(Title);
        }
Beispiel #12
0
        public void SetIsp(float isp)
        {
            if (isp <= 0)
            {
                return;
            }
            FloatCurve resultcurve = new FloatCurve();

            this.realIsp = isp;
            isp          = isp * IspMultiplier;//In 0.25 all Isp are 1/5 real value, weird.
            resultcurve.Add(0, isp);
            resultcurve.Add(1, isp);

            switch (type)
            {
            case EngineType.ModuleEngine:
                engine.atmosphereCurve = resultcurve;
                break;

            case EngineType.ModuleEngineFX:
                engineFX.atmosphereCurve = resultcurve;
                break;

            case EngineType.FSengine:
                //                   fsengine.fuelConsumption = "0,0.0001;1," + (fsengine.maxThrust * 1000f / 9.801f / isp).ToString();
                break;
            }
        }
        public override void OnStart(PartModule.StartState state)
        {
            deployStates = Utils.SetUpAnimation(DeployAnimation, part);
            heatStates   = Utils.SetUpAnimation(HeatAnimation, part);


            PressureCurve = new FloatCurve();
            PressureCurve.Add(0f, 0f);
            PressureCurve.Add(1f, 1f);

            if (State == RadiatorState.Deployed || State == RadiatorState.Deploying)
            {
                foreach (AnimationState deployState in deployStates)
                {
                    deployState.normalizedTime = 1f;
                }
            }
            else if (State == RadiatorState.Retracted || State == RadiatorState.Retracting)
            {
                foreach (AnimationState deployState in deployStates)
                {
                    deployState.normalizedTime = 0f;
                }
            }
            else
            {
                // broken! none for you!
            }

            this.part.force_activate();
        }
        private void UpdateAtmosphericCurve()
        {
            FloatCurve newAtmosphereCurve = new FloatCurve();

            newAtmosphereCurve.Add(0, (float)effectiveIsp);
            newAtmosphereCurve.Add(maxAtmosphereDensity, 0);
            curEngineT.atmosphereCurve = newAtmosphereCurve;
        }
Beispiel #15
0
        public static FloatCurve createDefaultCurve()
        {
            FloatCurve fc = new FloatCurve();

            fc.Add(0, 0);
            fc.Add(1, 1);
            return(fc);
        }
Beispiel #16
0
        private void UpdateAtmosphericCurve(double isp)
        {
            var newAtmosphereCurve = new FloatCurve();

            newAtmosphereCurve.Add(0, (float)isp);
            newAtmosphereCurve.Add(maxAtmosphereDensity, 0);
            curEngineT.atmosphereCurve = newAtmosphereCurve;
        }
Beispiel #17
0
        public void updateIspEngineParams(double athmosphere_isp_efficiency = 1, double max_thrust_in_space = 0)
        {
            // recaculate ISP based on power and core temp available
            FloatCurve newISP = new FloatCurve();
            FloatCurve vCurve = new FloatCurve();

            maxISP = (float)(Math.Sqrt((double)myAttachedReactor.CoreTemperature) * (PluginHelper.IspCoreTempMult + IspTempMultOffset) * GetIspPropellantModifier());

            if (!currentpropellant_is_jet)
            {
                if (maxPressureTresholdAtKerbinSurface <= max_thrust_in_space && FlightGlobals.getStaticPressure(vessel.transform.position) <= 1)
                {
                    var min_engine_thrust        = Math.Max(max_thrust_in_space - maxPressureTresholdAtKerbinSurface, 0.00001);
                    var minThrustAtmosphereRatio = min_engine_thrust / Math.Max(max_thrust_in_space, 0.000001);
                    minISP = maxISP * (float)minThrustAtmosphereRatio * heatExchangerThrustDivisor;
                    newISP.Add(0, Mathf.Min(maxISP, PluginHelper.MaxThermalNozzleIsp), 0, 0);
                    newISP.Add(1, Mathf.Min(minISP, PluginHelper.MaxThermalNozzleIsp), 0, 0);
                }
                else
                {
                    newISP.Add(0, Mathf.Min(maxISP * (float)athmosphere_isp_efficiency, PluginHelper.MaxThermalNozzleIsp), 0, 0);
                }

                myAttachedEngine.useVelocityCurve      = false;
                myAttachedEngine.useEngineResponseTime = false;
            }
            else
            {
                if (myAttachedReactor.shouldScaleDownJetISP())
                {
                    maxISP = maxISP * 2.0f / 3.0f;
                    if (maxISP > 300)
                    {
                        maxISP = maxISP / 2.5f;
                    }
                }
                newISP.Add(0, Mathf.Min(maxISP * 4.0f / 5.0f, PluginHelper.MaxThermalNozzleIsp));
                newISP.Add(0.15f, Mathf.Min(maxISP, PluginHelper.MaxThermalNozzleIsp));
                newISP.Add(0.3f, Mathf.Min(maxISP * 4.0f / 5.0f, PluginHelper.MaxThermalNozzleIsp));
                newISP.Add(1, Mathf.Min(maxISP * 2.0f / 3.0f, PluginHelper.MaxThermalNozzleIsp));
                vCurve.Add(0, 1.0f);
                vCurve.Add((float)(maxISP * PluginHelper.GravityConstant * 1.0 / 3.0), 1.0f);
                vCurve.Add((float)(maxISP * PluginHelper.GravityConstant), 1.0f);
                vCurve.Add((float)(maxISP * PluginHelper.GravityConstant * 4.0 / 3.0), 0);
                myAttachedEngine.useVelocityCurve      = true;
                myAttachedEngine.useEngineResponseTime = true;
                myAttachedEngine.ignitionThreshold     = 0.01f;
            }

            myAttachedEngine.atmosphereCurve = newISP;
            myAttachedEngine.velocityCurve   = vCurve;
            assThermalPower = myAttachedReactor.MaximumPower;
            if (myAttachedReactor is InterstellarFusionReactor)
            {
                assThermalPower = assThermalPower * 0.95f;
            }
        }
Beispiel #18
0
        public static FloatCurve ListToFloatCurve(List <NumericCollectionParser <Single> > parser)
        {
            if (parser == null)
            {
                return(null);
            }

            // Additional error correction will only happen at runtime to keep the configs
            // compatible with the stock KSP behaviour
            if (!Injector.IsInPrefab)
            {
                // First make sure that all elements contain at least 2 values
                for (Int32 i = 0; i < parser.Count; i++)
                {
                    if (parser[i].Value.Count < 2)
                    {
                        while (parser[i].Value.Count < 2)
                        {
                            parser[i].Value.Add(0);
                        }
                    }
                }

                // Then make sure that no index is used twice
                for (Int32 i = 0; i < parser.Count; i++)
                {
                    while (parser.Count(p => Math.Abs(p.Value[0] - parser[i].Value[0]) < 0.001) > 1)
                    {
                        parser[i].Value[0] += 0.1f;
                    }
                }
            }

            FloatCurve curve = new FloatCurve();

            for (Int32 i = 0; i < parser.Count; i++)
            {
                NumericCollectionParser <Single> key = parser[i];

                if (key.Value.Count < 2)
                {
                    Debug.LogError("FloatCurve: Invalid line. Requires two values, 'time' and 'value'");
                }

                if (key.Value.Count == 4)
                {
                    curve.Add(key.Value[0], key.Value[1], key.Value[2], key.Value[3]);
                }
                else
                {
                    curve.Add(key.Value[0], key.Value[1]);
                }
            }

            return(curve);
        }
Beispiel #19
0
        public void InitializeOverallEngineData(
            double nMinFlow,
            double nMaxFlow,
            FloatCurve nAtmosphereCurve,
            FloatCurve nAtmCurve,
            FloatCurve nVelCurve,
            double nThrottleResponseRate,
            double nChamberNominalTemp,
            double nMachLimit,
            double nMachMult,
            double nFlowMultMin,
            double nFlowMultCap,
            double nFlowMultSharp,
            bool nMultFlow,
            double nVaryThrust,
            float nSeed)
        {
            minFlow                  = nMinFlow * 1000d; // to kg
            maxFlow                  = nMaxFlow * 1000d;
            atmosphereCurve          = nAtmosphereCurve;
            atmCurve                 = nAtmCurve;
            velCurve                 = nVelCurve;
            throttleResponseRate     = nThrottleResponseRate;
            chamberTemp              = 288d;
            chamberNominalTemp       = nChamberNominalTemp;
            chamberNominalTemp_recip = 1d / chamberNominalTemp;
            machLimit                = nMachLimit;
            machMult                 = nMachMult;
            flowMultMin              = nFlowMultMin;
            flowMultCap              = nFlowMultCap;
            flowMultCapSharpness     = nFlowMultSharp;
            multFlow                 = nMultFlow;
            varyThrust               = nVaryThrust;
            seed = nSeed;

            // falloff at > sea level pressure.
            if (atmosphereCurve.Curve.keys.Length == 2 && atmosphereCurve.Curve.keys[0].value != atmosphereCurve.Curve.keys[1].value)
            {
                Keyframe k0 = atmosphereCurve.Curve.keys[0];
                Keyframe k1 = atmosphereCurve.Curve.keys[1];
                if (k0.time > k1.time)
                {
                    Keyframe t = k0;
                    k0 = k1;
                    k1 = t;
                }
                float minIsp   = 0.0001f;
                float invSlope = (k1.time - k0.time) / (k0.value - k1.value);
                float maxP     = k1.time + (k1.value - minIsp) * invSlope;

                atmosphereCurve = new FloatCurve();
                atmosphereCurve.Add(k0.time, k0.value, k0.inTangent, k0.outTangent);
                atmosphereCurve.Add(k1.time, k1.value, k1.inTangent, k1.outTangent);
                atmosphereCurve.Add(maxP, minIsp);
            }
        }
        void LoadEfficiencyCurves()
        {
            ConfigNode turboPropEffNode = GameDatabase.Instance.GetConfigNodes("ProcEngTurbopumpEff")[0];
            ConfigNode node             = turboPropEffNode.GetNode("PumpEffFromSpecificSpeed");

            pumpEffFromSpecificSpeed = new FloatCurve();

            string[] vals = node.GetValues("key");
            for (int i = 0; i < vals.Length; ++i)
            {
                string[] splitString = vals[i].Split(new char[] { ',', ' ', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (splitString.Length == 2)
                {
                    pumpEffFromSpecificSpeed.Add(float.Parse(splitString[0]), float.Parse(splitString[1]));
                }
                else if (splitString.Length == 4)
                {
                    pumpEffFromSpecificSpeed.Add(float.Parse(splitString[0]), float.Parse(splitString[1]), float.Parse(splitString[2]), float.Parse(splitString[3]));
                }
            }

            node = turboPropEffNode.GetNode("PumpEffMultFromFlowrate");
            pumpEffMultFromFlowrate = new FloatCurve();

            vals = node.GetValues("key");
            for (int i = 0; i < vals.Length; ++i)
            {
                string[] splitString = vals[i].Split(new char[] { ',', ' ', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (splitString.Length == 2)
                {
                    pumpEffMultFromFlowrate.Add(float.Parse(splitString[0]), float.Parse(splitString[1]));
                }
                else if (splitString.Length == 4)
                {
                    pumpEffMultFromFlowrate.Add(float.Parse(splitString[0]), float.Parse(splitString[1]), float.Parse(splitString[2]), float.Parse(splitString[3]));
                }
            }

            node = turboPropEffNode.GetNode("TurbineEffFromIsentropicVelRatio");
            turbineEffFromIsentropicVelRatio = new FloatCurve();

            vals = node.GetValues("key");
            for (int i = 0; i < vals.Length; ++i)
            {
                string[] splitString = vals[i].Split(new char[] { ',', ' ', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (splitString.Length == 2)
                {
                    turbineEffFromIsentropicVelRatio.Add(float.Parse(splitString[0]), float.Parse(splitString[1]));
                }
                else if (splitString.Length == 4)
                {
                    turbineEffFromIsentropicVelRatio.Add(float.Parse(splitString[0]), float.Parse(splitString[1]), float.Parse(splitString[2]), float.Parse(splitString[3]));
                }
            }
        }
        public ResourceBand(string resourceName, ConfigNode node)
        {
            ResourceName = resourceName;
            string distName = "Uniform";


            node.TryGetValue("name", ref name);
            node.TryGetValue("title", ref title);
            node.TryGetValue("countScale", ref countScale);
            node.TryGetValue("rotateRate", ref rotateRate);

            node.TryGetValue("minAbundance", ref minAbundance);
            node.TryGetValue("maxAbundance", ref maxAbundance);
            node.TryGetValue("useAirDensity", ref useAirDensity);

            node.TryGetValue("alwaysDiscovered", ref AlwaysDiscovered);
            node.TryGetValue("alwaysIdentified", ref AlwaysIdentified);
            node.TryGetValue("alwaysIdentified", ref AlwaysIdentified);

            node.TryGetValue("distributionType", ref distName);

            node.TryGetValue("remoteDiscoveryScale", ref RemoteDiscoveryScale);

            discoveryScienceReward = Settings.BaseDiscoverScienceReward;
            identifyScienceReward  = Settings.BaseIdentifyScienceReward;
            node.TryGetValue("discoveryScienceReward", ref discoveryScienceReward);
            node.TryGetValue("identifyScienceReward", ref identifyScienceReward);

            title = Localizer.Format(title);

            densityCurve = new FloatCurve();

            if (useAirDensity)
            {
                densityCurve.Add(0f, 0f);
                densityCurve.Add(1f, 1f);
                densityCurve.Add(12f, 12f);
                ConfigNode densCurve = new ConfigNode();
                if (node.TryGetNode("densityCurve", ref densCurve))
                {
                    densityCurve.Load(densCurve);
                }
            }

            if (distName == "Uniform")
            {
                Distribution = new UniformDistributionModel(node) as DistributionModel;
            }

            if (distName == "Spherical")
            {
                Distribution = new SphericalDistributionModel(node) as DistributionModel;
            }
        }
        void UpdateInjectorPerformance()
        {
            if (throttleInjectorCurve == null)
            {
                throttleInjectorCurve = new FloatCurve();
                throttleInjectorCurve.Add(0.1f, 0.67f, -0.65f, -0.65f);
                throttleInjectorCurve.Add(1f, 0.2f, 0f, 0);
            }

            injectorPressureRatioDrop = throttleInjectorCurve.Evaluate((float)minThrottle);
            //TODO: handle techlevel
        }
 public void SetAddMode(ModuleWaterfallFX mod)
 {
     showWindow     = true;
     fxMod          = mod;
     windowMode     = ControllerPopupMode.Add;
     controllerFlag = 0;
     WindowPosition = new Rect(Screen.width / 2, Screen.height / 2f, 400, 400);
     eventCurve     = new FloatCurve();
     eventCurve.Add(0f, 0f);
     eventCurve.Add(0.1f, 1f);
     eventCurve.Add(1f, 0f);
     GenerateCurveThumbs();
 }
Beispiel #24
0
        // Loads all plugin data
        public static void LoadPluginData()
        {
            //key = 206000000000 0 0 0
            //key = 13599840256 1 0 0
            //key = 68773560320 0.5 0 0
            //key = 0 10 0 0

            solarCurve = new FloatCurve();
            solarCurve.Add(0f, 13660f);
            solarCurve.Add(68773560320f, 683f);
            solarCurve.Add(13599840256f, 1366f);
            solarCurve.Add(206000000000f, 0f);
        }
Beispiel #25
0
        private void CalculateCurves()
        {
            AtmoThrustCurve = new FloatCurve();
            AtmoThrustCurve.Add(0f, engine.maxThrust);
            AtmoThrustCurve.Add(1f, 0f);

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

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

            AtmoIspCurve.Add(1f, FindIsp(0f, rate, fuelPropellant));
        }
Beispiel #26
0
        public void Start()
        {
            if (!CompatibilityChecker.IsAllCompatible())
            {
                return;
            }

            GameEvents.onVesselWasModified.Add(OnVesselWasModified);
            GameEvents.onVesselGoOffRails.Add(OnVesselOffRails);
            GameEvents.onVesselGoOnRails.Add(OnVesselOnRails);

            physicsEasingCurve.Add(numTicksForEasing, 1);
            physicsEasingCurve.Add(0, 0);
        }
Beispiel #27
0
        // auto-generates a planet temperature curve from a messy thing
        public static FloatCurve GetPlanetTemperatureCurve(CelestialBody body)
        {
            FloatCurve planetCurve = new FloatCurve();

            // it is zero at the top
            planetCurve.Add(MaxAtmosphereHeight(body), 0f);
            // defined in terms of incoming radiation, atmospheric pressure at sea level
            // earth or kerbin is 1366 w/m2
            float baseIrradiance = solarCurve.Evaluate((float)FlightGlobals.getAltitudeAtPos(body.position, FlightGlobals.Bodies[0]));

            planetCurve.Add(0f, Mathf.Pow((float)body.staticPressureASL, 0.01f) * Mathf.Pow((float)body.atmosphereScaleHeight, 0.5f) * (baseIrradiance / 20f));

            return(planetCurve);
        }
Beispiel #28
0
        public override void OnLoad(ConfigNode node)
        {
            base.OnLoad(node);
            if (node.HasNode("ClCurve"))
            {
                ClPotentialCurve = new FloatCurve();
                ClPotentialCurve.Load(node.GetNode("ClCurve"));
                ClViscousCurve = new FloatCurve();
                ClViscousCurve.Add(-1, 0);
                ClViscousCurve.Add(1, 0);
            }
            if (node.HasValue("majorMinorAxisRatio"))
            {
                double.TryParse(node.GetValue("majorMinorAxisRatio"), out majorMinorAxisRatio);
            }
            if (node.HasValue("taperCrossSectionAreaRatio"))
            {
                double.TryParse(node.GetValue("taperCrossSectionAreaRatio"), out taperCrossSectionAreaRatio);
            }
            if (node.HasValue("cosAngleCutoff"))
            {
                double.TryParse(node.GetValue("cosAngleCutoff"), out cosAngleCutoff);
            }
            if (node.HasValue("ignoreAnim"))
            {
                bool.TryParse(node.GetValue("ignoreAnim"), out ignoreAnim);
            }

            if (node.HasNode("CdCurve"))
            {
                CdCurve = new FloatCurve();
                CdCurve.Load(node.GetNode("CdCurve"));
            }
            if (node.HasNode("ClPotentialCurve"))
            {
                ClPotentialCurve = new FloatCurve();
                ClPotentialCurve.Load(node.GetNode("ClPotentialCurve"));
            }
            if (node.HasNode("ClViscousCurve"))
            {
                ClViscousCurve = new FloatCurve();
                ClViscousCurve.Load(node.GetNode("ClViscousCurve"));
            }
            if (node.HasNode("CmCurve"))
            {
                CmCurve = new FloatCurve();
                CmCurve.Load(node.GetNode("CmCurve"));
            }
        }
Beispiel #29
0
 internal override void postControllerSetup()
 {
     base.postControllerSetup();
     if (!string.IsNullOrEmpty(steeringName))
     {
         steeringTransform = part.transform.FindChildren(steeringName)[wheelData.indexInDuplicates];
         defaultRotation   = steeringTransform.localRotation;
     }
     if (steeringCurve == null || steeringCurve.Curve.length == 0)
     {
         steeringCurve = new FloatCurve();
         steeringCurve.Add(0, 1f, -0.9f, -0.9f);
         steeringCurve.Add(1, 0.1f, -0.9f, -0.9f);
     }
 }
        public FARWingInteraction(
            FARWingAerodynamicModel parentModule,
            Part parentPart,
            Vector3 rootChordMid,
            short srfAttachNegative
            )
        {
            parentWingModule  = parentModule;
            parentWingPart    = parentPart;
            rootChordMidLocal = rootChordMid;
            srfAttachFlipped  = srfAttachNegative;

            if (wingCamberFactor == null)
            {
                wingCamberFactor = new FloatCurve();
                wingCamberFactor.Add(0, 0);
                for (double i = 0.1; i <= 0.9; i += 0.1)
                {
                    double tmp = i * 2;
                    tmp--;
                    tmp = Math.Acos(tmp);

                    tmp -= Math.Sin(tmp);
                    tmp /= Math.PI;
                    tmp  = 1 - tmp;

                    wingCamberFactor.Add((float)i, (float)tmp);
                }

                wingCamberFactor.Add(1, 1);
            }

            if (wingCamberMoment != null)
            {
                return;
            }
            wingCamberMoment = new FloatCurve();
            for (double i = 0; i <= 1; i += 0.1)
            {
                double tmp = i * 2;
                tmp--;
                tmp = Math.Acos(tmp);

                tmp = (Math.Sin(2 * tmp) - 2 * Math.Sin(tmp)) / (8 * (Math.PI - tmp + Math.Sin(tmp)));

                wingCamberMoment.Add((float)i, (float)tmp);
            }
        }
 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 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
                {
                    Log.dbg("Error parsing vector2");
                }
            }
        }
        return(resultCurve);
    }
Beispiel #33
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 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);
            }
        }
 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 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);
 }
		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;
            }
		}
 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);
 }
 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 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 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;
                }
            }
		}
		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 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;
            }
        }
		public void updateIspEngineParams() {
			// recaculate ISP based on power and core temp available
			FloatCurve newISP = new FloatCurve();
			FloatCurve vCurve = new FloatCurve ();
			maxISP = (float)(Math.Sqrt ((double)myAttachedReactor.CoreTemperature) * isp_temp_rat * ispMultiplier);
            
			if (!currentpropellant_is_jet) {
				minISP = maxISP * 0.4f;
                newISP.Add(0, Mathf.Min(maxISP, 2997.13f), 0, 0);
                newISP.Add(1, Mathf.Min(minISP, 2997.13f), 0, 0);
				myAttachedEngine.useVelocityCurve = false;
				myAttachedEngine.useEngineResponseTime = false;
			} else {
				if (myAttachedReactor.shouldScaleDownJetISP ()) {
					maxISP = maxISP*2.0f/3.0f;
					if (maxISP > 300) {
						maxISP = maxISP / 2.5f;
					}
				}
                newISP.Add(0, Mathf.Min(maxISP * 4.0f / 5.0f, 2997.13f));
                newISP.Add(0.15f, Mathf.Min(maxISP, 2997.13f));
                newISP.Add(0.3f, Mathf.Min(maxISP * 4.0f / 5.0f, 2997.13f));
                newISP.Add(1, Mathf.Min(maxISP * 2.0f / 3.0f, 2997.13f));
				vCurve.Add(0, 1.0f);
				vCurve.Add((float)(maxISP*g0*1.0/3.0), 1.0f);
				vCurve.Add((float)(maxISP*g0), 1.0f);
				vCurve.Add ((float)(maxISP*g0*4.0/3.0), 0);
				myAttachedEngine.useVelocityCurve = true;
				myAttachedEngine.useEngineResponseTime = true;
				myAttachedEngine.ignitionThreshold = 0.01f;
			}

			myAttachedEngine.atmosphereCurve = newISP;
			myAttachedEngine.velocityCurve = vCurve;
			assThermalPower = myAttachedReactor.MaximumPower;
            if (myAttachedReactor is InterstellarFusionReactor) {
                assThermalPower = assThermalPower * 0.95f;
            }
		}
        public override void OnStart(PartModule.StartState state)
        {
            throttleCurve = new FloatCurve();
            throttleCurve.Add(0, 0, 0, 0);
            throttleCurve.Add(70, 10, 0, 0);
            throttleCurve.Add(100, 100, 0, 0);

            if (UseStagingIcon)
            {
                //this.part.stackIcon.CreateIcon();
                //this.part.stackIcon.SetIcon(DefaultIcons.FUEL_TANK);
            }
            else
                Utils.LogWarn("Fission Reactor: Staging Icon Disabled!");

            if (state != StartState.Editor)
            {
                core = this.GetComponent<ModuleCoreHeat>();
                if (core == null)
                    Utils.LogError("Fission Reactor: Could not find core heat module!");

                SetupResourceRatios();
                // Set up staging icon heat bar

                if (UseStagingIcon)
                {
                    infoBox = this.part.stackIcon.DisplayInfo();

                    //infoBox.SetMsgBgColor(XKCDColors.RedOrange);
                    //infoBox.SetMsgTextColor(XKCDColors.Orange);
                    //infoBox.SetLength(1.0f);
                    //infoBox.SetValue(0.0f);
                    //infoBox.SetMessage("Meltdwn");
                    //infoBox.SetProgressBarBgColor(XKCDColors.RedOrange);
                    //infoBox.SetProgressBarColor(XKCDColors.Orange);
                }

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

                if (UseForcedActivation)
                    this.part.force_activate();

            } else
            {
                this.CurrentSafetyOverride = this.NominalTemperature;
            }

            base.OnStart(state);
        }
 public float EvaluateVelCpCurve(float vel)
 {
     if (protoVelCpCurve != null)
     {
         velCpCurve = new FloatCurve();
         Debug.Log("Building Cp Curve Object...");
         foreach (CurveData data in protoVelCpCurve)
         {
             velCpCurve.Add(data.x, data.y, data.dy_dx, data.dy_dx);
         }
         protoVelCpCurve = null;
     }
     return velCpCurve.Evaluate(vel);
 }
        public void SetInitialValueOfField(string targetField)
        {
            object obj = null;
            FieldInfo fi = GetFieldInfo(targetField, out obj);
            if (obj != null)
            {
                if (fi.FieldType.Equals(typeof(Single)) || fi.FieldType.Equals(typeof(Double)) || fi.FieldType.Equals(typeof(Int32)) || fi.FieldType.Equals(typeof(UInt32)))
                {
                    Debug.Log("Field type is: " + fi.FieldType.Name);
                    if (m_startState == PartModule.StartState.Editor)
                    {
                        TweakableParamGUI.GetInstance().CheckClear();
                        TweakableParamGUIItem item = new TweakableParamGUIItem(TweakableParamGUI.GetInstance(), this);
                        if (tweakedValue == -1.0f)
                        {
                            tweakedValue = Convert.ToSingle(fi.GetValue(obj));
                            Debug.Log("Field is: " + tweakedValue.ToString());
                        }

                        if (this.parentModule != null)
                        {
                            this.parentModule.UpdateTweakedValue(this);
                        }
                    }
                    else
                    {
                        TweakableParamGUI.GetInstance().ClearGUIItem();

                        if (tweakedValue > maxValue) tweakedValue = maxValue;
                        if (tweakedValue < minValue) tweakedValue = minValue;
                        Debug.Log(String.Format("Setting tweakable parameter: {0} to {1}", fi.Name, tweakedValue));
                        if (!setOnlyOnLaunchPad || ((int)m_startState & (int)(PartModule.StartState.PreLaunch)) != 0)
                            fi.SetValue(obj, Convert.ChangeType(tweakedValue, fi.FieldType));
                    }
                }
                else
                {
                    // Float curve.
                    Debug.Log("Field type is: " + fi.FieldType.Name);
                    if (m_startState == PartModule.StartState.Editor)
                    {
                        TweakableParamGUI.GetInstance().CheckClear();
                        TweakableParamGUIItem item = new TweakableParamGUIItem(TweakableParamGUI.GetInstance(), this);
                        if (tweakedCurve == null)
                        {
                            Debug.Log("Starting analyzing FloatCurve.");
                            tweakedCurve = GetKeysFromFloatCurve((FloatCurve)fi.GetValue(obj));
                        }

                        if (this.parentModule != null)
                        {
                            this.parentModule.UpdateTweakedValue(this);
                        }
                    }
                    else
                    {
                        TweakableParamGUI.GetInstance().ClearGUIItem();

                        Debug.Log(String.Format("Setting tweakable parameter: {0} to {1}", fi.Name, tweakedCurve));
                        if (!setOnlyOnLaunchPad || ((int)m_startState & (int)(PartModule.StartState.PreLaunch)) != 0)
                        {
                            if (tweakedCurve == null)
                            {
                                fi.SetValue(obj, Convert.ChangeType(tweakedValue, fi.FieldType));
                            }
                            else
                            {
                                FloatCurve newFloatCurve = new FloatCurve();
                                for (int i = 0; i < tweakedCurve.Count / 2; ++i)
                                    newFloatCurve.Add(tweakedCurve[i * 2], tweakedCurve[i * 2 + 1]);

                                fi.SetValue(obj, newFloatCurve);
                            }
                        }
                    }
                }
            }
        }
        public void FixedUpdate()
        {
            if (HighLogic.LoadedSceneIsFlight && _attached_engine != null && _attached_engine.isOperational && _attached_reactor != null)
            {
                double minimum_isp = calculatedIsp * _attached_reactor.MinimumChargdIspMult;
                var maximum_isp = calculatedIsp * _attached_reactor.MaximumChargedIspMult; //113.835;
                var current_isp = _attached_engine.currentThrottle == 0 ? maximum_isp : Math.Min(maximum_isp, minimum_isp / Math.Pow(_attached_engine.currentThrottle, throtleExponent));

                // update Isp
                FloatCurve new_isp = new FloatCurve();
                new_isp.Add(0, (float)current_isp, 0, 0);
                _attached_engine.atmosphereCurve = new_isp;

                _max_charged_particles_power = _attached_reactor.MaximumChargedPower * exchanger_thrust_divisor;
                _charged_particles_requested = _attached_engine.currentThrottle > 0 ? _max_charged_particles_power : 0;
                _charged_particles_received = consumeFNResource(_charged_particles_requested * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES) / TimeWarp.fixedDeltaTime;

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

                var consumedByEngine = _attached_warpable_engine != null ? _attached_warpable_engine.propellantUsed : 0;
                _hydrogenProduction = chargedParticleRatio > 0 ? (float)_attached_reactor.UseProductForPropulsion(chargedParticleRatio, consumedByEngine) : 0;

                consumeFNResource(_charged_particles_received * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT);
                _requestedElectricPower = _charged_particles_received * (0.05f * Math.Max(_attached_reactor_distance, 1));
                _recievedElectricPower = consumeFNResource(_requestedElectricPower * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime;

                double megajoules_ratio = _recievedElectricPower / _requestedElectricPower;
                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));

                _engineMaxThrust = 0;
                if (_max_charged_particles_power > 0)
                {
                    double powerThrustModifier = GameConstants.BaseThrustPowerMultiplier * powerThrustMultiplier;
                    var enginethrust_from_recieved_particles = powerThrustModifier * _charged_particles_received * megajoules_ratio * atmo_thrust_factor / current_isp / PluginHelper.GravityConstant;
                    var max_theoretical_thrust = powerThrustModifier * _max_charged_particles_power * atmo_thrust_factor / current_isp / PluginHelper.GravityConstant;

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

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

                // set maximum flow
                _attached_engine.maxFuelFlow = Math.Min(0.5f, (float)max_fuel_flow_rate);

                // This whole thing may be inefficient, but it should clear up some confusion for people.
                if (!_attached_engine.getFlameoutState)
                {
                    if (megajoules_ratio < 0.75 && _requestedElectricPower > 0)
                        _attached_engine.status = "Insufficient Electricity";
                    else if (atmo_thrust_factor < 0.75)
                        _attached_engine.status = "Too dense atmospherere";
                }
            }
            else if (_attached_engine != null)
            {
                _attached_engine.maxFuelFlow = 0;
                _recievedElectricPower = 0;
                _charged_particles_requested = 0;
                _charged_particles_received = 0;
                _engineMaxThrust = 0;
            }
        }
        private void GenerateCrossFlowDragCurve()
        {
            crossFlowDragMachCurve = new FloatCurve();
            crossFlowDragMachCurve.Add(0, 1.2f, 0, 0);
            crossFlowDragMachCurve.Add(0.3f, 1.2f, 0, 0);
            crossFlowDragMachCurve.Add(0.7f, 1.5f, 0, 0);
            crossFlowDragMachCurve.Add(0.85f, 1.41f, 0, 0);
            crossFlowDragMachCurve.Add(0.95f, 2.1f, 0, 0);
            crossFlowDragMachCurve.Add(1f, 2f, -2f, -2f);
            crossFlowDragMachCurve.Add(1.3f, 1.6f, -0.5f, -0.5f);
            crossFlowDragMachCurve.Add(2f, 1.4f, -0.1f, -0.1f);
            crossFlowDragMachCurve.Add(5f, 1.25f, -0.02f, -0.02f);
            crossFlowDragMachCurve.Add(10f, 1.2f, 0, 0);

            crossFlowDragReynoldsCurve = new FloatCurve();
            crossFlowDragReynoldsCurve.Add(10000, 1f, 0, 0);
            crossFlowDragReynoldsCurve.Add(100000, 1.0083333333333333333333333333333f, 0, 0);
            crossFlowDragReynoldsCurve.Add(180000, 1.0083333333333333333333333333333f, 0, 0);
            crossFlowDragReynoldsCurve.Add(250000, 0.66666666666666666666666666666667f);
            crossFlowDragReynoldsCurve.Add(300000, 0.25f, -5E-07f, -5E-07f);
            crossFlowDragReynoldsCurve.Add(500000, 0.20833333333333333333333333333333f, 0, 0);
            crossFlowDragReynoldsCurve.Add(1000000, 0.33333333333333333333333333333333f, 7E-8f, 7E-8f);
            crossFlowDragReynoldsCurve.Add(10000000, 0.58333333333333333333333333333333f, 0, 0);
        }
 protected void updateISP(double isp_efficiency)
 {
     FloatCurve newISP = new FloatCurve();
     newISP.Add(0, (float)(isp_efficiency * _modifiedEngineBaseISP * _modifiedCurrentPropellantIspMultiplier * CurrentPropellantThrustMultiplier * ThrottleModifiedIsp()));
     _attached_engine.atmosphereCurve = newISP;
 }
        private void SetHeatGeneration(float heat)
        {
            if (Time.timeSinceLevelLoad > 5f)
                GeneratesHeat = true;
            else
                GeneratesHeat = false;

            //Utils.Log("Fudge Factor currently " + reactorFudgeFactor.ToString());
            if (float.IsNaN(reactorFudgeFactor))
            {
                reactorFudgeFactor = 0f;
            }

            TemperatureModifier = new FloatCurve();
            TemperatureModifier.Add(0f, heat + reactorFudgeFactor * 50f);

            D_RealHeat = String.Format("{0:F2}",heat/50f + reactorFudgeFactor);
        }
        public void evaluateMaxThrust()
        {
            bool electrothermal_prop = false;
            List<Part> vessel_parts = vessel.parts;
            total_power_output = 0;
            var curEngine = this.part.Modules["ModuleEngines"] as ModuleEngines;
            ConfigNode chosenpropellant = propellants[fuel_mode];
            ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT");
            List<Propellant> list_of_propellants = new List<Propellant>();
            //bool propellant_is_upgrade = false;

            for (int i = 0; i < assprops.Length; ++i) {
                fuelmode = chosenpropellant.GetValue("guiName");
                ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier"));
                thrust_efficiency = float.Parse(chosenpropellant.GetValue("efficiency"));
                //propellant_is_upgrade = bool.Parse(chosenpropellant.GetValue("isUpgraded"));
                electrothermal_prop = bool.Parse(chosenpropellant.GetValue("electroThermal"));
                Propellant curprop = new Propellant();
                curprop.Load(assprops[i]);
                if (curprop.drawStackGauge) {
                    curprop.drawStackGauge = false;
                    fuel_gauge.SetMessage(curprop.name);
                    fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime);
                    fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime);
                    fuel_gauge.SetProgressBarColor(XKCDColors.Yellow);
                    fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime);
                    fuel_gauge.SetValue(0f);
                }
                list_of_propellants.Add(curprop);
            }

            total_power_output = getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES);

            final_thrust_store = thrust_efficiency*2000.0f*total_power_output / (initialIsp * ispMultiplier * 9.81f);

            //float thrust_ratio = total_power_output / reference_power;
            //final_thrust_store = initial_thrust * thrust_ratio / ispMultiplier;

            FloatCurve newISP = new FloatCurve ();
            newISP.Add (0, initialIsp * ispMultiplier);
            curEngine.atmosphereCurve = newISP;

            if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) {

                curEngine.propellants.Clear();
                curEngine.propellants = list_of_propellants;
                curEngine.SetupPropellant();
            }

            List<PartResource> partresources = new List<PartResource>();
            part.GetConnectedResources(curEngine.propellants[0].id, PartResourceLibrary.Instance.GetDefinition(curEngine.propellants[0].name).resourceFlowMode, partresources);

            //if(!isupgraded) {
            if (partresources.Count == 0 && fuel_mode != 0) {
                if (isThrusterElectrothermal && !electrothermal_prop) {
                    TogglePropellant();
                } else if (!isThrusterElectrothermal) {
                    TogglePropellant();
                }
            }
            //}else{
            //    if(!propellant_is_upgrade) {
                    //TogglePropellant();
               //     }
            //}
        }
        public override void OnFixedUpdate()
        {
            if (!HighLogic.LoadedSceneIsFlight)
                return;

            if (!Deployed()) //For variants like the Medusa
                return;

            //Setup
            Transform t = part.FindModelTransform(transformName);
            if (lastCheck < ResourceUtilities.FLOAT_TOLERANCE)
                lastCheck = Planetarium.GetUniversalTime();

            var currentThrust = GetPulseThrust();
            var pulseInterval = GetPulseInterval(lastThrottle);

            //Check Emitters - turn them off if it's time.
            if (Planetarium.GetUniversalTime() > lastParticleCheck + particleLife)
                ToggleEmmitters(false);

            //Check for fuel
            if (!HasFuel())
                return;

            //See if it's time to fire.
            var eng = part.FindModuleImplementing<ModuleEngines>();
            if (Planetarium.GetUniversalTime() > lastCheck + pulseInterval)
            {
                lastThrottle = eng.currentThrottle;
                if (!eng.isActiveAndEnabled || lastThrottle < 0.01)
                {
                    ToggleEmmitters(false);
                    return;
                }
                ConsumeFuel();
                lastCheck = Planetarium.GetUniversalTime();
                lastParticleCheck = lastCheck;
                ToggleEmmitters(true);
                PlayAnimation();
            }

            //Where are we in the curve?
            var pulseCurve = new FloatCurve();
            pulseCurve.Add(0, (1 - powerCurve) / 2);
            pulseCurve.Add(0.5f,  powerCurve);
            pulseCurve.Add(1, (1 - powerCurve) / 2);

            if(Planetarium.GetUniversalTime() - lastCheck < minPulseTime)
            {
                var curveTime = (float) (Planetarium.GetUniversalTime() - lastCheck)/(float) minPulseTime;
                var atmoModifier = 1f;
                if(atmosphereNerf)
                    atmoModifier = (float)Math.Max(0, 1d - vessel.atmDensity);
                var thrustAmount = (float) (currentThrust*pulseCurve.Evaluate(curveTime)) * atmoModifier;

                part.GetComponent<Rigidbody>().AddForceAtPosition(-t.forward * thrustAmount, t.position, ForceMode.Force);
                part.AddThermalFlux(thrustAmount * heatMultiplier);
            }
        }
        public static void SetBasicDragModuleProperties(Part p)
        {
            FARBasicDragModel d = p.Modules["FARBasicDragModel"] as FARBasicDragModel;
            string title = p.partInfo.title.ToLowerInvariant();

            if (p.Modules.Contains("ModuleAsteroid"))
            {
                FARGeoUtil.BodyGeometryForDrag data = FARGeoUtil.CalcBodyGeometryFromMesh(p);

                FloatCurve TempCurve1 = new FloatCurve();
                double cd = 0.2; //cd based on diameter
                cd *= Math.Sqrt(data.crossSectionalArea / Math.PI) * 2 / data.area;

                TempCurve1.Add(-1, (float)cd);
                TempCurve1.Add(1, (float)cd);

                FloatCurve TempCurve2 = new FloatCurve();
                TempCurve2.Add(-1, 0);
                TempCurve2.Add(1, 0);

                FloatCurve TempCurve4 = new FloatCurve();
                TempCurve2.Add(-1, 0);
                TempCurve2.Add(1, 0);

                FloatCurve TempCurve3 = new FloatCurve();
                TempCurve3.Add(-1, 0);
                TempCurve3.Add(1, 0);

                d.BuildNewDragModel(data.area * FARAeroUtil.areaFactor, TempCurve1, TempCurve2, TempCurve4, TempCurve3, data.originToCentroid, data.majorMinorAxisRatio, 0, data.taperCrossSectionArea, double.MaxValue, double.MaxValue);
                return;
            }
            else if (FARPartClassification.IncludePartInGreeble(p, title))
            {
                FloatCurve TempCurve1 = new FloatCurve();
                /*if (title.Contains("heatshield") || (title.Contains("heat") && title.Contains("shield")))
                    TempCurve1.Add(-1, 0.3f);
                else*/
                TempCurve1.Add(-1, 0);
                TempCurve1.Add(0, 0.02f);
                TempCurve1.Add(1, 0);

                FloatCurve TempCurve2 = new FloatCurve();
                TempCurve2.Add(-1, 0);
                TempCurve2.Add(1, 0);

                FloatCurve TempCurve4 = new FloatCurve();
                TempCurve2.Add(-1, 0);
                TempCurve2.Add(1, 0);

                FloatCurve TempCurve3 = new FloatCurve();
                TempCurve3.Add(-1, 0);
                TempCurve3.Add(1, 0);

                double area = FARGeoUtil.CalcBodyGeometryFromMesh(p).area;

                d.BuildNewDragModel(area * FARAeroUtil.areaFactor, TempCurve1, TempCurve2, TempCurve4, TempCurve3, Vector3.zero, 1, 0, 0, double.MaxValue, double.MaxValue);
                return;
            }
            else
            {
                FARGeoUtil.BodyGeometryForDrag data = FARGeoUtil.CalcBodyGeometryFromMesh(p);
                FloatCurve TempCurve1 = new FloatCurve();
                FloatCurve TempCurve2 = new FloatCurve();
                FloatCurve TempCurve4 = new FloatCurve();
                FloatCurve TempCurve3 = new FloatCurve();
                double YmaxForce = double.MaxValue;
                double XZmaxForce = double.MaxValue;

                double Cn1, Cn2, cutoffAngle, cosCutoffAngle = 0;

                if (title.Contains("truss") || title.Contains("strut") || title.Contains("railing") || p.Modules.Contains("ModuleWheel"))
                {
                    TempCurve1.Add(-1, 0.1f);
                    TempCurve1.Add(1, 0.1f);
                    TempCurve2.Add(-1, 0f);
                    TempCurve2.Add(1, 0f);
                    TempCurve3.Add(-1, 0f);
                    TempCurve3.Add(1, 0f);
                }
                else if (title.Contains("plate") || title.Contains("panel"))
                {
                    TempCurve1.Add(-1, 1.2f);
                    TempCurve1.Add(0, 0f);
                    TempCurve1.Add(1, 1.2f);
                    TempCurve2.Add(-1, 0f);
                    TempCurve2.Add(1, 0f);
                    TempCurve3.Add(-1, 0f);
                    TempCurve3.Add(1, 0f);
                }
                else
                {

                    if (data.taperRatio <= 1)
                    {
                        Cn1 = NormalForceCoefficientTerm1(data.finenessRatio, data.taperRatio, data.crossSectionalArea, data.area);
                        Cn2 = NormalForceCoefficientTerm2(data.finenessRatio, data.taperRatio, data.crossSectionalArea, data.area);
                        cutoffAngle = cutoffAngleForLift(data.finenessRatio, data.taperRatio, data.crossSectionalArea, data.area);

                        cosCutoffAngle = -Math.Cos(cutoffAngle);

                        double axialPressureDrag = PressureDragDueToTaperingConic(data.finenessRatio, data.taperRatio, data.crossSectionalArea, data.area);

                        TempCurve1.Add(-1, (float)axialPressureDrag);
                        TempCurve1.Add(0, (float)Cn2);
                        TempCurve1.Add(1, (float)axialPressureDrag);

                        if (cutoffAngle > 30)
                            TempCurve2.Add((float)cosCutoffAngle, 0, (float)Cn1, 0);
                        else
                            TempCurve2.Add(-0.9f, 0, (float)Cn1, 0);
                        TempCurve2.Add(-0.8660f, (float)(Math.Cos((Math.PI * 0.5 - Math.Acos(0.8660f)) * 0.5) * Math.Sin(2 * (Math.PI * 0.5 - Math.Acos(0.8660f))) * Cn1), 0, 0);
                        TempCurve2.Add(0, 0);
                        TempCurve2.Add(0.8660f, (float)(Math.Cos((Math.PI * 0.5 - Math.Acos(0.8660f)) * 0.5) * Math.Sin(2 * (Math.PI * 0.5 - Math.Acos(0.8660f))) * Cn1), 0, 0);
                        TempCurve2.Add(1, 0, (float)Cn1, (float)Cn1);

                        TempCurve4.Add(-1, 0, 0, 0);
                        TempCurve4.Add(-0.95f, (float)(Math.Pow(Math.Sin(Math.Acos(0.95f)), 2) * Cn2 * -0.95f));
                        TempCurve4.Add(-0.8660f, (float)(Math.Pow(Math.Sin(Math.Acos(0.8660f)), 2) * Cn2 * -0.8660f));
                        TempCurve4.Add(-0.5f, (float)(Math.Pow(Math.Sin(Math.Acos(0.5f)), 2) * Cn2 * -0.5f));
                        TempCurve4.Add(0, 0);
                        TempCurve4.Add(0.5f, (float)(Math.Pow(Math.Sin(Math.Acos(0.5f)), 2) * Cn2 * 0.5f));
                        TempCurve4.Add(0.8660f, (float)(Math.Pow(Math.Sin(Math.Acos(0.8660f)), 2) * Cn2 * 0.8660f));
                        TempCurve4.Add(0.95f, (float)(Math.Pow(Math.Sin(Math.Acos(0.95f)), 2) * Cn2 * 0.95f));
                        TempCurve4.Add(1, 0, 0, 0);
                    }
                    else
                    {
                        Cn1 = NormalForceCoefficientTerm1(data.finenessRatio, 1 / data.taperRatio, data.crossSectionalArea, data.area);
                        Cn2 = NormalForceCoefficientTerm2(data.finenessRatio, 1 / data.taperRatio, data.crossSectionalArea, data.area);
                        cutoffAngle = cutoffAngleForLift(data.finenessRatio, 1 / data.taperRatio, data.crossSectionalArea, data.area);

                        cosCutoffAngle = Math.Cos(cutoffAngle);

                        double axialPressureDrag = PressureDragDueToTaperingConic(data.finenessRatio, 1 / data.taperRatio, data.crossSectionalArea, data.area);

                        TempCurve1.Add(-1, (float)axialPressureDrag, 0, 0);
                        TempCurve1.Add(0, (float)Cn2, 0, 0);
                        TempCurve1.Add(1, (float)axialPressureDrag, 0, 0);

                        TempCurve2.Add(-1, 0, (float)-Cn1, (float)-Cn1);
                        TempCurve2.Add(-0.8660f, (float)((-Math.Cos((Math.PI *0.5 - Math.Acos(0.8660)) *0.5) * Math.Sin(2 * (Math.PI *0.5 - Math.Acos(0.8660))) * Cn1)), 0, 0);
                        TempCurve2.Add(0, 0);
                        TempCurve2.Add(0.8660f, (float)((-Math.Cos((Math.PI *0.5 - Math.Acos(0.8660)) *0.5) * Math.Sin(2 * (Math.PI *0.5 - Math.Acos(0.8660))) * Cn1)), 0, 0);
                        if (cutoffAngle > 30)
                            TempCurve2.Add((float)cosCutoffAngle, 0, (float)-Cn1, 0);
                        else
                            TempCurve2.Add(0.9f, 0, (float)-Cn1, 0);

                        TempCurve4.Add(-1, 0, 0, 0);
                        TempCurve4.Add(-0.95f, (float)(Math.Pow(Math.Sin(Math.Acos(0.95)), 2) * Cn2 * -0.95));
                        TempCurve4.Add(-0.8660f, (float)(Math.Pow(Math.Sin(Math.Acos(0.8660)), 2) * Cn2 * -0.8660));
                        TempCurve4.Add(-0.5f, (float)(Math.Pow(Math.Sin(Math.Acos(0.5)), 2) * Cn2 * -0.5));
                        TempCurve4.Add(0, 0);
                        TempCurve4.Add(0.5f, (float)(Math.Pow(Math.Sin(Math.Acos(0.5)), 2) * Cn2 * 0.5));
                        TempCurve4.Add(0.8660f, (float)(Math.Pow(Math.Sin(Math.Acos(0.8660)), 2) * Cn2 * 0.8660));
                        TempCurve4.Add(0.95f, (float)(Math.Pow(Math.Sin(Math.Acos(0.95)), 2) * Cn2 * 0.95));
                        TempCurve4.Add(1, 0, 0, 0);
                    }

                    /*                    TempCurve2.Add(-1, 0);
                                        TempCurve2.Add(-0.866f, -0.138f);
                                        TempCurve2.Add(-0.5f, -0.239f, 0, 0);
                                        TempCurve2.Add(0, 0);
                                        TempCurve2.Add(0.5f, 0.239f, 0, 0);
                                        TempCurve2.Add(0.866f, 0.138f);
                                        TempCurve2.Add(1, 0);*/

                    /*                    if (p.partInfo.title.ToLowerInvariant().Contains("nose"))
                                        {
                                            TempCurve3.Add(-1, -0.1f, 0, 0);
                                            TempCurve3.Add(-0.5f, -0.1f, 0, 0);
                                            TempCurve3.Add(0, -0.1f, 0, 0);
                                            TempCurve3.Add(0.8660f, 0f, 0, 0);
                                            TempCurve3.Add(1, 0.1f, 0, 0);
                                        }
                                        else
                                        {*/

                    float cdM = (float)MomentDueToTapering(data.finenessRatio, data.taperRatio, data.crossSectionalArea, data.area);

                    TempCurve3.Add(-1, cdM);
                    TempCurve3.Add(-0.5f, cdM * 2);
                    TempCurve3.Add(0, cdM * 3);
                    TempCurve3.Add(0.5f, cdM * 2);
                    TempCurve3.Add(1, cdM);

                    if (HighLogic.LoadedSceneIsFlight && !FARAeroStress.PartIsGreeble(p, data.crossSectionalArea, data.finenessRatio, data.area) && FARDebugValues.allowStructuralFailures)
                    {
                        FARPartStressTemplate template = FARAeroStress.DetermineStressTemplate(p);

                        YmaxForce = template.YmaxStress;    //in MPa
                        YmaxForce *= data.crossSectionalArea;

                        /*XZmaxForce = 2 * Math.Sqrt(data.crossSectionalArea / Math.PI);
                        XZmaxForce = XZmaxForce * data.finenessRatio * XZmaxForce;
                        XZmaxForce *= template.XZmaxStress;*/

                        XZmaxForce = template.XZmaxStress * data.area * 0.5;

                        Debug.Log("Template: " + template.name + " YmaxForce: " + YmaxForce + " XZmaxForce: " + XZmaxForce);
                    }

                }
            //                if (p.Modules.Contains("FARPayloadFairingModule"))
            //                    data.area /= p.symmetryCounterparts.Count + 1;

                d.BuildNewDragModel(data.area * FARAeroUtil.areaFactor, TempCurve1, TempCurve2, TempCurve4, TempCurve3, data.originToCentroid, data.majorMinorAxisRatio, cosCutoffAngle, data.taperCrossSectionArea, YmaxForce, XZmaxForce);
                return;
            }
        }
 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 CalculateCurves()
        {
            AtmoThrustCurve = new FloatCurve();
            AtmoThrustCurve.Add(0f, engine.maxThrust);
            AtmoThrustCurve.Add(1f, 0f);

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

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

            AtmoIspCurve.Add(1f, FindIsp(0f, rate, fuelPropellant));
        }
        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;
        }
        public void InitializeOverallEngineData(
            double nMinFlow, 
            double nMaxFlow, 
            FloatCurve nAtmosphereCurve, 
            FloatCurve nAtmCurve, 
            FloatCurve nVelCurve,
            double nThrottleResponseRate,
            double nChamberNominalTemp,
            double nMachLimit,
            double nMachMult,
            double nFlowMultMin,
            double nFlowMultCap,
            double nFlowMultSharp,
            bool nMultFlow,
            double nVaryThrust,
            float nSeed)
        {
            minFlow = nMinFlow * 1000d; // to kg
            maxFlow = nMaxFlow * 1000d;
            atmosphereCurve = nAtmosphereCurve;
            atmCurve = nAtmCurve;
            velCurve = nVelCurve;
            throttleResponseRate = nThrottleResponseRate;
            chamberTemp = 288d;
            chamberNominalTemp = nChamberNominalTemp;
            chamberNominalTemp_recip = 1d / chamberNominalTemp;
            machLimit = nMachLimit;
            machMult = nMachMult;
            flowMultMin = nFlowMultMin;
            flowMultCap = nFlowMultCap;
            flowMultCapSharpness = nFlowMultSharp;
            multFlow = nMultFlow;
            varyThrust = nVaryThrust;
            seed = nSeed;

            // falloff at > sea level pressure.
            if (atmosphereCurve.Curve.keys.Length == 2 && atmosphereCurve.Curve.keys[0].value != atmosphereCurve.Curve.keys[1].value)
            {
                Keyframe k0 = atmosphereCurve.Curve.keys[0];
                Keyframe k1 = atmosphereCurve.Curve.keys[1];
                if(k0.time > k1.time)
                {
                    Keyframe t = k0;
                    k0 = k1;
                    k1 = t;
                }
                float minIsp = 0.0001f;
                float invSlope = (k1.time - k0.time) / (k0.value - k1.value);
                float maxP = k1.time + (k1.value - minIsp) * invSlope;

                atmosphereCurve = new FloatCurve();
                atmosphereCurve.Add(k0.time, k0.value, k0.inTangent, k0.outTangent);
                atmosphereCurve.Add(k1.time, k1.value, k1.inTangent, k1.outTangent);
                atmosphereCurve.Add(maxP, minIsp);
            }
        }
        public static FloatCurve ModifyCurveKeys(FloatCurve initialCurve, float vacMult, float atmMult, bool extendToZero)
        {
            ConfigNode tempNode = new ConfigNode();

            initialCurve.Save(tempNode);

            string[] keyStrings = tempNode.GetValues("key");

            float maxTime, ispAtMaxTime, secondTime, ispAtSecondTime, maxPressure;
            maxTime = ispAtMaxTime = secondTime = ispAtSecondTime = maxPressure = 0;
            FloatCurve newAtmosphereCurve = new FloatCurve();

            maxTime = initialCurve.maxTime;

            for (int i = 0; i < keyStrings.Length; i++)
            {
                string[] splitKey = keyStrings[i].Split(' ');

                float scalar = vacMult + Convert.ToSingle(splitKey[0]) * (atmMult - vacMult);
                if (!extendToZero)
                    scalar = Mathf.Clamp(scalar, Mathf.Min(atmMult, vacMult), Mathf.Max(atmMult, vacMult));

                if (Convert.ToSingle(splitKey[0]) != 0)
                    newAtmosphereCurve.Add(Convert.ToSingle(splitKey[0]), Convert.ToSingle(splitKey[1]) * scalar, Convert.ToSingle(splitKey[2]) * scalar, Convert.ToSingle(splitKey[3]) * scalar);
                else
                    newAtmosphereCurve.Add(Convert.ToSingle(splitKey[0]), Convert.ToSingle(splitKey[1]) * scalar, 0, 0);

                if (i == keyStrings.Length - 2)
                {
                    secondTime = Convert.ToSingle(splitKey[0]);
                    ispAtSecondTime = Convert.ToSingle(splitKey[1]) * scalar;
                }
            }

            ispAtMaxTime = newAtmosphereCurve.Evaluate(maxTime);

            if (extendToZero && (ispAtSecondTime - ispAtMaxTime) >= 0.0001f)
            {
                maxPressure = maxTime + (0.01f - ispAtMaxTime) / (ispAtSecondTime - ispAtMaxTime) * (secondTime - maxTime);
                newAtmosphereCurve.Add(maxPressure, 0.01f, 0, 0);
            }

            return newAtmosphereCurve;
        }
        private void initialize()
        {
            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
            }
            double hsp = 1;
            double dens = 1;
            if (heatSoak)
            {
                PartResourceDefinition resource = PartResourceLibrary.Instance.GetDefinition(resourceName);
                hsp = resource.specificHeatCapacity;
                dens = resource.density;
            }
            else
            {
                resource = part.Resources[resourceName];
                if (resource != null)
                {
                    hsp = resource.info.specificHeatCapacity;
                    dens = resource.info.density;
                }
                else
                {
                    hsp = PhysicsGlobals.StandardSpecificHeatCapacity;
                    dens = 0.005f;
                }
            }
            useToFluxMultiplier = hsp * ablationEfficiency * dens * ablationMult;
            baseSkinIntMult = part.skinInternalConductionMult;

            //stand-alone modular heat-shield setup
            if (standAlonePart)
            {
                if (string.IsNullOrEmpty(modelName))
                {
                    MonoBehaviour.print("SEVERE ERROR: SSTUModularHeatShield could has no model specified for part: " + part.name);
                }

                if (!String.IsNullOrEmpty(transformsToRemove))
                {
                    SSTUUtils.removeTransforms(part, SSTUUtils.parseCSV(transformsToRemove));
                }

                shieldTypeNames = SSTUDatabase.getHeatShieldNames();

                ConfigNode modelNode = new ConfigNode("MODEL");
                modelNode.AddValue("name", modelName);
                mainModelData = new SingleModelData(modelNode);
                mainModelData.setupModel(part.transform.FindRecursive("model"), ModelOrientation.CENTRAL, true);
                setModelDiameter(currentDiameter);
                updateAttachNodes(false);
                updateDragCube();
                updateEditorFields();
            }

            ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData);
            ConfigNode[] typeNodes = node.GetNodes("SHIELDTYPE");
            int len = typeNodes.Length;
            shieldTypeNames = new string[len];
            for (int i = 0; i < len; i++)
            {
                shieldTypeNames[i] = typeNodes[i].GetStringValue("name");
            }
            if (shieldTypeNames.Length == 0) { shieldTypeNames = new string[] { "Medium" }; }
            currentShieldTypeData = SSTUDatabase.getHeatShieldType(currentShieldType);
            heatCurve = currentShieldTypeData.heatCurve;

            updatePartCost();
            if (!initializedResources && (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight))
            {
                updatePartResources();
                initializedResources = true;
            }
        }