VesselInfo: Changed resource mass line to new combat stage/total resource mass.
VesselInfo: Changed resource mass line to new combat stage/total resource mass.

--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -39,7 +39,7 @@
 // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
 // The form "{Major}.{Minor}.*" will automatically update the build and revision,
 // and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion("0.11.0.*")]
+[assembly: AssemblyVersion("0.12.0.*")]
 // The following attributes are used to specify the signing key for the assembly,
 // if desired. See the Mono documentation for more information about signing.
 //[assembly: AssemblyDelaySign(false)]

--- a/VOID.csproj
+++ b/VOID.csproj
@@ -9,6 +9,7 @@
     <RootNamespace>VOID</RootNamespace>
     <AssemblyName>VOID</AssemblyName>
     <CodePage>65001</CodePage>
+    <UseMSBuildEngine>False</UseMSBuildEngine>
     <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ReleaseVersion>0.11</ReleaseVersion>
@@ -93,6 +94,7 @@
     <Compile Include="VOID_Tools.cs" />
     <Compile Include="VOID_Localization.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="VOID_HUDAdvanced.cs" />
   </ItemGroup>
   <ProjectExtensions>
     <MonoDevelop>

--- a/VOID_CBInfoBrowser.cs
+++ b/VOID_CBInfoBrowser.cs
@@ -274,14 +274,14 @@
 
 			GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
-			GUILayout.Label(((Math.Pow((body.Radius), 2) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
+			GUILayout.Label((((body.Radius * body.Radius) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
 			// divide by 1000 to convert m to km
-			GUILayout.Label((((4d / 3) * Math.PI * Math.Pow(body.Radius, 3)) / 1000).ToString("0.00e+00") + "km³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
+			GUILayout.Label((((4d / 3) * Math.PI * (body.Radius * body.Radius * body.Radius)) / 1000).ToString("0.00e+00") + "km³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
 			GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
-			double p = body.Mass / (Math.Pow(body.Radius, 3) * (4d / 3) * Math.PI);
+			double p = body.Mass / ((body.Radius * body.Radius * body.Radius) * (4d / 3) * Math.PI);
 
 			GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
@@ -299,7 +299,7 @@
 
 			GUILayout.Label(num_art_sats.ToString(), VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 
-			double g_ASL = (VOID_Core.Constant_G * body.Mass) / Math.Pow(body.Radius, 2);
+			double g_ASL = (VOID_Core.Constant_G * body.Mass) / (body.Radius * body.Radius);
 
 			GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Core.Instance.LabelStyles["right"], GUILayout.ExpandWidth(true));
 

--- a/VOID_Core.cs
+++ b/VOID_Core.cs
@@ -81,7 +81,7 @@
 		 * Fields
 		 * */
 		protected string VoidName = "VOID";
-		protected string VoidVersion = "0.11.0";
+		protected string VoidVersion;
 
 		protected bool _factoryReset = false;
 
@@ -480,8 +480,9 @@
 
 			if (this.vessel != null && this.vesselSimActive)
 			{
+				double radius = VOID_Core.Instance.vessel.Radius();
 				SimManager.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /
-					Math.Pow(VOID_Core.Instance.vessel.Radius(), 2);
+					(radius * radius);
 				SimManager.TryStartSimulation();
 			}
 			else if (!this.vesselSimActive)
@@ -991,6 +992,10 @@
 		{
 			this._Name = "VOID Core";
 
+			System.Version version = this.GetType().Assembly.GetName().Version;
+
+			this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision);
+
 			this._Active.value = true;
 
 			this._skinName = this.defaultSkin;

--- a/VOID_DataLogger.cs
+++ b/VOID_DataLogger.cs
@@ -234,7 +234,7 @@
 			line += vessel.flightIntegrator.getExternalTemperature().ToString("F2") + ";";
 			//gravity
 			double r_vessel = vessel.mainBody.Radius + vessel.mainBody.GetAltitude(vessel.findWorldCenterOfMass());
-			double g_vessel = (VOID_Core.Constant_G * vessel.mainBody.Mass) / Math.Pow(r_vessel, 2);
+			double g_vessel = (VOID_Core.Constant_G * vessel.mainBody.Mass) / (r_vessel * r_vessel);
 			line += g_vessel.ToString("F3") + ";";
 			//atm density
 			line += (vessel.atmDensity * 1000).ToString("F3") + ";";

--- a/VOID_DataValue.cs
+++ b/VOID_DataValue.cs
@@ -103,7 +103,7 @@
 			return (T)this.cache;
 		}
 
-		public string ValueUnitString() {
+		public virtual string ValueUnitString() {
 			return this.Value.ToString() + this.Units;
 		}
 
@@ -145,7 +145,6 @@
 		{
 			return v.ToSingle();
 		}
-
 
 		protected IFormatProvider formatProvider;
 
@@ -325,6 +324,26 @@
 	{
 		public VOID_StrValue(string Label, Func<string> ValueFunc) : base(Label, ValueFunc, "") {}
 	}
+
+	public class VOID_Vector3dValue : VOID_DataValue<Vector3d>
+	{
+		public VOID_Vector3dValue(string Label, Func<Vector3d> ValueFunc, string Units)
+			: base(Label, ValueFunc, Units)
+		{}
+
+		public string ToString(string format)
+		{
+			return string.Format("{0}: {1}{2}",
+				this.Label,
+				this.Value.ToString(format),
+				this.Units
+			);
+		}
+
+		public string ValueUnitString(string format) {
+			return this.Value.ToString(format) + this.Units;
+		}
+	}
 }
 
 

--- a/VOID_HUD.cs
+++ b/VOID_HUD.cs
@@ -269,62 +269,6 @@
 			() => core.vessel.getSurfacePitch(),
 			"°"
 		);
-
-		public static readonly VOID_DoubleValue stageMassFlow = new VOID_DoubleValue(
-			"Stage Mass Flow",
-			delegate()
-			{
-			if (SimManager.LastStage == null)
-				{
-					return double.NaN;
-				}
-
-				double stageIsp = SimManager.LastStage.isp;
-				double stageThrust = SimManager.LastStage.actualThrust;
-
-				return stageThrust / (stageIsp * KerbinGee);
-			},
-			"Mg/s"
-		);
-
-		public static readonly VOID_DoubleValue burnTimeCompleteAtNode = new VOID_DoubleValue(
-			"Full burn time to complete at node",
-			delegate()
-			{
-			if (SimManager.LastStage == null)
-				{
-					return double.NaN;
-				}
-			    
-				double nextManeuverDV = core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude;
-				double stageThrust = SimManager.LastStage.actualThrust;
-
-				return burnTime(nextManeuverDV, totalMass, stageMassFlow, stageThrust);
-			},
-			"s"
-		);
-
-		public static readonly VOID_DoubleValue burnTimeHalfDoneAtNode = new VOID_DoubleValue(
-			"Full burn time to be half done at node",
-			delegate()
-			{
-				if (SimManager.LastStage == null)
-				{
-					return double.NaN;
-				}
-			    
-				double nextManeuverDV = core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude / 2d;
-				double stageThrust = SimManager.LastStage.actualThrust;
-
-				return burnTime(nextManeuverDV, totalMass, stageMassFlow, stageThrust);
-			},
-			"s"
-		);
-
-		private static double burnTime(double deltaV, double initialMass, double massFlow, double thrust)
-		{
-			return initialMass / massFlow * (Math.Exp(deltaV * massFlow / thrust) - 1d);
-		}
 	}
 }
 

--- /dev/null
+++ b/VOID_HUDAdvanced.cs
@@ -1,1 +1,668 @@
-
+// VOID
+//
+// VOID_HUD.cs
+//
+// Copyright © 2014, toadicus
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+//    this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be used
+//    to endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+using Engineer.VesselSimulator;
+using KSP;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ToadicusTools;
+using UnityEngine;
+
+namespace VOID
+{
+	public class VOID_HUDAdvanced : VOID_Module, IVOID_Module
+	{
+		/*
+		 * Fields
+		 * */
+		protected VOID_HUD primaryHUD;
+
+		protected Rect leftHUDdefaultPos;
+		protected Rect rightHUDdefaultPos;
+
+		[AVOID_SaveValue("leftHUDPos")]
+		protected VOID_SaveValue<Rect> leftHUDPos;
+		[AVOID_SaveValue("rightHUDPos")]
+		protected VOID_SaveValue<Rect> rightHUDPos;
+
+		[AVOID_SaveValue("positionsLocked")]
+		protected VOID_SaveValue<bool> positionsLocked;
+
+		/*
+		 * Properties
+		 * */
+		public int ColorIndex
+		{
+			get
+			{
+				if (this.primaryHUD == null)
+				{
+					return 0;
+				}
+
+				return this.primaryHUD.ColorIndex;
+			}
+		}
+
+		/* 
+		 * Methods
+		 * */
+		public VOID_HUDAdvanced() : base()
+		{
+			this._Name = "Advanced Heads-Up Display";
+
+			this._Active.value = true;
+
+			this.leftHUDdefaultPos = new Rect(
+				Screen.width * .5f - (float)GameSettings.UI_SIZE * .25f - 300f,
+				Screen.height - 200f,
+				300f, 90f
+			);
+			this.leftHUDPos = new Rect(this.leftHUDdefaultPos);
+
+			this.rightHUDdefaultPos = new Rect(
+				Screen.width * .5f + (float)GameSettings.UI_SIZE * .25f,
+				Screen.height - 200f,
+				300f, 90f
+			);
+			this.rightHUDPos = new Rect(this.rightHUDdefaultPos);
+
+			this.positionsLocked = true;
+
+			Tools.PostDebugMessage (this, "Constructed.");
+		}
+
+		protected void leftHUDWindow(int id)
+		{
+			StringBuilder leftHUD;
+
+			leftHUD = new StringBuilder();
+
+			VOID_Core.Instance.LabelStyles["hud"].alignment = TextAnchor.UpperRight;
+
+			if (VOID_Core.Instance.powerAvailable)
+			{
+				leftHUD.AppendFormat(
+					string.Intern("Mass: {0}\n"),
+					VOID_Data.totalMass.ToSIString(2)
+				);
+
+				if (VOID_Data.vesselCrewCapacity > 0)
+				{
+					leftHUD.AppendFormat(
+						string.Intern("Crew: {0} / {1}\n"),
+						VOID_Data.vesselCrewCount.Value,
+						VOID_Data.vesselCrewCapacity.Value
+					);
+				}
+
+				leftHUD.AppendFormat(
+					string.Intern("Acc: {0} T:W: {1}\n"),
+					VOID_Data.vesselAccel.ToSIString(2),
+					VOID_Data.currThrustWeight.Value.ToString("f2")
+				);
+
+				leftHUD.AppendFormat(
+					string.Intern("Ang Vel: {0}\n"),
+					VOID_Data.vesselAngularVelocity.ToSIString(2)
+				);
+
+				if (VOID_Data.stageNominalThrust != 0d)
+				{
+					leftHUD.AppendFormat(
+						string.Intern("Thrust Offset: {0}\n"),
+						VOID_Data.vesselThrustOffset.Value.ToString("F1")
+					);
+				}
+			}
+			else
+			{
+				VOID_Core.Instance.LabelStyles["hud"].normal.textColor = Color.red;
+				leftHUD.Append(string.Intern("-- POWER LOST --"));
+			}
+
+			GUILayout.Label(leftHUD.ToString(), VOID_Core.Instance.LabelStyles["hud"], GUILayout.ExpandWidth(true));
+
+			if (!this.positionsLocked)
+			{
+				GUI.DragWindow();
+			}
+
+			GUI.BringWindowToBack(id);
+		}
+
+		protected void rightHUDWindow(int id)
+		{
+			StringBuilder rightHUD;
+
+			rightHUD = new StringBuilder();
+
+			VOID_Core.Instance.LabelStyles["hud"].alignment = TextAnchor.UpperLeft;
+
+			if (VOID_Core.Instance.powerAvailable)
+			{
+				rightHUD.AppendFormat(
+					"Burn Δv (Rem/Tot): {0} / {1}\n",
+					VOID_Data.currManeuverDVRemaining.ValueUnitString("f2"),
+					VOID_Data.currManeuverDeltaV.ValueUnitString("f2")
+				);
+
+				if (VOID_Data.upcomingManeuverNodes > 1)
+				{
+					rightHUD.AppendFormat("Next Burn Δv: {0}\n",
+						VOID_Data.nextManeuverDeltaV.ValueUnitString("f2")
+					);
+				}
+
+				rightHUD.AppendFormat("Burn Time (Rem/Total): {0} / {1}\n",
+					VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnRemaining.Value),
+					VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnDuration.Value)
+				);
+
+				if (VOID_Data.burnTimeDoneAtNode.Value != string.Empty)
+				{
+					rightHUD.AppendFormat("{0} (done @ node)\n",
+						VOID_Data.burnTimeDoneAtNode.Value
+					);
+
+					rightHUD.AppendFormat("{0} (½ done @ node)",
+						VOID_Data.burnTimeHalfDoneAtNode.Value
+					);
+				}
+				else
+				{
+					rightHUD.Append("Node is past");
+				}
+			}
+			else
+			{
+				VOID_Core.Instance.LabelStyles["hud"].normal.textColor = Color.red;
+				rightHUD.Append(string.Intern("-- POWER LOST --"));
+			}
+
+			GUILayout.Label(rightHUD.ToString(), VOID_Core.Instance.LabelStyles["hud"], GUILayout.ExpandWidth(true));
+
+			if (!this.positionsLocked)
+			{
+				GUI.DragWindow();
+			}
+
+			GUI.BringWindowToBack(id);
+		}
+
+		public override void DrawGUI()
+		{
+			if (this.primaryHUD == null)
+			{
+				foreach (IVOID_Module module in VOID_Core.Instance.Modules)
+				{
+					if (module is VOID_HUD)
+					{
+						this.primaryHUD = module as VOID_HUD;
+					}
+				}
+			}
+			else
+			{
+				if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
+				{
+					SimManager.RequestSimulation();
+				}
+
+				this.leftHUDPos.value = GUI.Window(
+					VOID_Core.Instance.windowID,
+					this.leftHUDPos,
+					VOID_Tools.GetWindowHandler(this.leftHUDWindow),
+					GUIContent.none,
+					GUIStyle.none
+				);
+
+				if (VOID_Data.upcomingManeuverNodes > 0)
+				{
+					this.rightHUDPos.value = GUI.Window(
+						VOID_Core.Instance.windowID,
+						this.rightHUDPos,
+						VOID_Tools.GetWindowHandler(this.rightHUDWindow),
+						GUIContent.none,
+						GUIStyle.none
+					);
+				}
+			}
+		}
+
+		public override void DrawConfigurables()
+		{
+			this.positionsLocked = GUILayout.Toggle(this.positionsLocked,
+				string.Intern("Lock Advanced HUD Positions"),
+				GUILayout.ExpandWidth(false));
+		}
+	}
+
+	public static partial class VOID_Data
+	{
+		public static int upcomingManeuverNodes
+		{
+			get
+			{
+				if (core.vessel == null ||
+					core.vessel.patchedConicSolver == null ||
+					core.vessel.patchedConicSolver.maneuverNodes == null
+				)
+				{
+					return 0;
+				}
+
+				return core.vessel.patchedConicSolver.maneuverNodes.Count;
+			}
+		}
+
+		public static readonly VOID_Vector3dValue vesselThrustOffset = new VOID_Vector3dValue(
+			"Thrust Offset",
+			delegate()
+		{
+			if (core.vessel == null)
+			{
+				return Vector3d.zero;
+			}
+
+			List<PartModule> engineModules = core.vessel.getModulesOfType<PartModule>();
+
+			Vector3d thrustPos = Vector3d.zero;
+			Vector3d thrustDir = Vector3d.zero;
+			float thrust = 0;
+
+			foreach (PartModule engine in engineModules)
+			{
+				float moduleThrust = 0;
+
+				switch (engine.moduleName)
+				{
+					case "ModuleEngines":
+					case "ModuleEnginesFX":
+						break;
+					default:
+						continue;
+				}
+
+				if (!engine.isEnabled)
+				{
+					continue;
+				}
+
+				CenterOfThrustQuery cotQuery = new CenterOfThrustQuery();
+
+				if (engine is ModuleEngines)
+				{
+					ModuleEngines engineModule = engine as ModuleEngines;
+
+					moduleThrust = engineModule.finalThrust;
+
+					engineModule.OnCenterOfThrustQuery(cotQuery);
+				}
+				else // engine is ModuleEnginesFX
+				{
+					ModuleEnginesFX engineFXModule = engine as ModuleEnginesFX;
+
+					moduleThrust = engineFXModule.finalThrust;
+
+					engineFXModule.OnCenterOfThrustQuery(cotQuery);
+				}
+
+				if (moduleThrust != 0d)
+				{
+					cotQuery.thrust = moduleThrust;
+				}
+
+				thrustPos += cotQuery.pos * cotQuery.thrust;
+				thrustDir += cotQuery.dir * cotQuery.thrust;
+				thrust += cotQuery.thrust;
+			}
+
+			if (thrust != 0)
+			{
+				thrustPos /= thrust;
+				thrustDir /= thrust;
+			}
+
+			Transform vesselTransform = core.vessel.transform;
+
+			thrustPos = vesselTransform.InverseTransformPoint(thrustPos);
+			thrustDir = vesselTransform.InverseTransformDirection(thrustDir);
+
+			Vector3d thrustOffset = VectorTools.PointDistanceToLine(
+				thrustPos, thrustDir.normalized, core.vessel.findLocalCenterOfMass());
+
+			Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" +
+				"\tthrustPos: {0}\n" +
+				"\tthrustDir: {1}\n" +
+				"\tthrustOffset: {2}\n" +
+				"\tvessel.CoM: {3}",
+				thrustPos,
+				thrustDir.normalized,
+				thrustOffset,
+				core.vessel.findWorldCenterOfMass()
+			);
+
+			return thrustOffset;
+		},
+			"m"
+		);
+
+		public static readonly VOID_DoubleValue vesselAccel = new VOID_DoubleValue(
+			"Acceleration",
+			() => geeForce * KerbinGee,
+			"m/s"
+		);
+
+		public static readonly VOID_IntValue vesselCrewCount = new VOID_IntValue(
+			"Crew Onboard",
+			delegate()
+			{
+				if (core.vessel != null)
+				{
+					return core.vessel.GetCrewCount();
+				}
+				else
+				{
+					return 0;
+				}
+			},
+			""
+		);
+
+		public static readonly VOID_IntValue vesselCrewCapacity = new VOID_IntValue(
+			"Crew Capacity",
+			delegate()
+		{
+			if (core.vessel != null)
+			{
+				return core.vessel.GetCrewCapacity();
+			}
+			else
+			{
+				return 0;
+			}
+		},
+			""
+		);
+
+		public static readonly VOID_DoubleValue vesselAngularVelocity = new VOID_DoubleValue(
+			"Angular Velocity",
+			delegate()
+		{
+			if (core.vessel != null)
+			{
+				return core.vessel.angularVelocity.magnitude;
+			}
+			else
+			{
+				return double.NaN;
+			}
+		},
+			"rad/s"
+		);
+
+		public static readonly VOID_DoubleValue stageNominalThrust = new VOID_DoubleValue(
+			"Nominal Stage Thrust",
+			delegate()
+		{
+			if (SimManager.LastStage == null)
+			{
+				return double.NaN;
+			}
+
+			if (SimManager.LastStage.actualThrust == 0d)
+			{
+				return SimManager.LastStage.thrust;
+			}
+			else
+			{
+				return SimManager.LastStage.actualThrust;
+			}
+		},
+			"kN"
+		);
+
+		public static readonly VOID_DoubleValue stageMassFlow = new VOID_DoubleValue(
+			"Stage Mass Flow",
+			delegate()
+			{
+				if (SimManager.LastStage == null)
+				{
+					return double.NaN;
+				}
+
+			double stageIsp = SimManager.LastStage.isp;
+			double stageThrust = stageNominalThrust;
+
+			Tools.PostDebugMessage(typeof(VOID_Data), "calculating stageMassFlow from:\n" +
+				"\tstageIsp: {0}\n" +
+				"\tstageThrust: {1}\n" +
+				"\tKerbinGee: {2}\n",
+				stageIsp,
+				stageThrust,
+				KerbinGee
+			);
+
+				return stageThrust / (stageIsp * KerbinGee);
+			},
+			"Mg/s"
+		);
+
+		public static readonly VOID_DoubleValue currManeuverDeltaV = new VOID_DoubleValue(
+			"Current Maneuver Delta-V",
+			delegate()
+			{
+				if (upcomingManeuverNodes > 0)
+				{
+				return core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude;
+				}
+				else
+				{
+					return double.NaN;
+				}
+			},
+			"m/s"
+		);
+
+		public static readonly VOID_DoubleValue currManeuverDVRemaining = new VOID_DoubleValue(
+			"Remaining Maneuver Delta-V",
+			delegate()
+			{
+				if (upcomingManeuverNodes > 0)
+				{
+					return core.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(core.vessel.orbit).magnitude;
+				}
+				else
+				{
+					return double.NaN;
+				}
+			},
+			"m/s"
+		);
+
+		public static readonly VOID_DoubleValue nextManeuverDeltaV = new VOID_DoubleValue(
+			"Current Maneuver Delta-V",
+			delegate()
+		{
+			if (upcomingManeuverNodes > 1)
+			{
+				return core.vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude;
+			}
+			else
+			{
+				return double.NaN;
+			}
+		},
+			"m/s"
+		);
+
+		public static readonly VOID_DoubleValue currentNodeBurnDuration = new VOID_DoubleValue(
+			"Total Burn Time",
+			delegate()
+			{
+				if (SimManager.LastStage == null || currManeuverDeltaV.Value == double.NaN)
+				{
+					return double.NaN;
+				}
+			    
+				double stageThrust = stageNominalThrust;
+
+				return burnTime(currManeuverDeltaV.Value, totalMass, stageMassFlow, stageThrust);
+			},
+			"s"
+		);
+
+		public static readonly VOID_DoubleValue currentNodeBurnRemaining = new VOID_DoubleValue(
+			"Burn Time Remaining",
+			delegate()
+			{
+				if (SimManager.LastStage == null || currManeuverDVRemaining == double.NaN)
+				{
+					return double.NaN;
+				}
+
+				double stageThrust = stageNominalThrust;
+
+				return burnTime(currManeuverDVRemaining, totalMass, stageMassFlow, stageThrust);
+			},
+			"s"
+		);
+
+		public static readonly VOID_DoubleValue currentNodeHalfBurnDuration = new VOID_DoubleValue(
+			"Half Burn Time",
+			delegate()
+		{
+			if (SimManager.LastStage == null || currManeuverDeltaV.Value == double.NaN)
+			{
+				return double.NaN;
+			}
+
+			double stageThrust = stageNominalThrust;
+
+			return burnTime(currManeuverDeltaV.Value / 2d, totalMass, stageMassFlow, stageThrust);
+		},
+			"s"
+		);
+
+		public static readonly VOID_StrValue burnTimeDoneAtNode = new VOID_StrValue(
+			"Full burn time to be half done at node",
+			delegate()
+		{
+			if (SimManager.LastStage == null && upcomingManeuverNodes < 1)
+			{
+				return "N/A";
+			}
+
+			ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0];
+
+			if ((node.UT - Planetarium.GetUniversalTime()) < 0)
+			{
+				return string.Empty;
+			}
+
+			double interval = (node.UT - currentNodeBurnDuration) - Planetarium.GetUniversalTime();
+
+			if (double.IsNaN(interval))
+			{
+				return string.Intern("NaN");
+			}
+
+			int sign = Math.Sign(interval);
+			interval = Math.Abs(interval);
+
+			string format;
+
+			if (sign >= 0)
+			{
+				format = string.Intern("T - {0}");
+			}
+			else
+			{
+				format = string.Intern("T + {0}");
+			}
+
+			return string.Format(format, VOID_Tools.ConvertInterval(interval));
+		}
+		);
+
+		public static readonly VOID_StrValue burnTimeHalfDoneAtNode = new VOID_StrValue(
+			"Full burn time to be half done at node",
+			delegate()
+			{
+			if (SimManager.LastStage == null && upcomingManeuverNodes < 1)
+			{
+				return "N/A";
+			}
+
+			ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0];
+
+			if ((node.UT - Planetarium.GetUniversalTime()) < 0)
+			{
+				return string.Empty;
+			}
+
+			double interval = (node.UT - currentNodeHalfBurnDuration) - Planetarium.GetUniversalTime();
+
+			int sign = Math.Sign(interval);
+			interval = Math.Abs(interval);
+
+			string format;
+
+			if (sign >= 0)
+			{
+				format = string.Intern("T - {0}");
+			}
+			else
+			{
+				format = string.Intern("T + {0}");
+			}
+
+			return string.Format(format, VOID_Tools.ConvertInterval(interval));
+			}
+		);
+
+		private static double burnTime(double deltaV, double initialMass, double massFlow, double thrust)
+		{
+			Tools.PostDebugMessage(typeof(VOID_Data), "calculating burnTime from:\n" +
+				"\tdeltaV: {0}\n" +
+				"\tinitialMass: {1}\n" +
+				"\tmassFlow: {2}\n" +
+				"\tthrust: {3}\n",
+				deltaV,
+				initialMass,
+				massFlow,
+				thrust
+			);
+			return initialMass / massFlow * (Math.Exp(deltaV * massFlow / thrust) - 1d);
+		}
+	}
+}
+

--- a/VOID_Module.cs
+++ b/VOID_Module.cs
@@ -51,6 +51,14 @@
 		/*
 		 * Properties
 		 * */
+		protected virtual VOID_Core core
+		{
+			get
+			{
+				return VOID_Core.Instance;
+			}
+		}
+
 		public virtual bool toggleActive
 		{
 			get
@@ -206,42 +214,7 @@
 		protected float defWidth = 250f;
 		protected float defHeight = 50f;
 
-		public virtual void ModuleWindow(int _)
-		{
-//			if (VOID_Core.Instance.updateTimer - this.lastUpdate > VOID_Core.Instance.updatePeriod) {
-//				foreach (var fieldinfo in this.GetType().GetFields(
-//					BindingFlags.Instance |
-//					BindingFlags.NonPublic |
-//					BindingFlags.Public |
-//					BindingFlags.FlattenHierarchy
-//				))
-//				{
-//					object field = null;
-//
-//					try
-//					{
-//						field = fieldinfo.GetValue (this);
-//					}
-//					catch (NullReferenceException) {
-//						Tools.PostDebugMessage(string.Format(
-//							"{0}: caught NullReferenceException, could not get value for field {1}.",
-//							this.GetType().Name,
-//							fieldinfo.Name
-//						));
-//					}
-//
-//					if (field == null) {
-//						continue;
-//					}
-//
-//					if (typeof(IVOID_DataValue).IsAssignableFrom (field.GetType ())) {
-//						(field as IVOID_DataValue).Refresh ();
-//					}
-//				}
-//
-//				this.lastUpdate = VOID_Core.Instance.updateTimer;
-//			}
-		}
+		public abstract void ModuleWindow(int _);
 
 		public override void DrawGUI()
 		{

--- a/VOID_Orbital.cs
+++ b/VOID_Orbital.cs
@@ -52,8 +52,6 @@
 
 		public override void ModuleWindow(int _)
 		{
-			base.ModuleWindow (_);
-
 			int idx = 0;
 
             GUILayout.BeginVertical();
@@ -186,7 +184,7 @@
 			double orbitRadius = VOID_Core.Instance.vessel.mainBody.Radius +
 				VOID_Core.Instance.vessel.mainBody.GetAltitude(VOID_Core.Instance.vessel.findWorldCenterOfMass());
 			return (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) /
-				Math.Pow(orbitRadius, 2);
+				(orbitRadius * orbitRadius);
 		},
 			"m/s²"
 		);

--- a/VOID_Rendezvous.cs
+++ b/VOID_Rendezvous.cs
@@ -193,7 +193,13 @@
 					GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 
-					//target_vessel_extended_orbital_info = GUILayout.Toggle(target_vessel_extended_orbital_info, "Extended info");
+					// Toadicus edit: added local sidereal longitude.
+					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
+					GUILayout.Label("Local Sidereal Longitude:");
+					GUILayout.Label(LSL.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"]);
+					GUILayout.EndHorizontal();
+
+					toggleExtendedOrbital.value = GUILayout.Toggle(toggleExtendedOrbital, "Extended info");
 
 					if (toggleExtendedOrbital)
 					{
@@ -237,12 +243,6 @@
 						GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 						GUILayout.Label("Arg. of periapsis:");
 						GUILayout.Label(v.orbit.argumentOfPeriapsis.ToString("F3") + "°", GUILayout.ExpandWidth(false));
-						GUILayout.EndHorizontal();
-
-						// Toadicus edit: added local sidereal longitude.
-						GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
-						GUILayout.Label("Local Sidereal Longitude:");
-						GUILayout.Label(LSL.ToString("F3") + "°", VOID_Core.Instance.LabelStyles["right"]);
 						GUILayout.EndHorizontal();
 					}
 				}

--- a/VOID_SurfAtmo.cs
+++ b/VOID_SurfAtmo.cs
@@ -49,8 +49,6 @@
 
 		public override void ModuleWindow(int _)
 		{
-			base.ModuleWindow (_);
-
 			int idx = 0;
 
 			GUILayout.BeginVertical();

--- a/VOID_Tools.cs
+++ b/VOID_Tools.cs
@@ -28,6 +28,7 @@
 
 using KSP;
 using System;
+using System.Collections.Generic;
 using UnityEngine;
 
 namespace VOID
@@ -256,6 +257,39 @@
 		}
 		#endregion
 
+		private static Dictionary<int, GUI.WindowFunction> functionCache;
+		public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func)
+		{
+			if (functionCache == null)
+			{
+				functionCache = new Dictionary<int, GUI.WindowFunction>();
+			}
+
+			int hashCode = func.GetHashCode();
+
+			if (!functionCache.ContainsKey(hashCode))
+			{
+				functionCache[hashCode] = delegate (int id)
+				{
+					try
+					{
+						func(id);
+					}
+					catch (ArgumentException ex)
+					{
+						Debug.LogWarning(
+							string.Format("[{0}]: ArgumentException caught during window call.", func.Target.GetType().Name)
+						);
+						#if DEBUG
+						Debug.LogException(ex);
+						#endif
+					}
+				};
+			}
+
+			return functionCache[hashCode];
+		}
+
 		/// <summary>
 		/// Converts the interval given in seconds to a human-friendly
 		/// time period in [years], [days], hours, minutes, and seconds.
@@ -345,8 +379,14 @@
 		//transfer angles
 		public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)
 		{
-			double T_target = (2 * Math.PI) * Math.Sqrt(Math.Pow((r_target / 1000), 3) / (grav_param / 1000000000));
-			double T_transfer = (2 * Math.PI) * Math.Sqrt(Math.Pow((((r_target / 1000) + (r_current / 1000)) / 2), 3) / (grav_param / 1000000000));
+			r_target /= 1000;
+			r_current /= 1000;
+			grav_param /= 1000000000;
+
+			double midpoint = (r_target + r_current) / 2;
+
+			double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param);
+			double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param);
 			return 360 * (0.5 - (T_transfer / (2 * T_target)));
 		}
 
@@ -385,7 +425,7 @@
             r = r1*r2
             return math.sqrt(bar / r)
             */
-			double foo = r2 * Math.Pow(v, 2) - 2 * mu;
+			double foo = r2 * (v * v) - 2 * mu;
 			double bar = r1 * foo + (2 * r2 * mu);
 			double r = r1 * r2;
 			return Math.Sqrt(bar / r);
@@ -407,9 +447,9 @@
             return 180 - degrees
             */
 			double epsilon, h, ee, theta, degrees;
-			epsilon = (Math.Pow(v, 2) / 2) - (mu / r);
+			epsilon = ((v * v) / 2) - (mu / r);
 			h = r * v * Math.Sin(angle);
-			ee = Math.Sqrt(1 + ((2 * epsilon * Math.Pow(h, 2)) / Math.Pow(mu, 2)));
+			ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu)));
 			theta = Math.Acos(1.0 / ee);
 			degrees = theta * (180.0 / Math.PI);
 			return 180 - degrees;

--- a/VOID_VesselInfo.cs
+++ b/VOID_VesselInfo.cs
@@ -48,8 +48,6 @@
 
 		public override void ModuleWindow(int _)
 		{
-			base.ModuleWindow (_);
-
 			if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
 			{
 				SimManager.RequestSimulation();
@@ -68,7 +66,7 @@
 
 			VOID_Data.totalMass.DoGUIHorizontal ("F3");
 
-			VOID_Data.resourceMass.DoGUIHorizontal ("F3");
+			VOID_Data.comboResourceMass.DoGUIHorizontal ();
 
 			VOID_Data.stageDeltaV.DoGUIHorizontal (3, false);
 
@@ -127,9 +125,31 @@
 					return double.NaN;
 				}
 
-				return SimManager.LastStage.totalBaseMass;
+				return SimManager.LastStage.totalMass - SimManager.LastStage.totalBaseMass;
 			},
 			"tons"
+		);
+
+		public static readonly VOID_DoubleValue stageResourceMass = new VOID_DoubleValue(
+			"Resource Mass (Current Stage)",
+			delegate()
+			{
+				if (SimManager.LastStage == null)
+				{
+					return double.NaN;
+				}
+
+				return SimManager.LastStage.mass - SimManager.LastStage.baseMass;
+			},
+			"tons"
+		);
+
+		public static readonly VOID_StrValue comboResourceMass = new VOID_StrValue(
+			"Resource Mass (curr / total)",
+			delegate()
+		{
+			return string.Format("{0} / {1}", stageResourceMass.ValueUnitString(), resourceMass.ValueUnitString());
+		}
 		);
 
 		public static readonly VOID_DoubleValue stageDeltaV = new VOID_DoubleValue(
@@ -178,6 +198,34 @@
 			}
 		);
 
+		public static readonly VOID_DoubleValue currThrustWeight = new VOID_DoubleValue(
+			"T:W Ratio",
+			delegate()
+		{
+			if (SimManager.LastStage == null)
+			{
+				return double.NaN;
+			}
+
+			return SimManager.LastStage.actualThrustToWeight;
+		},
+			""
+		);
+
+		public static readonly VOID_DoubleValue maxThrustWeight = new VOID_DoubleValue(
+			"T:W Ratio",
+			delegate()
+		{
+			if (SimManager.LastStage == null)
+			{
+				return double.NaN;
+			}
+
+			return SimManager.LastStage.maxThrustToWeight;
+		},
+			""
+		);
+
 		public static readonly VOID_StrValue currmaxThrustWeight = new VOID_StrValue(
 			"T:W (curr/max)",
 			delegate()
@@ -185,20 +233,10 @@
 				if (SimManager.Stages == null || SimManager.LastStage == null)
 					return "N/A";
 
-				double currThrust = SimManager.LastStage.actualThrust;
-				double maxThrust = SimManager.LastStage.thrust;
-				double mass = SimManager.LastStage.totalMass;
-				double gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /
-					Math.Pow(
-						VOID_Core.Instance.vessel.mainBody.Radius + VOID_Core.Instance.vessel.altitude,
-						2
-					);
-				double weight = mass * gravity;
-
 				return string.Format(
 					"{0} / {1}",
-					(currThrust / weight).ToString("F2"),
-					(maxThrust / weight).ToString("F2")
+					(VOID_Data.currThrustWeight.Value).ToString("F2"),
+					(VOID_Data.maxThrustWeight.Value).ToString("F2")
 				);
 			}
 		);
@@ -213,7 +251,7 @@
 				double maxThrust = SimManager.LastStage.thrust;
 				double mass = SimManager.LastStage.totalMass;
 				double gravity = (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) /
-					Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2);
+				(VOID_Core.Instance.vessel.mainBody.Radius * VOID_Core.Instance.vessel.mainBody.Radius);
 				double weight = mass * gravity;
 
 				return maxThrust / weight;