示例#1
0
        public void BreakShipIntoStages()
        {
            stages.Clear();
            //loop through the part tree and try to break it into stages
            List <Part>    parts          = EditorLogic.fetch.ship.parts;
            EditorStatItem current        = new EditorStatItem();
            int            stageNum       = 0;
            bool           realChuteInUse = false;

            StageParts  stage = new StageParts();
            List <Part> RemainingDecouplers = new List <Part>()
            {
                parts[0]
            };

            while (RemainingDecouplers.Count > 0)
            {
                //determine stages from the decouplers
                Part parent = RemainingDecouplers[0];
                RemainingDecouplers.RemoveAt(0);
                stage               = DetermineStage(parent);
                current             = new EditorStatItem();
                current.stageNumber = stageNum++;
                current.parts       = stage.parts;
                RemainingDecouplers.AddRange(stage.decouplers);

                //compute properties
                foreach (Part part in stage.parts)
                {
                    current.dryMass += part.mass;
                    current.mass    += part.mass + part.GetResourceMass();

                    double pChutes = 0;
                    if (part.Modules.Contains("RealChuteModule"))
                    {
                        PartModule realChute = part.Modules["RealChuteModule"];
                        ConfigNode rcNode    = new ConfigNode();
                        realChute.Save(rcNode);

                        //This is where the Reflection starts. We need to access the material library that RealChute has, so we first grab it's Type
                        Type matLibraryType = AssemblyLoader.loadedAssemblies
                                              .SelectMany(a => a.assembly.GetExportedTypes())
                                              .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary.MaterialsLibrary");


                        //We make a list of ConfigNodes containing the parachutes (usually 1, but now there can be any number of them)
                        //We get that from the PPMS
                        ConfigNode[] parachutes = rcNode.GetNodes("PARACHUTE");
                        //We then act on each individual parachute in the module
                        foreach (ConfigNode chute in parachutes)
                        {
                            //First off, the diameter of the parachute. From that we can (later) determine the Vt, assuming a circular chute
                            float diameter = float.Parse(chute.GetValue("deployedDiameter"));
                            //The name of the material the chute is made of. We need this to get the actual material object and then the drag coefficient
                            string mat = chute.GetValue("material");
                            //This grabs the method that RealChute uses to get the material. We will invoke that with the name of the material from before.
                            System.Reflection.MethodInfo matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { mat.GetType() });
                            //In order to invoke the method, we need to grab the active instance of the material library
                            object MatLibraryInstance = matLibraryType.GetProperty("Instance").GetValue(null, null);
                            //With the library instance we can invoke the GetMaterial method (passing the name of the material as a parameter) to receive an object that is the material
                            object materialObject = matMethod.Invoke(MatLibraryInstance, new object[] { mat });
                            //With that material object we can extract the dragCoefficient using the helper function above.
                            float dragC = (float)StageRecovery.GetMemberInfoValue(materialObject.GetType().GetMember("DragCoefficient")[0], materialObject);
                            //Now we calculate the RCParameter. Simple addition of this doesn't result in perfect results for Vt with parachutes with different diameter or drag coefficients
                            //But it works perfectly for mutiple identical parachutes (the normal case)
                            pChutes += dragC * (float)Math.Pow(diameter, 2);
                        }
                        realChuteInUse = true;
                    }
                    else if (part.Modules.Contains("RealChuteFAR")) //RealChute Lite for FAR
                    {
                        PartModule realChute = part.Modules["RealChuteFAR"];
                        float      diameter  = (float)realChute.Fields.GetValue("deployedDiameter");
                        // = float.Parse(realChute.moduleValues.GetValue("deployedDiameter"));
                        float dragC = 1.0f; //float.Parse(realChute.moduleValues.GetValue("staticCd"));
                        pChutes += dragC * (float)Math.Pow(diameter, 2);

                        realChuteInUse = true;
                    }
                    else if (!realChuteInUse && part.Modules.Contains("ModuleParachute"))
                    {
                        double scale = 1.0;
                        //check for Tweakscale and modify the area appropriately
                        if (part.Modules.Contains("TweakScale"))
                        {
                            PartModule tweakScale = part.Modules["TweakScale"];
                            double     currentScale = 100, defaultScale = 100;
                            double.TryParse(tweakScale.Fields.GetValue("currentScale").ToString(), out currentScale);
                            double.TryParse(tweakScale.Fields.GetValue("defaultScale").ToString(), out defaultScale);
                            scale = currentScale / defaultScale;
                        }

                        ModuleParachute mp = (ModuleParachute)part.Modules["ModuleParachute"];
                        //dragCoeff += part.mass * mp.fullyDeployedDrag;
                        pChutes += mp.areaDeployed * Math.Pow(scale, 2);
                    }

                    current.chuteArea += pChutes;
                }

                stages.Add(current);
            }

            ConsolidateStages();
            Debug.Log("[SR] Found " + stages.Count + " stages!");
        }
示例#2
0
        public static double GetChuteArea(List <Part> parts)
        {
            double RCParameter    = 0;
            bool   realChuteInUse = false;

            try
            {
                foreach (Part p in parts)
                {
                    //Make a list of all the Module Names for easy checking later. This can be avoided, but is convenient.
                    List <string> ModuleNames = new List <string>();
                    foreach (PartModule pm in p.Modules)
                    {
                        ModuleNames.Add(pm.moduleName);
                    }

                    if (ModuleNames.Contains("RealChuteModule"))
                    {
                        if (!realChuteInUse)
                        {
                            RCParameter = 0;
                        }
                        //First off, get the PPMS since we'll need that
                        PartModule realChute = p.Modules["RealChuteModule"];
                        //Assuming that's not somehow null, then we continue
                        if (realChute != null) //Some of this was adopted from DebRefund, as Vendan's method of handling multiple parachutes is better than what I had.
                        {
                            //We make a list of ConfigNodes containing the parachutes (usually 1, but now there can be any number of them)
                            //We get that from the PPMS
                            ConfigNode rcNode = new ConfigNode();
                            realChute.Save(rcNode);

                            //It's existence means that RealChute is installed and in use on the craft (you could have it installed and use stock chutes, so we only check if it's on the craft)
                            realChuteInUse = true;

                            RCParameter += ProcessRealchute(rcNode);
                        }
                    }
                    else if (ModuleNames.Contains("RealChuteFAR")) //RealChute Lite for FAR
                    {
                        if (!realChuteInUse)
                        {
                            RCParameter = 0;
                        }

                        PartModule realChute = p.Modules["RealChuteFAR"];
                        float      diameter  = 0.0F; //realChute.moduleValues.GetValue("deployedDiameter")

                        if (realChute != null)
                        {
                            try
                            {
                                diameter = realChute.Fields.GetValue <float>("deployedDiameter");
                                Log.Info($"[SR] Diameter is {diameter}.");
                            }
                            catch (Exception e)
                            {
                                Debug.LogError("[SR] Exception while finding deployedDiameter for RealChuteFAR module on module.");
                                Debug.LogException(e);
                            }
                        }
                        else
                        {
                            Log.Info("[SR] moduleRef is null, attempting workaround to find diameter.");
                            object dDefault = p.partInfo.partPrefab.Modules["RealChuteFAR"]?.Fields?.GetValue("deployedDiameter"); //requires C# 6
                            if (dDefault != null)
                            {
                                diameter = Convert.ToSingle(dDefault);
                                Log.Info($"[SR] Workaround gave a diameter of {diameter}.");
                            }
                            else
                            {
                                Log.Info("[SR] Couldn't get default value, setting to 0 and calling it a day.");
                                diameter = 0.0F;
                            }
                        }
                        float dragC = 1.0f; //float.Parse(realChute.moduleValues.GetValue("staticCd"));
                        RCParameter += (dragC * Mathf.Pow(diameter, 2) * Math.PI / 4.0);

                        realChuteInUse = true;
                    }
                    else if (!realChuteInUse && ModuleNames.Contains("ModuleParachute"))
                    {
                        //Credit to m4v and RCSBuildAid: https://github.com/m4v/RCSBuildAid/blob/master/Plugin/CoDMarker.cs
                        Part         part      = p ?? p.partInfo.partPrefab; //the part, or the part prefab
                        DragCubeList dragCubes = part.DragCubes;
                        dragCubes.SetCubeWeight("DEPLOYED", 1);
                        dragCubes.SetCubeWeight("SEMIDEPLOYED", 0);
                        dragCubes.SetCubeWeight("PACKED", 0);
                        dragCubes.SetOcclusionMultiplier(0);
                        Quaternion rotation = Quaternion.LookRotation(Vector3d.up);
                        try
                        {
                            rotation = Quaternion.LookRotation(part.partTransform?.InverseTransformDirection(Vector3d.up) ?? Vector3d.up);
                        }
                        catch (Exception e)
                        {
                            Debug.LogException(e);
                        }
                        dragCubes.SetDragVectorRotation(rotation);
                    }
                    if (!realChuteInUse)
                    {
                        Part         part      = p ?? p.partInfo.partPrefab; //the part reference, or the part prefab
                        DragCubeList dragCubes = part.DragCubes;
                        dragCubes.ForceUpdate(false, true);
                        dragCubes.SetDragWeights();
                        dragCubes.SetPartOcclusion();

                        Vector3 dir = Vector3d.up;
                        try
                        {
                            dir = -part.partTransform?.InverseTransformDirection(Vector3d.down) ?? Vector3d.up;
                        }
                        catch (Exception e)
                        {
                            //Debug.LogException(e);
                            Log.Info("[SR] The expected excpetion is still present. " + e.Message);
                        }
                        dragCubes.SetDrag(dir, 0.03f); //mach 0.03, or about 10m/s

                        double dragCoeff = dragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier;

                        RCParameter += (dragCoeff * PhysicsGlobals.DragMultiplier);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[SR] Error occured while trying to determine total chute area.");
                Debug.LogException(e);
            }
            return(RCParameter);
        }