コード例 #1
0
ファイル: KerbQuake.cs プロジェクト: darchambault/KerbQuake
        // Used to find when decouplers fire
        public void onVesselStageSeparate(EventReport report)
        {
            //Debug.Log("handling separation");

            Part part = report.origin;

            if (part.vessel.vesselType == VesselType.Debris)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleDecouple"))
                    {
                        ModuleDecouple md = module as ModuleDecouple;
                        ejectionForceTotal += md.ejectionForce;
                    }
                    else if (module.moduleName.Contains("ModuleAnchoredDecoupler"))
                    {
                        ModuleAnchoredDecoupler md = module as ModuleAnchoredDecoupler;
                        ejectionForceTotal += md.ejectionForce;
                    }

                    ejectionForceTotal = Mathf.Clamp(ejectionForceTotal, 0, maxDecoupleForce);
                }
            }
        }
コード例 #2
0
        public override void OnFixedUpdate()
        {
            ModuleAnchoredDecoupler DecouplerModule = (ModuleAnchoredDecoupler)part.Modules.GetModule(DecouplerModuleIndex);

            if (false == DecouplerModule.isDecoupled)
            {
                return;
            }

            // Debug.Log("MADFix: OnFixedUpdate, State Timer = " + StateTimer);

            if (0 == StateTimer)
            {
                part.vessel.angularMomentum.Zero();
                part.vessel.angularVelocity.Zero();
                part.rigidbody.angularVelocity.Zero();
            }
            else if (1 == StateTimer) // Waits for struts and fuel lines to all disconnect
            {
                part.rigidbody.AddRelativeForce(Vector3d.left * EjectionForce, ForceMode.Force);
                Debug.Log("ModuleAnchordDecouplerFix: Fix Applied. Force = " + EjectionForce);
            }
            else if (2 == StateTimer) // Waits for the force to disappate before deleting
            {
                part.RemoveModule(this);
            }
            StateTimer++;
        }
コード例 #3
0
        public static bool IsUnfiredDecoupler(this Part p)
        {
            for (int i = 0; i < p.Modules.Count; i++)
            {
                PartModule     m         = p.Modules[i];
                ModuleDecouple mDecouple = m as ModuleDecouple;
                if (mDecouple != null)
                {
                    if (!mDecouple.isDecoupled)
                    {
                        return(true);
                    }
                    break;
                }

                ModuleAnchoredDecoupler mAnchoredDecoupler = m as ModuleAnchoredDecoupler;
                if (mAnchoredDecoupler != null)
                {
                    if (!mAnchoredDecoupler.isDecoupled)
                    {
                        return(true);
                    }
                    break;
                }

                if (m.ClassName == "ProceduralFairingDecoupler")
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #4
0
ファイル: PartExtensions.cs プロジェクト: vvektr/MechJeb2
        public static bool IsUnfiredDecoupler(this Part p)
        {
            foreach (PartModule m in p.Modules)
            {
                ModuleDecouple mDecouple = m as ModuleDecouple;
                if (mDecouple != null)
                {
                    if (!mDecouple.isDecoupled)
                    {
                        return(true);
                    }
                    break;
                }

                ModuleAnchoredDecoupler mAnchoredDecoupler = m as ModuleAnchoredDecoupler;
                if (mAnchoredDecoupler != null)
                {
                    if (!mAnchoredDecoupler.isDecoupled)
                    {
                        return(true);
                    }
                    break;
                }
            }
            return(false);
        }
コード例 #5
0
        public void OnDestroy()
        {
            // Debug.LogWarning("MADFix: Destroyed.");

            ModuleAnchoredDecoupler DecouplerModule = (ModuleAnchoredDecoupler)part.Modules.GetModule(DecouplerModuleIndex);

            DecouplerModule.ejectionForce = EjectionForce;
        }
コード例 #6
0
 internal Decoupler (Part part)
 {
     this.part = part;
     decoupler = part.InternalPart.Module<ModuleDecouple> ();
     anchoredDecoupler = part.InternalPart.Module<ModuleAnchoredDecoupler> ();
     if (decoupler == null && anchoredDecoupler == null)
         throw new ArgumentException ("Part does not have a ModuleDecouple or ModuleAnchoredDecouple PartModule");
 }
コード例 #7
0
        public void Start()
        {
            Debug.Log("MADFix: Start() against Module #" + DecouplerModuleIndex);

            ModuleAnchoredDecoupler DecouplerModule = (ModuleAnchoredDecoupler)part.Modules.GetModule(DecouplerModuleIndex);

            EjectionForce = DecouplerModule.ejectionForce;
            DecouplerModule.ejectionForce = 0;
        }
コード例 #8
0
 internal Decoupler(Part part)
 {
     this.part         = part;
     decoupler         = part.InternalPart.Module <ModuleDecouple> ();
     anchoredDecoupler = part.InternalPart.Module <ModuleAnchoredDecoupler> ();
     if (decoupler == null && anchoredDecoupler == null)
     {
         throw new ArgumentException("Part is not a decoupler");
     }
 }
コード例 #9
0
            private void SetModuleAnchoredDecoupler()
            {
                ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler;

                if (decoupler == null)
                {
                    return;
                }

                EjectionForce = decoupler.ejectionForce;
            }
コード例 #10
0
ファイル: PartExtensions.cs プロジェクト: Fitiales/SmartTank
            private void SetModuleAnchoredDecoupler()
            {
                ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler;

                if (decoupler == null)
                {
                    return;
                }

                EjectionForce  = decoupler.ejectionForce;
                IsStageEnabled = decoupler.stagingEnabled;
            }
コード例 #11
0
        public override void OnUpdate()
        {
            ModuleAnchoredDecoupler DecouplerModule = (ModuleAnchoredDecoupler)part.Modules.GetModule(DecouplerModuleIndex);

            if (false == DecouplerModule.isDecoupled)
            {
                return;
            }
            part.vessel.angularMomentum.Zero();
            part.vessel.angularVelocity.Zero();
            part.rigidbody.angularVelocity.Zero();
        }
コード例 #12
0
        /// <summary>
        ///     Gets whether the part is a decoupler.
        /// </summary>
        static public bool IsDecoupler(this Part part)
        {
            //bool b = HasModule<ModuleDecouple>(part);
            ModuleDecouple          md  = part.FindModuleImplementing <ModuleDecouple>();
            ModuleAnchoredDecoupler mad = part.FindModuleImplementing <ModuleAnchoredDecoupler>();

            if (mad != null && !mad.isDecoupled)
            {
                return(true);
            }

            if (md != null && !md.isDecoupled)
            {
                return(true);
            }
            return(false);
        }
コード例 #13
0
ファイル: PartExtensions.cs プロジェクト: brandi91/MechJeb2
        public static bool IsUnfiredDecoupler(this Part p)
        {
            for (int i = 0; i < p.Modules.Count; i++)
            {
                PartModule     m         = p.Modules[i];
                ModuleDecouple mDecouple = m as ModuleDecouple;
                if (mDecouple != null)
                {
                    if (!mDecouple.isDecoupled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }

                ModuleAnchoredDecoupler mAnchoredDecoupler = m as ModuleAnchoredDecoupler;
                if (mAnchoredDecoupler != null)
                {
                    if (!mAnchoredDecoupler.isDecoupled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }

                ModuleDockingNode mDockingNode = m as ModuleDockingNode;
                if (mDockingNode != null)
                {
                    if (mDockingNode.staged && mDockingNode.stagingEnabled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }

                if (VesselState.isLoadedProceduralFairing && m.moduleName == "ProceduralFairingDecoupler")
                {
                    if (!m.Fields["decoupled"].GetValue <bool>(m) && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }
            }
            return(false);
        }
コード例 #14
0
        /// <summary>
        /// Called when the part is started by Unity.
        /// </summary>
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            if (HighLogic.LoadedSceneIsFlight)
            {
                GameEvents.onStageActivate.Add(new EventData<int>.OnEvent(DetermineFailure));

                decoupler = part.Modules.OfType<ModuleDecouple>().FirstOrDefault<ModuleDecouple>();

                if (!decoupler)
                {
                    aDecoupler = part.Modules.OfType<ModuleAnchoredDecoupler>().FirstOrDefault<ModuleAnchoredDecoupler>();
                }

                if (decoupler)
                {
                    if (failure != "")
                    {
                        decoupler.isDecoupled = true;
                    }
                    decoupler.Events["Decouple"].active = false;
                    decoupler.Actions["DecoupleAction"].active = false;
                }
                else if (aDecoupler)
                {
                    if (failure != "")
                    {
                        aDecoupler.isDecoupled = true;
                    }
                    aDecoupler.Events["Decouple"].active = false;
                    aDecoupler.Actions["DecoupleAction"].active = false;
                }
                else
                {
                    Logger.DebugError("Part \"" + part.partName + "\" contains neither a decouple or anchored decoupler module!");
                    return;
                }

                Fields["reliability"].guiActive = false;
            }
        }
コード例 #15
0
ファイル: PartExtensions.cs プロジェクト: vinix38/MechJeb2
        public static bool IsUnfiredDecoupler(this Part p, out Part decoupledPart)
        {
            for (int i = 0; i < p.Modules.Count; i++)
            {
                PartModule     m         = p.Modules[i];
                ModuleDecouple mDecouple = m as ModuleDecouple;
                if (mDecouple != null)
                {
                    if (!mDecouple.isDecoupled && mDecouple.stagingEnabled && p.stagingOn)
                    {
                        decoupledPart = mDecouple.ExplosiveNode.attachedPart;
                        if (decoupledPart == p.parent)
                        {
                            decoupledPart = p;
                        }
                        return(true);
                    }
                    break;
                }

                ModuleAnchoredDecoupler mAnchoredDecoupler = m as ModuleAnchoredDecoupler;
                if (mAnchoredDecoupler != null)
                {
                    if (!mAnchoredDecoupler.isDecoupled && mAnchoredDecoupler.stagingEnabled && p.stagingOn)
                    {
                        decoupledPart = mAnchoredDecoupler.ExplosiveNode.attachedPart;
                        if (decoupledPart == p.parent)
                        {
                            decoupledPart = p;
                        }
                        return(true);
                    }
                    break;
                }

                ModuleDockingNode mDockingNode = m as ModuleDockingNode;
                if (mDockingNode != null)
                {
                    if (mDockingNode.staged && mDockingNode.stagingEnabled && p.stagingOn)
                    {
                        decoupledPart = mDockingNode.referenceNode.attachedPart;
                        if (decoupledPart == p.parent)
                        {
                            decoupledPart = p;
                        }
                        return(true);
                    }
                    break;
                }

                if (VesselState.isLoadedProceduralFairing && m.moduleName == "ProceduralFairingDecoupler")
                {
                    if (!m.Fields["decoupled"].GetValue <bool>(m) && p.stagingOn)
                    {
                        // ProceduralFairingDecoupler always decouple from their parents
                        decoupledPart = p;
                        return(true);
                    }
                    break;
                }
            }
            decoupledPart = null;
            return(false);
        }
コード例 #16
0
ファイル: PartSim.cs プロジェクト: yalov/KerbalEngineer
        private int DecoupledInStage(Part thePart)
        {
            int  stage    = -1;
            Part original = thePart;

            if (original.parent == null)
            {
                return(stage);                     //root part is always present. Fixes phantom stage if root is stageable.
            }
            List <Part> chain = new List <Part>(); //prolly dont need a list, just the previous part but whatever.

            while (thePart != null)
            {
                chain.Add(thePart);

                if (thePart.inverseStage > stage)
                {
                    ModuleDecouple          mdec  = thePart.GetModule <ModuleDecouple>();
                    ModuleDockingNode       mdock = thePart.GetModule <ModuleDockingNode>();
                    ModuleAnchoredDecoupler manch = thePart.GetModule <ModuleAnchoredDecoupler>();

                    if (mdec != null)
                    {
                        AttachNode att = thePart.FindAttachNode(mdec.explosiveNodeID);
                        if (mdec.isOmniDecoupler)
                        {
                            stage = thePart.inverseStage;
                        }
                        else
                        {
                            if (att != null)
                            {
                                if ((thePart.parent != null && att.attachedPart == thePart.parent) || chain.Contains(att.attachedPart))
                                {
                                    stage = thePart.inverseStage;
                                }
                            }
                            else
                            {
                                stage = thePart.inverseStage;
                            }
                        }
                    }

                    if (manch != null)                                                  //radial decouplers (ALSO REENTRY PODS BECAUSE REASONS!)
                    {
                        AttachNode att = thePart.FindAttachNode(manch.explosiveNodeID); // these stupid fuckers don't initialize in the Editor scene.
                        if (att != null)
                        {
                            if ((thePart.parent != null && att.attachedPart == thePart.parent) || chain.Contains(att.attachedPart))
                            {
                                stage = thePart.inverseStage;
                            }
                        }
                        else
                        {
                            stage = thePart.inverseStage;    //radial decouplers it seems the attach node ('surface') comes back null.
                        }
                    }

                    if (mdock != null)           //docking port
                    {
                        if (original == thePart) //checking self, never leaves.

                        {
                        }
                        else
                        {
                            stage = thePart.inverseStage;
                        }
                    }
                }

                thePart = thePart.parent;
            }

            return(stage);
        }
コード例 #17
0
        public void computeStages()
        {
#if DEBUG
            DateTime startTime = DateTime.Now;
#endif
            double elapsedTime = 0;
            while (state.availableNodes.Count() > 0)
            {
                if (advancedSimulation)
                {
                    state.m = state.availableNodes.Sum(p => p.Value.mass);
                    // Compute flow for active engines
                    foreach (EngineWrapper e in state.activeEngines)
                    {
                        e.evaluateFuelFlow(state.atmDensity, state.machNumber, state.throttle, false);
                    }
                }
                else
                {
                    // Compute flow for active engines, in vacuum
                    foreach (EngineWrapper e in state.activeEngines)
                    {
                        e.evaluateFuelFlow(1, 1, 1, false);
                    }
                }

                double step = Math.Max(state.availableNodes.Min(node => node.Value.getNextEvent()), 1E-100);

                // Quit if there is no other event
                if (step == Double.MaxValue && state.throttle > 0)
                {
                    break;
                }

                if (advancedSimulation)
                {
                    if (step > simulationStep)
                    {
                        step = Math.Max(simulationStep, (elapsedTime + step - stages.Last().activationTime) / 100);
                    }

                    if (state.throttle == 0)
                    {
                        step = simulationStep;
                    }

                    float  throttle   = state.throttle;
                    var    savedState = state;
                    DState dState     = RungeKutta(ref state, step);
                    while (Math.Abs(state.throttle - throttle) > 0.05 && step > 1e-3)
                    {
                        state  = savedState;
                        step  /= 2;
                        dState = RungeKutta(ref state, step);
                    }
                    Sample sample;
                    sample.time         = elapsedTime + step;
                    sample.velocity     = state.v_surf;
                    sample.altitude     = state.r - state.planet.Radius;
                    sample.mass         = state.m;
                    sample.acceleration = Math.Sqrt(dState.ax_nograv * dState.ax_nograv + dState.ay_nograv * dState.ay_nograv);
                    sample.throttle     = state.throttle;
                    if (samples.Count == 0 || samples.Last().time + simulationStep <= sample.time)
                    {
                        samples.Add(sample);
                    }
                }
                elapsedTime += step;

                // Burn the fuel !
                bool eventHappens = false;
                foreach (Node node in state.availableNodes.Values)
                {
                    eventHappens |= node.applyFuelConsumption(step);
                }

                if (!eventHappens)
                {
                    continue;
                }

                // Add all decouplers in a new stage
                StageDescription newStage = new StageDescription(elapsedTime);
                foreach (Node node in state.availableNodes.Values)
                {
                    ModuleDecouple          decoupler  = node.part.Modules.OfType <ModuleDecouple>().FirstOrDefault();
                    ModuleAnchoredDecoupler aDecoupler = node.part.Modules.OfType <ModuleAnchoredDecoupler>().FirstOrDefault();
                    if ((decoupler != null || aDecoupler != null) && !node.hasFuelInChildren(state.availableNodes))
                    {
                        newStage.stageParts.Add(node.part);
                    }
                }

                if (newStage.stageParts.Count > 0)
                {
                    stages.Add(newStage);
                    List <Part> activableChildren = new List <Part>();

                    // Remove all decoupled elements, fire sepratrons and parachutes
                    foreach (Part part in newStage.stageParts)
                    {
                        if (state.availableNodes.ContainsKey(part))
                        {
                            activableChildren.AddRange(state.availableNodes[part].getRelevantChildrenOnDecouple(state.availableNodes));
                            dropPartAndChildren(part);
                        }
                    }
                    newStage.stageParts.AddRange(activableChildren);
                }

                // Update available engines and fuel flow
                List <Part> activeEngines = state.updateEngines();

                if (newStage.stageParts.Count > 0)
                {
                    newStage.stageParts.AddRange(activeEngines);
                }
            }

            // Put fairings in a separate stage before decoupling
            List <StageDescription> newStages = new List <StageDescription>();
            for (int i = 0; i < stages.Count; i++)
            {
                var fairings    = stages[i].stageParts.Where(p => p.Modules.OfType <ModuleProceduralFairing>().Count() != 0);
                var notfairings = stages[i].stageParts.Where(p => p.Modules.OfType <ModuleProceduralFairing>().Count() == 0);

                if (fairings.Count() != 0)
                {
                    StageDescription fairingStage = new StageDescription(stages[i].activationTime);
                    fairingStage.stageParts.AddRange(fairings);
                    newStages.Add(fairingStage);
                }

                StageDescription notfairingStage = new StageDescription(stages[i].activationTime);
                notfairingStage.stageParts.AddRange(notfairings);
                newStages.Add(notfairingStage);
            }
            stages = newStages;

            // Put all remaining items (parachutes?) in a separate 0 stage
            foreach (var stage in stages)
            {
                foreach (var part in stage.stageParts)
                {
                    state.availableNodes.Remove(part);
                }
            }

            var stage0 = new StageDescription(elapsedTime);
            stage0.stageParts = state.availableNodes.Keys.Where(p => p.hasStagingIcon).ToList();
            if (stage0.stageParts.Count != 0)
            {
                stages.Add(stage0);
            }

            stages.Reverse();

            // This is ugly, but on KSP 1.1 I have not found anything better
            // We call this private method for each part from the root, twice and it works...
            System.Reflection.MethodInfo SortIcons = null;

            // In KSP 1.10, an extra parameter was added to SortIcons
            if (Versioning.version_major == 1 && Versioning.version_minor >= 10)
            {
                SortIcons = typeof(KSP.UI.Screens.StageManager).GetMethod("SortIcons",
                                                                          System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null,
                                                                          new Type[] { typeof(bool), typeof(Part), typeof(bool), typeof(bool) }, null);
            }
            else
            {
                SortIcons = typeof(KSP.UI.Screens.StageManager).GetMethod("SortIcons",
                                                                          System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null,
                                                                          new Type[] { typeof(bool), typeof(Part), typeof(bool) }, null);
            }
            var root = stages[0].stageParts[0];
            while (root.parent != null)
            {
                root = root.parent;
            }


            setStages(root, SortIcons);
            //            setStages(root, SortIcons);


#if DEBUG
            var compTime = DateTime.Now - startTime;
            Debug.Log("Staging computed in " + compTime.TotalMilliseconds + "ms");
            if (samples.Count() > 0)
            {
                string result = "time;altitude;velocity;acceleration;mass;throttle\n";
                foreach (var sample in samples)
                {
                    result += sample.time + ";" + sample.altitude + ";" + sample.velocity + ";" + sample.acceleration + ";" + sample.mass + ";" + sample.throttle + "\n";
                }
                Debug.Log(result);
            }
#endif
        }
コード例 #18
0
        public static bool IsUnfiredDecoupler(this Part p)
        {
            bool isFairing = false;

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

                ModuleDecouple mDecouple = m as ModuleDecouple;
                if (mDecouple != null)
                {
                    if (!mDecouple.isDecoupled && mDecouple.stagingEnabled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }

                ModuleAnchoredDecoupler mAnchoredDecoupler = m as ModuleAnchoredDecoupler;
                if (mAnchoredDecoupler != null)
                {
                    if (!mAnchoredDecoupler.isDecoupled && mAnchoredDecoupler.stagingEnabled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }

                ModuleDockingNode mDockingNode = m as ModuleDockingNode;
                if (mDockingNode != null)
                {
                    if (mDockingNode.staged && mDockingNode.stagingEnabled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }

                if (m is ModuleProceduralFairing)
                {
                    isFairing = true;
                }

                if (isFairing)
                {
                    if (VesselState.isLoadedFAR && m.stagingEnabled && p.stagingOn)
                    {
                        return(true);
                    }

                    else
                    if (m is ModuleCargoBay)
                    {
                        ModuleCargoBay fairing = m as ModuleCargoBay;
                        if (fairing.ClosedAndLocked() && m.stagingEnabled && p.stagingOn)
                        {
                            return(true);
                        }
                        break;
                    }
                }

                if (VesselState.isLoadedProceduralFairing && m.moduleName == "ProceduralFairingDecoupler")
                {
                    if (!m.Fields["decoupled"].GetValue <bool>(m) && m.stagingEnabled && p.stagingOn)
                    {
                        return(true);
                    }
                    break;
                }
            }
            return(false);
        }
コード例 #19
0
ファイル: PartSim.cs プロジェクト: zxzxn3/KerbalEngineer
        private int DecoupledInStage(Part thePart)
        {
            int  stage    = -1;
            Part original = thePart;

            while (thePart != null)
            {
                if (thePart.inverseStage > stage)
                {
                    ModuleDecouple          mdec  = thePart.GetModule <ModuleDecouple>();
                    ModuleDockingNode       mdock = thePart.GetModule <ModuleDockingNode>();
                    ModuleAnchoredDecoupler manch = thePart.GetModule <ModuleAnchoredDecoupler>();

                    if (mdec != null)
                    {
                        ModuleDynamicNodes mdyn = thePart.GetModule <ModuleDynamicNodes>();
                        if (mdyn != null)
                        {                                                                        //engine plate
                            if (original == thePart)
                            {                                                                    //checking self, make sure not upside down
                                if (thePart.FindAttachNodeByPart(thePart.parent).id == "bottom") //leaves with stage
                                {
                                    stage = thePart.inverseStage;
                                }
                            }
                            else if (original.parent != null && original.parent == thePart)
                            { //plate direct child.
                                if (thePart.FindAttachNodeByPart(original).id == "bottom")
                                {
                                    stage = thePart.inverseStage; //goodbye!
                                }
                            }
                            else
                            {
                                stage = thePart.inverseStage;   //decouple.
                            }
                        }
                        else
                        {                                                                                             //regular decoupler
                            if (original == thePart)
                            {                                                                                         //checking self
                                if (mdec.isOmniDecoupler || thePart.FindAttachNodeByPart(thePart.parent).id == "top") //leaves with stage
                                {
                                    stage = thePart.inverseStage;
                                }
                            }
                            else
                            {
                                stage = thePart.inverseStage;
                            }
                        }
                    }

                    if (manch != null) //radial decouple
                    {
                        if (original == thePart)
                        {                                                                 //checking self
                            if (thePart.FindAttachNodeByPart(thePart.parent).id == "top") //leaves with stage
                            {
                                stage = thePart.inverseStage;
                            }
                        }
                        else
                        {
                            stage = thePart.inverseStage;
                        }
                    }

                    if (mdock != null) //docking port
                    {
                        if (original == thePart)
                        {    //checking self, never leaves.
                        }
                        else
                        {
                            stage = thePart.inverseStage;
                        }
                    }
                }

                thePart = thePart.parent;
            }

            return(stage);
        }
コード例 #20
0
ファイル: DecouplerManager.cs プロジェクト: deimos790/DangIt
 /// <summary>
 /// Creates an DecouplerManager for a part.
 /// Allows unified control of a ModuleDecouple/ModulenchoredDecoupler.
 /// </summary>
 public DecouplerManager(Part p)
 {
     this.decoupler   = p.Modules.OfType <ModuleDecouple>().FirstOrDefault();
     this.aDecoupler  = p.Modules.OfType <ModuleAnchoredDecoupler>().FirstOrDefault();
     this.isDecoupler = this.decoupler != null;
 }
コード例 #21
0
        // Determine when this part will be decoupled given when its parent will be decoupled.
        // Then recurse to all of this part's children.
        public void AssignDecoupledInStage(Part p, Dictionary <Part, FuelNode> nodeLookup, int parentDecoupledInStage)
        {
            // Already processed
            if (decoupledInStage != int.MinValue)
            {
                return;
            }

            bool isDecoupler = false;

            decoupledInStage = parentDecoupledInStage;

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

                ModuleDecouple mDecouple = m as ModuleDecouple;
                if (mDecouple != null)
                {
                    if (!mDecouple.isDecoupled && mDecouple.stagingEnabled && p.stagingOn)
                    {
                        if (mDecouple.isOmniDecoupler)
                        {
                            isDecoupler = true;
                            // We are decoupling our parent
                            // The part and its children are not part of the ship when we decouple
                            decoupledInStage = p.inverseStage;

                            // The parent should already have its info assigned at this point
                            //nodeLookup[p.parent].AssignDecoupledInStage(p.parent, nodeLookup, p.inverseStage);

                            // The part children are decoupled when we decouple
                            foreach (Part child in p.children)
                            {
                                nodeLookup[child].AssignDecoupledInStage(child, nodeLookup, p.inverseStage);
                            }
                        }
                        else
                        {
                            AttachNode attach;
                            if (mDecouple.explosiveNodeID != "srf")
                            {
                                attach = p.FindAttachNode(mDecouple.explosiveNodeID);
                            }
                            else
                            {
                                attach = p.srfAttachNode;
                            }

                            if (attach != null && attach.attachedPart != null)
                            {
                                if (attach.attachedPart == p.parent)
                                {
                                    isDecoupler = true;
                                    // We are decoupling our parent
                                    // The part and its children are not part of the ship when we decouple
                                    decoupledInStage = p.inverseStage;
                                    //print("AssignDecoupledInStage ModuleDecouple          " + p.partInfo.name + "(" + p.inverseStage + ") decoupling " + attach.attachedPart + "(" + attach.attachedPart.inverseStage + "). parent " + decoupledInStage);

                                    // The parent should already have its info assigned at this point
                                    //nodeLookup[p.parent].AssignDecoupledInStage(p.parent, nodeLookup, p.inverseStage);
                                }
                                else
                                {
                                    isDecoupler = true;
                                    // We are still attached to our parent
                                    // The part and it's children are dropped when the parent is
                                    decoupledInStage = parentDecoupledInStage;

                                    //print("AssignDecoupledInStage ModuleDecouple          " + p.partInfo.name + "(" + p.inverseStage + ") decoupling " + attach.attachedPart + "(" + attach.attachedPart.inverseStage + "). not the parent " + decoupledInStage);
                                    // The part we decouple is dropped when we decouple
                                    nodeLookup[attach.attachedPart].AssignDecoupledInStage(attach.attachedPart, nodeLookup, p.inverseStage);
                                }
                            }
                        }
                        break; // Hopefully no one made part with multiple decoupler modules ?
                    }
                }

                ModuleAnchoredDecoupler mAnchoredDecoupler = m as ModuleAnchoredDecoupler;
                if (mAnchoredDecoupler != null)
                {
                    if (!mAnchoredDecoupler.isDecoupled && mAnchoredDecoupler.stagingEnabled && p.stagingOn)
                    {
                        AttachNode attach;
                        if (mAnchoredDecoupler.explosiveNodeID != "srf")
                        {
                            attach = p.FindAttachNode(mAnchoredDecoupler.explosiveNodeID);
                        }
                        else
                        {
                            attach = p.srfAttachNode;
                        }

                        if (attach != null && attach.attachedPart != null)
                        {
                            if (attach.attachedPart == p.parent)
                            {
                                isDecoupler = true;
                                // We are decoupling our parent
                                // The part and its children are not part of the ship when we decouple
                                decoupledInStage = p.inverseStage;
                                //print("AssignDecoupledInStage ModuleAnchoredDecoupler " + p.partInfo.name + "(" + p.inverseStage + ") decoupling " + attach.attachedPart + "(" + attach.attachedPart.inverseStage + "). parent " + decoupledInStage);

                                // The parent should already have its info assigned at this point
                                //nodeLookup[p.parent].AssignDecoupledInStage(p.parent, nodeLookup, p.inverseStage);
                            }
                            else
                            {
                                isDecoupler = true;
                                // We are still attached to our parent
                                // The part and it's children are dropped when the parent is
                                decoupledInStage = parentDecoupledInStage;

                                //print("AssignDecoupledInStage ModuleAnchoredDecoupler " + p.partInfo.name + "(" + p.inverseStage + ") decoupling " + attach.attachedPart + "(" + attach.attachedPart.inverseStage + "). not the parent " + decoupledInStage);
                                // The part we decouple is dropped when we decouple
                                nodeLookup[attach.attachedPart].AssignDecoupledInStage(attach.attachedPart, nodeLookup, p.inverseStage);
                            }
                        }
                        break;
                    }
                }

                ModuleDockingNode mDockingNode = m as ModuleDockingNode;
                if (mDockingNode != null)
                {
                    if (mDockingNode.staged && mDockingNode.stagingEnabled && p.stagingOn)
                    {
                        Part attachedPart = mDockingNode.referenceNode.attachedPart;
                        if (attachedPart != null)
                        {
                            if (attachedPart == p.parent)
                            {
                                isDecoupler = true;
                                // We are decoupling our parent
                                // The part and its children are not part of the ship when we decouple
                                decoupledInStage = p.inverseStage;

                                // The parent should already have its info assigned at this point
                                //nodeLookup[p.parent].AssignDecoupledInStage(p.parent, nodeLookup, p.inverseStage);
                            }
                            else
                            {
                                isDecoupler      = true;
                                decoupledInStage = parentDecoupledInStage;
                                //childDecoupledInStage = parentDecoupledInStage;
                                nodeLookup[attachedPart].AssignDecoupledInStage(attachedPart, nodeLookup, p.inverseStage);
                            }
                        }
                    }
                    break;
                }

                if (m.moduleName == "ProceduralFairingDecoupler")
                {
                    if (!m.Fields["decoupled"].GetValue <bool>(m) && m.stagingEnabled && p.stagingOn)
                    {
                        isDecoupler = true;
                        // We are decoupling our parent
                        // The part and its children are not part of the ship when we decouple
                        decoupledInStage = p.inverseStage;
                        break;
                    }
                }
            }

            if (p.IsLaunchClamp())
            {
                decoupledInStage = p.inverseStage > parentDecoupledInStage ? p.inverseStage : parentDecoupledInStage;
                //print("AssignDecoupledInStage D " + p.partInfo.name + " " + parentDecoupledInStage);
            }
            else if (!isDecoupler)
            {
                decoupledInStage = parentDecoupledInStage;
                //print("AssignDecoupledInStage                         " + p.partInfo.name + "(" + p.inverseStage + ")" + decoupledInStage);
            }

            isSepratron = isEngine && (inverseStage == decoupledInStage);

            for (int i = 0; i < p.children.Count; i++)
            {
                Part child = p.children[i];
                nodeLookup[child].AssignDecoupledInStage(child, nodeLookup, decoupledInStage);
            }
        }
コード例 #22
0
        public void computeStages()
        {
                        #if DEBUG
            DateTime startTime = DateTime.Now;
                        #endif
            double elapsedTime = 0;
            while (state.availableNodes.Count() > 0)
            {
                if (advancedSimulation)
                {
                    state.m = state.availableNodes.Sum(p => p.Value.mass);
                    // Compute flow for active engines
                    foreach (EngineWrapper e in state.activeEngines)
                    {
                        e.evaluateFuelFlow(state.atmDensity, state.machNumber, state.throttle, false);
                    }
                }
                else
                {
                    // Compute flow for active engines, in vacuum
                    foreach (EngineWrapper e in state.activeEngines)
                    {
                        e.evaluateFuelFlow(1, 1, 1, false);
                    }
                }

                double step = Math.Max(state.availableNodes.Min(node => node.Value.getNextEvent()), 1E-100);

                // Quit if there is no other event
                if (step == Double.MaxValue && state.throttle > 0)
                {
                    break;
                }

                if (advancedSimulation)
                {
                    if (step > simulationStep)
                    {
                        step = Math.Max(simulationStep, (elapsedTime + step - stages.Last().activationTime) / 100);
                    }

                    if (state.throttle == 0)
                    {
                        step = simulationStep;
                    }

                    float  throttle   = state.throttle;
                    var    savedState = state;
                    DState dState     = RungeKutta(ref state, step);
                    while (Math.Abs(state.throttle - throttle) > 0.05 && step > 1e-3)
                    {
                        state  = savedState;
                        step  /= 2;
                        dState = RungeKutta(ref state, step);
                    }
                    Sample sample;
                    sample.time         = elapsedTime + step;
                    sample.velocity     = state.v_surf;
                    sample.altitude     = state.r - state.planet.Radius;
                    sample.mass         = state.m;
                    sample.acceleration = Math.Sqrt(dState.ax_nograv * dState.ax_nograv + dState.ay_nograv * dState.ay_nograv);
                    sample.throttle     = state.throttle;
                    if (samples.Count == 0 || samples.Last().time + simulationStep <= sample.time)
                    {
                        samples.Add(sample);
                    }
                }
                elapsedTime += step;

                // Burn the fuel !
                bool eventHappens = false;
                foreach (Node node in state.availableNodes.Values)
                {
                    eventHappens |= node.applyFuelConsumption(step);
                }

                if (!eventHappens)
                {
                    continue;
                }

                // Add all decouplers in a new stage
                StageDescription dpStage = new StageDescription(elapsedTime);
                foreach (Node node in state.availableNodes.Values)
                {
                    ModuleDecouple          decoupler  = node.part.Modules.OfType <ModuleDecouple>().FirstOrDefault();
                    ModuleAnchoredDecoupler aDecoupler = node.part.Modules.OfType <ModuleAnchoredDecoupler>().FirstOrDefault();
                    if ((decoupler != null || aDecoupler != null) && !node.hasFuelInChildren(state.availableNodes))
                    {
                        dpStage.stageParts.Add(node.part);
                    }
                }

                if (dpStage.stageParts.Count > 0)
                {
                    stages.Add(dpStage);
                    List <Part> activableChildren = new List <Part>();

                    // Remove all decoupled elements, fire sepratrons and parachutes
                    foreach (Part part in dpStage.stageParts)
                    {
                        if (state.availableNodes.ContainsKey(part))
                        {
                            activableChildren.AddRange(state.availableNodes[part].getRelevantChildrenOnDecouple(state.availableNodes));
                            dropPartAndChildren(part);
                        }
                    }
                    dpStage.stageParts.AddRange(activableChildren);
                }

                // Update available engines and fuel flow
                List <Part> activeEngines = state.updateEngines();

                StageDescription newStage = new StageDescription(elapsedTime);
                newStage.stageParts.AddRange(activeEngines);
                stages.Add(newStage);
            }

            // Put all remaining items (parachutes?) in a separate 0 stage
            foreach (var stage in stages)
            {
                foreach (var part in stage.stageParts)
                {
                    state.availableNodes.Remove(part);
                }
            }

            // Put fairings in a separate stage before decoupling
            List <StageDescription> newStages = new List <StageDescription>();
            for (int i = 0; i < stages.Count; i++)
            {
                var fairings    = stages[i].stageParts.Where(p => p.Modules.OfType <ModuleProceduralFairing>().Count() != 0);
                var notfairings = stages[i].stageParts.Where(p => p.Modules.OfType <ModuleProceduralFairing>().Count() == 0);

                if (fairings.Count() != 0)
                {
                    StageDescription fairingStage = new StageDescription(stages[i].activationTime);
                    fairingStage.stageParts.AddRange(fairings);
                    newStages.Add(fairingStage);
                }

                StageDescription notfairingStage = new StageDescription(stages[i].activationTime);
                notfairingStage.stageParts.AddRange(notfairings);
                newStages.Add(notfairingStage);
            }
            stages = newStages;

            int initialStage = 0;
            foreach (Part part in state.availableNodes.Keys)
            {
                if (part.hasStagingIcon)
                {
                    part.inverseStage = 0;
                    initialStage      = 1;
                }
            }

            // doesn't seem to work in 1.1
            // Set stage number correctly
            //StageManager.SetStageCount (stages.Count);

            for (int stage = stages.Count - 1; stage >= 0; stage--)
            {
                var currentStage = stages[stage];
                foreach (Part part in currentStage.stageParts)
                {
                    part.inverseStage = stages.Count - 1 - stage + initialStage;
                }
            }

            // doesn't seem to work in 1.1
            //StageManager.Instance.SortIcons (true);

                        #if DEBUG
            var compTime = DateTime.Now - startTime;
            Debug.Log("Staging computed in " + compTime.TotalMilliseconds + "ms");
            if (samples.Count() > 0)
            {
                string result = "time;altitude;velocity;acceleration;mass;throttle\n";
                foreach (var sample in samples)
                {
                    result += sample.time + ";" + sample.altitude + ";" + sample.velocity + ";" + sample.acceleration + ";" + sample.mass + ";" + sample.throttle + "\n";
                }
                Debug.Log(result);
            }
                        #endif
        }