Updated simulation & added part count to overlay.
Updated simulation & added part count to overlay.

--- a/KerbalEngineer/Editor/BuildOverlay.cs
+++ b/KerbalEngineer/Editor/BuildOverlay.cs
@@ -288,14 +288,14 @@
 
                 // Titles
                 GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-                //GUILayout.Label("Parts:", this.titleStyle);
+                GUILayout.Label("Parts:", this.titleStyle);
                 GUILayout.Label("Delta-V:", this.titleStyle);
                 GUILayout.Label("TWR:", this.titleStyle);
                 GUILayout.EndVertical();
 
                 // Details
                 GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-                //GUILayout.Label(SimulationManager.Instance.LastStage.partCount.ToString("N0"), this.infoStyle);
+                GUILayout.Label(this.lastStage.partCount.ToString("N0"), this.infoStyle);
                 GUILayout.Label(this.lastStage.totalDeltaV.ToString("N0") + " m/s", this.infoStyle);
                 GUILayout.Label(this.lastStage.thrustToWeight.ToString("F2"), this.infoStyle);
                 GUILayout.EndVertical();

--- a/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
+++ b/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
@@ -1,13 +1,36 @@
-using System;
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
+
+using System;
 using System.Text;
+
+#endregion
 
 namespace KerbalEngineer.VesselSimulator
 {
-    class AttachNodeSim
+    internal class AttachNodeSim
     {
         public PartSim attachedPartSim;
+        public String id;
         public AttachNode.NodeType nodeType;
-        public String id;
 
         public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
         {
@@ -35,4 +58,3 @@
         }
     }
 }
-

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -1,8 +1,23 @@
-// Kerbal Engineer Redux
-// Author:  CYBUTEK
-// License: Attribution-NonCommercial-ShareAlike 3.0 Unported
-
-#region
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
 
 using System;
 using System.Collections.Generic;
@@ -48,6 +63,7 @@
             StringBuilder buffer = null;
             //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
             //MonoBehaviour.print("maxThrust = " + maxThrust);
+            //MonoBehaviour.print("minThrust = " + minThrust);
             //MonoBehaviour.print("thrustPercentage = " + thrustPercentage);
             //MonoBehaviour.print("requestedThrust = " + requestedThrust);
             //MonoBehaviour.print("velocity = " + velocity);

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -1,10 +1,23 @@
-// Kerbal Engineer Redux
-// Author:  CYBUTEK
-// License: Attribution-NonCommercial-ShareAlike 3.0 Unported
-//
-// This class has taken a lot of inspiration from r4m0n's MuMech FuelFlowSimulator.  Although extremely
-// similar to the code used within MechJeb, it is a clean re-write.  The similarities are a testiment
-// to how well the MuMech code works and the robustness of the simulation algorithem used.
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
 
 using System;
 using System.Collections.Generic;
@@ -15,43 +28,44 @@
 
 using UnityEngine;
 
+#endregion
+
 namespace KerbalEngineer.VesselSimulator
 {
     public class PartSim
     {
-        public ResourceContainer resources = new ResourceContainer();
-        public ResourceContainer resourceDrains = new ResourceContainer();
-        public ResourceContainer resourceFlowStates = new ResourceContainer();
-
-        List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+        private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+        public double baseMass = 0d;
+        public float cost;
+        public int decoupledInStage;
+        public bool fuelCrossFeed;
         public List<PartSim> fuelTargets = new List<PartSim>();
-
-        public Part part;              // This is only set while the data structures are being initialised
-        public int partId = 0;
-        public String name;
-        public PartSim parent;
+        public bool hasModuleEngines;
+        public bool hasModuleEnginesFX;
+        public bool hasMultiModeEngine;
+
         public bool hasVessel;
-        public String vesselName;
-        public VesselType vesselType;
         public String initialVesselName;
-        public bool isLanded;
+        public int inverseStage;
         public bool isDecoupler;
-        public int decoupledInStage;
-        public int inverseStage;
-        public float cost;
-        public double baseMass = 0d;
-        public double startMass = 0d;
-        public String noCrossFeedNodeKey;
-        public bool fuelCrossFeed;
         public bool isEngine;
         public bool isFuelLine;
         public bool isFuelTank;
+        public bool isLanded;
+        public bool isNoPhysics;
         public bool isSepratron;
-        public bool hasMultiModeEngine;
-        public bool hasModuleEnginesFX;
-        public bool hasModuleEngines;
-        public bool isNoPhysics;
         public bool localCorrectThrust;
+        public String name;
+        public String noCrossFeedNodeKey;
+        public PartSim parent;
+        public Part part; // This is only set while the data structures are being initialised
+        public int partId = 0;
+        public ResourceContainer resourceDrains = new ResourceContainer();
+        public ResourceContainer resourceFlowStates = new ResourceContainer();
+        public ResourceContainer resources = new ResourceContainer();
+        public double startMass = 0d;
+        public String vesselName;
+        public VesselType vesselType;
 
         public PartSim(Part thePart, int id, double atmosphere, LogMsg log)
         {
@@ -60,7 +74,9 @@
             this.name = this.part.partInfo.name;
 
             if (log != null)
+            {
                 log.buf.AppendLine("Create PartSim for " + this.name);
+            }
 
             this.parent = null;
             this.fuelCrossFeed = this.part.fuelCrossFeed;
@@ -80,15 +96,19 @@
 
             // Work out if the part should have no physical significance
             this.isNoPhysics = this.part.HasModule<ModuleLandingGear>() ||
-                            this.part.HasModule<LaunchClamp>() ||
-                            this.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
-                            this.part.PhysicsSignificance == 1;
+                               this.part.HasModule<LaunchClamp>() ||
+                               this.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
+                               this.part.PhysicsSignificance == 1;
 
             if (!this.isNoPhysics)
+            {
                 this.baseMass = this.part.mass;
+            }
 
             if (SimManager.logOutput)
+            {
                 MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass);
+            }
 
             foreach (PartResource resource in this.part.Resources)
             {
@@ -97,7 +117,9 @@
                 if (!Double.IsNaN(resource.amount))
                 {
                     if (SimManager.logOutput)
+                    {
                         MonoBehaviour.print(resource.resourceName + " = " + resource.amount);
+                    }
 
                     this.resources.Add(resource.info.id, resource.amount);
                     this.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
@@ -126,7 +148,19 @@
             this.isEngine = this.hasMultiModeEngine || this.hasModuleEnginesFX || this.hasModuleEngines;
 
             if (SimManager.logOutput)
+            {
                 MonoBehaviour.print("Created " + this.name + ". Decoupled in stage " + this.decoupledInStage);
+            }
+        }
+
+        public ResourceContainer Resources
+        {
+            get { return this.resources; }
+        }
+
+        public ResourceContainer ResourceDrains
+        {
+            get { return this.resourceDrains; }
         }
 
         public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double velocity, bool vectoredThrust, LogMsg log)
@@ -155,7 +189,9 @@
                     if (engine.engineID == mode)
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("Module: " + engine.moduleName);
+                        }
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
@@ -185,10 +221,12 @@
                     foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("Module: " + engine.moduleName);
+                        }
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
-                        
+
                         EngineSim engineSim = new EngineSim(this,
                                                             atmosphere,
                                                             velocity,
@@ -213,7 +251,9 @@
                     foreach (ModuleEngines engine in this.part.GetModules<ModuleEngines>())
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("Module: " + engine.moduleName);
+                        }
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
@@ -238,30 +278,40 @@
             }
 
             if (log != null)
+            {
                 log.Flush();
+            }
         }
 
         private Vector3 CalculateThrustVector(List<Transform> thrustTransforms, LogMsg log)
         {
             if (thrustTransforms == null)
+            {
                 return Vector3.forward;
-            
+            }
+
             Vector3 thrustvec = Vector3.zero;
             foreach (Transform trans in thrustTransforms)
             {
                 if (log != null)
+                {
                     log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
+                }
 
                 thrustvec -= trans.forward;
             }
 
             if (log != null)
+            {
                 log.buf.AppendFormat("ThrustVec  = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
+            }
 
             thrustvec.Normalize();
 
             if (log != null)
+            {
                 log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
+            }
 
             return thrustvec;
         }
@@ -274,12 +324,16 @@
                 if (partSimLookup.TryGetValue(this.part.parent, out this.parent))
                 {
                     if (log != null)
+                    {
                         log.buf.AppendLine("Parent part is " + this.parent.name + ":" + this.parent.partId);
+                    }
                 }
                 else
                 {
                     if (log != null)
+                    {
                         log.buf.AppendLine("No PartSim for parent part (" + this.part.parent.partInfo.name + ")");
+                    }
                 }
             }
         }
@@ -287,13 +341,17 @@
         public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
         {
             if (log != null)
+            {
                 log.buf.AppendLine("SetupAttachNodes for " + this.name + ":" + this.partId + "");
+            }
 
             this.attachNodes.Clear();
             foreach (AttachNode attachNode in this.part.attachNodes)
             {
                 if (log != null)
+                {
                     log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
+                }
 
                 if (attachNode.attachedPart != null && attachNode.id != "Strut")
                 {
@@ -301,32 +359,43 @@
                     if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim))
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
+                        }
 
                         this.attachNodes.Add(new AttachNodeSim(attachedSim, attachNode.id, attachNode.nodeType));
                     }
                     else
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
+                        }
                     }
                 }
             }
 
             foreach (Part p in this.part.fuelLookupTargets)
             {
-                PartSim targetSim;
-                if (partSimLookup.TryGetValue(p, out targetSim))
-                {
-                    if (log != null)
-                        log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
-
-                    this.fuelTargets.Add(targetSim);
-                }
-                else
-                {
-                    if (log != null)
-                        log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
+                if (p != null)
+                {
+                    PartSim targetSim;
+                    if (partSimLookup.TryGetValue(p, out targetSim))
+                    {
+                        if (log != null)
+                        {
+                            log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
+                        }
+
+                        this.fuelTargets.Add(targetSim);
+                    }
+                    else
+                    {
+                        if (log != null)
+                        {
+                            log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
+                        }
+                    }
                 }
             }
         }
@@ -352,29 +421,37 @@
         private bool IsDecoupler(Part thePart)
         {
             return thePart.HasModule<ModuleDecouple>() ||
-                    thePart.HasModule<ModuleAnchoredDecoupler>();
+                   thePart.HasModule<ModuleAnchoredDecoupler>();
         }
 
         private bool IsActiveDecoupler(Part thePart)
         {
             return thePart.FindModulesImplementing<ModuleDecouple>().Any(mod => !mod.isDecoupled) ||
-                    thePart.FindModulesImplementing<ModuleAnchoredDecoupler>().Any(mod => !mod.isDecoupled);
+                   thePart.FindModulesImplementing<ModuleAnchoredDecoupler>().Any(mod => !mod.isDecoupled);
         }
 
         private bool IsSepratron()
         {
             if (!this.part.ActivatesEvenIfDisconnected)
+            {
                 return false;
+            }
 
             if (this.part is SolidRocket)
+            {
                 return true;
+            }
 
             var modList = this.part.Modules.OfType<ModuleEngines>();
             if (modList.Count() == 0)
+            {
                 return false;
-
-            if (modList.First().throttleLocked == true)
+            }
+
+            if (modList.First().throttleLocked)
+            {
                 return true;
+            }
 
             return false;
         }
@@ -383,7 +460,6 @@
         {
             this.part = null;
         }
-
 
         // All functions below this point must not rely on the part member (it may be null)
         //
@@ -403,7 +479,9 @@
             if (visited.Contains(this))
             {
                 if (log != null)
+                {
                     log.buf.AppendLine(indent + "Returning empty set, already visited (" + this.name + ":" + this.partId + ")");
+                }
 
                 return allSources;
             }
@@ -440,7 +518,9 @@
             if (allSources.Count > 0)
             {
                 if (log != null)
+                {
                     log.buf.AppendLine(indent + "Returning " + allSources.Count + " fuel target sources (" + this.name + ":" + this.partId + ")");
+                }
 
                 return allSources;
             }
@@ -458,7 +538,7 @@
                 {
                     if (attachSim.attachedPartSim != null)
                     {
-                        if (/*attachSim.nodeType != AttachNode.NodeType.Surface &&*/
+                        if ( /*attachSim.nodeType != AttachNode.NodeType.Surface &&*/
                             !(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 && attachSim.id.Contains(this.noCrossFeedNodeKey)))
                         {
                             if (visited.Contains(attachSim.attachedPartSim))
@@ -479,26 +559,18 @@
                                 }
                             }
                         }
-                        else
-                        {
-                            //if (log != null)
-                            //    log.buf.AppendLine(indent + "AttachNode is noCrossFeedKey, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
-                        }
                     }
                 }
 
                 if (allSources.Count > 0)
                 {
                     if (log != null)
+                    {
                         log.buf.AppendLine(indent + "Returning " + allSources.Count + " attached sources (" + this.name + ":" + this.partId + ")");
+                    }
 
                     return allSources;
                 }
-            }
-            else
-            {
-                //if (log != null)
-                //    log.buf.AppendLine(indent + "Crossfeed disabled, skipping axial connected parts (" + name + ":" + partId + ")");
             }
 
             // Rule 5: If the part is fuel container for searched type of fuel (i.e. it has capability to contain that type of fuel and the fuel type was not disabled [Experiment]) and it contains fuel, it returns itself.
@@ -510,12 +582,9 @@
                     allSources.Add(this);
 
                     if (log != null)
+                    {
                         log.buf.AppendLine(indent + "Returning enabled tank as only source (" + this.name + ":" + this.partId + ")");
-                }
-                else
-                {
-                    //if (log != null)
-                    //    log.buf.AppendLine(indent + "Returning empty set, enabled tank is empty (" + name + ":" + partId + ")");
+                    }
                 }
 
                 return allSources;
@@ -537,16 +606,13 @@
                         if (allSources.Count > 0)
                         {
                             if (log != null)
+                            {
                                 log.buf.AppendLine(indent + "Returning " + allSources.Count + " parent sources (" + this.name + ":" + this.partId + ")");
+                            }
 
                             return allSources;
                         }
                     }
-                }
-                else
-                {
-                    //if (log != null)
-                    //    log.buf.AppendLine(indent + "Crossfeed disabled, skipping radial parent (" + name + ":" + partId + ")");
                 }
             }
 
@@ -557,7 +623,6 @@
             return allSources;
         }
 
-
         public void RemoveAttachedParts(HashSet<PartSim> partSims)
         {
             // Loop through the attached parts
@@ -565,10 +630,11 @@
             {
                 // If the part is in the set then "remove" it by clearing the PartSim reference
                 if (partSims.Contains(attachSim.attachedPartSim))
+                {
                     attachSim.attachedPartSim = null;
-            }
-        }
-
+                }
+            }
+        }
 
         public void DrainResources(double time)
         {
@@ -607,7 +673,9 @@
             while (partSim != null)
             {
                 if (partSim.isDecoupler)
+                {
                     count++;
+                }
 
                 partSim = partSim.parent;
             }
@@ -624,25 +692,11 @@
             double mass = this.baseMass;
 
             foreach (int type in this.resources.Types)
+            {
                 mass += this.resources.GetResourceMass(type);
+            }
 
             return mass;
-        }
-
-        public ResourceContainer Resources
-        {
-            get
-            {
-                return this.resources;
-            }
-        }
-
-        public ResourceContainer ResourceDrains
-        {
-            get
-            {
-                return this.resourceDrains;
-            }
         }
 
         public String DumpPartAndParentsToBuffer(StringBuilder buffer, String prefix)
@@ -673,7 +727,9 @@
             buffer.AppendFormat(", isSep = {0}", this.isSepratron);
 
             foreach (int type in this.resources.Types)
+            {
                 buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), this.resources[type]);
+            }
 
             if (this.attachNodes.Count > 0)
             {
@@ -697,10 +753,11 @@
                 foreach (PartSim partSim in allParts)
                 {
                     if (partSim.parent == this)
+                    {
                         partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
+                    }
                 }
             }
         }
     }
 }
-

--- a/KerbalEngineer/VesselSimulator/ResourceContainer.cs
+++ b/KerbalEngineer/VesselSimulator/ResourceContainer.cs
@@ -1,37 +1,59 @@
-// Kerbal Engineer Redux
-// Author:  CYBUTEK
-// License: Attribution-NonCommercial-ShareAlike 3.0 Unported
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
 
 using System.Collections;
 using System.Collections.Generic;
+
+using UnityEngine;
+
+#endregion
 
 namespace KerbalEngineer.VesselSimulator
 {
     public class ResourceContainer
     {
-        Hashtable resources = new Hashtable();
+        private Hashtable resources = new Hashtable();
 
         public double this[int type]
         {
             get
             {
                 if (this.resources.ContainsKey(type))
+                {
                     return (double)this.resources[type];
+                }
 
                 return 0d;
             }
             set
             {
                 if (this.resources.ContainsKey(type))
+                {
                     this.resources[type] = value;
+                }
                 else
+                {
                     this.resources.Add(type, value);
+                }
             }
-        }
-
-        public bool HasType(int type)
-        {
-            return this.resources.ContainsKey(type);
         }
 
         public List<int> Types
@@ -41,7 +63,9 @@
                 List<int> types = new List<int>();
 
                 foreach (int key in this.resources.Keys)
+                {
                     types.Add(key);
+                }
 
                 return types;
             }
@@ -54,7 +78,9 @@
                 double mass = 0d;
 
                 foreach (double resource in this.resources.Values)
+                {
                     mass += resource;
+                }
 
                 return mass;
             }
@@ -67,11 +93,18 @@
                 foreach (int type in this.resources.Keys)
                 {
                     if ((double)this.resources[type] > SimManager.RESOURCE_MIN)
+                    {
                         return false;
+                    }
                 }
 
                 return true;
             }
+        }
+
+        public bool HasType(int type)
+        {
+            return this.resources.ContainsKey(type);
         }
 
         public bool EmptyOf(HashSet<int> types)
@@ -79,7 +112,9 @@
             foreach (int type in types)
             {
                 if (this.HasType(type) && (double)this.resources[type] > SimManager.RESOURCE_MIN)
+                {
                     return false;
+                }
             }
 
             return true;
@@ -88,9 +123,13 @@
         public void Add(int type, double amount)
         {
             if (this.resources.ContainsKey(type))
+            {
                 this.resources[type] = (double)this.resources[type] + amount;
+            }
             else
+            {
                 this.resources.Add(type, amount);
+            }
         }
 
         public void Reset()
@@ -102,7 +141,7 @@
         {
             foreach (int key in this.resources.Keys)
             {
-                UnityEngine.MonoBehaviour.print(" -> " + GetResourceName(key) + " = " + this.resources[key]);
+                MonoBehaviour.print(" -> " + GetResourceName(key) + " = " + this.resources[key]);
             }
         }
 
@@ -133,4 +172,3 @@
         }
     }
 }
-

--- a/KerbalEngineer/VesselSimulator/SimManager.cs
+++ b/KerbalEngineer/VesselSimulator/SimManager.cs
@@ -1,52 +1,72 @@
-using System;
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
+
+using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
+using System.Reflection;
 using System.Threading;
 
-using KerbalEngineer.Flight;
-
 using UnityEngine;
+
+#endregion
 
 namespace KerbalEngineer.VesselSimulator
 {
     public class SimManager
     {
-        public static SimManager Instance = new SimManager();
         public const double RESOURCE_MIN = 0.0001;
-        
-        private static bool bRequested = false;
-        private static bool bRunning = false;
-        private static Stopwatch timer = new Stopwatch();
-        private static long delayBetweenSims = 0;
-
-        public static Stage[] Stages { get; private set; }
-        public static Stage LastStage { get; private set; }
-        public static String failMessage { get; private set; }
+
+        private static bool bRequested;
+        private static bool bRunning;
+        private static readonly Stopwatch timer = new Stopwatch();
+        private static long delayBetweenSims;
 
         public static bool dumpTree = false;
         public static bool logOutput = false;
         public static bool vectoredThrust = false;
         public static long minSimTime = 150;
+
+        // Support for RealFuels using reflection to check localCorrectThrust without dependency
+        private static bool hasCheckedForRealFuels;
+        private static bool hasInstalledRealFuels;
+
+        private static FieldInfo RF_ModuleEngineConfigs_locaCorrectThrust;
+        private static FieldInfo RF_ModuleHybridEngine_locaCorrectThrust;
+        private static FieldInfo RF_ModuleHybridEngines_locaCorrectThrust;
+        public static Stage[] Stages { get; private set; }
+        public static Stage LastStage { get; private set; }
+        public static String failMessage { get; private set; }
         public static double Gravity { get; set; }
         public static double Atmosphere { get; set; }
         public static double Velocity { get; set; }
 
-        // Support for RealFuels using reflection to check localCorrectThrust without dependency
-        private static bool hasCheckedForRealFuels = false;
-        private static bool hasInstalledRealFuels = false;
-
-        private static System.Reflection.FieldInfo RF_ModuleEngineConfigs_locaCorrectThrust = null;
-        private static System.Reflection.FieldInfo RF_ModuleHybridEngine_locaCorrectThrust = null;
-        private static System.Reflection.FieldInfo RF_ModuleHybridEngines_locaCorrectThrust = null;
-
         private static void GetRealFuelsTypes()
         {
-			hasCheckedForRealFuels = true;
-
-			foreach (AssemblyLoader.LoadedAssembly assembly in AssemblyLoader.loadedAssemblies)
-            {
-                MonoBehaviour.print("Assembly:" + assembly.assembly.ToString());
+            hasCheckedForRealFuels = true;
+
+            foreach (AssemblyLoader.LoadedAssembly assembly in AssemblyLoader.loadedAssemblies)
+            {
+                MonoBehaviour.print("Assembly:" + assembly.assembly);
 
                 if (assembly.assembly.ToString().Split(',')[0] == "RealFuels")
                 {
@@ -54,28 +74,34 @@
 
                     Type RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");
                     if (RF_ModuleEngineConfigs_Type != null)
+                    {
                         RF_ModuleEngineConfigs_locaCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");
+                    }
 
                     Type RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");
                     if (RF_ModuleHybridEngine_Type != null)
+                    {
                         RF_ModuleHybridEngine_locaCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");
+                    }
 
                     Type RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");
                     if (RF_ModuleHybridEngines_Type != null)
+                    {
                         RF_ModuleHybridEngines_locaCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");
-
-					hasInstalledRealFuels = true;
-					break;
-				}
-
-			}
-
-		}
+                    }
+
+                    hasInstalledRealFuels = true;
+                    break;
+                }
+            }
+        }
 
         public static bool DoesEngineUseCorrectedThrust(Part theEngine)
         {
             if (!hasInstalledRealFuels /*|| HighLogic.LoadedSceneIsFlight*/)
+            {
                 return false;
+            }
 
             // Look for any of the Real Fuels engine modules and call the relevant method to find out
             if (RF_ModuleEngineConfigs_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs"))
@@ -85,7 +111,9 @@
                 {
                     // Check the localCorrectThrust
                     if ((bool)RF_ModuleEngineConfigs_locaCorrectThrust.GetValue(modEngineConfigs))
+                    {
                         return true;
+                    }
                 }
             }
 
@@ -96,7 +124,9 @@
                 {
                     // Check the localCorrectThrust
                     if ((bool)RF_ModuleHybridEngine_locaCorrectThrust.GetValue(modHybridEngine))
+                    {
                         return true;
+                    }
                 }
             }
 
@@ -107,22 +137,27 @@
                 {
                     // Check the localCorrectThrust
                     if ((bool)RF_ModuleHybridEngines_locaCorrectThrust.GetValue(modHybridEngines))
+                    {
                         return true;
+                    }
                 }
             }
 
             return false;
         }
 
-
         public static void RequestSimulation()
         {
             if (!hasCheckedForRealFuels)
+            {
                 GetRealFuelsTypes();
+            }
 
             bRequested = true;
             if (!timer.IsRunning)
+            {
                 timer.Start();
+            }
         }
 
         public static void TryStartSimulation()
@@ -163,7 +198,7 @@
                 // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
                 if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Velocity, dumpTree, vectoredThrust))
                 {
-                    ThreadPool.QueueUserWorkItem(new WaitCallback(RunSimulation), sim);
+                    ThreadPool.QueueUserWorkItem(RunSimulation, sim);
                 }
                 else
                 {
@@ -192,7 +227,9 @@
                     if (logOutput)
                     {
                         foreach (Stage stage in Stages)
+                        {
                             stage.Dump();
+                        }
                     }
                     LastStage = Stages.Last();
                 }
@@ -210,11 +247,15 @@
             MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
 #else
             if (logOutput)
+            {
                 MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
+            }
 #endif
             delayBetweenSims = minSimTime - timer.ElapsedMilliseconds;
             if (delayBetweenSims < 0)
+            {
                 delayBetweenSims = 0;
+            }
 
             timer.Reset();
             timer.Start();
@@ -254,4 +295,3 @@
         }
     }
 }
-

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -1,10 +1,23 @@
-// Kerbal Engineer Redux
-// Author:  CYBUTEK
-// License: Attribution-NonCommercial-ShareAlike 3.0 Unported
-//
-// This class has taken a lot of inspiration from r4m0n's MuMech FuelFlowSimulator.  Although extremely
-// similar to the code used within MechJeb, it is a clean re-write.  The similarities are a testiment
-// to how well the MuMech code works and the robustness of the simulation algorithem used.
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
 
 using System;
 using System.Collections.Generic;
@@ -13,51 +26,82 @@
 
 using UnityEngine;
 
+#endregion
+
 namespace KerbalEngineer.VesselSimulator
 {
     public class Simulation
     {
+        private const double STD_GRAVITY = 9.81d;
+        private const double SECONDS_PER_DAY = 86400d;
+        private readonly Stopwatch _timer = new Stopwatch();
+        private List<EngineSim> activeEngines;
+        private List<EngineSim> allEngines;
+        private List<PartSim> allFuelLines;
+        private List<PartSim> allParts;
+        private double atmosphere;
+        private int currentStage;
+        private double currentisp;
+        private bool doingCurrent;
+        private List<PartSim> dontStageParts;
+        private HashSet<PartSim> drainingParts;
+        private HashSet<int> drainingResources;
+        private double gravity;
+
+        private int lastStage;
         private List<Part> partList;
-
-        private List<PartSim> allParts;
-        private List<PartSim> allFuelLines;
-        private HashSet<PartSim> drainingParts;
-        private List<EngineSim> allEngines;
-        private List<EngineSim> activeEngines;
-        private HashSet<int> drainingResources;
-
-        private int lastStage = 0;
-        private int currentStage = 0;
-        private bool doingCurrent = false;
-
+        private double simpleTotalThrust;
+        private double stageStartMass;
+        private double stageTime;
+        private double stepEndMass;
+        private double stepStartMass;
+        private double totalStageActualThrust;
+        private double totalStageFlowRate;
+        private double totalStageIspFlowRate;
+        private double totalStageThrust;
+        private Vector3 vecActualThrust;
+        private Vector3 vecStageDeltaV;
+        private Vector3 vecThrust;
+        private double velocity;
         public String vesselName;
         public VesselType vesselType;
 
-        private double stageTime = 0d;
-        private Vector3 vecStageDeltaV;
-        private double simpleTotalThrust = 0d;
-        private double totalStageThrust = 0d;
-        private double totalStageActualThrust = 0d;
-        private Vector3 vecThrust;
-        private Vector3 vecActualThrust;
-        private double totalStageFlowRate = 0d;
-        private double totalStageIspFlowRate = 0d;
-        private double currentisp = 0d;
-        private double stageStartMass = 0d;
-        private double stepStartMass = 0d;
-        private double stepEndMass = 0d;
-
-        private double gravity = 0d;
-        private double atmosphere = 0d;
-        private double velocity = 0d;
-        private Stopwatch _timer = new Stopwatch();
-        private const double STD_GRAVITY = 9.81d;
-        private const double SECONDS_PER_DAY = 86400d;
-        
         public Simulation()
         {
             if (SimManager.logOutput)
+            {
                 MonoBehaviour.print("Simulation created");
+            }
+        }
+
+        private double ShipStartMass
+        {
+            get
+            {
+                double mass = 0d;
+
+                foreach (PartSim partSim in this.allParts)
+                {
+                    mass += partSim.GetStartMass();
+                }
+
+                return mass;
+            }
+        }
+
+        private double ShipMass
+        {
+            get
+            {
+                double mass = 0d;
+
+                foreach (PartSim partSim in this.allParts)
+                {
+                    mass += partSim.GetMass();
+                }
+
+                return mass;
+            }
         }
 
         // This function prepares the simulation by creating all the necessary data structures it will 
@@ -108,7 +152,9 @@
                 if (partSimLookup.ContainsKey(part))
                 {
                     if (log != null)
+                    {
                         log.buf.AppendLine("Part " + part.name + " appears in vessel list more than once");
+                    }
                     continue;
                 }
 
@@ -119,9 +165,13 @@
                 partSimLookup.Add(part, partSim);
                 this.allParts.Add(partSim);
                 if (partSim.isFuelLine)
+                {
                     this.allFuelLines.Add(partSim);
+                }
                 if (partSim.isEngine)
+                {
                     partSim.CreateEngineSims(this.allEngines, this.atmosphere, this.velocity, vectoredThrust, log);
+                }
 
                 partId++;
             }
@@ -134,7 +184,7 @@
             {
                 partSim.SetupParent(partSimLookup, log);
             }
-            
+
             // Then, in the VAB/SPH, we add the parent of each fuel line to the fuelTargets list of their targets
             if (HighLogic.LoadedSceneIsEditor)
             {
@@ -146,20 +196,26 @@
                         if (partSimLookup.TryGetValue((partSim.part as FuelLine).target, out targetSim))
                         {
                             if (log != null)
+                            {
                                 log.buf.AppendLine("Fuel line target is " + targetSim.name + ":" + targetSim.partId);
+                            }
 
                             targetSim.fuelTargets.Add(partSim.parent);
                         }
                         else
                         {
                             if (log != null)
+                            {
                                 log.buf.AppendLine("No PartSim for fuel line target (" + partSim.part.partInfo.name + ")");
+                            }
                         }
                     }
                     else
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("Fuel line target is null");
+                        }
                     }
                 }
             }
@@ -169,13 +225,17 @@
             {
                 partSim.SetupAttachNodes(partSimLookup, log);
                 if (partSim.decoupledInStage >= this.lastStage)
+                {
                     this.lastStage = partSim.decoupledInStage + 1;
+                }
             }
 
             // And finally release the Part references from all the PartSims
             //MonoBehaviour.print("ReleaseParts");
             foreach (PartSim partSim in this.allParts)
+            {
                 partSim.ReleasePart();
+            }
 
             // And dereference the core's part list
             this.partList = null;
@@ -188,48 +248,63 @@
             }
 
             if (dumpTree)
+            {
                 this.Dump();
+            }
 
             return true;
         }
 
-        
         // This function runs the simulation and returns a newly created array of Stage objects
         public Stage[] RunSimulation()
         {
             if (SimManager.logOutput)
+            {
                 MonoBehaviour.print("RunSimulation started");
+            }
             this._timer.Start();
+
+            LogMsg log = null;
+            if (SimManager.logOutput)
+            {
+                log = new LogMsg();
+            }
+
             // Start with the last stage to simulate
             // (this is in a member variable so it can be accessed by AllowedToStage and ActivateStage)
             this.currentStage = this.lastStage;
 
-            LogMsg log = null;
-            if (SimManager.logOutput)
-                log = new LogMsg();
-
             // Work out which engines would be active if just doing the staging and if this is different to the 
             // currently active engines then generate an extra stage
             // Loop through all the engines
+            bool anyActive = false;
             foreach (EngineSim engine in this.allEngines)
             {
                 if (log != null)
+                {
                     log.buf.AppendLine("Testing engine mod of " + engine.partSim.name + ":" + engine.partSim.partId);
+                }
                 bool bActive = engine.isActive;
                 bool bStage = (engine.partSim.inverseStage >= this.currentStage);
                 if (log != null)
+                {
                     log.buf.AppendLine("bActive = " + bActive + "   bStage = " + bStage);
+                }
                 if (HighLogic.LoadedSceneIsFlight)
                 {
+                    if (bActive)
+                    {
+                        anyActive = true;
+                    }
                     if (bActive != bStage)
                     {
                         // If the active state is different to the state due to staging
                         if (log != null)
+                        {
                             log.buf.AppendLine("Need to do current active engines first");
+                        }
 
                         this.doingCurrent = true;
-                        this.currentStage++;
-                        break;
                     }
                 }
                 else
@@ -237,15 +312,34 @@
                     if (bStage)
                     {
                         if (log != null)
+                        {
                             log.buf.AppendLine("Marking as active");
+                        }
 
                         engine.isActive = true;
                     }
                 }
             }
 
+            // If we need to do current because of difference in engine activation and there actually are active engines
+            // then we do the extra stage otherwise activate the next stage and don't treat it as current
+            if (this.doingCurrent && anyActive)
+            {
+                this.currentStage++;
+            }
+            else
+            {
+                this.ActivateStage();
+                this.doingCurrent = false;
+            }
+
+            // Create a list of lists of PartSims that prevent decoupling
+            List<List<PartSim>> dontStagePartsLists = this.BuildDontStageLists(log);
+
             if (log != null)
+            {
                 log.Flush();
+            }
 
             // Create the array of stages that will be returned
             Stage[] stages = new Stage[this.currentStage + 1];
@@ -286,7 +380,8 @@
                 stage.actualThrust = this.totalStageActualThrust;
                 stage.actualThrustToWeight = this.totalStageActualThrust / (this.stageStartMass * this.gravity);
 
-                // Calculate the cost and mass of this stage
+                // Calculate the cost and mass of this stage and add all engines and tanks that are decoupled
+                // in the next stage to the dontStageParts list
                 foreach (PartSim partSim in this.allParts)
                 {
                     if (partSim.decoupledInStage == this.currentStage - 1)
@@ -296,8 +391,27 @@
                     }
                 }
 
+                this.dontStageParts = dontStagePartsLists[this.currentStage];
+
                 if (log != null)
-                    MonoBehaviour.print("Stage setup took " + this._timer.ElapsedMilliseconds + "ms");
+                {
+                    log.buf.AppendLine("Stage setup took " + this._timer.ElapsedMilliseconds + "ms");
+
+                    if (this.dontStageParts.Count > 0)
+                    {
+                        log.buf.AppendLine("Parts preventing staging:");
+                        foreach (PartSim partSim in this.dontStageParts)
+                        {
+                            partSim.DumpPartToBuffer(log.buf, "");
+                        }
+                    }
+                    else
+                    {
+                        log.buf.AppendLine("No parts preventing staging");
+                    }
+
+                    log.Flush();
+                }
 
                 // Now we will loop until we are allowed to stage
                 int loopCounter = 0;
@@ -320,10 +434,14 @@
                     }
 
                     if (log != null)
+                    {
                         MonoBehaviour.print("Drain time = " + resourceDrainTime + " (" + partMinDrain.name + ":" + partMinDrain.partId + ")");
+                    }
 
                     foreach (PartSim partSim in this.drainingParts)
+                    {
                         partSim.DrainResources(resourceDrainTime);
+                    }
 
                     // Get the mass after draining
                     this.stepEndMass = this.ShipMass;
@@ -334,13 +452,17 @@
                     //MonoBehaviour.print("currentThrust = " + totalStageThrust);
                     //MonoBehaviour.print("currentTWR = " + stepEndTWR);
                     if (stepEndTWR > stage.maxThrustToWeight)
+                    {
                         stage.maxThrustToWeight = stepEndTWR;
+                    }
 
                     //MonoBehaviour.print("newMaxTWR = " + stage.maxThrustToWeight);
 
                     // If we have drained anything and the masses make sense then add this step's deltaV to the stage total
                     if (resourceDrainTime > 0d && this.stepStartMass > this.stepEndMass && this.stepStartMass > 0d && this.stepEndMass > 0d)
+                    {
                         this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * STD_GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
+                    }
 
                     // Update the active engines and resource drains for the next step
                     this.UpdateResourceDrains();
@@ -373,17 +495,22 @@
 
                 // Store the magnitude of the deltaV vector
                 stage.deltaV = this.vecStageDeltaV.magnitude;
-                
+
                 // Recalculate effective stage isp from the stage deltaV (flip the standard deltaV calculation around)
                 // Note: If the mass doesn't change then this is a divide by zero
                 if (this.stageStartMass != this.stepStartMass)
+                {
                     stage.isp = stage.deltaV / (STD_GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
+                }
                 else
+                {
                     stage.isp = 0;
+                }
 
                 // Zero stage time if more than a day (this should be moved into the window code)
                 stage.time = (this.stageTime < SECONDS_PER_DAY) ? this.stageTime : 0d;
-                stage.number = this.doingCurrent ? -1 : this.currentStage;                // Set the stage number to -1 if doing current engines
+                stage.number = this.doingCurrent ? -1 : this.currentStage; // Set the stage number to -1 if doing current engines
+                stage.partCount = this.allParts.Count;
                 stages[this.currentStage] = stage;
 
                 // Now activate the next stage
@@ -431,7 +558,9 @@
                 // Zero the total time if the value will be huge (24 hours?) to avoid the display going weird
                 // (this should be moved into the window code)
                 if (stages[i].totalTime > SECONDS_PER_DAY)
+                {
                     stages[i].totalTime = 0d;
+                }
             }
 
             if (log != null)
@@ -443,6 +572,52 @@
             return stages;
         }
 
+        private List<List<PartSim>> BuildDontStageLists(LogMsg log)
+        {
+            if (log != null)
+            {
+                log.buf.AppendLine("Creating list with capacity of " + (this.currentStage + 1));
+            }
+            List<List<PartSim>> lists = new List<List<PartSim>>();
+            for (int i = 0; i <= this.currentStage; i++)
+            {
+                lists.Add(new List<PartSim>());
+            }
+
+            foreach (PartSim partSim in this.allParts)
+            {
+                if (partSim.isEngine || !partSim.Resources.Empty)
+                {
+                    if (log != null)
+                    {
+                        log.buf.AppendLine(partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
+                    }
+
+                    if (partSim.decoupledInStage < -1 || partSim.decoupledInStage > this.currentStage - 1)
+                    {
+                        if (log != null)
+                        {
+                            log.buf.AppendLine("decoupledInStage out of range");
+                        }
+                    }
+                    else
+                    {
+                        lists[partSim.decoupledInStage + 1].Add(partSim);
+                    }
+                }
+            }
+
+            for (int i = 1; i <= this.lastStage; i++)
+            {
+                if (lists[i].Count == 0)
+                {
+                    lists[i] = lists[i - 1];
+                }
+            }
+
+            return lists;
+        }
+
         // This function simply rebuilds the active engines by testing the isActive flag of all the engines
         private void UpdateActiveEngines()
         {
@@ -450,7 +625,9 @@
             foreach (EngineSim engine in this.allEngines)
             {
                 if (engine.isActive)
+                {
                     this.activeEngines.Add(engine);
+                }
             }
         }
 
@@ -484,9 +661,13 @@
 
             // Calculate the effective isp at this point
             if (this.totalStageFlowRate > 0d && this.totalStageIspFlowRate > 0d)
+            {
                 this.currentisp = this.totalStageIspFlowRate / this.totalStageFlowRate;
+            }
             else
+            {
                 this.currentisp = 0;
+            }
         }
 
         // This function does all the hard work of working out which engines are burning, which tanks are being drained 
@@ -495,13 +676,15 @@
         {
             // Update the active engines
             this.UpdateActiveEngines();
-            
+
             // Empty the draining resources set
             this.drainingResources.Clear();
 
             // Reset the resource drains of all draining parts
             foreach (PartSim partSim in this.drainingParts)
+            {
                 partSim.ResourceDrains.Reset();
+            }
 
             // Empty the draining parts set
             this.drainingParts.Clear();
@@ -514,7 +697,9 @@
                 {
                     // If it is active then add the consumed resource types to the set
                     foreach (int type in engine.ResourceConsumptions.Types)
+                    {
                         this.drainingResources.Add(type);
+                    }
                 }
             }
 
@@ -527,7 +712,9 @@
                 buffer.AppendFormat("Active engines = {0:d}\n", this.activeEngines.Count);
                 int i = 0;
                 foreach (EngineSim engine in this.activeEngines)
+                {
                     engine.DumpEngineToBuffer(buffer, "Engine " + (i++) + ":");
+                }
                 MonoBehaviour.print(buffer);
             }
         }
@@ -543,28 +730,16 @@
                 buffer.AppendFormat("currentStage = {0:d}\n", this.currentStage);
             }
 
-            if (this.activeEngines.Count == 0)
-            {
-                if (SimManager.logOutput)
-                {
-                    buffer.AppendLine("No active engines => true");
-                    MonoBehaviour.print(buffer);
-                }
-
-                return true;
-            }
-
-            bool partDecoupled = false;
-            bool engineDecoupled = false;
-
-            foreach (PartSim partSim in this.allParts)
-            {
-                //partSim.DumpPartToBuffer(buffer, "Testing: ", allParts);
-                //buffer.AppendFormat("isSepratron = {0}\n", partSim.isSepratron ? "true" : "false");
-                if (partSim.decoupledInStage == (this.currentStage - 1) && (!partSim.isSepratron || partSim.decoupledInStage < partSim.inverseStage))
-                {
-                    partDecoupled = true;
-                    
+            if (this.activeEngines.Count > 0)
+            {
+                foreach (PartSim partSim in this.dontStageParts)
+                {
+                    if (SimManager.logOutput)
+                    {
+                        partSim.DumpPartToBuffer(buffer, "Testing: ");
+                    }
+                    //buffer.AppendFormat("isSepratron = {0}\n", partSim.isSepratron ? "true" : "false");
+
                     if (!partSim.Resources.EmptyOf(this.drainingResources))
                     {
                         if (SimManager.logOutput)
@@ -590,38 +765,26 @@
                                 return false;
                             }
                         }
-
-                        engineDecoupled = true;
-                    }
-                }
-            }
-
-            if (!partDecoupled)
+                    }
+                }
+            }
+
+            if (this.currentStage == 0 && this.doingCurrent)
             {
                 if (SimManager.logOutput)
                 {
-                    buffer.AppendLine("No engine decoupled but something is => false");
+                    buffer.AppendLine("Current stage == 0 && doingCurrent => false");
                     MonoBehaviour.print(buffer);
                 }
                 return false;
             }
 
-            if (this.currentStage > 0 && !this.doingCurrent)
-            {
-                if (SimManager.logOutput)
-                {
-                    buffer.AppendLine("Current stage > 0 && !doingCurrent => true");
-                    MonoBehaviour.print(buffer);
-                }
-                return true;
-            }
-
             if (SimManager.logOutput)
             {
-                buffer.AppendLine("Returning false");
+                buffer.AppendLine("Returning true");
                 MonoBehaviour.print(buffer);
             }
-            return false;
+            return true;
         }
 
         // This function activates the next stage
@@ -633,7 +796,9 @@
             foreach (PartSim partSim in this.allParts)
             {
                 if (partSim.decoupledInStage >= this.currentStage)
+                {
                     decoupledParts.Add(partSim);
+                }
             }
 
             foreach (PartSim partSim in decoupledParts)
@@ -646,12 +811,16 @@
                     for (int i = this.allEngines.Count - 1; i >= 0; i--)
                     {
                         if (this.allEngines[i].partSim == partSim)
+                        {
                             this.allEngines.RemoveAt(i);
+                        }
                     }
                 }
                 // If it is a fuel line then remove it from the list of all fuel lines
                 if (partSim.isFuelLine)
+                {
                     this.allFuelLines.Remove(partSim);
+                }
             }
 
             // Loop through all the (remaining) parts
@@ -662,40 +831,12 @@
             }
 
             // Now we loop through all the engines and activate those that are ignited in this stage
-            foreach(EngineSim engine in this.allEngines)
+            foreach (EngineSim engine in this.allEngines)
             {
                 if (engine.partSim.inverseStage == this.currentStage)
+                {
                     engine.isActive = true;
-            }
-        }
-
-        private double ShipStartMass
-        {
-            get
-            {
-                double mass = 0d;
-
-                foreach (PartSim partSim in this.allParts)
-                {
-                    mass += partSim.GetStartMass();
-                }
-
-                return mass;
-            }
-        }
-
-        private double ShipMass
-        {
-            get
-            {
-                double mass = 0d;
-
-                foreach (PartSim partSim in this.allParts)
-                {
-                    mass += partSim.GetMass();
-                }
-
-                return mass;
+                }
             }
         }
 
@@ -709,10 +850,14 @@
             {
                 PartSim root = this.allParts[0];
                 while (root.parent != null)
+                {
                     root = root.parent;
+                }
 
                 if (root.hasVessel)
+                {
                     buffer.AppendFormat("vesselName = '{0}'  vesselType = {1}\n", this.vesselName, SimManager.GetVesselTypeString(this.vesselType));
+                }
 
                 root.DumpPartToBuffer(buffer, "", this.allParts);
             }
@@ -721,4 +866,3 @@
         }
     }
 }
-

--- a/KerbalEngineer/VesselSimulator/Stage.cs
+++ b/KerbalEngineer/VesselSimulator/Stage.cs
@@ -1,38 +1,58 @@
-// Kerbal Engineer Redux
-// Author:  CYBUTEK
-// License: Attribution-NonCommercial-ShareAlike 3.0 Unported
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
 
 using System.Text;
 
 using UnityEngine;
 
+#endregion
+
 namespace KerbalEngineer.VesselSimulator
 {
     public class Stage
     {
+        public double actualThrust = 0f;
+        public double actualThrustToWeight = 0f;
+        public float cost = 0;
+        public double deltaV = 0f;
+        public double inverseTotalDeltaV = 0f;
+        public double isp = 0f;
+        public double mass = 0f;
+        public double maxThrustToWeight = 0f;
         public int number = 0;
-        public float cost = 0;
+        public double thrust = 0f;
+        public double thrustToWeight = 0f;
+        public double time = 0f;
         public float totalCost = 0;
-        public double time = 0f;
+        public double totalDeltaV = 0f;
+        public double totalMass = 0f;
         public double totalTime = 0f;
-        public double mass = 0f;
-        public double totalMass = 0f;
-        public double isp = 0f;
-        public double thrust = 0f;
-        public double actualThrust = 0f;
-        public double thrustToWeight = 0f;
-        public double maxThrustToWeight = 0f;
-        public double actualThrustToWeight = 0f;
-        public double deltaV = 0f;
-        public double totalDeltaV = 0f;
-        public double inverseTotalDeltaV = 0f;
+        public int partCount = 0;
 
         public void Dump()
         {
             StringBuilder str = new StringBuilder("", 512);
             str.AppendFormat("number        : {0:d}\n", this.number);
-            str.AppendFormat("cost          : {0:d}\n", this.cost);
-            str.AppendFormat("totalCost     : {0:d}\n", this.totalCost);
+            str.AppendFormat("cost          : {0:g6}\n", this.cost);
+            str.AppendFormat("totalCost     : {0:g6}\n", this.totalCost);
             str.AppendFormat("time          : {0:g6}\n", this.time);
             str.AppendFormat("totalTime     : {0:g6}\n", this.totalTime);
             str.AppendFormat("mass          : {0:g6}\n", this.mass);
@@ -46,9 +66,8 @@
             str.AppendFormat("deltaV        : {0:g6}\n", this.deltaV);
             str.AppendFormat("totalDeltaV   : {0:g6}\n", this.totalDeltaV);
             str.AppendFormat("invTotDeltaV  : {0:g6}\n", this.inverseTotalDeltaV);
-            
+
             MonoBehaviour.print(str);
         }
     }
 }
-

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ