ForceAccumulator is now resettable.
ForceAccumulator is now resettable.

 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 ? body.atmospherePressureSeaLevel : 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;
@@ -65,6 +65,7 @@
         private GUIStyle titleStyle;
         private bool visible = true;
         private GUIStyle windowStyle;
+        private float maxMach;
 
         #endregion
 
@@ -139,7 +140,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.Awake()");
             }
         }
 
@@ -165,7 +166,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.OnDestroy()");
             }
         }
 
@@ -215,7 +216,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.OnGUI()");
             }
         }
 
@@ -228,7 +229,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.Start()");
             }
         }
 
@@ -256,21 +257,21 @@
 
                 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();
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced->Update");
+                Logger.Exception(ex, "BuildAdvanced.Update()");
             }
         }
 
@@ -294,23 +295,30 @@
         /// </summary>
         private void DrawAtmosphericDetails()
         {
-            GUILayout.BeginHorizontal();
-            GUILayout.BeginVertical();
-            GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
-            GUI.skin = HighLogic.Skin;
-            this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f);
-            GUI.skin = null;
-            GUILayout.EndVertical();
-
-            GUILayout.Space(5.0f);
-
-            GUILayout.BeginVertical();
-            GUILayout.Label("Velocity: " + this.atmosphericVelocity.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
-            GUI.skin = HighLogic.Skin;
-            this.atmosphericVelocity = GUILayout.HorizontalSlider(this.atmosphericVelocity, 0, 2500f);
-            GUI.skin = null;
-            GUILayout.EndVertical();
-            GUILayout.EndHorizontal();
+            try
+            {
+                GUILayout.BeginHorizontal();
+                GUILayout.BeginVertical();
+                GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+                GUI.skin = HighLogic.Skin;
+                Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth));
+                GUI.skin = null;
+                GUILayout.EndVertical();
+
+                GUILayout.Space(5.0f);
+
+                GUILayout.BeginVertical();
+                GUILayout.Label("Mach: " + this.atmosphericMach.ToString("F1"), this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+                GUI.skin = HighLogic.Skin;
+                atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, maxMach), 0.0f, maxMach);
+                GUI.skin = null;
+                GUILayout.EndVertical();
+                GUILayout.EndHorizontal();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced.DrawAtmosphericDetails()");
+            }
         }
 
         private void DrawBodiesList()
@@ -335,6 +343,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();
@@ -589,7 +598,11 @@
 
         private void GetStageInfo()
         {
-            this.stages = SimManager.Stages;
+            stages = SimManager.Stages;
+            if (stages != null && stages.Length > 0)
+            {
+                maxMach = stages[stages.Length - 1].maxMach;
+            }
         }
 
         /// <summary>
@@ -702,7 +715,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced->Load");
+                Logger.Exception(ex, "BuildAdvanced.Load()");
             }
         }
 
@@ -797,7 +810,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.Window()");
             }
         }
 

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

--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -464,7 +464,7 @@
         /// </summary>
         public static bool IsSolidRocket(this Part part)
         {
-            return part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked;
+            return (part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked) || (part.HasModule<ModuleEnginesFX>() && part.GetModuleEnginesFx().throttleLocked);
         }
 
         #endregion

--- 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.ActiveVessel.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
@@ -38,6 +38,12 @@
                 return Vector3d.zero;
             }
         }
+
+        public void Reset()
+        {
+            sum = Vector3d.zero;
+            count = 0;
+        }
     }
 
     public class WeightedVectorAverager
@@ -61,6 +67,12 @@
         public double GetTotalWeight() {
             return totalweight;
         }
+
+        public void Reset()
+        {
+            sum = Vector3d.zero;
+            totalweight = 0.0;
+        }
     }
 }
 

--- a/KerbalEngineer/Helpers/ForceAccumulator.cs
+++ b/KerbalEngineer/Helpers/ForceAccumulator.cs
@@ -99,5 +99,12 @@
         {
             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/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -199,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" />

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

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -17,202 +17,175 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using UnityEngine;
-
-#endregion
-
 namespace KerbalEngineer.VesselSimulator
 {
+    using System;
+    using System.Collections.Generic;
+    using System.Text;
+    using Editor;
     using Helpers;
-
-    public class EngineSim
+    using UnityEngine;
+
+    public class EngineSim : Pool<EngineSim>
     {
-        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;
+        public float maxMach;
 
         public double thrust = 0;
-
-        public static double GetEngineThrust(float fuelFlow, double isp, float multiplier)
-        {
-            return fuelFlow * GetExhaustVelocity(isp) * multiplier;
-        }
-
-        public static double GetExhaustVelocity(double isp)
-        {
-            return isp * Units.GRAVITY;
-        }
-
-        public static double GetFlowRate(double thrust, double isp)
-        {
-            return thrust / GetExhaustVelocity(isp);
-        }
 
         // Add thrust vector to account for directional losses
         public Vector3 thrustVec;
-
-        public EngineSim(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, float minFuelFlow, float maxFuelFlow)
+        private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
+
+        public EngineSim Initialise(PartSim theEngine,
+            double atmosphere,
+            float machNumber,
+            float maxFuelFlow,
+            float minFuelFlow,
+            float thrustPercentage,
+            Vector3 vecThrust,
+            FloatCurve atmosphereCurve,
+            bool atmChangeFlow,
+            FloatCurve atmCurve,
+            FloatCurve velCurve,
+            float currentThrottle,
+            bool throttleLocked,
+            List<Propellant> propellants,
+            bool active,
+            float resultingThrust,
+            List<Transform> thrustTransforms)
         {
             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;
-            thrustPercentage = thrustPercentage * 0.01f;
-
-            this.isActive = active;
-            //this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
-            //MonoBehaviour.print("thrust = " + thrust);
-
-            this.thrustVec = vecThrust;
-
-            double flowRate = 0d;
-            if (this.partSim.hasVessel)
-            {
-                this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm);
-                if (this.isp == 0.0)
-                {
-                    MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
-                }
-
-                this.actualThrust = isActive ? requestedThrust : 0.0;
-                this.thrust = GetEngineThrust(maxFuelFlow, isp, thrustPercentage);
-                if (velocityCurve != null)
-                {
-                    this.actualThrust *= velocityCurve.Evaluate((float)velocity);
-                    this.thrust *= velocityCurve.Evaluate((float)velocity);
-                }
+
+            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)
                 {
-                    //MonoBehaviour.print("throttleLocked is true");
-                    flowRate = this.thrust / GetExhaustVelocity(isp);
+                    flowRate = GetFlowRate(thrust, isp);
                 }
                 else
                 {
-                    if (this.partSim.isLanded)
-                    {
-                        //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
-                        flowRate = GetFlowRate(Math.Max(float.Epsilon, this.thrust * FlightInputHandler.state.mainThrottle), isp);
+                    if (currentThrottle > 0.0f && partSim.isLanded == false)
+                    {
+                        flowRate = GetFlowRate(actualThrust, isp);
                     }
                     else
                     {
-                        if (requestedThrust > 0)
-                        {
-                            if (velocityCurve != null)
-                            {
-                                requestedThrust *= velocityCurve.Evaluate((float)velocity);
-                                //MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust);
-                            }
-
-                            //MonoBehaviour.print("requestedThrust > 0");
-                            flowRate = GetFlowRate(requestedThrust, isp);
-                        }
-                        else
-                        {
-                            //MonoBehaviour.print("requestedThrust <= 0");
-                            flowRate = GetFlowRate(thrust, isp);
-                        }
+                        flowRate = GetFlowRate(thrust, isp);
                     }
                 }
             }
             else
             {
-                this.isp = atmosphereCurve.Evaluate((float)atmosphere);
-                if (this.isp == 0d)
-                {
-                    MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
-                }
-
-                thrust = GetEngineThrust(maxFuelFlow, isp, thrustPercentage);
-
-                if (velocityCurve != null)
-                {
-                    this.thrust *= velocityCurve.Evaluate((float)velocity);
-                }
-
+                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)
-            {
-                buffer = new StringBuilder(1024);
-                buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
-            }
-
-            float flowMass = 0f;
-            foreach (Propellant propellant in propellants)
-            {
+            float flowMass = 0.0f;
+
+            for (int i = 0; i < propellants.Count; ++i)
+            {
+                Propellant propellant = propellants[i];
                 flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
-            }
-
-            if (SimManager.logOutput)
-            {
-                buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
-            }
-
-            foreach (Propellant propellant in propellants)
-            {
-                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
-                {
-                    continue;
-                }
 
                 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);
-            }
-
-            if (SimManager.logOutput)
-            {
-                MonoBehaviour.print(buffer);
-            }
-
-            appliedForces = new List<AppliedForce>();
+                resourceConsumptions.Add(propellant.id, consumptionRate);
+            }
+
             double thrustPerThrustTransform = thrust / thrustTransforms.Count;
-            foreach (Transform thrustTransform in thrustTransforms) {
+            for (int i = 0; i < thrustTransforms.Count; ++i)
+            {
+                Transform thrustTransform = thrustTransforms[i];
+
                 Vector3d direction = thrustTransform.forward.normalized;
                 Vector3d position = thrustTransform.position;
                 appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position));
             }
+
+            return this;
         }
 
         public ResourceContainer ResourceConsumptions
         {
-            get { return this.resourceConsumptions; }
+            get
+            {
+                return resourceConsumptions;
+            }
+        }
+
+        public static double GetExhaustVelocity(double isp)
+        {
+            return isp * Units.GRAVITY;
+        }
+
+        public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach)
+        {
+            float flowModifier = 1.0f;
+            if (atmChangeFlow)
+            {
+                flowModifier = (float)(atmDensity / 1.225);
+                if (atmCurve != null)
+                {
+                    flowModifier = atmCurve.Evaluate(flowModifier);
+                }
+            }
+            if (velCurve != null)
+            {
+                flowModifier = flowModifier * velCurve.Evaluate(machNumber);
+                maxMach = velCurve.maxTime;
+            }
+            if (flowModifier < float.Epsilon)
+            {
+                flowModifier = float.Epsilon;
+            }
+            return flowModifier;
+        }
+
+        public static double GetFlowRate(double thrust, double isp)
+        {
+            return thrust / GetExhaustVelocity(isp);
+        }
+
+        public static float GetThrottlePercent(float currentThrottle, float thrustPercentage)
+        {
+            return currentThrottle * GetThrustPercent(thrustPercentage);
+        }
+
+        public static double GetThrust(double flowRate, double isp)
+        {
+            return flowRate * GetExhaustVelocity(isp);
+        }
+
+        public static float GetThrustPercent(float thrustPercentage)
+        {
+            return thrustPercentage * 0.01f;
+        }
+
+        public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
+        {
+            buffer.Append(prefix);
+            buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", thrust, actualThrust, isp);
         }
 
         public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
@@ -222,23 +195,26 @@
             // 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 this.resourceConsumptions.Types)
-            {
+            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
+            {
+                int type = resourceConsumptions.Types[i];
                 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)
+                        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:
-                        foreach (PartSim aPartSim in allParts)
-                        {
+                        for (int j = 0; j < allParts.Count; ++j)
+                        {
+                            PartSim aPartSim = allParts[j];
+
                             if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0)
                             {
                                 if (sourcePartSet == null)
@@ -252,15 +228,19 @@
                         break;
 
                     case ResourceFlowMode.STAGE_PRIORITY_FLOW:
-                        var stagePartSets = new Dictionary<int, HashSet<PartSim>>();
-                        var maxStage = -1;
-
-                        //Logger.Log(type);
-                        foreach (var aPartSim in allParts)
-                        {
-                            if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0) continue;
-
-                            var stage = aPartSim.DecouplerCount();
+                        Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
+                        int maxStage = -1;
+
+                        for (int j = 0; j < allParts.Count; ++j)
+                        {
+                            PartSim aPartSim = allParts[j];
+
+                            if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
+                            {
+                                continue;
+                            }
+
+                            int stage = aPartSim.DecouplerCount();
                             if (stage > maxStage)
                             {
                                 maxStage = stage;
@@ -274,10 +254,10 @@
                             sourcePartSet.Add(aPartSim);
                         }
 
-                        for (var i = 0; i <= maxStage; i++)
+                        for (int j = 0; j <= maxStage; j++)
                         {
                             HashSet<PartSim> stagePartSet;
-                            if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0)
+                            if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
                             {
                                 sourcePartSet = stagePartSet;
                             }
@@ -290,9 +270,9 @@
                         if (SimManager.logOutput)
                         {
                             log = new LogMsg();
-                            log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + this.partSim.name + ":" + this.partSim.partId);
-                        }
-                        sourcePartSet = this.partSim.GetSourceSet(type, allParts, visited, 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);
@@ -300,7 +280,7 @@
                         break;
 
                     default:
-                        MonoBehaviour.print("SetResourceDrains(" + this.partSim.name + ":" + this.partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
+                        MonoBehaviour.print("SetResourceDrains(" + partSim.name + ":" + partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
                         break;
                 }
 
@@ -321,8 +301,10 @@
             }
 
             // If we don't have sources for all the needed resources then return false without setting up any drains
-            foreach (int type in this.resourceConsumptions.Types)
-            {
+            for(int i = 0; i < resourceConsumptions.Types.Count; ++i)
+            {
+                int type = resourceConsumptions.Types[i];
+
                 if (!sourcePartSets.ContainsKey(type))
                 {
                     if (SimManager.logOutput)
@@ -330,17 +312,19 @@
                         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
-            foreach (int type in this.resourceConsumptions.Types)
-            {
+            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
+            {
+                int type = resourceConsumptions.Types[i];
+
                 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)
@@ -355,11 +339,5 @@
 
             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
@@ -34,11 +34,11 @@
 {
     using CompoundParts;
 
-    public class PartSim
+    public class PartSim : Pool<PartSim>
     {
         private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
         public Vector3d centerOfMass;
-        public double baseMass = 0d;
+        public double baseMass;
         public double cost;
         public int decoupledInStage;
         public bool fuelCrossFeed;
@@ -71,8 +71,47 @@
         public String vesselName;
         public VesselType vesselType;
 
-        public PartSim(Part thePart, int id, double atmosphere, LogMsg log)
-        {
+        private static void Reset(PartSim partSim)
+        {
+            partSim.attachNodes.Clear();
+            partSim.fuelTargets.Clear();
+            partSim.resourceDrains.Reset();
+            partSim.resourceFlowStates.Reset();
+            partSim.resources.Reset();
+            partSim.baseMass = 0.0;
+            partSim.startMass = 0.0;
+            partSim.centerOfMass = Vector3d.zero;
+            partSim.cost = 0.0;
+            partSim.decoupledInStage = 0;
+            partSim.fuelCrossFeed = false;
+            partSim.hasModuleEngines = false;
+            partSim.hasModuleEnginesFX = false;
+            partSim.hasMultiModeEngine = false;
+            partSim.hasVessel = false;
+            partSim.initialVesselName = null;
+            partSim.inverseStage = 0;
+            partSim.isDecoupler = false;
+            partSim.isEngine = false;
+            partSim.isFuelLine = false;
+            partSim.isFuelTank = false;
+            partSim.isLanded = false;
+            partSim.isNoPhysics = false;
+            partSim.isSepratron = false;
+            partSim.localCorrectThrust = false;
+            partSim.name = null;
+            partSim.noCrossFeedNodeKey = null;
+            partSim.parent = null;
+            partSim.parentAttach = AttachModes.SRF_ATTACH;
+            partSim.part = null;
+            partSim.partId = 0;
+            partSim.vesselName = null;
+            partSim.vesselType = VesselType.Base;
+        }
+
+        public PartSim Initialise(Part thePart, int id, double atmosphere, LogMsg log)
+        {
+            Reset(this);
+
             this.part = thePart;
             this.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
             this.partId = id;
@@ -97,13 +136,11 @@
             this.cost = this.part.GetCostWet();
 
             // Work out if the part should have no physical significance
-            this.isNoPhysics = this.part.HasModule<LaunchClamp>() ||
-                               this.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
-                               this.part.PhysicsSignificance == 1;
-
-            if (!this.isNoPhysics)
-            {
-                this.baseMass = this.part.mass;
+            this.isNoPhysics = this.part.HasModule<LaunchClamp>();
+
+            if (isNoPhysics == false)
+            {
+                baseMass = part.mass;
             }
 
             if (SimManager.logOutput)
@@ -111,8 +148,10 @@
                 MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass);
             }
 
-            foreach (PartResource resource in this.part.Resources)
-            {
+            for (int i = 0; i < part.Resources.Count; ++i)
+            {
+                PartResource resource = part.Resources[i];
+
                 // Make sure it isn't NaN as this messes up the part mass and hence most of the values
                 // This can happen if a resource capacity is 0 and tweakable
                 if (!Double.IsNaN(resource.amount))
@@ -152,6 +191,8 @@
             {
                 MonoBehaviour.print("Created " + this.name + ". Decoupled in stage " + this.decoupledInStage);
             }
+
+            return this;
         }
 
         public ResourceContainer Resources
@@ -164,7 +205,7 @@
             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)
@@ -185,8 +226,12 @@
                 // The mode of the engine is the engineID of the ModuleEnginesFX that is active
                 string mode = this.part.GetModule<MultiModeEngine>().mode;
 
-                foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
-                {
+                List<ModuleEnginesFX> engines = part.GetModules<ModuleEnginesFX>();
+
+                for (int i = 0; i < engines.Count; ++i)
+                {
+                    ModuleEnginesFX engine = engines[i];
+
                     if (engine.engineID == mode)
                     {
                         if (log != null)
@@ -196,32 +241,35 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = new EngineSim(this,
-                                                            atmosphere,
-                                                            velocity,
-                                                            engine.maxThrust,
-                                                            engine.minThrust,
-                                                            engine.thrustPercentage,
-                                                            engine.resultingThrust,
-                                                            thrustvec,
-                                                            engine.realIsp,
-                                                            engine.atmosphereCurve,
-                                                            engine.useVelocityCurve ? engine.velocityCurve : null,
-                                                            engine.throttleLocked,
-                                                            engine.propellants,
-                                                            engine.isOperational,
-                                                            correctThrust,
-                                                            engine.thrustTransforms, engine.minFuelFlow, engine.maxFuelFlow);
+                        EngineSim engineSim = EngineSim.GetPoolObject().Initialise(this,
+                            atmosphere,
+                            (float)mach,
+                            engine.maxFuelFlow,
+                            engine.minFuelFlow,
+                            engine.thrustPercentage,
+                            thrustvec,
+                            engine.atmosphereCurve,
+                            engine.atmChangeFlow,
+                            engine.useAtmCurve ? engine.atmCurve : null,
+                            engine.useVelCurve ? engine.velCurve : null,
+                            engine.currentThrottle,
+                            engine.throttleLocked || fullThrust,
+                            engine.propellants,
+                            engine.isOperational,
+                            engine.resultingThrust,
+                            engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
                 }
             }
             else
             {
-                if (this.hasModuleEnginesFX)
-                {
-                    foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
-                    {
+                if (this.hasModuleEngines)
+                {
+                    List<ModuleEngines> engines = part.GetModules<ModuleEngines>();
+                    for (int i = 0; i < engines.Count; ++i)
+                    {
+                        ModuleEngines engine = engines[i];
                         if (log != null)
                         {
                             log.buf.AppendLine("Module: " + engine.moduleName);
@@ -229,56 +277,26 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = new EngineSim(this,
-                                                            atmosphere,
-                                                            velocity,
-                                                            engine.maxThrust,
-                                                            engine.minThrust,
-                                                            engine.thrustPercentage,
-                                                            engine.resultingThrust,
-                                                            thrustvec,
-                                                            engine.realIsp,
-                                                            engine.atmosphereCurve,
-                                                            engine.useVelocityCurve ? engine.velocityCurve : null,
-                                                            engine.throttleLocked,
-                                                            engine.propellants,
-                                                            engine.isOperational,
-                                                            correctThrust,
-                                                            engine.thrustTransforms, engine.minFuelFlow, engine.maxFuelFlow);
+                        EngineSim engineSim = EngineSim.GetPoolObject().Initialise(this,
+                            atmosphere,
+                            (float)mach,
+                            engine.maxFuelFlow,
+                            engine.minFuelFlow,
+                            engine.thrustPercentage,
+                            thrustvec,
+                            engine.atmosphereCurve,
+                            engine.atmChangeFlow,
+                            engine.useAtmCurve ? engine.atmCurve : null,
+                            engine.useVelCurve ? engine.velCurve : null,
+                            engine.currentThrottle,
+                            engine.throttleLocked || fullThrust,
+                            engine.propellants,
+                            engine.isOperational,
+                            engine.resultingThrust,
+                            engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
                 }
-
-                if (this.hasModuleEngines)
-                {
-                    foreach (ModuleEngines engine in this.part.GetModules<ModuleEngines>())
-                    {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Module: " + engine.moduleName);
-                        }
-
-                        Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
-
-                        EngineSim engineSim = new EngineSim(this,
-                                                            atmosphere,
-                                                            velocity,
-                                                            engine.maxThrust,
-                                                            engine.minThrust,
-                                                            engine.thrustPercentage,
-                                                            engine.resultingThrust,
-                                                            thrustvec,
-                                                            engine.realIsp,
-                                                            engine.atmosphereCurve,
-                                                            engine.useVelocityCurve ? engine.velocityCurve : null,
-                                                            engine.throttleLocked,
-                                                            engine.propellants,
-                                                            engine.isOperational,
-                                                            correctThrust,
-                                                            engine.thrustTransforms, engine.minFuelFlow, engine.maxFuelFlow);
-                        allEngines.Add(engineSim);
-                    }
-                }
             }
 
             if (log != null)
@@ -295,8 +313,10 @@
             }
 
             Vector3 thrustvec = Vector3.zero;
-            foreach (Transform trans in thrustTransforms)
-            {
+            for (int i = 0; i < thrustTransforms.Count; ++i)
+            {
+                Transform trans = thrustTransforms[i];
+
                 if (log != null)
                 {
                     log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
@@ -349,9 +369,12 @@
                 log.buf.AppendLine("SetupAttachNodes for " + this.name + ":" + this.partId + "");
             }
 
-            this.attachNodes.Clear();
-            foreach (AttachNode attachNode in this.part.attachNodes)
-            {
+            attachNodes.Clear();
+
+            for (int i = 0; i < part.attachNodes.Count; ++i)
+            {
+                AttachNode attachNode = part.attachNodes[i];
+
                 if (log != null)
                 {
                     log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
@@ -367,7 +390,7 @@
                             log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
                         }
 
-                        this.attachNodes.Add(new AttachNodeSim(attachedSim, attachNode.id, attachNode.nodeType));
+                        attachNodes.Add(AttachNodeSim.GetPoolObject().Initialise(attachedSim, attachNode.id, attachNode.nodeType));
                     }
                     else
                     {
@@ -379,8 +402,10 @@
                 }
             }
 
-            foreach (Part p in this.part.fuelLookupTargets)
-            {
+            for (int i = 0; i < part.fuelLookupTargets.Count; ++i)
+            {
+                Part p = part.fuelLookupTargets[i];
+
                 if (p != null)
                 {
                     PartSim targetSim;
@@ -498,9 +523,10 @@
             // Rule 2: Part performs scan on start of every fuel pipe ending in it. This scan is done in order in which pipes were installed.
             // Then it makes an union of fuel tank sets each pipe scan returned. If the resulting list is not empty, it is returned as result.
             //MonoBehaviour.print("foreach fuel line");
-
-            foreach (PartSim partSim in this.fuelTargets)
-            {
+            for (int i = 0; i < fuelTargets.Count; ++i)
+            {
+                PartSim partSim = fuelTargets[i];
+
                 if (visited.Contains(partSim))
                 {
                     //if (log != null)
@@ -540,8 +566,10 @@
             if (this.fuelCrossFeed)
             {
                 //MonoBehaviour.print("foreach attach node");
-                foreach (AttachNodeSim attachSim in this.attachNodes)
-                {
+                for (int i = 0; i < attachNodes.Count; ++i)
+                {
+                    AttachNodeSim attachSim = attachNodes[i];
+
                     if (attachSim.attachedPartSim != null)
                     {
                         if (attachSim.nodeType == AttachNode.NodeType.Stack)
@@ -637,8 +665,10 @@
         public void RemoveAttachedParts(HashSet<PartSim> partSims)
         {
             // Loop through the attached parts
-            foreach (AttachNodeSim attachSim in this.attachNodes)
-            {
+            for (int i = 0; i < attachNodes.Count; ++i)
+            {
+                AttachNodeSim attachSim = attachNodes[i];
+
                 // If the part is in the set then "remove" it by clearing the PartSim reference
                 if (partSims.Contains(attachSim.attachedPartSim))
                 {
@@ -650,8 +680,10 @@
         public void DrainResources(double time)
         {
             //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
-            foreach (int type in this.resourceDrains.Types)
-            {
+            for (int i = 0; i < resourceDrains.Types.Count; ++i)
+            {
+                int type = resourceDrains.Types[i];
+
                 //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
                 this.resources.Add(type, -time * this.resourceDrains[type]);
                 //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
@@ -663,8 +695,10 @@
             //MonoBehaviour.print("TimeToDrainResource(" + name + ":" + partId + ")");
             double time = double.MaxValue;
 
-            foreach (int type in this.resourceDrains.Types)
-            {
+            for (int i = 0; i < resourceDrains.Types.Count; ++i)
+            {
+                int type = resourceDrains.Types[i];
+
                 if (this.resourceDrains[type] > 0)
                 {
                     time = Math.Min(time, this.resources[type] / this.resourceDrains[type]);
@@ -715,9 +749,9 @@
         {
             double mass = this.baseMass;
 
-            foreach (int type in this.resources.Types)
-            {
-                mass += this.resources.GetResourceMass(type);
+            for (int i = 0; i < resources.Types.Count; ++i)
+            {
+                mass += this.resources.GetResourceMass(resources.Types[i]);
             }
 
             return mass;

--- a/KerbalEngineer/VesselSimulator/ResourceContainer.cs
+++ b/KerbalEngineer/VesselSimulator/ResourceContainer.cs
@@ -134,7 +134,7 @@
 
         public void Reset()
         {
-            this.resources = new Hashtable();
+            this.resources.Clear();
         }
 
         public void Debug()

--- 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)
@@ -297,8 +302,7 @@
             }
             catch (Exception e)
             {
-                MonoBehaviour.print("Exception in RunSimulation: " + e);
-                Logger.Exception(e);
+                Logger.Exception(e, "SimManager.RunSimulation()");
                 Stages = null;
                 LastStage = null;
                 failMessage = e.ToString();
@@ -350,15 +354,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
                 {
@@ -372,8 +382,7 @@
             }
             catch (Exception e)
             {
-                MonoBehaviour.print("Exception in StartSimulation: " + e);
-                Logger.Exception(e);
+                Logger.Exception(e, "SimManager.StartSimulation()");
                 failMessage = e.ToString();
                 lock (locker)
                 {

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -32,27 +32,30 @@
 {
     using CompoundParts;
     using Extensions;
+    using Helpers;
 
     public class Simulation
     {
-        private const double STD_GRAVITY = 9.82;
         private const double SECONDS_PER_DAY = 86400;
         private readonly Stopwatch _timer = new Stopwatch();
-        private List<EngineSim> activeEngines;
-        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;
-        private HashSet<PartSim> drainingParts;
-        private HashSet<int> drainingResources;
+        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 double gravity;
 
         private int lastStage;
-        private List<Part> partList;
+        private List<Part> partList = new List<Part>();
         private double simpleTotalThrust;
         private double stageStartMass;
         private Vector3d stageStartCom;
@@ -63,13 +66,15 @@
         private double totalStageFlowRate;
         private double totalStageIspFlowRate;
         private double totalStageThrust;
-        private ForceAccumulator totalStageThrustForce;
+        private ForceAccumulator totalStageThrustForce = new ForceAccumulator();
         private Vector3 vecActualThrust;
         private Vector3 vecStageDeltaV;
         private Vector3 vecThrust;
-        private double velocity;
+        private double mach;
+        private float maxMach;
         public String vesselName;
         public VesselType vesselType;
+        private WeightedVectorAverager vectorAverager = new WeightedVectorAverager();
 
         public Simulation()
         {
@@ -85,9 +90,8 @@
             {
                 double mass = 0d;
 
-                foreach (PartSim partSim in this.allParts)
-                {
-                    mass += partSim.GetMass();
+                for (int i = 0; i < allParts.Count; ++i) { 
+                    mass += allParts[i].GetMass();
                 }
 
                 return mass;
@@ -98,14 +102,15 @@
         {
             get
             {
-                WeightedVectorAverager averager = new WeightedVectorAverager();
-
-                foreach (PartSim partSim in this.allParts)
-                {
-                    averager.Add(partSim.centerOfMass, partSim.GetMass());
-                }
-
-                return averager.Get();
+                vectorAverager.Reset();
+
+                for (int i = 0; i < allParts.Count; ++i)
+                {
+                    PartSim partSim = allParts[i];
+                    vectorAverager.Add(partSim.centerOfMass, partSim.GetMass());
+                }
+
+                return vectorAverager.Get();
             }
         }
 
@@ -113,7 +118,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)
@@ -128,20 +133,24 @@
             this.partList = parts;
             this.gravity = theGravity;
             this.atmosphere = theAtmosphere;
-            this.velocity = theVelocity;
+            this.mach = theMach;
             this.lastStage = Staging.lastStage;
             //MonoBehaviour.print("lastStage = " + lastStage);
 
-            // Create the lists for our simulation parts
-            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>();
+            // Clear the lists for our simulation parts
+            allParts.Clear();
+            allFuelLines.Clear();
+            drainingParts.Clear();
+            allEngines.Clear();
+            activeEngines.Clear();
+            drainingResources.Clear();
+
+            PartSim.ReleaseAll();
+            EngineSim.ReleaseAll();
+            AttachNodeSim.ReleaseAll();
 
             // A dictionary for fast lookup of Part->PartSim during the preparation phase
-            Dictionary<Part, PartSim> partSimLookup = new Dictionary<Part, PartSim>();
+            partSimLookup.Clear();
 
             if (this.partList.Count > 0 && this.partList[0].vessel != null)
             {
@@ -151,8 +160,10 @@
 
             // First we create a PartSim for each Part (giving each a unique id)
             int partId = 1;
-            foreach (Part part in this.partList)
-            {
+            for (int i = 0; i < partList.Count; ++i)
+            {
+                Part part = partList[i];
+
                 // If the part is already in the lookup dictionary then log it and skip to the next part
                 if (partSimLookup.ContainsKey(part))
                 {
@@ -164,7 +175,7 @@
                 }
 
                 // Create the PartSim
-                PartSim partSim = new PartSim(part, partId, this.atmosphere, log);
+                PartSim partSim = PartSim.GetPoolObject().Initialise(part, partId, this.atmosphere, log);
 
                 // Add it to the Part lookup dictionary and the necessary lists
                 partSimLookup.Add(part, partSim);
@@ -175,10 +186,15 @@
                 }
                 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();
@@ -193,8 +209,10 @@
             // Then, in the VAB/SPH, we add the parent of each fuel line to the fuelTargets list of their targets
             if (HighLogic.LoadedSceneIsEditor)
             {
-                foreach (PartSim partSim in this.allFuelLines)
-                {
+                for (int i = 0; i < allFuelLines.Count; ++i)
+                {
+                    PartSim partSim = allFuelLines[i];
+
                     CModuleFuelLine fuelLine = partSim.part.GetModule<CModuleFuelLine>();
                     if (fuelLine.target != null)
                     {
@@ -227,8 +245,10 @@
             }
 
             //MonoBehaviour.print("SetupAttachNodes and count stages");
-            foreach (PartSim partSim in this.allParts)
-            {
+            for (int i = 0; i < allParts.Count; ++i)
+            {
+                PartSim partSim = allParts[i];
+
                 partSim.SetupAttachNodes(partSimLookup, log);
                 if (partSim.decoupledInStage >= this.lastStage)
                 {
@@ -238,9 +258,9 @@
 
             // And finally release the Part references from all the PartSims
             //MonoBehaviour.print("ReleaseParts");
-            foreach (PartSim partSim in this.allParts)
-            {
-                partSim.ReleasePart();
+            for (int i = 0; i < allParts.Count; ++i)
+            { 
+                allParts[i].ReleasePart();
             }
 
             // And dereference the core's part list
@@ -285,8 +305,10 @@
             // currently active engines then generate an extra stage
             // Loop through all the engines
             bool anyActive = false;
-            foreach (EngineSim engine in this.allEngines)
-            {
+            for (int i = 0; i < allEngines.Count; ++i)
+            {
+                EngineSim engine = allEngines[i];
+
                 if (log != null)
                 {
                     log.buf.AppendLine("Testing engine mod of " + engine.partSim.name + ":" + engine.partSim.partId);
@@ -341,7 +363,7 @@
             }
 
             // Create a list of lists of PartSims that prevent decoupling
-            List<List<PartSim>> dontStagePartsLists = this.BuildDontStageLists(log);
+            BuildDontStageLists(log);
 
             if (log != null)
             {
@@ -414,8 +436,10 @@
 
                 // Calculate the cost and mass of this stage and add all engines and tanks that are decoupled
                 // in the next stage to the dontStageParts list
-                foreach (PartSim partSim in this.allParts)
-                {
+                for (int i = 0; i < allParts.Count; ++i)
+                {
+                    PartSim partSim = allParts[i];
+
                     if (partSim.decoupledInStage == this.currentStage - 1)
                     {
                         stage.cost += partSim.cost;
@@ -493,7 +517,7 @@
                     // If we have drained anything and the masses make sense then add this step's deltaV to the stage total
                     if (resourceDrainTime > 0d && this.stepStartMass > this.stepEndMass && this.stepStartMass > 0d && this.stepEndMass > 0d)
                     {
-                        this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * STD_GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
+                        this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * Units.GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
                     }
 
                     // Update the active engines and resource drains for the next step
@@ -537,7 +561,7 @@
                 // Note: If the mass doesn't change then this is a divide by zero
                 if (this.stageStartMass != this.stepStartMass)
                 {
-                    stage.isp = stage.deltaV / (STD_GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
+                    stage.isp = stage.deltaV / (Units.GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
                 }
                 else
                 {
@@ -548,6 +572,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
@@ -610,20 +635,30 @@
             return stages;
         }
 
-        private List<List<PartSim>> BuildDontStageLists(LogMsg log)
+        private void BuildDontStageLists(LogMsg log)
         {
             if (log != null)
             {
                 log.buf.AppendLine("Creating list with capacity of " + (this.currentStage + 1));
             }
-            List<List<PartSim>> lists = new List<List<PartSim>>();
+
+            dontStagePartsLists.Clear();
             for (int i = 0; i <= this.currentStage; i++)
             {
-                lists.Add(new List<PartSim>());
-            }
-
-            foreach (PartSim partSim in this.allParts)
-            {
+                if (i < dontStagePartsLists.Count)
+                {
+                    dontStagePartsLists[i].Clear();
+                }
+                else
+                {
+                    dontStagePartsLists.Add(new List<PartSim>());
+                }
+            }
+
+            for (int i = 0; i < allParts.Count; ++i)
+            {
+                PartSim partSim = allParts[i];
+
                 if (partSim.isEngine || !partSim.Resources.Empty)
                 {
                     if (log != null)
@@ -640,28 +675,28 @@
                     }
                     else
                     {
-                        lists[partSim.decoupledInStage + 1].Add(partSim);
+                        dontStagePartsLists[partSim.decoupledInStage + 1].Add(partSim);
                     }
                 }
             }
 
             for (int i = 1; i <= this.lastStage; i++)
             {
-                if (lists[i].Count == 0)
-                {
-                    lists[i] = lists[i - 1];
-                }
-            }
-
-            return lists;
+                if (dontStagePartsLists[i].Count == 0)
+                {
+                    dontStagePartsLists[i] = dontStagePartsLists[i - 1];
+                }
+            }
         }
 
         // This function simply rebuilds the active engines by testing the isActive flag of all the engines
         private void UpdateActiveEngines()
         {
             this.activeEngines.Clear();
-            foreach (EngineSim engine in this.allEngines)
-            {
+            for (int i = 0; i < allEngines.Count; ++i)
+            {
+                EngineSim engine = allEngines[i];
+
                 if (engine.isActive)
                 {
                     this.activeEngines.Add(engine);
@@ -679,12 +714,14 @@
             this.totalStageActualThrust = 0d;
             this.totalStageFlowRate = 0d;
             this.totalStageIspFlowRate = 0d;
-            this.totalStageThrustForce = new ForceAccumulator();
+            this.totalStageThrustForce.Reset();
 
             // Loop through all the active engines totalling the thrust, actual thrust and mass flow rates
             // The thrust is totalled as vectors
-            foreach (EngineSim engine in this.activeEngines)
-            {
+            for (int i = 0; i < activeEngines.Count; ++i)
+            {
+                EngineSim engine = activeEngines[i];
+
                 this.simpleTotalThrust += engine.thrust;
                 this.vecThrust += ((float)engine.thrust * engine.thrustVec);
                 this.vecActualThrust += ((float)engine.actualThrust * engine.thrustVec);
@@ -692,8 +729,9 @@
                 this.totalStageFlowRate += engine.ResourceConsumptions.Mass;
                 this.totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp;
 
-                foreach (AppliedForce f in engine.appliedForces) {
-                    this.totalStageThrustForce.AddForce(f);
+                for (int j = 0; j < engine.appliedForces.Count; ++j)
+                {
+                    this.totalStageThrustForce.AddForce(engine.appliedForces[j]);
                 }
             }
 
@@ -733,15 +771,17 @@
             this.drainingParts.Clear();
 
             // Loop through all the active engine modules
-            foreach (EngineSim engine in this.activeEngines)
-            {
+            for (int i = 0; i < activeEngines.Count; ++i)
+            {
+                EngineSim engine = activeEngines[i];
+
                 // Set the resource drains for this engine
                 if (engine.SetResourceDrains(this.allParts, this.allFuelLines, this.drainingParts))
                 {
                     // If it is active then add the consumed resource types to the set
-                    foreach (int type in engine.ResourceConsumptions.Types)
-                    {
-                        this.drainingResources.Add(type);
+                    for (int j = 0; j < engine.ResourceConsumptions.Types.Count; ++j)
+                    { 
+                        drainingResources.Add(engine.ResourceConsumptions.Types[j]);
                     }
                 }
             }
@@ -775,8 +815,10 @@
 
             if (this.activeEngines.Count > 0)
             {
-                foreach (PartSim partSim in this.dontStageParts)
-                {
+                for (int i = 0; i < dontStageParts.Count; ++i)
+                {
+                    PartSim partSim = dontStageParts[i];
+
                     if (SimManager.logOutput)
                     {
                         partSim.DumpPartToBuffer(buffer, "Testing: ");
@@ -795,8 +837,10 @@
 
                     if (partSim.isEngine)
                     {
-                        foreach (EngineSim engine in this.activeEngines)
-                        {
+                        for (int j = 0; j < activeEngines.Count; ++j)
+                        {
+                            EngineSim engine = activeEngines[j];
+
                             if (engine.partSim == partSim)
                             {
                                 if (SimManager.logOutput)
@@ -834,9 +878,11 @@
         private void ActivateStage()
         {
             // Build a set of all the parts that will be decoupled
-            HashSet<PartSim> decoupledParts = new HashSet<PartSim>();
-            foreach (PartSim partSim in this.allParts)
-            {
+            decoupledParts.Clear();
+            for (int i = 0; i < allParts.Count; ++i)
+            {
+                PartSim partSim = allParts[i];
+
                 if (partSim.decoupledInStage >= this.currentStage)
                 {
                     decoupledParts.Add(partSim);
@@ -866,15 +912,15 @@
             }
 
             // Loop through all the (remaining) parts
-            foreach (PartSim partSim in this.allParts)
-            {
+            for (int i = 0; i < allParts.Count; ++i) { 
                 // Ask the part to remove all the parts that are decoupled
-                partSim.RemoveAttachedParts(decoupledParts);
+                allParts[i].RemoveAttachedParts(decoupledParts);
             }
 
             // Now we loop through all the engines and activate those that are ignited in this stage
-            foreach (EngineSim engine in this.allEngines)
-            {
+            for (int i = 0; i < allEngines.Count; ++i)
+            {
+                EngineSim engine = allEngines[i];
                 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
 	}
 }