示例#1
0
        //return the mass of the simulated FuelNode. This is not the same as the mass of the Part,
        //because the simulated node may have lost resources, and thus mass, during the simulation.
        public float Mass(int simStage)
        {
            //print("\n(" + simStage + ") " + partName.PadRight(25) + " dryMass " + dryMass.ToString("F3")
            //          + " ResMass " + (resources.Keys.Sum(id => resources[id] * MuUtils.ResourceDensity(id))).ToString("F3")
            //          + " Fairing Mass " + (inverseStage < simStage ? fairingMass : 0).ToString("F3")
            //          + " (" + fairingMass.ToString("F3") + ")"
            //          + " ModuleMass " + moduleMass.ToString("F3")
            //          );

            return(dryMass + resources.Keys.Sum(id => resources[id] * MuUtils.ResourceDensity(id)) +
                   (inverseStage < simStage ? fairingMass : 0));
        }
示例#2
0
        //return the mass of the simulated FuelNode. This is not the same as the mass of the Part,
        //because the simulated node may have lost resources, and thus mass, during the simulation.
        public double Mass(int simStage)
        {
            //print("\n(" + simStage + ") " + partName.PadRight(25) + " dryMass " + dryMass.ToString("F3")
            //          + " ResMass " + (resources.Keys.Sum(id => resources[id] * MuUtils.ResourceDensity(id))).ToString("F3")
            //          + " Fairing Mass " + (inverseStage < simStage ? fairingMass : 0).ToString("F3")
            //          + " (" + fairingMass.ToString("F3") + ")"
            //          + " ModuleMass " + moduleMass.ToString("F3")
            //          );

            //return dryMass + resources.Keys.Sum(id => resources[id] * MuUtils.ResourceDensity(id)) +
            double resMass = resources.KeysList.Slinq().Select((r, rs) => rs[r] * MuUtils.ResourceDensity(r), resources).Sum();

            return(dryMass + resMass +
                   (inverseStage < simStage ? modulesUnstagedMass : modulesStagedMass));
        }
示例#3
0
        public float moduleMass;           // for debugging

        public FuelNode(Part part, bool dVLinearThrust)
        {
            if (!part.IsLaunchClamp())
            {
                //print(part.partInfo.name.PadRight(25) + " " + part.mass.ToString("F4") + " " + part.GetPhysicslessChildMass().ToString("F4") + " " + part.GetModuleMass(part.partInfo.partPrefab.mass).ToString("F4"));
                dryMass = part.mass; // Intentionally ignore the physic flag.

                moduleMass = part.GetModuleMass(part.partInfo.partPrefab.mass);
                if (part.HasModule <ModuleProceduralFairing>())
                {
                    fairingMass = moduleMass;
                }
            }

            inverseStage = part.inverseStage;
            partName     = part.partInfo.name;

            //note which resources this part has stored
            for (int i = 0; i < part.Resources.Count; i++)
            {
                PartResource r = part.Resources[i];
                if (r.info.density > 0 && r.info.name != "IntakeAir")
                {
                    if (r.flowState)
                    {
                        resources[r.info.id] = (float)r.amount;
                    }
                    else
                    {
                        dryMass += (float)(r.amount * r.info.density); // disabled resources are just dead weight
                    }
                }
            }

            // TODO : handle the multiple active ModuleEngine case ( SXT engines with integrated vernier )

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

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

                    isEngine = true;

                    g = engine.g;

                    // If we take into account the engine rotation
                    if (dVLinearThrust)
                    {
                        Vector3 thrust = Vector3d.zero;
                        for (int i = 0; i < engine.thrustTransforms.Count; i++)
                        {
                            thrust -= engine.thrustTransforms[i].forward / engine.thrustTransforms.Count;
                        }

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

                    thrustPercentage = engine.thrustPercentage;

                    minFuelFlow = engine.minFuelFlow;
                    maxFuelFlow = engine.maxFuelFlow;

                    atmosphereCurve = new FloatCurve(engine.atmosphereCurve.Curve.keys);
                    atmChangeFlow   = engine.atmChangeFlow;
                    useAtmCurve     = engine.useAtmCurve;
                    if (useAtmCurve)
                    {
                        atmCurve = new FloatCurve(engine.atmCurve.Curve.keys);
                    }
                    useVelCurve = engine.useVelCurve;
                    if (useAtmCurve)
                    {
                        velCurve = new FloatCurve(engine.velCurve.Curve.keys);
                    }

                    propellantSumRatioTimesDensity = engine.propellants.Where(prop => !prop.ignoreForIsp).Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id));
                    propellantRatios = engine.propellants.Where(prop => MuUtils.ResourceDensity(prop.id) > 0 && !prop.ignoreForIsp).ToDictionary(prop => prop.id, prop => prop.ratio);
                }
            }
        }
示例#4
0
        public string partName;       //for debugging

        public FuelNode(Part part, bool dVLinearThrust)
        {
            if (part.IsPhysicallySignificant())
            {
                dryMass = part.mass;
            }

            inverseStage = part.inverseStage;
            partName     = part.partInfo.name;

            //note which resources this part has stored
            foreach (PartResource r in part.Resources)
            {
                if (r.info.density > 0 && r.name != "IntakeAir")
                {
                    if (r.flowState)
                    {
                        resources[r.info.id] = (float)r.amount;
                    }
                    else
                    {
                        dryMass += (float)(r.amount * r.info.density);  // disabled resources are just dead weight
                    }
                }
            }

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

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

                    isEngine = true;

                    g = engine.g;

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

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

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

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

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


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

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

                    isEngine = true;

                    g = enginefx.g;

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

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

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

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

                    propellantSumRatioTimesDensity = enginefx.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id));
                    propellantRatios = enginefx.propellants.Where(prop => PartResourceLibrary.Instance.GetDefinition(prop.id).density > 0 && prop.name != "IntakeAir").ToDictionary(prop => prop.id, prop => prop.ratio);
                }
            }
        }
示例#5
0
        public string partName;          //for debugging

        public FuelNode(Part part, bool dVLinearThrust)
        {
            if (part.IsPhysicallySignificant())
            {
                dryMass = part.mass;
            }

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

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

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

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

                    isEngine = true;

                    g = engine.g;

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

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

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

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

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


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

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

                    isEngine = true;

                    g = enginefx.g;

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

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

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

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

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



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

            while (true)
            {
                if (p.IsDecoupler() || p.IsLaunchClamp())
                {
                    if (p.inverseStage > decoupledInStage)
                    {
                        decoupledInStage = p.inverseStage;
                    }
                }
                if (p.parent == null)
                {
                    break;
                }
                else
                {
                    p = p.parent;
                }
            }
        }
示例#6
0
        public string partName;       //for debugging

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

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

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

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

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

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

                    isEngine = true;

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

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

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

            while (true)
            {
                if (p.IsDecoupler())
                {
                    if (p.inverseStage > decoupledInStage)
                    {
                        decoupledInStage = p.inverseStage;
                    }
                }
                if (p.parent == null)
                {
                    break;
                }
                else
                {
                    p = p.parent;
                }
            }
        }
示例#7
0
        private void Init(Part part, bool dVLinearThrust)
        {
            resources.Clear();
            resourceConsumptions.Clear();
            resourceDrains.Clear();
            freeResources.Clear();

            propellantRatios.Clear();
            propellantFlows.Clear();

            crossfeedSources.Clear();

            isEngine = false;

            dryMass           = 0;
            modulesStagedMass = 0;

            decoupledInStage = int.MinValue;

            modulesUnstagedMass = 0;
            if (!part.IsLaunchClamp())
            {
                dryMass = part.prefabMass; // Intentionally ignore the physic flag.

                modulesUnstagedMass = part.GetModuleMassNoAlloc((float)dryMass, ModifierStagingSituation.UNSTAGED);

                modulesStagedMass = part.GetModuleMassNoAlloc((float)dryMass, ModifierStagingSituation.STAGED);

                float currentModulesMass = part.GetModuleMassNoAlloc((float)dryMass, ModifierStagingSituation.CURRENT);

                // if it was manually staged
                if (currentModulesMass == modulesStagedMass)
                {
                    modulesUnstagedMass = modulesStagedMass;
                }

                //print(part.partInfo.name.PadRight(25) + " " + part.mass.ToString("F4") + " " + part.GetPhysicslessChildMass().ToString("F4") + " " + modulesUnstagedMass.ToString("F4") + " " + modulesStagedMass.ToString("F4"));
            }

            inverseStage = part.inverseStage;
            partName     = part.partInfo.name;

            resourceRequestRemainingThreshold = Math.Max(part.resourceRequestRemainingThreshold, DRAINED);
            resourcePriority = part.GetResourcePriority();

            //note which resources this part has stored
            for (int i = 0; i < part.Resources.Count; i++)
            {
                PartResource r = part.Resources[i];
                if (r.info.density > 0)
                {
                    if (r.flowState)
                    {
                        resources[r.info.id] = r.amount;
                    }
                    else
                    {
                        dryMass += (r.amount * r.info.density); // disabled resources are just dead weight
                    }
                }
                if (r.info.name == "IntakeAir")
                {
                    freeResources[PartResourceLibrary.Instance.GetDefinition("IntakeAir").id] = true;
                }
                // Those two are in the CRP.
                if (r.info.name == "IntakeLqd")
                {
                    freeResources[PartResourceLibrary.Instance.GetDefinition("IntakeLqd").id] = true;
                }
                if (r.info.name == "IntakeAtm")
                {
                    freeResources[PartResourceLibrary.Instance.GetDefinition("IntakeAtm").id] = true;
                }
            }

            // TODO : handle the multiple active ModuleEngine case ( SXT engines with integrated vernier )

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

            for (int i = 0; i < part.Modules.Count; i++)
            {
                PartModule    pm = part.Modules[i];
                ModuleEngines e  = pm as ModuleEngines;
                if (e != null && e.isEnabled)
                {
                    engine = e;
                    break;
                }
            }

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

                    isEngine = true;

                    g = engine.g;

                    // If we take into account the engine rotation
                    if (dVLinearThrust)
                    {
                        Vector3 thrust = Vector3.zero;
                        for (int i = 0; i < engine.thrustTransforms.Count; i++)
                        {
                            thrust -= engine.thrustTransforms[i].forward * engine.thrustTransformMultipliers[i];
                        }

                        Vector3d fwd = HighLogic.LoadedScene == GameScenes.EDITOR ? EditorLogic.VesselRotation * Vector3d.up : engine.part.vessel.GetTransform().up;
                        fwdThrustRatio = Vector3.Dot(fwd, thrust);
                    }
                    else
                    {
                        fwdThrustRatio = 1;
                    }

                    thrustPercentage = engine.thrustPercentage;

                    minFuelFlow = engine.minFuelFlow;
                    maxFuelFlow = engine.maxFuelFlow;

                    // Some brilliant engine mod seems to consider that FuelFlow is not something they should properly initialize
                    if (minFuelFlow == 0 && engine.minThrust > 0)
                    {
                        maxFuelFlow = engine.minThrust / (engine.atmosphereCurve.Evaluate(0f) * engine.g);
                    }
                    if (maxFuelFlow == 0 && engine.maxThrust > 0)
                    {
                        maxFuelFlow = engine.maxThrust / (engine.atmosphereCurve.Evaluate(0f) * engine.g);
                    }

                    atmosphereCurve = new FloatCurve(engine.atmosphereCurve.Curve.keys);
                    atmChangeFlow   = engine.atmChangeFlow;
                    useAtmCurve     = engine.useAtmCurve;
                    if (useAtmCurve)
                    {
                        atmCurve = new FloatCurve(engine.atmCurve.Curve.keys);
                    }
                    useVelCurve = engine.useVelCurve;
                    if (useVelCurve)
                    {
                        velCurve = new FloatCurve(engine.velCurve.Curve.keys);
                    }

                    propellantSumRatioTimesDensity = engine.propellants.Slinq().Where(prop => !prop.ignoreForIsp).Select(prop => prop.ratio * MuUtils.ResourceDensity(prop.id)).Sum();
                    propellantRatios.Clear();
                    propellantFlows.Clear();
                    var dics = new Tuple <KeyableDictionary <int, float>, KeyableDictionary <int, ResourceFlowMode> >(propellantRatios, propellantFlows);
                    engine.propellants.Slinq()
                    .Where(prop => MuUtils.ResourceDensity(prop.id) > 0 && !prop.ignoreForIsp)
                    .ForEach((p, dic) =>
                    {
                        dic.Item1.Add(p.id, p.ratio);
                        dic.Item2.Add(p.id, p.GetFlowMode());
                    }, dics);
                }
            }
        }
示例#8
0
        private void Init(Part part, bool dVLinearThrust)
        {
            resources.Clear();
            resourceConsumptions.Clear();
            resourceDrains.Clear();
            freeResources.Clear();

            propellantRatios.Clear();
            propellantFlows.Clear();

            fuelLineSources.Clear();
            stackNodeSources.Clear();
            surfaceMountSources.Clear();

            surfaceMountParent = null;
            isEngine           = false;

            dryMass     = 0;
            fairingMass = 0;

            moduleMass = 0;
            if (!part.IsLaunchClamp())
            {
                //print(part.partInfo.name.PadRight(25) + " " + part.mass.ToString("F4") + " " + part.GetPhysicslessChildMass().ToString("F4") + " " + part.GetModuleMass(part.partInfo.partPrefab.mass).ToString("F4"));
                dryMass = part.mass; // Intentionally ignore the physic flag.

                moduleMass = part.GetModuleMass(part.partInfo.partPrefab != null ? part.partInfo.partPrefab.mass : dryMass);
                if (part.HasModule <ModuleProceduralFairing>())
                {
                    fairingMass = moduleMass;
                }
            }

            inverseStage = part.inverseStage;
            partName     = part.partInfo.name;

            //note which resources this part has stored
            for (int i = 0; i < part.Resources.Count; i++)
            {
                PartResource r = part.Resources[i];
                if (r.info.density > 0)
                {
                    if (r.flowState)
                    {
                        resources[r.info.id] = (float)r.amount;
                    }
                    else
                    {
                        dryMass += (float)(r.amount * r.info.density); // disabled resources are just dead weight
                    }
                }
                if (r.info.name == "IntakeAir")
                {
                    freeResources[PartResourceLibrary.Instance.GetDefinition("IntakeAir").id] = true;
                }
                // Those two are in the CRP.
                if (r.info.name == "IntakeLqd")
                {
                    freeResources[PartResourceLibrary.Instance.GetDefinition("IntakeLqd").id] = true;
                }
                if (r.info.name == "IntakeAtm")
                {
                    freeResources[PartResourceLibrary.Instance.GetDefinition("IntakeAtm").id] = true;
                }
            }

            // TODO : handle the multiple active ModuleEngine case ( SXT engines with integrated vernier )

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

            for (int i = 0; i < part.Modules.Count; i++)
            {
                PartModule    pm = part.Modules[i];
                ModuleEngines e  = pm as ModuleEngines;
                if (e != null && e.isEnabled)
                {
                    engine = e;
                    break;
                }
            }

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

                    isEngine = true;

                    g = engine.g;

                    // If we take into account the engine rotation
                    if (dVLinearThrust)
                    {
                        Vector3 thrust = Vector3d.zero;
                        for (int i = 0; i < engine.thrustTransforms.Count; i++)
                        {
                            thrust -= engine.thrustTransforms[i].forward / engine.thrustTransforms.Count;
                        }

                        Vector3d fwd = HighLogic.LoadedScene == GameScenes.EDITOR ? EditorLogic.VesselRotation * Vector3d.up : engine.part.vessel.GetTransform().up;
                        fwdThrustRatio = Vector3.Dot(fwd, thrust);
                    }
                    else
                    {
                        fwdThrustRatio = 1;
                    }

                    thrustPercentage = engine.thrustPercentage;

                    minFuelFlow = engine.minFuelFlow;
                    maxFuelFlow = engine.maxFuelFlow;

                    atmosphereCurve = new FloatCurve(engine.atmosphereCurve.Curve.keys);
                    atmChangeFlow   = engine.atmChangeFlow;
                    useAtmCurve     = engine.useAtmCurve;
                    if (useAtmCurve)
                    {
                        atmCurve = new FloatCurve(engine.atmCurve.Curve.keys);
                    }
                    useVelCurve = engine.useVelCurve;
                    if (useVelCurve)
                    {
                        velCurve = new FloatCurve(engine.velCurve.Curve.keys);
                    }

                    propellantSumRatioTimesDensity = engine.propellants.Slinq().Where(prop => !prop.ignoreForIsp).Select(prop => prop.ratio * MuUtils.ResourceDensity(prop.id)).Sum();
                    propellantRatios.Clear();
                    propellantFlows.Clear();
                    var dics = new Tuple <KeyableDictionary <int, float>, KeyableDictionary <int, ResourceFlowMode> >(propellantRatios, propellantFlows);
                    engine.propellants.Slinq()
                    .Where(prop => MuUtils.ResourceDensity(prop.id) > 0 && !prop.ignoreForIsp)
                    .ForEach((p, dic) =>
                    {
                        dic._1.Add(p.id, p.ratio);
                        dic._2.Add(p.id, p.GetFlowMode());
                    }, dics);
                }
            }
        }