Fixed resource costs and costs with tweakscale.
Fixed resource costs and costs with tweakscale.

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -389,7 +389,7 @@
             {
                 if (this.showAllStages || stage.deltaV > 0)
                 {
-                    GUILayout.Label(stage.cost.ToString("N0") + " / " + stage.totalCost.ToString("N0"), this.infoStyle);
+                    GUILayout.Label(Units.Concat(stage.cost, stage.totalCost), this.infoStyle);
                 }
             }
             GUILayout.EndVertical();

--- a/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
+++ b/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
@@ -118,7 +118,7 @@
                         return;
                     }
 
-                    this.infoItems.Add(new PartInfoItem("Cost", this.selectedPart.partInfo.cost.ToString("N0")));
+                    this.SetCostInfo();
                     this.SetMassItems();
                     this.SetResourceItems();
                     this.SetEngineInfo();
@@ -182,6 +182,11 @@
             }
         }
 
+        private void SetCostInfo()
+        {
+            this.infoItems.Add(new PartInfoItem("Cost", Units.Concat(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet())));
+        }
+
         private void SetDecouplerInfo()
         {
             if (!this.selectedPart.IsDecoupler())

--- a/KerbalEngineer/Editor/BuildOverlayResources.cs
+++ b/KerbalEngineer/Editor/BuildOverlayResources.cs
@@ -67,7 +67,10 @@
                 }
 
                 this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
-                this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.Window, String.Empty, BuildOverlay.WindowStyle);
+                if (this.openPercent > 0.0)
+                {
+                    this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.Window, String.Empty, BuildOverlay.WindowStyle);
+                }
             }
             catch (Exception ex)
             {
@@ -97,40 +100,8 @@
                     return;
                 }
 
-                var previousCount = this.resources.Count;
-                this.resources.Clear();
-                foreach (var resource in EditorLogic.fetch.ship.parts.SelectMany(p => p.Resources.list).Where(r => r.amount > 0.0))
-                {
-                    if (this.resources.ContainsKey(resource.info.id))
-                    {
-                        this.resources[resource.info.id].Amount += resource.amount;
-                    }
-                    else
-                    {
-                        this.resources.Add(resource.info.id, new ResourceInfoItem(resource));
-                    }
-                }
-
-                if (this.resources.Count < previousCount)
-                {
-                    this.windowPosition.height = 0;
-                }
-
-                if (this.open && this.openPercent < 1.0f)
-                {
-                    this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
-                }
-                else if (!this.open && this.openPercent > 0.0f)
-                {
-                    this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
-                }
-
-                this.windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f;
-                this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
-                this.tabPosition.width = this.tabSize.x;
-                this.tabPosition.height = this.tabSize.y;
-                this.tabPosition.x = this.windowPosition.x;
-                this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
+                this.SetResources();
+                this.SetSlidePosition();
             }
             catch (Exception ex)
             {
@@ -141,6 +112,47 @@
         #endregion
 
         #region Methods: private
+
+        private void SetResources()
+        {
+            var previousCount = this.resources.Count;
+            this.resources.Clear();
+            foreach (var resource in EditorLogic.fetch.ship.parts.SelectMany(p => p.Resources.list).Where(r => r.amount > 0.0))
+            {
+                if (this.resources.ContainsKey(resource.info.id))
+                {
+                    this.resources[resource.info.id].Amount += resource.amount;
+                }
+                else
+                {
+                    this.resources.Add(resource.info.id, new ResourceInfoItem(resource));
+                }
+            }
+
+            if (this.resources.Count < previousCount)
+            {
+                this.windowPosition.height = 0;
+            }
+        }
+
+        private void SetSlidePosition()
+        {
+            if (this.open && this.openPercent < 1.0f)
+            {
+                this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+            }
+            else if (!this.open && this.openPercent > 0.0f)
+            {
+                this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+            }
+
+            this.windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f;
+            this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
+            this.tabPosition.width = this.tabSize.x;
+            this.tabPosition.height = this.tabSize.y;
+            this.tabPosition.x = this.windowPosition.x;
+            this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
+        }
 
         private void Window(int windowId)
         {

--- a/KerbalEngineer/Editor/BuildOverlayVessel.cs
+++ b/KerbalEngineer/Editor/BuildOverlayVessel.cs
@@ -74,7 +74,10 @@
                 }
 
                 this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
-                this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle);
+                if (this.openPercent > 0.0)
+                {
+                    this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle);
+                }
             }
             catch (Exception ex)
             {
@@ -102,6 +105,20 @@
                 return;
             }
 
+            if (this.openPercent > 0.0)
+            {
+                this.SetVesselInfo();
+            }
+
+            this.SetSlidePosition();
+        }
+
+        #endregion
+
+        #region Methods: private
+
+        private void SetSlidePosition()
+        {
             if (this.open && this.openPercent < 1.0f)
             {
                 this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
@@ -116,7 +133,10 @@
             this.tabPosition.height = this.tabSize.y;
             this.tabPosition.x = this.windowPosition.x;
             this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
-
+        }
+
+        private void SetVesselInfo()
+        {
             SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
 
             if (BuildAdvanced.Instance.ShowAtmosphericDetails)
@@ -145,10 +165,6 @@
                 this.infoItems.Add(new PartInfoItem("Parts", this.lastStage.partCount.ToString("N0")));
             }
         }
-
-        #endregion
-
-        #region Methods: private
 
         private void VesselWindow(int windowId)
         {

--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -31,6 +31,9 @@
     {
         #region Methods: public
 
+        /// <summary>
+        ///     Gets whether the part contains a specific resource.
+        /// </summary>
         public static bool ContainsResource(this Part part, int resourceId)
         {
             return part.Resources.Contains(resourceId);
@@ -59,6 +62,30 @@
             }
 
             return false;
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part excluding resources.
+        /// </summary>
+        public static double GetCostDry(this Part part)
+        {
+            return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts();
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part including maximum resources.
+        /// </summary>
+        public static double GetCostMax(this Part part)
+        {
+            return part.partInfo.cost + part.GetModuleCosts();
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part including resources.
+        /// </summary>
+        public static double GetCostWet(this Part part)
+        {
+            return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts();
         }
 
         /// <summary>
@@ -189,6 +216,19 @@
             return part.Modules.OfType<T>().ToList();
         }
 
+        public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part)
+        {
+            if (HasModule<ModuleDecouple>(part))
+            {
+                return new ProtoModuleDecoupler(GetModule<ModuleDecouple>(part));
+            }
+            if (HasModule<ModuleAnchoredDecoupler>(part))
+            {
+                return new ProtoModuleDecoupler(GetModule<ModuleAnchoredDecoupler>(part));
+            }
+            return null;
+        }
+
         /// <summary>
         ///     Gets a generic proto engine for the current engine module attached to the part.
         /// </summary>
@@ -210,6 +250,30 @@
         }
 
         /// <summary>
+        ///     Gets the cost of the part's contained resources.
+        /// </summary>
+        public static double GetResourceCost(this Part part)
+        {
+            return part.Resources.list.Sum(r => r.amount * r.info.unitCost);
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part's contained resources, inverted.
+        /// </summary>
+        public static double GetResourceCostInverted(this Part part)
+        {
+            return part.Resources.list.Sum(r => (r.maxAmount - r.amount) * r.info.unitCost);
+        }
+
+        /// <summary>
+        ///     Gets the cost of the part's maximum contained resources.
+        /// </summary>
+        public static double GetResourceCostMax(this Part part)
+        {
+            return part.Resources.list.Sum(r => r.maxAmount * r.info.unitCost);
+        }
+
+        /// <summary>
         ///     Gets the current specific impulse for the engine.
         /// </summary>
         public static double GetSpecificImpulse(this Part part, float atmosphere)
@@ -228,19 +292,6 @@
             }
 
             return 0d;
-        }
-
-        public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part)
-        {
-            if (HasModule<ModuleDecouple>(part))
-            {
-                return new ProtoModuleDecoupler(GetModule<ModuleDecouple>(part));
-            }
-            if (HasModule<ModuleAnchoredDecoupler>(part))
-            {
-                return new ProtoModuleDecoupler(GetModule<ModuleAnchoredDecoupler>(part));
-            }
-            return null;
         }
 
         /// <summary>

--- a/KerbalEngineer/Extensions/PartResourceExtensions.cs
+++ b/KerbalEngineer/Extensions/PartResourceExtensions.cs
@@ -21,28 +21,40 @@
 {
     public static class PartResourceExtensions
     {
+        #region Methods: public
+
+        /// <summary>
+        ///     Gets the cost of the resource.
+        /// </summary>
+        public static double GetCost(this PartResource resource)
+        {
+            return resource.amount * resource.info.unitCost;
+        }
+
         /// <summary>
         ///     Gets the definition object for the resource.
         /// </summary>
-        public static PartResourceDefinition GetDefinition(this PartResource value)
+        public static PartResourceDefinition GetDefinition(this PartResource resource)
         {
-            return PartResourceLibrary.Instance.GetDefinition(value.info.id);
+            return PartResourceLibrary.Instance.GetDefinition(resource.info.id);
         }
 
         /// <summary>
         ///     Gets the density of the resource.
         /// </summary>
-        public static double GetDensity(this PartResource value)
+        public static double GetDensity(this PartResource resource)
         {
-            return value.GetDefinition().density;
+            return resource.GetDefinition().density;
         }
 
         /// <summary>
         ///     Gets the mass of the resource.
         /// </summary>
-        public static double GetMass(this PartResource value)
+        public static double GetMass(this PartResource resource)
         {
-            return value.amount * value.GetDensity();
+            return resource.amount * resource.GetDensity();
         }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Helpers/Units.cs
+++ b/KerbalEngineer/Helpers/Units.cs
@@ -28,6 +28,16 @@
     public static class Units
     {
         #region Methods: public
+
+        public static string Concat(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)
+        {
+            return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals) + " / " + value3.ToString("F" + decimals);
+        }
 
         public static string ToAcceleration(double value, int decimals = 2)
         {
@@ -123,11 +133,6 @@
             return TimeFormatter.ConvertToString(value);
         }
 
-        public static string Concat(double value1, double value2, int decimals = 1)
-        {
-            return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals);
-        }
-
         #endregion
     }
 }

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -36,7 +36,7 @@
     {
         private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
         public double baseMass = 0d;
-        public float cost;
+        public double cost;
         public int decoupledInStage;
         public bool fuelCrossFeed;
         public List<PartSim> fuelTargets = new List<PartSim>();
@@ -88,11 +88,7 @@
             this.inverseStage = this.part.inverseStage;
             //MonoBehaviour.print("inverseStage = " + inverseStage);
 
-            this.cost = this.part.partInfo.cost;
-            foreach (PartResource resource in this.part.Resources)
-            {
-                this.cost -= (float)((resource.maxAmount - resource.amount) * resource.info.unitCost);
-            }
+            this.cost = this.part.GetCostWet();
 
             // Work out if the part should have no physical significance
             this.isNoPhysics = this.part.HasModule<ModuleLandingGear>() ||

--- a/KerbalEngineer/VesselSimulator/Stage.cs
+++ b/KerbalEngineer/VesselSimulator/Stage.cs
@@ -31,7 +31,7 @@
     {
         public double actualThrust = 0f;
         public double actualThrustToWeight = 0f;
-        public float cost = 0;
+        public double cost = 0d;
         public double deltaV = 0f;
         public double inverseTotalDeltaV = 0f;
         public double isp = 0f;
@@ -41,7 +41,7 @@
         public double thrust = 0f;
         public double thrustToWeight = 0f;
         public double time = 0f;
-        public float totalCost = 0;
+        public double totalCost = 0;
         public double totalDeltaV = 0f;
         public double totalMass = 0f;
         public double totalTime = 0f;

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