EngineSim objects are now pooled.
EngineSim objects are now pooled.

 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,3 +1,23 @@
+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,16 +17,12 @@
 //     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
@@ -36,8 +32,6 @@
 
     public static class CelestialBodies
     {
-        #region Constructors
-
         static CelestialBodies()
         {
             try
@@ -55,16 +49,8 @@
             }
         }
 
-        #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.
@@ -89,7 +75,7 @@
         {
             try
             {
-                var body = GetBodyInfo(bodyName);
+                BodyInfo body = GetBodyInfo(bodyName);
                 if (body != null)
                 {
                     if (SelectedBody != null)
@@ -108,33 +94,26 @@
             return false;
         }
 
-        #endregion
-
-        #region Nested type: BodyInfo
-
         public class BodyInfo
         {
-            #region Constructors
-
             public BodyInfo(CelestialBody body, BodyInfo parent = null)
             {
                 try
                 {
                     // Set the body information.
-                    this.CelestialBody = body;
-                    this.Name = body.bodyName;
-                    this.Gravity = 9.81 * body.GeeASL;
-                    this.Atmosphere = body.atmosphere ? 101.325 * body.atmosphereMultiplier : 0;
-                    this.Parent = parent;
+                    CelestialBody = body;
+                    Name = body.bodyName;
+                    Gravity = 9.81 * body.GeeASL;
+                    Parent = parent;
 
                     // Set orbiting bodies information.
-                    this.Children = new List<BodyInfo>();
-                    foreach (var orbitingBody in body.orbitingBodies)
-                    {
-                        this.Children.Add(new BodyInfo(orbitingBody, this));
-                    }
-
-                    this.SelectedDepth = 0;
+                    Children = new List<BodyInfo>();
+                    foreach (CelestialBody orbitingBody in body.orbitingBodies)
+                    {
+                        Children.Add(new BodyInfo(orbitingBody, this));
+                    }
+
+                    SelectedDepth = 0;
                 }
                 catch (Exception ex)
                 {
@@ -142,37 +121,28 @@
                 }
             }
 
-            #endregion
-
-            #region Properties
-
+            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 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 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(this.Name, bodyName, StringComparison.CurrentCultureIgnoreCase))
+                    if (String.Equals(Name, bodyName, StringComparison.CurrentCultureIgnoreCase))
                     {
                         return this;
                     }
 
                     // Check to see if any of this bodies children are the searched body.
-                    foreach (var child in this.Children)
-                    {
-                        var body = child.GetBodyInfo(bodyName);
+                    foreach (BodyInfo child in Children)
+                    {
+                        BodyInfo body = child.GetBodyInfo(bodyName);
                         if (body != null)
                         {
                             return body;
@@ -188,33 +158,44 @@
                 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)
             {
-                this.Selected = state;
-                this.SelectedDepth = depth;
-                if (this.Parent != null)
-                {
-                    this.Parent.SetSelected(state, depth + 1);
-                }
-            }
-
-            #endregion
-
-            #region Debugging
+                Selected = state;
+                SelectedDepth = depth;
+                if (Parent != null)
+                {
+                    Parent.SetSelected(state, depth + 1);
+                }
+            }
 
             public override string ToString()
             {
-                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
+                string log = "\n" + Name +
+                             "\n\tGravity: " + Gravity +
+                             "\n\tSelected: " + Selected;
+
+                return Children.Aggregate(log, (current, child) => current + "\n" + child);
+            }
+        }
     }
 }

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -37,11 +37,11 @@
     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 atmosphericVelocity;
+        private float atmosphericMach;
         private GUIStyle bodiesButtonActiveStyle;
         private GUIStyle bodiesButtonStyle;
         private DropDown bodiesList;
@@ -256,14 +256,14 @@
 
                 if (this.showAtmosphericDetails)
                 {
-                    SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage;
+                    SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(Altitude);
                 }
                 else
                 {
                     SimManager.Atmosphere = 0;
                 }
 
-                SimManager.Velocity = this.atmosphericVelocity;
+                SimManager.Mach = this.atmosphericMach;
 
                 SimManager.RequestSimulation();
                 SimManager.TryStartSimulation();
@@ -296,18 +296,18 @@
         {
             GUILayout.BeginHorizontal();
             GUILayout.BeginVertical();
-            GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
             GUI.skin = HighLogic.Skin;
-            this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f);
+            Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth));
             GUI.skin = null;
             GUILayout.EndVertical();
 
             GUILayout.Space(5.0f);
-
+            
             GUILayout.BeginVertical();
-            GUILayout.Label("Velocity: " + this.atmosphericVelocity.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("Mach: " + this.atmosphericMach.ToString("F1"), this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
             GUI.skin = HighLogic.Skin;
-            this.atmosphericVelocity = GUILayout.HorizontalSlider(this.atmosphericVelocity, 0, 2500f);
+            atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, SimManager.LastStage.maxMach), 0.0f, SimManager.LastStage.maxMach);
             GUI.skin = null;
             GUILayout.EndVertical();
             GUILayout.EndHorizontal();
@@ -335,6 +335,7 @@
             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;
                 this.bodiesList.Resize = true;
             }
             GUILayout.EndHorizontal();

--- a/KerbalEngineer/Editor/BuildOverlayVessel.cs
+++ b/KerbalEngineer/Editor/BuildOverlayVessel.cs
@@ -188,7 +188,7 @@
 
             if (BuildAdvanced.Instance.ShowAtmosphericDetails)
             {
-                SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01;
+                SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(BuildAdvanced.Altitude);
             }
             else
             {

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

--- 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.0";
+        public const string AssemblyVersion = "1.0.16.3";
 
         #endregion
 

--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -83,27 +83,11 @@
         }
 
         /// <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. 
+            return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts(0.0f);
         }
 
         /// <summary>
@@ -140,13 +124,7 @@
         /// </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;
+            return part.Modules.OfType<T>().FirstOrDefault();
         }
 
         /// <summary>
@@ -286,13 +264,7 @@
         /// </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;
+            return part.Resources.list.Sum(r => (r.maxAmount - r.amount) * r.info.unitCost);
         }
 
         /// <summary>
@@ -337,12 +309,7 @@
         /// </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;
+            return part.Modules.OfType<T>().Any();
         }
 
         /// <summary>
@@ -350,13 +317,7 @@
         /// </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;
+            return part.Modules.OfType<T>().Any(predicate);
         }
 
         /// <summary>
@@ -460,9 +421,8 @@
         /// </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];
+            foreach (var vesselPart in partsList)
+            {
                 if (!vesselPart.HasModule(module.ClassID))
                 {
                     continue;

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

--- a/KerbalEngineer/Flight/Readouts/Surface/AtmosphericProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/AtmosphericProcessor.cs
@@ -29,6 +29,8 @@
 
 namespace KerbalEngineer.Flight.Readouts.Surface
 {
+    using UnityEngine;
+
     public class AtmosphericProcessor : IUpdatable, IUpdateRequest
     {
         #region Instance
@@ -46,7 +48,10 @@
         /// </summary>
         public static AtmosphericProcessor Instance
         {
-            get { return instance; }
+            get
+            {
+                return instance;
+            }
         }
 
         #endregion
@@ -122,13 +127,13 @@
                 }
                 else
                 {
-                    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.DragMultiplier;
-
-                    TerminalVelocity = Math.Sqrt((2 * mass * grav) / (atmo * drag * coef));
+                    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;
+
+                    TerminalVelocity = Math.Sqrt((2.0 * m * g) / (p * a * c));
                 }
 
                 Efficiency = FlightGlobals.ship_srfSpeed / TerminalVelocity;

--- a/KerbalEngineer/Flight/Readouts/Vessel/AttitudeProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/AttitudeProcessor.cs
@@ -123,7 +123,8 @@
             // This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation.
             this.centreOfMass = FlightGlobals.ActiveVessel.findWorldCenterOfMass();
             this.up = (this.centreOfMass - FlightGlobals.ActiveVessel.mainBody.position).normalized;
-            this.north = Vector3.Exclude(this.up, (FlightGlobals.ActiveVessel.mainBody.position + FlightGlobals.ActiveVessel.mainBody.transform.up * (float)FlightGlobals.ActiveVessel.mainBody.Radius) - this.centreOfMass).normalized;
+            this.north = Vector3.ProjectOnPlane((FlightGlobals.ActiveVessel.mainBody.position + FlightGlobals.ActiveVessel.mainBody.transform.up * (float)FlightGlobals.ActiveVessel.mainBody.Radius) - this.centreOfMass, this.up).normalized;
+
             return Quaternion.Inverse(Quaternion.Euler(90.0f, 0.0f, 0.0f) * Quaternion.Inverse(FlightGlobals.ActiveVessel.transform.rotation) * Quaternion.LookRotation(this.north, this.up));
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/SimulationProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SimulationProcessor.cs
@@ -119,7 +119,7 @@
                 SimManager.Gravity = FlightGlobals.ActiveVessel.mainBody.gravParameter /
                                      Math.Pow(FlightGlobals.ActiveVessel.mainBody.Radius +
                                               FlightGlobals.ActiveVessel.mainBody.GetAltitude(FlightGlobals.ActiveVessel.CoM), 2);
-                SimManager.Velocity = FlightGlobals.ActiveVessel.srfSpeed;
+                SimManager.Mach = FlightGlobals.ActiveVessel.mach;
             }
         }
 

--- a/KerbalEngineer/Helpers/Averager.cs
+++ b/KerbalEngineer/Helpers/Averager.cs
@@ -45,12 +45,6 @@
         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;
             totalweight += weight;

--- a/KerbalEngineer/Helpers/ForceAccumulator.cs
+++ b/KerbalEngineer/Helpers/ForceAccumulator.cs
@@ -19,27 +19,16 @@
 
 using System;
 using System.Collections.Generic;
-using KerbalEngineer.VesselSimulator;
-using Smooth.Pools;
 
 namespace KerbalEngineer
 {
     // a (force, application point) tuple
     public class AppliedForce
     {
-        public static readonly Pool<AppliedForce> pool = new Pool<AppliedForce>(Create, Reset);
-
         public Vector3d vector;
         public Vector3d applicationPoint;
 
-        static private AppliedForce Create()
-        {
-            return new AppliedForce();
-        }
-
-        static  private void Reset(AppliedForce appliedForce) { }
-
-        public void Set(Vector3d vector, Vector3d applicationPoint) {
+        public AppliedForce(Vector3d vector, Vector3d applicationPoint) {
             this.vector = vector;
             this.applicationPoint = applicationPoint;
         }
@@ -58,7 +47,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;
@@ -110,12 +99,5 @@
         {
             return GetMinTorqueForceApplicationPoint(avgApplicationPoint.Get());
         }
-
-        public void Reset()
-        {
-            totalForce = Vector3d.zero;
-            totalZeroOriginTorque = Vector3d.zero;
-            avgApplicationPoint.Reset();
-        }
 	}
 }

--- /dev/null
+++ b/KerbalEngineer/Helpers/Pool.cs
@@ -1,1 +1,53 @@
+namespace KerbalEngineer.VesselSimulator
+{
+    using System.Collections.Generic;
 
+    public class Pool<T> where T : new()
+    {
+        private static List<T> available = new List<T>();
+        private static List<T> inUse = new List<T>();
+
+        public static int PoolCount
+        {
+            get
+            {
+                return available.Count + inUse.Count;
+            }
+        }
+
+        public static T GetPoolObject()
+        {
+            T obj;
+            if (available.Count > 0)
+            {
+                obj = available[0];
+                available.RemoveAt(0);
+            }
+            else
+            {
+                obj = new T();
+            }
+
+            inUse.Add(obj);
+            return obj;
+        }
+
+        public static void Release(T obj)
+        {
+            if (inUse.Contains(obj))
+            {
+                inUse.Remove(obj);
+                available.Add(obj);
+            }
+        }
+
+        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,7 +20,6 @@
 namespace KerbalEngineer.Helpers
 {
     #region Using Directives
-
     using System;
 
     #endregion
@@ -28,6 +27,7 @@
     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)
         {
-            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";
+            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";
             return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN";
         }
 
@@ -180,7 +180,6 @@
         {
             return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
         }
-
         #endregion
     }
 }

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -124,11 +124,6 @@
     <Compile Include="Helpers\TimeFormatter.cs" />
     <Compile Include="KeyBinder.cs" />
     <Compile Include="Control\ControlCentre.cs" />
-    <Compile Include="Smooth\Delegates\Delegates.cs" />
-    <Compile Include="Smooth\Dispose\Disposable.cs" />
-    <Compile Include="Smooth\Dispose\DisposalQueue.cs" />
-    <Compile Include="Smooth\Dispose\SmoothDisposer.cs" />
-    <Compile Include="Smooth\Pools\Pool.cs" />
     <Compile Include="UIControls\DropDown.cs" />
     <Compile Include="Logger.cs" />
     <Compile Include="EngineerGlobals.cs" />
@@ -204,6 +199,7 @@
     <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" />
@@ -212,7 +208,7 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="Assembly-CSharp">
-      <HintPath>..\..\..\..\..\..\KSP\Releases\Clean_0.90.0\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
+      <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
       <Private>False</Private>
     </Reference>
     <Reference Include="System">
@@ -224,11 +220,10 @@
       <Private>False</Private>
     </Reference>
     <Reference Include="UnityEngine">
-      <HintPath>..\..\..\..\..\..\KSP\Releases\Clean_0.90.0\KSP_Data\Managed\UnityEngine.dll</HintPath>
+      <HintPath>..\Game\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/Smooth/Delegates/Delegates.cs
+++ /dev/null
@@ -1,25 +1,1 @@
-using System;
 
-namespace Smooth.Delegates {
-	public delegate void DelegateAction();
-	public delegate void DelegateAction<in T1>(T1 _1);
-	public delegate void DelegateAction<in T1, in T2>(T1 _1, T2 _2);
-	public delegate void DelegateAction<in T1, in T2, in T3>(T1 _1, T2 _2, T3 _3);
-	public delegate void DelegateAction<in T1, in T2, in T3, in T4>(T1 _1, T2 _2, T3 _3, T4 _4);
-	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5);
-	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6);
-	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6, in T7>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7);
-	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8);
-	public delegate void DelegateAction<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8, T9 _9);
-
-	public delegate R DelegateFunc<out R>();
-	public delegate R DelegateFunc<in T1, out R>(T1 _1);
-	public delegate R DelegateFunc<in T1, in T2, out R>(T1 _1, T2 _2);
-	public delegate R DelegateFunc<in T1, in T2, in T3, out R>(T1 _1, T2 _2, T3 _3);
-	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, out R>(T1 _1, T2 _2, T3 _3, T4 _4);
-	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5);
-	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6);
-	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, in T7, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7);
-	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8);
-	public delegate R DelegateFunc<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, out R>(T1 _1, T2 _2, T3 _3, T4 _4, T5 _5, T6 _6, T7 _7, T8 _8, T9 _9);
-}

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

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

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

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

--- a/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
+++ b/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
@@ -21,7 +21,6 @@
 
 using System;
 using System.Text;
-using Smooth.Pools;
 
 #endregion
 
@@ -29,26 +28,16 @@
 {
     internal class AttachNodeSim
     {
-
-        public 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 void Set(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
+        public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
         {
             this.attachedPartSim = partSim;
             this.nodeType = newNodeType;
             this.id = newId;
         }
-
-        static private void Reset(AttachNodeSim attachNodeSim) { }
 
         public void DumpToBuffer(StringBuilder buffer)
         {

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -17,187 +17,89 @@
 //     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 Smooth.Pools;
-using UnityEngine;
-
-#endregion
-
 namespace KerbalEngineer.VesselSimulator
 {
-    public class EngineSim
+    using System;
+    using System.Collections.Generic;
+    using System.Text;
+    using Editor;
+    using Helpers;
+    using UnityEngine;
+
+    public class EngineSim : Pool<EngineSim>
     {
-        public static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
-
-        private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
-
-        public double actualThrust = 0;
+        public double actualThrust = 0.0;
+        public List<AppliedForce> appliedForces = new List<AppliedForce>();
         public bool isActive = false;
         public double isp = 0;
         public PartSim partSim;
-        public List<AppliedForce> appliedForces = new List<AppliedForce>();
+        public float maxMach;
 
         public double thrust = 0;
 
         // Add thrust vector to account for directional losses
         public Vector3 thrustVec;
-
-        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++)
-            {
-                AppliedForce.pool.Release(engineSim.appliedForces[i]);
-            }
-            engineSim.appliedForces.Clear();
-            engineSim.thrust = 0;
-        }
-
-        public void Set(PartSim theEngine,
-                         double atmosphere,
-                         double velocity,
-                         float maxThrust,
-                         float minThrust,
-                         float thrustPercentage,
-                         float requestedThrust,
-                         Vector3 vecThrust,
-                         float realIsp,
-                         FloatCurve atmosphereCurve,
-                         FloatCurve velocityCurve,
-                         bool throttleLocked,
-                         List<Propellant> propellants,
-                         bool active,
-                         bool correctThrust,
-                         List<Transform> thrustTransforms)
+        private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
+
+        public EngineSim Init(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)
         {
             StringBuilder buffer = null;
-            //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
-            //MonoBehaviour.print("maxThrust = " + maxThrust);
-            //MonoBehaviour.print("minThrust = " + minThrust);
-            //MonoBehaviour.print("thrustPercentage = " + thrustPercentage);
-            //MonoBehaviour.print("requestedThrust = " + requestedThrust);
-            //MonoBehaviour.print("velocity = " + velocity);
-
-            this.partSim = theEngine;
-
-            this.isActive = active;
-            this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
-            //MonoBehaviour.print("thrust = " + thrust);
-
-            this.thrustVec = vecThrust;
-
-            double flowRate = 0d;
-            if (this.partSim.hasVessel)
-            {
-                //MonoBehaviour.print("hasVessel is true");
-                this.actualThrust = isActive ? requestedThrust : 0.0;
-                if (velocityCurve != null)
-                {
-                    this.actualThrust *= velocityCurve.Evaluate((float)velocity);
-                    //MonoBehaviour.print("actualThrust at velocity = " + actualThrust);
-                }
-
-                this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm);
-                if (this.isp == 0d)
-                {
-                    MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
-                }
-
-                if (correctThrust && realIsp == 0)
-                {
-                    float ispsl = atmosphereCurve.Evaluate(0);
-                    if (ispsl != 0)
-                    {
-                        this.thrust = this.thrust * this.isp / ispsl;
+
+            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;
+
+                if (throttleLocked)
+                {
+                    flowRate = GetFlowRate(thrust, isp);
+                }
+                else
+                {
+                    if (currentThrottle > 0.0f && partSim.isLanded == false)
+                    {
+                        flowRate = GetFlowRate(actualThrust, isp);
                     }
                     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);
-                }
-
-                if (throttleLocked)
-                {
-                    //MonoBehaviour.print("throttleLocked is true");
-                    flowRate = this.thrust / (this.isp * 9.82);
-                }
-                else
-                {
-                    if (this.partSim.isLanded)
-                    {
-                        //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
-                        flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.82);
-                    }
-                    else
-                    {
-                        if (requestedThrust > 0)
-                        {
-                            if (velocityCurve != null)
-                            {
-                                requestedThrust *= velocityCurve.Evaluate((float)velocity);
-                                //MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust);
-                            }
-
-                            //MonoBehaviour.print("requestedThrust > 0");
-                            flowRate = requestedThrust / (this.isp * 9.82);
-                        }
-                        else
-                        {
-                            //MonoBehaviour.print("requestedThrust <= 0");
-                            flowRate = this.thrust / (this.isp * 9.82);
-                        }
+                        flowRate = GetFlowRate(thrust, isp);
                     }
                 }
             }
             else
             {
-                //MonoBehaviour.print("hasVessel is false");
-                this.isp = atmosphereCurve.Evaluate((float)atmosphere);
-                if (this.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);
-                }
-
-                if (velocityCurve != null)
-                {
-                    this.thrust *= velocityCurve.Evaluate((float)velocity);
-                    //MonoBehaviour.print("thrust at velocity = " + thrust);
-                }
-
-                flowRate = this.thrust / (this.isp * 9.82);
+                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);
             }
 
             if (SimManager.logOutput)
@@ -207,9 +109,8 @@
             }
 
             float flowMass = 0f;
-            for (int i = 0; i < propellants.Count; i++)
-            {
-                Propellant propellant = propellants[i];
+            foreach (Propellant propellant in propellants)
+            {
                 flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
             }
 
@@ -218,9 +119,8 @@
                 buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
             }
 
-            for (int i = 0; i < propellants.Count; i++)
-            {
-                Propellant propellant = propellants[i];
+            foreach (Propellant propellant in propellants)
+            {
                 if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                 {
                     continue;
@@ -229,14 +129,9 @@
                 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);
-                }
-                this.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);
+                }
+                resourceConsumptions.Add(propellant.id, consumptionRate);
             }
 
             if (SimManager.logOutput)
@@ -244,106 +139,143 @@
                 MonoBehaviour.print(buffer);
             }
 
+            appliedForces.Clear();
             double thrustPerThrustTransform = thrust / thrustTransforms.Count;
-            for (int i = 0; i < thrustTransforms.Count; i++)
-            {
-                Transform thrustTransform = thrustTransforms[i];
+            foreach (Transform thrustTransform in thrustTransforms)
+            {
                 Vector3d direction = thrustTransform.forward.normalized;
                 Vector3d position = thrustTransform.position;
-
-                AppliedForce appliedForce = AppliedForce.pool.Borrow();
-                appliedForce.Set(direction * thrustPerThrustTransform, position);
-                appliedForces.Add(appliedForce);
-            }
+                appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position));
+            }
+
+            return this;
         }
 
         public ResourceContainer ResourceConsumptions
         {
-            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>();
+            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);
+        }
 
         public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
         {
             LogMsg log = 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);
-                }
+
+            // A dictionary to hold a set of parts for each resource
+            Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
+
+            foreach (int type in resourceConsumptions.Types)
+            {
+                HashSet<PartSim> sourcePartSet = null;
                 switch (ResourceContainer.GetResourceFlowMode(type))
                 {
                     case ResourceFlowMode.NO_FLOW:
-                        if (this.partSim.resources[type] > SimManager.RESOURCE_MIN && this.partSim.resourceFlowStates[type] != 0)
-                        {
-                            //sourcePartSet = new HashSet<PartSim>();
+                        if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0)
+                        {
+                            sourcePartSet = new HashSet<PartSim>();
                             //MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this");
-                            sourcePartSet.Add(this.partSim);
+                            sourcePartSet.Add(partSim);
                         }
                         break;
 
                     case ResourceFlowMode.ALL_VESSEL:
-                        for (int i = 0; i < allParts.Count; i++)
-                        {
-                            PartSim aPartSim = allParts[i];
+                        foreach (PartSim aPartSim in allParts)
+                        {
                             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:
-
-                        foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values)
-                        {
-                            stagePartSet.Clear();
-                        }
-                        var maxStage = -1;
+                        Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
+                        int maxStage = -1;
 
                         //Logger.Log(type);
-                        for (int i = 0; i < allParts.Count; i++)
-                        {
-                            var aPartSim = allParts[i];
+                        foreach (PartSim aPartSim in allParts)
+                        {
                             if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
                             {
                                 continue;
                             }
 
-                            var stage = aPartSim.DecouplerCount();
+                            int stage = aPartSim.DecouplerCount();
                             if (stage > maxStage)
                             {
                                 maxStage = stage;
                             }
 
-                            if (!stagePartSets.TryGetValue(stage, out sourcePartSet) || sourcePartSet.Count == 0)
-                            {
-                                if (sourcePartSet == null)
-                                    sourcePartSet = new HashSet<PartSim>();
-
+                            if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
+                            {
+                                sourcePartSet = new HashSet<PartSim>();
                                 stagePartSets.Add(stage, sourcePartSet);
                             }
                             sourcePartSet.Add(aPartSim);
                         }
 
-                        for (var i = 0; i <= maxStage; i++)
+                        for (int i = 0; i <= maxStage; i++)
                         {
                             HashSet<PartSim> stagePartSet;
                             if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0)
@@ -354,16 +286,14 @@
                         break;
 
                     case ResourceFlowMode.STACK_PRIORITY_SEARCH:
-                        visited.Clear();
+                        HashSet<PartSim> visited = new HashSet<PartSim>();
 
                         if (SimManager.logOutput)
                         {
                             log = new LogMsg();
-                            log.buf.AppendLine(
-                                "Find " + ResourceContainer.GetResourceName(type) + " sources for " + this.partSim.name + ":" +
-                                this.partSim.partId);
-                        }
-                        this.partSim.GetSourceSet(type, allParts, visited, sourcePartSet, log, "");
+                            log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId);
+                        }
+                        sourcePartSet = partSim.GetSourceSet(type, allParts, visited, log, "");
                         if (SimManager.logOutput)
                         {
                             MonoBehaviour.print(log.buf);
@@ -371,14 +301,11 @@
                         break;
 
                     default:
-                        MonoBehaviour.print(
-                            "SetResourceDrains(" + this.partSim.name + ":" + this.partSim.partId + ") Unexpected flow type for " +
-                            ResourceContainer.GetResourceName(type) + ")");
-                        break;
-                }
-
-
-                if (sourcePartSet.Count > 0)
+                        MonoBehaviour.print("SetResourceDrains(" + partSim.name + ":" + partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
+                        break;
+                }
+
+                if (sourcePartSet != null && sourcePartSet.Count > 0)
                 {
                     sourcePartSets[type] = sourcePartSet;
                     if (SimManager.logOutput)
@@ -393,50 +320,41 @@
                     }
                 }
             }
-            
+
             // If we don't have sources for all the needed resources then return false without setting up any drains
-            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)
+            foreach (int type in resourceConsumptions.Types)
+            {
+                if (!sourcePartSets.ContainsKey(type))
                 {
                     if (SimManager.logOutput)
                     {
                         MonoBehaviour.print("No source of " + ResourceContainer.GetResourceName(type));
                     }
 
-                    this.isActive = false;
+                    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 < this.resourceConsumptions.Types.Count; i++)
-            {
-                int type = this.resourceConsumptions.Types[i];
+            foreach (int type in resourceConsumptions.Types)
+            {
                 HashSet<PartSim> sourcePartSet = sourcePartSets[type];
                 // Loop through the members of the set 
-                double amount = this.resourceConsumptions[type] / sourcePartSet.Count;
+                double amount = 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
@@ -25,7 +25,7 @@
 using System.Text;
 
 using KerbalEngineer.Extensions;
-using Smooth.Pools;
+
 using UnityEngine;
 
 #endregion
@@ -36,10 +36,7 @@
 
     public class PartSim
     {
-        public 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;
@@ -73,29 +70,8 @@
         public double startMass = 0d;
         public String vesselName;
         public VesselType vesselType;
-        
-
-        private static PartSim Create()
-        {
-            return new PartSim();
-        }
-
-        private static void Reset(PartSim partSim)
-        {
-            for (int i = 0; i < partSim.attachNodes.Count; i++)
-            {
-                AttachNodeSim.pool.Release(partSim.attachNodes[i]);
-            }
-            partSim.attachNodes.Clear();
-            partSim.fuelTargets.Clear();
-            partSim.resourceDrains.Reset();
-            partSim.resourceFlowStates.Reset();
-            partSim.resources.Reset();
-            partSim.baseMass = 0d;
-            partSim.startMass = 0d;
-        }
-
-        public void Set(Part thePart, int id, double atmosphere, LogMsg log)
+
+        public PartSim(Part thePart, int id, double atmosphere, LogMsg log)
         {
             this.part = thePart;
             this.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
@@ -135,10 +111,8 @@
                 MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass);
             }
 
-            for (int i = 0; i < this.part.Resources.Count; i++)
-            {
-                PartResource resource = this.part.Resources[i];
-
+            foreach (PartResource resource in this.part.Resources)
+            {
                 // 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))
@@ -190,15 +164,15 @@
             get { return this.resourceDrains; }
         }
 
-        public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double velocity, bool vectoredThrust, LogMsg log)
+        public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double mach, bool vectoredThrust, bool fullThrust, LogMsg log)
         {
             bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(this.part);
             if (log != null)
             {
                 log.buf.AppendLine("CreateEngineSims for " + this.name);
-                for (int i = 0; i < this.part.Modules.Count; i++)
-                {
-                    PartModule partMod = this.part.Modules[i];
+
+                foreach (PartModule partMod in this.part.Modules)
+                {
                     log.buf.AppendLine("Module: " + partMod.moduleName);
                 }
 
@@ -211,10 +185,8 @@
                 // The mode of the engine is the engineID of the ModuleEnginesFX that is active
                 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];
+                foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
+                {
                     if (engine.engineID == mode)
                     {
                         if (log != null)
@@ -224,23 +196,22 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.pool.Borrow();
-                        engineSim.Set(
-                            this,
+                        EngineSim engineSim = EngineSim.GetPoolObject().Init(this,
                             atmosphere,
-                            velocity,
-                            engine.maxThrust,
-                            engine.minThrust,
+                            (float)mach,
+                            engine.maxFuelFlow,
+                            engine.minFuelFlow,
                             engine.thrustPercentage,
-                            engine.requestedThrust,
                             thrustvec,
-                            engine.realIsp,
                             engine.atmosphereCurve,
-                            engine.useVelocityCurve ? engine.velocityCurve : null,
-                            engine.throttleLocked,
+                            engine.atmChangeFlow,
+                            engine.useAtmCurve ? engine.atmCurve : null,
+                            engine.useVelCurve ? engine.velCurve : null,
+                            engine.currentThrottle,
+                            engine.throttleLocked || fullThrust,
                             engine.propellants,
                             engine.isOperational,
-                            correctThrust,
+                            engine.resultingThrust,
                             engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
@@ -248,12 +219,10 @@
             }
             else
             {
-                if (this.hasModuleEnginesFX)
-                {
-                    List<ModuleEnginesFX> enginesFx = this.part.GetModules<ModuleEnginesFX>();  // only place that still allocate some memory
-                    for (int i = 0; i < enginesFx.Count; i++)
-                    {
-                        ModuleEnginesFX engine = enginesFx[i];
+                if (this.hasModuleEngines)
+                {
+                    foreach (ModuleEngines engine in this.part.GetModules<ModuleEngines>())
+                    {
                         if (log != null)
                         {
                             log.buf.AppendLine("Module: " + engine.moduleName);
@@ -261,62 +230,26 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.pool.Borrow();
-                        engineSim.Set(
-                            this,
+                        EngineSim engineSim = EngineSim.GetPoolObject().Init(this,
                             atmosphere,
-                            velocity,
-                            engine.maxThrust,
-                            engine.minThrust,
+                            (float)mach,
+                            engine.maxFuelFlow,
+                            engine.minFuelFlow,
                             engine.thrustPercentage,
-                            engine.requestedThrust,
                             thrustvec,
-                            engine.realIsp,
                             engine.atmosphereCurve,
-                            engine.useVelocityCurve ? engine.velocityCurve : null,
-                            engine.throttleLocked,
+                            engine.atmChangeFlow,
+                            engine.useAtmCurve ? engine.atmCurve : null,
+                            engine.useVelCurve ? engine.velCurve : null,
+                            engine.currentThrottle,
+                            engine.throttleLocked || fullThrust,
                             engine.propellants,
                             engine.isOperational,
-                            correctThrust,
+                            engine.resultingThrust,
                             engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
                 }
-
-                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)
-                        {
-                            log.buf.AppendLine("Module: " + engine.moduleName);
-                        }
-
-                        Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
-
-                        EngineSim engineSim = EngineSim.pool.Borrow();
-                        engineSim.Set(
-                            this,
-                            atmosphere,
-                            velocity,
-                            engine.maxThrust,
-                            engine.minThrust,
-                            engine.thrustPercentage,
-                            engine.requestedThrust,
-                            thrustvec,
-                            engine.realIsp,
-                            engine.atmosphereCurve,
-                            engine.useVelocityCurve ? engine.velocityCurve : null,
-                            engine.throttleLocked,
-                            engine.propellants,
-                            engine.isOperational,
-                            correctThrust,
-                            engine.thrustTransforms);
-                        allEngines.Add(engineSim);
-                    }
-                }
             }
 
             if (log != null)
@@ -333,17 +266,11 @@
             }
 
             Vector3 thrustvec = Vector3.zero;
-            for (int i = 0; i < thrustTransforms.Count; i++)
-            {
-                Transform trans = thrustTransforms[i];
+            foreach (Transform trans in thrustTransforms)
+            {
                 if (log != null)
                 {
-                    log.buf.AppendFormat(
-                        "Transform = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n",
-                        trans.forward.x,
-                        trans.forward.y,
-                        trans.forward.z,
-                        trans.forward.magnitude);
+                    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;
@@ -394,14 +321,11 @@
             }
 
             this.attachNodes.Clear();
-            for (int i = 0; i < this.part.attachNodes.Count; i++)
-            {
-                AttachNode attachNode = this.part.attachNodes[i];
+            foreach (AttachNode attachNode in this.part.attachNodes)
+            {
                 if (log != null)
                 {
-                    log.buf.AppendLine(
-                        "AttachNode " + attachNode.id + " = " +
-                        (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
+                    log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
                 }
 
                 if (attachNode.attachedPart != null && attachNode.id != "Strut")
@@ -414,9 +338,7 @@
                             log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
                         }
 
-                        AttachNodeSim attachnode = AttachNodeSim.pool.Borrow();
-                        attachnode.Set(attachedSim, attachNode.id, attachNode.nodeType);
-                        this.attachNodes.Add(attachnode);
+                        this.attachNodes.Add(new AttachNodeSim(attachedSim, attachNode.id, attachNode.nodeType));
                     }
                     else
                     {
@@ -428,9 +350,8 @@
                 }
             }
 
-            for (int i = 0; i < this.part.fuelLookupTargets.Count; i++)
-            {
-                Part p = this.part.fuelLookupTargets[i];
+            foreach (Part p in this.part.fuelLookupTargets)
+            {
                 if (p != null)
                 {
                     PartSim targetSim;
@@ -496,13 +417,18 @@
                 return true;
             }
 
-            if (!this.part.IsEngine())
+            var modList = this.part.Modules.OfType<ModuleEngines>();
+            if (modList.Count() == 0)
             {
                 return false;
             }
 
-
-            return this.part.IsSolidRocket();
+            if (modList.First().throttleLocked)
+            {
+                return true;
+            }
+
+            return false;
         }
 
         public void ReleasePart()
@@ -513,7 +439,7 @@
         // 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)
+        public HashSet<PartSim> GetSourceSet(int type, List<PartSim> allParts, HashSet<PartSim> visited, LogMsg log, String indent)
         {
             if (log != null)
             {
@@ -521,7 +447,10 @@
                 indent += "  ";
             }
 
-            // Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns as is.
+            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.
             if (visited.Contains(this))
             {
                 if (log != null)
@@ -529,7 +458,7 @@
                     log.buf.AppendLine(indent + "Returning empty set, already visited (" + this.name + ":" + this.partId + ")");
                 }
 
-                return;
+                return allSources;
             }
 
             //if (log != null)
@@ -541,11 +470,8 @@
             // 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");
 
-            int lastCount = allSources.Count;
-
-            for (int i = 0; i < this.fuelTargets.Count; i++)
-            {
-                PartSim partSim = this.fuelTargets[i];
+            foreach (PartSim partSim in this.fuelTargets)
+            {
                 if (visited.Contains(partSim))
                 {
                     //if (log != null)
@@ -556,20 +482,24 @@
                     //if (log != null)
                     //    log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
 
-                    partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
-                }
-            }
-
-            if (allSources.Count > lastCount)
+                    partSources = partSim.GetSourceSet(type, allParts, visited, log, indent);
+                    if (partSources.Count > 0)
+                    {
+                        allSources.UnionWith(partSources);
+                        partSources.Clear();
+                    }
+                }
+            }
+
+            if (allSources.Count > 0)
             {
                 if (log != null)
                 {
-                    log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
-                }
-
-                return;
-            }
-
+                    log.buf.AppendLine(indent + "Returning " + allSources.Count + " fuel target sources (" + this.name + ":" + this.partId + ")");
+                }
+
+                return allSources;
+            }
 
             // Rule 3: This rule has been removed and merged with rules 4 and 7 to fix issue with fuel tanks with disabled crossfeed
 
@@ -580,18 +510,14 @@
             //  The order in which mount points of a part are scanned appears to be fixed and defined by the part specification file. [Experiment]
             if (this.fuelCrossFeed)
             {
-                lastCount = allSources.Count;
                 //MonoBehaviour.print("foreach attach node");
-                for (int i = 0; i < this.attachNodes.Count; i++)
-                {
-                    AttachNodeSim attachSim = this.attachNodes[i];
+                foreach (AttachNodeSim attachSim in this.attachNodes)
+                {
                     if (attachSim.attachedPartSim != null)
                     {
                         if (attachSim.nodeType == AttachNode.NodeType.Stack)
                         {
-                            if (
-                                !(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 &&
-                                  attachSim.id.Contains(this.noCrossFeedNodeKey)))
+                            if (!(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 && attachSim.id.Contains(this.noCrossFeedNodeKey)))
                             {
                                 if (visited.Contains(attachSim.attachedPartSim))
                                 {
@@ -603,21 +529,26 @@
                                     //if (log != null)
                                     //    log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
 
-                                    attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
+                                    partSources = attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, log, indent);
+                                    if (partSources.Count > 0)
+                                    {
+                                        allSources.UnionWith(partSources);
+                                        partSources.Clear();
+                                    }
                                 }
                             }
                         }
                     }
                 }
 
-                if (allSources.Count > lastCount)
+                if (allSources.Count > 0)
                 {
                     if (log != null)
                     {
-                        log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
-                    }
-
-                    return;
+                        log.buf.AppendLine(indent + "Returning " + allSources.Count + " attached sources (" + this.name + ":" + this.partId + ")");
+                    }
+
+                    return allSources;
                 }
             }
 
@@ -637,7 +568,7 @@
                     }
                 }
 
-                return;
+                return allSources;
             }
 
             // 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 
@@ -653,16 +584,15 @@
                     }
                     else
                     {
-                        lastCount = allSources.Count;
-                        this.parent.GetSourceSet(type, allParts, visited, allSources, log, indent);
-                        if (allSources.Count > lastCount)
+                        allSources = this.parent.GetSourceSet(type, allParts, visited, log, indent);
+                        if (allSources.Count > 0)
                         {
                             if (log != null)
                             {
-                                log.buf.AppendLine(indent + "Returning " + (allSources.Count  - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
+                                log.buf.AppendLine(indent + "Returning " + allSources.Count + " parent sources (" + this.name + ":" + this.partId + ")");
                             }
 
-                            return;
+                            return allSources;
                         }
                     }
                 }
@@ -672,15 +602,14 @@
             //if (log != null)
             //    log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
 
-            return;
+            return allSources;
         }
 
         public void RemoveAttachedParts(HashSet<PartSim> partSims)
         {
             // Loop through the attached parts
-            for (int i = 0; i < this.attachNodes.Count; i++)
-            {
-                AttachNodeSim attachSim = this.attachNodes[i];
+            foreach (AttachNodeSim attachSim in this.attachNodes)
+            {
                 // If the part is in the set then "remove" it by clearing the PartSim reference
                 if (partSims.Contains(attachSim.attachedPartSim))
                 {
@@ -692,9 +621,8 @@
         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];
+            foreach (int type in this.resourceDrains.Types)
+            {
                 //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]);
@@ -706,9 +634,8 @@
             //MonoBehaviour.print("TimeToDrainResource(" + name + ":" + partId + ")");
             double time = double.MaxValue;
 
-            for (int i = 0; i < this.resourceDrains.Types.Count; i++)
-            {
-                int type = this.resourceDrains.Types[i];
+            foreach (int type in this.resourceDrains.Types)
+            {
                 if (this.resourceDrains[type] > 0)
                 {
                     time = Math.Min(time, this.resources[type] / this.resourceDrains[type]);
@@ -759,9 +686,8 @@
         {
             double mass = this.baseMass;
 
-            for (int i = 0; i < this.resources.Types.Count; i++)
-            {
-                int type = this.resources.Types[i];
+            foreach (int type in this.resources.Types)
+            {
                 mass += this.resources.GetResourceMass(type);
             }
 
@@ -795,9 +721,8 @@
 
             buffer.AppendFormat(", isSep = {0}", this.isSepratron);
 
-            for (int i = 0; i < this.resources.Types.Count; i++)
-            {
-                int type = this.resources.Types[i];
+            foreach (int type in this.resources.Types)
+            {
                 buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), this.resources[type]);
             }
 
@@ -820,9 +745,8 @@
             if (allParts != null)
             {
                 String newPrefix = prefix + " ";
-                for (int i = 0; i < allParts.Count; i++)
-                {
-                    PartSim partSim = allParts[i];
+                foreach (PartSim partSim in allParts)
+                {
                     if (partSim.parent == this)
                     {
                         partSim.DumpPartToBuffer(buffer, newPrefix, allParts);

--- a/KerbalEngineer/VesselSimulator/ResourceContainer.cs
+++ b/KerbalEngineer/VesselSimulator/ResourceContainer.cs
@@ -19,7 +19,6 @@
 
 #region Using Directives
 
-using System;
 using System.Collections;
 using System.Collections.Generic;
 
@@ -31,17 +30,15 @@
 {
     public class ResourceContainer
     {
-        private Dictionary<int, double> resources = new Dictionary<int, double>();
-        private List<int> types = new List<int>();
+        private Hashtable resources = new Hashtable();
 
         public double this[int type]
         {
             get
             {
-                double value;
-                if (this.resources.TryGetValue(type, out value))
+                if (this.resources.ContainsKey(type))
                 {
-                    return value;
+                    return (double)this.resources[type];
                 }
 
                 return 0d;
@@ -55,7 +52,6 @@
                 else
                 {
                     this.resources.Add(type, value);
-                    this.types.Add(type);
                 }
             }
         }
@@ -64,6 +60,13 @@
         {
             get
             {
+                List<int> types = new List<int>();
+
+                foreach (int key in this.resources.Keys)
+                {
+                    types.Add(key);
+                }
+
                 return types;
             }
         }
@@ -89,7 +92,7 @@
             {
                 foreach (int type in this.resources.Keys)
                 {
-                    if (this.resources[type] > SimManager.RESOURCE_MIN)
+                    if ((double)this.resources[type] > SimManager.RESOURCE_MIN)
                     {
                         return false;
                     }
@@ -108,7 +111,7 @@
         {
             foreach (int type in types)
             {
-                if (this.HasType(type) && this.resources[type] > SimManager.RESOURCE_MIN)
+                if (this.HasType(type) && (double)this.resources[type] > SimManager.RESOURCE_MIN)
                 {
                     return false;
                 }
@@ -121,19 +124,17 @@
         {
             if (this.resources.ContainsKey(type))
             {
-                this.resources[type] = this.resources[type] + amount;
+                this.resources[type] = (double)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()
@@ -147,7 +148,7 @@
         public double GetResourceMass(int type)
         {
             double density = GetResourceDensity(type);
-            return density == 0d ? 0d : this.resources[type] * density;
+            return density == 0d ? 0d : (double)this.resources[type] * density;
         }
 
         public static ResourceFlowMode GetResourceFlowMode(int type)
@@ -157,7 +158,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,6 +22,7 @@
     #region Using Directives
 
     using System;
+    using System.Collections.Generic;
     using System.Diagnostics;
     using System.Reflection;
     using System.Threading;
@@ -60,6 +61,9 @@
         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
@@ -84,7 +88,7 @@
 
         public static Stage[] Stages { get; private set; }
 
-        public static double Velocity { get; set; }
+        public static double Mach { get; set; }
 
         public static String failMessage { get; private set; }
 
@@ -283,6 +287,7 @@
             try
             {
                 Stages = (simObject as Simulation).RunSimulation();
+
                 if (Stages != null && Stages.Length > 0)
                 {
                     if (logOutput)
@@ -350,15 +355,21 @@
                     timer.Start();
                 }
 
-                var parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.ship.parts : FlightGlobals.ActiveVessel.Parts;
-
-                // Create the Simulation object in this thread
-                var sim = new Simulation();
+                if (HighLogic.LoadedSceneIsEditor)
+                {
+                    parts = EditorLogic.fetch.ship.parts;
+                }
+                else
+                {
+                    parts = FlightGlobals.ActiveVessel.Parts;
+                    Atmosphere = FlightGlobals.ActiveVessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres;
+                }
 
                 // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
-                if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Velocity, dumpTree, vectoredThrust))
-                {
-                    ThreadPool.QueueUserWorkItem(RunSimulation, sim);
+                if (simulation.PrepareSimulation(parts, Gravity, Atmosphere, Mach, dumpTree, vectoredThrust))
+                {
+                    //ThreadPool.QueueUserWorkItem(RunSimulation, simulation);
+                    RunSimulation(simulation);
                 }
                 else
                 {

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -38,24 +38,24 @@
         private const double STD_GRAVITY = 9.82;
         private const double SECONDS_PER_DAY = 86400;
         private readonly Stopwatch _timer = new Stopwatch();
-        private List<EngineSim> activeEngines;
-        private List<EngineSim> allEngines;
-        private List<PartSim> allFuelLines;
-        private List<PartSim> allParts;
+        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 double atmosphere;
         private int currentStage;
         private double currentisp;
+        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 bool doingCurrent;
-        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;
+        private List<Part> partList = new List<Part>();
         private double simpleTotalThrust;
         private double stageStartMass;
         private Vector3d stageStartCom;
@@ -70,23 +70,13 @@
         private Vector3 vecActualThrust;
         private Vector3 vecStageDeltaV;
         private Vector3 vecThrust;
-        private double velocity;
+        private double mach;
+        private float maxMach;
         public String vesselName;
         public VesselType vesselType;
 
         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");
@@ -99,9 +89,8 @@
             {
                 double mass = 0d;
 
-                for (int i = 0; i < this.allParts.Count; i++)
-                {
-                    PartSim partSim = this.allParts[i];
+                foreach (PartSim partSim in this.allParts)
+                {
                     mass += partSim.GetMass();
                 }
 
@@ -115,9 +104,8 @@
             {
                 WeightedVectorAverager averager = new WeightedVectorAverager();
 
-                for (int i = 0; i < this.allParts.Count; i++)
-                {
-                    PartSim partSim = this.allParts[i];
+                foreach (PartSim partSim in this.allParts)
+                {
                     averager.Add(partSim.centerOfMass, partSim.GetMass());
                 }
 
@@ -129,7 +117,7 @@
         // need during the simulation.  All required data is copied from the core game data structures 
         // so that the simulation itself can be run in a background thread without having issues with 
         // the core game changing the data while the simulation is running.
-        public bool PrepareSimulation(List<Part> parts, double theGravity, double theAtmosphere = 0, double theVelocity = 0, bool dumpTree = false, bool vectoredThrust = false)
+        public bool PrepareSimulation(List<Part> parts, double theGravity, double theAtmosphere = 0, double theMach = 0, bool dumpTree = false, bool vectoredThrust = false, bool fullThrust = false)
         {
             LogMsg log = null;
             if (SimManager.logOutput)
@@ -144,17 +132,19 @@
             this.partList = parts;
             this.gravity = theGravity;
             this.atmosphere = theAtmosphere;
-            this.velocity = theVelocity;
+            this.mach = theMach;
             this.lastStage = Staging.lastStage;
             //MonoBehaviour.print("lastStage = " + lastStage);
 
             // Clear the lists for our simulation parts
-            this.allParts.Clear();
-            this.allFuelLines.Clear();
-            this.drainingParts.Clear();
-            this.allEngines.Clear();
-            this.activeEngines.Clear();
-            this.drainingResources.Clear();
+            allParts.Clear();
+            allFuelLines.Clear();
+            drainingParts.Clear();
+            allEngines.Clear();
+            activeEngines.Clear();
+            drainingResources.Clear();
+
+            EngineSim.ReleaseAll();
 
             // A dictionary for fast lookup of Part->PartSim during the preparation phase
             partSimLookup.Clear();
@@ -164,12 +154,11 @@
                 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 < this.partList.Count; i++)
-            {
-                Part part = this.partList[i];
+            foreach (Part part in this.partList)
+            {
                 // If the part is already in the lookup dictionary then log it and skip to the next part
                 if (partSimLookup.ContainsKey(part))
                 {
@@ -181,8 +170,7 @@
                 }
 
                 // Create the PartSim
-                PartSim partSim = PartSim.pool.Borrow();
-                partSim.Set(part, partId, this.atmosphere, log);
+                PartSim partSim = new PartSim(part, partId, this.atmosphere, log);
 
                 // Add it to the Part lookup dictionary and the necessary lists
                 partSimLookup.Add(part, partSim);
@@ -193,28 +181,31 @@
                 }
                 if (partSim.isEngine)
                 {
-                    partSim.CreateEngineSims(this.allEngines, this.atmosphere, this.velocity, vectoredThrust, log);
+                    partSim.CreateEngineSims(this.allEngines, this.atmosphere, this.mach, vectoredThrust, fullThrust, log);
                 }
 
                 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
-            for (int i = 0; i < this.allParts.Count; i++)
-            {
-                PartSim partSim = this.allParts[i];
+            foreach (PartSim partSim in this.allParts)
+            {
                 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 < this.allFuelLines.Count; i++)
-                {
-                    PartSim partSim = this.allFuelLines[i];
+                foreach (PartSim partSim in this.allFuelLines)
+                {
                     CModuleFuelLine fuelLine = partSim.part.GetModule<CModuleFuelLine>();
                     if (fuelLine.target != null)
                     {
@@ -247,9 +238,8 @@
             }
 
             //MonoBehaviour.print("SetupAttachNodes and count stages");
-            for (int i = 0; i < this.allParts.Count; i++)
-            {
-                PartSim partSim = this.allParts[i];
+            foreach (PartSim partSim in this.allParts)
+            {
                 partSim.SetupAttachNodes(partSimLookup, log);
                 if (partSim.decoupledInStage >= this.lastStage)
                 {
@@ -259,9 +249,8 @@
 
             // And finally release the Part references from all the PartSims
             //MonoBehaviour.print("ReleaseParts");
-            for (int i = 0; i < this.allParts.Count; i++)
-            {
-                PartSim partSim = this.allParts[i];
+            foreach (PartSim partSim in this.allParts)
+            {
                 partSim.ReleasePart();
             }
 
@@ -282,7 +271,7 @@
 
             return true;
         }
-        
+
         // This function runs the simulation and returns a newly created array of Stage objects
         public Stage[] RunSimulation()
         {
@@ -302,13 +291,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 < this.allEngines.Count; i++)
-            {
-                EngineSim engine = this.allEngines[i];
+            foreach (EngineSim engine in this.allEngines)
+            {
                 if (log != null)
                 {
                     log.buf.AppendLine("Testing engine mod of " + engine.partSim.name + ":" + engine.partSim.partId);
@@ -363,7 +352,7 @@
             }
 
             // Create a list of lists of PartSims that prevent decoupling
-            this.BuildDontStageLists(log);
+            BuildDontStageLists(log);
 
             if (log != null)
             {
@@ -372,6 +361,7 @@
 
             // Create the array of stages that will be returned
             Stage[] stages = new Stage[this.currentStage + 1];
+
 
             // Loop through the stages
             while (this.currentStage >= 0)
@@ -435,9 +425,8 @@
 
                 // 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 < this.allParts.Count; i++)
-                {
-                    PartSim partSim = this.allParts[i];
+                foreach (PartSim partSim in this.allParts)
+                {
                     if (partSim.decoupledInStage == this.currentStage - 1)
                     {
                         stage.cost += partSim.cost;
@@ -454,9 +443,8 @@
                     if (this.dontStageParts.Count > 0)
                     {
                         log.buf.AppendLine("Parts preventing staging:");
-                        for (int i = 0; i < this.dontStageParts.Count; i++)
-                        {
-                            PartSim partSim = this.dontStageParts[i];
+                        foreach (PartSim partSim in this.dontStageParts)
+                        {
                             partSim.DumpPartToBuffer(log.buf, "");
                         }
                     }
@@ -467,7 +455,6 @@
 
                     log.Flush();
                 }
-
 
                 // Now we will loop until we are allowed to stage
                 int loopCounter = 0;
@@ -475,6 +462,7 @@
                 {
                     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;
@@ -492,6 +480,7 @@
                     {
                         MonoBehaviour.print("Drain time = " + resourceDrainTime + " (" + partMinDrain.name + ":" + partMinDrain.partId + ")");
                     }
+
                     foreach (PartSim partSim in this.drainingParts)
                     {
                         partSim.DrainResources(resourceDrainTime);
@@ -523,7 +512,7 @@
 
                     // Recalculate the current thrust and isp for the next step
                     this.CalculateThrustAndISP();
-                    
+
                     // Check if we actually changed anything
                     if (this.stepStartMass == this.stepEndMass)
                     {
@@ -549,7 +538,6 @@
                     this.stepStartMass = this.stepEndMass;
                 }
 
-
                 // Store more values in the Stage object and stick it in the array
 
                 // Store the magnitude of the deltaV vector
@@ -571,6 +559,7 @@
                 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
@@ -629,54 +618,37 @@
                 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)
-            {
-                PartSim.pool.Release(part);
-            }
-            //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)
-            {
-                EngineSim.pool.Release(engine);
-            }
-            //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 < this.allParts.Count; i++)
-            {
-                PartSim partSim = this.allParts[i];
+                }
+            }
+
+            foreach (PartSim partSim in this.allParts)
+            {
                 if (partSim.isEngine || !partSim.Resources.Empty)
                 {
                     if (log != null)
                     {
-                        log.buf.AppendLine(
-                            partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
+                        log.buf.AppendLine(partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
                     }
 
                     if (partSim.decoupledInStage < -1 || partSim.decoupledInStage > this.currentStage - 1)
@@ -706,9 +678,8 @@
         private void UpdateActiveEngines()
         {
             this.activeEngines.Clear();
-            for (int i = 0; i < this.allEngines.Count; i++)
-            {
-                EngineSim engine = this.allEngines[i];
+            foreach (EngineSim engine in this.allEngines)
+            {
                 if (engine.isActive)
                 {
                     this.activeEngines.Add(engine);
@@ -726,12 +697,12 @@
             this.totalStageActualThrust = 0d;
             this.totalStageFlowRate = 0d;
             this.totalStageIspFlowRate = 0d;
-            this.totalStageThrustForce.Reset();
+            this.totalStageThrustForce = new ForceAccumulator();
+
             // 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 < this.activeEngines.Count; i++)
-            {
-                EngineSim engine = this.activeEngines[i];
+            foreach (EngineSim engine in this.activeEngines)
+            {
                 this.simpleTotalThrust += engine.thrust;
                 this.vecThrust += ((float)engine.thrust * engine.thrustVec);
                 this.vecActualThrust += ((float)engine.actualThrust * engine.thrustVec);
@@ -739,13 +710,13 @@
                 this.totalStageFlowRate += engine.ResourceConsumptions.Mass;
                 this.totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp;
 
-                for (int j = 0; j < engine.appliedForces.Count; j++)
-                {
-                    AppliedForce f = engine.appliedForces[j];
+                foreach (AppliedForce f in engine.appliedForces) {
                     this.totalStageThrustForce.AddForce(f);
                 }
             }
+
             //MonoBehaviour.print("vecThrust = " + vecThrust.ToString() + "   magnitude = " + vecThrust.magnitude);
+
             this.totalStageThrust = this.vecThrust.magnitude;
             this.totalStageActualThrust = this.vecActualThrust.magnitude;
 
@@ -780,16 +751,14 @@
             this.drainingParts.Clear();
 
             // Loop through all the active engine modules
-            for (int i = 0; i < this.activeEngines.Count; i++)
-            {
-                EngineSim engine = this.activeEngines[i];
+            foreach (EngineSim engine in this.activeEngines)
+            {
                 // 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++)
-                    {
-                        int type = engine.ResourceConsumptions.Types[j];
+                    foreach (int type in engine.ResourceConsumptions.Types)
+                    {
                         this.drainingResources.Add(type);
                     }
                 }
@@ -803,9 +772,8 @@
                 StringBuilder buffer = new StringBuilder(1024);
                 buffer.AppendFormat("Active engines = {0:d}\n", this.activeEngines.Count);
                 int i = 0;
-                for (int j = 0; j < this.activeEngines.Count; j++)
-                {
-                    EngineSim engine = this.activeEngines[j];
+                foreach (EngineSim engine in this.activeEngines)
+                {
                     engine.DumpEngineToBuffer(buffer, "Engine " + (i++) + ":");
                 }
                 MonoBehaviour.print(buffer);
@@ -825,9 +793,8 @@
 
             if (this.activeEngines.Count > 0)
             {
-                for (int i = 0; i < this.dontStageParts.Count; i++)
-                {
-                    PartSim partSim = this.dontStageParts[i];
+                foreach (PartSim partSim in this.dontStageParts)
+                {
                     if (SimManager.logOutput)
                     {
                         partSim.DumpPartToBuffer(buffer, "Testing: ");
@@ -846,9 +813,8 @@
 
                     if (partSim.isEngine)
                     {
-                        for (int j = 0; j < this.activeEngines.Count; j++)
-                        {
-                            EngineSim engine = this.activeEngines[j];
+                        foreach (EngineSim engine in this.activeEngines)
+                        {
                             if (engine.partSim == partSim)
                             {
                                 if (SimManager.logOutput)
@@ -887,9 +853,8 @@
         {
             // Build a set of all the parts that will be decoupled
             decoupledParts.Clear();
-            for (int i = 0; i < this.allParts.Count; i++)
-            {
-                PartSim partSim = this.allParts[i];
+            foreach (PartSim partSim in this.allParts)
+            {
                 if (partSim.decoupledInStage >= this.currentStage)
                 {
                     decoupledParts.Add(partSim);
@@ -900,17 +865,14 @@
             {
                 // Remove it from the all parts list
                 this.allParts.Remove(partSim);
-                PartSim.pool.Release(partSim);
                 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--)
                     {
-                        EngineSim engine = this.allEngines[i];
-                        if (engine.partSim == partSim)
+                        if (this.allEngines[i].partSim == partSim)
                         {
                             this.allEngines.RemoveAt(i);
-                            EngineSim.pool.Release(engine);
                         }
                     }
                 }
@@ -922,17 +884,15 @@
             }
 
             // Loop through all the (remaining) parts
-            for (int i = 0; i < this.allParts.Count; i++)
-            {
-                PartSim partSim = this.allParts[i];
+            foreach (PartSim partSim in this.allParts)
+            {
                 // Ask the part to remove all the parts that are decoupled
                 partSim.RemoveAttachedParts(decoupledParts);
             }
 
             // Now we loop through all the engines and activate those that are ignited in this stage
-            for (int i = 0; i < this.allEngines.Count; i++)
-            {
-                EngineSim engine = this.allEngines[i];
+            foreach (EngineSim engine in this.allEngines)
+            {
                 if (engine.partSim.inverseStage == this.currentStage)
                 {
                     engine.isActive = true;

--- a/KerbalEngineer/VesselSimulator/Stage.cs
+++ b/KerbalEngineer/VesselSimulator/Stage.cs
@@ -51,6 +51,7 @@
         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":15,
-		"BUILD":2
+		"PATCH":16,
+		"BUILD":3
 	},
 	"KSP_VERSION":
 	{
-		"MAJOR":0,
-		"MINOR":90,
+		"MAJOR":1,
+		"MINOR":0,
 		"PATCH":0
 	}
 }