Fixed longitude to correctly clamp to 180°.
Fixed longitude to correctly clamp to 180°.

--- a/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
@@ -17,35 +17,25 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using KerbalEngineer.Flight.Sections;
-
-#endregion
-
 namespace KerbalEngineer.Flight.Readouts.Surface
 {
+    using Helpers;
+    using Sections;
+
     public class Longitude : ReadoutModule
     {
-        #region Constructors
-
         public Longitude()
         {
-            this.Name = "Longitude";
-            this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = "Shows the vessel's longitude around a celestial body.  Longitude is the angle from the bodies prime meridian.";
-            this.IsDefault = true;
+            Name = "Longitude";
+            Category = ReadoutCategory.GetCategory("Surface");
+            HelpString = "Shows the vessel's longitude around a celestial body.  Longitude is the angle from the bodies prime meridian.";
+            IsDefault = true;
         }
-
-        #endregion
-
-        #region Methods: public
 
         public override void Draw(SectionModule section)
         {
-            this.DrawLine(KSPUtil.PrintLongitude(FlightGlobals.ship_longitude), section.IsHud);
+            double angle = AngleHelper.Clamp180(FlightGlobals.ship_longitude);
+            DrawLine(Units.ToAngleDMS(angle) + (angle < 0.0 ? "W" : " E"), section.IsHud);
         }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/Helpers/AngleHelper.cs
+++ b/KerbalEngineer/Helpers/AngleHelper.cs
@@ -17,21 +17,30 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using UnityEngine;
-
-#endregion
-
 namespace KerbalEngineer.Helpers
 {
+    using UnityEngine;
+
     public static class AngleHelper
     {
-        #region Methods: public
+        public static double Clamp180(double angle)
+        {
+            angle = Clamp360(angle);
+            if (angle > 180.0)
+            {
+                angle = angle - 360.0;
+            }
+            return angle;
+        }
 
-        public static double Clamp360(double value)
+        public static double Clamp360(double angle)
         {
-            return ClampBetween(value, 0.0, 360.0);
+            angle = angle % 360.0;
+            if (angle < 0.0)
+            {
+                angle = angle + 360.0;
+            }
+            return angle;
         }
 
         public static double ClampBetween(double value, double minimum, double maximum)
@@ -51,8 +60,8 @@
 
         public static double GetAngleBetweenVectors(Vector3d left, Vector3d right)
         {
-            var angle = Vector3d.Angle(left, right);
-            var rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * right;
+            double angle = Vector3d.Angle(left, right);
+            Vector3d rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * right;
 
             if (Vector3d.Angle(rotated, left) > 90.0)
             {
@@ -60,7 +69,5 @@
             }
             return angle;
         }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -208,8 +208,7 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="Assembly-CSharp">
-      <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
     </Reference>
     <Reference Include="System">
       <HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath>
@@ -220,8 +219,7 @@
       <Private>False</Private>
     </Reference>
     <Reference Include="UnityEngine">
-      <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\UnityEngine.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup />

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -86,11 +86,10 @@
                          List<Propellant> propellants,
                          bool active,
                          float resultingThrust,
-                         List<Transform> thrustTransforms)
+                         List<Transform> thrustTransforms,
+                        LogMsg log)
         {
             EngineSim engineSim = pool.Borrow();
-
-            StringBuilder buffer = null;
 
             engineSim.isp = 0.0;
             engineSim.maxMach = 0.0f;
@@ -133,11 +132,7 @@
                 flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
             }
 
-            if (SimManager.logOutput)
-            {
-                buffer = new StringBuilder(1024);
-                buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
-            }
+            if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);
 
             engineSim.thrust = flowRate * (engineSim.isp * IspG);
             // I did not look into the diff between those 2 so I made them equal...
@@ -150,10 +145,7 @@
                 flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
             }
 
-            if (SimManager.logOutput)
-            {
-                buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
-            }
+            if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);
 
             for (int i = 0; i < propellants.Count; ++i)
             {
@@ -165,21 +157,13 @@
                 }
 
                 double consumptionRate = propellant.ratio * flowRate / flowMass;
-                if (SimManager.logOutput)
-                {
-                    buffer.AppendFormat(
+                if (log != null) log.buf.AppendFormat(
                         "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
                         ResourceContainer.GetResourceName(propellant.id),
                         theEngine.name,
                         theEngine.partId,
                         consumptionRate);
-                }
                 engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
-            }
-
-            if (SimManager.logOutput)
-            {
-                MonoBehaviour.print(buffer);
             }
 
             double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -34,7 +34,9 @@
 
         private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
 
+        public double realMass;
         public double baseMass;
+        public double baseMassForCoM;
         public Vector3d centerOfMass;
         public double cost;
         public int decoupledInStage;
@@ -89,6 +91,7 @@
             partSim.resourceFlowStates.Reset();
             partSim.resources.Reset();
             partSim.baseMass = 0d;
+            partSim.baseMassForCoM = 0d;
             partSim.startMass = 0d;
         }
 
@@ -100,15 +103,13 @@
         public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log)
         {
             PartSim partSim = pool.Borrow();
-
 
             partSim.part = thePart;
             partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
             partSim.partId = id;
             partSim.name = partSim.part.partInfo.name;
 
-            if (log != null)
-                log.buf.AppendLine("Create PartSim for " + partSim.name);
+            if (log != null) log.buf.AppendLine("Create PartSim for " + partSim.name);
 
             partSim.parent = null;
             partSim.parentAttach = partSim.part.attachMode;
@@ -123,20 +124,27 @@
 
             partSim.cost = partSim.part.GetCostWet();
 
+            if (log != null)
+            {
+                log.buf.AppendLine("Parent part = " + (partSim.part.parent == null ? "null" : partSim.part.parent.partInfo.name));
+                log.buf.AppendLine("physicalSignificance = " + partSim.part.physicalSignificance);
+                log.buf.AppendLine("PhysicsSignificance = " + partSim.part.PhysicsSignificance);
+            }
+
             // Work out if the part should have no physical significance
+            // The root part is never "no physics"
             partSim.isNoPhysics = partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
-                               partSim.part.PhysicsSignificance == 1;
+                                    partSim.part.PhysicsSignificance == 1;
 
             if (partSim.part.HasModule<LaunchClamp>())
             {
-                if (log != null)
-                  log.buf.AppendLine("Ignoring mass of launch clamp");
+                partSim.realMass = 0d;
+                if (log != null) log.buf.AppendLine("Ignoring mass of launch clamp");
             }
             else
             {
-                partSim.baseMass = partSim.part.mass;
-                if (log != null)
-                    log.buf.AppendLine("Using part.mass of " + partSim.part.mass);
+                partSim.realMass = partSim.part.mass;
+                if (log != null) log.buf.AppendLine("Using part.mass of " + partSim.part.mass);
             }
 
             for (int i = 0; i < partSim.part.Resources.Count; i++)
@@ -155,12 +163,9 @@
                 }
                 else
                 {
-                    if (log != null)
-                        log.buf.AppendLine(resource.resourceName + " is NaN. Skipping.");
-                }
-            }
-
-            partSim.startMass = partSim.GetMass(-1);
+                    if (log != null) log.buf.AppendLine(resource.resourceName + " is NaN. Skipping.");
+                }
+            }
 
             partSim.hasVessel = (partSim.part.vessel != null);
             partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed;
@@ -177,8 +182,7 @@
 
             partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines;
 
-            if (log != null)
-                log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
+            if (log != null) log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
 
             return partSim;
         }
@@ -226,10 +230,7 @@
                     ModuleEnginesFX engine = engines[i];
                     if (engine.engineID == mode)
                     {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Module: " + engine.moduleName);
-                        }
+                        if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
@@ -251,7 +252,8 @@
                             engine.propellants,
                             engine.isOperational,
                             engine.resultingThrust,
-                            engine.thrustTransforms);
+                            engine.thrustTransforms,
+                            log);
                         allEngines.Add(engineSim);
                     }
                 }
@@ -264,10 +266,7 @@
                     for (int i = 0; i < engines.Count; ++i)
                     {
                         ModuleEngines engine = engines[i];
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Module: " + engine.moduleName);
-                        }
+                        if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
@@ -289,7 +288,8 @@
                             engine.propellants,
                             engine.isOperational,
                             engine.resultingThrust,
-                            engine.thrustTransforms);
+                            engine.thrustTransforms,
+                            log);
                         allEngines.Add(engineSim);
                     }
                 }
@@ -348,9 +348,13 @@
             buffer.Append(name);
             buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", partId, decoupledInStage, inverseStage);
 
-            buffer.AppendFormat(", vesselName = '{0}'", vesselName);
-            buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
-            buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
+            //buffer.AppendFormat(", vesselName = '{0}'", vesselName);
+            //buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
+            //buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
+
+            buffer.AppendFormat(", isNoPhys = {0}", isNoPhysics);
+            buffer.AppendFormat(", baseMass = {0}", baseMass);
+            buffer.AppendFormat(", baseMassForCoM = {0}", baseMassForCoM);
 
             buffer.AppendFormat(", fuelCF = {0}", fuelCrossFeed);
             buffer.AppendFormat(", noCFNKey = '{0}'", noCrossFeedNodeKey);
@@ -386,9 +390,7 @@
                 {
                     PartSim partSim = allParts[i];
                     if (partSim.parent == this)
-                    {
                         partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
-                    }
                 }
             }
         }
@@ -398,17 +400,15 @@
             foreach (int type in types)
             {
                 if (resources.HasType(type) && resourceFlowStates[type] != 0 && resources[type] > SimManager.RESOURCE_PART_EMPTY_THRESH)
-                {
                     return false;
-                }
             }
 
             return true;
         }
 
-        public double GetMass(int currentStage)
-        {
-            double mass = baseMass;
+        public double GetMass(int currentStage, bool forCoM = false)
+        {
+            double mass = forCoM ? baseMassForCoM : baseMass;
 
             for (int i = 0; i < resources.Types.Count; ++i)
             {
@@ -442,14 +442,11 @@
             // Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns as is.
             if (visited.Contains(this))
             {
-                if (log != null)
-                    log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
-
+                if (log != null) log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
                 return;
             }
 
-            if (log != null)
-                log.buf.AppendLine(indent + "Adding this to visited");
+            if (log != null) log.buf.AppendLine(indent + "Adding this to visited");
 
             visited.Add(this);
 
@@ -466,13 +463,11 @@
                 {
                     if (visited.Contains(partSim))
                     {
-                        if (log != null)
-                            log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
+                        if (log != null) log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
                     }
                     else
                     {
-                        if (log != null)
-                            log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
+                        if (log != null) log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
 
                         partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
                     }
@@ -481,9 +476,7 @@
 
             if (allSources.Count > lastCount)
             {
-                if (log != null)
-                    log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
-
+                if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
                 return;
             }
 
@@ -512,13 +505,11 @@
                             {
                                 if (visited.Contains(attachSim.attachedPartSim))
                                 {
-                                    if (log != null)
-                                        log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
+                                    if (log != null) log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
                                 }
                                 else
                                 {
-                                    if (log != null)
-                                        log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
+                                    if (log != null) log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
 
                                     attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
                                 }
@@ -529,9 +520,7 @@
 
                 if (allSources.Count > lastCount)
                 {
-                    if (log != null)
-                        log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
-
+                    if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
                     return;
                 }
             }
@@ -546,16 +535,14 @@
                 {
                     allSources.Add(this);
 
-                    if (log != null)
-                        log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
+                    if (log != null) log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
                 }
 
                 return;
             }
             else
             {
-                if (log != null)
-                    log.buf.AppendLine(indent + "Not fuel tank or disabled. HasType = " + resources.HasType(type) + "  FlowState = " + resourceFlowStates[type]);
+                if (log != null) log.buf.AppendLine(indent + "Not fuel tank or disabled. HasType = " + resources.HasType(type) + "  FlowState = " + resourceFlowStates[type]);
             }
 
             // Rule 7: If the part is radially attached to another part and it is child of that part in the ship's tree structure, it scans its 
@@ -566,8 +553,7 @@
                 {
                     if (visited.Contains(parent))
                     {
-                        if (log != null)
-                            log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
+                        if (log != null) log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
                     }
                     else
                     {
@@ -575,9 +561,7 @@
                         this.parent.GetSourceSet(type, allParts, visited, allSources, log, indent);
                         if (allSources.Count > lastCount)
                         {
-                            if (log != null)
-                                log.buf.AppendLine(indent + "Returning " + (allSources.Count  - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
-
+                            if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count  - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
                             return;
                         }
                     }
@@ -585,8 +569,7 @@
             }
 
             // Rule 8: If all preceding rules failed, part returns empty list.
-            if (log != null)
-                log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
+            if (log != null) log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
 
             return;
         }
@@ -623,10 +606,7 @@
 
         public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
         {
-            if (log != null)
-            {
-                log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
-            }
+            if (log != null) log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
 
             attachNodes.Clear();
 
@@ -634,29 +614,20 @@
             {
                 AttachNode attachNode = part.attachNodes[i];
 
-                if (log != null)
-                {
-                    log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
-                }
+                if (log != null) log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
 
                 if (attachNode.attachedPart != null && attachNode.id != "Strut")
                 {
                     PartSim attachedSim;
                     if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim))
                     {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
-                        }
+                        if (log != null) log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
 
                         attachNodes.Add(AttachNodeSim.New(attachedSim, attachNode.id, attachNode.nodeType));
                     }
                     else
                     {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
-                        }
+                        if (log != null) log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
                     }
                 }
             }
@@ -670,34 +641,15 @@
                     PartSim targetSim;
                     if (partSimLookup.TryGetValue(p, out targetSim))
                     {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
-                        }
+                        if (log != null) log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
 
                         fuelTargets.Add(targetSim);
                     }
                     else
                     {
-                        if (log != null)
-                        {
-                            log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
-                        }
-                    }
-                }
-            }
-
-            if (isNoPhysics)
-            {
-                if (log != null)
-                    log.buf.AppendLine("Moving NoPhysics part mass of " + this.baseMass + " to parent part");
-
-                // Apply this part's mass to the part we have found
-                if (parent != null && !parent.isNoPhysics)
-                    parent.baseMass += this.baseMass;
-
-                // And zero out this part's mass regardless of whether the mass was added to the parent
-                this.baseMass = 0;
+                        if (log != null) log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
+                    }
+                }
             }
         }
 
@@ -708,13 +660,11 @@
                 parent = null;
                 if (partSimLookup.TryGetValue(part.parent, out parent))
                 {
-                    if (log != null)
-                        log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
+                    if (log != null) log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
                 }
                 else
                 {
-                    if (log != null)
-                        log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
+                    if (log != null) log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
                 }
             }
         }
@@ -752,43 +702,27 @@
             {
                 Transform trans = thrustTransforms[i];
 
-                if (log != null)
-                {
-                    log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
-                }
+                if (log != null) log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
 
                 thrustvec -= trans.forward;
             }
 
-            if (log != null)
-            {
-                log.buf.AppendFormat("ThrustVec  = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
-            }
+            if (log != null) log.buf.AppendFormat("ThrustVec  = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
 
             thrustvec.Normalize();
 
-            if (log != null)
-            {
-                log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
-            }
+            if (log != null) log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
 
             return thrustvec;
         }
 
         private int DecoupledInStage(Part thePart, int stage = -1)
         {
-            if (IsDecoupler(thePart))
-            {
-                if (thePart.inverseStage > stage)
-                {
-                    stage = thePart.inverseStage;
-                }
-            }
+            if (IsDecoupler(thePart) && thePart.inverseStage > stage)
+                stage = thePart.inverseStage;
 
             if (thePart.parent != null)
-            {
                 stage = DecoupledInStage(thePart.parent, stage);
-            }
 
             return stage;
         }

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -119,7 +119,7 @@
                 for (int i = 0; i < allParts.Count; ++i)
                 {
                     PartSim partSim = allParts[i];
-                    vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage));
+                    vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage, true));
                 }
 
                 return vectorAverager.Get();
@@ -394,6 +394,12 @@
                     this._timer.Start();
                 }
 
+                // Update the masses of the parts to correctly handle "no physics" parts
+                this.UpdatePartMasses();
+
+                if (log != null)
+                    this.allParts[0].DumpPartToBuffer(log.buf, "", this.allParts);
+
                 // Update active engines and resource drains
                 this.UpdateResourceDrains();
 
@@ -413,11 +419,11 @@
 
                 // Store various things in the Stage object
                 stage.thrust = this.totalStageThrust;
-                //MonoBehaviour.print("stage.thrust = " + stage.thrust);
+                if (log != null) log.buf.AppendLine("stage.thrust = " + stage.thrust);
                 stage.thrustToWeight = this.totalStageThrust / (this.stageStartMass * this.gravity);
                 stage.maxThrustToWeight = stage.thrustToWeight;
-                //MonoBehaviour.print("StageMass = " + stageStartMass);
-                //MonoBehaviour.print("Initial maxTWR = " + stage.maxThrustToWeight);
+                if (log != null) log.buf.AppendLine("StageMass = " + stageStartMass);
+                if (log != null) log.buf.AppendLine("Initial maxTWR = " + stage.maxThrustToWeight);
                 stage.actualThrust = this.totalStageActualThrust;
                 stage.actualThrustToWeight = this.totalStageActualThrust / (this.stageStartMass * this.gravity);
 
@@ -650,6 +656,40 @@
             return stages;
         }
 
+        public void UpdatePartMasses()
+        {
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                this.allParts[i].baseMass = this.allParts[i].realMass;
+                this.allParts[i].baseMassForCoM = this.allParts[i].realMass;
+            }
+
+            for (int i = 0; i < this.allParts.Count; i++)
+            {
+                PartSim part = this.allParts[i];
+                // If the part has a parent
+                if (part.parent != null)
+                {
+                    if (part.isNoPhysics)
+                    {
+                        if (part.parent.isNoPhysics && part.parent.parent != null)
+                        {
+                            part.baseMass = 0d;
+                            part.baseMassForCoM = 0d;
+                        }
+                        else
+                        {
+                            part.parent.baseMassForCoM += part.baseMassForCoM;
+                            part.baseMassForCoM = 0d;
+                        }
+                    }
+                }
+            }
+
+            for (int i = 0; i < this.allParts.Count; i++)
+                this.allParts[i].startMass = this.allParts[i].GetMass(currentStage);
+        }
+
         // Make sure we free them all, even if they should all be free already at this point
         public void FreePooledObject()
         {

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ