Merged Sarbian's 1.0 fixes to vessel simulator
Merged Sarbian's 1.0 fixes to vessel simulator

 Binary files a/Assets/CurseLogo.png and b/Assets/CurseLogo.png differ
 Binary files a/Assets/CurseLogo.psd and b/Assets/CurseLogo.psd differ
--- a/Documents/CHANGES.txt
+++ b/Documents/CHANGES.txt
@@ -1,36 +1,3 @@
-1.0.16.5, 02-05-2015
-    Fixed: Delta-V not being correctly calculated.
-    Changed: Editor locking now uses the InputLockManager.
-
-1.0.16.4, 01-05-2015
-    Fixed: Physically insignificant part mass is now accounted for.
-    Changed: Module mass accounted for as it now makes its way onto the launch pad (e.g. fairings).
-
-    Various optimisations:
-        Object pooling.
-        Removed LINQ expressions.
-        Converted foreach to for loops.
-
-1.0.16.3, 27-04-2015
-    Fixed issue with the toolbar icons not being created.
-    Removed superfluous 'm/s' on the mach slider in the build engineer.
-
-1.0.16.2, 27-04-2015
-    Changed the atmospheric slider on the build engineer to default to 0km when changing bodies.
-
-1.0.16.1, 26-04-2015, KSP Build #828
-    Merged Sarbian's mach adjustments.
-    Fixed bugs relating to thrust and atmosphere/velocity curves.
-    Changed the atmospheric slider on the Build Engineer to work based on altitude.
-    Changed the atmospheric slider to clamp to the maximum altitude for the selected body.
-    Changed the velocity slider to clamp to the maximum usable mach value for the current vessel.
-
-1.0.16.0, 25-04-2015, KSP Build #821
-    Fixed errors relating to KSP 1.0 update.
-    Fixed fuel simulation to account for new thrust system.
-    Fixed atmospheric engines to use the new velocity curve.
-    Fixed atmospheric readouts to work with the new atmospheric model.
-
 1.0.15.2, 13-02-2015
     Padishar's Fixes:
         Fixed: Calculation of per-stage resource mass.

--- a/KerbalEngineer/CelestialBodies.cs
+++ b/KerbalEngineer/CelestialBodies.cs
@@ -17,12 +17,16 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
+#region Using Directives
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+#endregion
+
 namespace KerbalEngineer
 {
-    using System;
-    using System.Collections.Generic;
-    using System.Linq;
-
     /*
      * 
      * With thanks to Nathaniel R. Lewis (aka. Teknoman117) (linux.robotdude@gmail.com) for working out
@@ -32,6 +36,8 @@
 
     public static class CelestialBodies
     {
+        #region Constructors
+
         static CelestialBodies()
         {
             try
@@ -49,8 +55,16 @@
             }
         }
 
+        #endregion
+
+        #region Properties
+
         public static BodyInfo SelectedBody { get; private set; }
         public static BodyInfo SystemBody { get; private set; }
+
+        #endregion
+
+        #region Public Methods
 
         /// <summary>
         ///     Gets a body given a supplied body name.
@@ -75,7 +89,7 @@
         {
             try
             {
-                BodyInfo body = GetBodyInfo(bodyName);
+                var body = GetBodyInfo(bodyName);
                 if (body != null)
                 {
                     if (SelectedBody != null)
@@ -94,26 +108,34 @@
             return false;
         }
 
+        #endregion
+
+        #region Nested type: BodyInfo
+
         public class BodyInfo
         {
+            #region Constructors
+
             public BodyInfo(CelestialBody body, BodyInfo parent = null)
             {
                 try
                 {
                     // Set the body information.
-                    CelestialBody = body;
-                    Name = body.bodyName;
-                    Gravity = 9.81 * body.GeeASL;
-                    Parent = parent;
+                    this.CelestialBody = body;
+                    this.Name = body.bodyName;
+                    this.Gravity = 9.81 * body.GeeASL;
+                    //this.Atmosphere = body.atmosphere ? body.GetPressure(0) : 0;
+                    this.Atmosphere = body.atmosphere ? body.atmospherePressureSeaLevel : 0;   // Check that one because I did not. S
+                    this.Parent = parent; 
 
                     // Set orbiting bodies information.
-                    Children = new List<BodyInfo>();
-                    foreach (CelestialBody orbitingBody in body.orbitingBodies)
-                    {
-                        Children.Add(new BodyInfo(orbitingBody, this));
-                    }
-
-                    SelectedDepth = 0;
+                    this.Children = new List<BodyInfo>();
+                    foreach (var orbitingBody in body.orbitingBodies)
+                    {
+                        this.Children.Add(new BodyInfo(orbitingBody, this));
+                    }
+
+                    this.SelectedDepth = 0;
                 }
                 catch (Exception ex)
                 {
@@ -121,28 +143,37 @@
                 }
             }
 
+            #endregion
+
+            #region Properties
+
+            public string Name { get; private set; }
+            public double Gravity { get; private set; }
+            public double Atmosphere { get; private set; }
+            public BodyInfo Parent { get; private set; }
+            public List<BodyInfo> Children { get; private set; }
             public CelestialBody CelestialBody { get; private set; }
-            public List<BodyInfo> Children { get; private set; }
-            public double Gravity { get; private set; }
-            public string Name { get; private set; }
-            public BodyInfo Parent { get; private set; }
             public bool Selected { get; private set; }
             public int SelectedDepth { get; private set; }
 
+            #endregion
+
+            #region Public Methods
+
             public BodyInfo GetBodyInfo(string bodyName)
             {
                 try
                 {
                     // This is the searched body.
-                    if (String.Equals(Name, bodyName, StringComparison.CurrentCultureIgnoreCase))
+                    if (String.Equals(this.Name, bodyName, StringComparison.CurrentCultureIgnoreCase))
                     {
                         return this;
                     }
 
                     // Check to see if any of this bodies children are the searched body.
-                    foreach (BodyInfo child in Children)
-                    {
-                        BodyInfo body = child.GetBodyInfo(bodyName);
+                    foreach (var child in this.Children)
+                    {
+                        var body = child.GetBodyInfo(bodyName);
                         if (body != null)
                         {
                             return body;
@@ -158,44 +189,33 @@
                 return null;
             }
 
-            public double GetDensity(double altitude)
-            {
-                return CelestialBody.GetDensity(GetPressure(altitude), GetTemperature(altitude));
-            }
-
-            public double GetPressure(double altitude)
-            {
-                return CelestialBody.GetPressure(altitude);
-            }
-
-            public double GetTemperature(double altitude)
-            {
-                return CelestialBody.GetTemperature(altitude);
-            }
-
-            public double GetAtmospheres(double altitude)
-            {
-                return GetPressure(altitude) * PhysicsGlobals.KpaToAtmospheres;
-            }
-
             public void SetSelected(bool state, int depth = 0)
             {
-                Selected = state;
-                SelectedDepth = depth;
-                if (Parent != null)
-                {
-                    Parent.SetSelected(state, depth + 1);
-                }
-            }
+                this.Selected = state;
+                this.SelectedDepth = depth;
+                if (this.Parent != null)
+                {
+                    this.Parent.SetSelected(state, depth + 1);
+                }
+            }
+
+            #endregion
+
+            #region Debugging
 
             public override string ToString()
             {
-                string log = "\n" + Name +
-                             "\n\tGravity: " + Gravity +
-                             "\n\tSelected: " + Selected;
-
-                return Children.Aggregate(log, (current, child) => current + "\n" + child);
-            }
-        }
+                var log = "\n" + this.Name +
+                          "\n\tGravity: " + this.Gravity +
+                          "\n\tAtmosphere: " + this.Atmosphere +
+                          "\n\tSelected: " + this.Selected;
+
+                return this.Children.Aggregate(log, (current, child) => current + "\n" + child);
+            }
+
+            #endregion
+        }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -20,7 +20,9 @@
 namespace KerbalEngineer.Editor
 {
     #region Using Directives
+
     using System;
+    using System.Linq;
     using Extensions;
     using Flight;
     using Helpers;
@@ -35,10 +37,10 @@
     public class BuildAdvanced : MonoBehaviour
     {
         #region Fields
-        public static float Altitude = 0.0f;
 
         private GUIStyle areaSettingStyle;
         private GUIStyle areaStyle;
+        private float atmosphericPercentage = 1.0f;
         private float atmosphericMach;
         private GUIStyle bodiesButtonActiveStyle;
         private GUIStyle bodiesButtonStyle;
@@ -52,7 +54,6 @@
         private bool hasChanged;
         private GUIStyle infoStyle;
         private bool isEditorLocked;
-        private float maxMach;
         private int numberOfStages;
         private Rect position = new Rect(265.0f, 45.0f, 0, 0);
         private GUIStyle settingAtmoStyle;
@@ -64,9 +65,11 @@
         private GUIStyle titleStyle;
         private bool visible = true;
         private GUIStyle windowStyle;
+
         #endregion
 
         #region Properties
+
         /// <summary>
         ///     Gets the current instance if started or returns null.
         /// </summary>
@@ -77,14 +80,8 @@
         /// </summary>
         public bool CompactMode
         {
-            get
-            {
-                return compactMode;
-            }
-            set
-            {
-                compactMode = value;
-            }
+            get { return this.compactMode; }
+            set { this.compactMode = value; }
         }
 
         /// <summary>
@@ -92,14 +89,8 @@
         /// </summary>
         public bool ShowAllStages
         {
-            get
-            {
-                return showAllStages;
-            }
-            set
-            {
-                showAllStages = value;
-            }
+            get { return this.showAllStages; }
+            set { this.showAllStages = value; }
         }
 
         /// <summary>
@@ -107,14 +98,8 @@
         /// </summary>
         public bool ShowAtmosphericDetails
         {
-            get
-            {
-                return showAtmosphericDetails;
-            }
-            set
-            {
-                showAtmosphericDetails = value;
-            }
+            get { return this.showAtmosphericDetails; }
+            set { this.showAtmosphericDetails = value; }
         }
 
         /// <summary>
@@ -122,14 +107,8 @@
         /// </summary>
         public bool ShowSettings
         {
-            get
-            {
-                return showSettings;
-            }
-            set
-            {
-                showSettings = value;
-            }
+            get { return this.showSettings; }
+            set { this.showSettings = value; }
         }
 
         /// <summary>
@@ -137,40 +116,30 @@
         /// </summary>
         public bool Visible
         {
-            get
-            {
-                return visible;
-            }
-            set
-            {
-                visible = value;
-            }
-        }
+            get { return this.visible; }
+            set { this.visible = value; }
+        }
+
         #endregion
 
         #region Methods
-        private static Rect compactModeRect = new Rect(0.0f, 5.0f, 0.0f, 20.0f);
-        private static Stage stage;
-        private static int stagesCount;
-        private static int stagesLength;
-        private static string title;
 
         protected void Awake()
         {
             try
             {
                 Instance = this;
-                bodiesList = gameObject.AddComponent<DropDown>();
-                bodiesList.DrawCallback = DrawBodiesList;
-                Load();
+                this.bodiesList = this.gameObject.AddComponent<DropDown>();
+                this.bodiesList.DrawCallback = this.DrawBodiesList;
+                this.Load();
 
                 SimManager.UpdateModSettings();
-                SimManager.OnReady -= GetStageInfo;
-                SimManager.OnReady += GetStageInfo;
+                SimManager.OnReady -= this.GetStageInfo;
+                SimManager.OnReady += this.GetStageInfo;
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced.Awake()");
+                Logger.Exception(ex);
             }
         }
 
@@ -181,22 +150,22 @@
         {
             try
             {
-                SettingHandler handler = new SettingHandler();
-                handler.Set("visible", visible);
-                handler.Set("windowPositionX", position.x);
-                handler.Set("windowPositionY", position.y);
-                handler.Set("compactMode", compactMode);
-                handler.Set("compactCollapseRight", compactCollapseRight);
-                handler.Set("showAllStages", showAllStages);
-                handler.Set("showAtmosphericDetails", showAtmosphericDetails);
-                handler.Set("showSettings", showSettings);
+                var handler = new SettingHandler();
+                handler.Set("visible", this.visible);
+                handler.Set("windowPositionX", this.position.x);
+                handler.Set("windowPositionY", this.position.y);
+                handler.Set("compactMode", this.compactMode);
+                handler.Set("compactCollapseRight", this.compactCollapseRight);
+                handler.Set("showAllStages", this.showAllStages);
+                handler.Set("showAtmosphericDetails", this.showAtmosphericDetails);
+                handler.Set("showSettings", this.showSettings);
                 handler.Set("selectedBodyName", CelestialBodies.SelectedBody.Name);
                 handler.Save("BuildAdvanced.xml");
-                GuiDisplaySize.OnSizeChanged -= OnSizeChanged;
+                GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged;
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced.OnDestroy()");
+                Logger.Exception(ex);
             }
         }
 
@@ -204,120 +173,104 @@
         {
             try
             {
-                if (!visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
+                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
                 {
                     return;
                 }
 
-                if (stages == null)
+                if (this.stages == null)
                 {
                     return;
                 }
 
                 // Change the window title based on whether in compact mode or not.
-                title = !compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion + (showAtmosphericDetails ? " (ATMOS.)" : String.Empty);
+                var title = !this.compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion + (this.showAtmosphericDetails ? " (ATMOS.)" : String.Empty);
 
                 // Reset the window size when the staging or something else has changed.
-                stagesLength = stages.Length;
-                if (showAllStages)
-                {
-                    stagesCount = stagesLength;
-                }
-                if (showAllStages == false)
-                {
-                    stagesCount = 0;
-                    for (int i = 0; i < stagesLength; ++i)
+                var stageCount = this.stages.Count(stage => this.showAllStages || stage.deltaV > 0);
+                if (this.hasChanged || stageCount != this.numberOfStages)
+                {
+                    this.hasChanged = false;
+                    this.numberOfStages = stageCount;
+
+                    this.position.width = 0;
+                    this.position.height = 0;
+                }
+
+                GUI.skin = null;
+                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen();
+
+                if (this.compactCheck > 0 && this.compactCollapseRight)
+                {
+                    this.position.x = this.compactRight - this.position.width;
+                    this.compactCheck--;
+                }
+                else if (this.compactCheck > 0)
+                {
+                    this.compactCheck = 0;
+                }
+
+                // Check editor lock to manage click-through.
+                this.CheckEditorLock();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        protected void Start()
+        {
+            try
+            {
+                this.InitialiseStyles();
+                GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        protected void Update()
+        {
+            try
+            {
+                if (Input.GetKeyDown(KeyBinder.EditorShowHide))
+                {
+                    this.visible = !this.visible;
+                    if (!this.visible)
                     {
-                        if (stages[i].deltaV > 0.0f)
-                        {
-                            stagesCount = stagesCount + 1;
-                        }
+                        this.EditorLock(false);
                     }
                 }
 
-                if (hasChanged || stagesCount != numberOfStages)
-                {
-                    hasChanged = false;
-                    numberOfStages = stagesCount;
-
-                    position.width = 0;
-                    position.height = 0;
-                }
-
-                GUI.skin = null;
-                position = GUILayout.Window(GetInstanceID(), position, Window, title, windowStyle).ClampToScreen();
-
-                if (compactCheck > 0 && compactCollapseRight)
-                {
-                    position.x = compactRight - position.width;
-                    compactCheck--;
-                }
-                else if (compactCheck > 0)
-                {
-                    compactCheck = 0;
-                }
-
-                // Check editor lock to manage click-through.
-                CheckEditorLock();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced.OnGUI()");
-            }
-        }
-
-        protected void Start()
-        {
-            try
-            {
-                InitialiseStyles();
-                GuiDisplaySize.OnSizeChanged += OnSizeChanged;
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced.Start()");
-            }
-        }
-
-        protected void Update()
-        {
-            try
-            {
-                if (Input.GetKeyDown(KeyBinder.EditorShowHide))
-                {
-                    visible = !visible;
-                    if (!visible)
-                    {
-                        EditorLock(false);
-                    }
-                }
-
-                if (!visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
-                {
-                    bodiesList.enabled = false;
+                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
+                {
+                    this.bodiesList.enabled = false;
                     return;
                 }
 
                 // Configure the simulation parameters based on the selected reference body.
                 SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
 
-                if (showAtmosphericDetails)
-                {
-                    SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(Altitude);
+                if (this.showAtmosphericDetails)
+                {
+                    SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage;
                 }
                 else
                 {
                     SimManager.Atmosphere = 0;
                 }
 
-                SimManager.Mach = atmosphericMach;
+                SimManager.Mach = this.atmosphericMach;
 
                 SimManager.RequestSimulation();
                 SimManager.TryStartSimulation();
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced.Update()");
+                Logger.Exception(ex, "BuildAdvanced->Update");
             }
         }
 
@@ -326,13 +279,13 @@
         /// </summary>
         private void CheckEditorLock()
         {
-            if ((position.MouseIsOver() || bodiesList.Position.MouseIsOver()) && !isEditorLocked)
-            {
-                EditorLock(true);
-            }
-            else if (!position.MouseIsOver() && !bodiesList.Position.MouseIsOver() && isEditorLocked)
-            {
-                EditorLock(false);
+            if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && !this.isEditorLocked)
+            {
+                this.EditorLock(true);
+            }
+            else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked)
+            {
+                this.EditorLock(false);
             }
         }
 
@@ -341,43 +294,36 @@
         /// </summary>
         private void DrawAtmosphericDetails()
         {
-            try
-            {
-                GUILayout.BeginHorizontal();
-                GUILayout.BeginVertical();
-                GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
-                GUI.skin = HighLogic.Skin;
-                Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth));
-                GUI.skin = null;
-                GUILayout.EndVertical();
-
-                GUILayout.Space(5.0f);
-
-                GUILayout.BeginVertical();
-                GUILayout.Label("Mach: " + atmosphericMach.ToString("F1"), settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
-                GUI.skin = HighLogic.Skin;
-                atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, maxMach), 0.0f, maxMach);
-                GUI.skin = null;
-                GUILayout.EndVertical();
-                GUILayout.EndHorizontal();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced.DrawAtmosphericDetails()");
-            }
+            GUILayout.BeginHorizontal();
+            GUILayout.BeginVertical();
+            GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+            GUI.skin = HighLogic.Skin;
+            this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f);
+            GUI.skin = null;
+            GUILayout.EndVertical();
+
+            GUILayout.Space(5.0f);
+
+            GUILayout.BeginVertical();
+            GUILayout.Label("Mach: " + this.atmosphericMach.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+            GUI.skin = HighLogic.Skin;
+            this.atmosphericMach = GUILayout.HorizontalSlider(this.atmosphericMach, 0, 25f); // the game limits mach to 50 but I did not see curve with more than 25
+            GUI.skin = null;
+            GUILayout.EndVertical();
+            GUILayout.EndHorizontal();
         }
 
         private void DrawBodiesList()
         {
             if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody)
             {
-                DrawBody(CelestialBodies.SystemBody);
+                this.DrawBody(CelestialBodies.SystemBody);
             }
             else
             {
-                foreach (CelestialBodies.BodyInfo body in CelestialBodies.SystemBody.Children)
-                {
-                    DrawBody(body);
+                foreach (var body in CelestialBodies.SystemBody.Children)
+                {
+                    this.DrawBody(body);
                 }
             }
         }
@@ -386,19 +332,18 @@
         {
             GUILayout.BeginHorizontal();
             GUILayout.Space(20.0f * depth);
-            if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? bodiesButtonActiveStyle : bodiesButtonStyle))
+            if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? this.bodiesButtonActiveStyle : this.bodiesButtonStyle))
             {
                 CelestialBodies.SetSelectedBody(bodyInfo.Name);
-                Altitude = 0.0f;
-                bodiesList.Resize = true;
+                this.bodiesList.Resize = true;
             }
             GUILayout.EndHorizontal();
 
             if (bodyInfo.Selected)
             {
-                for (int i = 0; i < bodyInfo.Children.Count; ++i)
-                {
-                    DrawBody(bodyInfo.Children[i], depth + 1);
+                foreach (var body in bodyInfo.Children)
+                {
+                    this.DrawBody(body, depth + 1);
                 }
             }
         }
@@ -409,13 +354,12 @@
         private void DrawBurnTime()
         {
             GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("BURN", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(TimeFormatter.ConvertToString(stage.time), infoStyle);
+            GUILayout.Label("BURN", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(TimeFormatter.ConvertToString(stage.time), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -427,13 +371,12 @@
         private void DrawCost()
         {
             GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("COST", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), infoStyle);
+            GUILayout.Label("COST", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -445,13 +388,12 @@
         private void DrawDeltaV()
         {
             GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("DELTA-V", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", infoStyle);
+            GUILayout.Label("DELTA-V", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -463,13 +405,12 @@
         private void DrawIsp()
         {
             GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("ISP", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(stage.isp.ToString("F1") + "s", infoStyle);
+            GUILayout.Label("ISP", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -481,13 +422,12 @@
         private void DrawMass()
         {
             GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("MASS", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), infoStyle);
+            GUILayout.Label("MASS", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -499,13 +439,12 @@
         private void DrawPartCount()
         {
             GUILayout.BeginVertical(GUILayout.Width(50.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("PARTS", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, infoStyle);
+            GUILayout.Label("PARTS", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -517,48 +456,48 @@
         private void DrawSettings()
         {
             GUILayout.BeginHorizontal();
-            GUILayout.Label("Compact mode collapses to the:", settingStyle);
-            compactCollapseRight = !GUILayout.Toggle(!compactCollapseRight, "LEFT", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            compactCollapseRight = GUILayout.Toggle(compactCollapseRight, "RIGHT", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("Compact mode collapses to the:", this.settingStyle);
+            this.compactCollapseRight = !GUILayout.Toggle(!this.compactCollapseRight, "LEFT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            this.compactCollapseRight = GUILayout.Toggle(this.compactCollapseRight, "RIGHT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
             GUILayout.Label("Simulate using vectored thrust values:");
-            SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
-            GUILayout.Label("Build Engineer Overlay:", settingStyle);
-            BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("Build Engineer Overlay:", this.settingStyle);
+            BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
-            GUILayout.Label("Flight Engineer activation mode:", settingStyle);
-            FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("Flight Engineer activation mode:", this.settingStyle);
+            FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
-            GUILayout.Label("Flight Engineer Career Limitations:", settingStyle);
-            FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("Flight Engineer Career Limitations:", this.settingStyle);
+            FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
-            GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, settingStyle);
-            if (GUILayout.Button("<", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
+            GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, this.settingStyle);
+            if (GUILayout.Button("<", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
             {
                 GuiDisplaySize.Increment--;
             }
-            if (GUILayout.Button(">", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
+            if (GUILayout.Button(">", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
             {
                 GuiDisplaySize.Increment++;
             }
             GUILayout.EndHorizontal();
 
-            GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.Milliseconds + "ms", settingStyle);
+            GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.Milliseconds + "ms", this.settingStyle);
             GUI.skin = HighLogic.Skin;
             SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 2000.0f));
             GUI.skin = null;
@@ -570,13 +509,12 @@
         private void DrawStageNumbers()
         {
             GUILayout.BeginVertical(GUILayout.Width(30.0f * GuiDisplaySize.Offset));
-            GUILayout.Label(string.Empty, titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label("S" + stage.number, titleStyle);
+            GUILayout.Label(string.Empty, this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label("S" + stage.number, this.titleStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -588,13 +526,12 @@
         private void DrawThrust()
         {
             GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("THRUST", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(stage.thrust.ToForce(), infoStyle);
+            GUILayout.Label("THRUST", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.thrust.ToForce(), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -606,13 +543,12 @@
         private void DrawTorque()
         {
             GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("TORQUE", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(stage.maxThrustTorque.ToTorque(), infoStyle);
+            GUILayout.Label("TORQUE", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.maxThrustTorque.ToTorque(), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -624,13 +560,12 @@
         private void DrawTwr()
         {
             GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            GUILayout.Label("TWR (MAX)", titleStyle);
-            for (int i = 0; i < stagesLength; ++i)
-            {
-                stage = stages[i];
-                if (showAllStages || stage.deltaV > 0.0)
-                {
-                    GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", infoStyle);
+            GUILayout.Label("TWR (MAX)", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -640,25 +575,21 @@
         {
             if (state)
             {
-                InputLockManager.SetControlLock(ControlTypes.All, "KER_BuildAdvanced");
+                EditorLogic.fetch.Lock(true, true, true, "KER_BuildAdvanced");
                 BuildOverlayPartInfo.Hidden = true;
-                isEditorLocked = true;
+                this.isEditorLocked = true;
             }
             else
             {
-                InputLockManager.SetControlLock(ControlTypes.None, "KER_BuildAdvanced");
+                EditorLogic.fetch.Unlock("KER_BuildAdvanced");
                 BuildOverlayPartInfo.Hidden = false;
-                isEditorLocked = false;
+                this.isEditorLocked = false;
             }
         }
 
         private void GetStageInfo()
         {
-            stages = SimManager.Stages;
-            if (stages != null && stages.Length > 0)
-            {
-                maxMach = stages[stages.Length - 1].maxMach;
-            }
+            this.stages = SimManager.Stages;
         }
 
         /// <summary>
@@ -666,22 +597,22 @@
         /// </summary>
         private void InitialiseStyles()
         {
-            windowStyle = new GUIStyle(HighLogic.Skin.window)
+            this.windowStyle = new GUIStyle(HighLogic.Skin.window)
             {
                 alignment = TextAnchor.UpperLeft
             };
 
-            areaStyle = new GUIStyle(HighLogic.Skin.box)
+            this.areaStyle = new GUIStyle(HighLogic.Skin.box)
             {
                 padding = new RectOffset(0, 0, 9, 0)
             };
 
-            areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
+            this.areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
             {
                 padding = new RectOffset(10, 10, 10, 10)
             };
 
-            buttonStyle = new GUIStyle(HighLogic.Skin.button)
+            this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
             {
                 normal =
                 {
@@ -692,7 +623,7 @@
                 alignment = TextAnchor.MiddleCenter
             };
 
-            titleStyle = new GUIStyle(HighLogic.Skin.label)
+            this.titleStyle = new GUIStyle(HighLogic.Skin.label)
             {
                 normal =
                 {
@@ -704,7 +635,7 @@
                 stretchWidth = true,
             };
 
-            infoStyle = new GUIStyle(HighLogic.Skin.label)
+            this.infoStyle = new GUIStyle(HighLogic.Skin.label)
             {
                 fontSize = (int)(11 * GuiDisplaySize.Offset),
                 fontStyle = FontStyle.Bold,
@@ -712,21 +643,21 @@
                 stretchWidth = true
             };
 
-            settingStyle = new GUIStyle(titleStyle)
+            this.settingStyle = new GUIStyle(this.titleStyle)
             {
                 alignment = TextAnchor.MiddleLeft,
                 stretchWidth = true,
                 stretchHeight = true
             };
 
-            settingAtmoStyle = new GUIStyle(titleStyle)
+            this.settingAtmoStyle = new GUIStyle(this.titleStyle)
             {
                 margin = new RectOffset(),
                 padding = new RectOffset(),
                 alignment = TextAnchor.UpperLeft
             };
 
-            bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
+            this.bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
             {
                 margin = new RectOffset(0, 0, 2, 0),
                 padding = new RectOffset(5, 5, 5, 5),
@@ -744,10 +675,10 @@
                 fixedHeight = 20.0f
             };
 
-            bodiesButtonActiveStyle = new GUIStyle(bodiesButtonStyle)
-            {
-                normal = bodiesButtonStyle.onNormal,
-                hover = bodiesButtonStyle.onHover
+            this.bodiesButtonActiveStyle = new GUIStyle(this.bodiesButtonStyle)
+            {
+                normal = this.bodiesButtonStyle.onNormal,
+                hover = this.bodiesButtonStyle.onHover
             };
         }
 
@@ -758,27 +689,27 @@
         {
             try
             {
-                SettingHandler handler = SettingHandler.Load("BuildAdvanced.xml");
-                handler.Get("visible", ref visible);
-                position.x = handler.Get("windowPositionX", position.x);
-                position.y = handler.Get("windowPositionY", position.y);
-                handler.Get("compactMode", ref compactMode);
-                handler.Get("compactCollapseRight", ref compactCollapseRight);
-                handler.Get("showAllStages", ref showAllStages);
-                handler.Get("showAtmosphericDetails", ref showAtmosphericDetails);
-                handler.Get("showSettings", ref showSettings);
+                var handler = SettingHandler.Load("BuildAdvanced.xml");
+                handler.Get("visible", ref this.visible);
+                this.position.x = handler.Get("windowPositionX", this.position.x);
+                this.position.y = handler.Get("windowPositionY", this.position.y);
+                handler.Get("compactMode", ref this.compactMode);
+                handler.Get("compactCollapseRight", ref this.compactCollapseRight);
+                handler.Get("showAllStages", ref this.showAllStages);
+                handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails);
+                handler.Get("showSettings", ref this.showSettings);
                 CelestialBodies.SetSelectedBody(handler.Get("selectedBodyName", CelestialBodies.SelectedBody.Name));
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced.Load()");
+                Logger.Exception(ex, "BuildAdvanced->Load");
             }
         }
 
         private void OnSizeChanged()
         {
-            InitialiseStyles();
-            hasChanged = true;
+            this.InitialiseStyles();
+            this.hasChanged = true;
         }
 
         /// <summary>
@@ -788,79 +719,77 @@
         {
             try
             {
-                compactModeRect = new Rect(position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f);
-
                 // Draw the compact mode toggle.
-                if (GUI.Toggle(compactModeRect, compactMode, "COMPACT", buttonStyle) != compactMode)
-                {
-                    hasChanged = true;
-                    compactCheck = 2;
-                    compactRight = position.xMax;
-                    compactMode = !compactMode;
+                if (GUI.Toggle(new Rect(this.position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f), this.compactMode, "COMPACT", this.buttonStyle) != this.compactMode)
+                {
+                    this.hasChanged = true;
+                    this.compactCheck = 2;
+                    this.compactRight = this.position.xMax;
+                    this.compactMode = !this.compactMode;
                 }
 
                 // When not in compact mode draw the 'All Stages' and 'Atmospheric' toggles.
-                if (!compactMode)
-                {
-                    if (GUI.Toggle(new Rect(position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), showSettings, "SETTINGS", buttonStyle) != showSettings)
+                if (!this.compactMode)
+                {
+                    if (GUI.Toggle(new Rect(this.position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), this.showSettings, "SETTINGS", this.buttonStyle) != this.showSettings)
                     {
-                        hasChanged = true;
-                        showSettings = !showSettings;
+                        this.hasChanged = true;
+                        this.showSettings = !this.showSettings;
                     }
 
-                    if (GUI.Toggle(new Rect(position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), showAllStages, "ALL STAGES", buttonStyle) != showAllStages)
+                    if (GUI.Toggle(new Rect(this.position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), this.showAllStages, "ALL STAGES", this.buttonStyle) != this.showAllStages)
                     {
-                        hasChanged = true;
-                        showAllStages = !showAllStages;
+                        this.hasChanged = true;
+                        this.showAllStages = !this.showAllStages;
                     }
 
-                    if (GUI.Toggle(new Rect(position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), showAtmosphericDetails, "ATMOSPHERIC", buttonStyle) != showAtmosphericDetails)
+                    if (GUI.Toggle(new Rect(this.position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), this.showAtmosphericDetails, "ATMOSPHERIC", this.buttonStyle) != this.showAtmosphericDetails)
                     {
-                        hasChanged = true;
-                        showAtmosphericDetails = !showAtmosphericDetails;
+                        this.hasChanged = true;
+                        this.showAtmosphericDetails = !this.showAtmosphericDetails;
                     }
 
-                    bodiesListPosition = new Rect(position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
-                    bodiesList.enabled = GUI.Toggle(bodiesListPosition, bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), buttonStyle);
-                    bodiesList.SetPosition(bodiesListPosition.Translate(position));
+                    this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
+                    this.bodiesList.enabled = GUI.Toggle(this.bodiesListPosition, this.bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), this.buttonStyle);
+                    this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position));
                 }
 
                 // Draw the main informational display box.
-                if (!compactMode)
-                {
-                    GUILayout.BeginHorizontal(areaStyle);
-                    DrawStageNumbers();
-                    DrawPartCount();
-                    DrawCost();
-                    DrawMass();
-                    DrawIsp();
-                    DrawThrust();
-                    DrawTorque();
-                    DrawTwr();
-                    DrawDeltaV();
-                    DrawBurnTime();
+                if (!this.compactMode)
+                {
+                    GUILayout.BeginHorizontal(this.areaStyle);
+                    this.DrawStageNumbers();
+                    this.DrawPartCount();
+                    this.DrawCost();
+                    this.DrawMass();
+                    this.DrawIsp();
+                    this.DrawThrust();
+                    this.DrawTorque();
+                    this.DrawTwr();
+                    this.DrawDeltaV();
+                    this.DrawBurnTime();
                     GUILayout.EndHorizontal();
 
-                    if (showAtmosphericDetails)
+                    if (this.showAtmosphericDetails)
                     {
-                        GUILayout.BeginVertical(areaSettingStyle);
-                        DrawAtmosphericDetails();
+                        GUILayout.BeginVertical(this.areaSettingStyle);
+                        this.DrawAtmosphericDetails();
                         GUILayout.EndVertical();
                     }
 
-                    if (showSettings)
+                    if (this.showSettings)
                     {
-                        GUILayout.BeginVertical(areaSettingStyle);
-                        DrawSettings();
+                        GUILayout.BeginVertical(this.areaSettingStyle);
+                        this.DrawSettings();
                         GUILayout.EndVertical();
                     }
                 }
                 else // Draw only a few details when in compact mode.
                 {
-                    GUILayout.BeginHorizontal(areaStyle);
-                    DrawStageNumbers();
-                    DrawTwr();
-                    DrawDeltaV();
+                    GUILayout.BeginHorizontal(this.areaStyle);
+                    this.DrawStageNumbers();
+                    this.DrawTwr();
+                    this.DrawDeltaV();
                     GUILayout.EndHorizontal();
                 }
 
@@ -868,9 +797,10 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced.Window()");
-            }
-        }
+                Logger.Exception(ex);
+            }
+        }
+
         #endregion
     }
 }

--- a/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
+++ b/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
@@ -17,35 +17,27 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
+#region Using Directives
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
+
+using UnityEngine;
+
+#endregion
+
 namespace KerbalEngineer.Editor
 {
-    using System;
-    using System.Collections.Generic;
-    using Extensions;
-    using Helpers;
-    using UnityEngine;
-
     public class BuildOverlayPartInfo : MonoBehaviour
     {
+        #region Fields
+
         private static bool clickToOpen = true;
-        private static ModuleGenerator.GeneratorResource generatorResource;
-        private static ModuleAlternator moduleAlternator;
-        private static ModuleDataTransmitter moduleDataTransmitter;
-        private static ModuleDeployableSolarPanel moduleDeployableSolarPanel;
-        private static ModuleGenerator moduleGenerator;
-        private static ModuleGimbal moduleGimbal;
-        private static ModuleParachute moduleParachute;
-        private static ModuleRCS moduleRcs;
-        private static ModuleReactionWheel moduleReactionWheel;
-        private static ModuleResource moduleResource;
-        private static ModuleScienceExperiment moduleScienceExperiment;
         private static bool namesOnly;
-        private static Part part;
-        private static PartInfoItem partInfoItem;
-        private static PartResource partResource;
-        private static Propellant propellant;
-        private static PartExtensions.ProtoModuleDecoupler protoModuleDecoupler;
-        private static PartExtensions.ProtoModuleEngine protoModuleEngine;
         private static bool visible = true;
 
         private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
@@ -55,54 +47,44 @@
         private bool showInfo;
         private bool skipFrame;
 
+        #endregion
+
+        #region Properties
+
         public static bool ClickToOpen
         {
-            get
-            {
-                return clickToOpen;
-            }
-            set
-            {
-                clickToOpen = value;
-            }
+            get { return clickToOpen; }
+            set { clickToOpen = value; }
         }
 
         public static bool Hidden { get; set; }
 
         public static bool NamesOnly
         {
-            get
-            {
-                return namesOnly;
-            }
-            set
-            {
-                namesOnly = value;
-            }
+            get { return namesOnly; }
+            set { namesOnly = value; }
         }
 
         public static bool Visible
         {
-            get
-            {
-                return visible;
-            }
-            set
-            {
-                visible = value;
-            }
-        }
+            get { return visible; }
+            set { visible = value; }
+        }
+
+        #endregion
+
+        #region Methods: protected
 
         protected void OnGUI()
         {
             try
             {
-                if (!Visible || Hidden || selectedPart == null)
+                if (!Visible || Hidden || this.selectedPart == null)
                 {
                     return;
                 }
 
-                position = GUILayout.Window(GetInstanceID(), position, Window, String.Empty, BuildOverlay.WindowStyle);
+                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, BuildOverlay.WindowStyle);
             }
             catch (Exception ex)
 
@@ -120,345 +102,341 @@
                     return;
                 }
 
-                position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - position.width);
-                position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - position.height);
-                if (position.x < Input.mousePosition.x + 20.0f)
-                {
-                    position.y = Mathf.Clamp(position.y + 20.0f, 0.0f, Screen.height - position.height);
-                }
-                if (position.x < Input.mousePosition.x + 16.0f && position.y < Screen.height - Input.mousePosition.y)
-                {
-                    position.x = Input.mousePosition.x - 3 - position.width;
-                }
-
-                part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
+                this.position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - this.position.width);
+                this.position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - this.position.height);
+                if (this.position.x < Input.mousePosition.x + 20.0f)
+                {
+                    this.position.y = Mathf.Clamp(this.position.y + 20.0f, 0.0f, Screen.height - this.position.height);
+                }
+                if (this.position.x < Input.mousePosition.x + 16.0f && this.position.y < Screen.height - Input.mousePosition.y)
+                {
+                    this.position.x = Input.mousePosition.x - 3 - this.position.width;
+                }
+
+                this.infoItems.Clear();
+                var part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
                 if (part != null)
                 {
-                    if (!part.Equals(selectedPart))
+                    if (!part.Equals(this.selectedPart))
                     {
-                        selectedPart = part;
-                        ResetInfo();
+                        this.selectedPart = part;
+                        this.ResetInfo();
                     }
-                    if (NamesOnly || skipFrame)
+                    if (NamesOnly || this.skipFrame)
                     {
-                        skipFrame = false;
+                        this.skipFrame = false;
                         return;
                     }
 
-                    if (!showInfo && Input.GetMouseButtonDown(2))
+                    this.SetCostInfo();
+                    this.SetMassItems();
+                    this.SetResourceItems();
+                    this.SetEngineInfo();
+                    this.SetAlternatorInfo();
+                    this.SetGimbalInfo();
+                    this.SetRcsInfo();
+                    this.SetParachuteInfo();
+                    this.SetSasInfo();
+                    this.SetReactionWheelInfo();
+                    this.SetSolarPanelInfo();
+                    this.SetGeneratorInfo();
+                    this.SetDecouplerInfo();
+                    this.SetTransmitterInfo();
+                    this.SetScienceExperimentInfo();
+                    this.SetScienceContainerInfo();
+                    this.SetSingleActivationInfo();
+
+                    if (!this.showInfo && Input.GetMouseButtonDown(2))
                     {
-                        showInfo = true;
+                        this.showInfo = true;
                     }
-                    else if (ClickToOpen && showInfo && Input.GetMouseButtonDown(2))
+                    else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
                     {
-                        ResetInfo();
+                        this.ResetInfo();
                     }
-
-                    if (showInfo)
+                }
+                else
+                {
+                    this.selectedPart = null;
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+
+        #region Methods: private
+
+        private void ResetInfo()
+        {
+            this.showInfo = !clickToOpen;
+            this.skipFrame = true;
+            this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
+            this.position.height = 0.0f;
+        }
+
+        private void SetAlternatorInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleAlternator>())
+            {
+                return;
+            }
+
+            var alternator = this.selectedPart.GetModule<ModuleAlternator>();
+            this.infoItems.Add(new PartInfoItem("Alternator"));
+            foreach (var resource in alternator.outputResources)
+            {
+                this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
+            }
+        }
+
+        private void SetCostInfo()
+        {
+            this.infoItems.Add(new PartInfoItem("Cost", Units.ConcatF(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet())));
+        }
+
+        private void SetDecouplerInfo()
+        {
+            if (!this.selectedPart.IsDecoupler())
+            {
+                return;
+            }
+
+            var decoupler = this.selectedPart.GetProtoModuleDecoupler();
+            this.infoItems.Add(new PartInfoItem("Ejection Force", decoupler.EjectionForce.ToForce()));
+            if (decoupler.IsOmniDecoupler)
+            {
+                this.infoItems.Add(new PartInfoItem("Omni-directional"));
+            }
+        }
+
+        private void SetEngineInfo()
+        {
+            if (!this.selectedPart.IsEngine())
+            {
+                return;
+            }
+
+            var engine = this.selectedPart.GetProtoModuleEngine();
+            this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust)));
+            this.infoItems.Add(new PartInfoItem("Isp", Units.ConcatF(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
+            if (engine.Propellants.Count > 0)
+            {
+                this.infoItems.Add(new PartInfoItem("Propellants"));
+                var totalRatio = engine.Propellants.Sum(p => p.ratio);
+                foreach (var propellant in engine.Propellants)
+                {
+                    this.infoItems.Add(new PartInfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
+                }
+            }
+        }
+
+        private void SetGeneratorInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleGenerator>())
+            {
+                return;
+            }
+
+            var generator = this.selectedPart.GetModule<ModuleGenerator>();
+            if (generator.inputList.Count > 0)
+            {
+                this.infoItems.Add(new PartInfoItem("Generator Input"));
+                foreach (var resource in generator.inputList)
+                {
+                    this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
+                }
+            }
+            if (generator.outputList.Count > 0)
+            {
+                this.infoItems.Add(new PartInfoItem("Generator Output"));
+                foreach (var resource in generator.outputList)
+                {
+                    this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
+                }
+            }
+            if (generator.isAlwaysActive)
+            {
+                this.infoItems.Add(new PartInfoItem("Generator is Always Active"));
+            }
+        }
+
+        private void SetGimbalInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleGimbal>())
+            {
+                return;
+            }
+
+            var gimbal = this.selectedPart.GetModule<ModuleGimbal>();
+            this.infoItems.Add(new PartInfoItem("Thrust Vectoring", gimbal.gimbalRange.ToString("F2")));
+        }
+
+        private void SetMassItems()
+        {
+            if (this.selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL)
+            {
+                this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass())));
+            }
+        }
+
+        private void SetParachuteInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleParachute>())
+            {
+                return;
+            }
+
+            var parachute = this.selectedPart.GetModule<ModuleParachute>();
+            this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.ConcatF(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
+            this.infoItems.Add(new PartInfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance()));
+            this.infoItems.Add(new PartInfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2")));
+        }
+
+        private void SetRcsInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleRCS>())
+            {
+                return;
+            }
+
+            var rcs = this.selectedPart.GetModule<ModuleRCS>();
+            this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce()));
+            this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.ConcatF(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
+        }
+
+        private void SetReactionWheelInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleReactionWheel>())
+            {
+                return;
+            }
+
+            var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>();
+            this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque"));
+            this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToTorque()));
+            this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToTorque()));
+            this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToTorque()));
+            foreach (var resource in reactionWheel.inputResources)
+            {
+                this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
+            }
+        }
+
+        private void SetResourceItems()
+        {
+            if (this.selectedPart.Resources.list.Any(r => !r.hideFlow))
+            {
+                this.infoItems.Add(new PartInfoItem("Resources"));
+                foreach (var resource in this.selectedPart.Resources.list.Where(r => !r.hideFlow))
+                {
+                    this.infoItems.Add(resource.GetDensity() > 0
+                        ? new PartInfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1"))
+                        : new PartInfoItem("\t" + resource.info.name, resource.amount.ToString("F1")));
+                }
+            }
+        }
+
+        private void SetSasInfo()
+        {
+            if (this.selectedPart.HasModule<ModuleSAS>())
+            {
+                this.infoItems.Add(new PartInfoItem("SAS Equiped"));
+            }
+        }
+
+        private void SetScienceContainerInfo()
+        {
+            if (this.selectedPart.HasModule<ModuleScienceContainer>())
+            {
+                this.infoItems.Add(new PartInfoItem("Science Container"));
+            }
+        }
+
+        private void SetScienceExperimentInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleScienceExperiment>())
+            {
+                return;
+            }
+
+            var experiment = this.selectedPart.GetModule<ModuleScienceExperiment>();
+            this.infoItems.Add(new PartInfoItem("Science Experiment", experiment.experimentActionName));
+            this.infoItems.Add(new PartInfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent()));
+            if (!experiment.rerunnable)
+            {
+                this.infoItems.Add(new PartInfoItem("\tSingle Usage"));
+            }
+        }
+
+        private void SetSingleActivationInfo()
+        {
+            if (this.selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot))
+            {
+                this.infoItems.Add(new PartInfoItem("Single Activation"));
+            }
+        }
+
+        private void SetSolarPanelInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleDeployableSolarPanel>())
+            {
+                return;
+            }
+
+            var solarPanel = this.selectedPart.GetModule<ModuleDeployableSolarPanel>();
+            this.infoItems.Add(new PartInfoItem("Charge Rate", solarPanel.chargeRate.ToRate()));
+            if (solarPanel.isBreakable)
+            {
+                this.infoItems.Add(new PartInfoItem("Breakable"));
+            }
+            if (solarPanel.sunTracking)
+            {
+                this.infoItems.Add(new PartInfoItem("Sun Tracking"));
+            }
+        }
+
+        private void SetTransmitterInfo()
+        {
+            if (!this.selectedPart.HasModule<ModuleDataTransmitter>())
+            {
+                return;
+            }
+
+            var transmitter = this.selectedPart.GetModule<ModuleDataTransmitter>();
+            this.infoItems.Add(new PartInfoItem("Packet Size", transmitter.packetSize.ToString("F2") + " Mits"));
+            this.infoItems.Add(new PartInfoItem("Bandwidth", (transmitter.packetInterval * transmitter.packetSize).ToString("F2") + "Mits/sec"));
+            this.infoItems.Add(new PartInfoItem(transmitter.requiredResource, transmitter.packetResourceCost.ToString("F2") + "/Packet"));
+        }
+
+        private void Window(int windowId)
+        {
+            try
+            {
+                GUILayout.Label(this.selectedPart.partInfo.title, BuildOverlay.TitleStyle);
+                if (this.showInfo)
+                {
+                    foreach (var item in this.infoItems)
                     {
-                        PartInfoItem.Release(infoItems);
-                        infoItems.Clear();
-                        SetCostInfo();
-                        SetMassItems();
-                        SetResourceItems();
-                        SetEngineInfo();
-                        SetAlternatorInfo();
-                        SetGimbalInfo();
-                        SetRcsInfo();
-                        SetParachuteInfo();
-                        SetSasInfo();
-                        SetReactionWheelInfo();
-                        SetSolarPanelInfo();
-                        SetGeneratorInfo();
-                        SetDecouplerInfo();
-                        SetTransmitterInfo();
-                        SetScienceExperimentInfo();
-                        SetScienceContainerInfo();
-                        SetSingleActivationInfo();
-                    }
-                }
-                else
-                {
-                    selectedPart = null;
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        private void ResetInfo()
-        {
-            showInfo = !clickToOpen;
-            skipFrame = true;
-            position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
-            position.height = 0.0f;
-        }
-
-        private void SetAlternatorInfo()
-        {
-            moduleAlternator = selectedPart.GetModule<ModuleAlternator>();
-            if (moduleAlternator != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Alternator"));
-                for (int i = 0; i < moduleAlternator.outputResources.Count; ++i)
-                {
-                    moduleResource = moduleAlternator.outputResources[i];
-                    infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.rate.ToRate()));
-                }
-            }
-        }
-
-        private void SetCostInfo()
-        {
-            infoItems.Add(PartInfoItem.Create("Cost", Units.ConcatF(selectedPart.GetCostDry(), selectedPart.GetCostWet())));
-        }
-
-        private void SetDecouplerInfo()
-        {
-            protoModuleDecoupler = selectedPart.GetProtoModuleDecoupler();
-            if (protoModuleDecoupler != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Ejection Force", protoModuleDecoupler.EjectionForce.ToForce()));
-                if (protoModuleDecoupler.IsOmniDecoupler)
-                {
-                    infoItems.Add(PartInfoItem.Create("Omni-directional"));
-                }
-            }
-        }
-
-        private void SetEngineInfo()
-        {
-            protoModuleEngine = selectedPart.GetProtoModuleEngine();
-            if (protoModuleEngine != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Thrust", Units.ToForce(protoModuleEngine.MinimumThrust, protoModuleEngine.MaximumThrust)));
-                infoItems.Add(PartInfoItem.Create("Isp", Units.ConcatF(protoModuleEngine.GetSpecificImpulse(1.0f), protoModuleEngine.GetSpecificImpulse(0.0f)) + "s"));
-                if (protoModuleEngine.Propellants.Count > 0)
-                {
-                    infoItems.Add(PartInfoItem.Create("Propellants"));
-
-                    float totalRatio = 0.0f;
-                    for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i)
-                    {
-                        totalRatio = totalRatio + protoModuleEngine.Propellants[i].ratio;
-                    }
-
-                    for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i)
-                    {
-                        propellant = protoModuleEngine.Propellants[i];
-                        infoItems.Add(PartInfoItem.Create("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
-                    }
-                }
-            }
-        }
-
-        private void SetGeneratorInfo()
-        {
-            moduleGenerator = selectedPart.GetModule<ModuleGenerator>();
-            if (moduleGenerator != null)
-            {
-                if (moduleGenerator.inputList.Count > 0)
-                {
-                    infoItems.Add(PartInfoItem.Create("Generator Input"));
-                    for (int i = 0; i < moduleGenerator.inputList.Count; ++i)
-                    {
-                        generatorResource = moduleGenerator.inputList[i];
-                        infoItems.Add(PartInfoItem.Create("\t" + generatorResource.name, generatorResource.rate.ToRate()));
-                    }
-                }
-                if (moduleGenerator.outputList.Count > 0)
-                {
-                    infoItems.Add(PartInfoItem.Create("Generator Output"));
-                    for (int i = 0; i < moduleGenerator.outputList.Count; ++i)
-                    {
-                        generatorResource = moduleGenerator.outputList[i];
-                        infoItems.Add(PartInfoItem.Create("\t" + generatorResource.name, generatorResource.rate.ToRate()));
-                    }
-                }
-                if (moduleGenerator.isAlwaysActive)
-                {
-                    infoItems.Add(PartInfoItem.Create("Generator is Always Active"));
-                }
-            }
-        }
-
-        private void SetGimbalInfo()
-        {
-            moduleGimbal = selectedPart.GetModule<ModuleGimbal>();
-            if (moduleGimbal != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Thrust Vectoring", moduleGimbal.gimbalRange.ToString("F2")));
-            }
-        }
-
-        private void SetMassItems()
-        {
-            if (selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL)
-            {
-                infoItems.Add(PartInfoItem.Create("Mass", Units.ToMass(selectedPart.GetDryMass(), selectedPart.GetWetMass())));
-            }
-        }
-
-        private void SetParachuteInfo()
-        {
-            moduleParachute = selectedPart.GetModule<ModuleParachute>();
-            if (moduleParachute != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Deployed Drag", Units.ConcatF(moduleParachute.semiDeployedDrag, moduleParachute.fullyDeployedDrag)));
-                infoItems.Add(PartInfoItem.Create("Deployment Altitude", moduleParachute.deployAltitude.ToDistance()));
-                infoItems.Add(PartInfoItem.Create("Deployment Pressure", moduleParachute.minAirPressureToOpen.ToString("F2")));
-            }
-        }
-
-        private void SetRcsInfo()
-        {
-            moduleRcs = selectedPart.GetModule<ModuleRCS>();
-            if (moduleRcs != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Thruster Power", moduleRcs.thrusterPower.ToForce()));
-                infoItems.Add(PartInfoItem.Create("Specific Impulse", Units.ConcatF(moduleRcs.atmosphereCurve.Evaluate(1.0f), moduleRcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
-            }
-        }
-
-        private void SetReactionWheelInfo()
-        {
-            moduleReactionWheel = selectedPart.GetModule<ModuleReactionWheel>();
-            if (moduleReactionWheel != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Reaction Wheel Torque"));
-                infoItems.Add(PartInfoItem.Create("\tPitch", moduleReactionWheel.PitchTorque.ToTorque()));
-                infoItems.Add(PartInfoItem.Create("\tRoll", moduleReactionWheel.RollTorque.ToTorque()));
-                infoItems.Add(PartInfoItem.Create("\tYaw", moduleReactionWheel.YawTorque.ToTorque()));
-                for (int i = 0; i < moduleReactionWheel.inputResources.Count; ++i)
-                {
-                    moduleResource = moduleReactionWheel.inputResources[i];
-                    infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.rate.ToRate()));
-                }
-            }
-        }
-
-        private void SetResourceItems()
-        {
-            bool visibleResources = false;
-            for (int i = 0; i < selectedPart.Resources.list.Count; ++i)
-            {
-                if (selectedPart.Resources.list[i].hideFlow == false)
-                {
-                    visibleResources = true;
-                    break;
-                }
-            }
-            if (visibleResources)
-            {
-                infoItems.Add(PartInfoItem.Create("Resources"));
-                for (int i = 0; i < selectedPart.Resources.list.Count; ++i)
-                {
-                    partResource = selectedPart.Resources.list[i];
-
-                    if (partResource.hideFlow == false)
-                    {
-                        infoItems.Add(partResource.GetDensity() > 0
-                            ? PartInfoItem.Create("\t" + partResource.info.name, "(" + partResource.GetMass().ToMass() + ") " + partResource.amount.ToString("F1"))
-                            : PartInfoItem.Create("\t" + partResource.info.name, partResource.amount.ToString("F1")));
-                    }
-                }
-            }
-        }
-
-        private void SetSasInfo()
-        {
-            if (selectedPart.HasModule<ModuleSAS>())
-            {
-                infoItems.Add(PartInfoItem.Create("SAS Equiped"));
-            }
-        }
-
-        private void SetScienceContainerInfo()
-        {
-            if (selectedPart.HasModule<ModuleScienceContainer>())
-            {
-                infoItems.Add(PartInfoItem.Create("Science Container"));
-            }
-        }
-
-        private void SetScienceExperimentInfo()
-        {
-            moduleScienceExperiment = selectedPart.GetModule<ModuleScienceExperiment>();
-            if (moduleScienceExperiment != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Science Experiment", moduleScienceExperiment.experimentActionName));
-                infoItems.Add(PartInfoItem.Create("\tTransmit Efficiency", moduleScienceExperiment.xmitDataScalar.ToPercent()));
-                if (moduleScienceExperiment.rerunnable == false)
-                {
-                    infoItems.Add(PartInfoItem.Create("\tSingle Usage"));
-                }
-            }
-        }
-
-        private void SetSingleActivationInfo()
-        {
-            if (selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot))
-            {
-                infoItems.Add(PartInfoItem.Create("Single Activation"));
-            }
-        }
-
-        private void SetSolarPanelInfo()
-        {
-            moduleDeployableSolarPanel = selectedPart.GetModule<ModuleDeployableSolarPanel>();
-            if (moduleDeployableSolarPanel != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Charge Rate", moduleDeployableSolarPanel.chargeRate.ToRate()));
-                if (moduleDeployableSolarPanel.isBreakable)
-                {
-                    infoItems.Add(PartInfoItem.Create("Breakable"));
-                }
-                if (moduleDeployableSolarPanel.sunTracking)
-                {
-                    infoItems.Add(PartInfoItem.Create("Sun Tracking"));
-                }
-            }
-        }
-
-        private void SetTransmitterInfo()
-        {
-            moduleDataTransmitter = selectedPart.GetModule<ModuleDataTransmitter>();
-            if (moduleDataTransmitter != null)
-            {
-                infoItems.Add(PartInfoItem.Create("Packet Size", moduleDataTransmitter.packetSize.ToString("F2") + " Mits"));
-                infoItems.Add(PartInfoItem.Create("Bandwidth", (moduleDataTransmitter.packetInterval * moduleDataTransmitter.packetSize).ToString("F2") + "Mits/sec"));
-                infoItems.Add(PartInfoItem.Create(moduleDataTransmitter.requiredResource, moduleDataTransmitter.packetResourceCost.ToString("F2") + "/Packet"));
-            }
-        }
-
-        private void Window(int windowId)
-        {
-            try
-            {
-                GUILayout.Label(selectedPart.partInfo.title, BuildOverlay.TitleStyle);
-                if (showInfo)
-                {
-                    for (int i = 0; i < infoItems.Count; ++i)
-                    {
-                        partInfoItem = infoItems[i];
                         GUILayout.Space(2.0f);
                         GUILayout.BeginHorizontal();
-                        if (partInfoItem.Value != null)
+                        if (item.Value != null)
                         {
-                            GUILayout.Label(partInfoItem.Name + ":", BuildOverlay.NameStyle);
+                            GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle);
                             GUILayout.Space(25.0f);
-                            GUILayout.Label(partInfoItem.Value, BuildOverlay.ValueStyle);
+                            GUILayout.Label(item.Value, BuildOverlay.ValueStyle);
                         }
                         else
                         {
-                            GUILayout.Label(partInfoItem.Name, BuildOverlay.NameStyle);
+                            GUILayout.Label(item.Name, BuildOverlay.NameStyle);
                         }
                         GUILayout.EndHorizontal();
                     }
                 }
-                else if (clickToOpen && namesOnly == false)
+                else if (this.infoItems.Count > 0)
                 {
                     GUILayout.Space(2.0f);
                     GUILayout.Label("Click middle mouse to show more info...", BuildOverlay.NameStyle);
@@ -469,5 +447,7 @@
                 Logger.Exception(ex);
             }
         }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Editor/BuildOverlayResources.cs
+++ b/KerbalEngineer/Editor/BuildOverlayResources.cs
@@ -19,18 +19,22 @@
 
 #region Using Directives
 
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using KerbalEngineer.Extensions;
+
+using UnityEngine;
+
 #endregion
 
 namespace KerbalEngineer.Editor
 {
-    using System;
-    using System.Collections.Generic;
-    using Extensions;
-    using UnityEngine;
-
     public class BuildOverlayResources : MonoBehaviour
     {
         #region Fields
+
         private static bool visible = true;
 
         private readonly Dictionary<int, ResourceInfoItem> resources = new Dictionary<int, ResourceInfoItem>();
@@ -41,48 +45,40 @@
         private Rect tabPosition;
         private Vector2 tabSize;
         private Rect windowPosition = new Rect(0.0f, 0.0f, BuildOverlay.MinimumWidth, 0.0f);
+
         #endregion
 
         #region Properties
+
         public static bool Visible
         {
-            get
-            {
-                return visible;
-            }
-            set
-            {
-                visible = value;
-            }
+            get { return visible; }
+            set { visible = value; }
         }
 
         public bool Open
         {
-            get
-            {
-                return open;
-            }
-            set
-            {
-                open = value;
-            }
-        }
+            get { return this.open; }
+            set { this.open = value; }
+        }
+
         #endregion
 
         #region Methods: protected
+
         protected void OnGUI()
         {
             try
             {
-                if (!Visible || resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
+                if (!Visible || this.resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
                 {
                     return;
                 }
 
-                open = GUI.Toggle(tabPosition, open, tabContent, BuildOverlay.TabStyle);
-                if (openPercent > 0.0)
-                {
-                    windowPosition = GUILayout.Window(GetInstanceID(), windowPosition, Window, String.Empty, BuildOverlay.WindowStyle);
+                this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
+                if (this.openPercent > 0.0)
+                {
+                    this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.Window, String.Empty, BuildOverlay.WindowStyle);
                 }
             }
             catch (Exception ex)
@@ -95,8 +91,8 @@
         {
             try
             {
-                tabContent = new GUIContent("RESOURCES");
-                tabSize = BuildOverlay.TabStyle.CalcSize(tabContent);
+                this.tabContent = new GUIContent("RESOURCES");
+                this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent);
             }
             catch (Exception ex)
             {
@@ -113,74 +109,66 @@
                     return;
                 }
 
-                SetResources();
-                SetSlidePosition();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
+                this.SetResources();
+                this.SetSlidePosition();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
         #endregion
 
         #region Methods: private
-        private static Part part;
-        private static PartResource partResource;
 
         private void SetResources()
         {
-            int previousCount = resources.Count;
-            resources.Clear();
-
-            for (int i = 0; i < EditorLogic.fetch.ship.parts.Count; ++i)
-            {
-                part = EditorLogic.fetch.ship.parts[i];
-                for (int j = 0; j < part.Resources.list.Count; ++j)
-                {
-                    partResource = part.Resources.list[j];
-
-                    if (resources.ContainsKey(partResource.info.id))
-                    {
-                        resources[partResource.info.id].Amount += partResource.amount;
-                    }
-                    else
-                    {
-                        resources.Add(partResource.info.id, new ResourceInfoItem(partResource));
-                    }
-                }
-            }
-
-            if (resources.Count < previousCount)
-            {
-                windowPosition.height = 0;
+            var previousCount = this.resources.Count;
+            this.resources.Clear();
+            foreach (var resource in EditorLogic.fetch.ship.parts.SelectMany(p => p.Resources.list).Where(r => r.amount > 0.0))
+            {
+                if (this.resources.ContainsKey(resource.info.id))
+                {
+                    this.resources[resource.info.id].Amount += resource.amount;
+                }
+                else
+                {
+                    this.resources.Add(resource.info.id, new ResourceInfoItem(resource));
+                }
+            }
+
+            if (this.resources.Count < previousCount)
+            {
+                this.windowPosition.height = 0;
             }
         }
 
         private void SetSlidePosition()
         {
-            if (open && openPercent < 1.0f)
-            {
-                openPercent = Mathf.Clamp(openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
-            }
-            else if (!open && openPercent > 0.0f)
-            {
-                openPercent = Mathf.Clamp(openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
-            }
-
-            windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f;
-            windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - windowPosition.height, openPercent);
-            tabPosition.width = tabSize.x;
-            tabPosition.height = tabSize.y;
-            tabPosition.x = windowPosition.x;
-            tabPosition.y = windowPosition.y - tabPosition.height;
+            if (this.open && this.openPercent < 1.0f)
+            {
+                this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+            }
+            else if (!this.open && this.openPercent > 0.0f)
+            {
+                this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+            }
+
+            this.windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f;
+            this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
+            this.tabPosition.width = this.tabSize.x;
+            this.tabPosition.height = this.tabSize.y;
+            this.tabPosition.x = this.windowPosition.x;
+            this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
         }
 
         private void Window(int windowId)
         {
             try
             {
-                bool firstItem = true;
-                foreach (KeyValuePair<int, ResourceInfoItem> resource in resources)
+                var firstItem = true;
+                foreach (var resource in this.resources)
                 {
                     if (!firstItem)
                     {
@@ -209,6 +197,7 @@
                 Logger.Exception(ex);
             }
         }
+
         #endregion
     }
 }

--- a/KerbalEngineer/Editor/BuildOverlayVessel.cs
+++ b/KerbalEngineer/Editor/BuildOverlayVessel.cs
@@ -18,11 +18,13 @@
 // 
 
 #region Using Directives
+
 #endregion
 
 namespace KerbalEngineer.Editor
 {
     #region Using Directives
+
     using System;
     using System.Collections.Generic;
     using Helpers;
@@ -34,10 +36,13 @@
     public class BuildOverlayVessel : MonoBehaviour
     {
         #region Constants
+
         private const float Width = 175.0f;
+
         #endregion
 
         #region Fields
+
         private static bool visible = true;
 
         private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
@@ -49,61 +54,44 @@
         private Rect tabPosition;
         private Vector2 tabSize;
         private Rect windowPosition = new Rect(330.0f, 0.0f, Width, 0.0f);
+
         #endregion
 
         #region Properties
+
         public static bool Visible
         {
-            get
-            {
-                return visible;
-            }
-            set
-            {
-                visible = value;
-            }
+            get { return visible; }
+            set { visible = value; }
         }
 
         public bool Open
         {
-            get
-            {
-                return open;
-            }
-            set
-            {
-                open = value;
-            }
+            get { return this.open; }
+            set { this.open = value; }
         }
 
         public Rect WindowPosition
         {
-            get
-            {
-                return windowPosition;
-            }
+            get { return this.windowPosition; }
         }
 
         public float WindowX
         {
-            get
-            {
-                return windowPosition.x;
-            }
-            set
-            {
-                windowPosition.x = value;
-            }
-        }
+            get { return this.windowPosition.x; }
+            set { this.windowPosition.x = value; }
+        }
+
         #endregion
 
         #region Methods
+
         protected void Awake()
         {
             try
             {
-                SimManager.OnReady -= GetStageInfo;
-                SimManager.OnReady += GetStageInfo;
+                SimManager.OnReady -= this.GetStageInfo;
+                SimManager.OnReady += this.GetStageInfo;
             }
             catch (Exception ex)
             {
@@ -120,10 +108,10 @@
                     return;
                 }
 
-                open = GUI.Toggle(tabPosition, open, tabContent, BuildOverlay.TabStyle);
-                if (openPercent > 0.0)
-                {
-                    windowPosition = GUILayout.Window(GetInstanceID(), windowPosition, VesselWindow, String.Empty, BuildOverlay.WindowStyle);
+                this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
+                if (this.openPercent > 0.0)
+                {
+                    this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle);
                 }
             }
             catch (Exception ex)
@@ -136,8 +124,8 @@
         {
             try
             {
-                tabContent = new GUIContent("VESSEL");
-                tabSize = BuildOverlay.TabStyle.CalcSize(tabContent);
+                this.tabContent = new GUIContent("VESSEL");
+                this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent);
             }
             catch (Exception ex)
             {
@@ -154,12 +142,12 @@
                     return;
                 }
 
-                if (openPercent > 0.0)
-                {
-                    SetVesselInfo();
-                }
-
-                SetSlidePosition();
+                if (this.openPercent > 0.0)
+                {
+                    this.SetVesselInfo();
+                }
+
+                this.SetSlidePosition();
             }
             catch (Exception ex)
             {
@@ -169,29 +157,29 @@
 
         private void GetStageInfo()
         {
-            lastStage = SimManager.LastStage;
+            this.lastStage = SimManager.LastStage;
         }
 
         private void SetSlidePosition()
         {
-            if (open && openPercent < 1.0f)
-            {
-                openPercent = Mathf.Clamp(openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
-            }
-            else if (!open && openPercent > 0.0f)
-            {
-                openPercent = Mathf.Clamp(openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
-            }
-
-            windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - windowPosition.height, openPercent);
-            if (windowPosition.width < Width)
-            {
-                windowPosition.width = Width;
-            }
-            tabPosition.width = tabSize.x;
-            tabPosition.height = tabSize.y;
-            tabPosition.x = windowPosition.x;
-            tabPosition.y = windowPosition.y - tabPosition.height;
+            if (this.open && this.openPercent < 1.0f)
+            {
+                this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+            }
+            else if (!this.open && this.openPercent > 0.0f)
+            {
+                this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+            }
+
+            this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
+            if (this.windowPosition.width < Width)
+            {
+                this.windowPosition.width = Width;
+            }
+            this.tabPosition.width = this.tabSize.x;
+            this.tabPosition.height = this.tabSize.y;
+            this.tabPosition.x = this.windowPosition.x;
+            this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
         }
 
         private void SetVesselInfo()
@@ -200,7 +188,7 @@
 
             if (BuildAdvanced.Instance.ShowAtmosphericDetails)
             {
-                SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(BuildAdvanced.Altitude);
+                SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01;
             }
             else
             {
@@ -210,14 +198,13 @@
             SimManager.RequestSimulation();
             SimManager.TryStartSimulation();
 
-            if (lastStage != null)
-            {
-                PartInfoItem.Release(infoItems);
-                infoItems.Clear();
-                infoItems.Add(PartInfoItem.Create("Delta-V", lastStage.deltaV.ToString("N0") + " / " + lastStage.totalDeltaV.ToString("N0") + "m/s"));
-                infoItems.Add(PartInfoItem.Create("Mass", Units.ToMass(lastStage.mass, lastStage.totalMass)));
-                infoItems.Add(PartInfoItem.Create("TWR", lastStage.thrustToWeight.ToString("F2") + " (" + lastStage.maxThrustToWeight.ToString("F2") + ")"));
-                infoItems.Add(PartInfoItem.Create("Parts", lastStage.partCount + " / " + lastStage.totalPartCount));
+            if (this.lastStage != null)
+            {
+                this.infoItems.Clear();
+                this.infoItems.Add(new PartInfoItem("Delta-V", this.lastStage.deltaV.ToString("N0") + " / " + this.lastStage.totalDeltaV.ToString("N0") + "m/s"));
+                this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.lastStage.mass, this.lastStage.totalMass)));
+                this.infoItems.Add(new PartInfoItem("TWR", this.lastStage.thrustToWeight.ToString("F2") + " (" + this.lastStage.maxThrustToWeight.ToString("F2") + ")"));
+                this.infoItems.Add(new PartInfoItem("Parts", this.lastStage.partCount + " / " + this.lastStage.totalPartCount));
             }
         }
 
@@ -225,8 +212,8 @@
         {
             try
             {
-                bool firstItem = true;
-                foreach (PartInfoItem item in infoItems)
+                var firstItem = true;
+                foreach (var item in this.infoItems)
                 {
                     if (!firstItem)
                     {
@@ -253,6 +240,7 @@
                 Logger.Exception(ex);
             }
         }
+
         #endregion
     }
 }

--- a/KerbalEngineer/Editor/BuildToolbar.cs
+++ b/KerbalEngineer/Editor/BuildToolbar.cs
@@ -42,14 +42,6 @@
         {
             GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady);
             Logger.Log("BuildToolbar->Awake");
-        }
-
-        private void Start()
-        {
-            if (button == null)
-            {
-                OnGuiAppLauncherReady();
-            }
         }
 
         private void OnDestroy()

--- a/KerbalEngineer/Editor/PartInfoItem.cs
+++ b/KerbalEngineer/Editor/PartInfoItem.cs
@@ -19,38 +19,29 @@
 
 namespace KerbalEngineer.Editor
 {
-    using VesselSimulator;
+    public class PartInfoItem
+    {
+        #region Constructors
 
-    public class PartInfoItem : Pool<PartInfoItem>
-    {
+        public PartInfoItem(string name)
+        {
+            this.Name = name;
+        }
+
+        public PartInfoItem(string name, string value)
+        {
+            this.Name = name;
+            this.Value = value;
+        }
+
+        #endregion
+
+        #region Properties
+
         public string Name { get; set; }
 
         public string Value { get; set; }
 
-        public static PartInfoItem Create(string name)
-        {
-            return GetPoolObject().Initialise(name);
-        }
-
-        public static PartInfoItem Create(string name, string value)
-        {
-            return GetPoolObject().Initialise(name, value);
-        }
-
-        public PartInfoItem Initialise(string name)
-        {
-            Name = name;
-            Value = string.Empty;
-
-            return this;
-        }
-
-        public PartInfoItem Initialise(string name, string value)
-        {
-            Name = name;
-            Value = value;
-
-            return this;
-        }
+        #endregion
     }
 }

--- a/KerbalEngineer/EngineerGlobals.cs
+++ b/KerbalEngineer/EngineerGlobals.cs
@@ -33,7 +33,7 @@
         /// <summary>
         ///     Current version of the Kerbal Engineer assembly.
         /// </summary>
-        public const string AssemblyVersion = "1.0.16.5";
+        public const string AssemblyVersion = "1.0.16.0";
 
         #endregion
 

--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -17,17 +17,21 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
+#region Using Directives
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+#endregion
+
 namespace KerbalEngineer.Extensions
 {
-    using System;
-    using System.Collections.Generic;
     using CompoundParts;
 
     public static class PartExtensions
     {
-        private static Part cachePart;
-        private static PartModule cachePartModule;
-        private static PartResource cachePartResource;
+        #region Methods: public
 
         /// <summary>
         ///     Gets whether the part contains a specific resource.
@@ -42,473 +46,441 @@
         /// </summary>
         public static bool ContainsResources(this Part part)
         {
-            for (int i = 0; i < part.Resources.list.Count; ++i)
-            {
-                if (part.Resources.list[i].amount > 0.0)
-                {
+            return part.Resources.list.Count(p => p.amount > 0d) > 0;
+        }
+
+        /// <summary>
+        ///     Gets whether the part has fuel.
+        /// </summary>
+        public static bool EngineHasFuel(this Part part)
+        {
+            if (part.HasModule<ModuleEngines>())
+            {
+                return part.GetModuleEngines().getFlameoutState;
+            }
+            if (part.HasModule<MultiModeEngine>())
+            {
+                return part.GetModuleMultiModeEngine().getFlameoutState;
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part excluding resources.
+        /// </summary>
+        public static double GetCostDry(this Part part)
+        {
+            return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts(0.0f);
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part including maximum resources.
+        /// </summary>
+        public static double GetCostMax(this Part part)
+        {
+            return part.partInfo.cost + part.GetModuleCosts(0.0f);
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part modules
+        ///     Same as stock but without mem allocation
+        /// </summary>
+        public static double GetModuleCostsNoAlloc(this Part part, float defaultCost)
+        {
+            float cost = 0f;
+            for (int i = 0; i < part.Modules.Count; i++)
+            {
+                PartModule pm = part.Modules[i];
+                if (pm is IPartCostModifier)
+                    cost += (pm as IPartCostModifier).GetModuleCost(defaultCost);
+            }
+            return cost;
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part including resources.
+        /// </summary>
+        public static double GetCostWet(this Part part)
+        {
+            return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCostsNoAlloc(0.0f); // part.GetModuleCosts allocate 44B per call. 
+        }
+
+        /// <summary>
+        ///     Gets the dry mass of the part.
+        /// </summary>
+        public static double GetDryMass(this Part part)
+        {
+            return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass : 0d;
+        }
+
+        /// <summary>
+        ///     Gets the maximum thrust of the part if it's an engine.
+        /// </summary>
+        public static double GetMaxThrust(this Part part)
+        {
+            if (part.HasModule<ModuleEngines>())
+            {
+                return part.GetModuleEngines().maxThrust;
+            }
+            if (part.HasModule<MultiModeEngine>())
+            {
+                return part.GetModuleMultiModeEngine().maxThrust;
+            }
+            if (part.HasModule<ModuleEnginesFX>())
+            {
+                return part.GetModuleEnginesFx().maxThrust;
+            }
+
+            return 0d;
+        }
+
+        /// <summary>
+        ///     Gets the first typed PartModule in the part's module list.
+        /// </summary>
+        public static T GetModule<T>(this Part part) where T : PartModule
+        {
+            for (int i = 0; i < part.Modules.Count; i++)
+            {
+                PartModule pm = part.Modules[i];
+                if (pm is T)
+                    return (T)pm;
+            }
+            return null;
+        }
+
+        /// <summary>
+        ///     Gets a typed PartModule.
+        /// </summary>
+        public static T GetModule<T>(this Part part, string className) where T : PartModule
+        {
+            return (T)Convert.ChangeType(part.Modules[className], typeof(T));
+        }
+
+        /// <summary>
+        ///     Gets a typed PartModule.
+        /// </summary>
+        public static T GetModule<T>(this Part part, int classId) where T : PartModule
+        {
+            return (T)Convert.ChangeType(part.Modules[classId], typeof(T));
+        }
+
+        /// <summary>
+        ///     Gets a ModuleAlternator typed PartModule.
+        /// </summary>
+        public static ModuleAlternator GetModuleAlternator(this Part part)
+        {
+            return part.GetModule<ModuleAlternator>();
+        }
+
+        /// <summary>
+        ///     Gets a ModuleDeployableSolarPanel typed PartModule.
+        /// </summary>
+        public static ModuleDeployableSolarPanel GetModuleDeployableSolarPanel(this Part part)
+        {
+            return part.GetModule<ModuleDeployableSolarPanel>();
+        }
+
+        /// <summary>
+        ///     Gets a ModuleEngines typed PartModule.
+        /// </summary>
+        public static ModuleEngines GetModuleEngines(this Part part)
+        {
+            return part.GetModule<ModuleEngines>();
+        }
+
+        public static ModuleEnginesFX GetModuleEnginesFx(this Part part)
+        {
+            return part.GetModule<ModuleEnginesFX>();
+        }
+
+        /// <summary>
+        ///     Gets a ModuleGenerator typed PartModule.
+        /// </summary>
+        public static ModuleGenerator GetModuleGenerator(this Part part)
+        {
+            return part.GetModule<ModuleGenerator>();
+        }
+
+        /// <summary>
+        ///     Gets a ModuleGimbal typed PartModule.
+        /// </summary>
+        public static ModuleGimbal GetModuleGimbal(this Part part)
+        {
+            return part.GetModule<ModuleGimbal>();
+        }
+
+        /// <summary>
+        ///     Gets the current selected ModuleEnginesFX.
+        /// </summary>
+        public static ModuleEnginesFX GetModuleMultiModeEngine(this Part part)
+        {
+            var mode = part.GetModule<MultiModeEngine>().mode;
+            return part.Modules.OfType<ModuleEnginesFX>().FirstOrDefault(engine => engine.engineID == mode);
+        }
+
+        /// <summary>
+        ///     Gets a ModuleParachute typed PartModule.
+        /// </summary>
+        public static ModuleParachute GetModuleParachute(this Part part)
+        {
+            return part.GetModule<ModuleParachute>();
+        }
+
+        public static ModuleRCS GetModuleRcs(this Part part)
+        {
+            return part.GetModule<ModuleRCS>();
+        }
+
+        /// <summary>
+        ///     Gets a typed list of PartModules.
+        /// </summary>
+        public static List<T> GetModules<T>(this Part part) where T : PartModule
+        {
+            return part.Modules.OfType<T>().ToList();
+        }
+
+        public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part)
+        {
+            if (HasModule<ModuleDecouple>(part))
+            {
+                return new ProtoModuleDecoupler(GetModule<ModuleDecouple>(part));
+            }
+            if (HasModule<ModuleAnchoredDecoupler>(part))
+            {
+                return new ProtoModuleDecoupler(GetModule<ModuleAnchoredDecoupler>(part));
+            }
+            return null;
+        }
+
+        /// <summary>
+        ///     Gets a generic proto engine for the current engine module attached to the part.
+        /// </summary>
+        public static ProtoModuleEngine GetProtoModuleEngine(this Part part)
+        {
+            if (HasModule<ModuleEngines>(part))
+            {
+                return new ProtoModuleEngine(GetModule<ModuleEngines>(part));
+            }
+            if (HasModule<MultiModeEngine>(part))
+            {
+                return new ProtoModuleEngine(GetModuleMultiModeEngine(part));
+            }
+            if (HasModule<ModuleEnginesFX>(part))
+            {
+                return new ProtoModuleEngine(GetModule<ModuleEnginesFX>(part));
+            }
+            return null;
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part's contained resources.
+        /// </summary>
+        public static double GetResourceCost(this Part part)
+        {
+            return part.Resources.list.Sum(r => r.amount * r.info.unitCost);
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part's contained resources, inverted.
+        /// </summary>
+        public static double GetResourceCostInverted(this Part part)
+        {
+            double sum = 0;
+            for (int i = 0; i < part.Resources.list.Count; i++)
+            {
+                PartResource r = part.Resources.list[i];
+                sum += (r.maxAmount - r.amount) * r.info.unitCost;
+            }
+            return sum;
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part's maximum contained resources.
+        /// </summary>
+        public static double GetResourceCostMax(this Part part)
+        {
+            return part.Resources.list.Sum(r => r.maxAmount * r.info.unitCost);
+        }
+
+        /// <summary>
+        ///     Gets the current specific impulse for the engine.
+        /// </summary>
+        public static double GetSpecificImpulse(this Part part, float atmosphere)
+        {
+            if (part.HasModule<ModuleEngines>())
+            {
+                return part.GetModuleEngines().atmosphereCurve.Evaluate(atmosphere);
+            }
+            if (part.HasModule<MultiModeEngine>())
+            {
+                return part.GetModuleMultiModeEngine().atmosphereCurve.Evaluate(atmosphere);
+            }
+            if (part.HasModule<ModuleEnginesFX>())
+            {
+                return part.GetModuleEnginesFx().atmosphereCurve.Evaluate(atmosphere);
+            }
+
+            return 0d;
+        }
+
+        /// <summary>
+        ///     Gets the total mass of the part including resources.
+        /// </summary>
+        public static double GetWetMass(this Part part)
+        {
+            return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass + part.GetResourceMass() : part.GetResourceMass();
+        }
+
+        /// <summary>
+        ///     Gets whether the part contains a PartModule.
+        /// </summary>
+        public static bool HasModule<T>(this Part part) where T : PartModule
+        {
+            for (int i = 0; i < part.Modules.Count; i++)
+            {
+                if (part.Modules[i] is T)
                     return true;
-                }
             }
             return false;
         }
 
         /// <summary>
-        ///     Gets whether the part has fuel.
-        /// </summary>
-        public static bool EngineHasFuel(this Part part)
-        {
-            cachePartModule = GetModule<ModuleEngines>(part);
-            if (cachePartModule != null)
-            {
-                return (cachePartModule as ModuleEngines).getFlameoutState;
-            }
-
-            cachePartModule = GetModuleMultiModeEngine(part);
-            if (cachePartModule != null)
-            {
-                return (cachePartModule as ModuleEnginesFX).getFlameoutState;
-            }
-
+        ///     Gets whether the part contains a PartModule conforming to the supplied predicate.
+        /// </summary>
+        public static bool HasModule<T>(this Part part, Func<T, bool> predicate) where T : PartModule
+        {
+            for (int i = 0; i < part.Modules.Count; i++)
+            {
+                PartModule pm = part.Modules[i];
+                if (pm is T && predicate(pm as T))
+                    return true;
+            }
             return false;
         }
 
         /// <summary>
-        ///     Gets the cost of the part excluding resources.
-        /// </summary>
-        public static double GetCostDry(this Part part)
-        {
-            return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts(0.0f);
-        }
-
-        /// <summary>
-        ///     Gets the cost of the part including maximum resources.
-        /// </summary>
-        public static double GetCostMax(this Part part)
-        {
-            return part.partInfo.cost + part.GetModuleCosts(0.0f);
-        }
-
-        /// <summary>
-        ///     Gets the cost of the part including resources.
-        /// </summary>
-        public static double GetCostWet(this Part part)
-        {
-            return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts(0.0f);
-        }
-
-        /// <summary>
-        ///     Gets the dry mass of the part.
-        /// </summary>
-        public static double GetDryMass(this Part part)
-        {
-            return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass : 0d;
-        }
-
-        /// <summary>
-        ///     Gets the maximum thrust of the part if it's an engine.
-        /// </summary>
-        public static double GetMaxThrust(this Part part)
-        {
-            cachePartModule = GetModule<ModuleEngines>(part);
-            if (cachePartModule != null)
-            {
-                return (cachePartModule as ModuleEngines).maxThrust;
-            }
-
-            cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
-            if (cachePartModule != null)
-            {
-                return (cachePartModule as ModuleEnginesFX).maxThrust;
-            }
-
-            return 0.0;
-        }
-
-        /// <summary>
-        ///     Gets the first typed PartModule in the part's module list.
-        /// </summary>
-        public static T GetModule<T>(this Part part) where T : PartModule
-        {
-            PartModule partModule;
-            for (int i = 0; i < part.Modules.Count; ++i)
-            {
-                partModule = part.Modules[i];
-                if (partModule is T)
-                {
-                    return partModule as T;
-                }
-            }
-            return null;
-        }
-
-        /// <summary>
-        ///     Gets a typed PartModule.
-        /// </summary>
-        public static T GetModule<T>(this Part part, string className) where T : PartModule
-        {
-            return part.Modules[className] as T;
-        }
-
-        /// <summary>
-        ///     Gets a typed PartModule.
-        /// </summary>
-        public static T GetModule<T>(this Part part, int classId) where T : PartModule
-        {
-            return part.Modules[classId] as T;
-        }
-
-        /// <summary>
-        ///     Gets a ModuleAlternator typed PartModule.
-        /// </summary>
-        public static ModuleAlternator GetModuleAlternator(this Part part)
-        {
-            return GetModule<ModuleAlternator>(part);
-        }
-
-        /// <summary>
-        ///     Gets a ModuleDeployableSolarPanel typed PartModule.
-        /// </summary>
-        public static ModuleDeployableSolarPanel GetModuleDeployableSolarPanel(this Part part)
-        {
-            return GetModule<ModuleDeployableSolarPanel>(part);
-        }
-
-        /// <summary>
-        ///     Gets a ModuleEngines typed PartModule.
-        /// </summary>
-        public static ModuleEngines GetModuleEngines(this Part part)
-        {
-            return GetModule<ModuleEngines>(part);
-        }
-
-        public static ModuleEnginesFX GetModuleEnginesFx(this Part part)
-        {
-            return GetModule<ModuleEnginesFX>(part);
-        }
-
-        /// <summary>
-        ///     Gets a ModuleGenerator typed PartModule.
-        /// </summary>
-        public static ModuleGenerator GetModuleGenerator(this Part part)
-        {
-            return GetModule<ModuleGenerator>(part);
-        }
-
-        /// <summary>
-        ///     Gets a ModuleGimbal typed PartModule.
-        /// </summary>
-        public static ModuleGimbal GetModuleGimbal(this Part part)
-        {
-            return GetModule<ModuleGimbal>(part);
-        }
-
-        /// <summary>
-        ///     Gets the current selected ModuleEnginesFX.
-        /// </summary>
-        public static ModuleEnginesFX GetModuleMultiModeEngine(this Part part)
-        {
-            ModuleEnginesFX moduleEngineFx;
-            string mode = GetModule<MultiModeEngine>(part).mode;
-            for (int i = 0; i < part.Modules.Count; ++i)
-            {
-                moduleEngineFx = part.Modules[i] as ModuleEnginesFX;
-                if (moduleEngineFx != null && moduleEngineFx.engineID == mode)
-                {
-                    return moduleEngineFx;
-                }
-            }
-            return null;
-        }
-
-        /// <summary>
-        ///     Gets a ModuleParachute typed PartModule.
-        /// </summary>
-        public static ModuleParachute GetModuleParachute(this Part part)
-        {
-            return GetModule<ModuleParachute>(part);
-        }
-
-        public static ModuleRCS GetModuleRcs(this Part part)
-        {
-            return GetModule<ModuleRCS>(part);
-        }
-
-        /// <summary>
-        ///     Gets a typed list of PartModules.
-        /// </summary>
-        public static List<T> GetModules<T>(this Part part) where T : PartModule
-        {
-            List<T> list = new List<T>();
-            for (int i = 0; i < part.Modules.Count; ++i)
-            {
-                T module = part.Modules[i] as T;
-                if (module != null)
-                {
-                    list.Add(module);
-                }
-            }
-            return list;
-        }
-
-        public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part)
-        {
-            cachePartModule = GetModule<ModuleDecouple>(part);
-            if (cachePartModule == null)
-            {
-                cachePartModule = GetModule<ModuleAnchoredDecoupler>(part);
-            }
-            if (cachePartModule != null)
-            {
-                return new ProtoModuleDecoupler(cachePartModule);
-            }
-
-            return null;
-        }
-
-        /// <summary>
-        ///     Gets a generic proto engine for the current engine module attached to the part.
-        /// </summary>
-        public static ProtoModuleEngine GetProtoModuleEngine(this Part part)
-        {
-            cachePartModule = GetModule<ModuleEngines>(part);
-            if (cachePartModule != null)
-            {
-                return new ProtoModuleEngine(cachePartModule);
-            }
-
-            cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
-            if (cachePartModule != null)
-            {
-                return new ProtoModuleEngine(cachePartModule);
-            }
-
-            return null;
-        }
-
-        /// <summary>
-        ///     Gets the cost of the part's contained resources.
-        /// </summary>
-        public static double GetResourceCost(this Part part)
-        {
-            double cost = 0.0;
-            for (int i = 0; i < part.Resources.list.Count; ++i)
-            {
-                cachePartResource = part.Resources.list[i];
-                cost = cost + (cachePartResource.amount * cachePartResource.info.unitCost);
-            }
-            return cost;
-        }
-
-        /// <summary>
-        ///     Gets the cost of the part's contained resources, inverted.
-        /// </summary>
-        public static double GetResourceCostInverted(this Part part)
-        {
-            double cost = 0.0;
-            for (int i = 0; i < part.Resources.list.Count; ++i)
-            {
-                cachePartResource = part.Resources.list[i];
-                cost = cost + ((cachePartResource.maxAmount - cachePartResource.amount) * cachePartResource.info.unitCost);
-            }
-            return cost;
-        }
-
-        /// <summary>
-        ///     Gets the cost of the part's maximum contained resources.
-        /// </summary>
-        public static double GetResourceCostMax(this Part part)
-        {
-            double cost = 0.0;
-            for (int i = 0; i < part.Resources.list.Count; ++i)
-            {
-                cachePartResource = part.Resources.list[i];
-                cost = cost + (cachePartResource.maxAmount * cachePartResource.info.unitCost);
-            }
-            return cost;
-        }
-
-        /// <summary>
-        ///     Gets the current specific impulse for the engine.
-        /// </summary>
-        public static double GetSpecificImpulse(this Part part, float atmosphere)
-        {
-            cachePartModule = GetModule<ModuleEngines>(part);
-            if (cachePartModule != null)
-            {
-                return (cachePartModule as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
-            }
-
-            cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
-            if (cachePartModule != null)
-            {
-                return (cachePartModule as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere);
-            }
-
-            return 0.0;
-        }
-
-        /// <summary>
-        ///     Gets the total mass of the part including resources.
-        /// </summary>
-        public static double GetWetMass(this Part part)
-        {
-            return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass + part.GetResourceMass() : part.GetResourceMass();
-        }
-
-        /// <summary>
         ///     Gets whether the part contains a PartModule.
         /// </summary>
-        public static bool HasModule<T>(this Part part) where T : PartModule
-        {
-            for (int i = 0; i < part.Modules.Count; ++i)
-            {
-                if (part.Modules[i] is T)
+        public static bool HasModule(this Part part, string className)
+        {
+            return part.Modules.Contains(className);
+        }
+
+        /// <summary>
+        ///     Gets whether the part contains a PartModule.
+        /// </summary>
+        public static bool HasModule(this Part part, int moduleId)
+        {
+            return part.Modules.Contains(moduleId);
+        }
+
+        /// <summary>
+        ///     Gets whether the part has a one shot animation.
+        /// </summary>
+        public static bool HasOneShotAnimation(this Part part)
+        {
+            return part.HasModule<ModuleAnimateGeneric>() && part.GetModule<ModuleAnimateGeneric>().isOneShot;
+        }
+
+        /// <summary>
+        ///     Gets whether the part is a command module.
+        /// </summary>
+        public static bool IsCommandModule(this Part part)
+        {
+            return part.HasModule<ModuleCommand>();
+        }
+
+        /// <summary>
+        ///     Gets whether the part is decoupled in a specified stage.
+        /// </summary>
+        public static bool IsDecoupledInStage(this Part part, int stage)
+        {
+            if ((part.IsDecoupler() || part.IsLaunchClamp()) && part.inverseStage == stage)
+            {
+                return true;
+            }
+            if (part.parent == null)
+            {
+                return false;
+            }
+            return part.parent.IsDecoupledInStage(stage);
+        }
+
+        /// <summary>
+        ///     Gets whether the part is a decoupler.
+        /// </summary>
+        public static bool IsDecoupler(this Part part)
+        {
+            return part.HasModule<ModuleDecouple>() || part.HasModule<ModuleAnchoredDecoupler>();
+        }
+
+        /// <summary>
+        ///     Gets whether the part is an active engine.
+        /// </summary>
+        public static bool IsEngine(this Part part)
+        {
+            return part.HasModule<ModuleEngines>() || part.HasModule<ModuleEnginesFX>();
+        }
+
+        /// <summary>
+        ///     Gets whether the part is a fuel line.
+        /// </summary>
+        public static bool IsFuelLine(this Part part)
+        {
+            return (HasModule<CModuleFuelLine>(part));
+        }
+
+        /// <summary>
+        ///     Gets whether the part is a generator.
+        /// </summary>
+        public static bool IsGenerator(this Part part)
+        {
+            return part.HasModule<ModuleGenerator>();
+        }
+
+        /// <summary>
+        ///     Gets whether the part is a launch clamp.
+        /// </summary>
+        public static bool IsLaunchClamp(this Part part)
+        {
+            return part.HasModule<LaunchClamp>();
+        }
+
+        /// <summary>
+        ///     Gets whether the part is a parachute.
+        /// </summary>
+        public static bool IsParachute(this Part part)
+        {
+            return part.HasModule<ModuleParachute>();
+        }
+
+        /// <summary>
+        ///     Gets whether the part is considered a primary part on the vessel.
+        /// </summary>
+        public static bool IsPrimary(this Part part, List<Part> partsList, PartModule module)
+        {
+            for (int i = 0; i < partsList.Count; i++)
+            {
+                var vesselPart = partsList[i];
+                if (!vesselPart.HasModule(module.ClassID))
+                {
+                    continue;
+                }
+
+                if (vesselPart == part)
                 {
                     return true;
                 }
-            }
+                break;
+            }
+
             return false;
         }
 
-        /// <summary>
-        ///     Gets whether the part contains a PartModule conforming to the supplied predicate.
-        /// </summary>
-        public static bool HasModule<T>(this Part part, Func<T, bool> predicate) where T : PartModule
-        {
-            for (int i = 0; i < part.Modules.Count; ++i)
-            {
-                cachePartModule = part.Modules[i] as T;
-                if (cachePartModule != null && predicate(cachePartModule as T))
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /// <summary>
-        ///     Gets whether the part contains a PartModule.
-        /// </summary>
-        public static bool HasModule(this Part part, string className)
-        {
-            return part.Modules.Contains(className);
-        }
-
-        /// <summary>
-        ///     Gets whether the part contains a PartModule.
-        /// </summary>
-        public static bool HasModule(this Part part, int moduleId)
-        {
-            return part.Modules.Contains(moduleId);
-        }
-
-        /// <summary>
-        ///     Gets whether the part has a one shot animation.
-        /// </summary>
-        public static bool HasOneShotAnimation(this Part part)
-        {
-            cachePartModule = GetModule<ModuleAnimateGeneric>(part);
-            return cachePartModule != null && (cachePartModule as ModuleAnimateGeneric).isOneShot;
-        }
-
-        /// <summary>
-        ///     Gets whether the part is a command module.
-        /// </summary>
-        public static bool IsCommandModule(this Part part)
-        {
-            return HasModule<ModuleCommand>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is decoupled in a specified stage.
-        /// </summary>
-        public static bool IsDecoupledInStage(this Part part, int stage)
-        {
-            if ((IsDecoupler(part) || IsLaunchClamp(part)) && part.inverseStage == stage)
-            {
-                return true;
-            }
-            if (part.parent == null)
-            {
-                return false;
-            }
-            return IsDecoupledInStage(part.parent, stage);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is a decoupler.
-        /// </summary>
-        public static bool IsDecoupler(this Part part)
-        {
-            return HasModule<ModuleDecouple>(part) || HasModule<ModuleAnchoredDecoupler>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is an active engine.
-        /// </summary>
-        public static bool IsEngine(this Part part)
-        {
-            return HasModule<ModuleEngines>(part) || HasModule<ModuleEnginesFX>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is a fuel line.
-        /// </summary>
-        public static bool IsFuelLine(this Part part)
-        {
-            return HasModule<CModuleFuelLine>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is a generator.
-        /// </summary>
-        public static bool IsGenerator(this Part part)
-        {
-            return HasModule<ModuleGenerator>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is a launch clamp.
-        /// </summary>
-        public static bool IsLaunchClamp(this Part part)
-        {
-            return HasModule<LaunchClamp>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is a parachute.
-        /// </summary>
-        public static bool IsParachute(this Part part)
-        {
-            return HasModule<ModuleParachute>(part);
-        }
-
-        /// <summary>
-        ///     Gets whether the part is considered a primary part on the vessel.
-        /// </summary>
-        public static bool IsPrimary(this Part part, List<Part> partsList, PartModule module)
-        {
-            for (int i = 0; i < partsList.Count; ++i)
-            {
-                cachePart = partsList[i];
-
-                if (HasModule(cachePart, module.ClassID) == false)
-                {
-                    continue;
-                }
-                if (cachePart == part)
-                {
-                    return true;
-                }
-                break;
-            }
-
-            return false;
-        }
-
         public static bool IsRcsModule(this Part part)
         {
-            return HasModule<ModuleRCS>(part);
+            return part.HasModule<ModuleRCS>();
         }
 
         /// <summary>
@@ -516,7 +488,7 @@
         /// </summary>
         public static bool IsSepratron(this Part part)
         {
-            return IsSolidRocket(part) && part.ActivatesEvenIfDisconnected && IsDecoupledInStage(part, part.inverseStage);
+            return (part.IsSolidRocket() && part.ActivatesEvenIfDisconnected && part.IsDecoupledInStage(part.inverseStage));
         }
 
         /// <summary>
@@ -524,7 +496,7 @@
         /// </summary>
         public static bool IsSolarPanel(this Part part)
         {
-            return HasModule<ModuleDeployableSolarPanel>(part);
+            return part.HasModule<ModuleDeployableSolarPanel>();
         }
 
         /// <summary>
@@ -532,106 +504,160 @@
         /// </summary>
         public static bool IsSolidRocket(this Part part)
         {
-            return (HasModule<ModuleEngines>(part) && GetModuleEngines(part).throttleLocked) || (HasModule<ModuleEnginesFX>(part) && GetModuleEnginesFx(part).throttleLocked);
-        }
+            return (part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked) || (part.HasModule<ModuleEnginesFX>() && part.GetModuleEnginesFx().throttleLocked);
+        }
+
+        #endregion
+
+        #region Nested Type: ProtoModuleDecoupler
 
         public class ProtoModuleDecoupler
         {
+            #region Fields
+
             private readonly PartModule module;
 
+            #endregion
+
+            #region Constructors
+
             public ProtoModuleDecoupler(PartModule module)
             {
                 this.module = module;
 
                 if (this.module is ModuleDecouple)
                 {
-                    SetModuleDecouple();
+                    this.SetModuleDecouple();
                 }
                 else if (this.module is ModuleAnchoredDecoupler)
                 {
-                    SetModuleAnchoredDecoupler();
-                }
-            }
+                    this.SetModuleAnchoredDecoupler();
+                }
+            }
+
+            #endregion
+
+            #region Properties
 
             public double EjectionForce { get; private set; }
             public bool IsOmniDecoupler { get; private set; }
 
+            #endregion
+
+            #region Methods: private
+
             private void SetModuleAnchoredDecoupler()
             {
-                ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler;
+                var decoupler = this.module as ModuleAnchoredDecoupler;
                 if (decoupler == null)
                 {
                     return;
                 }
 
-                EjectionForce = decoupler.ejectionForce;
+                this.EjectionForce = decoupler.ejectionForce;
             }
 
             private void SetModuleDecouple()
             {
-                ModuleDecouple decoupler = module as ModuleDecouple;
+                var decoupler = this.module as ModuleDecouple;
                 if (decoupler == null)
                 {
                     return;
                 }
 
-                EjectionForce = decoupler.ejectionForce;
-                IsOmniDecoupler = decoupler.isOmniDecoupler;
-            }
-        }
+                this.EjectionForce = decoupler.ejectionForce;
+                this.IsOmniDecoupler = decoupler.isOmniDecoupler;
+            }
+
+            #endregion
+        }
+
+        #endregion
+
+        #region Nested Type: ProtoModuleEngine
 
         public class ProtoModuleEngine
         {
+            #region Fields
+
             private readonly PartModule module;
 
+            #endregion
+
+            #region Constructors
+
             public ProtoModuleEngine(PartModule module)
             {
                 this.module = module;
 
                 if (module is ModuleEngines)
                 {
-                    SetModuleEngines();
-                }
-            }
+                    this.SetModuleEngines();
+                }
+                else if (module is ModuleEnginesFX)
+                {
+                    this.SetModuleEnginesFx();
+                }
+            }
+
+            #endregion
+
+            #region Properties
 
             public double MaximumThrust { get; private set; }
             public double MinimumThrust { get; private set; }
             public List<Propellant> Propellants { get; private set; }
 
+            #endregion
+
+            #region Methods: public
+
             public float GetSpecificImpulse(float atmosphere)
             {
-                if (module is ModuleEngines)
-                {
-                    return (module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
+                if (this.module is ModuleEngines)
+                {
+                    return (this.module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
+                }
+                if (this.module is ModuleEnginesFX)
+                {
+                    return (this.module as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere);
                 }
                 return 0.0f;
             }
 
+            #endregion
+
+            #region Methods: private
+
             private void SetModuleEngines()
             {
-                ModuleEngines engine = module as ModuleEngines;
+                var engine = this.module as ModuleEngines;
                 if (engine == null)
                 {
                     return;
                 }
 
-                MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
-                MinimumThrust = engine.minThrust;
-                Propellants = engine.propellants;
+                this.MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
+                this.MinimumThrust = engine.minThrust;
+                this.Propellants = engine.propellants;
             }
 
             private void SetModuleEnginesFx()
             {
-                ModuleEnginesFX engine = module as ModuleEnginesFX;
+                var engine = this.module as ModuleEnginesFX;
                 if (engine == null)
                 {
                     return;
                 }
 
-                MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
-                MinimumThrust = engine.minThrust;
-                Propellants = engine.propellants;
-            }
-        }
+                this.MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
+                this.MinimumThrust = engine.minThrust;
+                this.Propellants = engine.propellants;
+            }
+
+            #endregion
+        }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Flight/ActionMenu.cs
+++ b/KerbalEngineer/Flight/ActionMenu.cs
@@ -55,14 +55,6 @@
             Logger.Log("ActionMenu was created.");
         }
 
-        protected void Start()
-        {
-            if (button == null)
-            {
-                OnGuiAppLauncherReady();
-            }
-        }
-
         protected void OnDestroy()
         {
             try
@@ -70,10 +62,7 @@
                 GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady);
                 GameEvents.onHideUI.Remove(this.OnHide);
                 GameEvents.onShowUI.Remove(this.OnShow);
-                if (button != null)
-                {
-                    ApplicationLauncher.Instance.RemoveModApplication(this.button);
-                }
+                ApplicationLauncher.Instance.RemoveModApplication(this.button);
             }
             catch (Exception ex)
             {

--- a/KerbalEngineer/Flight/Readouts/Surface/AtmosphericProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/AtmosphericProcessor.cs
@@ -29,8 +29,6 @@
 
 namespace KerbalEngineer.Flight.Readouts.Surface
 {
-    using UnityEngine;
-
     public class AtmosphericProcessor : IUpdatable, IUpdateRequest
     {
         #region Instance
@@ -48,10 +46,7 @@
         /// </summary>
         public static AtmosphericProcessor Instance
         {
-            get
-            {
-                return instance;
-            }
+            get { return instance; }
         }
 
         #endregion
@@ -127,13 +122,13 @@
                 }
                 else
                 {
-                    var m = FlightGlobals.ActiveVessel.parts.Sum(part => part.GetWetMass()) * 1000.0;
-                    var g = FlightGlobals.getGeeForceAtPosition(FlightGlobals.ship_position).magnitude;
-                    var a = FlightGlobals.ActiveVessel.parts.Sum(part => part.DragCubes.AreaDrag) * PhysicsGlobals.DragCubeMultiplier;
-                    var p = FlightGlobals.ActiveVessel.atmDensity;
-                    var c = PhysicsGlobals.DragMultiplier;
+                    var mass = FlightGlobals.ActiveVessel.parts.Sum(p => p.GetWetMass());
+                    var drag = FlightGlobals.ActiveVessel.parts.Sum(p => p.GetWetMass() * p.maximum_drag);
+                    var grav = FlightGlobals.getGeeForceAtPosition(FlightGlobals.ship_position).magnitude;
+                    var atmo = FlightGlobals.ActiveVessel.atmDensity;
+                    var coef = FlightGlobals.ActiveVessel.parts.Sum(p => p.DragCubes.DragCoeff);
 
-                    TerminalVelocity = Math.Sqrt((2.0 * m * g) / (p * a * c));
+                    TerminalVelocity = Math.Sqrt((2 * mass * grav) / (atmo * drag * coef));
                 }
 
                 Efficiency = FlightGlobals.ship_srfSpeed / TerminalVelocity;

--- a/KerbalEngineer/Helpers/Averager.cs
+++ b/KerbalEngineer/Helpers/Averager.cs
@@ -38,18 +38,18 @@
                 return Vector3d.zero;
             }
         }
-
-        public void Reset()
-        {
-            sum = Vector3d.zero;
-            count = 0;
-        }
     }
 
     public class WeightedVectorAverager
     {
         private Vector3d sum = Vector3d.zero;
         private double totalweight = 0;
+
+        public void Reset()
+        {
+            sum = Vector3d.zero;
+            totalweight = 0;
+        }
 
         public void Add(Vector3d v, double weight) {
             sum += v * weight;
@@ -67,12 +67,6 @@
         public double GetTotalWeight() {
             return totalweight;
         }
-
-        public void Reset()
-        {
-            sum = Vector3d.zero;
-            totalweight = 0.0;
-        }
     }
 }
 

--- a/KerbalEngineer/Helpers/ForceAccumulator.cs
+++ b/KerbalEngineer/Helpers/ForceAccumulator.cs
@@ -19,19 +19,39 @@
 
 using System;
 using System.Collections.Generic;
+using KerbalEngineer.VesselSimulator;
 
 namespace KerbalEngineer
 {
     // a (force, application point) tuple
     public class AppliedForce
     {
+        private static readonly Pool<AppliedForce> pool = new Pool<AppliedForce>(Create, Reset);
+
         public Vector3d vector;
         public Vector3d applicationPoint;
 
-        public AppliedForce(Vector3d vector, Vector3d applicationPoint) {
-            this.vector = vector;
-            this.applicationPoint = applicationPoint;
+        static private AppliedForce Create()
+        {
+            return new AppliedForce();
         }
+
+        static private void Reset(AppliedForce appliedForce) { }
+
+        static public AppliedForce New(Vector3d vector, Vector3d applicationPoint)
+        {
+            AppliedForce force = pool.Borrow();
+            force.vector = vector;
+            force.applicationPoint = applicationPoint;
+            return force;
+        }
+
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
+
     }
 
 	// This class was mostly adapted from FARCenterQuery, part of FAR, by ferram4, GPLv3
@@ -47,7 +67,7 @@
 	// some amount of residual torque. The line with the least amount of residual torque is chosen.
 	public class ForceAccumulator
 	{
-		// Total force.
+	    // Total force.
 		private Vector3d totalForce = Vector3d.zero;
 		// Torque needed to compensate if force were applied at origin.
 		private Vector3d totalZeroOriginTorque = Vector3d.zero;
@@ -100,11 +120,11 @@
             return GetMinTorqueForceApplicationPoint(avgApplicationPoint.Get());
         }
 
-	    public void Reset()
-	    {
-	        totalForce = Vector3d.zero;
-	        totalZeroOriginTorque = Vector3d.zero;
+        public void Reset()
+        {
+            totalForce = Vector3d.zero;
+            totalZeroOriginTorque = Vector3d.zero;
             avgApplicationPoint.Reset();
-	    }
+        }
 	}
 }

--- a/KerbalEngineer/Helpers/Pool.cs
+++ b/KerbalEngineer/Helpers/Pool.cs
@@ -1,61 +1,54 @@
-namespace KerbalEngineer.VesselSimulator
+using System.Collections.Generic;
+
+namespace KerbalEngineer
 {
-    using System.Collections.Generic;
+    /// <summary>
+    ///     Pool of object
+    /// </summary>
+    public class Pool<T> {
+        
+        private readonly Stack<T> values = new Stack<T>();
 
-    public class Pool<T> where T : new()
-    {
-        private static List<T> available = new List<T>();
-        private static List<T> inUse = new List<T>();
+        private readonly CreateDelegate<T> create;
+        private readonly ResetDelegate<T> reset;
 
-        public static int PoolCount
-        {
-            get
-            {
-                return available.Count + inUse.Count;
+        public delegate R CreateDelegate<out R>();
+        public delegate void ResetDelegate<in T1>(T1 a);
+        
+        /// <summary>
+        ///     Creates an empty pool with the specified object creation and reset delegates.
+        /// </summary>
+        public Pool(CreateDelegate<T> create, ResetDelegate<T> reset) {
+            this.create = create;
+            this.reset = reset;
+        }
+
+        /// <summary>
+        ///     Borrows an object from the pool.
+        /// </summary>
+        public T Borrow() {
+            lock (values) {
+                return values.Count > 0 ? values.Pop() : create();
             }
         }
-
-        public static T GetPoolObject()
+        
+        /// <summary>
+        ///     Release an object, reset it and returns it to the pool.
+        /// </summary>
+        public void Release(T value) {
+            reset(value);
+            lock (values) {
+                values.Push(value);
+            }
+        }
+        
+        /// <summary>
+        ///     Current size of the pool.
+        /// </summary>
+        public int Count()
         {
-            T obj;
-            if (available.Count > 0)
-            {
-                obj = available[0];
-                available.RemoveAt(0);
-            }
-            else
-            {
-                obj = new T();
-            }
-
-            inUse.Add(obj);
-            return obj;
+            return values.Count;
         }
 
-        public static void Release(T obj)
-        {
-            if (inUse.Contains(obj))
-            {
-                inUse.Remove(obj);
-                available.Add(obj);
-            }
-        }
-
-        public static void Release(List<T> objList)
-        {
-            for (int i = 0; i < objList.Count; ++i)
-            {
-                Release(objList[i]);
-            }
-        }
-
-        public static void ReleaseAll()
-        {
-            for (int i = 0; i < inUse.Count; ++i)
-            {
-                available.Add(inUse[i]);
-            }
-            inUse.Clear();
-        }
     }
 }

--- a/KerbalEngineer/Helpers/Units.cs
+++ b/KerbalEngineer/Helpers/Units.cs
@@ -20,6 +20,7 @@
 namespace KerbalEngineer.Helpers
 {
     #region Using Directives
+
     using System;
 
     #endregion
@@ -27,7 +28,6 @@
     public static class Units
     {
         #region Methods
-        public const double GRAVITY = 9.80665;
 
         public static string Concat(int value1, int value2)
         {
@@ -123,8 +123,8 @@
 
         public static string ToForce(double value1, double value2)
         {
-            string format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
-            string format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
+            var format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
+            var format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
             return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN";
         }
 
@@ -180,6 +180,7 @@
         {
             return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
         }
+
         #endregion
     }
 }

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -124,6 +124,11 @@
     <Compile Include="Helpers\TimeFormatter.cs" />
     <Compile Include="KeyBinder.cs" />
     <Compile Include="Control\ControlCentre.cs" />
+    <Compile Include="Smooth\Delegates\Delegates.cs" />
+    <Compile Include="Smooth\Dispose\Disposable.cs" />
+    <Compile Include="Smooth\Dispose\DisposalQueue.cs" />
+    <Compile Include="Smooth\Dispose\SmoothDisposer.cs" />
+    <Compile Include="Smooth\Pools\Pool.cs" />
     <Compile Include="UIControls\DropDown.cs" />
     <Compile Include="Logger.cs" />
     <Compile Include="EngineerGlobals.cs" />
@@ -199,7 +204,6 @@
     <Compile Include="UIControls\WindowObject.cs" />
     <Compile Include="VesselSimulator\AttachNodeSim.cs" />
     <Compile Include="VesselSimulator\EngineSim.cs" />
-    <Compile Include="Helpers\Pool.cs" />
     <Compile Include="VesselSimulator\PartSim.cs" />
     <Compile Include="VesselSimulator\ResourceContainer.cs" />
     <Compile Include="VesselSimulator\SimManager.cs" />
@@ -208,8 +212,7 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="Assembly-CSharp">
-      <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
     </Reference>
     <Reference Include="System">
       <HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath>
@@ -220,10 +223,10 @@
       <Private>False</Private>
     </Reference>
     <Reference Include="UnityEngine">
-      <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\UnityEngine.dll</HintPath>
     </Reference>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Target Name="PostBuildMacros">
     <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">

--- /dev/null
+++ b/KerbalEngineer/Smooth/Delegates/Delegates.cs
@@ -1,1 +1,25 @@
+using System;
 
+namespace Smooth.Delegates {
+	public delegate void DelegateAction();
+	public delegate void DelegateAction<in T1>(T1 _1);
+	public delegate void DelegateAction<in T1, in T2>(T1 _1, T2 _2);
+	public delegate void DelegateAction<in T1, in T2, in T3>(T1 _1, T2 _2, T3 _3);
+	public delegate void DelegateAction<in T1, in T2, in T3, in T4>(T1 _1, T2 _2, T3 _3, T4 _4);
+	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5);
+	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6);
+	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6, in T7>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7);
+	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8);
+	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8, T9 _9);
+
+	public delegate R DelegateFunc<out R>();
+	public delegate R DelegateFunc<in T1, out R>(T1 _1);
+	public delegate R DelegateFunc<in T1, in T2, out R>(T1 _1, T2 _2);
+	public delegate R DelegateFunc<in T1, in T2, in T3, out R>(T1 _1, T2 _2, T3 _3);
+	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, out R>(T1 _1, T2 _2, T3 _3, T4 _4);
+	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5);
+	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6);
+	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, in T7, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7);
+	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8);
+	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8, T9 _9);
+}

--- /dev/null
+++ b/KerbalEngineer/Smooth/Dispose/Disposable.cs
@@ -1,1 +1,106 @@
+using System;
+using Smooth.Delegates;
+using Smooth.Pools;
 
+namespace Smooth.Dispose {
+
+#if UNITY_IOS || UNITY_PS3 || UNITY_XBOX360 || UNITY_WII
+
+	/// <summary>
+	/// Wrapper around a value that uses the IDisposable interface to dispose of the value.
+	/// 
+	/// On iOS, this is a struct to avoid compute_class_bitmap errors.
+	/// 
+	/// On other platforms, it is a pooled object to avoid boxing when disposed by a using block with the Unity compiler.
+	/// </summary>
+	public struct Disposable<T> : IDisposable {
+		/// <summary>
+		/// Borrows a wrapper for the specified value and disposal delegate.
+		/// </summary>
+		public static Disposable<T> Borrow(T value, DelegateAction<T> dispose) {
+			return new Disposable<T>(value, dispose);
+		}
+		
+		private readonly DelegateAction<T> dispose;
+
+		/// <summary>
+		/// The wrapped value.
+		/// </summary>
+		public readonly T value;
+
+		public Disposable(T value, DelegateAction<T> dispose) {
+			this.value = value;
+			this.dispose = dispose;
+		}
+		
+		/// <summary>
+		/// Relinquishes ownership of the wrapper and disposes the wrapped value.
+		/// </summary>
+		public void Dispose() {
+			dispose(value);
+		}
+		
+		/// <summary>
+		/// Relinquishes ownership of the wrapper and adds it to the disposal queue.
+		/// </summary>
+		public void DisposeInBackground() {
+			DisposalQueue.Enqueue(this);
+		}
+	}
+
+#else
+
+	/// <summary>
+	/// Wrapper around a value that uses the IDisposable interface to dispose of the value.
+	/// 
+	/// On IOS, this is a value type to avoid compute_class_bitmap errors.
+	/// 
+	/// On other platforms, it is a pooled object to avoid boxing when disposed by a using block with the Unity compiler.
+	/// </summary>
+	public class Disposable<T> : IDisposable {
+		private static readonly Pool<Disposable<T>> pool = new Pool<Disposable<T>>(
+			() => new Disposable<T>(),
+			wrapper => {
+				wrapper.dispose(wrapper.value);
+				wrapper.dispose = t => {};
+				wrapper.value = default(T);
+			}
+		);
+
+		/// <summary>
+		/// Borrows a wrapper for the specified value and disposal delegate.
+		/// </summary>
+		public static Disposable<T> Borrow(T value, DelegateAction<T> dispose) {
+			var wrapper = pool.Borrow();
+			wrapper.value = value;
+			wrapper.dispose = dispose;
+			return wrapper;
+		}
+
+		private DelegateAction<T> dispose;
+
+		/// <summary>
+		/// The wrapped value.
+		/// </summary>
+		public T value { get; private set; }
+		
+		private Disposable() {}
+
+		/// <summary>
+		/// Relinquishes ownership of the wrapper, disposes the wrapped value, and returns the wrapper to the pool.
+		/// </summary>
+		public void Dispose() {
+			pool.Release(this);
+		}
+
+		/// <summary>
+		/// Relinquishes ownership of the wrapper and adds it to the disposal queue.
+		/// </summary>
+		public void DisposeInBackground() {
+			DisposalQueue.Enqueue(this);
+		}
+	}
+
+#endif
+
+}

--- /dev/null
+++ b/KerbalEngineer/Smooth/Dispose/DisposalQueue.cs
@@ -1,1 +1,67 @@
+using UnityEngine;
+using System;
+using System.Collections.Generic;
+using System.Threading;
 
+namespace Smooth.Dispose {
+
+	/// <summary>
+	/// Queues pooled resources for cleanup by a background thread.
+	/// 
+	/// By default, the disposal thread is woken up at the end of LateUpdate, when there is likely to be free CPU time available while GPU operations are in progress.
+	/// 
+	/// Various pools may be locked and unlocked while resources are released, potentially causing contention if pooled resources are borrowed during the disposal process.
+	/// 
+	/// Advanced users who are using pools from the main thread during the rendering phase may want to customize the point in the Unity event loop when the queue lock is pulsed, potentially pulsing from a Camera event.
+	/// </summary>
+	public static class DisposalQueue {
+		private static readonly object queueLock = new object();
+		private static Queue<IDisposable> enqueue = new Queue<IDisposable>();
+		private static Queue<IDisposable> dispose = new Queue<IDisposable>();
+
+		/// <summary>
+		/// Adds the specified item to the disposal queue.
+		/// </summary>
+		public static void Enqueue(IDisposable item) {
+			lock (queueLock) {
+				enqueue.Enqueue(item);
+			}
+		}
+
+		/// <summary>
+		/// Pulses the queue lock, potentially waking up the disposal thread.
+		/// </summary>
+		public static void Pulse() {
+			lock (queueLock) {
+				Monitor.Pulse(queueLock);
+			}
+		}
+
+		private static void Dispose() {
+			while (true) {
+				lock (queueLock) {
+					while (enqueue.Count == 0) {
+						Monitor.Wait(queueLock);
+					}
+					var t = enqueue;
+					enqueue = dispose;
+					dispose = t;
+				}
+				while (dispose.Count > 0) {
+					try {
+						dispose.Dequeue().Dispose();
+					} catch (ThreadAbortException) {
+					} catch (Exception e) {
+						Debug.LogError(e);
+					}
+				}
+			}
+		}
+
+		static DisposalQueue() {
+			new Thread(new ThreadStart(Dispose)).Start();
+			new GameObject(typeof(SmoothDisposer).Name).AddComponent<SmoothDisposer>();
+		}
+	}
+}
+

--- /dev/null
+++ b/KerbalEngineer/Smooth/Dispose/SmoothDisposer.cs
@@ -1,1 +1,21 @@
+using UnityEngine;
+using System;
+using Smooth.Dispose;
 
+public class SmoothDisposer : MonoBehaviour {
+	private static SmoothDisposer instance;
+
+	private void Awake() {
+		if (instance) {
+			Debug.LogWarning("Only one " + GetType().Name + " should exist at a time, instantiated by the " + typeof(DisposalQueue).Name + " class.");
+			Destroy(this);
+		} else {
+			instance = this;
+			DontDestroyOnLoad(this);
+		}
+	}
+	
+	private void LateUpdate() {
+		DisposalQueue.Pulse();
+	}
+}

--- /dev/null
+++ b/KerbalEngineer/Smooth/Pools/Pool.cs
@@ -1,1 +1,60 @@
+using System;
+using System.Collections.Generic;
+using Smooth.Delegates;
+using Smooth.Dispose;
 
+namespace Smooth.Pools {
+	/// <summary>
+	/// Pool that lends values of type T.
+	/// </summary>
+	public class Pool<T> {
+		private readonly Stack<T> values = new Stack<T>();
+
+		private readonly DelegateFunc<T> create;
+		private readonly DelegateAction<T> reset;
+		private readonly DelegateAction<T> release;
+
+		private Pool() {}
+		
+		/// <summary>
+		/// Creates a new pool with the specified value creation and reset delegates.
+		/// </summary>
+		public Pool(DelegateFunc<T> create, DelegateAction<T> reset) {
+			this.create = create;
+			this.reset = reset;
+			this.release = Release;
+		}
+
+		/// <summary>
+		/// Borrows a value from the pool.
+		/// </summary>
+		public T Borrow() {
+			lock (values) {
+				return values.Count > 0 ? values.Pop() : create();
+			}
+		}
+		
+		/// <summary>
+		/// Relinquishes ownership of the specified value and returns it to the pool.
+		/// </summary>
+		public void Release(T value) {
+			reset(value);
+			lock (values) {
+				values.Push(value);
+			}
+		}
+
+		/// <summary>
+		/// Borrows a wrapped value from the pool.
+		/// </summary>
+		public Disposable<T> BorrowDisposable() {
+			return Disposable<T>.Borrow(Borrow(), release);
+		}
+
+        public int Count()
+	    {
+	        return values.Count;
+	    }
+
+	}
+}

--- a/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
+++ b/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
@@ -19,44 +19,62 @@
 
 #region Using Directives
 
+using System;
+using System.Text;
+
 #endregion
 
 namespace KerbalEngineer.VesselSimulator
 {
-    using System;
-    using System.Text;
+    internal class AttachNodeSim
+    {
 
-    internal class AttachNodeSim : Pool<AttachNodeSim>
-    {
+        private static readonly Pool<AttachNodeSim> pool = new Pool<AttachNodeSim>(Create, Reset);
+
         public PartSim attachedPartSim;
         public String id;
         public AttachNode.NodeType nodeType;
 
+        private static AttachNodeSim Create()
+        {
+            return new AttachNodeSim();
+        }
+
+        public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
+        {
+            AttachNodeSim nodeSim = pool.Borrow();
+
+            nodeSim.attachedPartSim = partSim;
+            nodeSim.nodeType = newNodeType;
+            nodeSim.id = newId;
+
+            return nodeSim;
+        }
+
+        static private void Reset(AttachNodeSim attachNodeSim) { }
+
+
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
         public void DumpToBuffer(StringBuilder buffer)
         {
-            if (attachedPartSim == null)
+            if (this.attachedPartSim == null)
             {
                 buffer.Append("<staged>:<n>");
             }
             else
             {
-                buffer.Append(attachedPartSim.name);
+                buffer.Append(this.attachedPartSim.name);
                 buffer.Append(":");
-                buffer.Append(attachedPartSim.partId);
+                buffer.Append(this.attachedPartSim.partId);
             }
             buffer.Append("#");
-            buffer.Append(nodeType);
+            buffer.Append(this.nodeType);
             buffer.Append(":");
-            buffer.Append(id);
-        }
-
-        public AttachNodeSim Initialise(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
-        {
-            attachedPartSim = partSim;
-            nodeType = newNodeType;
-            id = newId;
-
-            return this;
+            buffer.Append(this.id);
         }
     }
 }

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -17,89 +17,217 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
+#region Using Directives
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+#endregion
+
 namespace KerbalEngineer.VesselSimulator
 {
-    using System;
-    using System.Collections.Generic;
-    using System.Text;
-    using Editor;
-    using Helpers;
-    using UnityEngine;
-
-    public class EngineSim : Pool<EngineSim>
+    public class EngineSim
     {
-        public double actualThrust = 0.0;
-        public List<AppliedForce> appliedForces = new List<AppliedForce>();
+        private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
+
+        private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
+
+        public double actualThrust = 0;
         public bool isActive = false;
         public double isp = 0;
         public PartSim partSim;
-        public float maxMach;
+        public List<AppliedForce> appliedForces = new List<AppliedForce>();
 
         public double thrust = 0;
 
         // Add thrust vector to account for directional losses
         public Vector3 thrustVec;
-        private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
-
-        public EngineSim Initialise(PartSim theEngine,
-            double atmosphere,
-            float machNumber,
-            float maxFuelFlow,
-            float minFuelFlow,
-            float thrustPercentage,
-            Vector3 vecThrust,
-            FloatCurve atmosphereCurve,
-            bool atmChangeFlow,
-            FloatCurve atmCurve,
-            FloatCurve velCurve,
-            float currentThrottle,
-            bool throttleLocked,
-            List<Propellant> propellants,
-            bool active,
-            float resultingThrust,
-            List<Transform> thrustTransforms)
-        {
+
+        private static EngineSim Create()
+        {
+            return new EngineSim();
+        }
+
+        private static void Reset(EngineSim engineSim)
+        {
+            engineSim.resourceConsumptions.Reset();
+            engineSim.actualThrust = 0;
+            engineSim.isActive = false;
+            engineSim.isp = 0;
+            for (int i = 0; i < engineSim.appliedForces.Count; i++)
+            {
+                engineSim.appliedForces[i].Release();
+            }
+            engineSim.appliedForces.Clear();
+            engineSim.thrust = 0;
+        }
+
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
+        public static EngineSim New(PartSim theEngine,
+                         double atmosphere,
+                         double machNumber,
+                         float maxFuelFlow,
+                         float minFuelFlow,
+                         float thrustPercentage,
+                         Vector3 vecThrust,
+                         FloatCurve atmosphereCurve,
+                         bool atmChangeFlow,
+                         FloatCurve atmCurve,
+                         FloatCurve velCurve,
+                         float currentThrottle,
+                         float IspG,
+                         bool throttleLocked,
+                         List<Propellant> propellants,
+                         bool active,
+                         bool correctThrust,
+                         List<Transform> thrustTransforms)
+        {
+            EngineSim engineSim = pool.Borrow();
+
+
             StringBuilder buffer = null;
-
-            isp = 0.0;
-            maxMach = 0.0f;
-            actualThrust = 0.0;
-            partSim = theEngine;
-            isActive = active;
-            thrustVec = vecThrust;
-            resourceConsumptions.Reset();
-            appliedForces.Clear();
-
-            double flowRate = 0.0;
-            if (partSim.hasVessel)
-            {
-                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, partSim.part.atmDensity, velCurve, machNumber, ref maxMach);
-                isp = atmosphereCurve.Evaluate((float)atmosphere);
-                thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, isp);
-                actualThrust = isActive ? resultingThrust : 0.0;
+            //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);
+
+            engineSim.partSim = theEngine;
+
+            engineSim.isActive = active;
+            //this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
+            //MonoBehaviour.print("thrust = " + thrust);
+
+            engineSim.thrustVec = vecThrust;
+
+            double flowRate = 0d;
+            if (engineSim.partSim.hasVessel)
+            {
+                //MonoBehaviour.print("hasVessel is true");
+
+                //this.actualThrust = this.isActive ? resultingThrust : 0.0;
+
+                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
+
+                //if (this.isp == 0d)
+                //{
+                //    MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
+                //}
+
+
+                // correctThrust is less usefull now that the stock engines do it. Keep or remove.
+
+                //if (correctThrust && realIsp == 0)
+                //{
+                //    float ispsl = atmosphereCurve.Evaluate(0);
+                //    if (ispsl != 0)
+                //    {
+                //        this.thrust = this.thrust * this.isp / ispsl;
+                //    }
+                //    else
+                //    {
+                //        MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
+                //    }
+                //    //MonoBehaviour.print("corrected thrust = " + thrust);
+                //}
+
+                //if (velocityCurve != null)
+                //{
+                //    this.thrust *= velocityCurve.Evaluate((float)velocity);
+                //    //MonoBehaviour.print("thrust at velocity = " + thrust);
+                //}
+                
+                float multiplier = 1;
+                if (atmChangeFlow)
+                {
+                    multiplier = (float)(theEngine.part.atmDensity / 1.225);
+                    if (atmCurve != null)
+                    {
+                        multiplier = atmCurve.Evaluate(multiplier);
+                    }
+                    //MonoBehaviour.print("corrected thrust = " + thrust);
+                }
+                if (velCurve != null)
+                {
+                    multiplier *= velCurve.Evaluate((float)machNumber);
+                }
 
                 if (throttleLocked)
                 {
-                    flowRate = GetFlowRate(thrust, isp);
+                    //MonoBehaviour.print("throttleLocked is true");
+                    //flowRate = this.thrust / (this.isp * 9.82);
+                    flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier;
                 }
                 else
                 {
-                    if (currentThrottle > 0.0f && partSim.isLanded == false)
-                    {
-                        flowRate = GetFlowRate(actualThrust, isp);
+                    if (theEngine.isLanded)
+                    {
+                        //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
+                        flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, FlightInputHandler.state.mainThrottle * (thrustPercentage / 100f)) * multiplier;
                     }
                     else
                     {
-                        flowRate = GetFlowRate(thrust, isp);
+                        if (currentThrottle > 0)
+                        {
+                            //MonoBehaviour.print("requestedThrust > 0");
+                            //flowRate = requestedThrust / (this.isp * 9.82) * multiplier;
+                            flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, currentThrottle * (thrustPercentage / 100f)) * multiplier;
+                        }
+                        else
+                        {
+                            //MonoBehaviour.print("requestedThrust <= 0");
+                            flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier;
+                        }
                     }
                 }
             }
             else
             {
-                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, ref maxMach);
-                isp = atmosphereCurve.Evaluate((float)atmosphere);
-                thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, isp);
-                flowRate = GetFlowRate(thrust, isp);
+                //MonoBehaviour.print("hasVessel is false");
+                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
+                if (engineSim.isp == 0d)
+                {
+                    MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
+                }
+                //if (correctThrust)
+                //{
+                //    float ispsl = atmosphereCurve.Evaluate(0);
+                //    if (ispsl != 0)
+                //    {
+                //        this.thrust = this.thrust * this.isp / ispsl;
+                //    }
+                //    else
+                //    {
+                //        MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
+                //    }
+                //    //MonoBehaviour.print("corrected thrust = " + thrust);
+                //}
+
+                float multiplier = 1;
+                if (atmChangeFlow)
+                {
+                    //multiplier = (float)(this.partSim.part.atmDensity / 1.225);
+                    multiplier = (float)atmosphere;    // technically wrong but the same for my Editor need
+                    if (atmCurve != null)
+                    {
+                        multiplier = atmCurve.Evaluate(multiplier);
+                    }
+                }
+
+                if (velCurve != null)
+                {
+                    multiplier *= velCurve.Evaluate((float)machNumber);
+                }
+
+                flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier;
             }
 
             if (SimManager.logOutput)
@@ -108,8 +236,12 @@
                 buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
             }
 
+            engineSim.thrust = flowRate * (engineSim.isp * IspG);
+            // I did not look into the diff between those 2 so I made them equal...
+            engineSim.actualThrust = engineSim.thrust;
+
             float flowMass = 0f;
-            for (int i = 0; i < propellants.Count; ++i)
+            for (int i = 0; i < propellants.Count; i++)
             {
                 Propellant propellant = propellants[i];
                 flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
@@ -120,10 +252,9 @@
                 buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
             }
 
-            for (int i = 0; i < propellants.Count; ++i)
+            for (int i = 0; i < propellants.Count; i++)
             {
                 Propellant propellant = propellants[i];
-
                 if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                 {
                     continue;
@@ -132,9 +263,14 @@
                 double consumptionRate = propellant.ratio * flowRate / flowMass;
                 if (SimManager.logOutput)
                 {
-                    buffer.AppendFormat("Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate);
-                }
-                resourceConsumptions.Add(propellant.id, consumptionRate);
+                    buffer.AppendFormat(
+                        "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
+                        ResourceContainer.GetResourceName(propellant.id),
+                        theEngine.name,
+                        theEngine.partId,
+                        consumptionRate);
+                }
+                engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
             }
 
             if (SimManager.logOutput)
@@ -142,134 +278,90 @@
                 MonoBehaviour.print(buffer);
             }
 
-            appliedForces.Clear();
-            double thrustPerThrustTransform = thrust / thrustTransforms.Count;
-            for (int i = 0; i < thrustTransforms.Count; ++i)
+            double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
+            for (int i = 0; i < thrustTransforms.Count; i++)
             {
                 Transform thrustTransform = thrustTransforms[i];
                 Vector3d direction = thrustTransform.forward.normalized;
                 Vector3d position = thrustTransform.position;
-                appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position));
-            }
-
-            return this;
+
+                AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
+                engineSim.appliedForces.Add(appliedForce);
+            }
+            return engineSim;
         }
 
         public ResourceContainer ResourceConsumptions
         {
-            get
-            {
-                return resourceConsumptions;
-            }
-        }
-
-        public static double GetExhaustVelocity(double isp)
-        {
-            return isp * Units.GRAVITY;
-        }
-
-        public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach)
-        {
-            float flowModifier = 1.0f;
-            if (atmChangeFlow)
-            {
-                flowModifier = (float)(atmDensity / 1.225);
-                if (atmCurve != null)
-                {
-                    flowModifier = atmCurve.Evaluate(flowModifier);
-                }
-            }
-            if (velCurve != null)
-            {
-                flowModifier = flowModifier * velCurve.Evaluate(machNumber);
-                maxMach = velCurve.maxTime;
-            }
-            if (flowModifier < float.Epsilon)
-            {
-                flowModifier = float.Epsilon;
-            }
-            return flowModifier;
-        }
-
-        public static double GetFlowRate(double thrust, double isp)
-        {
-            return thrust / GetExhaustVelocity(isp);
-        }
-
-        public static float GetThrottlePercent(float currentThrottle, float thrustPercentage)
-        {
-            return currentThrottle * GetThrustPercent(thrustPercentage);
-        }
-
-        public static double GetThrust(double flowRate, double isp)
-        {
-            return flowRate * GetExhaustVelocity(isp);
-        }
-
-        public static float GetThrustPercent(float thrustPercentage)
-        {
-            return thrustPercentage * 0.01f;
-        }
-
-        public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
-        {
-            buffer.Append(prefix);
-            buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", thrust, actualThrust, isp);
-        }
+            get { return this.resourceConsumptions; }
+        }
+
+        // A dictionary to hold a set of parts for each resource
+        Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
+
+        Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
+
+        HashSet<PartSim> visited = new HashSet<PartSim>();
 
         public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
         {
             LogMsg log = null;
-
-            // A dictionary to hold a set of parts for each resource
-            Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
-
-            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
-            {
-                int type = resourceConsumptions.Types[i];
-
-                HashSet<PartSim> sourcePartSet = null;
+            
+            foreach (HashSet<PartSim> sourcePartSet in sourcePartSets.Values)
+            {
+                sourcePartSet.Clear();
+            }
+
+            for (int index = 0; index < this.resourceConsumptions.Types.Count; index++)
+            {
+                int type = this.resourceConsumptions.Types[index];
+
+                HashSet<PartSim> sourcePartSet;
+                if (!sourcePartSets.TryGetValue(type, out sourcePartSet))
+                {
+                    sourcePartSet = new HashSet<PartSim>();
+                    sourcePartSets.Add(type, sourcePartSet);
+                }
                 switch (ResourceContainer.GetResourceFlowMode(type))
                 {
                     case ResourceFlowMode.NO_FLOW:
-                        if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0)
-                        {
-                            sourcePartSet = new HashSet<PartSim>();
+                        if (this.partSim.resources[type] > SimManager.RESOURCE_MIN && this.partSim.resourceFlowStates[type] != 0)
+                        {
+                            //sourcePartSet = new HashSet<PartSim>();
                             //MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this");
-                            sourcePartSet.Add(partSim);
+                            sourcePartSet.Add(this.partSim);
                         }
                         break;
 
                     case ResourceFlowMode.ALL_VESSEL:
-                        for (int j = 0; j < allParts.Count; ++j)
-                        {
-                            PartSim aPartSim = allParts[j];
+                        for (int i = 0; i < allParts.Count; i++)
+                        {
+                            PartSim aPartSim = allParts[i];
                             if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0)
                             {
-                                if (sourcePartSet == null)
-                                {
-                                    sourcePartSet = new HashSet<PartSim>();
-                                }
-
                                 sourcePartSet.Add(aPartSim);
                             }
                         }
                         break;
 
                     case ResourceFlowMode.STAGE_PRIORITY_FLOW:
-                        Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
-                        int maxStage = -1;
+
+                        foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values)
+                        {
+                            stagePartSet.Clear();
+                        }
+                        var maxStage = -1;
 
                         //Logger.Log(type);
-                        for (int j = 0; j < allParts.Count; ++j)
-                        {
-                            PartSim aPartSim = allParts[j];
+                        for (int i = 0; i < allParts.Count; i++)
+                        {
+                            var aPartSim = allParts[i];
                             if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
                             {
                                 continue;
                             }
 
-                            int stage = aPartSim.DecouplerCount();
+                            var stage = aPartSim.DecouplerCount();
                             if (stage > maxStage)
                             {
                                 maxStage = stage;
@@ -283,10 +375,10 @@
                             sourcePartSet.Add(aPartSim);
                         }
 
-                        for (int j = 0; j <= maxStage; j++)
+                        for (var i = 0; i <= maxStage; i++)
                         {
                             HashSet<PartSim> stagePartSet;
-                            if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
+                            if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0)
                             {
                                 sourcePartSet = stagePartSet;
                             }
@@ -294,14 +386,16 @@
                         break;
 
                     case ResourceFlowMode.STACK_PRIORITY_SEARCH:
-                        HashSet<PartSim> visited = new HashSet<PartSim>();
+                        visited.Clear();
 
                         if (SimManager.logOutput)
                         {
                             log = new LogMsg();
-                            log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId);
-                        }
-                        sourcePartSet = partSim.GetSourceSet(type, allParts, visited, log, "");
+                            log.buf.AppendLine(
+                                "Find " + ResourceContainer.GetResourceName(type) + " sources for " + this.partSim.name + ":" +
+                                this.partSim.partId);
+                        }
+                        this.partSim.GetSourceSet(type, allParts, visited, sourcePartSet, log, "");
                         if (SimManager.logOutput)
                         {
                             MonoBehaviour.print(log.buf);
@@ -309,11 +403,14 @@
                         break;
 
                     default:
-                        MonoBehaviour.print("SetResourceDrains(" + partSim.name + ":" + partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
+                        MonoBehaviour.print(
+                            "SetResourceDrains(" + this.partSim.name + ":" + this.partSim.partId + ") Unexpected flow type for " +
+                            ResourceContainer.GetResourceName(type) + ")");
                         break;
                 }
 
-                if (sourcePartSet != null && sourcePartSet.Count > 0)
+
+                if (sourcePartSet.Count > 0)
                 {
                     sourcePartSets[type] = sourcePartSet;
                     if (SimManager.logOutput)
@@ -328,45 +425,50 @@
                     }
                 }
             }
-
+            
             // If we don't have sources for all the needed resources then return false without setting up any drains
-            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
-            {
-                int type = resourceConsumptions.Types[i];
-
-                if (!sourcePartSets.ContainsKey(type))
+            for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
+            {
+                int type = this.resourceConsumptions.Types[i];
+                HashSet<PartSim> sourcePartSet; 
+                if (!sourcePartSets.TryGetValue(type, out sourcePartSet) || sourcePartSet.Count() == 0)
                 {
                     if (SimManager.logOutput)
                     {
                         MonoBehaviour.print("No source of " + ResourceContainer.GetResourceName(type));
                     }
 
-                    isActive = false;
+                    this.isActive = false;
                     return false;
                 }
             }
-
             // Now we set the drains on the members of the sets and update the draining parts set
-            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
-            {
-                int type = resourceConsumptions.Types[i];
-
+            for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
+            {
+                int type = this.resourceConsumptions.Types[i];
                 HashSet<PartSim> sourcePartSet = sourcePartSets[type];
                 // Loop through the members of the set 
-                double amount = resourceConsumptions[type] / sourcePartSet.Count;
+                double amount = this.resourceConsumptions[type] / sourcePartSet.Count;
                 foreach (PartSim partSim in sourcePartSet)
                 {
                     if (SimManager.logOutput)
                     {
-                        MonoBehaviour.print("Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" + partSim.partId);
+                        MonoBehaviour.print(
+                            "Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" +
+                            partSim.partId);
                     }
 
                     partSim.resourceDrains.Add(type, amount);
                     drainingParts.Add(partSim);
                 }
             }
-
             return true;
+        }
+
+        public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
+        {
+            buffer.Append(prefix);
+            buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", this.thrust, this.actualThrust, this.isp);
         }
     }
 }

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -18,22 +18,29 @@
 // 
 
 #region Using Directives
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using KerbalEngineer.Extensions;
+using UnityEngine;
+
 #endregion
 
 namespace KerbalEngineer.VesselSimulator
 {
-    using System;
-    using System.Collections.Generic;
-    using System.Linq;
-    using System.Text;
     using CompoundParts;
-    using Extensions;
-    using UnityEngine;
-
-    public class PartSim : Pool<PartSim>
+
+    public class PartSim
     {
-        public double baseMass;
+        private static readonly Pool<PartSim> pool = new Pool<PartSim>(Create, Reset);
+
+        private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+
         public Vector3d centerOfMass;
+        public double baseMass = 0d;
         public double cost;
         public int decoupledInStage;
         public bool fuelCrossFeed;
@@ -52,10 +59,7 @@
         public bool isLanded;
         public bool isNoPhysics;
         public bool isSepratron;
-        public bool isFairing;
         public bool localCorrectThrust;
-        public float moduleMass;
-        public int stageIndex;
         public String name;
         public String noCrossFeedNodeKey;
         public PartSim parent;
@@ -68,51 +72,157 @@
         public double startMass = 0d;
         public String vesselName;
         public VesselType vesselType;
-        private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+        
+
+        private static PartSim Create()
+        {
+            return new PartSim();
+        }
+
+        private static void Reset(PartSim partSim)
+        {
+            for (int i = 0; i < partSim.attachNodes.Count; i++)
+            {
+                partSim.attachNodes[i].Release();
+            }
+            partSim.attachNodes.Clear();
+            partSim.fuelTargets.Clear();
+            partSim.resourceDrains.Reset();
+            partSim.resourceFlowStates.Reset();
+            partSim.resources.Reset();
+            partSim.baseMass = 0d;
+            partSim.startMass = 0d;
+        }
+
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
+        public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log)
+        {
+            PartSim partSim = pool.Borrow();
+
+
+            partSim.part = thePart;
+            partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
+            partSim.partId = id;
+            partSim.name = partSim.part.partInfo.name;
+
+            if (log != null)
+            {
+                log.buf.AppendLine("Create PartSim for " + partSim.name);
+            }
+
+            partSim.parent = null;
+            partSim.parentAttach = partSim.part.attachMode;
+            partSim.fuelCrossFeed = partSim.part.fuelCrossFeed;
+            partSim.noCrossFeedNodeKey = partSim.part.NoCrossFeedNodeKey;
+            partSim.decoupledInStage = partSim.DecoupledInStage(partSim.part);
+            partSim.isFuelLine = partSim.part.HasModule<CModuleFuelLine>();
+            partSim.isFuelTank = partSim.part is FuelTank;
+            partSim.isSepratron = partSim.IsSepratron();
+            partSim.inverseStage = partSim.part.inverseStage;
+            //MonoBehaviour.print("inverseStage = " + inverseStage);
+
+            partSim.cost = partSim.part.GetCostWet();
+
+            // Work out if the part should have no physical significance
+            partSim.isNoPhysics = partSim.part.HasModule<LaunchClamp>() ||
+                               partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
+                               partSim.part.PhysicsSignificance == 1;
+
+            if (!partSim.isNoPhysics)
+            {
+                partSim.baseMass = partSim.part.mass;
+            }
+
+            if (SimManager.logOutput)
+            {
+                MonoBehaviour.print((partSim.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + partSim.part.mass);
+            }
+
+            for (int i = 0; i < partSim.part.Resources.Count; i++)
+            {
+                PartResource resource = partSim.part.Resources[i];
+
+                // Make sure it isn't NaN as this messes up the part mass and hence most of the values
+                // This can happen if a resource capacity is 0 and tweakable
+                if (!Double.IsNaN(resource.amount))
+                {
+                    if (SimManager.logOutput)
+                    {
+                        MonoBehaviour.print(resource.resourceName + " = " + resource.amount);
+                    }
+
+                    partSim.resources.Add(resource.info.id, resource.amount);
+                    partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
+                }
+                else
+                {
+                    MonoBehaviour.print(resource.resourceName + " is NaN. Skipping.");
+                }
+            }
+
+            partSim.startMass = partSim.GetMass();
+
+            partSim.hasVessel = (partSim.part.vessel != null);
+            partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed;
+            if (partSim.hasVessel)
+            {
+                partSim.vesselName = partSim.part.vessel.vesselName;
+                partSim.vesselType = partSim.part.vesselType;
+            }
+            partSim.initialVesselName = partSim.part.initialVesselName;
+
+            partSim.hasMultiModeEngine = partSim.part.HasModule<MultiModeEngine>();
+            partSim.hasModuleEnginesFX = partSim.part.HasModule<ModuleEnginesFX>();
+            partSim.hasModuleEngines = partSim.part.HasModule<ModuleEngines>();
+
+            partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines;
+
+            if (SimManager.logOutput)
+            {
+                MonoBehaviour.print("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
+            }
+            return partSim;
+        }
+
+        public ResourceContainer Resources
+        {
+            get { return this.resources; }
+        }
 
         public ResourceContainer ResourceDrains
         {
-            get
-            {
-                return resourceDrains;
-            }
-        }
-
-        public ResourceContainer Resources
-        {
-            get
-            {
-                return resources;
-            }
+            get { return this.resourceDrains; }
         }
 
         public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double mach, bool vectoredThrust, bool fullThrust, LogMsg log)
         {
-            bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(part);
+            bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(this.part);
             if (log != null)
             {
-                log.buf.AppendLine("CreateEngineSims for " + name);
-
-                foreach (PartModule partMod in part.Modules)
-                {
+                log.buf.AppendLine("CreateEngineSims for " + this.name);
+                for (int i = 0; i < this.part.Modules.Count; i++)
+                {
+                    PartModule partMod = this.part.Modules[i];
                     log.buf.AppendLine("Module: " + partMod.moduleName);
                 }
 
                 log.buf.AppendLine("correctThrust = " + correctThrust);
             }
 
-            if (hasMultiModeEngine)
+            if (this.hasMultiModeEngine)
             {
                 // A multi-mode engine has multiple ModuleEnginesFX but only one is active at any point
                 // The mode of the engine is the engineID of the ModuleEnginesFX that is active
-                string mode = part.GetModule<MultiModeEngine>().mode;
-
-                List<ModuleEnginesFX> engines = part.GetModules<ModuleEnginesFX>();
-
-                for (int i = 0; i < engines.Count; ++i)
-                {
-                    ModuleEnginesFX engine = engines[i];
-
+                string mode = this.part.GetModule<MultiModeEngine>().mode;
+
+                List<ModuleEnginesFX> enginesFx = this.part.GetModules<ModuleEnginesFX>();
+                for (int i = 0; i < enginesFx.Count; i++)
+                {
+                    ModuleEnginesFX engine = enginesFx[i];
                     if (engine.engineID == mode)
                     {
                         if (log != null)
@@ -120,11 +230,12 @@
                             log.buf.AppendLine("Module: " + engine.moduleName);
                         }
 
-                        Vector3 thrustvec = CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
-
-                        EngineSim engineSim = EngineSim.GetPoolObject().Initialise(this,
+                        Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
+
+                        EngineSim engineSim = EngineSim.New(
+                            this,
                             atmosphere,
-                            (float)mach,
+                            mach,
                             engine.maxFuelFlow,
                             engine.minFuelFlow,
                             engine.thrustPercentage,
@@ -134,10 +245,11 @@
                             engine.useAtmCurve ? engine.atmCurve : null,
                             engine.useVelCurve ? engine.velCurve : null,
                             engine.currentThrottle,
+                            engine.g,
                             engine.throttleLocked || fullThrust,
                             engine.propellants,
                             engine.isOperational,
-                            engine.resultingThrust,
+                            correctThrust,
                             engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
@@ -145,10 +257,10 @@
             }
             else
             {
-                if (hasModuleEngines)
-                {
-                    List<ModuleEngines> engines = part.GetModules<ModuleEngines>();
-                    for (int i = 0; i < engines.Count; ++i)
+                if (this.hasModuleEngines)
+                {
+                    List<ModuleEngines> engines = this.part.GetModules<ModuleEngines>();  // only place that still allocate some memory
+                    for (int i = 0; i < engines.Count; i++)
                     {
                         ModuleEngines engine = engines[i];
                         if (log != null)
@@ -156,11 +268,12 @@
                             log.buf.AppendLine("Module: " + engine.moduleName);
                         }
 
-                        Vector3 thrustvec = CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
-
-                        EngineSim engineSim = EngineSim.GetPoolObject().Initialise(this,
+                        Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
+
+                        EngineSim engineSim = EngineSim.New(
+                            this,
                             atmosphere,
-                            (float)mach,
+                            mach,
                             engine.maxFuelFlow,
                             engine.minFuelFlow,
                             engine.thrustPercentage,
@@ -170,10 +283,11 @@
                             engine.useAtmCurve ? engine.atmCurve : null,
                             engine.useVelCurve ? engine.velCurve : null,
                             engine.currentThrottle,
+                            engine.g,
                             engine.throttleLocked || fullThrust,
                             engine.propellants,
                             engine.isOperational,
-                            engine.resultingThrust,
+                            correctThrust,
                             engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
@@ -186,146 +300,210 @@
             }
         }
 
-        public int DecouplerCount()
-        {
-            int count = 0;
-            PartSim partSim = this;
-            while (partSim != null)
-            {
-                if (partSim.isDecoupler)
-                {
-                    count++;
-                }
-
-                partSim = partSim.parent;
-            }
-            return count;
-        }
-
-        public void DrainResources(double time)
-        {
-            //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
-            for (int i = 0; i < resourceDrains.Types.Count; ++i)
-            {
-                int type = resourceDrains.Types[i];
-
-                //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
-                resources.Add(type, -time * resourceDrains[type]);
-                //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
-            }
-        }
-
-        public String DumpPartAndParentsToBuffer(StringBuilder buffer, String prefix)
-        {
-            if (parent != null)
-            {
-                prefix = parent.DumpPartAndParentsToBuffer(buffer, prefix) + " ";
-            }
-
-            DumpPartToBuffer(buffer, prefix);
-
-            return prefix;
-        }
-
-        public void DumpPartToBuffer(StringBuilder buffer, String prefix, List<PartSim> allParts = null)
-        {
-            buffer.Append(prefix);
-            buffer.Append(name);
-            buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", partId, decoupledInStage, inverseStage);
-
-            buffer.AppendFormat(", vesselName = '{0}'", vesselName);
-            buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
-            buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
-
-            buffer.AppendFormat(", fuelCF = {0}", fuelCrossFeed);
-            buffer.AppendFormat(", noCFNKey = '{0}'", noCrossFeedNodeKey);
-
-            buffer.AppendFormat(", isSep = {0}", isSepratron);
-
-            foreach (int type in resources.Types)
-            {
-                buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), resources[type]);
-            }
-
-            if (attachNodes.Count > 0)
-            {
-                buffer.Append(", attached = <");
-                attachNodes[0].DumpToBuffer(buffer);
-                for (int i = 1; i < attachNodes.Count; i++)
-                {
-                    buffer.Append(", ");
-                    attachNodes[i].DumpToBuffer(buffer);
-                }
-                buffer.Append(">");
-            }
-
-            // Add more info here
-
-            buffer.Append("]\n");
-
-            if (allParts != null)
-            {
-                String newPrefix = prefix + " ";
-                foreach (PartSim partSim in allParts)
-                {
-                    if (partSim.parent == this)
-                    {
-                        partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
-                    }
-                }
-            }
-        }
-
-        public bool EmptyOf(HashSet<int> types)
-        {
-            foreach (int type in types)
-            {
-                if (resources.HasType(type) && resourceFlowStates[type] != 0 && resources[type] > SimManager.RESOURCE_MIN)
-                {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        public double GetMass(int currentStage)
-        {
-            double mass = baseMass;
-
-            for (int i = 0; i < resources.Types.Count; ++i)
-            {
-                mass += resources.GetResourceMass(resources.Types[i]);
-            }
-
-            if (hasVessel == false && isFairing && inverseStage < currentStage)
-            {
-                mass = mass + moduleMass;
-            }
-
-            return mass;
-        }
-
-        public HashSet<PartSim> GetSourceSet(int type, List<PartSim> allParts, HashSet<PartSim> visited, LogMsg log, String indent)
-        {
+        private Vector3 CalculateThrustVector(List<Transform> thrustTransforms, LogMsg log)
+        {
+            if (thrustTransforms == null)
+            {
+                return Vector3.forward;
+            }
+
+            Vector3 thrustvec = Vector3.zero;
+            for (int i = 0; i < thrustTransforms.Count; i++)
+            {
+                Transform trans = thrustTransforms[i];
+                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.AppendLine(indent + "GetSourceSet(" + ResourceContainer.GetResourceName(type) + ") for " + name + ":" + partId);
+                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;
+        }
+
+        public void SetupParent(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
+        {
+            if (this.part.parent != null)
+            {
+                this.parent = null;
+                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 + ")");
+                    }
+                }
+            }
+        }
+
+        public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
+        {
+            if (log != null)
+            {
+                log.buf.AppendLine("SetupAttachNodes for " + this.name + ":" + this.partId + "");
+            }
+
+            this.attachNodes.Clear();
+            for (int i = 0; i < this.part.attachNodes.Count; i++)
+            {
+                AttachNode attachNode = this.part.attachNodes[i];
+                if (log != null)
+                {
+                    log.buf.AppendLine(
+                        "AttachNode " + attachNode.id + " = " +
+                        (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
+                }
+
+                if (attachNode.attachedPart != null && attachNode.id != "Strut")
+                {
+                    PartSim attachedSim;
+                    if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim))
+                    {
+                        if (log != null)
+                        {
+                            log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
+                        }
+
+                        AttachNodeSim attachnode = AttachNodeSim.New(attachedSim, attachNode.id, attachNode.nodeType);
+                        this.attachNodes.Add(attachnode);
+                    }
+                    else
+                    {
+                        if (log != null)
+                        {
+                            log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
+                        }
+                    }
+                }
+            }
+
+            for (int i = 0; i < this.part.fuelLookupTargets.Count; i++)
+            {
+                Part p = this.part.fuelLookupTargets[i];
+                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 + ")");
+                        }
+                    }
+                }
+            }
+        }
+
+        private int DecoupledInStage(Part thePart, int stage = -1)
+        {
+            if (this.IsDecoupler(thePart))
+            {
+                if (thePart.inverseStage > stage)
+                {
+                    stage = thePart.inverseStage;
+                }
+            }
+
+            if (thePart.parent != null)
+            {
+                stage = this.DecoupledInStage(thePart.parent, stage);
+            }
+
+            return stage;
+        }
+
+        private bool IsDecoupler(Part thePart)
+        {
+            return thePart.HasModule<ModuleDecouple>() ||
+                   thePart.HasModule<ModuleAnchoredDecoupler>();
+        }
+
+        private bool IsActiveDecoupler(Part thePart)
+        {
+            return thePart.FindModulesImplementing<ModuleDecouple>().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;
+            }
+
+            if (!this.part.IsEngine())
+            {
+                return false;
+            }
+
+
+            return this.part.IsSolidRocket();
+        }
+
+        public void ReleasePart()
+        {
+            this.part = null;
+        }
+
+        // All functions below this point must not rely on the part member (it may be null)
+        //
+
+        public void GetSourceSet(int type, List<PartSim> allParts, HashSet<PartSim> visited, HashSet<PartSim> allSources, LogMsg log, String indent)
+        {
+            if (log != null)
+            {
+                log.buf.AppendLine(indent + "GetSourceSet(" + ResourceContainer.GetResourceName(type) + ") for " + this.name + ":" + this.partId);
                 indent += "  ";
             }
 
-            HashSet<PartSim> allSources = new HashSet<PartSim>();
-            HashSet<PartSim> partSources = null;
-
-            // Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns empty list.
+            // Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns as is.
             if (visited.Contains(this))
             {
                 if (log != null)
                 {
-                    log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
-                }
-
-                return allSources;
+                    log.buf.AppendLine(indent + "Returning empty set, already visited (" + this.name + ":" + this.partId + ")");
+                }
+
+                return;
             }
 
             //if (log != null)
@@ -336,10 +514,12 @@
             // Rule 2: Part performs scan on start of every fuel pipe ending in it. This scan is done in order in which pipes were installed.
             // Then it makes an union of fuel tank sets each pipe scan returned. If the resulting list is not empty, it is returned as result.
             //MonoBehaviour.print("foreach fuel line");
-            for (int i = 0; i < fuelTargets.Count; ++i)
-            {
-                PartSim partSim = fuelTargets[i];
-
+
+            int lastCount = allSources.Count;
+
+            for (int i = 0; i < this.fuelTargets.Count; i++)
+            {
+                PartSim partSim = this.fuelTargets[i];
                 if (visited.Contains(partSim))
                 {
                     //if (log != null)
@@ -350,24 +530,20 @@
                     //if (log != null)
                     //    log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
 
-                    partSources = partSim.GetSourceSet(type, allParts, visited, log, indent);
-                    if (partSources.Count > 0)
-                    {
-                        allSources.UnionWith(partSources);
-                        partSources.Clear();
-                    }
-                }
-            }
-
-            if (allSources.Count > 0)
+                    partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
+                }
+            }
+
+            if (allSources.Count > lastCount)
             {
                 if (log != null)
                 {
-                    log.buf.AppendLine(indent + "Returning " + allSources.Count + " fuel target sources (" + name + ":" + partId + ")");
-                }
-
-                return allSources;
-            }
+                    log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
+                }
+
+                return;
+            }
+
 
             // Rule 3: This rule has been removed and merged with rules 4 and 7 to fix issue with fuel tanks with disabled crossfeed
 
@@ -376,18 +552,20 @@
             //  skip the points on the side where multiple points are. [Experiment]
             //  Again, the part creates union of scan lists from each of its neighbor and if it is not empty, returns this list. 
             //  The order in which mount points of a part are scanned appears to be fixed and defined by the part specification file. [Experiment]
-            if (fuelCrossFeed)
-            {
+            if (this.fuelCrossFeed)
+            {
+                lastCount = allSources.Count;
                 //MonoBehaviour.print("foreach attach node");
-                for (int i = 0; i < attachNodes.Count; ++i)
-                {
-                    AttachNodeSim attachSim = attachNodes[i];
-
+                for (int i = 0; i < this.attachNodes.Count; i++)
+                {
+                    AttachNodeSim attachSim = this.attachNodes[i];
                     if (attachSim.attachedPartSim != null)
                     {
                         if (attachSim.nodeType == AttachNode.NodeType.Stack)
                         {
-                            if (!(noCrossFeedNodeKey != null && noCrossFeedNodeKey.Length > 0 && attachSim.id.Contains(noCrossFeedNodeKey)))
+                            if (
+                                !(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 &&
+                                  attachSim.id.Contains(this.noCrossFeedNodeKey)))
                             {
                                 if (visited.Contains(attachSim.attachedPartSim))
                                 {
@@ -399,26 +577,21 @@
                                     //if (log != null)
                                     //    log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
 
-                                    partSources = attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, log, indent);
-                                    if (partSources.Count > 0)
-                                    {
-                                        allSources.UnionWith(partSources);
-                                        partSources.Clear();
-                                    }
+                                    attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
                                 }
                             }
                         }
                     }
                 }
 
-                if (allSources.Count > 0)
+                if (allSources.Count > lastCount)
                 {
                     if (log != null)
                     {
-                        log.buf.AppendLine(indent + "Returning " + allSources.Count + " attached sources (" + name + ":" + partId + ")");
-                    }
-
-                    return allSources;
+                        log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
+                    }
+
+                    return;
                 }
             }
 
@@ -426,43 +599,44 @@
             // type was not disabled [Experiment]) and it contains fuel, it returns itself.
             // Rule 6: 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) but it does not contain the requested fuel, it returns empty list. [Experiment]
-            if (resources.HasType(type) && resourceFlowStates[type] != 0)
-            {
-                if (resources[type] > SimManager.RESOURCE_MIN)
+            if (this.resources.HasType(type) && this.resourceFlowStates[type] != 0)
+            {
+                if (this.resources[type] > SimManager.RESOURCE_MIN)
                 {
                     allSources.Add(this);
 
                     if (log != null)
                     {
-                        log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
-                    }
-                }
-
-                return allSources;
+                        log.buf.AppendLine(indent + "Returning enabled tank as only source (" + this.name + ":" + this.partId + ")");
+                    }
+                }
+
+                return;
             }
 
             // Rule 7: If the part is radially attached to another part and it is child of that part in the ship's tree structure, it scans its 
             // parent and returns whatever the parent scan returned. [Experiment] [Experiment]
-            if (parent != null && parentAttach == AttachModes.SRF_ATTACH)
-            {
-                if (fuelCrossFeed)
-                {
-                    if (visited.Contains(parent))
+            if (this.parent != null && this.parentAttach == AttachModes.SRF_ATTACH)
+            {
+                if (this.fuelCrossFeed)
+                {
+                    if (visited.Contains(this.parent))
                     {
                         //if (log != null)
                         //    log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
                     }
                     else
                     {
-                        allSources = parent.GetSourceSet(type, allParts, visited, log, indent);
-                        if (allSources.Count > 0)
+                        lastCount = allSources.Count;
+                        this.parent.GetSourceSet(type, allParts, visited, allSources, log, indent);
+                        if (allSources.Count > lastCount)
                         {
                             if (log != null)
                             {
-                                log.buf.AppendLine(indent + "Returning " + allSources.Count + " parent sources (" + name + ":" + partId + ")");
+                                log.buf.AppendLine(indent + "Returning " + (allSources.Count  - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
                             }
 
-                            return allSources;
+                            return;
                         }
                     }
                 }
@@ -472,113 +646,15 @@
             //if (log != null)
             //    log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
 
-            return allSources;
-        }
-
-        public double GetStartMass()
-        {
-            return startMass;
-        }
-
-        public PartSim Initialise(Part thePart, int id, double atmosphere, LogMsg log)
-        {
-            Reset(this);
-
-            part = thePart;
-            hasVessel = (part.vessel != null);
-            centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
-            partId = id;
-            name = part.partInfo.name;
-
-            if (log != null)
-            {
-                log.buf.AppendLine("Create PartSim for " + name);
-            }
-
-            parent = null;
-            parentAttach = part.attachMode;
-            fuelCrossFeed = part.fuelCrossFeed;
-            noCrossFeedNodeKey = part.NoCrossFeedNodeKey;
-            decoupledInStage = DecoupledInStage(part);
-            isFuelLine = part.HasModule<CModuleFuelLine>();
-            isFuelTank = part is FuelTank;
-            isSepratron = IsSepratron();
-            isFairing = IsFairing(part);
-            inverseStage = part.inverseStage;
-            stageIndex = part.inStageIndex;
-            //MonoBehaviour.print("inverseStage = " + inverseStage);
-
-            // Work out if the part should have no physical significance
-            isNoPhysics = part.HasModule<LaunchClamp>();
-            if (isNoPhysics == false)
-            {
-                baseMass = part.mass;
-                if (hasVessel == false)
-                {
-                    moduleMass = part.GetModuleMass(part.mass);
-                }
-            }
-
-            cost = part.GetCostWet();
-
-            for (int i = 0; i < part.Resources.Count; ++i)
-            {
-                PartResource resource = part.Resources[i];
-
-                // Make sure it isn't NaN as this messes up the part mass and hence most of the values
-                // This can happen if a resource capacity is 0 and tweakable
-                if (!Double.IsNaN(resource.amount))
-                {
-                    if (SimManager.logOutput)
-                    {
-                        MonoBehaviour.print(resource.resourceName + " = " + resource.amount);
-                    }
-
-                    resources.Add(resource.info.id, resource.amount);
-                    resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
-                }
-                else
-                {
-                    MonoBehaviour.print(resource.resourceName + " is NaN. Skipping.");
-                }
-            }
-
-            isLanded = hasVessel && part.vessel.Landed;
-            if (hasVessel)
-            {
-                vesselName = part.vessel.vesselName;
-                vesselType = part.vesselType;
-            }
-            initialVesselName = part.initialVesselName;
-
-            hasMultiModeEngine = part.HasModule<MultiModeEngine>();
-            hasModuleEnginesFX = part.HasModule<ModuleEnginesFX>();
-            hasModuleEngines = part.HasModule<ModuleEngines>();
-
-            isEngine = hasMultiModeEngine || hasModuleEnginesFX || hasModuleEngines;
-
-            startMass = GetMass(-1);
-
-            if (SimManager.logOutput)
-            {
-                MonoBehaviour.print("Created " + name + ". Decoupled in stage " + decoupledInStage);
-            }
-
-            return this;
-        }
-
-        public void ReleasePart()
-        {
-            part = null;
+            return;
         }
 
         public void RemoveAttachedParts(HashSet<PartSim> partSims)
         {
             // Loop through the attached parts
-            for (int i = 0; i < attachNodes.Count; ++i)
-            {
-                AttachNodeSim attachSim = attachNodes[i];
-
+            for (int i = 0; i < this.attachNodes.Count; i++)
+            {
+                AttachNodeSim attachSim = this.attachNodes[i];
                 // If the part is in the set then "remove" it by clearing the PartSim reference
                 if (partSims.Contains(attachSim.attachedPartSim))
                 {
@@ -587,92 +663,15 @@
             }
         }
 
-        public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
-        {
-            if (log != null)
-            {
-                log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
-            }
-
-            attachNodes.Clear();
-
-            for (int i = 0; i < part.attachNodes.Count; ++i)
-            {
-                AttachNode attachNode = part.attachNodes[i];
-
-                if (log != null)
-                {
-                    log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
-                }
-
-                if (attachNode.attachedPart != null && attachNode.id != "Strut")
-                {
-                    PartSim attachedSim;
-                    if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim))
-                    {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
-                        }
-
-                        attachNodes.Add(AttachNodeSim.GetPoolObject().Initialise(attachedSim, attachNode.id, attachNode.nodeType));
-                    }
-                    else
-                    {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
-                        }
-                    }
-                }
-            }
-
-            for (int i = 0; i < part.fuelLookupTargets.Count; ++i)
-            {
-                Part p = part.fuelLookupTargets[i];
-
-                if (p != null)
-                {
-                    PartSim targetSim;
-                    if (partSimLookup.TryGetValue(p, out targetSim))
-                    {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
-                        }
-
-                        fuelTargets.Add(targetSim);
-                    }
-                    else
-                    {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
-                        }
-                    }
-                }
-            }
-        }
-
-        public void SetupParent(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
-        {
-            if (part.parent != null)
-            {
-                parent = null;
-                if (partSimLookup.TryGetValue(part.parent, out parent))
-                {
-                    if (log != null)
-                    {
-                        log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
-                    }
-                }
-                else
-                {
-                    if (log != null)
-                    {
-                        log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
-                    }
-                }
+        public void DrainResources(double time)
+        {
+            //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
+            for (int i = 0; i < this.resourceDrains.Types.Count; i++)
+            {
+                int type = this.resourceDrains.Types[i];
+                //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
+                this.resources.Add(type, -time * this.resourceDrains[type]);
+                //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
             }
         }
 
@@ -681,13 +680,12 @@
             //MonoBehaviour.print("TimeToDrainResource(" + name + ":" + partId + ")");
             double time = double.MaxValue;
 
-            for (int i = 0; i < resourceDrains.Types.Count; ++i)
-            {
-                int type = resourceDrains.Types[i];
-
-                if (resourceDrains[type] > 0)
-                {
-                    time = Math.Min(time, resources[type] / resourceDrains[type]);
+            for (int i = 0; i < this.resourceDrains.Types.Count; i++)
+            {
+                int type = this.resourceDrains.Types[i];
+                if (this.resourceDrains[type] > 0)
+                {
+                    time = Math.Min(time, this.resources[type] / this.resourceDrains[type]);
                     //MonoBehaviour.print("type = " + ResourceContainer.GetResourceName(type) + "  amount = " + resources[type] + "  rate = " + resourceDrains[type] + "  time = " + time);
                 }
             }
@@ -697,140 +695,114 @@
             return time;
         }
 
-        private static void Reset(PartSim partSim)
-        {
-            partSim.attachNodes.Clear();
-            partSim.fuelTargets.Clear();
-            partSim.resourceDrains.Reset();
-            partSim.resourceFlowStates.Reset();
-            partSim.resources.Reset();
-            partSim.baseMass = 0.0;
-            partSim.startMass = 0.0;
-            partSim.centerOfMass = Vector3d.zero;
-            partSim.cost = 0.0;
-            partSim.decoupledInStage = 0;
-            partSim.fuelCrossFeed = false;
-            partSim.hasModuleEngines = false;
-            partSim.hasModuleEnginesFX = false;
-            partSim.hasMultiModeEngine = false;
-            partSim.hasVessel = false;
-            partSim.initialVesselName = null;
-            partSim.inverseStage = 0;
-            partSim.isDecoupler = false;
-            partSim.isEngine = false;
-            partSim.isFuelLine = false;
-            partSim.isFuelTank = false;
-            partSim.isLanded = false;
-            partSim.isNoPhysics = false;
-            partSim.isSepratron = false;
-            partSim.isFairing = false;
-            partSim.localCorrectThrust = false;
-            partSim.name = null;
-            partSim.noCrossFeedNodeKey = null;
-            partSim.parent = null;
-            partSim.parentAttach = AttachModes.SRF_ATTACH;
-            partSim.part = null;
-            partSim.partId = 0;
-            partSim.vesselName = null;
-            partSim.vesselType = VesselType.Base;
-            partSim.moduleMass = 0.0f;
-            partSim.stageIndex = 0;
-        }
-
-        private Vector3 CalculateThrustVector(List<Transform> thrustTransforms, LogMsg log)
-        {
-            if (thrustTransforms == null)
-            {
-                return Vector3.forward;
-            }
-
-            Vector3 thrustvec = Vector3.zero;
-            for (int i = 0; i < thrustTransforms.Count; ++i)
-            {
-                Transform trans = thrustTransforms[i];
-
-                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;
-        }
-
-        private int DecoupledInStage(Part thePart, int stage = -1)
-        {
-            if (IsDecoupler(thePart))
-            {
-                if (thePart.inverseStage > stage)
-                {
-                    stage = thePart.inverseStage;
-                }
-            }
-
-            if (thePart.parent != null)
-            {
-                stage = DecoupledInStage(thePart.parent, stage);
-            }
-
-            return stage;
-        }
-
-        private bool IsActiveDecoupler(Part thePart)
-        {
-            return thePart.FindModulesImplementing<ModuleDecouple>().Any(mod => !mod.isDecoupled) ||
-                   thePart.FindModulesImplementing<ModuleAnchoredDecoupler>().Any(mod => !mod.isDecoupled);
-        }
-
-        private bool IsDecoupler(Part thePart)
-        {
-            return thePart.HasModule<ModuleDecouple>() ||
-                   thePart.HasModule<ModuleAnchoredDecoupler>();
-        }
-
-        private bool IsFairing(Part thePart)
-        {
-            return thePart.HasModule<ModuleProceduralFairing>();
-        }
-
-        private bool IsSepratron()
-        {
-            if (!part.ActivatesEvenIfDisconnected)
-            {
-                return false;
-            }
-
-            if (part is SolidRocket)
-            {
-                return true;
-            }
-
-            IEnumerable<ModuleEngines> modList = part.Modules.OfType<ModuleEngines>();
-            if (modList.Count() == 0)
-            {
-                return false;
-            }
-
-            if (modList.First().throttleLocked)
-            {
-                return true;
-            }
-
-            return false;
+        public bool EmptyOf(HashSet<int> types)
+        {
+            foreach (int type in types)
+            {
+                if (this.resources.HasType(type) && this.resourceFlowStates[type] != 0 && (double)this.resources[type] > SimManager.RESOURCE_MIN)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        public int DecouplerCount()
+        {
+            int count = 0;
+            PartSim partSim = this;
+            while (partSim != null)
+            {
+                if (partSim.isDecoupler)
+                {
+                    count++;
+                }
+
+                partSim = partSim.parent;
+            }
+            return count;
+        }
+
+        public double GetStartMass()
+        {
+            return this.startMass;
+        }
+
+        public double GetMass()
+        {
+            double mass = this.baseMass;
+
+            for (int i = 0; i < this.resources.Types.Count; i++)
+            {
+                int type = this.resources.Types[i];
+                mass += this.resources.GetResourceMass(type);
+            }
+
+            return mass;
+        }
+
+        public String DumpPartAndParentsToBuffer(StringBuilder buffer, String prefix)
+        {
+            if (this.parent != null)
+            {
+                prefix = this.parent.DumpPartAndParentsToBuffer(buffer, prefix) + " ";
+            }
+
+            this.DumpPartToBuffer(buffer, prefix);
+
+            return prefix;
+        }
+
+        public void DumpPartToBuffer(StringBuilder buffer, String prefix, List<PartSim> allParts = null)
+        {
+            buffer.Append(prefix);
+            buffer.Append(this.name);
+            buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", this.partId, this.decoupledInStage, this.inverseStage);
+
+            buffer.AppendFormat(", vesselName = '{0}'", this.vesselName);
+            buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(this.vesselType));
+            buffer.AppendFormat(", initialVesselName = '{0}'", this.initialVesselName);
+
+            buffer.AppendFormat(", fuelCF = {0}", this.fuelCrossFeed);
+            buffer.AppendFormat(", noCFNKey = '{0}'", this.noCrossFeedNodeKey);
+
+            buffer.AppendFormat(", isSep = {0}", this.isSepratron);
+
+            for (int i = 0; i < this.resources.Types.Count; i++)
+            {
+                int type = this.resources.Types[i];
+                buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), this.resources[type]);
+            }
+
+            if (this.attachNodes.Count > 0)
+            {
+                buffer.Append(", attached = <");
+                this.attachNodes[0].DumpToBuffer(buffer);
+                for (int i = 1; i < this.attachNodes.Count; i++)
+                {
+                    buffer.Append(", ");
+                    this.attachNodes[i].DumpToBuffer(buffer);
+                }
+                buffer.Append(">");
+            }
+
+            // Add more info here
+
+            buffer.Append("]\n");
+
+            if (allParts != null)
+            {
+                String newPrefix = prefix + " ";
+                for (int i = 0; i < allParts.Count; i++)
+                {
+                    PartSim partSim = allParts[i];
+                    if (partSim.parent == this)
+                    {
+                        partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
+                    }
+                }
+            }
         }
     }
 }

--- a/KerbalEngineer/VesselSimulator/ResourceContainer.cs
+++ b/KerbalEngineer/VesselSimulator/ResourceContainer.cs
@@ -19,6 +19,7 @@
 
 #region Using Directives
 
+using System;
 using System.Collections;
 using System.Collections.Generic;
 
@@ -30,15 +31,17 @@
 {
     public class ResourceContainer
     {
-        private Hashtable resources = new Hashtable();
+        private Dictionary<int, double> resources = new Dictionary<int, double>();
+        private List<int> types = new List<int>();
 
         public double this[int type]
         {
             get
             {
-                if (this.resources.ContainsKey(type))
+                double value;
+                if (this.resources.TryGetValue(type, out value))
                 {
-                    return (double)this.resources[type];
+                    return value;
                 }
 
                 return 0d;
@@ -52,6 +55,7 @@
                 else
                 {
                     this.resources.Add(type, value);
+                    this.types.Add(type);
                 }
             }
         }
@@ -60,13 +64,6 @@
         {
             get
             {
-                List<int> types = new List<int>();
-
-                foreach (int key in this.resources.Keys)
-                {
-                    types.Add(key);
-                }
-
                 return types;
             }
         }
@@ -92,7 +89,7 @@
             {
                 foreach (int type in this.resources.Keys)
                 {
-                    if ((double)this.resources[type] > SimManager.RESOURCE_MIN)
+                    if (this.resources[type] > SimManager.RESOURCE_MIN)
                     {
                         return false;
                     }
@@ -111,7 +108,7 @@
         {
             foreach (int type in types)
             {
-                if (this.HasType(type) && (double)this.resources[type] > SimManager.RESOURCE_MIN)
+                if (this.HasType(type) && this.resources[type] > SimManager.RESOURCE_MIN)
                 {
                     return false;
                 }
@@ -124,17 +121,19 @@
         {
             if (this.resources.ContainsKey(type))
             {
-                this.resources[type] = (double)this.resources[type] + amount;
+                this.resources[type] = this.resources[type] + amount;
             }
             else
             {
                 this.resources.Add(type, amount);
+                this.types.Add(type);
             }
         }
 
         public void Reset()
         {
             this.resources.Clear();
+            this.types.Clear();
         }
 
         public void Debug()
@@ -148,7 +147,7 @@
         public double GetResourceMass(int type)
         {
             double density = GetResourceDensity(type);
-            return density == 0d ? 0d : (double)this.resources[type] * density;
+            return density == 0d ? 0d : this.resources[type] * density;
         }
 
         public static ResourceFlowMode GetResourceFlowMode(int type)
@@ -158,7 +157,7 @@
 
         public static ResourceTransferMode GetResourceTransferMode(int type)
         {
-            return PartResourceLibrary.Instance.GetDefinition(type).resourceTransferMode;
+            return PartResourceLibrary.Instance.GetDefinition(type).resourceTransferMode;;
         }
 
         public static float GetResourceDensity(int type)

--- a/KerbalEngineer/VesselSimulator/SimManager.cs
+++ b/KerbalEngineer/VesselSimulator/SimManager.cs
@@ -22,7 +22,6 @@
     #region Using Directives
 
     using System;
-    using System.Collections.Generic;
     using System.Diagnostics;
     using System.Reflection;
     using System.Threading;
@@ -61,9 +60,6 @@
         private static bool hasInstalledKIDS;
         private static MethodInfo KIDS_Utils_GetIspMultiplier;
         private static bool bKIDSThrustISP = false;
-        private static List<Part> parts = new List<Part>(); 
-
-        private static Simulation simulation = new Simulation();
         #endregion
 
         #region Delegates
@@ -287,7 +283,6 @@
             try
             {
                 Stages = (simObject as Simulation).RunSimulation();
-
                 if (Stages != null && Stages.Length > 0)
                 {
                     if (logOutput)
@@ -302,7 +297,8 @@
             }
             catch (Exception e)
             {
-                Logger.Exception(e, "SimManager.RunSimulation()");
+                MonoBehaviour.print("Exception in RunSimulation: " + e);
+                Logger.Exception(e);
                 Stages = null;
                 LastStage = null;
                 failMessage = e.ToString();
@@ -354,21 +350,15 @@
                     timer.Start();
                 }
 
-                if (HighLogic.LoadedSceneIsEditor)
-                {
-                    parts = EditorLogic.fetch.ship.parts;
-                }
-                else
-                {
-                    parts = FlightGlobals.ActiveVessel.Parts;
-                    Atmosphere = FlightGlobals.ActiveVessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres;
-                }
+                var parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.ship.parts : FlightGlobals.ActiveVessel.Parts;
+
+                // Create the Simulation object in this thread
+                var sim = new Simulation();
 
                 // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
-                if (simulation.PrepareSimulation(parts, Gravity, Atmosphere, Mach, dumpTree, vectoredThrust))
-                {
-                    ThreadPool.QueueUserWorkItem(RunSimulation, simulation);
-                    //RunSimulation(simulation);
+                if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Mach, dumpTree, vectoredThrust))
+                {
+                    ThreadPool.QueueUserWorkItem(RunSimulation, sim);
                 }
                 else
                 {
@@ -382,7 +372,8 @@
             }
             catch (Exception e)
             {
-                Logger.Exception(e, "SimManager.StartSimulation()");
+                MonoBehaviour.print("Exception in StartSimulation: " + e);
+                Logger.Exception(e);
                 failMessage = e.ToString();
                 lock (locker)
                 {

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -32,30 +32,30 @@
 {
     using CompoundParts;
     using Extensions;
-    using Helpers;
 
     public class Simulation
     {
+        private const double STD_GRAVITY = 9.82;
         private const double SECONDS_PER_DAY = 86400;
         private readonly Stopwatch _timer = new Stopwatch();
-        private List<EngineSim> activeEngines = new List<EngineSim>();
-        private List<EngineSim> allEngines = new List<EngineSim>();
-        private List<PartSim> allFuelLines = new List<PartSim>();
-        private List<PartSim> allParts = new List<PartSim>();
-        private Dictionary<Part, PartSim> partSimLookup = new Dictionary<Part, PartSim>();
+        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 HashSet<PartSim> decoupledParts = new HashSet<PartSim>();
         private bool doingCurrent;
-        private List<PartSim> dontStageParts = new List<PartSim>();
-        List<List<PartSim>> dontStagePartsLists = new List<List<PartSim>>();
-        private HashSet<PartSim> drainingParts = new HashSet<PartSim>();
-        private HashSet<int> drainingResources = new HashSet<int>();
-        private HashSet<PartSim> decoupledParts = new HashSet<PartSim>();
+        private List<PartSim> dontStageParts;
+        private List<List<PartSim>> dontStagePartsLists = new List<List<PartSim>>();
+        private HashSet<PartSim> drainingParts;
+        private HashSet<int> drainingResources;
         private double gravity;
+        private Dictionary<Part, PartSim> partSimLookup;
 
         private int lastStage;
-        private List<Part> partList = new List<Part>();
+        private List<Part> partList;
         private double simpleTotalThrust;
         private double stageStartMass;
         private Vector3d stageStartCom;
@@ -66,19 +66,27 @@
         private double totalStageFlowRate;
         private double totalStageIspFlowRate;
         private double totalStageThrust;
-        private ForceAccumulator totalStageThrustForce = new ForceAccumulator();
+        private ForceAccumulator totalStageThrustForce;
         private Vector3 vecActualThrust;
         private Vector3 vecStageDeltaV;
         private Vector3 vecThrust;
         private double mach;
-        private float maxMach;
         public String vesselName;
         public VesselType vesselType;
-        private WeightedVectorAverager vectorAverager = new WeightedVectorAverager();
-        private static ModuleProceduralFairing moduleProceduralFairing;
 
         public Simulation()
         {
+            this.allParts = new List<PartSim>();
+            this.allFuelLines = new List<PartSim>();
+            this.drainingParts = new HashSet<PartSim>();
+            this.allEngines = new List<EngineSim>();
+            this.activeEngines = new List<EngineSim>();
+            this.drainingResources = new HashSet<int>();
+            this.totalStageThrustForce = new ForceAccumulator();
+
+            // A dictionary for fast lookup of Part->PartSim during the preparation phase
+            partSimLookup = new Dictionary<Part, PartSim>();
+
             if (SimManager.logOutput)
             {
                 MonoBehaviour.print("Simulation created");
@@ -91,8 +99,10 @@
             {
                 double mass = 0d;
 
-                for (int i = 0; i < allParts.Count; ++i) { 
-                    mass += allParts[i].GetMass(currentStage);
+                for (int i = 0; i < this.allParts.Count; i++)
+                {
+                    PartSim partSim = this.allParts[i];
+                    mass += partSim.GetMass();
                 }
 
                 return mass;
@@ -103,15 +113,15 @@
         {
             get
             {
-                vectorAverager.Reset();
-
-                for (int i = 0; i < allParts.Count; ++i)
-                {
-                    PartSim partSim = allParts[i];
-                    vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage));
-                }
-
-                return vectorAverager.Get();
+                WeightedVectorAverager averager = new WeightedVectorAverager();
+
+                for (int i = 0; i < this.allParts.Count; i++)
+                {
+                    PartSim partSim = this.allParts[i];
+                    averager.Add(partSim.centerOfMass, partSim.GetMass());
+                }
+
+                return averager.Get();
             }
         }
 
@@ -139,16 +149,12 @@
             //MonoBehaviour.print("lastStage = " + lastStage);
 
             // Clear the lists for our simulation parts
-            allParts.Clear();
-            allFuelLines.Clear();
-            drainingParts.Clear();
-            allEngines.Clear();
-            activeEngines.Clear();
-            drainingResources.Clear();
-
-            PartSim.ReleaseAll();
-            EngineSim.ReleaseAll();
-            AttachNodeSim.ReleaseAll();
+            this.allParts.Clear();
+            this.allFuelLines.Clear();
+            this.drainingParts.Clear();
+            this.allEngines.Clear();
+            this.activeEngines.Clear();
+            this.drainingResources.Clear();
 
             // A dictionary for fast lookup of Part->PartSim during the preparation phase
             partSimLookup.Clear();
@@ -158,13 +164,12 @@
                 this.vesselName = this.partList[0].vessel.vesselName;
                 this.vesselType = this.partList[0].vessel.vesselType;
             }
-
+            //MonoBehaviour.print("PrepareSimulation pool size = " + PartSim.pool.Count());
             // First we create a PartSim for each Part (giving each a unique id)
             int partId = 1;
-            for (int i = 0; i < partList.Count; ++i)
-            {
-                Part part = partList[i];
-
+            for (int i = 0; i < this.partList.Count; i++)
+            {
+                Part part = this.partList[i];
                 // If the part is already in the lookup dictionary then log it and skip to the next part
                 if (partSimLookup.ContainsKey(part))
                 {
@@ -176,7 +181,7 @@
                 }
 
                 // Create the PartSim
-                PartSim partSim = PartSim.GetPoolObject().Initialise(part, partId, this.atmosphere, log);
+                PartSim partSim = PartSim.New(part, partId, this.atmosphere, log);
 
                 // Add it to the Part lookup dictionary and the necessary lists
                 partSimLookup.Add(part, partSim);
@@ -193,27 +198,22 @@
                 partId++;
             }
 
-            for (int i = 0; i < allEngines.Count; ++i)
-            {
-                maxMach = Mathf.Max(maxMach, allEngines[i].maxMach);
-            }
-
             this.UpdateActiveEngines();
 
             // Now that all the PartSims have been created we can do any set up that needs access to other parts
             // First we set up all the parent links
-            foreach (PartSim partSim in this.allParts)
-            {
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim partSim = this.allParts[i];
                 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)
             {
-                for (int i = 0; i < allFuelLines.Count; ++i)
-                {
-                    PartSim partSim = allFuelLines[i];
-
+                for (int i = 0; i < this.allFuelLines.Count; i++)
+                {
+                    PartSim partSim = this.allFuelLines[i];
                     CModuleFuelLine fuelLine = partSim.part.GetModule<CModuleFuelLine>();
                     if (fuelLine.target != null)
                     {
@@ -246,10 +246,9 @@
             }
 
             //MonoBehaviour.print("SetupAttachNodes and count stages");
-            for (int i = 0; i < allParts.Count; ++i)
-            {
-                PartSim partSim = allParts[i];
-
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim partSim = this.allParts[i];
                 partSim.SetupAttachNodes(partSimLookup, log);
                 if (partSim.decoupledInStage >= this.lastStage)
                 {
@@ -259,9 +258,10 @@
 
             // And finally release the Part references from all the PartSims
             //MonoBehaviour.print("ReleaseParts");
-            for (int i = 0; i < allParts.Count; ++i)
-            { 
-                allParts[i].ReleasePart();
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim partSim = this.allParts[i];
+                partSim.ReleasePart();
             }
 
             // And dereference the core's part list
@@ -281,7 +281,7 @@
 
             return true;
         }
-
+        
         // This function runs the simulation and returns a newly created array of Stage objects
         public Stage[] RunSimulation()
         {
@@ -301,15 +301,13 @@
             // 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;
-
             // 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;
-            for (int i = 0; i < allEngines.Count; ++i)
-            {
-                EngineSim engine = allEngines[i];
-
+            for (int i = 0; i < this.allEngines.Count; i++)
+            {
+                EngineSim engine = this.allEngines[i];
                 if (log != null)
                 {
                     log.buf.AppendLine("Testing engine mod of " + engine.partSim.name + ":" + engine.partSim.partId);
@@ -364,7 +362,7 @@
             }
 
             // Create a list of lists of PartSims that prevent decoupling
-            BuildDontStageLists(log);
+            this.BuildDontStageLists(log);
 
             if (log != null)
             {
@@ -436,20 +434,14 @@
 
                 // 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
-                for (int i = 0; i < allParts.Count; ++i)
-                {
-                    PartSim partSim = allParts[i];
-
+                for (int i = 0; i < this.allParts.Count; i++)
+                {
+                    PartSim partSim = this.allParts[i];
                     if (partSim.decoupledInStage == this.currentStage - 1)
                     {
                         stage.cost += partSim.cost;
                         stage.mass += partSim.GetStartMass();
                     }
-
-                    if (partSim.hasVessel == false && partSim.isFairing && partSim.inverseStage == currentStage)
-                    {
-                        stage.mass += partSim.moduleMass;
-                    }
                 }
 
                 this.dontStageParts = dontStagePartsLists[this.currentStage];
@@ -461,8 +453,9 @@
                     if (this.dontStageParts.Count > 0)
                     {
                         log.buf.AppendLine("Parts preventing staging:");
-                        foreach (PartSim partSim in this.dontStageParts)
-                        {
+                        for (int i = 0; i < this.dontStageParts.Count; i++)
+                        {
+                            PartSim partSim = this.dontStageParts[i];
                             partSim.DumpPartToBuffer(log.buf, "");
                         }
                     }
@@ -473,6 +466,7 @@
 
                     log.Flush();
                 }
+
 
                 // Now we will loop until we are allowed to stage
                 int loopCounter = 0;
@@ -480,7 +474,6 @@
                 {
                     loopCounter++;
                     //MonoBehaviour.print("loop = " + loopCounter);
-
                     // Calculate how long each draining tank will take to drain and run for the minimum time
                     double resourceDrainTime = double.MaxValue;
                     PartSim partMinDrain = null;
@@ -498,7 +491,6 @@
                     {
                         MonoBehaviour.print("Drain time = " + resourceDrainTime + " (" + partMinDrain.name + ":" + partMinDrain.partId + ")");
                     }
-
                     foreach (PartSim partSim in this.drainingParts)
                     {
                         partSim.DrainResources(resourceDrainTime);
@@ -522,7 +514,7 @@
                     // 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 * Units.GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
+                        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
@@ -530,7 +522,7 @@
 
                     // Recalculate the current thrust and isp for the next step
                     this.CalculateThrustAndISP();
-
+                    
                     // Check if we actually changed anything
                     if (this.stepStartMass == this.stepEndMass)
                     {
@@ -556,6 +548,7 @@
                     this.stepStartMass = this.stepEndMass;
                 }
 
+
                 // Store more values in the Stage object and stick it in the array
 
                 // Store the magnitude of the deltaV vector
@@ -566,7 +559,7 @@
                 // Note: If the mass doesn't change then this is a divide by zero
                 if (this.stageStartMass != this.stepStartMass)
                 {
-                    stage.isp = stage.deltaV / (Units.GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
+                    stage.isp = stage.deltaV / (STD_GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
                 }
                 else
                 {
@@ -577,7 +570,6 @@
                 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.totalPartCount = this.allParts.Count;
-                stage.maxMach = maxMach;
                 stages[this.currentStage] = stage;
 
                 // Now activate the next stage
@@ -636,39 +628,54 @@
                 this._timer.Stop();
                 MonoBehaviour.print("RunSimulation: " + this._timer.ElapsedMilliseconds + "ms");
             }
-
+            FreePooledObject();
+            
             return stages;
         }
 
+        
+        // Make sure we free them all, even if they should all be free already at this point
+        public void FreePooledObject()
+        {
+            //MonoBehaviour.print("FreePooledObject pool size before = " + PartSim.pool.Count() + " for " + allParts.Count + " parts");
+            foreach (PartSim part in allParts)
+            {
+                part.Release();
+            }
+            //MonoBehaviour.print("FreePooledObject pool size after = " + PartSim.pool.Count());
+
+            //MonoBehaviour.print("FreePooledObject pool size before = " + EngineSim.pool.Count() + " for " + allEngines.Count + " engines");
+            foreach (EngineSim engine in allEngines)
+            {
+                engine.Release();
+            }
+            //MonoBehaviour.print("FreePooledObject pool size after = " + EngineSim.pool.Count());
+        }
+
         private void BuildDontStageLists(LogMsg log)
         {
             if (log != null)
             {
                 log.buf.AppendLine("Creating list with capacity of " + (this.currentStage + 1));
             }
-
-            dontStagePartsLists.Clear();
+            
             for (int i = 0; i <= this.currentStage; i++)
             {
                 if (i < dontStagePartsLists.Count)
-                {
                     dontStagePartsLists[i].Clear();
-                }
                 else
-                {
                     dontStagePartsLists.Add(new List<PartSim>());
-                }
-            }
-
-            for (int i = 0; i < allParts.Count; ++i)
-            {
-                PartSim partSim = allParts[i];
-
+            }
+
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim partSim = this.allParts[i];
                 if (partSim.isEngine || !partSim.Resources.Empty)
                 {
                     if (log != null)
                     {
-                        log.buf.AppendLine(partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
+                        log.buf.AppendLine(
+                            partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
                     }
 
                     if (partSim.decoupledInStage < -1 || partSim.decoupledInStage > this.currentStage - 1)
@@ -698,10 +705,9 @@
         private void UpdateActiveEngines()
         {
             this.activeEngines.Clear();
-            for (int i = 0; i < allEngines.Count; ++i)
-            {
-                EngineSim engine = allEngines[i];
-
+            for (int i = 0; i < this.allEngines.Count; i++)
+            {
+                EngineSim engine = this.allEngines[i];
                 if (engine.isActive)
                 {
                     this.activeEngines.Add(engine);
@@ -720,13 +726,11 @@
             this.totalStageFlowRate = 0d;
             this.totalStageIspFlowRate = 0d;
             this.totalStageThrustForce.Reset();
-
             // Loop through all the active engines totalling the thrust, actual thrust and mass flow rates
             // The thrust is totalled as vectors
-            for (int i = 0; i < activeEngines.Count; ++i)
-            {
-                EngineSim engine = activeEngines[i];
-
+            for (int i = 0; i < this.activeEngines.Count; i++)
+            {
+                EngineSim engine = this.activeEngines[i];
                 this.simpleTotalThrust += engine.thrust;
                 this.vecThrust += ((float)engine.thrust * engine.thrustVec);
                 this.vecActualThrust += ((float)engine.actualThrust * engine.thrustVec);
@@ -734,14 +738,13 @@
                 this.totalStageFlowRate += engine.ResourceConsumptions.Mass;
                 this.totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp;
 
-                for (int j = 0; j < engine.appliedForces.Count; ++j)
-                {
-                    this.totalStageThrustForce.AddForce(engine.appliedForces[j]);
-                }
-            }
-
+                for (int j = 0; j < engine.appliedForces.Count; j++)
+                {
+                    AppliedForce f = engine.appliedForces[j];
+                    this.totalStageThrustForce.AddForce(f);
+                }
+            }
             //MonoBehaviour.print("vecThrust = " + vecThrust.ToString() + "   magnitude = " + vecThrust.magnitude);
-
             this.totalStageThrust = this.vecThrust.magnitude;
             this.totalStageActualThrust = this.vecActualThrust.magnitude;
 
@@ -776,17 +779,17 @@
             this.drainingParts.Clear();
 
             // Loop through all the active engine modules
-            for (int i = 0; i < activeEngines.Count; ++i)
-            {
-                EngineSim engine = activeEngines[i];
-
+            for (int i = 0; i < this.activeEngines.Count; i++)
+            {
+                EngineSim engine = this.activeEngines[i];
                 // Set the resource drains for this engine
                 if (engine.SetResourceDrains(this.allParts, this.allFuelLines, this.drainingParts))
                 {
                     // If it is active then add the consumed resource types to the set
-                    for (int j = 0; j < engine.ResourceConsumptions.Types.Count; ++j)
-                    { 
-                        drainingResources.Add(engine.ResourceConsumptions.Types[j]);
+                    for (int j = 0; j < engine.ResourceConsumptions.Types.Count; j++)
+                    {
+                        int type = engine.ResourceConsumptions.Types[j];
+                        this.drainingResources.Add(type);
                     }
                 }
             }
@@ -799,8 +802,9 @@
                 StringBuilder buffer = new StringBuilder(1024);
                 buffer.AppendFormat("Active engines = {0:d}\n", this.activeEngines.Count);
                 int i = 0;
-                foreach (EngineSim engine in this.activeEngines)
-                {
+                for (int j = 0; j < this.activeEngines.Count; j++)
+                {
+                    EngineSim engine = this.activeEngines[j];
                     engine.DumpEngineToBuffer(buffer, "Engine " + (i++) + ":");
                 }
                 MonoBehaviour.print(buffer);
@@ -820,10 +824,9 @@
 
             if (this.activeEngines.Count > 0)
             {
-                for (int i = 0; i < dontStageParts.Count; ++i)
-                {
-                    PartSim partSim = dontStageParts[i];
-
+                for (int i = 0; i < this.dontStageParts.Count; i++)
+                {
+                    PartSim partSim = this.dontStageParts[i];
                     if (SimManager.logOutput)
                     {
                         partSim.DumpPartToBuffer(buffer, "Testing: ");
@@ -842,10 +845,9 @@
 
                     if (partSim.isEngine)
                     {
-                        for (int j = 0; j < activeEngines.Count; ++j)
-                        {
-                            EngineSim engine = activeEngines[j];
-
+                        for (int j = 0; j < this.activeEngines.Count; j++)
+                        {
+                            EngineSim engine = this.activeEngines[j];
                             if (engine.partSim == partSim)
                             {
                                 if (SimManager.logOutput)
@@ -884,10 +886,9 @@
         {
             // Build a set of all the parts that will be decoupled
             decoupledParts.Clear();
-            for (int i = 0; i < allParts.Count; ++i)
-            {
-                PartSim partSim = allParts[i];
-
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim partSim = this.allParts[i];
                 if (partSim.decoupledInStage >= this.currentStage)
                 {
                     decoupledParts.Add(partSim);
@@ -898,14 +899,17 @@
             {
                 // Remove it from the all parts list
                 this.allParts.Remove(partSim);
+                partSim.Release();
                 if (partSim.isEngine)
                 {
                     // If it is an engine then loop through all the engine modules and remove all the ones from this engine part
                     for (int i = this.allEngines.Count - 1; i >= 0; i--)
                     {
-                        if (this.allEngines[i].partSim == partSim)
+                        EngineSim engine = this.allEngines[i];
+                        if (engine.partSim == partSim)
                         {
                             this.allEngines.RemoveAt(i);
+                            engine.Release();
                         }
                     }
                 }
@@ -917,15 +921,17 @@
             }
 
             // Loop through all the (remaining) parts
-            for (int i = 0; i < allParts.Count; ++i) { 
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim partSim = this.allParts[i];
                 // Ask the part to remove all the parts that are decoupled
-                allParts[i].RemoveAttachedParts(decoupledParts);
+                partSim.RemoveAttachedParts(decoupledParts);
             }
 
             // Now we loop through all the engines and activate those that are ignited in this stage
-            for (int i = 0; i < allEngines.Count; ++i)
-            {
-                EngineSim engine = allEngines[i];
+            for (int i = 0; i < this.allEngines.Count; i++)
+            {
+                EngineSim engine = this.allEngines[i];
                 if (engine.partSim.inverseStage == this.currentStage)
                 {
                     engine.isActive = true;

--- a/KerbalEngineer/VesselSimulator/Stage.cs
+++ b/KerbalEngineer/VesselSimulator/Stage.cs
@@ -51,7 +51,6 @@
         public double resourceMass = 0.0;
         public double maxThrustTorque = 0.0;
         public double thrustOffsetAngle = 0.0;
-        public float maxMach = 0.0f;
 
         public void Dump()
         {

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ
--- a/Output/KerbalEngineer/KerbalEngineer.version
+++ b/Output/KerbalEngineer/KerbalEngineer.version
@@ -5,13 +5,13 @@
 	{
 		"MAJOR":1,
 		"MINOR":0,
-		"PATCH":16,
-		"BUILD":5
+		"PATCH":15,
+		"BUILD":2
 	},
 	"KSP_VERSION":
 	{
-		"MAJOR":1,
-		"MINOR":0,
-		"PATCH":2
+		"MAJOR":0,
+		"MINOR":90,
+		"PATCH":0
 	}
 }