StageParts DetermineStage(Part parent) { StageParts stage = new StageParts(); List <Part> toCheck = new List <Part>() { parent }; while (toCheck.Count > 0) //should instead search through the children, stopping when finding a decoupler, then switch to it's children { Part checking = toCheck[0]; toCheck.RemoveAt(0); stage.parts.Add(checking); foreach (Part part in checking.children) { //search for decouplers if (part.FindModulesImplementing <IStageSeparator>().Count() >= 1) { stage.decouplers.Add(part); } else { toCheck.Add(part); } } } return(stage); }
StageParts DetermineStage(Part parent) { StageParts stage = new StageParts(); List <Part> toCheck = new List <Part>() { parent }; while (toCheck.Count > 0) //should instead search through the children, stopping when finding a decoupler, then switch to it's children { Part checking = toCheck[0]; toCheck.RemoveAt(0); stage.parts.Add(checking); foreach (Part part in checking.children) { //search for decouplers if (part.Modules.Contains("ModuleDecouple") || part.Modules.Contains("ModuleAnchoredDecoupler")) { stage.decouplers.Add(part); } else { toCheck.Add(part); } } } return(stage); }
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; StageParts stage = new StageParts(); List <Part> RemainingDecouplers = null; // = new List<Part>() { parts[0] }; foreach (var p in parts) { if (p.parent == null) { RemainingDecouplers = new List <Part>() { p }; break; } } if (RemainingDecouplers == null) { Log.Error("No parent part found"); return; } while (RemainingDecouplers.Count > 0) { //determine stages from the decouplers Part parent = RemainingDecouplers[0]; RemainingDecouplers.RemoveAt(0); stage = DetermineStage(parent); current = new EditorStatItem { stageNumber = stageNum++, parts = stage.parts }; RemainingDecouplers.AddRange(stage.decouplers); //compute properties double dryMass = 0; double wetMass = 0; stage.parts.ForEach(p => { dryMass += p.mass; wetMass += p.mass + p.GetResourceMass(); }); current.dryMass = dryMass; current.mass = wetMass; current.chuteArea = StageRecovery.GetChuteArea(stage.parts); stages.Add(current); } ConsolidateStages(); Log.Info("[SR] Found " + stages.Count + " stages!"); }
StageParts DetermineStage(Part parent) { Log.Info("DetermineStage 1 parent: " + parent.partInfo.title); StageParts stage = new StageParts(); List <Part> toCheck = new List <Part>() { parent }; while (toCheck.Count > 0) //should instead search through the children, stopping when finding a decoupler, then switch to it's children { Part checking = toCheck[0]; toCheck.RemoveAt(0); bool isEnginePlate = false; if (Versioning.version_major == 1 && Versioning.version_minor >= 7) { isEnginePlate = CheckForEnginePlate(parent, checking); } stage.parts.Add(checking); for (int i = 0; i < checking.children.Count; i++) //foreach (Part part in checking.children) { Part part = checking.children[i]; //search for decouplers //if (part.Modules.Contains("ModuleDecouple") || part.Modules.Contains("ModuleAnchoredDecoupler")) if (Versioning.version_major == 1 && Versioning.version_minor >= 7 && isEnginePlate) { if (CheckForParentEnginePlate(part)) { stage.decouplers.Add(part); continue; } } // If this part is a decoupler, add it to the list if (part.FindModulesImplementing <IStageSeparator>().Count > 0) { stage.decouplers.Add(part); } else { toCheck.Add(part); } } } return(stage); }
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!"); }
public void BreakShipIntoStages() { //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; StageParts stage = new StageParts(); List <Part> RemainingDecouplers = null; // = new List<Part>() { parts[0] }; for (int i = 0; i < parts.Count; i++) { Part p = parts[i]; if (p.parent == null) { RemainingDecouplers = new List <Part>() { p }; break; } } if (RemainingDecouplers == null) { stages.Clear(); Log.Error("No parent part found"); return; } var stageList = new List <EditorStatItem>(); while (RemainingDecouplers.Count > 0) { //determine stages from the decouplers Part parent = RemainingDecouplers[0]; RemainingDecouplers.RemoveAt(0); stage = DetermineStage(parent); current = new EditorStatItem { stageNumber = stageNum++, parts = stage.parts }; #if DEBUG Log.Info("Parent part: " + parent.partInfo.title); foreach (var d in stage.decouplers) { Log.Info("Child decouplers: " + d.partInfo.title); } #endif RemainingDecouplers.AddRange(stage.decouplers); //compute properties double dryMass = 0; double wetMass = 0; stage.parts.ForEach(p => { dryMass += p.mass; wetMass += p.mass + p.GetResourceMass(); }); current.dryMass = dryMass; current.mass = wetMass; current.chuteArea = StageRecovery.GetChuteArea(stage.parts); stageList.Add(current); } ConsolidateStages(ref stageList); stages.Clear(); // wait until we have a full stages collection before we clear it stages.AddRange(stageList); Log.Info("[SR] Found " + stages.Count + " stages!"); }
StageParts DetermineStage(Part parent) { StageParts stage = new StageParts(); List<Part> toCheck = new List<Part>() { parent }; while (toCheck.Count > 0) //should instead search through the children, stopping when finding a decoupler, then switch to it's children { Part checking = toCheck[0]; toCheck.RemoveAt(0); stage.parts.Add(checking); foreach (Part part in checking.children) { //search for decouplers if (part.Modules.Contains("ModuleDecouple") || part.Modules.Contains("ModuleAnchoredDecoupler")) { stage.decouplers.Add(part); } else { toCheck.Add(part); } } } return stage; }
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!"); }