// Constructor
 PersistentPropellant(Propellant p)
 {
     propellant = p;
     definition = PartResourceLibrary.Instance.GetDefinition(propellant.name);
     density = definition.density;
     ratio = propellant.ratio;
 }
 public ElectricEnginePropellant(ConfigNode node) {
     propellantname = node.GetValue("name");
     propellantguiname = node.GetValue("guiName");
     ispMultiplier = Convert.ToDouble(node.GetValue("ispMultiplier"));
     efficiency = Convert.ToDouble(node.GetValue("efficiency"));
     prop_type = Convert.ToInt32(node.GetValue("type"));
     effectname = node.GetValue("effectName");
     ConfigNode propellantnode = node.GetNode("PROPELLANT");
     propellant = new Propellant();
     propellant.Load(propellantnode);
 }
 public ElectricEnginePropellant(ConfigNode node)
 {
     propellantname = node.GetValue("name");
     propellantguiname = node.GetValue("guiName");
     ispMultiplier = Convert.ToSingle(node.GetValue("ispMultiplier"));
     thrustMultiplier = node.HasValue("thrustMultiplier") ? Convert.ToSingle(node.GetValue("thrustMultiplier")) : 1;
     thrustMultiplierCold = node.HasValue("thrustMultiplierCold") ? Convert.ToSingle(node.GetValue("thrustMultiplierCold")) : thrustMultiplier;
     wasteheatMultiplier = node.HasValue("wasteheatMultiplier") ? Convert.ToDouble(node.GetValue("wasteheatMultiplier")) : 1;
     efficiency = Convert.ToDouble(node.GetValue("efficiency"));
     prop_type = Convert.ToInt32(node.GetValue("type"));
     effectname = node.GetValue("effectName");
     techRquirement = node.HasValue("techRequirement") ? node.GetValue("techRequirement") : String.Empty;
     ConfigNode propellantnode = node.GetNode("PROPELLANT");
     propellant = new Propellant();
     propellant.Load(propellantnode);
 }
        private void FuelConsumptionFromEngineModule(ModuleEngines e, ref double totalThrust, ref double totalThrust_Isp, ref double fuelConsumptionVol, ref double airDemandVol, double invDeltaTime)
        {
            if (e.EngineIgnited && !e.engineShutdown)
            {
                totalThrust     += e.finalThrust;
                totalThrust_Isp += e.finalThrust * e.realIsp;
                for (int i = 0; i < e.propellants.Count; i++)
                {
                    Propellant v = e.propellants[i];

                    if (v.id == intakeAirId)
                    {
                        airDemandVol += v.currentRequirement;
                    }

                    if (!v.ignoreForIsp)
                    {
                        fuelConsumptionVol += v.currentRequirement * invDeltaTime;
                    }
                }
            }
        }
        private double consumeResource(Propellant propellant, float consumption, Part part)
        {
            double requestAmount = consumption * propellant.ratio * fuelFlow * TimeWarp.deltaTime;

            if (requestAmount < minAmount)
            {
                if (requestAmount <= 0f)
                {
                    requestAmount = 0f;
                }
                else
                {
                    requestAmount = minAmount;
                }
            }
            if (requestAmount > 0f)
            {
                double recievedAmount = part.RequestResource(propellant.id, requestAmount, propellant.GetFlowMode());
                return(recievedAmount / requestAmount);
            }
            return(1);
        }
        private void SetMode()
        {
            if (multiEngine.runningPrimary)
            {
                EngineModeID = 0;
            }
            else
            {
                EngineModeID = 1;
            }

            Utils.Log("VariableIspEngine: Changing mode to " + engineModes[EngineModeID].name);
            CurrentEngineID = engineModes[EngineModeID].name;
            engine          = engines[EngineModeID];
            ThrustCurve     = engineModes[EngineModeID].thrustCurve;
            IspCurve        = engineModes[EngineModeID].ispCurve;


            for (int i = 0; i < engine.propellants.Count; i++)
            {
                if (engine.propellants[i].name != "ElectricCharge")
                {
                    fuelPropellant = engine.propellants[i];
                }
                else
                {
                    ecPropellant = engine.propellants[i];
                }
            }

            //Utils.Log("VariableIspEngine: Changed mode to " + engine.engineID);
            Utils.Log("VariableIspEngine: Fuel: " + fuelPropellant.name);
            Utils.Log("VariableIspEngine: Thrust Curve: " + ThrustCurve.Evaluate(0f) + " to " + ThrustCurve.Evaluate(1f));
            Utils.Log("VariableIspEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f));

            AdjustVariableThrust();
        }
        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));
        }
 private float FindThrust(float isp, float flowRate, Propellant fuelPropellant)
 {
     double fuelDensity = PartResourceLibrary.Instance.GetDefinition(fuelPropellant.name).density;
     double thrust = Utils.GRAVITY * isp * flowRate;
     //double isp = (((thrust * 1000f) / (Utils.GRAVITY)) / flowRate) / (fuelDensity * 1000f);
     return (float)isp;
 }
Example #9
0
        public void MarkPropellant(Propellant propel)
        {
            ResourceData r = nameResources[propel.name];

            r.ispropellant = true;
        }
        /// <summary>
        /// Get the vessel's acceleration ability, in m/s2
        /// </summary>
        /// <param name="propellantsConsumed">All the propellants consumed, in tons/second for each one</param>
        /// <param name="totalThrust">The total thrust produced, in kilonewtons</param>
        private void GetThrustInfo(
            Tally propellantsConsumed,
            out double totalThrust)
        {
            // Add up all the thrust for all the active engines on the vessel.
            // We do this as a vector because the engines might not be parallel to each other.
            Vector3 totalThrustVector = Vector3.zero;

            totalThrust = 0.0F;
            propellantsConsumed.Zero();
            Tally availableResources = vessel.AvailableResources;
            int   engineCount        = 0;

            for (int engineIndex = 0; engineIndex < vessel.ActiveEngines.Count; ++engineIndex)
            {
                ModuleEngines engine = vessel.ActiveEngines[engineIndex];
                if (engine.thrustPercentage > 0)
                {
                    double engineKilonewtons = engine.ThrustLimit();
                    if (!CheatOptions.InfinitePropellant)
                    {
                        // Possible future consideraiton:
                        // Get the vacuum Isp from engine.atmosphereCurve.Evaluate(0), rather than ask
                        // for engine.realIsp, because there may be mods that tinker with the atmosphere
                        // curve, which changes the actual Isp that the game uses for vacuum without
                        // updating engine.realIsp.
                        double engineIsp = engine.realIsp;

                        double engineTotalFuelConsumption = engineKilonewtons / (KERBIN_GRAVITY * engineIsp); // tons/sec
                        double ratioSum  = 0.0;
                        bool   isStarved = false;
                        for (int propellantIndex = 0; propellantIndex < engine.propellants.Count; ++propellantIndex)
                        {
                            Propellant propellant = engine.propellants[propellantIndex];
                            if (!ShouldIgnore(propellant.name))
                            {
                                if (!availableResources.Has(propellant.name))
                                {
                                    isStarved = true;
                                    break;
                                }
                                ratioSum += propellant.ratio;
                            }
                        }
                        if (isStarved)
                        {
                            continue;
                        }
                        if (ratioSum > 0)
                        {
                            double ratio = 1.0 / ratioSum;
                            for (int propellantIndex = 0; propellantIndex < engine.propellants.Count; ++propellantIndex)
                            {
                                Propellant propellant = engine.propellants[propellantIndex];
                                if (!ShouldIgnore(propellant.name))
                                {
                                    double consumptionRate = ratio * propellant.ratio * engineTotalFuelConsumption; // tons/sec
                                    propellantsConsumed.Add(propellant.name, consumptionRate);
                                }
                            }
                        }
                    } // if we need to worry about fuel
                    ++engineCount;
                    totalThrustVector += engine.Forward() * (float)engineKilonewtons;
                } // if the engine is operational
            }     // for each engine module on the part
            totalThrust = totalThrustVector.magnitude;
            if (engineCount != lastEngineCount)
            {
                lastEngineCount = engineCount;
                Logging.Log(engineCount.ToString("Active engines: ##0"));
            }
        }
        public void RetrofitEngine()
        {
            if (ResearchAndDevelopment.Instance == null) { return;}
            if (isupgraded || ResearchAndDevelopment.Instance.Science < upgradeCost) { return; }
            isupgraded = true;
            var curEngine = this.part.Modules["ModuleEngines"] as ModuleEngines;
            if (curEngine != null) {
                Propellant prop = new Propellant();
                //prop.id = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").id;
                //ConfigNode prop_node = new ConfigNode();
                //PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").Save(prop_node);

                //PartResource part_resource = part.Resources.list[0];
                //part_resource.info = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma");
                //part_resource.maxAmount = 10;
                //part_resource.amount = 10;

                ConfigNode node = new ConfigNode("RESOURCE");
                node.AddValue("name", "VacuumPlasma");
                node.AddValue("maxAmount", 10);
                node.AddValue("amount", 10);
                part.AddResource(node);

                propellants = ElectricEngineController.getPropellants(isupgraded);
                fuel_mode = 0;

                //curEngine.propellants[1].id = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").id;
                //curEngine.propellants[1].name = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").name;
                engineType = upgradedName;
                ResearchAndDevelopment.Instance.Science = ResearchAndDevelopment.Instance.Science - upgradeCost;
                evaluateMaxThrust();
            }
        }
Example #12
0
 public float getMaxFuelFlow(Propellant p)
 {
     return(p.ratio * this.thrusterPower / (atmosphereCurve.Evaluate(0f) * 9.82f) / this.resourceMass);
 }
Example #13
0
        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();
            //     }
            //}
        }
Example #14
0
 public float getMaxFuelFlow(Propellant p)
 {
     return p.ratio * this.thrusterPower / (atmosphereCurve.Evaluate(0f) * 9.82f) / this.resourceMass;
 }
 public double GetPropellants(Propellant prop)
 {
     return(0);
 }
        public double GetMaximumPossibleLifetime()
        {
            double Lifetime = 0;

            //List<Part> constructPartsList = EditorLogic.RootPart.FindChildParts<Part>().ToList();
            //constructPartsList.AddUnique(EditorLogic.RootPart);
            var constructParts = EditorLogic.SortedShipList.ToArray();
            //Part[] constructParts = EditorLogic.RootPart.FindChildParts<Part>();
            //constructParts.AddUnique(EditorLogic.RootPart);

            bool   ClockType  = Settings.Read24Hr();
            double HoursInDay = 6;

            if (ClockType)
            {
                HoursInDay = 24.0;
            }
            else
            {
                HoursInDay = 6.0;
            }
            AllUsableFuels.Clear();

            var allResources = GetResources(constructParts);

            for (int pi = 0; pi < constructParts.Length; pi++)
            {
                Part p = constructParts[pi];

                Dictionary <string, double> UsableFuels = new Dictionary <string, double>();
                Dictionary <string, double> FuelRatios  = new Dictionary <string, double>();

                var moduleEngines = p.FindModuleImplementing <ModuleEngines>();
                if (moduleEngines != null)
                {
                    double engEfficiency = moduleEngines.atmosphereCurve.Evaluate(0);

                    if (moduleEngines != null)
                    {
                        for (int mep = 0; mep < moduleEngines.propellants.Count; mep++)
                        {
                            Propellant pro = moduleEngines.propellants[mep];

                            //if (pro.ToString() == GetResources(constructParts, pro.name)[i])
                            if (allResources.ContainsKey(pro.name))
                            {
                                // Blah blah blah
                                if (!UsableFuels.ContainsKey(pro.name))
                                {
                                    UsableFuels.Add(pro.name, pro.totalResourceCapacity);
                                    FuelRatios.Add(pro.name, pro.ratio);
                                }
                                if (!AllUsableFuels.ContainsKey(pro.name))
                                {
                                    AllUsableFuels.Add(pro.name, pro.totalResourceCapacity);
                                }

                                double ResEff = 1.0 / engEfficiency;

                                Lifetime = Lifetime + allResources[pro.name] /
                                           (DecayManager.EditorDecayRateRadiationPressure(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody) * ResEff * Settings.ReadResourceRateDifficulty() +
                                            DecayManager.EditorDecayRateAtmosphericDrag(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody)
                                           ) / (60 * 60 * HoursInDay);
                            }
                        }
                    }
                }
                var moduleRCS = p.FindModuleImplementing <ModuleRCS>();
                if (moduleRCS != null)
                {
                    var rcsEfficiency = moduleRCS.atmosphereCurve.Evaluate(0);
                    if (moduleRCS != null)
                    {
                        for (int mep = 0; mep < moduleRCS.propellants.Count; mep++)
                        {
                            Propellant pro = moduleRCS.propellants[mep];
                            if (allResources.ContainsKey(pro.name))
                            {
                                // Blah blah blah
                                if (!UsableFuels.ContainsKey(pro.name))
                                {
                                    UsableFuels.Add(pro.name, pro.totalResourceCapacity);
                                    FuelRatios.Add(pro.name, pro.ratio);
                                }
                                if (!AllUsableFuels.ContainsKey(pro.name))
                                {
                                    AllUsableFuels.Add(pro.name, pro.totalResourceCapacity);
                                }

                                double ResEff = 1.0 / rcsEfficiency;

                                Lifetime = Lifetime + allResources[pro.name] /
                                           (DecayManager.EditorDecayRateRadiationPressure(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody) * ResEff * Settings.ReadResourceRateDifficulty() +
                                            DecayManager.EditorDecayRateAtmosphericDrag(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody)
                                           ) / (60 * 60 * HoursInDay);
                            }
                        }
                    }
                }
            }
            return(Lifetime);
        }
Example #17
0
        public void UpdateAeroData(List <FARAeroPartModule> allUsedAeroModules, List <FARAeroPartModule> allUnusedAeroModules)
        {
            _aeroModulesWithIntakes.Clear();
            _intakeModules.Clear();
            _intakeTransforms.Clear();
            _airBreathingEngines.Clear();

            for (int i = 0; i < allUsedAeroModules.Count; i++)       //get all exposed intakes and engines
            {
                FARAeroPartModule aeroModule = allUsedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;

                if (p.Modules.Contains("ModuleResourceIntake"))
                {
                    ModuleResourceIntake intake = (ModuleResourceIntake)p.Modules["ModuleResourceIntake"];
                    _aeroModulesWithIntakes.Add(aeroModule);
                    _intakeModules.Add(intake);
                    _intakeTransforms.Add(p.FindModelTransform(intake.intakeTransformName));
                }
                if (p.Modules.Contains("ModuleEngines"))
                {
                    ModuleEngines engines = (ModuleEngines)p.Modules["ModuleEngines"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
                if (p.Modules.Contains("ModuleEnginesFX"))
                {
                    ModuleEnginesFX engines = (ModuleEnginesFX)p.Modules["ModuleEnginesFX"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
            }

            for (int i = 0; i < allUnusedAeroModules.Count; i++)     //get all covered airbreathing Engines
            {
                FARAeroPartModule aeroModule = allUnusedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;
                if (p.Modules.Contains("ModuleEngines"))
                {
                    ModuleEngines engines = (ModuleEngines)p.Modules["ModuleEngines"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
                if (p.Modules.Contains("ModuleEnginesFX"))
                {
                    ModuleEnginesFX engines = (ModuleEnginesFX)p.Modules["ModuleEnginesFX"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
            }
        }
        private void SetMode()
        {
            if (multiEngine.runningPrimary)
                EngineModeID = 0;
            else
                EngineModeID = 1;

            Utils.Log("VariableIspEngine: Changing mode to " + engineModes[EngineModeID].name);
            CurrentEngineID = engineModes[EngineModeID].name;
            engine = engines[EngineModeID];
            ThrustCurve = engineModes[EngineModeID].thrustCurve;
            IspCurve = engineModes[EngineModeID].ispCurve;

            for (int i=0; i < engine.propellants.Count; i++)
            {
                if (engine.propellants[i].name != "ElectricCharge")
                {
                    fuelPropellant = engine.propellants[i];
                }
                else
                {
                    ecPropellant = engine.propellants[i];
                }
            }

            //Utils.Log("VariableIspEngine: Changed mode to " + engine.engineID);
            Utils.Log("VariableIspEngine: Fuel: " + fuelPropellant.name);
            Utils.Log("VariableIspEngine: Thrust Curve: " + ThrustCurve.Evaluate(0f) + " to " + ThrustCurve.Evaluate(1f));
            Utils.Log("VariableIspEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f));

            AdjustVariableThrust();
        }
        private void SetupPropellants()
        {
            foreach (Propellant prop in engine.propellants)
            {
                if (prop.name != "ElectricCharge")
                {
                    fuelPropellant = prop;
                }
                else
                {
                    ecPropellant = prop;
                }
            }
            //Utils.Log("VariablePowerEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f));

            AdjustVariablePower();
        }
Example #20
0
 public void LoadPropellants(ConfigNode node)
 {
     propellants.Clear();
     foreach (ConfigNode prop in node.GetNodes("PROPELLANT"))
     {
         Propellant fuel = new Propellant();
         fuel.Load(prop);
         propellants.Add(fuel);
     }
     SetupPropellant();
 }
        // Initialization
        public override void OnLoad(ConfigNode node)
        {
            // Run base OnLoad method
            base.OnLoad(node);

            // Initialize density of propellant used in deltaV and mass calculations
            densityHydrogen = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.Hydrogen).density;
            densityDeuterium = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.Deuterium).density;
            densityTritium = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.Tritium).density;

            hydrogenPropellant = this.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Hydrogen);
            deuteriumPropellant = this.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Deuterium);
            tritiumPropellant = this.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Tritium);
        }
        public override void OnStart(PartModule.StartState state)
        {
            if (state != StartState.Editor)
            {
                started = true;
            }
            else
            {
                started = false;
            }
            // Get moduleEngines
            PartModuleList pml = this.part.Modules;

            for (int i = 0; i < pml.Count; i++)
            {
                PartModule curModule = pml.GetModule(i);
                engine = curModule.GetComponent <ModuleEnginesFX>();
            }

            if (engine != null)
            {
                Debug.Log("NFPP: Engine Check Passed");
            }

            foreach (Propellant prop in engine.propellants)
            {
                if (prop.name == FuelName)
                {
                    fuelPropellant = prop;
                }
                if (prop.name == "ElectricCharge")
                {
                    ecPropellant = prop;
                }
            }



            if (UseDirectThrottle)
            {
                ChangeIspAndThrust(engine.requestedThrottle);
            }
            else
            {
                ChangeIspAndThrust(CurThrustSetting / 100f);
            }

            if (state != StartState.Editor)
            {
                SetupVariableEngines();
            }


            CalculateCurves();

            Debug.Log("NFPP: Variable ISP engine setup complete");
            if (UseDirectThrottle)
            {
                Debug.Log("NFPP: Using direct throttle method");
            }
        }
Example #23
0
        public static EngineSim New(PartSim theEngine,
                                    ModuleEngines engineMod,
                                    double atmosphere,
                                    float machNumber,
                                    bool vectoredThrust,
                                    bool fullThrust,
                                    LogMsg log)
        {
            float            maxFuelFlow                = engineMod.maxFuelFlow;
            float            minFuelFlow                = engineMod.minFuelFlow;
            float            thrustPercentage           = engineMod.thrustPercentage;
            List <Transform> thrustTransforms           = engineMod.thrustTransforms;
            List <float>     thrustTransformMultipliers = engineMod.thrustTransformMultipliers;
            Vector3          vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null,
                                                               vectoredThrust ? thrustTransformMultipliers : null,
                                                               log);
            FloatCurve        atmosphereCurve = engineMod.atmosphereCurve;
            bool              atmChangeFlow   = engineMod.atmChangeFlow;
            FloatCurve        atmCurve        = engineMod.useAtmCurve ? engineMod.atmCurve : null;
            FloatCurve        velCurve        = engineMod.useVelCurve ? engineMod.velCurve : null;
            float             currentThrottle = engineMod.currentThrottle;
            float             IspG            = engineMod.g;
            bool              throttleLocked  = engineMod.throttleLocked || fullThrust;
            List <Propellant> propellants     = engineMod.propellants;
            bool              active          = engineMod.isOperational;
            float             resultingThrust = engineMod.resultingThrust;
            bool              isFlamedOut     = engineMod.flameout;

            EngineSim engineSim = pool.Borrow();

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

            double flowRate    = 0.0;
            double maxFlowRate = 0.0;

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

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

                if (throttleLocked)
                {
                    if (log != null)
                    {
                        log.AppendLine("throttleLocked is true, using thrust for flowRate");
                    }
                    flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                }
                else
                {
                    if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
                    {
                        // TODO: This bit doesn't work for RF engines
                        if (log != null)
                        {
                            log.AppendLine("throttled up and not landed, using actualThrust for flowRate");
                        }
                        flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
                    }
                    else
                    {
                        if (log != null)
                        {
                            log.AppendLine("throttled down or landed, using thrust for flowRate");
                        }
                        flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                    }
                }

                maxFlowRate = GetFlowRate(engineSim.fullThrust, engineSim.isp);
            }
            else
            {
                if (log != null)
                {
                    log.buf.AppendLine("hasVessel is false");
                }
                float altitude     = BasicDeltaV.Instance.AtmosphereDepth;
                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, BasicDeltaV.Instance.CurrentCelestialBody.GetDensity(BasicDeltaV.Instance.CurrentCelestialBody.GetPressure(altitude), BasicDeltaV.Instance.CurrentCelestialBody.GetTemperature(altitude)), velCurve, machNumber, ref engineSim.maxMach);
                engineSim.isp          = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.fullThrust   = GetThrust(maxFuelFlow * flowModifier, engineSim.isp);
                engineSim.thrust       = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = 0d;
                if (log != null)
                {
                    log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                    log.AppendLine("no vessel, using thrust for flowRate");
                }

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

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

            float flowMass = 0f;

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

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

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

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

                double consumptionRate = propellant.ratio * flowRate / flowMass;

                if (log != null)
                {
                    log.buf.AppendFormat(
                        "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
                        ResourceContainer.GetResourceName(propellant.id),
                        theEngine.name,
                        theEngine.partId,
                        consumptionRate);
                }

                engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
                engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode());

                double maxConsumptionRate = propellant.ratio * maxFlowRate / flowMass;

                engineSim.maxResourceConsumptions.Add(propellant.id, maxConsumptionRate);
            }

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

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

            return(engineSim);
        }
        /// <summary>
        /// Load the engine config
        /// </summary>
        /// <param name="node">The config node to load from</param>
        public void Load(ConfigNode node)
        {
            if (node.name.Equals("MODE"))
            {
                ConfigNode.LoadObjectFromConfig(this, node);

                //load the propellants
                ConfigNode[] propellantNodes = node.GetNodes("PROPELLANT");
                propellants = new List <Propellant>();
                for (int i = 0; i < propellantNodes.Length; i++)
                {
                    Propellant p = new Propellant();
                    p.Load(propellantNodes[i]);
                    propellants.Add(p);
                }

                //load the name of the mode
                if (node.HasValue("name"))
                {
                    name = node.GetValue("name");
                }

                //load the curve for atmosphere ISP or Thrust
                if (node.HasNode("atmosphereISPCurve"))
                {
                    atmosphereISPCurve = new FloatCurve();
                    atmosphereISPCurve.Load(node.GetNode("atmosphereISPCurve"));

                    float tmpMin;
                    atmosphereISPCurve.FindMinMaxValue(out tmpMin, out maxISP);
                }
                else if (node.HasNode("atmosphereThrustCurve"))
                {
                    atmosphereThrustCurve = new FloatCurve();
                    atmosphereThrustCurve.Load(node.GetNode("atmosphereThrustCurve"));
                }
                else
                {
                    atmosphereISPCurve = new FloatCurve();
                    atmosphereISPCurve.Add(0, 0);
                    atmosphereISPCurve.Add(1, 100);
                    maxISP = 100;
                }

                //load the consumption curve
                if (node.HasNode("consumptionCurve"))
                {
                    consumptionCurve = new FloatCurve();
                    consumptionCurve.Load(node.GetNode("consumptionCurve"));
                }

                //load the velocity curve
                if (node.HasNode("velocityCurve"))
                {
                    velocityCurve = new FloatCurve();
                    velocityCurve.Load(node.GetNode("velocityCurve"));
                }

                //wheter the engine needs an atmosphere to work
                if (node.HasValue("needsAtmosphere"))
                {
                    needsAtmosphere = bool.Parse(node.GetValue("needsAtmosphere"));
                }

                //wheter the engine needs oxygen to operate
                if (node.HasValue("needsOxygen"))
                {
                    needsOxygen = bool.Parse(node.GetValue("needsOxygen"));
                }

                //wheter the engine needs to be in water to operate
                if (node.HasValue("needsWater"))
                {
                    needsWater = bool.Parse(node.GetValue("needsWater"));
                }

                //wheter the engine needs to be in water to operate
                if (node.HasValue("maxThrust"))
                {
                    try
                    {
                        maxThrust = float.Parse(node.GetValue("maxThrust"));
                    }
                    catch (Exception e)
                    {
                        maxThrust = 0;
                        Debug.LogError("[LYNX] Cannot load maxThrust for engine: " + e.Message);
                    }
                }

                //wheter the engine needs to be in water to operate
                if (node.HasValue("flameoutThreshold"))
                {
                    try
                    {
                        flameoutThreshold = float.Parse(node.GetValue("flameoutThreshold"));
                    }
                    catch (Exception e)
                    {
                        flameoutThreshold = 0.1f;
                        Debug.LogError("[LYNX] Cannot load flameoutThreshold for engine: " + e.Message);
                    }
                }

                //calculate the fuel flow modifier
                if (atmosphereISPCurve != null)
                {
                    float fuelDensity = 0.0f;
                    for (int i = 0; i < propellants.Count; i++)
                    {
                        fuelDensity += PartResourceLibrary.Instance.resourceDefinitions[propellants[i].name].density;
                    }

                    fuelFlow = (fuelDensity > 0.0f) ? maxThrust / (9.80665f * maxISP * fuelDensity) : 1;
                }
                else
                {
                    fuelFlow = 1.0f;
                }
            }
        }
Example #25
0
        private void SetupPropellants(bool moveNext)
        {
            try
            {
                Current_propellant = fuel_mode < _propellants.Count ? _propellants[fuel_mode] : _propellants.FirstOrDefault();

                if ((Current_propellant.SupportedEngines & type) != type)
                {
                    _rep++;
                    togglePropellant(moveNext);
                    return;
                }

                Propellant new_propellant = Current_propellant.Propellant;
                if (fuel_gauge != null && new_propellant.drawStackGauge)
                {
                    new_propellant.drawStackGauge = false;
                    fuel_gauge.SetMessage(Current_propellant.PropellantGUIName);
                    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 <Propellant> list_of_propellants = new List <Propellant>();
                list_of_propellants.Add(new_propellant);
                if (!list_of_propellants.Exists(prop => PartResourceLibrary.Instance.GetDefinition(prop.name) == null))
                {
                    _attached_engine.propellants.Clear();
                    _attached_engine.propellants = list_of_propellants;
                    _attached_engine.SetupPropellant();
                }
                else if (_rep < _propellants.Count)
                {
                    _rep++;
                    togglePropellant(moveNext);
                    return;
                }


                if (HighLogic.LoadedSceneIsFlight)
                {
                    // you can have any fuel you want in the editor but not in flight
                    List <PartResource> totalpartresources = list_of_propellants.SelectMany(prop => part.GetConnectedResources(prop.name.Replace("LqdWater", "Water"))).ToList();

                    if (!list_of_propellants.All(prop => totalpartresources.Select(pr => pr.resourceName).Contains(prop.name.Replace("LqdWater", "Water"))) && _rep < _propellants.Count)
                    {
                        _rep++;
                        togglePropellant(moveNext);
                        return;
                    }
                }

                if (Current_propellant.Propellant.name == "LqdWater")
                {
                    if (fuel_gauge != null)
                    {
                        fuel_gauge.SetMessage("Water");
                    }

                    if (!part.Resources.Contains("LqdWater"))
                    {
                        ConfigNode node = new ConfigNode("RESOURCE");
                        node.AddValue("name", "LqdWater");
                        node.AddValue("maxAmount", this.maxPower / this.baseISP);
                        node.AddValue("possibleAmount", 0);
                        this.part.AddResource(node);
                        this.part.Resources.UpdateList();
                    }
                }
                else
                {
                    if (part.Resources.Contains("LqdWater"))
                    {
                        var partresource = part.Resources["LqdWater"];
                        if (partresource.amount > 0 && HighLogic.LoadedSceneIsFlight)
                        {
                            ORSHelper.fixedRequestResource(this.part, "Water", -partresource.amount);
                        }
                        this.part.Resources.list.Remove(partresource);
                        DestroyImmediate(partresource);
                    }
                }

                _rep = 0;
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError("[KSPI] - SetupPropellants ElectricEngineControllerFX " + e.Message);
            }
        }
 public static float FindIsp(float thrust, float flowRate, Propellant fuelPropellant)
 {
     double fuelDensity = PartResourceLibrary.Instance.GetDefinition(fuelPropellant.name).density;
     double isp = (((thrust * 1000f) / (9.82d)) / flowRate) / (fuelDensity * 1000f);
     return (float)isp;
 }
        public override void OnStart(PartModule.StartState state)
        {
            if (state != StartState.Editor)
                started = true;
            else
                started = false;
            // Get moduleEngines
            PartModuleList pml = this.part.Modules;
            for (int i = 0; i < pml.Count; i++)
            {
                PartModule curModule = pml.GetModule(i);
                engine  = curModule.GetComponent<ModuleEnginesFX>();
            }

            if (engine != null)
                Debug.Log("NFPP: Engine Check Passed");

            foreach (Propellant prop in engine.propellants)
            {
                if (prop.name == FuelName)
                    fuelPropellant = prop;
                if (prop.name == "ElectricCharge")
                    ecPropellant = prop;
            }

            if (UseDirectThrottle)
                ChangeIspAndThrust(engine.requestedThrottle);
            else
                ChangeIspAndThrust(CurThrustSetting / 100f);

            if (state != StartState.Editor)
                SetupVariableEngines();

            CalculateCurves();

            Debug.Log("NFPP: Variable ISP engine setup complete");
            if (UseDirectThrottle)
            {
                Debug.Log("NFPP: Using direct throttle method");
            }
        }
        /// <summary>
        /// Refresh cached information.
        /// </summary>
        public void Refresh()
        {
            if (!NeedUpdate())
            {
                return;
            }
            lastUpdateTime = DateTime.Now;
            Vessel vessel = FlightGlobals.ActiveVessel;

            if (vessel == null)
            {
                return;
            }
            vesselId        = vessel.id;
            vesselPartCount = vessel.parts.Count;
            totalMass       = vessel.GetTotalMass();
            activeEngines.Clear();
            for (int engineIndex = 0; engineIndex < Propulsion.Engines.Count; ++engineIndex)
            {
                Part part = Propulsion.Engines[engineIndex];
                for (int moduleIndex = 0; moduleIndex < part.Modules.Count; ++moduleIndex)
                {
                    ModuleEngines engine = part.Modules[moduleIndex] as ModuleEngines;
                    if (engine == null)
                    {
                        continue;
                    }
                    if (!engine.isOperational)
                    {
                        continue;
                    }
                    if (!CheatOptions.InfinitePropellant)
                    {
                        bool isDeprived = false;
                        for (int propellantIndex = 0; propellantIndex < engine.propellants.Count; ++propellantIndex)
                        {
                            Propellant propellant = engine.propellants[propellantIndex];
                            if (propellant.isDeprived && !propellant.ignoreForIsp)
                            {
                                isDeprived = true; // out of fuel!
                                break;
                            }
                        }
                        if (isDeprived)
                        {
                            continue;             // skip this engine
                        }
                    }
                    activeEngines.Add(engine);
                }
            }

            availableResources = new Tally();
            for (int tankIndex = 0; tankIndex < Propulsion.Tanks.Count; ++tankIndex)
            {
                Part part = Propulsion.Tanks[tankIndex];
                for (int resourceIndex = 0; resourceIndex < part.Resources.Count; ++resourceIndex)
                {
                    PartResource resource = part.Resources[resourceIndex];
                    if (resource.flowState)
                    {
                        availableResources.Add(resource.resourceName, resource.amount * resource.info.density);
                    }
                }
            }
        }
Example #29
0
        public static EngineSim New(PartSim theEngine,
                                    double atmosphere,
                                    float machNumber,
                                    float maxFuelFlow,
                                    float minFuelFlow,
                                    float thrustPercentage,
                                    Vector3 vecThrust,
                                    FloatCurve atmosphereCurve,
                                    bool atmChangeFlow,
                                    FloatCurve atmCurve,
                                    FloatCurve velCurve,
                                    float currentThrottle,
                                    float IspG,
                                    bool throttleLocked,
                                    List <Propellant> propellants,
                                    bool active,
                                    float resultingThrust,
                                    List <Transform> thrustTransforms,
                                    LogMsg log)
        {
            EngineSim engineSim = pool.Borrow();

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

            double flowRate = 0.0;

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

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

                if (throttleLocked)
                {
                    if (log != null)
                    {
                        log.buf.AppendLine("throttleLocked is true, using thrust for flowRate");
                    }
                    flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                }
                else
                {
                    if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
                    {
                        if (log != null)
                        {
                            log.buf.AppendLine("throttled up and not landed, using actualThrust for flowRate");
                        }
                        flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
                    }
                    else
                    {
                        if (log != null)
                        {
                            log.buf.AppendLine("throttled down or landed, using thrust for flowRate");
                        }
                        flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                    }
                }
            }
            else
            {
                if (log != null)
                {
                    log.buf.AppendLine("hasVessel is false");
                }
                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, SimManager.Body.GetDensity(FlightGlobals.getStaticPressure(0, SimManager.Body), FlightGlobals.getExternalTemperature(0, SimManager.Body)), velCurve, machNumber, ref engineSim.maxMach);
                engineSim.isp          = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust       = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = 0d;
                if (log != null)
                {
                    log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                }

                if (log != null)
                {
                    log.buf.AppendLine("no vessel, using thrust for flowRate");
                }
                flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
            }

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

            float flowMass = 0f;

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

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

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

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

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

            double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;

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

                AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
                engineSim.appliedForces.Add(appliedForce);
            }

            return(engineSim);
        }
Example #30
0
        public static EngineSim New(PartSim theEngine,
                                    double atmosphere,
                                    double machNumber,
                                    float maxFuelFlow,
                                    float minFuelFlow,
                                    float thrustPercentage,
                                    Vector3 vecThrust,
                                    FloatCurve atmosphereCurve,
                                    bool atmChangeFlow,
                                    FloatCurve atmCurve,
                                    FloatCurve velCurve,
                                    float currentThrottle,
                                    float IspG,
                                    bool throttleLocked,
                                    List <Propellant> propellants,
                                    bool active,
                                    bool correctThrust,
                                    List <Transform> thrustTransforms)
        {
            EngineSim engineSim = pool.Borrow();


            StringBuilder buffer = null;

            //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
            //MonoBehaviour.print("maxThrust = " + maxThrust);
            //MonoBehaviour.print("minThrust = " + minThrust);
            //MonoBehaviour.print("thrustPercentage = " + thrustPercentage);
            //MonoBehaviour.print("requestedThrust = " + requestedThrust);
            //MonoBehaviour.print("velocity = " + velocity);

            engineSim.partSim = theEngine;

            engineSim.isActive = active;
            //engineSim.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
            //MonoBehaviour.print("thrust = " + thrust);

            engineSim.thrustVec = vecThrust;

            double flowRate = 0d;

            if (engineSim.partSim.hasVessel)
            {
                //MonoBehaviour.print("hasVessel is true");

                //engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0;

                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);

                //if (engineSim.isp == 0d)
                //{
                //    MonoBehaviour.print("Isp at " + engineSim.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
                //}

                //if (correctThrust && realIsp == 0)
                //{
                //    float ispsl = atmosphereCurve.Evaluate(0);
                //    if (ispsl != 0)
                //    {
                //        engineSim.thrust = engineSim.thrust * engineSim.isp / ispsl;
                //    }
                //    else
                //    {
                //        MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
                //    }
                //    //MonoBehaviour.print("corrected thrust = " + thrust);
                //}

                //if (velocityCurve != null)
                //{
                //    engineSim.thrust *= velocityCurve.Evaluate((float)velocity);
                //    //MonoBehaviour.print("thrust at velocity = " + thrust);
                //}

                float multiplier = 1;
                if (atmChangeFlow)
                {
                    multiplier = (float)(engineSim.partSim.part.atmDensity / 1.225);
                    if (atmCurve != null)
                    {
                        multiplier = atmCurve.Evaluate(multiplier);
                    }
                }
                if (velCurve != null)
                {
                    multiplier *= velCurve.Evaluate((float)machNumber);
                }

                if (throttleLocked)
                {
                    //MonoBehaviour.print("throttleLocked is true");
                    //flowRate = engineSim.thrust / (engineSim.isp * 9.82);
                    flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier;
                }
                else
                {
                    if (engineSim.partSim.isLanded)
                    {
                        //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
                        flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, FlightInputHandler.state.mainThrottle * (thrustPercentage / 100f)) * multiplier;
                    }
                    else
                    {
                        if (currentThrottle > 0)
                        {
                            //MonoBehaviour.print("requestedThrust > 0");
                            //flowRate = requestedThrust / (engineSim.isp * 9.82) * multiplier;
                            flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, currentThrottle * (thrustPercentage / 100f)) * multiplier;
                        }
                        else
                        {
                            //MonoBehaviour.print("requestedThrust <= 0");
                            flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier;
                        }
                    }
                }
            }
            else
            {
                //MonoBehaviour.print("hasVessel is false");
                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
                if (engineSim.isp == 0d)
                {
                    MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
                }
                //if (correctThrust)
                //{
                //    float ispsl = atmosphereCurve.Evaluate(0);
                //    if (ispsl != 0)
                //    {
                //        engineSim.thrust = engineSim.thrust * engineSim.isp / ispsl;
                //    }
                //    else
                //    {
                //        MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
                //    }
                //    //MonoBehaviour.print("corrected thrust = " + thrust);
                //}

                float multiplier = 1;
                if (atmChangeFlow)
                {
                    //multiplier = (float)(engineSim.partSim.part.atmDensity / 1.225);
                    multiplier = (float)atmosphere;    // technically wrong but about the same for my Editor need
                    if (atmCurve != null)
                    {
                        multiplier = atmCurve.Evaluate(multiplier);
                    }
                }

                if (velCurve != null)
                {
                    multiplier *= velCurve.Evaluate((float)machNumber);
                }

                flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier;
            }

            if (SimManager.logOutput)
            {
                buffer = new StringBuilder(1024);
                buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
            }

            engineSim.thrust = flowRate * (engineSim.isp * IspG);
            // TODO : look into the diff between the 2 in the old code (jet real thrust vs ideal thrust ?)
            engineSim.actualThrust = engineSim.thrust;

            float flowMass = 0f;

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

            if (SimManager.logOutput)
            {
                buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
            }

            for (int i = 0; i < propellants.Count; i++)
            {
                Propellant propellant = propellants[i];
                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                {
                    continue;
                }

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

            if (SimManager.logOutput)
            {
                MonoBehaviour.print(buffer);
            }

            double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;

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

                AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
                engineSim.appliedForces.Add(appliedForce);
            }
            return(engineSim);
        }
 public static float FindPowerUse(float thrust,float isp,Propellant ecPropellant, Propellant fuelPropellant)
 {
     return (ecPropellant.ratio / fuelPropellant.ratio) * FindFlowRate(thrust, isp, fuelPropellant);
 }
Example #32
0
 public static float FindPowerUse(float thrust, float isp, Propellant ecPropellant, Propellant fuelPropellant)
 {
     return((ecPropellant.ratio / fuelPropellant.ratio) * FindFlowRate(thrust, isp, fuelPropellant));
 }
        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();
               //     }
            //}
        }
Example #34
0
        public static RCSSim New(PartSim theEngine,
                                 ModuleRCS engineMod,
                                 double atmosphere,
                                 float machNumber,
                                 bool vectoredThrust,
                                 bool fullThrust,
                                 LogMsg log)
        {
            double maxFuelFlow = engineMod.maxFuelFlow;
            // double minFuelFlow = engineMod.minFuelFlow;
            float            thrustPercentage = engineMod.thrustPercentage;
            List <Transform> thrustTransforms = engineMod.thrusterTransforms;
            //   List<float> thrustTransformMultipliers = engineMod.th
            Vector3    vecThrust       = CalculateThrustVector(vectoredThrust ? thrustTransforms : null, log);
            FloatCurve atmosphereCurve = engineMod.atmosphereCurve;
            //   bool atmChangeFlow = engineMod.at
            //   FloatCurve atmCurve = engineMod.useAtmCurve ? engineMod.atmCurve : null;
            //   FloatCurve velCurve = engineMod.useVelCurve ? engineMod.velCurve : null;
            //    float currentThrottle = engineMod.currentThrottle;
            double IspG = engineMod.G;
            //    bool throttleLocked = engineMod.throttleLocked || fullThrust;
            List <Propellant> propellants = engineMod.propellants;
            bool active = engineMod.moduleIsEnabled;
            //    float resultingThrust = engineMod.resultingThrust;
            bool isFlamedOut = engineMod.flameout;

            RCSSim engineSim = pool.Borrow();

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

            double flowRate = 0.0;

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

                engineSim.isp          = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust       = GetThrust(maxFuelFlow, engineSim.isp);
                engineSim.actualThrust = engineSim.isActive ? engineSim.thrust : 0.0;

                if (log != null)
                {
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                }

                if (true)
                {
                    if (log != null)
                    {
                        log.AppendLine("throttleLocked is true, using thrust for flowRate");
                    }
                    flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                }
                else
                {
                    //              if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
                    //              {
                    //// TODO: This bit doesn't work for RF engines
                    //if (log != null) log.AppendLine("throttled up and not landed, using actualThrust for flowRate");
                    //                  flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
                    //              }
                    //              else
                    //              {
                    //                  if (log != null) log.AppendLine("throttled down or landed, using thrust for flowRate");
                    //                  flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                    //              }
                }
            }
            else
            {
                if (log != null)
                {
                    log.buf.AppendLine("hasVessel is false");
                }
                engineSim.isp          = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust       = GetThrust(maxFuelFlow, engineSim.isp);
                engineSim.actualThrust = 0d;
                if (log != null)
                {
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                    log.AppendLine("no vessel, using thrust for flowRate");
                }

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

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

            float flowMass = 0f;

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

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

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

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

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

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

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

            return(engineSim);
        }
        private void SetupPropellants()
        {
            for (int i = 0; i < engine.propellants.Count; i++ )
            {
                if (engine.propellants[i].name != "ElectricCharge")
                {
                    fuelPropellant = engine.propellants[i];
                }
                else
                {
                    ecPropellant = engine.propellants[i];
                }
            }
            //Utils.Log("VariablePowerEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f));

            AdjustVariablePower();
        }
Example #36
0
        public void setupPropellants()
        {
            ConfigNode chosenpropellant = propellants[fuel_mode];

            ConfigNode[]      assprops            = chosenpropellant.GetNodes("PROPELLANT");
            List <Propellant> list_of_propellants = new List <Propellant>();

            // loop though propellants until we get to the selected one, then set it up
            foreach (ConfigNode prop_node in assprops)
            {
                fuelmode                 = chosenpropellant.GetValue("guiName");
                ispMultiplier            = float.Parse(chosenpropellant.GetValue("ispMultiplier"));
                isLFO                    = bool.Parse(chosenpropellant.GetValue("isLFO"));
                currentpropellant_is_jet = false;
                if (chosenpropellant.HasValue("isJet"))
                {
                    currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet"));
                }
                //print (currentpropellant_is_jet);

                Propellant curprop = new Propellant();
                curprop.Load(prop_node);
                if (curprop.drawStackGauge && HighLogic.LoadedSceneIsFlight)
                {
                    curprop.drawStackGauge = false;
                    if (currentpropellant_is_jet)
                    {
                        fuel_gauge.SetMessage("Atmosphere");
                    }
                    else
                    {
                        fuel_gauge.SetMessage(curprop.name);
                        myAttachedEngine.thrustPercentage = 100;
                        part.temperature = 1;
                    }
                    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);
            }

            // update the engine with the new propellants
            if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null)
            {
                myAttachedEngine.propellants.Clear();
                myAttachedEngine.propellants = list_of_propellants;
                myAttachedEngine.SetupPropellant();
            }

            if (HighLogic.LoadedSceneIsFlight)   // you can have any fuel you want in the editor but not in flight
            // should we switch to another propellant because we have none of this one?
            {
                bool next_propellant = false;
                List <Propellant> curEngine_propellants_list = new List <Propellant>();
                curEngine_propellants_list = myAttachedEngine.propellants;
                foreach (Propellant curEngine_propellant in curEngine_propellants_list)
                {
                    List <PartResource> partresources = part.GetConnectedResources(curEngine_propellant.name).ToList();

                    if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name))
                    {
                        next_propellant = true;
                    }
                }

                // do the switch if needed
                if (next_propellant && fuel_mode != 1)
                {
                    TogglePropellant();
                }
            }
            else
            {
                if (!PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name) && fuel_mode != 1)   // Still ignore propellants that don't exist
                {
                    TogglePropellant();
                }
                estimateEditorPerformance(); // update editor estimates
            }
        }
 private float FindFlowRate(float thrust, float isp, Propellant fuelPropellant)
 {
     double fuelDensity = PartResourceLibrary.Instance.GetDefinition(fuelPropellant.name).density;
     double fuelRate = ((thrust * 1000f) / (isp * Utils.GRAVITY)) / (fuelDensity * 1000f);
     return (float)fuelRate;
 }
		public void setupPropellants() {
			ConfigNode chosenpropellant = propellants[fuel_mode];
			ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT");
			List<Propellant> list_of_propellants = new List<Propellant>();
			// loop though propellants until we get to the selected one, then set it up
			foreach(ConfigNode prop_node in assprops) 
            {
				fuelmode = chosenpropellant.GetValue("guiName");
				ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier"));
				isLFO = bool.Parse(chosenpropellant.GetValue("isLFO"));
				currentpropellant_is_jet = false;
				if(chosenpropellant.HasValue("isJet")) {
					currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet"));
				}
				//print (currentpropellant_is_jet);

				Propellant curprop = new Propellant();
				curprop.Load(prop_node);
				if (curprop.drawStackGauge && HighLogic.LoadedSceneIsFlight) {
					curprop.drawStackGauge = false;
					if (currentpropellant_is_jet) {
						fuel_gauge.SetMessage("Atmosphere");
					}else {
						fuel_gauge.SetMessage(curprop.name);
                        myAttachedEngine.thrustPercentage = 100;
                        part.temperature = 1;
					}
					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);
			}
            
			// update the engine with the new propellants
			if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) {
				myAttachedEngine.propellants.Clear();
				myAttachedEngine.propellants = list_of_propellants;
				myAttachedEngine.SetupPropellant();
			}

            if (HighLogic.LoadedSceneIsFlight) { // you can have any fuel you want in the editor but not in flight
                // should we switch to another propellant because we have none of this one?
                bool next_propellant = false;
                List<Propellant> curEngine_propellants_list = new List<Propellant>();
                curEngine_propellants_list = myAttachedEngine.propellants;
                foreach (Propellant curEngine_propellant in curEngine_propellants_list) {
                    List<PartResource> partresources = part.GetConnectedResources(curEngine_propellant.name).ToList();

                    if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name)) {
                        next_propellant = true;
                    }
                }

                // do the switch if needed
                if (next_propellant && fuel_mode != 1) {
                    TogglePropellant();
                }
            } else {
                if (!PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name) && fuel_mode != 1) { // Still ignore propellants that don't exist
                    TogglePropellant();
                }
                estimateEditorPerformance(); // update editor estimates
            }

		}
Example #39
0
        public static EngineSim New(PartSim theEngine,
                                    ModuleEngines engineMod,
                                    double atmosphere,
                                    float machNumber,
                                    bool vectoredThrust,
                                    bool fullThrust,
                                    LogMsg log)
        {
            float            maxFuelFlow                = engineMod.maxFuelFlow;
            float            minFuelFlow                = engineMod.minFuelFlow;
            float            thrustPercentage           = engineMod.thrustPercentage;
            List <Transform> thrustTransforms           = engineMod.thrustTransforms;
            List <float>     thrustTransformMultipliers = engineMod.thrustTransformMultipliers;
            Vector3          vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null,
                                                               vectoredThrust ? thrustTransformMultipliers : null,
                                                               log);
            FloatCurve        atmosphereCurve  = engineMod.atmosphereCurve;
            bool              atmChangeFlow    = engineMod.atmChangeFlow;
            FloatCurve        atmCurve         = engineMod.useAtmCurve ? engineMod.atmCurve : null;
            FloatCurve        velCurve         = engineMod.useVelCurve ? engineMod.velCurve : null;
            FloatCurve        thrustCurve      = engineMod.useThrustCurve ? engineMod.thrustCurve : null;
            float             currentThrottle  = engineMod.currentThrottle;
            float             IspG             = engineMod.g;
            bool              throttleLocked   = engineMod.throttleLocked || fullThrust;
            List <Propellant> propellants      = engineMod.propellants;
            float             thrustCurveRatio = engineMod.thrustCurveRatio;

            foreach (Propellant p in propellants)
            {
                if (p.ignoreForThrustCurve)
                {
                    continue;
                }
                double ratio = p.totalResourceAvailable / p.totalResourceCapacity;
                if (ratio < thrustCurveRatio)
                {
                    thrustCurveRatio = (float)ratio;
                }
            }

            bool active = engineMod.isOperational;

            //I do not know if this matters. RF and stock always have finalThrust. But stock uses resultingThrust in the mass flow calculations, so keep it.
            float resultingThrust = SimManager.hasInstalledRealFuels ? engineMod.finalThrust : engineMod.resultingThrust;

            bool isFlamedOut = engineMod.flameout;

            EngineSim engineSim = pool.Borrow();

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



            double flowRate = 0.0;

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

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

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

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

            float flowMass = 0f;

            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];
                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                {
                    continue;
                }
                flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
            }

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

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

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

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

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

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

            return(engineSim);
        }
        public void setupPropellants()
        {
            ConfigNode chosenpropellant = propellants[fuel_mode];
            ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT");
            List<Propellant> list_of_propellants = new List<Propellant>();
            // loop though propellants until we get to the selected one, then set it up
            for (int i = 0; i < assprops.Length; ++i) {
                fuelmode = chosenpropellant.GetValue("guiName");
                ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier"));
                isLFO = bool.Parse(chosenpropellant.GetValue("isLFO"));
                currentpropellant_is_jet = false;
                if(chosenpropellant.HasValue("isJet")) {
                    currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet"));
                }
                //print (currentpropellant_is_jet);

                Propellant curprop = new Propellant();
                curprop.Load(assprops[i]);
                if (curprop.drawStackGauge) {
                    curprop.drawStackGauge = false;
                    if (currentpropellant_is_jet) {
                        fuel_gauge.SetMessage("Atmosphere");
                    }else {
                        fuel_gauge.SetMessage(curprop.name);
                        myAttachedEngine.thrustPercentage = 100;
                        part.temperature = 1;
                    }
                    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);
            }
            // update the engine with the new propellants
            if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) {
                myAttachedEngine.propellants.Clear();
                myAttachedEngine.propellants = list_of_propellants;
                myAttachedEngine.SetupPropellant();
            }

            // should we switch to another propellant because we have none of this one?
            bool next_propellant = false;
            List<Propellant> curEngine_propellants_list = new List<Propellant>();
            curEngine_propellants_list = myAttachedEngine.propellants;
            foreach(Propellant curEngine_propellant in curEngine_propellants_list) {
                List<PartResource> partresources = new List<PartResource>();
                part.GetConnectedResources(curEngine_propellant.id, PartResourceLibrary.Instance.GetDefinition(curEngine_propellant.name).resourceFlowMode, partresources);

                if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name)) {
                    next_propellant = true;
                }
            }
            // do the switch if needed
            if (next_propellant && fuel_mode != 1) {
                TogglePropellant();
            }
        }
        private void SetupPropellants(bool moveNext)
        {
            try
            {
                Current_propellant = fuel_mode < _propellants.Count ? _propellants[fuel_mode] : _propellants.FirstOrDefault();

                if ((Current_propellant.SupportedEngines & type) != type)
                {
                    _rep++;
                    togglePropellant(moveNext);
                    return;
                }

                Propellant new_propellant = Current_propellant.Propellant;

                List <Propellant> list_of_propellants = new List <Propellant>();
                list_of_propellants.Add(new_propellant);

                // if all propellant exist
                if (!list_of_propellants.Exists(prop => PartResourceLibrary.Instance.GetDefinition(prop.name) == null))
                {
                    //Get the Ignition state, i.e. is the engine shutdown or activated
                    var engineState = _attached_engine.getIgnitionState;

                    _attached_engine.Shutdown();

                    ConfigNode newPropNode = new ConfigNode();
                    foreach (var prop in list_of_propellants)
                    {
                        ConfigNode propellantConfigNode = newPropNode.AddNode("PROPELLANT");
                        propellantConfigNode.AddValue("name", prop.name);
                        propellantConfigNode.AddValue("ratio", prop.ratio);
                        propellantConfigNode.AddValue("DrawGauge", "true");
                    }
                    _attached_engine.Load(newPropNode);

                    if (engineState == true)
                    {
                        _attached_engine.Activate();
                    }
                }
                else if (_rep < _propellants.Count)
                {
                    _rep++;
                    togglePropellant(moveNext);
                    return;
                }

                if (HighLogic.LoadedSceneIsFlight)
                {
                    // you can have any fuel you want in the editor but not in flight
                    var allVesselResourcesNames = part.vessel.parts.SelectMany(m => m.Resources).Select(m => m.resourceName).Distinct();
                    if (!list_of_propellants.All(prop => allVesselResourcesNames.Contains(prop.name.Replace("LqdWater", "Water"))) && _rep < _propellants.Count)
                    {
                        _rep++;
                        togglePropellant(moveNext);
                        return;
                    }
                }

                _rep = 0;
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError("[KSPI] - SetupPropellants ElectricEngineControllerFX " + e.Message);
            }
        }
		public void MarkPropellant(Propellant propel)
		{
			foreach (PartResource resource in propel.connectedResources) {
				data[resource.info.id].ispropellant = true;
			}
		}
        private void SetEngineInfo()
        {
            protoModuleEngine = selectedPart.GetProtoModuleEngine();
            if (protoModuleEngine != null)
            {
                infoItems.Add(PartInfoItem.Create("Thrust", Units.ToForce(protoModuleEngine.MinimumThrust, protoModuleEngine.MaximumThrust)));
                infoItems.Add(PartInfoItem.Create("Isp", Units.ConcatF(protoModuleEngine.GetSpecificImpulse(1.0f), protoModuleEngine.GetSpecificImpulse(0.0f)) + "s"));
                if (protoModuleEngine.Propellants.Count > 0)
                {
                    infoItems.Add(PartInfoItem.Create("Propellants"));

                    float totalRatio = 0.0f;
                    for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i)
                    {
                        totalRatio = totalRatio + protoModuleEngine.Propellants[i].ratio;
                    }

                    for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i)
                    {
                        propellant = protoModuleEngine.Propellants[i];
                        infoItems.Add(PartInfoItem.Create("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
                    }
                }
            }
        }
Example #44
0
        private void SetupPropellants(bool moveNext = true, int maxSwitching = 0)
        {
            Current_propellant = fuel_mode < _propellants.Count ? _propellants[fuel_mode] : _propellants.FirstOrDefault();
            fuel_mode_name     = Current_propellant.PropellantName;

            if ((Current_propellant.SupportedEngines & type) != type)
            {
                SwitchPropellant(moveNext, --maxSwitching);
                return;
            }

            Propellant new_propellant = Current_propellant.Propellant;

            if (HighLogic.LoadedSceneIsFlight)
            {
                // you can have any fuel you want in the editor but not in flight
                var totalpartresources = part.GetConnectedResources(new_propellant.name).ToList();
                if (!totalpartresources.Any() && maxSwitching > 0)
                {
                    SwitchPropellant(moveNext, --maxSwitching);
                    return;
                }
            }

            if (PartResourceLibrary.Instance.GetDefinition(new_propellant.name) != null)
            {
                var effectiveIspMultiplier = type == 2 ? Current_propellant.DecomposedIspMult : Current_propellant.IspMultiplier;

                //var effectiveThrust = (thrustLimiter / 100) * Current_propellant.ThrustMultiplier * baseThrust / effectiveIspMultiplier;

                var moduleConfig = new ConfigNode("MODULE");

                moduleConfig.AddValue("thrusterPower", attachedRCS.thrusterPower.ToString("0.000"));
                moduleConfig.AddValue("resourceName", new_propellant.name);
                moduleConfig.AddValue("resourceFlowMode", "STAGE_PRIORITY_FLOW");

                //var newPropNode = new ConfigNode();
                ConfigNode propellantConfigNode = moduleConfig.AddNode("PROPELLANT");
                propellantConfigNode.AddValue("name", new_propellant.name);
                propellantConfigNode.AddValue("ratio", "1");
                propellantConfigNode.AddValue("DrawGauge", "True");
                propellantConfigNode.AddValue("resourceFlowMode", "STAGE_PRIORITY_FLOW");
                attachedRCS.Load(propellantConfigNode);

                currentThrustMultiplier = hasSufficientPower ? Current_propellant.ThrustMultiplier : Current_propellant.ThrustMultiplierCold;

                //var effectiveThrustModifier = currentThrustMultiplier * (currentThrustMultiplier / Current_propellant.ThrustMultiplier);

                var effectiveBaseIsp = hasSufficientPower ? maxIsp : minIsp;

                maxPropellantIsp = (float)(effectiveBaseIsp * effectiveIspMultiplier * currentThrustMultiplier);

                var atmosphereCurve = new ConfigNode("atmosphereCurve");
                atmosphereCurve.AddValue("key", "0 " + (maxPropellantIsp).ToString("0.000"));
                if (type != 8)
                {
                    atmosphereCurve.AddValue("key", "1 " + (maxPropellantIsp * 0.5).ToString("0.000"));
                    atmosphereCurve.AddValue("key", "4 " + (maxPropellantIsp * 0.00001).ToString("0.000"));
                }
                else
                {
                    atmosphereCurve.AddValue("key", "1 " + (maxPropellantIsp).ToString("0.000"));
                }

                moduleConfig.AddNode(atmosphereCurve);

                attachedRCS.Load(moduleConfig);
            }
            else if (maxSwitching > 0)
            {
                Debug.Log("ElectricRCSController SetupPropellants switching mode because no definition found for " + new_propellant.name);
                SwitchPropellant(moveNext, --maxSwitching);
                return;
            }
        }
        public void UpdateAeroData(List <FARAeroPartModule> allUsedAeroModules, List <FARAeroPartModule> allUnusedAeroModules)
        {
            _aeroModulesWithIntakes.Clear();
            _intakeModules.Clear();
            _intakeTransforms.Clear();
            _airBreathingEngines.Clear();

            HashSet <string> intakeResourceNames = new HashSet <string>();


            for (int i = 0; i < allUsedAeroModules.Count; i++)       //get all exposed intakes
            {
                FARAeroPartModule aeroModule = allUsedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;

                for (int j = 0; j < p.Modules.Count; j++)
                {
                    PartModule m = p.Modules[j];
                    if (m is ModuleResourceIntake)
                    {
                        ModuleResourceIntake intake = (ModuleResourceIntake)m;

                        if (intake.node != null && intake.node.attachedPart != null)
                        {
                            continue;
                        }

                        _aeroModulesWithIntakes.Add(aeroModule);
                        _intakeModules.Add(intake);
                        _intakeTransforms.Add(p.FindModelTransform(intake.intakeTransformName));
                        if (!intakeResourceNames.Contains(intake.resourceName))
                        {
                            intakeResourceNames.Add(intake.resourceName);
                        }
                    }
                }
            }


            for (int i = 0; i < allUsedAeroModules.Count; i++)       //get all exposed engines
            {
                FARAeroPartModule aeroModule = allUsedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;

                for (int j = 0; j < p.Modules.Count; j++)
                {
                    PartModule m = p.Modules[j];

                    if (m is ModuleEngines)
                    {
                        ModuleEngines e = (ModuleEngines)m;
                        if (FARAeroUtil.AJELoaded)
                        {
                            if (m.ClassID == AJE_JET_CLASS_ID || m.ClassID == AJE_PROP_CLASS_ID)
                            {
                                _airBreathingEngines.Add(e);
                                continue;
                            }
                        }

                        for (int k = 0; k < e.propellants.Count; k++)
                        {
                            Propellant prop = e.propellants[k];
                            if (intakeResourceNames.Contains(prop.name))
                            {
                                _airBreathingEngines.Add(e);
                                break;
                            }
                        }
                    }
                }
            }
        }
        public void setupPropellants()
        {
            ConfigNode chosenpropellant = propellants[fuel_mode];

            ConfigNode[]      assprops            = chosenpropellant.GetNodes("PROPELLANT");
            List <Propellant> list_of_propellants = new List <Propellant>();

            // loop though propellants until we get to the selected one, then set it up
            for (int i = 0; i < assprops.Length; ++i)
            {
                fuelmode                 = chosenpropellant.GetValue("guiName");
                ispMultiplier            = float.Parse(chosenpropellant.GetValue("ispMultiplier"));
                isLFO                    = bool.Parse(chosenpropellant.GetValue("isLFO"));
                currentpropellant_is_jet = false;
                if (chosenpropellant.HasValue("isJet"))
                {
                    currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet"));
                }
                //print (currentpropellant_is_jet);

                Propellant curprop = new Propellant();
                curprop.Load(assprops[i]);
                if (curprop.drawStackGauge)
                {
                    curprop.drawStackGauge = false;
                    if (currentpropellant_is_jet)
                    {
                        fuel_gauge.SetMessage("Atmosphere");
                    }
                    else
                    {
                        fuel_gauge.SetMessage(curprop.name);
                        myAttachedEngine.thrustPercentage = 100;
                        part.temperature = 1;
                    }
                    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);
            }
            // update the engine with the new propellants
            if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null)
            {
                myAttachedEngine.propellants.Clear();
                myAttachedEngine.propellants = list_of_propellants;
                myAttachedEngine.SetupPropellant();
            }

            // should we switch to another propellant because we have none of this one?
            bool next_propellant = false;
            List <Propellant> curEngine_propellants_list = new List <Propellant>();

            curEngine_propellants_list = myAttachedEngine.propellants;
            foreach (Propellant curEngine_propellant in curEngine_propellants_list)
            {
                List <PartResource> partresources = new List <PartResource>();
                part.GetConnectedResources(curEngine_propellant.id, partresources);

                if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name))
                {
                    next_propellant = true;
                }
            }
            // do the switch if needed
            if (next_propellant && fuel_mode != 1)
            {
                TogglePropellant();
            }
        }
Example #47
0
        private void SetupICrossSectionAdjusters()
        {
            Matrix4x4 worldToVesselMatrix;

            if (HighLogic.LoadedSceneIsFlight)
            {
                worldToVesselMatrix = vessel.vesselTransform.worldToLocalMatrix;
            }
            else
            {
                worldToVesselMatrix = EditorLogic.RootPart.partTransform.worldToLocalMatrix;
            }
            crossSectionAdjusters = new List <ICrossSectionAdjuster>();

            string intakeType = "", engineType = "";

            if (part.Modules.Contains("ModuleEnginesAJEJet"))       //hard-coded support for AJE; TODO: separate out for more configurable compatibility on 3rd-party end
            {
                engineType = "ModuleEnginesAJEJet";
            }
            else if (part.Modules.Contains("ModuleEngines"))
            {
                engineType = "ModuleEngines";
            }
            else if (part.Modules.Contains("ModuleEnginesFX"))
            {
                engineType = "ModuleEnginesFX";
            }


            if (part.Modules.Contains("AJEInlet"))
            {
                intakeType = "AJEInlet";
            }
            else if (part.Modules.Contains("ModuleResourceIntake"))
            {
                intakeType = "ModuleResourceIntake";
            }

            if (intakeType != "" && engineType != "")
            {
                PartModule module = part.Modules[intakeType];

                if (module is ModuleResourceIntake)
                {
                    ModuleResourceIntake intake = (ModuleResourceIntake)module;

                    IntegratedIntakeEngineCrossSectionAdjuster intakeAdjuster = IntegratedIntakeEngineCrossSectionAdjuster.CreateAdjuster(intake, worldToVesselMatrix);
                    crossSectionAdjusters.Add(intakeAdjuster);
                }
                else
                {
                    IntegratedIntakeEngineCrossSectionAdjuster intakeAdjuster = IntegratedIntakeEngineCrossSectionAdjuster.CreateAdjuster(module, worldToVesselMatrix);
                    crossSectionAdjusters.Add(intakeAdjuster);
                }
                return;
            }
            if (intakeType != "")
            {
                PartModule module = part.Modules[intakeType];

                if (module is ModuleResourceIntake)
                {
                    ModuleResourceIntake intake = (ModuleResourceIntake)module;

                    IntakeCrossSectionAdjuster intakeAdjuster = IntakeCrossSectionAdjuster.CreateAdjuster(intake, worldToVesselMatrix);
                    crossSectionAdjusters.Add(intakeAdjuster);
                }
                else
                {
                    IntakeCrossSectionAdjuster intakeAdjuster = IntakeCrossSectionAdjuster.CreateAdjuster(module, worldToVesselMatrix);
                    crossSectionAdjusters.Add(intakeAdjuster);
                }
                return;
            }
            if (engineType != "")
            {
                ModuleEngines engines     = (ModuleEngines)part.Modules[engineType];
                bool          airBreather = false;

                if (engineType == "ModuleEnginesAJEJet")
                {
                    airBreather = true;
                }
                else
                {
                    for (int i = 0; i < engines.propellants.Count; ++i)
                    {
                        Propellant p = engines.propellants[i];
                        if (p.name == "IntakeAir")
                        {
                            airBreather = true;
                            break;
                        }
                    }
                }

                if (airBreather)
                {
                    AirbreathingEngineCrossSectonAdjuster engineAdjuster = new AirbreathingEngineCrossSectonAdjuster(engines, worldToVesselMatrix);
                    crossSectionAdjusters.Add(engineAdjuster);
                }
                return;
            }
        }
        public override void Start()
        {
            if (curveResource != string.Empty)
            {
                curveProp = propellants.FirstOrDefault(x => x.name.Equals(curveResource));
            }
            useThrustCurve = curveProp is Propellant;

            CalcThrottleResponseRate(ref throttleResponseRate, ref instantThrottle);

            if (!HighLogic.LoadedSceneIsFlight)
            {
                partSeed            = -1;
                calculatedResiduals = localResidualsThresholdBase;
                ignited             = false;
            }
            else
            {
                if (partSeed == -1)
                {
                    calculatedResiduals = localResidualsThresholdBase + UnityEngine.Random.Range(0f, (float)localVaryResiduals);
                    partSeed            = UnityEngine.Random.Range(0, int.MaxValue);
                }
            }

            base.Start();
            if (!(engineSolver is SolverRF))
            {
                CreateEngine();
            }

            // Setup for mixture variation
            backupPropellantRatios.Clear();
            oxidizerPropellant = fuelPropellant = null;
            for (int i = 0; i < propellants.Count(); ++i)
            {
                Propellant p = propellants[i];
                backupPropellantRatios.Add(p.ratio);

                if (p.ignoreForIsp || p.resourceDef.density == 0d)
                {
                    continue;
                }

                if (fuelPropellant == null)
                {
                    fuelPropellant = p;
                }
                else if (oxidizerPropellant == null)
                {
                    oxidizerPropellant = p;
                }
            }
            if (fuelPropellant != null && oxidizerPropellant != null)
            {
                mixtureRatio = (oxidizerPropellant.ratio * oxidizerPropellant.resourceDef.density) / (fuelPropellant.ratio * fuelPropellant.resourceDef.density);
            }

            ullageSet = new Ullage.UllageSet(this);
            ullageSet.Load(ullageNode);

            Fields[nameof(ignitions)].guiActive        = ignitions >= 0 && RFSettings.Instance.limitedIgnitions;
            Fields[nameof(tags)].guiActiveEditor       = ShowPropStatus;
            Fields[nameof(propellantStatus)].guiActive = Fields[nameof(propellantStatus)].guiActiveEditor = ShowPropStatus;
            Fields[nameof(sIgnitions)].guiActiveEditor = RFSettings.Instance.limitedIgnitions;

            igniteFailIgnitions = new ScreenMessage($"<color=orange>[{part.partInfo.title}]: no ignitions remaining!</color>", 5f, ScreenMessageStyle.UPPER_CENTER);
            igniteFailResources = new ScreenMessage($"<color=orange>[{part.partInfo.title}]: insufficient resources to ignite!</color>", 5f, ScreenMessageStyle.UPPER_CENTER);
            ullageFail          = new ScreenMessage($"<color=orange>[{part.partInfo.title}]: vapor in feedlines, shut down!</color>", 5f, ScreenMessageStyle.UPPER_CENTER);

            Fields[nameof(thrustPercentage)].guiActive   = Fields[nameof(thrustPercentage)].guiActiveEditor = minFuelFlow != maxFuelFlow;
            Fields[nameof(thrustCurveDisplay)].guiActive = useThrustCurve;

            var group = Fields[nameof(propellantStatus)].group;

            Fields[nameof(engineTempString)].group = group;
            Fields[nameof(actualThrottle)].group   = group;
            Fields[nameof(realIsp)].group          = group;
            Fields[nameof(finalThrust)].group      = group;
            Fields[nameof(propellantReqMet)].group = group;
            Fields[nameof(fuelFlowGui)].group      = group;

            SetFields();
            started = true;
        }