Removed Smooth library
Removed Smooth library

 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
@@ -119,6 +119,7 @@
     <Compile Include="Helpers\AngleHelper.cs" />
     <Compile Include="Helpers\Averager.cs" />
     <Compile Include="Helpers\ForceAccumulator.cs" />
+    <Compile Include="Helpers\Pool.cs" />
     <Compile Include="Helpers\TextureHelper.cs" />
     <Compile Include="Helpers\Units.cs" />
     <Compile Include="Helpers\TimeFormatter.cs" />
@@ -199,7 +200,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,7 +208,7 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="Assembly-CSharp">
-      <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
+      <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
       <Private>False</Private>
     </Reference>
     <Reference Include="System">
@@ -220,10 +220,11 @@
       <Private>False</Private>
     </Reference>
     <Reference Include="UnityEngine">
-      <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
+      <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\UnityEngine.dll</HintPath>
       <Private>False</Private>
     </Reference>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Target Name="PostBuildMacros">
     <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">

--- 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
@@ -19,22 +19,28 @@
 
 #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;
@@ -66,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)
@@ -118,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,
@@ -132,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);
                     }
@@ -143,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)
@@ -154,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,
@@ -168,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);
                     }
@@ -184,141 +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()
-        {
-            double mass = baseMass;
-
-            for (int i = 0; i < resources.Types.Count; ++i)
-            {
-                mass += resources.GetResourceMass(resources.Types[i]);
-            }
-
-            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)
@@ -329,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)
@@ -343,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
 
@@ -369,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))
                                 {
@@ -392,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;
                 }
             }
 
@@ -419,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;
                         }
                     }
                 }
@@ -465,120 +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;
-            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();
-            inverseStage = part.inverseStage;
-            //MonoBehaviour.print("inverseStage = " + inverseStage);
-
-            cost = part.GetCostWet();
-
-            // Work out if the part should have no physical significance
-            isNoPhysics = part.HasModule<LaunchClamp>();
-
-            if (isNoPhysics == false)
-            {
-                if (part.vessel != null)
-                {
-                    baseMass = part.mass;
-                }
-                else
-                {
-                    baseMass = part.mass + part.GetModuleMass(part.mass);
-                }
-            }
-
-            if (SimManager.logOutput)
-            {
-                MonoBehaviour.print((isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + part.mass);
-            }
-
-            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.");
-                }
-            }
-
-            startMass = GetMass();
-
-            hasVessel = (part.vessel != null);
-            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;
-
-            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,132 +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.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;
-        }
-
-        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 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,18 +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();
 
         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");
@@ -90,8 +99,10 @@
             {
                 double mass = 0d;
 
-                for (int i = 0; i < allParts.Count; ++i) { 
-                    mass += allParts[i].GetMass();
+                for (int i = 0; i < this.allParts.Count; i++)
+                {
+                    PartSim partSim = this.allParts[i];
+                    mass += partSim.GetMass();
                 }
 
                 return mass;
@@ -102,15 +113,15 @@
         {
             get
             {
-                vectorAverager.Reset();
-
-                for (int i = 0; i < allParts.Count; ++i)
-                {
-                    PartSim partSim = allParts[i];
-                    vectorAverager.Add(partSim.centerOfMass, partSim.GetMass());
-                }
-
-                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();
             }
         }
 
@@ -138,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();
@@ -157,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))
                 {
@@ -175,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);
@@ -192,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)
                     {
@@ -245,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)
                 {
@@ -258,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
@@ -280,7 +281,7 @@
 
             return true;
         }
-
+        
         // This function runs the simulation and returns a newly created array of Stage objects
         public Stage[] RunSimulation()
         {
@@ -300,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);
@@ -363,7 +362,7 @@
             }
 
             // Create a list of lists of PartSims that prevent decoupling
-            BuildDontStageLists(log);
+            this.BuildDontStageLists(log);
 
             if (log != null)
             {
@@ -372,7 +371,6 @@
 
             // Create the array of stages that will be returned
             Stage[] stages = new Stage[this.currentStage + 1];
-
 
             // Loop through the stages
             while (this.currentStage >= 0)
@@ -436,10 +434,9 @@
 
                 // 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;
@@ -456,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, "");
                         }
                     }
@@ -468,6 +466,7 @@
 
                     log.Flush();
                 }
+
 
                 // Now we will loop until we are allowed to stage
                 int loopCounter = 0;
@@ -475,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;
@@ -493,7 +491,6 @@
                     {
                         MonoBehaviour.print("Drain time = " + resourceDrainTime + " (" + partMinDrain.name + ":" + partMinDrain.partId + ")");
                     }
-
                     foreach (PartSim partSim in this.drainingParts)
                     {
                         partSim.DrainResources(resourceDrainTime);
@@ -517,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
@@ -525,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)
                     {
@@ -551,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
@@ -561,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
                 {
@@ -572,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
@@ -631,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)
@@ -693,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);
@@ -715,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);
@@ -729,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;
 
@@ -771,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);
                     }
                 }
             }
@@ -794,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);
@@ -815,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: ");
@@ -837,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)
@@ -879,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);
@@ -893,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();
                         }
                     }
                 }
@@ -912,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
 	}
 }