Added calls to UpdateModSettings in relevant places
Added calls to UpdateModSettings in relevant places

--- a/Documents/CHANGES.txt
+++ b/Documents/CHANGES.txt
@@ -1,3 +1,63 @@
+1.0.14.1, 28-12-2014
+    Fixed: Missing texture on the ER-7500 model.
+    
+1.0.14.0, 28-12-2014
+    Added: Career mode that limits the Flight Engineer by:
+        - Requiring an Engineer Kerbal of any level, or placement of an Engineer Chip or ER-7500 part.
+        - Tracking station level 3 enables Flight Engineer everywhere.
+
+    Added: New readouts to the orbital category:
+        - Mean Anomaly at Epoc
+
+    Added: New readouts to the miscellaneous category:
+        - System Time
+
+    Added: Editor Overlay Tab's X position is now changable in the BuildOverlay.xml settings file.
+    Changed: Editor Overlay Tabs start position moved over as to not overlap the parts menu.
+    Fixed: Bug where STAGE_PRIORITY_FLOW resources would not be corrently disabled/enabled.
+    Fixed: Issue with the formatting large Mass and Cost values.
+    Fixed: Error when loading the Engineer7500 part model.
+
+1.0.13.1, 16-12-2014
+    Fixed: Issue with manoeuvre node readouts and low tier tracking station.
+
+1.0.13.0, 16-12-2014
+    Updated for KSP version 0.90
+
+    Added: New readouts to the vessel category:
+        - Heading Rate
+        - Pitch Rate
+        - Roll Rate
+
+    Changed: Simulation to look for fuel lines that use CModuleFuelLine module.
+    Fixed: Editor Overlay now loads the saved visibility value properly.
+    Fixed: Altitude (Terrain) will no longer give a reading below sea level.
+    Fixed: Suicide burn now uses radar altitude that clamps to sea level.
+
+1.0.12.0, 01-12-2014
+    Added: Setting in Build Engineer to enable/disable vectored thrust calculations.
+    Added: Thrust torque field in Build Engineer (courtesy of mic_e).
+    Added: New readouts to the vessel category:
+        - Thrust Offset Angle (courtesy of mic_e)
+        - Thrust Torque (courtesy of mic_e)
+        - Part Count:  stage/total
+        - Heading
+        - Pitch
+        - Roll
+
+    Added: New readouts to the surface category:
+        - Situation
+
+    Added: New readouts to the miscellaneous category:
+        - Vectored Thrust Toggle
+
+    Fixed: The category selection within the section editors now do not always reset back to 'Orbital'.
+    Fixed: Issue where the vessel simulation can sometimes permanently freeze.
+    Fixed: Issue where the vessel simulation would not show updates when the delay was set lower than the frame rate.
+
+1.0.11.3, 11-11-2014
+    Changed: Gravity measurements for Isp to 9.82.
+
 1.0.11.2, 10-11-2014
     Changed: Gravity measurements for Isp calculations from 9.81 to 9.8066 for accuracy.
     Changed: Manoeuvre node burn times are now more accurate.

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -17,24 +17,22 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-using System.Linq;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight;
-using KerbalEngineer.Helpers;
-using KerbalEngineer.Settings;
-using KerbalEngineer.UIControls;
-using KerbalEngineer.VesselSimulator;
-
-using UnityEngine;
-
-#endregion
-
 namespace KerbalEngineer.Editor
 {
+    #region Using Directives
+
+    using System;
+    using System.Linq;
+    using Extensions;
+    using Flight;
+    using Helpers;
+    using Settings;
+    using UIControls;
+    using UnityEngine;
+    using VesselSimulator;
+
+    #endregion
+
     [KSPAddon(KSPAddon.Startup.EditorAny, false)]
     public class BuildAdvanced : MonoBehaviour
     {
@@ -124,7 +122,7 @@
 
         #endregion
 
-        #region Methods: protected
+        #region Methods
 
         protected void Awake()
         {
@@ -134,6 +132,10 @@
                 this.bodiesList = this.gameObject.AddComponent<DropDown>();
                 this.bodiesList.DrawCallback = this.DrawBodiesList;
                 this.Load();
+
+                SimManager.UpdateModSettings();
+                SimManager.OnReady -= this.GetStageInfo;
+                SimManager.OnReady += this.GetStageInfo;
             }
             catch (Exception ex)
             {
@@ -171,17 +173,10 @@
         {
             try
             {
-                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
                 {
                     return;
                 }
-
-                if (SimManager.ResultsReady())
-                {
-                    this.stages = SimManager.Stages;
-                }
-
-                SimManager.RequestSimulation();
 
                 if (this.stages == null)
                 {
@@ -269,6 +264,8 @@
                 }
 
                 SimManager.Velocity = this.atmosphericVelocity;
+
+                SimManager.RequestSimulation();
                 SimManager.TryStartSimulation();
             }
             catch (Exception ex)
@@ -276,10 +273,6 @@
                 Logger.Exception(ex, "BuildAdvanced->Update");
             }
         }
-
-        #endregion
-
-        #region Methods: private
 
         /// <summary>
         ///     Checks whether the editor should be locked to stop click-through.
@@ -383,7 +376,7 @@
             {
                 if (this.showAllStages || stage.deltaV > 0)
                 {
-                    GUILayout.Label(Units.Concat(stage.cost, stage.totalCost), this.infoStyle);
+                    GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -466,6 +459,11 @@
             GUILayout.Label("Compact mode collapses to the:", this.settingStyle);
             this.compactCollapseRight = !GUILayout.Toggle(!this.compactCollapseRight, "LEFT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             this.compactCollapseRight = GUILayout.Toggle(this.compactCollapseRight, "RIGHT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            GUILayout.EndHorizontal();
+
+            GUILayout.BeginHorizontal();
+            GUILayout.Label("Simulate using vectored thrust values:");
+            SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
@@ -477,8 +475,14 @@
 
             GUILayout.BeginHorizontal();
             GUILayout.Label("Flight Engineer activation mode:", this.settingStyle);
-            FlightEngineerPartless.IsPartless = GUILayout.Toggle(FlightEngineerPartless.IsPartless, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            FlightEngineerPartless.IsPartless = !GUILayout.Toggle(!FlightEngineerPartless.IsPartless, "MODULE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            GUILayout.EndHorizontal();
+
+            GUILayout.BeginHorizontal();
+            GUILayout.Label("Flight Engineer Career Limitations:", this.settingStyle);
+            FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
@@ -493,9 +497,9 @@
             }
             GUILayout.EndHorizontal();
 
-            GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime + "ms", this.settingStyle);
+            GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.Milliseconds + "ms", this.settingStyle);
             GUI.skin = HighLogic.Skin;
-            SimManager.minSimTime = (long)GUILayout.HorizontalSlider(SimManager.minSimTime, 0, 2000.0f);
+            SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 2000.0f));
             GUI.skin = null;
         }
 
@@ -528,6 +532,23 @@
                 if (this.showAllStages || stage.deltaV > 0)
                 {
                     GUILayout.Label(stage.thrust.ToForce(), this.infoStyle);
+                }
+            }
+            GUILayout.EndVertical();
+        }
+
+        /// <summary>
+        ///     Draws the torque column.
+        /// </summary>
+        private void DrawTorque()
+        {
+            GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
+            GUILayout.Label("TORQUE", this.titleStyle);
+            foreach (var stage in this.stages)
+            {
+                if (this.showAllStages || stage.deltaV > 0)
+                {
+                    GUILayout.Label(stage.maxThrustTorque.ToTorque(), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();
@@ -564,6 +585,11 @@
                 BuildOverlayPartInfo.Hidden = false;
                 this.isEditorLocked = false;
             }
+        }
+
+        private void GetStageInfo()
+        {
+            this.stages = SimManager.Stages;
         }
 
         /// <summary>
@@ -738,6 +764,7 @@
                     this.DrawMass();
                     this.DrawIsp();
                     this.DrawThrust();
+                    this.DrawTorque();
                     this.DrawTwr();
                     this.DrawDeltaV();
                     this.DrawBurnTime();

--- a/KerbalEngineer/Editor/BuildOverlay.cs
+++ b/KerbalEngineer/Editor/BuildOverlay.cs
@@ -19,17 +19,21 @@
 
 #region Using Directives
 
-using System;
-
-using KerbalEngineer.Helpers;
-using KerbalEngineer.Settings;
-
-using UnityEngine;
+
 
 #endregion
 
 namespace KerbalEngineer.Editor
 {
+    #region Using Directives
+
+    using System;
+    using Helpers;
+    using Settings;
+    using UnityEngine;
+
+    #endregion
+
     [KSPAddon(KSPAddon.Startup.EditorAny, false)]
     public class BuildOverlay : MonoBehaviour
     {
@@ -191,16 +195,17 @@
 
         #endregion
 
-        #region Methods: public
+        #region Methods
 
         public static void Load()
         {
             var handler = SettingHandler.Load("BuildOverlay.xml");
-            handler.GetSet("visible", Visible);
+            Visible = handler.GetSet("visible", Visible);
             BuildOverlayPartInfo.NamesOnly = handler.GetSet("namesOnly", BuildOverlayPartInfo.NamesOnly);
             BuildOverlayPartInfo.ClickToOpen = handler.GetSet("clickToOpen", BuildOverlayPartInfo.ClickToOpen);
             buildOverlayVessel.Open = handler.GetSet("vesselOpen", buildOverlayVessel.Open);
             buildOverlayResources.Open = handler.GetSet("resourcesOpen", buildOverlayResources.Open);
+            buildOverlayVessel.WindowX = handler.GetSet("vesselWindowX", buildOverlayVessel.WindowX);
             handler.Save("BuildOverlay.xml");
         }
 
@@ -212,12 +217,9 @@
             handler.Set("clickToOpen", BuildOverlayPartInfo.ClickToOpen);
             handler.Set("vesselOpen", buildOverlayVessel.Open);
             handler.Set("resourcesOpen", buildOverlayResources.Open);
+            handler.Set("vesselWindowX", buildOverlayVessel.WindowX);
             handler.Save("BuildOverlay.xml");
         }
-
-        #endregion
-
-        #region Methods: protected
 
         protected void Awake()
         {

--- a/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
+++ b/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
@@ -97,7 +97,7 @@
         {
             try
             {
-                if (!Visible || Hidden || EditorLogic.startPod == null || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+                if (!Visible || Hidden || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
                 {
                     return;
                 }
@@ -195,7 +195,7 @@
 
         private void SetCostInfo()
         {
-            this.infoItems.Add(new PartInfoItem("Cost", Units.Concat(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet())));
+            this.infoItems.Add(new PartInfoItem("Cost", Units.ConcatF(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet())));
         }
 
         private void SetDecouplerInfo()
@@ -222,7 +222,7 @@
 
             var engine = this.selectedPart.GetProtoModuleEngine();
             this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust)));
-            this.infoItems.Add(new PartInfoItem("Isp", Units.Concat(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
+            this.infoItems.Add(new PartInfoItem("Isp", Units.ConcatF(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
             if (engine.Propellants.Count > 0)
             {
                 this.infoItems.Add(new PartInfoItem("Propellants"));
@@ -291,7 +291,7 @@
             }
 
             var parachute = this.selectedPart.GetModule<ModuleParachute>();
-            this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.Concat(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
+            this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.ConcatF(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
             this.infoItems.Add(new PartInfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance()));
             this.infoItems.Add(new PartInfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2")));
         }
@@ -305,7 +305,7 @@
 
             var rcs = this.selectedPart.GetModule<ModuleRCS>();
             this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce()));
-            this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.Concat(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
+            this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.ConcatF(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
         }
 
         private void SetReactionWheelInfo()
@@ -317,9 +317,9 @@
 
             var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>();
             this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque"));
-            this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToForce()));
-            this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToForce()));
-            this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToForce()));
+            this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToTorque()));
+            this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToTorque()));
+            this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToTorque()));
             foreach (var resource in reactionWheel.inputResources)
             {
                 this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));

--- a/KerbalEngineer/Editor/BuildOverlayResources.cs
+++ b/KerbalEngineer/Editor/BuildOverlayResources.cs
@@ -70,7 +70,7 @@
         {
             try
             {
-                if (!Visible || this.resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+                if (!Visible || this.resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
                 {
                     return;
                 }

--- a/KerbalEngineer/Editor/BuildOverlayVessel.cs
+++ b/KerbalEngineer/Editor/BuildOverlayVessel.cs
@@ -19,18 +19,20 @@
 
 #region Using Directives
 
-using System;
-using System.Collections.Generic;
-
-using KerbalEngineer.Helpers;
-using KerbalEngineer.VesselSimulator;
-
-using UnityEngine;
-
 #endregion
 
 namespace KerbalEngineer.Editor
 {
+    #region Using Directives
+
+    using System;
+    using System.Collections.Generic;
+    using Helpers;
+    using UnityEngine;
+    using VesselSimulator;
+
+    #endregion
+
     public class BuildOverlayVessel : MonoBehaviour
     {
         #region Constants
@@ -51,7 +53,7 @@
         private GUIContent tabContent;
         private Rect tabPosition;
         private Vector2 tabSize;
-        private Rect windowPosition = new Rect(300.0f, 0.0f, Width, 0.0f);
+        private Rect windowPosition = new Rect(330.0f, 0.0f, Width, 0.0f);
 
         #endregion
 
@@ -74,15 +76,34 @@
             get { return this.windowPosition; }
         }
 
-        #endregion
-
-        #region Methods: protected
+        public float WindowX
+        {
+            get { return this.windowPosition.x; }
+            set { this.windowPosition.x = value; }
+        }
+
+        #endregion
+
+        #region Methods
+
+        protected void Awake()
+        {
+            try
+            {
+                SimManager.OnReady -= this.GetStageInfo;
+                SimManager.OnReady += this.GetStageInfo;
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
 
         protected void OnGUI()
         {
             try
             {
-                if (!Visible || EditorLogic.startPod == null || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+                if (!Visible || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
                 {
                     return;
                 }
@@ -116,7 +137,7 @@
         {
             try
             {
-                if (!Visible || EditorLogic.startPod == null)
+                if (!Visible || EditorLogic.RootPart == null)
                 {
                     return;
                 }
@@ -134,9 +155,10 @@
             }
         }
 
-        #endregion
-
-        #region Methods: private
+        private void GetStageInfo()
+        {
+            this.lastStage = SimManager.LastStage;
+        }
 
         private void SetSlidePosition()
         {
@@ -175,11 +197,6 @@
 
             SimManager.RequestSimulation();
             SimManager.TryStartSimulation();
-
-            if (SimManager.ResultsReady())
-            {
-                this.lastStage = SimManager.LastStage;
-            }
 
             if (this.lastStage != null)
             {

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

--- a/KerbalEngineer/Extensions/DoubleExtensions.cs
+++ b/KerbalEngineer/Extensions/DoubleExtensions.cs
@@ -49,6 +49,11 @@
             return Units.ToDistance(value);
         }
 
+        public static string ToTorque(this double value)
+        {
+            return Units.ToTorque(value);
+        }
+
         public static string ToForce(this double value)
         {
             return Units.ToForce(value);

--- a/KerbalEngineer/Extensions/FloatExtensions.cs
+++ b/KerbalEngineer/Extensions/FloatExtensions.cs
@@ -49,6 +49,11 @@
             return Units.ToForce(value);
         }
 
+        public static string ToTorque(this float value)
+        {
+            return Units.ToTorque(value);
+        }
+
         public static string ToMass(this float value)
         {
             return Units.ToMass(value);

--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -27,6 +27,8 @@
 
 namespace KerbalEngineer.Extensions
 {
+    using CompoundParts;
+
     public static class PartExtensions
     {
         #region Methods: public
@@ -69,7 +71,7 @@
         /// </summary>
         public static double GetCostDry(this Part part)
         {
-            return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts();
+            return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts(0.0f);
         }
 
         /// <summary>
@@ -77,7 +79,7 @@
         /// </summary>
         public static double GetCostMax(this Part part)
         {
-            return part.partInfo.cost + part.GetModuleCosts();
+            return part.partInfo.cost + part.GetModuleCosts(0.0f);
         }
 
         /// <summary>
@@ -85,7 +87,7 @@
         /// </summary>
         public static double GetCostWet(this Part part)
         {
-            return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts();
+            return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts(0.0f);
         }
 
         /// <summary>
@@ -387,7 +389,7 @@
         /// </summary>
         public static bool IsFuelLine(this Part part)
         {
-            return (part is FuelLine);
+            return (HasModule<CModuleFuelLine>(part));
         }
 
         /// <summary>

--- a/KerbalEngineer/Flight/ActionMenu.cs
+++ b/KerbalEngineer/Flight/ActionMenu.cs
@@ -79,11 +79,11 @@
                 {
                     return;
                 }
-                if (FlightEngineerCore.Instance != null && this.button.State == RUIToggleButton.ButtonState.DISABLED)
+                if (FlightEngineerCore.IsDisplayable && this.button.State == RUIToggleButton.ButtonState.DISABLED)
                 {
                     this.button.Enable();
                 }
-                else if (FlightEngineerCore.Instance == null && this.button.State != RUIToggleButton.ButtonState.DISABLED)
+                else if (!FlightEngineerCore.IsDisplayable && this.button.State != RUIToggleButton.ButtonState.DISABLED)
                 {
                     this.button.Disable();
                 }

--- a/KerbalEngineer/Flight/ActionMenuGui.cs
+++ b/KerbalEngineer/Flight/ActionMenuGui.cs
@@ -132,7 +132,7 @@
         {
             try
             {
-                if (this.Hidden)
+                if (this.Hidden || !FlightEngineerCore.IsDisplayable)
                 {
                     return;
                 }

--- a/KerbalEngineer/Flight/DisplayStack.cs
+++ b/KerbalEngineer/Flight/DisplayStack.cs
@@ -33,6 +33,8 @@
 
 namespace KerbalEngineer.Flight
 {
+    using Upgradeables;
+
     /// <summary>
     ///     Graphical controller for displaying stacked sections.
     /// </summary>
@@ -150,7 +152,7 @@
         {
             try
             {
-                if (FlightEngineerCore.Instance == null)
+                if (!FlightEngineerCore.IsDisplayable)
                 {
                     return;
                 }
@@ -177,7 +179,7 @@
         {
             try
             {
-                if (FlightEngineerCore.Instance == null)
+                if (!FlightEngineerCore.IsDisplayable)
                 {
                     return;
                 }

--- a/KerbalEngineer/Flight/FlightEngineerCore.cs
+++ b/KerbalEngineer/Flight/FlightEngineerCore.cs
@@ -19,21 +19,28 @@
 
 #region Using Directives
 
-using System;
-using System.Collections.Generic;
-
-using KerbalEngineer.Flight.Readouts;
-using KerbalEngineer.Flight.Sections;
-
-using UnityEngine;
-
 #endregion
 
 namespace KerbalEngineer.Flight
 {
+    #region Using Directives
+
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using Extensions;
+    using Readouts;
+    using Sections;
+    using Settings;
+    using UnityEngine;
+    using VesselSimulator;
+
+    #endregion
+
     /// <summary>
     ///     Core management system for the Flight Engineer.
     /// </summary>
+    [KSPAddon(KSPAddon.Startup.Flight, false)]
     public sealed class FlightEngineerCore : MonoBehaviour
     {
         #region Instance
@@ -45,7 +52,210 @@
 
         #endregion
 
+        #region Fields
+
+        private static bool isCareerMode = true;
+        private static bool isKerbalLimited = true;
+        private static bool isTrackingStationLimited = true;
+
+        #endregion
+
         #region Constructors
+
+        static FlightEngineerCore()
+        {
+            try
+            {
+                var handler = SettingHandler.Load("FlightEngineerCore.xml");
+                handler.Get("isCareerMode", ref isCareerMode);
+                handler.Get("isKerbalLimited", ref isKerbalLimited);
+                handler.Get("isTrackingStationLimited", ref isTrackingStationLimited);
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+
+        #region Properties
+
+        /// <summary>
+        ///     Gets and sets whether to the Flight Engineer should be run using career limitations.
+        /// </summary>
+        public static bool IsCareerMode
+        {
+            get { return isCareerMode; }
+            set
+            {
+                try
+                {
+                    if (isCareerMode != value)
+                    {
+                        var handler = SettingHandler.Load("FlightEngineerCore.xml");
+                        handler.Set("isCareerMode", value);
+                        handler.Save("FlightEngineerCore.xml");
+                    }
+                    isCareerMode = value;
+                }
+                catch (Exception ex)
+                {
+                    Logger.Exception(ex);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets whether the FlightEngineer should be displayed.
+        /// </summary>
+        public static bool IsDisplayable
+        {
+            get
+            {
+                if (isCareerMode)
+                {
+                    if (isKerbalLimited && FlightGlobals.ActiveVessel.GetVesselCrew().Exists(c => c.experienceTrait.TypeName == "Engineer"))
+                    {
+                        return true;
+                    }
+                    if (isTrackingStationLimited && ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) == 1.0f)
+                    {
+                        return true;
+                    }
+                    return FlightGlobals.ActiveVessel.parts.Any(p => p.HasModule<FlightEngineerModule>());
+                }
+
+                return true;
+            }
+        }
+
+        /// <summary>
+        ///     Gets and sets whether to the Flight Engineer should be kerbal limited.
+        /// </summary>
+        public static bool IsKerbalLimited
+        {
+            get { return isKerbalLimited; }
+            set
+            {
+                try
+                {
+                    if (isKerbalLimited != value)
+                    {
+                        var handler = SettingHandler.Load("FlightEngineerCore.xml");
+                        handler.Set("isKerbalLimited", value);
+                        handler.Save("FlightEngineerCore.xml");
+                    }
+                    isKerbalLimited = value;
+                }
+                catch (Exception ex)
+                {
+                    Logger.Exception(ex);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets and sets whether to the Flight Engineer should be tracking station limited.
+        /// </summary>
+        public static bool IsTrackingStationLimited
+        {
+            get { return isTrackingStationLimited; }
+            set
+            {
+                try
+                {
+                    if (isTrackingStationLimited != value)
+                    {
+                        var handler = SettingHandler.Load("FlightEngineerCore.xml");
+                        handler.Set("isTrackingStationLimited", value);
+                        handler.Save("FlightEngineerCore.xml");
+                    }
+                    isTrackingStationLimited = value;
+                }
+                catch (Exception ex)
+                {
+                    Logger.Exception(ex);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets the editor windows for sections with open editors.
+        /// </summary>
+        public List<SectionEditor> SectionEditors { get; private set; }
+
+        /// <summary>
+        ///     Gets the section windows for floating sections.
+        /// </summary>
+        public List<SectionWindow> SectionWindows { get; private set; }
+
+        /// <summary>
+        ///     Gets the list of currently running updatable modules.
+        /// </summary>
+        public List<IUpdatable> UpdatableModules { get; private set; }
+
+        #endregion
+
+        #region Methods
+
+        /// <summary>
+        ///     Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.
+        /// </summary>
+        public SectionEditor AddSectionEditor(SectionModule section)
+        {
+            try
+            {
+                var editor = this.gameObject.AddComponent<SectionEditor>();
+                editor.ParentSection = section;
+                editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);
+                this.SectionEditors.Add(editor);
+                return editor;
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+                return null;
+            }
+        }
+
+        /// <summary>
+        ///     Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.
+        /// </summary>
+        public SectionWindow AddSectionWindow(SectionModule section)
+        {
+            try
+            {
+                var window = this.gameObject.AddComponent<SectionWindow>();
+                window.ParentSection = section;
+                window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);
+                this.SectionWindows.Add(window);
+                return window;
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+                return null;
+            }
+        }
+
+        /// <summary>
+        ///     Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.
+        /// </summary>
+        public void AddUpdatable(IUpdatable updatable)
+        {
+            try
+            {
+                if (!this.UpdatableModules.Contains(updatable))
+                {
+                    this.UpdatableModules.Add(updatable);
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
 
         /// <summary>
         ///     Create base Flight Engineer child objects.
@@ -59,11 +269,58 @@
                 this.SectionWindows = new List<SectionWindow>();
                 this.SectionEditors = new List<SectionEditor>();
                 this.UpdatableModules = new List<IUpdatable>();
+
+                SimManager.UpdateModSettings();
+
                 Logger.Log("FlightEngineerCore->Awake");
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "FlightEngineerCore->Awake");
+                Logger.Exception(ex);
+            }
+        }
+
+        /// <summary>
+        ///     Fixed update all required Flight Engineer objects.
+        /// </summary>
+        private void FixedUpdate()
+        {
+            try
+            {
+                SectionLibrary.FixedUpdate();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        /// <summary>
+        ///     Force the destruction of child objects on core destruction.
+        /// </summary>
+        private void OnDestroy()
+        {
+            try
+            {
+                SectionLibrary.Save();
+
+                foreach (var window in this.SectionWindows)
+                {
+                    print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);
+                    Destroy(window);
+                }
+
+                foreach (var editor in this.SectionEditors)
+                {
+                    print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);
+                    Destroy(editor);
+                }
+
+                Logger.Log("FlightEngineerCore->OnDestroy");
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
             }
         }
 
@@ -80,44 +337,6 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "FlightEngineerCore->Start");
-            }
-        }
-
-        #endregion
-
-        #region Properties
-
-        /// <summary>
-        ///     Gets the section windows for floating sections.
-        /// </summary>
-        public List<SectionWindow> SectionWindows { get; private set; }
-
-        /// <summary>
-        ///     Gets the editor windows for sections with open editors.
-        /// </summary>
-        public List<SectionEditor> SectionEditors { get; private set; }
-
-        /// <summary>
-        ///     Gets the list of currently running updatable modules.
-        /// </summary>
-        public List<IUpdatable> UpdatableModules { get; private set; }
-
-        #endregion
-
-        #region Updating
-
-        /// <summary>
-        ///     Fixed update all required Flight Engineer objects.
-        /// </summary>
-        private void FixedUpdate()
-        {
-            try
-            {
-                SectionLibrary.FixedUpdate();
-            }
-            catch (Exception ex)
-            {
                 Logger.Exception(ex);
             }
         }
@@ -134,7 +353,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "FlightEngineerCore->Update");
+                Logger.Exception(ex);
             }
         }
 
@@ -164,102 +383,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "FlightEngineerCore->UpdateModules");
-            }
-        }
-
-        #endregion
-
-        #region Destruction
-
-        /// <summary>
-        ///     Force the destruction of child objects on core destruction.
-        /// </summary>
-        private void OnDestroy()
-        {
-            try
-            {
-                SectionLibrary.Save();
-
-                foreach (var window in this.SectionWindows)
-                {
-                    print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);
-                    Destroy(window);
-                }
-
-                foreach (var editor in this.SectionEditors)
-                {
-                    print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);
-                    Destroy(editor);
-                }
-
-                Logger.Log("FlightEngineerCore->OnDestroy");
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerCore->OnDestroy");
-            }
-        }
-
-        #endregion
-
-        #region Methods
-
-        /// <summary>
-        ///     Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.
-        /// </summary>
-        public SectionWindow AddSectionWindow(SectionModule section)
-        {
-            try
-            {
-                var window = this.gameObject.AddComponent<SectionWindow>();
-                window.ParentSection = section;
-                window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);
-                this.SectionWindows.Add(window);
-                return window;
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerCore->AddSectionWindow");
-                return null;
-            }
-        }
-
-        /// <summary>
-        ///     Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.
-        /// </summary>
-        public SectionEditor AddSectionEditor(SectionModule section)
-        {
-            try
-            {
-                var editor = this.gameObject.AddComponent<SectionEditor>();
-                editor.ParentSection = section;
-                editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);
-                this.SectionEditors.Add(editor);
-                return editor;
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerCore->AddSectionEditor");
-                return null;
-            }
-        }
-
-        /// <summary>
-        ///     Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.
-        /// </summary>
-        public void AddUpdatable(IUpdatable updatable)
-        {
-            try
-            {
-                if (!this.UpdatableModules.Contains(updatable))
-                {
-                    this.UpdatableModules.Add(updatable);
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerCore->AddUpdatable");
+                Logger.Exception(ex);
             }
         }
 

--- a/KerbalEngineer/Flight/FlightEngineerModule.cs
+++ b/KerbalEngineer/Flight/FlightEngineerModule.cs
@@ -19,9 +19,6 @@
 
 #region Using Directives
 
-using System;
-using System.Linq;
-
 #endregion
 
 namespace KerbalEngineer.Flight
@@ -29,73 +26,5 @@
     /// <summary>
     ///     Module that can be attached to parts, giving them FlightEngineerCore management.
     /// </summary>
-    public sealed class FlightEngineerModule : PartModule
-    {
-        #region Fields
-
-        /// <summary>
-        ///     Contains the current FlightEngineerCore through the lifespan of this part.
-        /// </summary>
-        private FlightEngineerCore flightEngineerCore;
-
-        #endregion
-
-        #region Updating
-
-        /// <summary>
-        ///     Logic to create and destroy the FlightEngineerCore.
-        /// </summary>
-        private void Update()
-        {
-            try
-            {
-                if (!HighLogic.LoadedSceneIsFlight || FlightEngineerPartless.IsPartless)
-                {
-                    return;
-                }
-
-                if (this.vessel == FlightGlobals.ActiveVessel)
-                {
-                    // Checks for an existing instance of FlightEngineerCore, and if this part is the first part containing FlightEngineerModule within the vessel.
-                    if (flightEngineerCore == null && this.part == this.vessel.parts.FirstOrDefault(p => p.Modules.Contains("FlightEngineerModule")))
-                    {
-                        this.flightEngineerCore = this.gameObject.AddComponent<FlightEngineerCore>();
-                    }
-                }
-                else if (flightEngineerCore != null)
-                {
-                    // Using DestroyImmediate to force early destruction and keep saving/loading in synch when switching vessels.
-                    DestroyImmediate(flightEngineerCore);
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerModule->Update");
-            }
-        }
-
-        #endregion
-
-        #region Destruction
-
-        /// <summary>
-        ///     Force the destruction of the FlightEngineerCore on part destruction.
-        /// </summary>
-        private void OnDestroy()
-        {
-            try
-            {
-                if (flightEngineerCore != null)
-                {
-                    DestroyImmediate(flightEngineerCore);
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerModule->OnDestroy");
-            }
-        }
-
-        #endregion
-    }
+    public class FlightEngineerModule : PartModule { }
 }

--- a/KerbalEngineer/Flight/FlightEngineerPartless.cs
+++ /dev/null
@@ -1,101 +1,1 @@
-// 
-//     Kerbal Engineer Redux
-// 
-//     Copyright (C) 2014 CYBUTEK
-// 
-//     This program is free software: you can redistribute it and/or modify
-//     it under the terms of the GNU General Public License as published by
-//     the Free Software Foundation, either version 3 of the License, or
-//     (at your option) any later version.
-// 
-//     This program is distributed in the hope that it will be useful,
-//     but WITHOUT ANY WARRANTY; without even the implied warranty of
-//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//     GNU General Public License for more details.
-// 
-//     You should have received a copy of the GNU General Public License
-//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-// 
 
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Settings;
-
-using UnityEngine;
-
-#endregion
-
-namespace KerbalEngineer.Flight
-{
-    [KSPAddon(KSPAddon.Startup.Flight, false)]
-    public class FlightEngineerPartless : MonoBehaviour
-    {
-        #region Fields
-
-        private FlightEngineerCore flightEngineerCore;
-
-        #endregion
-
-        #region Initialisation
-
-        static FlightEngineerPartless()
-        {
-            try
-            {
-                var handler = SettingHandler.Load("FlightEngineerPartless.xml");
-                handler.Get("isPartless", ref isPartless);
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerPartless->FlightEngineerPartless");
-            }
-        }
-
-        private void Awake()
-        {
-            try
-            {
-                if (isPartless)
-                {
-                    this.flightEngineerCore = this.gameObject.AddComponent<FlightEngineerCore>();
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "FlightEngineerPartless->Awake");
-            }
-        }
-
-        #endregion
-
-        #region Properties
-
-        private static bool isPartless = true;
-
-        public static bool IsPartless
-        {
-            get { return isPartless; }
-            set
-            {
-                try
-                {
-                    if (isPartless != value)
-                    {
-                        var handler = SettingHandler.Load("FlightEngineerPartless.xml");
-                        handler.Set("isPartless", value);
-                        handler.Save("FlightEngineerPartless.xml");
-                    }
-                    isPartless = value;
-                }
-                catch (Exception ex)
-                {
-                    Logger.Exception(ex, "FlightEngineerPartless->IsPartless");
-                }
-            }
-        }
-
-        #endregion
-    }
-}

--- a/KerbalEngineer/Flight/Readouts/Miscellaneous/SimulationDelay.cs
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/SimulationDelay.cs
@@ -28,6 +28,8 @@
 
 namespace KerbalEngineer.Flight.Readouts.Miscellaneous
 {
+    using System;
+
     public class SimulationDelay : ReadoutModule
     {
         #region Constructors
@@ -49,7 +51,7 @@
             GUILayout.BeginHorizontal();
             GUILayout.Label("Sim Delay", this.NameStyle);
             GUI.skin = HighLogic.Skin;
-            SimManager.minSimTime = (long)GUILayout.HorizontalSlider(SimManager.minSimTime, 0, 1000.0f);
+            SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 1000.0f));
             GUI.skin = null;
             GUILayout.EndHorizontal();
         }

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/SystemTime.cs
@@ -1,1 +1,59 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Miscellaneous
+{
+    public class SystemTime : ReadoutModule
+    {
+
+
+        #region Constructors
+
+        public SystemTime()
+        {
+            this.Name = "System Time";
+            this.Category = ReadoutCategory.GetCategory("Miscellaneous");
+            this.HelpString = String.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(DateTime.Now.ToLongTimeString(), section.IsHud);
+        }
+
+        #endregion
+
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/VectoredThrustToggle.cs
@@ -1,1 +1,56 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Miscellaneous
+{
+    #region Using Directives
+
+    using Sections;
+    using UnityEngine;
+    using VesselSimulator;
+
+    #endregion
+
+    public class VectoredThrustToggle : ReadoutModule
+    {
+        #region Constructors
+
+        public VectoredThrustToggle()
+        {
+            this.Name = "Vectored Thrust";
+            this.Category = ReadoutCategory.GetCategory("Miscellaneous");
+            this.HelpString = "Shows a control that will allow you to adjust whether the vessel simulation should account for vectored thrust.";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            GUILayout.BeginHorizontal();
+            GUILayout.Label("Vectored Thrust: ", this.NameStyle);
+            SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", this.ButtonStyle);
+            GUILayout.EndHorizontal();
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
@@ -91,7 +91,11 @@
 
         public void Update()
         {
-            if (FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes.Count == 0 || !SimulationProcessor.ShowDetails)
+            // Extra tests for low level tracking station not supporting patched conics and maneuver nodes
+            if (FlightGlobals.ActiveVessel.patchedConicSolver == null ||
+                FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes == null ||
+                FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes.Count == 0 ||
+                !SimulationProcessor.ShowDetails)
             {
                 ShowDetails = false;
                 return;
@@ -159,7 +163,7 @@
                     deltaVDrain = deltaV.Clamp(0.0, stageDeltaV);
                 }
 
-                var exhaustVelocity = stage.isp * 9.8066;
+                var exhaustVelocity = stage.isp * 9.82;
                 var flowRate = stage.thrust / exhaustVelocity;
                 var endMass = Math.Exp(Math.Log(startMass) - deltaVDrain / exhaustVelocity);
                 var deltaMass = (startMass - endMass) * Math.Exp(-(deltaVDrain * 0.001) / exhaustVelocity);

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/MeanAnomalyAtEpoc.cs
@@ -1,1 +1,54 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital
+{
+    public class MeanAnomalyAtEpoc : ReadoutModule
+    {
+        #region Constructors
+
+        public MeanAnomalyAtEpoc()
+        {
+            this.Name = "Mean Anomaly at Epoc";
+            this.Category = ReadoutCategory.GetCategory("Orbital");
+            this.HelpString = String.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(FlightGlobals.ship_orbit.meanAnomalyAtEpoch.ToAngle(), section.IsHud);
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/ReadoutCategory.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutCategory.cs
@@ -56,6 +56,7 @@
         public static ReadoutCategory Selected { get; set; }
 
         public string Description { get; set; }
+
         public string Name { get; set; }
 
         #endregion

--- a/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
@@ -17,33 +17,31 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using KerbalEngineer.Flight.Readouts.Miscellaneous;
-using KerbalEngineer.Flight.Readouts.Orbital;
-using KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode;
-using KerbalEngineer.Flight.Readouts.Rendezvous;
-using KerbalEngineer.Flight.Readouts.Surface;
-using KerbalEngineer.Flight.Readouts.Vessel;
-using KerbalEngineer.Settings;
-
-using AltitudeSeaLevel = KerbalEngineer.Flight.Readouts.Surface.AltitudeSeaLevel;
-using ApoapsisHeight = KerbalEngineer.Flight.Readouts.Orbital.ApoapsisHeight;
-using OrbitalPeriod = KerbalEngineer.Flight.Readouts.Orbital.OrbitalPeriod;
-using PeriapsisHeight = KerbalEngineer.Flight.Readouts.Orbital.PeriapsisHeight;
-using SemiMajorAxis = KerbalEngineer.Flight.Readouts.Orbital.SemiMajorAxis;
-using SemiMinorAxis = KerbalEngineer.Flight.Readouts.Orbital.SemiMinorAxis;
-using TimeToApoapsis = KerbalEngineer.Flight.Readouts.Orbital.TimeToApoapsis;
-using TimeToPeriapsis = KerbalEngineer.Flight.Readouts.Orbital.TimeToPeriapsis;
-
-#endregion
-
 namespace KerbalEngineer.Flight.Readouts
 {
+    #region Using Directives
+
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using Miscellaneous;
+    using Orbital;
+    using Orbital.ManoeuvreNode;
+    using Rendezvous;
+    using Settings;
+    using Surface;
+    using Vessel;
+    using AltitudeSeaLevel = Surface.AltitudeSeaLevel;
+    using ApoapsisHeight = Orbital.ApoapsisHeight;
+    using OrbitalPeriod = Orbital.OrbitalPeriod;
+    using PeriapsisHeight = Orbital.PeriapsisHeight;
+    using SemiMajorAxis = Orbital.SemiMajorAxis;
+    using SemiMinorAxis = Orbital.SemiMinorAxis;
+    using TimeToApoapsis = Orbital.TimeToApoapsis;
+    using TimeToPeriapsis = Orbital.TimeToPeriapsis;
+
+    #endregion
+
     public static class ReadoutLibrary
     {
         #region Fields
@@ -66,6 +64,7 @@
                 ReadoutCategory.SetCategory("Vessel", "Vessel performance statistics.");
                 ReadoutCategory.SetCategory("Rendezvous", "Readouts for rendezvous manovoeures.");
                 ReadoutCategory.SetCategory("Miscellaneous", "Miscellaneous readouts.");
+                ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
 
                 // Orbital
                 readouts.Add(new ApoapsisHeight());
@@ -86,6 +85,7 @@
                 readouts.Add(new ArgumentOfPeriapsis());
                 readouts.Add(new TrueAnomaly());
                 readouts.Add(new MeanAnomaly());
+                readouts.Add(new MeanAnomalyAtEpoc());
                 readouts.Add(new EccentricAnomaly());
                 readouts.Add(new SemiMajorAxis());
                 readouts.Add(new SemiMinorAxis());
@@ -132,6 +132,8 @@
                 readouts.Add(new Mass());
                 readouts.Add(new Thrust());
                 readouts.Add(new ThrustToWeight());
+                readouts.Add(new ThrustOffsetAngle());
+                readouts.Add(new ThrustTorque());
                 readouts.Add(new SurfaceThrustToWeight());
                 readouts.Add(new Acceleration());
                 readouts.Add(new SuicideBurnAltitude());
@@ -141,6 +143,13 @@
                 readouts.Add(new IntakeAirDemand());
                 readouts.Add(new IntakeAirSupply());
                 readouts.Add(new IntakeAirDemandSupply());
+                readouts.Add(new PartCount());
+                readouts.Add(new Heading());
+                readouts.Add(new Pitch());
+                readouts.Add(new Roll());
+                readouts.Add(new HeadingRate());
+                readouts.Add(new PitchRate());
+                readouts.Add(new RollRate());
 
                 // Rendezvous
                 readouts.Add(new TargetSelector());
@@ -162,12 +171,14 @@
                 readouts.Add(new Rendezvous.OrbitalPeriod());
                 readouts.Add(new Rendezvous.SemiMajorAxis());
                 readouts.Add(new Rendezvous.SemiMinorAxis());
-
+                
                 // Misc
                 readouts.Add(new Separator());
                 readouts.Add(new GuiSizeAdjustor());
                 readouts.Add(new SimulationDelay());
                 readouts.Add(new TimeReference());
+                readouts.Add(new VectoredThrustToggle());
+                readouts.Add(new SystemTime());
 
                 LoadHelpStrings();
             }
@@ -192,7 +203,7 @@
 
         #endregion
 
-        #region Methods: public
+        #region Methods
 
         /// <summary>
         ///     Gets a list of readout modules which are associated with the specified category.
@@ -220,10 +231,6 @@
                 readout.Reset();
             }
         }
-
-        #endregion
-
-        #region Methods: private
 
         /// <summary>
         ///     Loads the help strings from file.

--- a/KerbalEngineer/Flight/Readouts/Surface/AltitudeTerrain.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/AltitudeTerrain.cs
@@ -19,13 +19,17 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight.Sections;
-
 #endregion
 
 namespace KerbalEngineer.Flight.Readouts.Surface
 {
+    #region Using Directives
+
+    using Extensions;
+    using Sections;
+
+    #endregion
+
     public class AltitudeTerrain : ReadoutModule
     {
         #region Constructors
@@ -40,11 +44,18 @@
 
         #endregion
 
-        #region Methods: public
+        #region Methods
 
         public override void Draw(SectionModule section)
         {
-            this.DrawLine((FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude).ToDistance(), section.IsHud);
+            if (FlightGlobals.ActiveVessel.terrainAltitude > 0.0)
+            {
+                this.DrawLine((FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude).ToDistance(), section.IsHud);
+            }
+            else
+            {
+                this.DrawLine((FlightGlobals.ship_altitude).ToDistance(), section.IsHud);
+            }
         }
 
         #endregion

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/AttitudeProcessor.cs
@@ -1,1 +1,132 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using UnityEngine;
+
+    #endregion
+
+    public class AttitudeProcessor : IUpdatable, IUpdateRequest
+    {
+        #region Fields
+
+        private static readonly AttitudeProcessor instance = new AttitudeProcessor();
+
+        private Vector3 centreOfMass = Vector3.zero;
+
+        private double heading;
+        private double headingRate;
+        private Vector3 north = Vector3.zero;
+        private double pitch;
+        private double pitchRate;
+        private double previousHeading;
+        private double previousPitch;
+        private double previousRoll;
+        private double roll;
+        private double rollRate;
+        private Quaternion surfaceRotation;
+        private Vector3 up = Vector3.zero;
+
+        #endregion
+
+        #region Properties
+
+        public static double Heading
+        {
+            get { return instance.heading; }
+        }
+
+        public static double HeadingRate
+        {
+            get { return instance.headingRate; }
+        }
+
+        public static AttitudeProcessor Instance
+        {
+            get { return instance; }
+        }
+
+        public static double Pitch
+        {
+            get { return instance.pitch; }
+        }
+
+        public static double PitchRate
+        {
+            get { return instance.pitchRate; }
+        }
+
+        public static double Roll
+        {
+            get { return instance.roll; }
+        }
+
+        public static double RollRate
+        {
+            get { return instance.rollRate; }
+        }
+
+        public bool UpdateRequested { get; set; }
+
+        #endregion
+
+        #region Methods
+
+        public static void RequestUpdate()
+        {
+            instance.UpdateRequested = true;
+        }
+
+        public void Update()
+        {
+            this.surfaceRotation = this.GetSurfaceRotation();
+
+            this.previousHeading = this.heading;
+            this.previousPitch = this.pitch;
+            this.previousRoll = this.roll;
+
+            // This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation.
+            this.heading = this.surfaceRotation.eulerAngles.y;
+            this.pitch = this.surfaceRotation.eulerAngles.x > 180.0f
+                ? 360.0f - this.surfaceRotation.eulerAngles.x
+                : -this.surfaceRotation.eulerAngles.x;
+            this.roll = this.surfaceRotation.eulerAngles.z > 180.0f
+                ? this.surfaceRotation.eulerAngles.z - 360.0f
+                : this.surfaceRotation.eulerAngles.z;
+
+            this.headingRate = this.heading - this.previousHeading;
+            this.pitchRate = this.pitch - this.previousPitch;
+            this.rollRate = this.roll - this.previousRoll;
+        }
+
+        private Quaternion GetSurfaceRotation()
+        {
+            // 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;
+            return Quaternion.Inverse(Quaternion.Euler(90.0f, 0.0f, 0.0f) * Quaternion.Inverse(FlightGlobals.ActiveVessel.transform.rotation) * Quaternion.LookRotation(this.north, this.up));
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Heading.cs
@@ -1,1 +1,62 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class Heading : ReadoutModule
+    {
+        #region Constructors
+
+        public Heading()
+        {
+            this.Name = "Heading";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(Units.ToAngle(AttitudeProcessor.Heading), section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            AttitudeProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/HeadingRate.cs
@@ -1,1 +1,62 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class HeadingRate : ReadoutModule
+    {
+        #region Constructors
+
+        public HeadingRate()
+        {
+            this.Name = "Heading Rate";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(Units.ToAngle(AttitudeProcessor.HeadingRate) + "/sec", section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            AttitudeProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/PartCount.cs
@@ -1,1 +1,65 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class PartCount : ReadoutModule
+    {
+        #region Constructors
+
+        public PartCount()
+        {
+            this.Name = "Part Count";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = true;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            if (SimulationProcessor.ShowDetails)
+            {
+                this.DrawLine(Units.ConcatF(SimulationProcessor.LastStage.partCount, SimulationProcessor.LastStage.totalPartCount), section.IsHud);
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            SimulationProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Pitch.cs
@@ -1,1 +1,62 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class Pitch : ReadoutModule
+    {
+        #region Constructors
+
+        public Pitch()
+        {
+            this.Name = "Pitch";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(Units.ToAngle(AttitudeProcessor.Pitch), section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            AttitudeProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/PitchRate.cs
@@ -1,1 +1,62 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class PitchRate : ReadoutModule
+    {
+        #region Constructors
+
+        public PitchRate()
+        {
+            this.Name = "Pitch Rate";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(Units.ToAngle(AttitudeProcessor.PitchRate) + "/sec", section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            AttitudeProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Roll.cs
@@ -1,1 +1,62 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class Roll : ReadoutModule
+    {
+        #region Constructors
+
+        public Roll()
+        {
+            this.Name = "Roll";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(Units.ToAngle(AttitudeProcessor.Roll), section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            AttitudeProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/RollRate.cs
@@ -1,1 +1,62 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    #region Using Directives
+
+    using Helpers;
+    using Sections;
+
+    #endregion
+
+    public class RollRate : ReadoutModule
+    {
+        #region Constructors
+
+        public RollRate()
+        {
+            this.Name = "Roll Rate";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = string.Empty;
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods
+
+        public override void Draw(SectionModule section)
+        {
+            this.DrawLine(Units.ToAngle(AttitudeProcessor.RollRate) + "/sec", section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            AttitudeProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/Vessel/SimulationProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SimulationProcessor.cs
@@ -19,14 +19,19 @@
 
 #region Using Directives
 
-using System;
 
-using KerbalEngineer.VesselSimulator;
 
 #endregion
 
 namespace KerbalEngineer.Flight.Readouts.Vessel
 {
+    #region Using Directives
+
+    using System;
+    using VesselSimulator;
+
+    #endregion
+
     public class SimulationProcessor : IUpdatable, IUpdateRequest
     {
         #region Instance
@@ -34,6 +39,15 @@
         #region Fields
 
         private static readonly SimulationProcessor instance = new SimulationProcessor();
+
+        #endregion
+
+        #region Constructors
+
+        static SimulationProcessor()
+        {
+            SimManager.OnReady += GetStageInfo;
+        }
 
         #endregion
 
@@ -72,7 +86,13 @@
 
         #endregion
 
-        #region Methods: public
+        #region Methods
+
+        private static void GetStageInfo()
+        {
+            Stages = SimManager.Stages;
+            LastStage = SimManager.LastStage;
+        }
 
         public static void RequestUpdate()
         {
@@ -89,9 +109,6 @@
                 return;
             }
 
-            Stages = SimManager.Stages;
-            LastStage = SimManager.LastStage;
-
             if (Stages != null && LastStage != null)
             {
                 ShowDetails = true;
@@ -104,9 +121,6 @@
                                               FlightGlobals.ActiveVessel.mainBody.GetAltitude(FlightGlobals.ActiveVessel.CoM), 2);
                 SimManager.Velocity = FlightGlobals.ActiveVessel.srfSpeed;
             }
-
-            // Cybutek: We should be allowing this to be set too but not sure where you want to put the control
-            //SimManager.vectoredThrust = vectoredThrust; 
         }
 
         #endregion

--- a/KerbalEngineer/Flight/Readouts/Vessel/SuicideBurnProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SuicideBurnProcessor.cs
@@ -19,12 +19,18 @@
 
 #region Using Directives
 
-using System;
+
 
 #endregion
 
 namespace KerbalEngineer.Flight.Readouts.Vessel
 {
+    #region Using Directives
+
+    using System;
+
+    #endregion
+
     public class SuicideBurnProcessor : IUpdatable, IUpdateRequest
     {
         #region Fields
@@ -55,7 +61,7 @@
 
         #endregion
 
-        #region Methods: public
+        #region Methods
 
         public static void RequestUpdate()
         {
@@ -79,7 +85,9 @@
 
             this.gravity = FlightGlobals.currentMainBody.gravParameter / Math.Pow(FlightGlobals.currentMainBody.Radius, 2.0);
             this.acceleration = SimulationProcessor.LastStage.thrust / SimulationProcessor.LastStage.totalMass;
-            this.radarAltitude = FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude;
+            this.radarAltitude = FlightGlobals.ActiveVessel.terrainAltitude > 0.0
+                ? FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude
+                : FlightGlobals.ship_altitude;
 
             DeltaV = Math.Sqrt((2 * this.gravity * this.radarAltitude) + Math.Pow(FlightGlobals.ship_verticalSpeed, 2.0));
             Altitude = Math.Pow(DeltaV, 2.0) / (2.0 * this.acceleration);

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/ThrustOffsetAngle.cs
@@ -1,1 +1,66 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    public class ThrustOffsetAngle : ReadoutModule
+    {
+        #region Constructors
+
+        public ThrustOffsetAngle()
+        {
+            this.Name = "Thrust offset angle";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = "Thrust angle offset due to vessel asymmetries and gimballing";
+            this.IsDefault = true;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (SimulationProcessor.ShowDetails)
+            {
+                this.DrawLine(Units.ToAngle(SimulationProcessor.LastStage.thrustOffsetAngle, 1), section.IsHud);
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            SimulationProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}
+

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/ThrustTorque.cs
@@ -1,1 +1,66 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    public class ThrustTorque : ReadoutModule
+    {
+        #region Constructors
+
+        public ThrustTorque()
+        {
+            this.Name = "Thrust torque";
+            this.Category = ReadoutCategory.GetCategory("Vessel");
+            this.HelpString = "Thrust torque due to vessel asymmetries and gimballing";
+            this.IsDefault = true;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (SimulationProcessor.ShowDetails)
+            {
+                this.DrawLine(Units.ToTorque(SimulationProcessor.LastStage.maxThrustTorque), section.IsHud);
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            SimulationProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}
+

--- a/KerbalEngineer/Flight/Sections/SectionEditor.cs
+++ b/KerbalEngineer/Flight/Sections/SectionEditor.cs
@@ -119,7 +119,7 @@
             try
             {
                 this.InitialiseStyles();
-                ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
+                //ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
                 RenderingManager.AddToPostDrawQueue(0, this.Draw);
             }
             catch (Exception ex)

--- a/KerbalEngineer/Flight/Sections/SectionWindow.cs
+++ b/KerbalEngineer/Flight/Sections/SectionWindow.cs
@@ -118,7 +118,7 @@
         /// </summary>
         private void Draw()
         {
-            if (this.ParentSection == null || !this.ParentSection.IsVisible || (DisplayStack.Instance.Hidden && !this.ParentSection.IsHud))
+            if (this.ParentSection == null || !this.ParentSection.IsVisible || (DisplayStack.Instance.Hidden && !this.ParentSection.IsHud) || !FlightEngineerCore.IsDisplayable)
             {
                 return;
             }

--- /dev/null
+++ b/KerbalEngineer/Helpers/Averager.cs
@@ -1,1 +1,67 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+using System;
+
+namespace KerbalEngineer
+{ 
+    public class VectorAverager
+    {
+        private Vector3d sum = Vector3d.zero;
+        private uint count = 0;
+
+        public void Add(Vector3d v) {
+            sum += v;
+            count += 1;
+        }
+
+        public Vector3d Get() {
+            if (count > 0) {
+                return sum / count;
+            } else {
+                return Vector3d.zero;
+            }
+        }
+    }
+
+    public class WeightedVectorAverager
+    {
+        private Vector3d sum = Vector3d.zero;
+        private double totalweight = 0;
+
+        public void Add(Vector3d v, double weight) {
+            sum += v * weight;
+            totalweight += weight;
+        }
+
+        public Vector3d Get() {
+            if (totalweight > 0) {
+                return sum / totalweight;
+            } else {
+                return Vector3d.zero;
+            }
+        }
+
+        public double GetTotalWeight() {
+            return totalweight;
+        }
+    }
+}
+
+

--- /dev/null
+++ b/KerbalEngineer/Helpers/ForceAccumulator.cs
@@ -1,1 +1,103 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+using System;
+using System.Collections.Generic;
+
+namespace KerbalEngineer
+{
+    // a (force, application point) tuple
+    public class AppliedForce
+    {
+        public Vector3d vector;
+        public Vector3d applicationPoint;
+
+        public AppliedForce(Vector3d vector, Vector3d applicationPoint) {
+            this.vector = vector;
+            this.applicationPoint = applicationPoint;
+        }
+    }
+
+	// This class was mostly adapted from FARCenterQuery, part of FAR, by ferram4, GPLv3
+	// https://github.com/ferram4/Ferram-Aerospace-Research/blob/master/FerramAerospaceResearch/FARCenterQuery.cs
+    // Also see https://en.wikipedia.org/wiki/Resultant_force
+
+	// It accumulates forces and their points of applications, and provides methods for
+    // calculating the effective torque at any position, as well as the minimum-torque net force application point.
+    //
+    // The latter is a non-trivial issue; there is a 1-dimensional line of physically-equivalent solutions parallel
+    // to the resulting force vector; the solution closest to the weighted average of force positions is chosen.
+	// In the case of non-parallel forces, there usually is an infinite number of such lines, all of which have
+	// some amount of residual torque. The line with the least amount of residual torque is chosen.
+	public class ForceAccumulator
+	{
+		// Total force.
+		private Vector3d totalForce = Vector3d.zero;
+		// Torque needed to compensate if force were applied at origin.
+		private Vector3d totalZeroOriginTorque = Vector3d.zero;
+
+		// Weighted average of force application points.
+		private WeightedVectorAverager avgApplicationPoint = new WeightedVectorAverager();
+
+		// Feed an force to the accumulator.
+		public void AddForce(Vector3d applicationPoint, Vector3d force)
+		{
+			totalForce += force;
+			totalZeroOriginTorque += Vector3d.Cross(applicationPoint, force);
+			avgApplicationPoint.Add(applicationPoint, force.magnitude);
+		}
+
+        public Vector3d GetAverageForceApplicationPoint() {
+            return avgApplicationPoint.Get();
+        }
+
+        public void AddForce(AppliedForce force) {
+            AddForce(force.applicationPoint, force.vector);
+        }
+
+		// Residual torque for given force application point.
+		public Vector3d TorqueAt(Vector3d origin)
+		{
+			return totalZeroOriginTorque - Vector3d.Cross(origin, totalForce);
+		}
+
+        // Total force vector.
+        public Vector3d GetTotalForce()
+        {
+            return totalForce;
+        }
+
+        // Returns the minimum-residual-torque force application point that is closest to origin.
+        // Note that TorqueAt(GetMinTorquePos()) is always parallel to totalForce.
+        public Vector3d GetMinTorqueForceApplicationPoint(Vector3d origin)
+        {
+            double fmag = totalForce.sqrMagnitude;
+            if (fmag <= 0) {
+                return origin;
+            }
+
+            return origin + Vector3d.Cross(totalForce, TorqueAt(origin)) / fmag;
+        }
+
+        public Vector3d GetMinTorqueForceApplicationPoint()
+        {
+            return GetMinTorqueForceApplicationPoint(avgApplicationPoint.Get());
+        }
+	}
+}

--- a/KerbalEngineer/Helpers/Units.cs
+++ b/KerbalEngineer/Helpers/Units.cs
@@ -17,26 +17,59 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-
-#endregion
-
 namespace KerbalEngineer.Helpers
 {
+    #region Using Directives
+
+    using System;
+
+    #endregion
+
     public static class Units
     {
-        #region Methods: public
+        #region Methods
 
-        public static string Concat(double value1, double value2, int decimals = 1)
+        public static string Concat(int value1, int value2)
+        {
+            return value1 + " / " + value2;
+        }
+
+        public static string ConcatF(double value1, double value2, int decimals = 1)
         {
             return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals);
         }
 
-        public static string Concat(double value1, double value2, double value3, int decimals = 1)
+        public static string ConcatF(double value1, double value2, double value3, int decimals = 1)
         {
             return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals) + " / " + value3.ToString("F" + decimals);
+        }
+
+        public static string ConcatN(double value1, double value2, int decimals = 1)
+        {
+            return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals);
+        }
+
+        public static string ConcatN(double value1, double value2, double value3, int decimals = 1)
+        {
+            return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + " / " + value3.ToString("N" + decimals);
+        }
+
+        public static string Cost(double value, int decimals = 1)
+        {
+            if (value >= 1000000.0)
+            {
+                return (value / 1000.0).ToString("N" + decimals) + "K";
+            }
+            return value.ToString("N" + decimals);
+        }
+
+        public static string Cost(double value1, double value2, int decimals = 1)
+        {
+            if (value1 >= 1000000.0 || value2 >= 1000000.0)
+            {
+                return (value1 / 1000.0).ToString("N" + decimals) + " / " + (value2 / 1000.0).ToString("N" + decimals) + "K";
+            }
+            return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals);
         }
 
         public static string ToAcceleration(double value, int decimals = 2)
@@ -97,12 +130,22 @@
 
         public static string ToMass(double value, int decimals = 0)
         {
+            if (value >= 1000.0)
+            {
+                return value.ToString("N" + decimals + 2) + "t";
+            }
+
             value *= 1000.0;
             return value.ToString("N" + decimals) + "kg";
         }
 
         public static string ToMass(double value1, double value2, int decimals = 0)
         {
+            if (value1 >= 1000.0f || value2 >= 1000.0f)
+            {
+                return value1.ToString("N" + decimals + 2) + " / " + value2.ToString("N" + decimals + 2) + "t";
+            }
+
             value1 *= 1000.0;
             value2 *= 1000.0;
             return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "kg";
@@ -133,6 +176,11 @@
             return TimeFormatter.ConvertToString(value);
         }
 
+        public static string ToTorque(double value)
+        {
+            return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
+        }
+
         #endregion
     }
 }

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -49,8 +49,9 @@
     <Compile Include="Extensions\FloatExtensions.cs" />
     <Compile Include="Extensions\OrbitExtensions.cs" />
     <Compile Include="Flight\ActionMenuGui.cs" />
-    <Compile Include="Flight\FlightEngineerPartless.cs" />
     <Compile Include="Flight\Presets\Preset.cs" />
+    <Compile Include="Flight\Readouts\Miscellaneous\SystemTime.cs" />
+    <Compile Include="Flight\Readouts\Miscellaneous\VectoredThrustToggle.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\TimeReference.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\Separator.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\GuiSizeAdjustor.cs" />
@@ -69,6 +70,7 @@
     <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToPrograde.cs" />
     <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTotalDeltaV.cs" />
     <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeProgradeDeltaV.cs" />
+    <Compile Include="Flight\Readouts\Orbital\MeanAnomalyAtEpoc.cs" />
     <Compile Include="Flight\Readouts\Orbital\MeanAnomaly.cs" />
     <Compile Include="Flight\Readouts\Orbital\EccentricAnomaly.cs" />
     <Compile Include="Flight\Readouts\Orbital\ArgumentOfPeriapsis.cs" />
@@ -87,7 +89,15 @@
     <Compile Include="Flight\Readouts\Surface\Biome.cs" />
     <Compile Include="Flight\Readouts\Surface\HorizontalAcceleration.cs" />
     <Compile Include="Flight\Readouts\Surface\VerticalAcceleration.cs" />
+    <Compile Include="Flight\Readouts\Vessel\AttitudeProcessor.cs" />
     <Compile Include="Flight\Readouts\Vessel\DeltaVCurrentTotal.cs" />
+    <Compile Include="Flight\Readouts\Vessel\PitchRate.cs" />
+    <Compile Include="Flight\Readouts\Vessel\HeadingRate.cs" />
+    <Compile Include="Flight\Readouts\Vessel\RollRate.cs" />
+    <Compile Include="Flight\Readouts\Vessel\Roll.cs" />
+    <Compile Include="Flight\Readouts\Vessel\Pitch.cs" />
+    <Compile Include="Flight\Readouts\Vessel\Heading.cs" />
+    <Compile Include="Flight\Readouts\Vessel\PartCount.cs" />
     <Compile Include="Flight\Readouts\Vessel\SuicideBurnDeltaV.cs" />
     <Compile Include="Flight\Readouts\Vessel\SuicideBurnAltitude.cs" />
     <Compile Include="Flight\Readouts\Vessel\SuicideBurnDistance.cs" />
@@ -103,8 +113,12 @@
     <Compile Include="Flight\Readouts\Vessel\SuicideBurnProcessor.cs" />
     <Compile Include="Flight\Readouts\Vessel\SurfaceThrustToWeight.cs" />
     <Compile Include="Flight\Readouts\Surface\Situation.cs" />
+    <Compile Include="Flight\Readouts\Vessel\ThrustOffsetAngle.cs" />
+    <Compile Include="Flight\Readouts\Vessel\ThrustTorque.cs" />
     <Compile Include="GuiDisplaySize.cs" />
     <Compile Include="Helpers\AngleHelper.cs" />
+    <Compile Include="Helpers\Averager.cs" />
+    <Compile Include="Helpers\ForceAccumulator.cs" />
     <Compile Include="Helpers\TextureHelper.cs" />
     <Compile Include="Helpers\Units.cs" />
     <Compile Include="Helpers\TimeFormatter.cs" />

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -38,6 +38,7 @@
         public bool isActive = false;
         public double isp = 0;
         public PartSim partSim;
+        public List<AppliedForce> appliedForces;
 
         public double thrust = 0;
 
@@ -58,7 +59,8 @@
                          bool throttleLocked,
                          List<Propellant> propellants,
                          bool active,
-                         bool correctThrust)
+                         bool correctThrust,
+                         List<Transform> thrustTransforms)
         {
             StringBuilder buffer = null;
             //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
@@ -116,14 +118,14 @@
                 if (throttleLocked)
                 {
                     //MonoBehaviour.print("throttleLocked is true");
-                    flowRate = this.thrust / (this.isp * 9.81d);
+                    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.8066);
+                        flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.82);
                     }
                     else
                     {
@@ -136,12 +138,12 @@
                             }
 
                             //MonoBehaviour.print("requestedThrust > 0");
-                            flowRate = requestedThrust / (this.isp * 9.8066);
+                            flowRate = requestedThrust / (this.isp * 9.82);
                         }
                         else
                         {
                             //MonoBehaviour.print("requestedThrust <= 0");
-                            flowRate = this.thrust / (this.isp * 9.8066);
+                            flowRate = this.thrust / (this.isp * 9.82);
                         }
                     }
                 }
@@ -174,7 +176,7 @@
                     //MonoBehaviour.print("thrust at velocity = " + thrust);
                 }
 
-                flowRate = this.thrust / (this.isp * 9.8066);
+                flowRate = this.thrust / (this.isp * 9.82);
             }
 
             if (SimManager.logOutput)
@@ -212,6 +214,14 @@
             if (SimManager.logOutput)
             {
                 MonoBehaviour.print(buffer);
+            }
+
+            appliedForces = new List<AppliedForce>();
+            double thrustPerThrustTransform = thrust / thrustTransforms.Count;
+            foreach (Transform thrustTransform in thrustTransforms) {
+                Vector3d direction = thrustTransform.forward.normalized;
+                Vector3d position = thrustTransform.position;
+                appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position));
             }
         }
 
@@ -257,46 +267,36 @@
                         break;
 
                     case ResourceFlowMode.STAGE_PRIORITY_FLOW:
-                    {
-                        Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
-                        int maxStage = -1;
-                        foreach (PartSim aPartSim in allParts)
-                        {
-                            if (aPartSim.resources[type] > SimManager.RESOURCE_MIN)
-                            {
-                                //int stage = aPartSim.decoupledInStage;            // Use the number of the stage the tank is decoupled in
-                                int stage = aPartSim.DecouplerCount(); // Use the count of decouplers between tank and root
-                                if (stage > maxStage)
-                                {
-                                    maxStage = stage;
-                                }
-                                if (stagePartSets.ContainsKey(stage))
-                                {
-                                    sourcePartSet = stagePartSets[stage];
-                                }
-                                else
-                                {
-                                    sourcePartSet = new HashSet<PartSim>();
-                                    stagePartSets.Add(stage, sourcePartSet);
-                                }
-
-                                sourcePartSet.Add(aPartSim);
-                            }
-                        }
-
-                        while (maxStage >= 0)
-                        {
-                            if (stagePartSets.ContainsKey(maxStage))
-                            {
-                                if (stagePartSets[maxStage].Count() > 0)
-                                {
-                                    sourcePartSet = stagePartSets[maxStage];
-                                    break;
-                                }
-                            }
-                            maxStage--;
-                        }
-                    }
+                        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();
+                            if (stage > maxStage)
+                            {
+                                maxStage = stage;
+                            }
+
+                            if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
+                            {
+                                sourcePartSet = new HashSet<PartSim>();
+                                stagePartSets.Add(stage, sourcePartSet);
+                            }
+                            sourcePartSet.Add(aPartSim);
+                        }
+
+                        for (var i = 0; i <= maxStage; i++)
+                        {
+                            HashSet<PartSim> stagePartSet;
+                            if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0)
+                            {
+                                sourcePartSet = stagePartSet;
+                            }
+                        }
                         break;
 
                     case ResourceFlowMode.STACK_PRIORITY_SEARCH:

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -32,9 +32,12 @@
 
 namespace KerbalEngineer.VesselSimulator
 {
+    using CompoundParts;
+
     public class PartSim
     {
         private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+        public Vector3d centerOfMass;
         public double baseMass = 0d;
         public double cost;
         public int decoupledInStage;
@@ -71,6 +74,7 @@
         public PartSim(Part thePart, int id, double atmosphere, LogMsg log)
         {
             this.part = thePart;
+            this.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
             this.partId = id;
             this.name = this.part.partInfo.name;
 
@@ -84,7 +88,7 @@
             this.fuelCrossFeed = this.part.fuelCrossFeed;
             this.noCrossFeedNodeKey = this.part.NoCrossFeedNodeKey;
             this.decoupledInStage = this.DecoupledInStage(this.part);
-            this.isFuelLine = this.part is FuelLine;
+            this.isFuelLine = this.part.HasModule<CModuleFuelLine>();
             this.isFuelTank = this.part is FuelTank;
             this.isSepratron = this.IsSepratron();
             this.inverseStage = this.part.inverseStage;
@@ -206,7 +210,8 @@
                                                             engine.throttleLocked,
                                                             engine.propellants,
                                                             engine.isOperational,
-                                                            correctThrust);
+                                                            correctThrust,
+                                                            engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
                 }
@@ -238,7 +243,8 @@
                                                             engine.throttleLocked,
                                                             engine.propellants,
                                                             engine.isOperational,
-                                                            correctThrust);
+                                                            correctThrust,
+                                                            engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
                 }
@@ -268,7 +274,8 @@
                                                             engine.throttleLocked,
                                                             engine.propellants,
                                                             engine.isOperational,
-                                                            correctThrust);
+                                                            correctThrust,
+                                                            engine.thrustTransforms);
                         allEngines.Add(engineSim);
                     }
                 }

--- a/KerbalEngineer/VesselSimulator/SimManager.cs
+++ b/KerbalEngineer/VesselSimulator/SimManager.cs
@@ -17,251 +17,187 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Reflection;
-using System.Threading;
-
-using UnityEngine;
-
-#endregion
-
 namespace KerbalEngineer.VesselSimulator
 {
+    #region Using Directives
+
+    using System;
+    using System.Diagnostics;
+    using System.Reflection;
+    using System.Threading;
+    using UnityEngine;
+
+    #endregion
+
     public class SimManager
     {
+        #region Constants
+
         public const double RESOURCE_MIN = 0.0001;
+
+        #endregion
+
+        #region Fields
+
+        public static bool dumpTree = false;
+        public static bool logOutput = false;
+        public static TimeSpan minSimTime = new TimeSpan(0, 0, 0, 0, 150);
+        public static bool vectoredThrust = false;
+        private static readonly object locker = new object();
+        private static readonly Stopwatch timer = new Stopwatch();
 
         private static bool bRequested;
         private static bool bRunning;
-        private static readonly Stopwatch timer = new Stopwatch();
-        private static long delayBetweenSims;
-
-        public static bool dumpTree = false;
-        public static bool logOutput = false;
-        public static bool vectoredThrust = false;
-        public static long minSimTime = 150;
+        private static TimeSpan delayBetweenSims;
 
         // Support for RealFuels using reflection to check localCorrectThrust without dependency
-        private static bool hasCheckedForRealFuels;
+
+        private static bool hasCheckedForMods;
         private static bool hasInstalledRealFuels;
-
-        private static FieldInfo RF_ModuleEngineConfigs_locaCorrectThrust;
-        private static FieldInfo RF_ModuleHybridEngine_locaCorrectThrust;
-        private static FieldInfo RF_ModuleHybridEngines_locaCorrectThrust;
+        private static FieldInfo RF_ModuleEngineConfigs_localCorrectThrust;
+        private static FieldInfo RF_ModuleHybridEngine_localCorrectThrust;
+        private static FieldInfo RF_ModuleHybridEngines_localCorrectThrust;
+        private static bool hasInstalledKIDS;
+        private static MethodInfo KIDS_Utils_GetIspMultiplier;
+        private static bool bKIDSThrustISP = false;
+        #endregion
+
+        #region Delegates
+
+        public delegate void ReadyEvent();
+
+        #endregion
+
+        #region Events
+
+        public static event ReadyEvent OnReady;
+
+        #endregion
+
+        #region Properties
+
+        public static double Atmosphere { get; set; }
+
+        public static double Gravity { get; set; }
+
+        public static Stage LastStage { get; private set; }
+
         public static Stage[] Stages { get; private set; }
-        public static Stage LastStage { get; private set; }
+
+        public static double Velocity { get; set; }
+
         public static String failMessage { get; private set; }
-        public static double Gravity { get; set; }
-        public static double Atmosphere { get; set; }
-        public static double Velocity { get; set; }
-
-        private static void GetRealFuelsTypes()
-        {
-            hasCheckedForRealFuels = true;
-
-            foreach (AssemblyLoader.LoadedAssembly assembly in AssemblyLoader.loadedAssemblies)
+
+        #endregion
+
+        #region Methods
+
+        private static void CheckForMods()
+        {
+            hasCheckedForMods = true;
+
+            foreach (var assembly in AssemblyLoader.loadedAssemblies)
             {
                 MonoBehaviour.print("Assembly:" + assembly.assembly);
 
-                if (assembly.assembly.ToString().Split(',')[0] == "RealFuels")
+                var name = assembly.assembly.ToString().Split(',')[0];
+
+                if (name == "RealFuels")
                 {
                     MonoBehaviour.print("Found RealFuels mod");
 
-                    Type RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");
+                    var RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");
                     if (RF_ModuleEngineConfigs_Type != null)
                     {
-                        RF_ModuleEngineConfigs_locaCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");
-                    }
-
-                    Type RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");
+                        RF_ModuleEngineConfigs_localCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");
+                    }
+
+                    var RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");
                     if (RF_ModuleHybridEngine_Type != null)
                     {
-                        RF_ModuleHybridEngine_locaCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");
-                    }
-
-                    Type RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");
+                        RF_ModuleHybridEngine_localCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");
+                    }
+
+                    var RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");
                     if (RF_ModuleHybridEngines_Type != null)
                     {
-                        RF_ModuleHybridEngines_locaCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");
+                        RF_ModuleHybridEngines_localCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");
                     }
 
                     hasInstalledRealFuels = true;
                     break;
                 }
+                else if (name == "KerbalIspDifficultyScaler")
+                {
+                    var KIDS_Utils_Type = assembly.assembly.GetType("KerbalIspDifficultyScaler.KerbalIspDifficultyScalerUtils");
+                    if (KIDS_Utils_Type != null)
+                    {
+                        KIDS_Utils_GetIspMultiplier = KIDS_Utils_Type.GetMethod("GetIspMultiplier");
+                    }
+
+                    hasInstalledKIDS = true;
+                }
             }
         }
 
         public static bool DoesEngineUseCorrectedThrust(Part theEngine)
         {
-            if (!hasInstalledRealFuels /*|| HighLogic.LoadedSceneIsFlight*/)
-            {
-                return false;
-            }
-
-            // Look for any of the Real Fuels engine modules and call the relevant method to find out
-            if (RF_ModuleEngineConfigs_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs"))
-            {
-                PartModule modEngineConfigs = theEngine.Modules["ModuleEngineConfigs"];
-                if (modEngineConfigs != null)
-                {
-                    // Check the localCorrectThrust
-                    if ((bool)RF_ModuleEngineConfigs_locaCorrectThrust.GetValue(modEngineConfigs))
-                    {
-                        return true;
-                    }
-                }
-            }
-
-            if (RF_ModuleHybridEngine_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngine"))
-            {
-                PartModule modHybridEngine = theEngine.Modules["ModuleHybridEngine"];
-                if (modHybridEngine != null)
-                {
-                    // Check the localCorrectThrust
-                    if ((bool)RF_ModuleHybridEngine_locaCorrectThrust.GetValue(modHybridEngine))
-                    {
-                        return true;
-                    }
-                }
-            }
-
-            if (RF_ModuleHybridEngines_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngines"))
-            {
-                PartModule modHybridEngines = theEngine.Modules["ModuleHybridEngines"];
-                if (modHybridEngines != null)
-                {
-                    // Check the localCorrectThrust
-                    if ((bool)RF_ModuleHybridEngines_locaCorrectThrust.GetValue(modHybridEngines))
-                    {
-                        return true;
-                    }
-                }
+            if (hasInstalledRealFuels)
+            {
+                // Look for any of the Real Fuels engine modules and call the relevant method to find out
+                if (RF_ModuleEngineConfigs_localCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs"))
+                {
+                    var modEngineConfigs = theEngine.Modules["ModuleEngineConfigs"];
+                    if (modEngineConfigs != null)
+                    {
+                        // Return the localCorrectThrust
+                        return (bool)RF_ModuleEngineConfigs_localCorrectThrust.GetValue(modEngineConfigs);
+                    }
+                }
+
+                if (RF_ModuleHybridEngine_localCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngine"))
+                {
+                    var modHybridEngine = theEngine.Modules["ModuleHybridEngine"];
+                    if (modHybridEngine != null)
+                    {
+                        // Return the localCorrectThrust
+                        return (bool)RF_ModuleHybridEngine_localCorrectThrust.GetValue(modHybridEngine);
+                    }
+                }
+
+                if (RF_ModuleHybridEngines_localCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngines"))
+                {
+                    var modHybridEngines = theEngine.Modules["ModuleHybridEngines"];
+                    if (modHybridEngines != null)
+                    {
+                        // Return the localCorrectThrust
+                        return (bool)RF_ModuleHybridEngines_localCorrectThrust.GetValue(modHybridEngines);
+                    }
+                }
+            }
+
+            if (hasInstalledKIDS && HighLogic.LoadedSceneIsEditor)
+            {
+                return bKIDSThrustISP;
             }
 
             return false;
         }
 
-        public static void RequestSimulation()
-        {
-            if (!hasCheckedForRealFuels)
-            {
-                GetRealFuelsTypes();
-            }
-
-            bRequested = true;
-            if (!timer.IsRunning)
-            {
-                timer.Start();
-            }
-        }
-
-        public static void TryStartSimulation()
-        {
-            if (bRequested && !bRunning && (HighLogic.LoadedSceneIsEditor || FlightGlobals.ActiveVessel != null) && timer.ElapsedMilliseconds > delayBetweenSims)
-            {
-                bRequested = false;
-                timer.Reset();
-                StartSimulation();
-            }
-        }
-
-        public static bool ResultsReady()
-        {
-            return !bRunning;
-        }
-
-        private static void ClearResults()
-        {
-            failMessage = "";
-            Stages = null;
-            LastStage = null;
-        }
-
-        private static void StartSimulation()
-        {
-            try
-            {
-                bRunning = true;
-                ClearResults();
-                timer.Start();
-
-                List<Part> parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.SortedShipList : FlightGlobals.ActiveVessel.Parts;
-
-                // Create the Simulation object in this thread
-                Simulation sim = new Simulation();
-
-                // 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);
-                }
-                else
-                {
-                    failMessage = "PrepareSimulation failed";
-                    bRunning = false;
-                    logOutput = false;
-                }
-            }
-            catch (Exception e)
-            {
-                MonoBehaviour.print("Exception in StartSimulation: " + e);
-                failMessage = e.ToString();
-                bRunning = false;
-                logOutput = false;
-            }
-            dumpTree = false;
-        }
-
-        private static void RunSimulation(object simObject)
-        {
-            try
-            {
-                Stages = (simObject as Simulation).RunSimulation();
-                if (Stages != null)
-                {
-                    if (logOutput)
-                    {
-                        foreach (Stage stage in Stages)
-                        {
-                            stage.Dump();
-                        }
-                    }
-                    LastStage = Stages.Last();
-                }
-            }
-            catch (Exception e)
-            {
-                MonoBehaviour.print("Exception in RunSimulation: " + e);
-                Stages = null;
-                LastStage = null;
-                failMessage = e.ToString();
-            }
-
-            timer.Stop();
-#if TIMERS
-            MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
-#else
-            if (logOutput)
-            {
-                MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
-            }
-#endif
-            delayBetweenSims = minSimTime - timer.ElapsedMilliseconds;
-            if (delayBetweenSims < 0)
-            {
-                delayBetweenSims = 0;
-            }
-
-            timer.Reset();
-            timer.Start();
-
-            bRunning = false;
-            logOutput = false;
+        public static void UpdateModSettings()
+        {
+            if (!hasCheckedForMods)
+            {
+                CheckForMods();
+            }
+
+            if (hasInstalledKIDS)
+            {
+                // (out ispMultiplierVac, out ispMultiplierAtm, out extendToZeroIsp, out thrustCorrection, out ispCutoff, out thrustCutoff);
+                object[] parameters = new object[6];
+                KIDS_Utils_GetIspMultiplier.Invoke(null, parameters);
+                bKIDSThrustISP = (bool)parameters[3];
+            }
         }
 
         public static String GetVesselTypeString(VesselType vesselType)
@@ -293,5 +229,161 @@
             }
             return "Undefined";
         }
+
+        public static void RequestSimulation()
+        {
+            if (!hasCheckedForMods)
+            {
+                CheckForMods();
+            }
+
+            lock (locker)
+            {
+                bRequested = true;
+                if (!timer.IsRunning)
+                {
+                    timer.Start();
+                }
+            }
+        }
+
+        public static bool ResultsReady()
+        {
+            lock (locker)
+            {
+                return !bRunning;
+            }
+        }
+
+        public static void TryStartSimulation()
+        {
+            lock (locker)
+            {
+                if (!bRequested || bRunning || (timer.Elapsed < delayBetweenSims && timer.Elapsed >= TimeSpan.Zero) || (!HighLogic.LoadedSceneIsEditor && FlightGlobals.ActiveVessel == null))
+                {
+                    return;
+                }
+
+                bRequested = false;
+                timer.Reset();
+            }
+
+            StartSimulation();
+        }
+
+        private static void ClearResults()
+        {
+            failMessage = "";
+            Stages = null;
+            LastStage = null;
+        }
+
+        private static void RunSimulation(object simObject)
+        {
+            try
+            {
+                Stages = (simObject as Simulation).RunSimulation();
+                if (Stages != null && Stages.Length > 0)
+                {
+                    if (logOutput)
+                    {
+                        foreach (var stage in Stages)
+                        {
+                            stage.Dump();
+                        }
+                    }
+                    LastStage = Stages[Stages.Length - 1];
+                }
+            }
+            catch (Exception e)
+            {
+                MonoBehaviour.print("Exception in RunSimulation: " + e);
+                Logger.Exception(e);
+                Stages = null;
+                LastStage = null;
+                failMessage = e.ToString();
+            }
+            lock (locker)
+            {
+                timer.Stop();
+#if TIMERS
+            MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
+#else
+                if (logOutput)
+                {
+                    MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
+                }
+#endif
+
+                delayBetweenSims = minSimTime - timer.Elapsed;
+                if (delayBetweenSims < TimeSpan.Zero)
+                {
+                    delayBetweenSims = TimeSpan.Zero;
+                }
+
+                timer.Reset();
+                timer.Start();
+
+                bRunning = false;
+                if (OnReady != null)
+                {
+                    OnReady();
+                }
+            }
+
+            logOutput = false;
+        }
+
+        private static void StartSimulation()
+        {
+            try
+            {
+                lock (locker)
+                {
+                    bRunning = true;
+                }
+
+                ClearResults();
+
+                lock (locker)
+                {
+                    timer.Start();
+                }
+
+                var parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.ship.parts : FlightGlobals.ActiveVessel.Parts;
+
+                // Create the Simulation object in this thread
+                var sim = new Simulation();
+
+                // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
+                if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Velocity, dumpTree, vectoredThrust))
+                {
+                    ThreadPool.QueueUserWorkItem(RunSimulation, sim);
+                }
+                else
+                {
+                    failMessage = "PrepareSimulation failed";
+                    lock (locker)
+                    {
+                        bRunning = false;
+                    }
+                    logOutput = false;
+                }
+            }
+            catch (Exception e)
+            {
+                MonoBehaviour.print("Exception in StartSimulation: " + e);
+                Logger.Exception(e);
+                failMessage = e.ToString();
+                lock (locker)
+                {
+                    bRunning = false;
+                }
+                logOutput = false;
+            }
+            dumpTree = false;
+        }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -30,9 +30,12 @@
 
 namespace KerbalEngineer.VesselSimulator
 {
+    using CompoundParts;
+    using Extensions;
+
     public class Simulation
     {
-        private const double STD_GRAVITY = 9.8066;
+        private const double STD_GRAVITY = 9.82;
         private const double SECONDS_PER_DAY = 86400;
         private readonly Stopwatch _timer = new Stopwatch();
         private List<EngineSim> activeEngines;
@@ -52,6 +55,7 @@
         private List<Part> partList;
         private double simpleTotalThrust;
         private double stageStartMass;
+        private Vector3d stageStartCom;
         private double stageTime;
         private double stepEndMass;
         private double stepStartMass;
@@ -59,6 +63,7 @@
         private double totalStageFlowRate;
         private double totalStageIspFlowRate;
         private double totalStageThrust;
+        private ForceAccumulator totalStageThrustForce;
         private Vector3 vecActualThrust;
         private Vector3 vecStageDeltaV;
         private Vector3 vecThrust;
@@ -74,7 +79,7 @@
             }
         }
 
-        private double ShipStartMass
+        private double ShipMass
         {
             get
             {
@@ -82,25 +87,25 @@
 
                 foreach (PartSim partSim in this.allParts)
                 {
-                    mass += partSim.GetStartMass();
+                    mass += partSim.GetMass();
                 }
 
                 return mass;
             }
         }
 
-        private double ShipMass
+        private Vector3d ShipCom
         {
             get
             {
-                double mass = 0d;
+                WeightedVectorAverager averager = new WeightedVectorAverager();
 
                 foreach (PartSim partSim in this.allParts)
                 {
-                    mass += partSim.GetMass();
-                }
-
-                return mass;
+                    averager.Add(partSim.centerOfMass, partSim.GetMass());
+                }
+
+                return averager.Get();
             }
         }
 
@@ -190,10 +195,11 @@
             {
                 foreach (PartSim partSim in this.allFuelLines)
                 {
-                    if ((partSim.part as FuelLine).target != null)
+                    CModuleFuelLine fuelLine = partSim.part.GetModule<CModuleFuelLine>();
+                    if (fuelLine.target != null)
                     {
                         PartSim targetSim;
-                        if (partSimLookup.TryGetValue((partSim.part as FuelLine).target, out targetSim))
+                        if (partSimLookup.TryGetValue(fuelLine.target, out targetSim))
                         {
                             if (log != null)
                             {
@@ -262,6 +268,7 @@
             {
                 MonoBehaviour.print("RunSimulation started");
             }
+
             this._timer.Start();
 
             LogMsg log = null;
@@ -365,7 +372,10 @@
 
                 this.stageTime = 0d;
                 this.vecStageDeltaV = Vector3.zero;
+
                 this.stageStartMass = this.ShipMass;
+                this.stageStartCom = this.ShipCom;
+
                 this.stepStartMass = this.stageStartMass;
                 this.stepEndMass = 0;
 
@@ -381,6 +391,27 @@
                 stage.actualThrust = this.totalStageActualThrust;
                 stage.actualThrustToWeight = this.totalStageActualThrust / (this.stageStartMass * this.gravity);
 
+                // calculate torque and associates
+                stage.maxThrustTorque = this.totalStageThrustForce.TorqueAt(this.stageStartCom).magnitude;
+
+                // torque divided by thrust. imagine that all engines are at the end of a lever that tries to turn the ship.
+                // this numerical value, in meters, would represent the length of that lever.
+                double torqueLeverArmLength = (stage.thrust <= 0) ? 0 : stage.maxThrustTorque / stage.thrust;
+
+                // how far away are the engines from the CoM, actually?
+                double thrustDistance = (this.stageStartCom - this.totalStageThrustForce.GetAverageForceApplicationPoint()).magnitude;
+
+                // the combination of the above two values gives an approximation of the offset angle.
+                double sinThrustOffsetAngle = 0;
+                if (thrustDistance > 1e-7) {
+                    sinThrustOffsetAngle = torqueLeverArmLength / thrustDistance;
+                    if (sinThrustOffsetAngle > 1) {
+                        sinThrustOffsetAngle = 1;
+                    }
+                }
+
+                stage.thrustOffsetAngle = Math.Asin(sinThrustOffsetAngle) * 180 / Math.PI;
+
                 // 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)
@@ -485,6 +516,10 @@
                         MonoBehaviour.print("stageStartMass = " + this.stageStartMass);
                         MonoBehaviour.print("stepStartMass = " + this.stepStartMass);
                         MonoBehaviour.print("StepEndMass   = " + this.stepEndMass);
+                        Logger.Log("exceeded loop count");
+                        Logger.Log("stageStartMass = " + this.stageStartMass);
+                        Logger.Log("stepStartMass = " + this.stepStartMass);
+                        Logger.Log("StepEndMass   = " + this.stepEndMass);
                         break;
                     }
 
@@ -644,6 +679,7 @@
             this.totalStageActualThrust = 0d;
             this.totalStageFlowRate = 0d;
             this.totalStageIspFlowRate = 0d;
+            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
@@ -655,6 +691,10 @@
 
                 this.totalStageFlowRate += engine.ResourceConsumptions.Mass;
                 this.totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp;
+
+                foreach (AppliedForce f in engine.appliedForces) {
+                    this.totalStageThrustForce.AddForce(f);
+                }
             }
 
             //MonoBehaviour.print("vecThrust = " + vecThrust.ToString() + "   magnitude = " + vecThrust.magnitude);
@@ -750,7 +790,6 @@
                             partSim.DumpPartToBuffer(buffer, "Decoupled part not empty => false: ");
                             MonoBehaviour.print(buffer);
                         }
-
                         return false;
                     }
 

--- a/KerbalEngineer/VesselSimulator/Stage.cs
+++ b/KerbalEngineer/VesselSimulator/Stage.cs
@@ -29,25 +29,28 @@
 {
     public class Stage
     {
-        public double actualThrust = 0f;
-        public double actualThrustToWeight = 0f;
-        public double cost = 0d;
-        public double deltaV = 0f;
-        public double inverseTotalDeltaV = 0f;
-        public double isp = 0f;
-        public double mass = 0f;
-        public double maxThrustToWeight = 0f;
+        public double actualThrust = 0.0;
+        public double actualThrustToWeight = 0.0;
+        public double cost = 0.0;
+        public double deltaV = 0.0;
+        public double inverseTotalDeltaV = 0.0;
+        public double isp = 0.0;
+        public double mass = 0.0;
+        public double rcsMass = 0.0;
+        public double maxThrustToWeight = 0.0;
         public int number = 0;
-        public double thrust = 0f;
-        public double thrustToWeight = 0f;
-        public double time = 0f;
-        public double totalCost = 0;
-        public double totalDeltaV = 0f;
-        public double totalMass = 0f;
-        public double totalTime = 0f;
+        public double thrust = 0.0;
+        public double thrustToWeight = 0.0;
+        public double time = 0.0;
+        public double totalCost = 0.0;
+        public double totalDeltaV = 0.0;
+        public double totalMass = 0.0;
+        public double totalTime = 0.0;
         public int totalPartCount = 0;
         public int partCount = 0;
         public double resourceMass = 0.0;
+        public double maxThrustTorque = 0.0;
+        public double thrustOffsetAngle = 0.0;
 
         public void Dump()
         {
@@ -65,6 +68,8 @@
             str.AppendFormat("thrustToWeight: {0:g6}\n", this.thrustToWeight);
             str.AppendFormat("maxTWR        : {0:g6}\n", this.maxThrustToWeight);
             str.AppendFormat("actualTWR     : {0:g6}\n", this.actualThrustToWeight);
+            str.AppendFormat("ThrustTorque  : {0:g6}\n", this.maxThrustTorque);
+            str.AppendFormat("ThrustOffset  : {0:g6}\n", this.thrustOffsetAngle);
             str.AppendFormat("deltaV        : {0:g6}\n", this.deltaV);
             str.AppendFormat("totalDeltaV   : {0:g6}\n", this.totalDeltaV);
             str.AppendFormat("invTotDeltaV  : {0:g6}\n", this.inverseTotalDeltaV);

 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":11,
-		"BUILD":2
+		"PATCH":14,
+		"BUILD":1
 	},
 	"KSP_VERSION":
 	{
 		"MAJOR":0,
-		"MINOR":25,
+		"MINOR":90,
 		"PATCH":0
 	}
 }

 Binary files /dev/null and b/Output/KerbalEngineer/Parts/Engineer7500/model000.mbm differ
--- a/Output/KerbalEngineer/Parts/Engineer7500/part.cfg
+++ b/Output/KerbalEngineer/Parts/Engineer7500/part.cfg
@@ -7,7 +7,6 @@
 	
 	// --- asset parameters ---
 	mesh = model.mu
-	texture = model000.mbm
 	rescaleFactor = 0.8
 
 	PhysicsSignificance = 1

 Binary files a/Output/KerbalEngineer/Parts/Engineer7500/textures/model000.mbm and /dev/null differ