VOID_Data: Got rid of intakeAirPostForEach because it wasn't necessary.
VOID_Data: Got rid of intakeAirPostForEach because it wasn't necessary.

file:b/API/Enums.cs (new)
--- /dev/null
+++ b/API/Enums.cs
@@ -1,1 +1,25 @@
+// VOID © 2015 toadicus
+//
+// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
+// copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
+using System;
 
+namespace VOID
+{
+	public enum VOID_TimeScale : UInt32
+	{
+		KERBIN_TIME = 1, // Earth if 0
+		SOLAR_DAY = 4, // Sidereal if 0
+		ROUNDED_SCALE = 1024 // Real values if 0
+	}
+
+	public enum IconState : UInt32
+	{
+		PowerOff = 1,
+		PowerOn = 2,
+		Inactive = 4,
+		Active = 8
+	}
+}
+
+

--- a/API/IVOID_Module.cs
+++ b/API/IVOID_Module.cs
@@ -38,15 +38,16 @@
 		bool InValidScene { get; }
 		bool InValidGame { get; }
 
-		void DrawGUI();
+		void DrawGUI(object sender);
 		void StartGUI();
 		void StopGUI();
 
 		void DrawConfigurables();
 
-		void LoadConfig();
+		// void LoadConfig();
+		void LoadConfig(KSP.IO.PluginConfiguration config);
 
-		void Save(KSP.IO.PluginConfiguration config);
+		void Save(KSP.IO.PluginConfiguration config, string sceneKey);
 	}
 
 	public interface IVOID_BehaviorModule : IVOID_Module

--- a/API/VOIDCore.cs
+++ b/API/VOIDCore.cs
@@ -29,8 +29,8 @@
 using KerbalEngineer.VesselSimulator;
 using KSP;
 using System;
+using System.Linq;
 using System.Collections.Generic;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
@@ -40,13 +40,39 @@
 		public const double Constant_G = 6.674e-11;
 		public const int CONFIG_VERSION = 2;
 
+		public static event VOIDEventHandler onModulesLoaded;
+		public static event VOIDEventHandler onModulesDestroyed;
+
+		protected static void FireOnModulesLoaded(object sender)
+		{
+			if (onModulesLoaded != null)
+			{
+				onModulesLoaded(sender);
+			}
+		}
+
+		protected static void FireOnModulesDestroyed(object sender)
+		{
+			if (onModulesDestroyed != null)
+			{
+				onModulesDestroyed(sender);
+			}
+		}
+
 		public abstract int ConfigVersion { get; }
 		public virtual bool configNeedsUpdate { get; set; }
+
+		public virtual string SaveGamePath { get; protected set; }
+		public virtual string VOIDSettingsPath { get; protected set; }
+
+		public abstract string SceneKey { get; }
 
 		public abstract int WindowID { get; }
 		public abstract bool configDirty { get; set; }
 		public abstract bool powerAvailable	{ get; protected set; }
 
+		public virtual bool gameUIHidden { get; protected set; }
+
 		public abstract IList<IVOID_Module> Modules { get; }
 
 		public abstract float UpdateTimer { get; protected set; }
@@ -57,32 +83,136 @@
 		public abstract GUISkin Skin { get; }
 
 		public abstract CelestialBody HomeBody { get; }
-		public abstract IList<CelestialBody> AllBodies { get; }
 		public abstract List<CelestialBody> SortedBodyList { get; protected set; }
 
 		public abstract VesselType[] AllVesselTypes { get; protected set; }
 		public abstract Stage LastStage { get; protected set; }
 		public abstract Stage[] Stages { get; protected set; }
 
+		public abstract VOID_TimeScale TimeScale { get; protected set; }
+
 		public abstract event VOIDEventHandler onApplicationQuit;
 		public abstract event VOIDEventHandler onSkinChanged;
-
-		public virtual void OnGUI() {}
-
-		public override void LoadConfig()
-		{
-			base.LoadConfig();
+		public abstract event VOIDEventHandler onUpdate;
+
+		public abstract event VOIDEventHandler onPreForEach;
+		public abstract event VOIDForEachPartHandler onForEachPart;
+		public abstract event VOIDForEachPartModuleHandler onForEachModule;
+		public abstract event VOIDEventHandler onPostForEach;
+
+		public virtual event VOIDEventHandler onPreRender;
+		public virtual event VOIDEventHandler onPostRender;
+
+		public virtual bool MethodInPreRenderQueue(VOIDEventHandler method)
+		{
+			if (this.onPreRender != null)
+			{
+				ToadicusTools.Logging.PostDebugMessage(this, "Looking in onPreRender for method {0} in onGui", method);
+
+				foreach (Delegate invoker in this.onPreRender.GetInvocationList())
+				{
+					ToadicusTools.Logging.PostDebugMessage(this, "Checking invoker {0}", invoker);
+
+					if (invoker == method)
+					{
+						ToadicusTools.Logging.PostDebugMessage(this, "Found match.");
+						return true;
+					}
+				}
+			}
+			#if DEBUG
+			else
+			{
+			ToadicusTools.Logging.PostDebugMessage(this, "this.onPreRender == null");
+			}
+			#endif
+
+
+			return false;
+		}
+
+		public virtual bool MethodInPostRenderQueue(VOIDEventHandler method)
+		{
+			if (this.onPostRender != null)
+			{
+				ToadicusTools.Logging.PostDebugMessage(this, "Looking in onPostRender for method {0} in onGui", method);
+
+				foreach (Delegate invoker in this.onPostRender.GetInvocationList())
+				{
+					ToadicusTools.Logging.PostDebugMessage(this, "Checking invoker {0}", invoker);
+
+					if (invoker == method)
+					{
+						ToadicusTools.Logging.PostDebugMessage(this, "Found match.");
+						return true;
+					}
+				}
+			}
+			#if DEBUG
+			else
+			{
+				ToadicusTools.Logging.PostDebugMessage(this, "this.onPostRender == null");
+			}
+			#endif
+
+
+			return false;
+		}
+
+		public void OnGUI()
+		{
+			if (this.gameUIHidden)
+			{
+				return;
+			}
+
+			if (Event.current.type == EventType.Repaint || Event.current.isMouse)
+			{
+				if (this.onPreRender != null)
+				{
+					ToadicusTools.Logging.PostDebugMessage(this, "In OnGUI; doing 'pre draw' stuff");
+					this.onPreRender(this);
+				}
+			}
+
+			if (this.onPostRender != null)
+			{
+				ToadicusTools.Logging.PostDebugMessage(this, "In OnGUI; doing 'post draw' stuff");
+				this.onPostRender(this);
+			}
 		}
 
 		public abstract void SaveConfig();
 
-		public override void Save(KSP.IO.PluginConfiguration config)
-		{
-			base.Save(config);
+		public override void Save(KSP.IO.PluginConfiguration config, string sceneKey)
+		{
+			base.Save(config, sceneKey);
+
 		}
 	}
 
 	public delegate void VOIDEventHandler(object sender);
+	public delegate void VOIDForEachPartHandler(object sender, VOIDForEachPartArgs args);
+	public delegate void VOIDForEachPartModuleHandler(object sender, VOIDForEachPartModuleArgs args);
+
+	public abstract class VOIDForEachEventArgs<T> : EventArgs where T : class
+	{
+		public T Data;
+
+		public VOIDForEachEventArgs(T data)
+		{
+			this.Data = data;
+		}
+	}
+
+	public class VOIDForEachPartArgs : VOIDForEachEventArgs<Part>
+	{
+		public VOIDForEachPartArgs(Part data) : base(data) {}
+	}
+	public class VOIDForEachPartModuleArgs : VOIDForEachEventArgs<PartModule>
+	{
+		public VOIDForEachPartModuleArgs(PartModule data) : base(data) {}
+	}
 }
 
 

--- a/API/VOIDMaster.cs
+++ b/API/VOIDMaster.cs
@@ -43,7 +43,7 @@
 using System;
 using UnityEngine;
 using KerbalEngineer.VesselSimulator;
-using ToadicusTools;
+using ToadicusTools.Extensions;
 
 namespace VOID
 {
@@ -80,6 +80,8 @@
 				this.LogDebug("Factory reset is true; deleting config and disposing!");
 
 				KSP.IO.File.Delete<T>("config.xml");
+				System.IO.File.Delete(this.Core.VOIDSettingsPath);
+
 				this.Core.Dispose();
 				this.Core = null;
 			}
@@ -127,8 +129,11 @@
 
 		protected virtual bool InValidScene()
 		{
-			foreach (var attr in this.GetType().GetCustomAttributes(true))
+			object[] attributes = this.GetType().GetCustomAttributes(true);
+			object attr;
+			for (int idx = 0; idx < attributes.Length; idx++)
 			{
+				attr = attributes[idx];
 				if (attr is KSPAddon)
 				{
 					KSPAddon addonAttr = (KSPAddon)attr;

--- a/API/VOID_HUDModule.cs
+++ b/API/VOID_HUDModule.cs
@@ -31,7 +31,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
-using ToadicusTools;
+using ToadicusTools.GUIUtils;
 using UnityEngine;
 
 namespace VOID
@@ -91,8 +91,13 @@
 			this.Windows = new List<HUDWindow>();
 		}
 
-		public override void DrawGUI()
-		{
+		public override void DrawGUI(object sender)
+		{
+			if (this.core == null)
+			{
+				return;
+			}
+
 			VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex];
 
 			GUI.skin = this.core.Skin;
@@ -104,8 +109,11 @@
 				SimManager.RequestSimulation();
 			}
 
-			foreach (HUDWindow window in this.Windows)
-			{
+			HUDWindow window;
+			for (int idx = 0; idx < this.Windows.Count; idx++)
+			{
+				window = this.Windows[idx];
+
 				window.WindowPos = GUILayout.Window(
 					this.core.WindowID,
 					window.WindowPos,
@@ -127,24 +135,29 @@
 
 			if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false)))
 			{
-				foreach (HUDWindow window in this.Windows)
+				HUDWindow window;
+				for (int idx = 0; idx < this.Windows.Count; idx++)
 				{
+					window = this.Windows[idx];
+
 					window.WindowPos = new Rect(window.defaultWindowPos);
 				}
 			}
 
-			this.positionsLocked.value = GUITools.Toggle(this.positionsLocked, "Lock HUD Positions");
-		}
-
-		public override void LoadConfig()
-		{
-			base.LoadConfig();
-
-			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_HUDModule>();
+			this.positionsLocked.value = Layout.Toggle(this.positionsLocked, "Lock HUD Positions");
+		}
+
+		public override void LoadConfig(KSP.IO.PluginConfiguration config)
+		{
+			base.LoadConfig(config);
+
 			config.load();
 
-			foreach (HUDWindow window in this.Windows)
-			{
+			HUDWindow window;
+			for (int idx = 0; idx < this.Windows.Count; idx++)
+			{
+				window = this.Windows[idx];
+
 				string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
 				Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos);
 
@@ -152,12 +165,15 @@
 			}
 		}
 
-		public override void Save(KSP.IO.PluginConfiguration config)
-		{
-			base.Save(config);
-
-			foreach (HUDWindow window in this.Windows)
-			{
+		public override void Save(KSP.IO.PluginConfiguration config, string sceneKey)
+		{
+			base.Save(config, sceneKey);
+
+			HUDWindow window;
+			for (int idx = 0; idx < this.Windows.Count; idx++)
+			{
+				window = this.Windows[idx];
+
 				string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName);
 				config.SetValue(saveName, window.WindowPos);
 			}

--- a/API/VOID_Module.cs
+++ b/API/VOID_Module.cs
@@ -26,11 +26,13 @@
 // 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.
 
+// TODO: Remove ToadicusTools. prefixes after refactor is done.
+
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Reflection;
-using ToadicusTools;
+using ToadicusTools.Extensions;
+using ToadicusTools.GUIUtils;
 using UnityEngine;
 
 namespace VOID
@@ -68,24 +70,22 @@
 		{
 			get
 			{
-				if (
-					RenderingManager.fetch == null ||
-					RenderingManager.fetch.postDrawQueue == null ||
-					RenderingManager.fetch.postDrawQueue.Length < 4
-				)
-				{
-					return false;
-				}
-				else
-				{
-					Delegate callback = RenderingManager.fetch.postDrawQueue[3];
-					if (callback == null)
+				using (var log = ToadicusTools.DebugTools.PooledDebugLogger.New(this))
+				{
+					log.AppendFormat("this.core: {0}\n", this.core != null ? this.core.ToString() : "null");
+					if (this.core != null)
 					{
-						return false;
+						log.AppendFormat("this.core.MethodInPostRenderQueue(this.DrawGUI): {0}\n",
+							this.core.MethodInPostRenderQueue(this.DrawGUI));
 					}
 
-					return callback.GetInvocationList().Contains((Callback)this.DrawGUI);
-				}
+					log.AppendFormat("this.GUIRunning: {0}\n",
+						this.core != null && this.core.MethodInPostRenderQueue(this.DrawGUI));
+
+					log.Print(false);
+				}
+
+				return this.core != null && this.core.MethodInPostRenderQueue(this.DrawGUI);
 			}
 		}
 
@@ -117,16 +117,21 @@
 			{
 				if (this.validModes == null)
 				{
-					Tools.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute.");
-					foreach (var attr in this.GetType().GetCustomAttributes(false))
+					ToadicusTools.Logging.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute.");
+
+					object[] attributes = this.GetType().GetCustomAttributes(false);
+					object attr;
+					for (int idx = 0; idx < attributes.Length; idx++)
 					{
+						attr = attributes[idx];
+
 						if (attr is VOID_GameModesAttribute)
 						{
 							VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr;
 
 							this.validModes = addonAttr.ValidModes;
 
-							Tools.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set.");
+							ToadicusTools.Logging.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set.");
 
 							break;
 						}
@@ -143,7 +148,7 @@
 							Game.Modes.SCIENCE_SANDBOX
 						};
 
-						Tools.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight.");
+						ToadicusTools.Logging.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight.");
 					}
 				}
 
@@ -157,16 +162,20 @@
 			{
 				if (this.validScenes == null)
 				{
-					Tools.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute.");
-					foreach (var attr in this.GetType().GetCustomAttributes(false))
+					ToadicusTools.Logging.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute.");
+					object[] attributes = this.GetType().GetCustomAttributes(false);
+					object attr;
+					for (int idx = 0; idx < attributes.Length; idx++)
 					{
+						attr = attributes[idx];
+
 						if (attr is VOID_ScenesAttribute)
 						{
 							VOID_ScenesAttribute addonAttr = (VOID_ScenesAttribute)attr;
 
 							this.validScenes = addonAttr.ValidScenes;
 
-							Tools.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set.");
+							ToadicusTools.Logging.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set.");
 
 							break;
 						}
@@ -175,7 +184,7 @@
 					if (this.validScenes == null)
 					{
 						this.validScenes = new GameScenes[] { GameScenes.FLIGHT };
-						Tools.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight.");
+						ToadicusTools.Logging.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight.");
 					}
 				}
 
@@ -220,8 +229,8 @@
 				return;
 			}
 
-			Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
-			RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);
+			ToadicusTools.Logging.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
+			this.core.onPostRender += this.DrawGUI;
 		}
 
 		public virtual void StopGUI()
@@ -230,17 +239,16 @@
 			{
 				return;
 			}
-			Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
-			RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI);
-		}
-
-		public abstract void DrawGUI();
+			ToadicusTools.Logging.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
+			this.core.onPostRender -= this.DrawGUI;
+		}
+
+		public abstract void DrawGUI(object sender);
 
 		public virtual void DrawConfigurables() {}
 
-		public virtual void LoadConfig()
-		{
-			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Module> ();
+		public virtual void LoadConfig(KSP.IO.PluginConfiguration config)
+		{
 			config.load ();
 
 			if (this is VOIDCore)
@@ -253,30 +261,40 @@
 				}
 			}
 
-			foreach (var field in this.GetType().GetMembers(
-				BindingFlags.NonPublic |
-				BindingFlags.Public |
-				BindingFlags.Instance |
-				BindingFlags.FlattenHierarchy
-			))
-			{
-				if (!(field is FieldInfo || field is PropertyInfo))
+			MemberInfo[] members = this.GetType().GetMembers(
+				                         BindingFlags.NonPublic |
+				                         BindingFlags.Public |
+				                         BindingFlags.Instance |
+				                         BindingFlags.FlattenHierarchy
+			                         );
+			MemberInfo member;
+
+			for (int fIdx = 0; fIdx < members.Length; fIdx++)
+			{
+				member = members[fIdx];
+
+				if (!(member is FieldInfo || member is PropertyInfo))
 				{
 					continue;
 				}
 
-				if (field is PropertyInfo && (field as PropertyInfo).GetIndexParameters().Length > 0)
+				if (member is PropertyInfo && (member as PropertyInfo).GetIndexParameters().Length > 0)
 				{
 					continue;
 				}
 
-				object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
-
-				if (attrs.Length == 0) {
+				object[] attrs = member.GetCustomAttributes(typeof(AVOID_SaveValue), false);
+
+				AVOID_SaveValue attr;
+
+				if (attrs.Length > 0)
+				{
+					attr = (AVOID_SaveValue)attrs[0];
+				}
+				else
+				{
 					continue;
 				}
-
-				AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
 
 				string fieldName = string.Empty;
 
@@ -308,17 +326,17 @@
 					);
 				}
 
-				Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName));
+				ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName));
 
 				object fieldValue;
 
-				if (field is FieldInfo)
-				{
-					fieldValue = (field as FieldInfo).GetValue(this);
-				}
-				else
-				{
-					fieldValue = (field as PropertyInfo).GetValue(this, null);
+				if (member is FieldInfo)
+				{
+					fieldValue = (member as FieldInfo).GetValue(this);
+				}
+				else
+				{
+					fieldValue = (member as PropertyInfo).GetValue(this, null);
 				}
 
 				bool convertBack = false;
@@ -338,35 +356,61 @@
 					fieldValue = convertValue;
 				}
 
-				if (field is FieldInfo)
-				{
-					(field as FieldInfo).SetValue(this, fieldValue);
-				}
-				else
-				{
-					(field as PropertyInfo).SetValue(this, fieldValue, null);
-				}
-
-				Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));
-			}
-		}
-
-		public virtual void Save(KSP.IO.PluginConfiguration config)
-		{
-			foreach (var field in this.GetType().GetMembers(
-				BindingFlags.Instance |
+				if (member is FieldInfo)
+				{
+					(member as FieldInfo).SetValue(this, fieldValue);
+				}
+				else
+				{
+					(member as PropertyInfo).SetValue(this, fieldValue, null);
+				}
+
+				ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));
+			}
+		}
+
+		public virtual void Save(KSP.IO.PluginConfiguration config, string sceneKey)
+		{
+			if (config == null)
+			{
+				ToadicusTools.Logging.PostErrorMessage(
+					"{0}: config argument was null, bailing out.",
+					this.GetType().Name
+				);
+			}
+
+			if (sceneKey == null)
+			{
+				ToadicusTools.Logging.PostErrorMessage(
+					"{0}: sceneKey argument was null, bailing out.",
+					this.GetType().Name
+				);
+			}
+
+			MemberInfo[] members = this.GetType().GetMembers(
 				BindingFlags.NonPublic |
 				BindingFlags.Public |
+				BindingFlags.Instance |
 				BindingFlags.FlattenHierarchy
-				))
-			{
-				object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false);
-
-				if (attrs.Length == 0) {
+			);
+			MemberInfo member;
+
+			for (int fIdx = 0; fIdx < members.Length; fIdx++)
+			{
+				member = members[fIdx];
+
+				object[] attrs = member.GetCustomAttributes(typeof(AVOID_SaveValue), false);
+
+				AVOID_SaveValue attr;
+
+				if (attrs.Length > 0)
+				{
+					attr = (AVOID_SaveValue)attrs[0];
+				}
+				else
+				{
 					continue;
 				}
-
-				AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue;
 
 				string fieldName;
 
@@ -379,20 +423,20 @@
 					fieldName = string.Format(
 						"{0}_{1}_{2}",
 						this.GetType().Name,
-						Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
+						sceneKey,
 						attr.Name
 					);
 				}
 
 				object fieldValue;
 
-				if (field is FieldInfo)
-				{
-					fieldValue = (field as FieldInfo).GetValue(this);
-				}
-				else
-				{
-					fieldValue = (field as PropertyInfo).GetValue(this, null);
+				if (member is FieldInfo)
+				{
+					fieldValue = (member as FieldInfo).GetValue(this);
+				}
+				else
+				{
+					fieldValue = (member as PropertyInfo).GetValue(this, null);
 				}
 
 				if (fieldValue is IVOID_SaveValue)
@@ -402,7 +446,7 @@
 
 				config.SetValue(fieldName, fieldValue);
 
-				Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));
+				ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));
 			}
 		}
 	}
@@ -456,14 +500,20 @@
 				if (closeRect.Contains(Event.current.mousePosition))
 				{
 					this.Active = false;
+					this.removeUILock();
 				}
 			}
 
 			GUI.DragWindow();
 		}
 
-		public override void DrawGUI()
-		{
+		public override void DrawGUI(object sender)
+		{
+			if (this.core == null)
+			{
+				return;
+			}
+
 			GUI.skin = this.core.Skin;
 
 			Rect _Pos = this.WindowPos;
@@ -479,61 +529,68 @@
 
 			bool cursorInWindow = _Pos.Contains(Mouse.screenPos);
 
+			if (cursorInWindow)
+			{
+				this.setUILock();
+			}
+			else
+			{
+				this.removeUILock();
+			}
+
+			if (HighLogic.LoadedSceneIsEditor)
+			{
+				_Pos = WindowTools.ClampRectToEditorPad(_Pos);
+			}
+			else
+			{
+				_Pos = WindowTools.ClampRectToScreen(_Pos);
+			}
+
+			if (_Pos != this.WindowPos)
+			{
+				this.WindowPos = _Pos;
+				this.core.configDirty = true;
+			}
+		}
+
+		protected void setUILock()
+		{
 			switch (HighLogic.LoadedScene)
 			{
 				case GameScenes.EDITOR:
-					if (cursorInWindow)
-					{
-						InputLockManager.SetControlLock(
-							ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK |
-							ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY,
-							this.inputLockName
-						);
-						EditorLogic.fetch.Lock(false, false, false, this.inputLockName);
-					}
-					else
-					{
-						EditorLogic.fetch.Unlock(this.inputLockName);
-					}
+					InputLockManager.SetControlLock(
+						ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK |
+						ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY,
+						this.inputLockName
+					);
+					EditorLogic.fetch.Lock(false, false, false, this.inputLockName);
 					break;
 				case GameScenes.FLIGHT:
-					if (cursorInWindow)
-					{
-						InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);
-					}
-					else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None)
-					{
-						InputLockManager.RemoveControlLock(this.inputLockName);
-					}
+					InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);
 					break;
 				case GameScenes.SPACECENTER:
-					if (cursorInWindow)
-					{
-						InputLockManager.SetControlLock(
-							ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS,
-							this.inputLockName
-						);
-					}
-					else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None)
-					{
-						InputLockManager.RemoveControlLock(this.inputLockName);
-					}
+					InputLockManager.SetControlLock(
+						ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS,
+						this.inputLockName
+					);
 					break;
 			}
-
-			if (HighLogic.LoadedSceneIsEditor)
-			{
-				_Pos = Tools.ClampRectToEditorPad(_Pos);
-			}
-			else
-			{
-				_Pos = Tools.ClampRectToScreen(_Pos);
-			}
-
-			if (_Pos != this.WindowPos)
-			{
-				this.WindowPos = _Pos;
-				this.core.configDirty = true;
+		}
+
+		protected void removeUILock()
+		{
+			switch (HighLogic.LoadedScene)
+			{
+				case GameScenes.EDITOR:
+					EditorLogic.fetch.Unlock(this.inputLockName);
+					break;
+				case GameScenes.FLIGHT:
+					InputLockManager.RemoveControlLock(this.inputLockName);
+					break;
+				case GameScenes.SPACECENTER:
+					InputLockManager.RemoveControlLock(this.inputLockName);
+					break;
 			}
 		}
 	}

--- /dev/null
+++ b/API/VOID_SingletonCore.cs
@@ -1,1 +1,71 @@
+// VOID
+//
+// VOID_SingletonModule.cs
+//
+// Copyright © 2015, 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 System;
+using UnityEngine;
+
+namespace VOID
+{
+	public abstract class VOID_SingletonCore<T> : VOIDCore, IVOID_Module, IDisposable
+		where T : VOID_Module, new()
+	{
+		#region Singleton Members
+		/*
+		 * Static Members
+		 * */
+		protected static bool _initialized = false;
+
+		public static bool Initialized
+		{
+			get
+			{
+				return _initialized;
+			}
+		}
+
+		protected static T _instance;
+
+		public static T Instance
+		{
+			get
+			{
+				if (_instance == null)
+				{
+					_instance = new T();
+					_initialized = true;
+				}
+				return _instance;
+			}
+		}
+
+		public abstract void Dispose();
+		#endregion
+	}
+}
+
+

--- a/API/VOID_SingletonModule.cs
+++ /dev/null
@@ -1,67 +1,1 @@
-// VOID
-//
-// VOID_SingletonModule.cs
-//
-// Copyright © 2015, 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 System;
 
-namespace VOID
-{
-	public abstract class VOID_SingletonModule<T> : VOIDCore, IVOID_Module
-		where T : VOID_Module, new()
-	{
-		#region Singleton Members
-		/*
-		 * Static Members
-		 * */
-		protected static bool _initialized = false;
-
-		public static bool Initialized
-		{
-			get
-			{
-				return _initialized;
-			}
-		}
-
-		protected static T _instance;
-
-		public static T Instance
-		{
-			get
-			{
-				if (_instance == null)
-				{
-					_instance = new T();
-					_initialized = true;
-				}
-				return _instance;
-			}
-		}
-		#endregion
-	}
-}
-
-

--- /dev/null
+++ b/API/VOID_SingletonWindow.cs
@@ -1,1 +1,73 @@
+// VOID
+//
+// VOID_SingletonModule.cs
+//
+// Copyright © 2015, 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 System;
 
+namespace VOID
+{
+	public abstract class VOID_SingletonWindow<T> : VOID_WindowModule, IVOID_Module, IDisposable
+		where T : VOID_WindowModule, new()
+	{
+		#region Singleton Members
+		/*
+		 * Static Members
+		 * */
+		protected static bool _initialized = false;
+
+		public static bool Initialized
+		{
+			get
+			{
+				return _initialized;
+			}
+		}
+
+		protected static T _instance;
+
+		public static T Instance
+		{
+			get
+			{
+				if (_instance == null)
+				{
+					_instance = new T();
+					_initialized = true;
+				}
+				return _instance;
+			}
+		}
+
+		public virtual void Dispose()
+		{
+			_instance = null;
+			_initialized = false;
+		}
+		#endregion
+	}
+}
+
+

--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -39,10 +39,9 @@
 // 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.16.4.*")]
+[assembly: AssemblyVersion("0.19.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)]
 //[assembly: AssemblyKeyFile("")]
 
-

--- a/Tools/VOID_DataValue.cs
+++ b/Tools/VOID_DataValue.cs
@@ -26,8 +26,11 @@
 // 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.
 
+// TODO: Remove ToadicusTools. prefixes after refactor is done.
+
 using System;
-using ToadicusTools;
+using ToadicusTools.MuMechTools;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -106,8 +109,26 @@
 			return (T)this.cache;
 		}
 
-		public virtual string ValueUnitString() {
-			return this.Value.ToString() + this.Units;
+		public virtual string ValueUnitString()
+		{
+			if (this.Value == null || this.Units == null)
+			{
+				using (PooledStringBuilder sb = PooledStringBuilder.Get())
+				{
+					if (this.Value == null)
+					{
+						sb.AppendFormat("{0}: Value is null during ValueUnitString\n", this.Label);
+					}
+					if (this.Units == null)
+					{
+						sb.AppendFormat("{0}: Units is null during ValueUnitString\n", this.Label);
+					}
+
+					ToadicusTools.Logging.PostErrorMessage(sb.ToString());
+				}
+			}
+
+			return string.Format("{0}{1}", this.Value == null ? "NULL" : this.Value.ToString(), this.Units);
 		}
 
 		public virtual void DoGUIHorizontal()
@@ -148,7 +169,7 @@
 	public abstract class VOID_NumValue<T> : VOID_DataValue<T>, IFormattable
 		where T : IFormattable, IConvertible, IComparable
 	{
-		public static IFormatProvider formatProvider = Tools.SIFormatter;
+		public static IFormatProvider formatProvider = SIFormatProvider.SIFormatter;
 
 		public static implicit operator Double(VOID_NumValue<T> v)
 		{
@@ -218,7 +239,7 @@
 		{
 			return string.Format (
 				"{0}{1}",
-				Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude),
+				MuMechTools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude),
 				this.Units
 			);
 		}
@@ -229,12 +250,12 @@
 		}
 		
 		public virtual string ValueUnitString(int digits) {
-			return Tools.MuMech_ToSI(this, digits) + this.Units;
+			return string.Format("{0}{1}", SIFormatProvider.ToSI(this, digits), Units);
 		}
 
 		public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude)
 		{
-			return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units;
+			return MuMechTools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units;
 		}
 
 		public virtual void DoGUIHorizontal(string format)
@@ -264,26 +285,17 @@
 
 		public virtual int DoGUIHorizontalPrec(int digits)
 		{
-			double magnitude;
-			double magLimit;
-
-			magnitude = Math.Log10(Math.Abs((double)this));
-
-			magLimit = Math.Max(Math.Abs(magnitude), 3d) + 3d;
-			magLimit = Math.Round(Math.Ceiling(magLimit / 3f)) * 3d;
+			if (digits < 0 || digits > 8)
+			{
+				digits = 5;
+			}
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true));
 			GUILayout.FlexibleSpace();
 
-			if (magnitude >= 0)
-			{
-				GUILayout.Label(this.ValueUnitString(3, int.MinValue, (int)magnitude - digits), GUILayout.ExpandWidth(false));
-			}
-			else
-			{
-				GUILayout.Label(this.ValueUnitString(3, (int)magnitude + digits, int.MaxValue), GUILayout.ExpandWidth(false));
-			}
+			GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false));
+
 			GUILayout.EndHorizontal();
 
 			if (Event.current.type == EventType.mouseUp)
@@ -291,33 +303,28 @@
 				Rect lastRect = GUILayoutUtility.GetLastRect();
 				if (lastRect.Contains(Event.current.mousePosition))
 				{
-					Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1} within magLimit {2}.",
+					ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Changing digits from {1}",
 						this.GetType().Name,
-						digits,
-						magLimit));
+						digits
+					));
 
 					if (Event.current.button == 0)
 					{
-						digits = (digits + 3) % (int)magLimit;
+						digits = (digits + 3) % 9;
 					}
 					else if (Event.current.button == 1)
 					{
-						digits = (digits - 3) % (int)magLimit;
+						digits = (digits - 3) % 9;
 					}
 
 					if (digits < 0)
 					{
-						digits += (int)magLimit;
-					}
-
-					Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}." +
-						"\n\tNew minMagnitude: {2}, maxMagnitude: {3}" +
-						"\n\tMagnitude: {4}",
+						digits += 9;
+					}
+
+					ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Changed digits to {1}.",
 						this.GetType().Name,
-						digits,
-						magnitude >= 0 ? int.MinValue : (int)magnitude - 4 + digits,
-						magnitude >= 0 ? (int)magnitude - digits : int.MaxValue,
-						magnitude
+						digits
 					));
 				}
 			}
@@ -346,9 +353,9 @@
 		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)
+	public class VOID_Vector3Value : VOID_DataValue<Vector3>
+	{
+		public VOID_Vector3Value(string Label, Func<Vector3> ValueFunc, string Units)
 			: base(Label, ValueFunc, Units)
 		{}
 

--- a/Tools/VOID_SaveValue.cs
+++ b/Tools/VOID_SaveValue.cs
@@ -26,10 +26,11 @@
 // 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.
 
+// TODO: Remove ToadicusTools. prefixes after refactor is done.
+
 using KSP;
 using System;
 using System.Collections.Generic;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
@@ -65,13 +66,11 @@
 			{
 				if (this.Core != null && !System.Object.Equals(this._value, value))
 				{
-					Tools.PostDebugMessage (string.Format (
+					ToadicusTools.Logging.PostDebugMessage (string.Format (
 						"VOID: Dirtying config for type {0}." +
-						"\n\t Old Value: {2}, New Value: {3}" +
-						"\n\t Object.Equals(New, Old): {4}\n" +
-						"{1}",
+						"\n\t Old Value: {1}, New Value: {2}" +
+						"\n\t Object.Equals(New, Old): {3}\n" +
 						this._type,
-						new System.Diagnostics.StackTrace().ToString(),
 						this._value,
 						value,
 						System.Object.Equals(this._value, value)

--- /dev/null
+++ b/Tools/VOID_StageExtensions.cs
@@ -1,1 +1,38 @@
+// VOID © 2015 toadicus
+//
+// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
+// copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
 
+using KerbalEngineer.VesselSimulator;
+using KSP;
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace VOID
+{
+	public static class VOID_StageExtensions
+	{
+		public static double NominalThrust(this Stage stage)
+		{
+			if (stage.actualThrust == 0d)
+			{
+				return stage.thrust;
+			}
+			else
+			{
+				return stage.actualThrust;
+			}
+		}
+
+		public static double MassFlow(this Stage stage)
+		{
+			double stageIsp = VOID_Data.Core.LastStage.isp;
+			double stageThrust = stage.NominalThrust();
+
+			return stageThrust / (stageIsp * VOID_Data.KerbinGee);
+		}
+	}
+}
+
+

--- a/Tools/VOID_Tools.cs
+++ b/Tools/VOID_Tools.cs
@@ -316,6 +316,7 @@
 		}
 		#endregion
 
+		#region WINDOW_UTILS
 		private static Dictionary<int, GUI.WindowFunction> functionCache;
 		public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func)
 		{
@@ -334,21 +335,16 @@
 					{
 						func(id);
 					}
-					#if DEBUG
+					#if !DEBUG
 					catch (ArgumentException)
-					#else
-					catch (ArgumentException)
-					#endif
 					{
 						Debug.LogWarning(
-							string.Format("[{0}]: ArgumentException caught during window call.  This is not a bug.",
+							string.Format("[{0}]: ArgumentException caught during window call." +
+								"  This may not be a bug when occuring during scene changes.",
 								func.Target.GetType().Name
 							));
-
-						/*#if DEBUG
-						Debug.LogException(ex);
-						#endif*/
 					}
+					#endif
 					catch (Exception ex)
 					{
 						Debug.LogError(
@@ -377,7 +373,9 @@
 				}
 			}
 		}
-
+		#endregion
+
+		#region TIME_UTILS
 		/// <summary>
 		/// Formats the interval given in seconds as a human-friendly
 		/// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds.
@@ -411,28 +409,55 @@
 			{
 				get
 				{
-					if (GameSettings.KERBIN_TIME)
+					VOID_TimeScale flags = VOID_Data.Core.TimeScale &
+						(VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE);
+
+					switch (flags)
 					{
-						return 21600d;
+						// Earth day, sidereal
+						case 0:
+							return 86164.1d;
+						// Earth day, solar (also rounded)
+						case VOID_TimeScale.ROUNDED_SCALE | VOID_TimeScale.SOLAR_DAY:
+						case VOID_TimeScale.ROUNDED_SCALE:
+						case VOID_TimeScale.SOLAR_DAY:
+							return 86400d;
+						// Kerbin day, solar
+						case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY:
+							return 21650.813d;
+						// Kerbin day, sidereal (also rounded)
+						default:
+							return 21600d;
 					}
-					else
+				}
+			}
+
+			public static double SecondsPerYear
+			{
+				get
+				{
+					VOID_TimeScale flags = VOID_Data.Core.TimeScale &
+						(VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE);
+
+					switch (flags)
 					{
-						return 86164.1d;
-					}
-				}
-			}
-
-			public static double SecondsPerYear
-			{
-				get
-				{
-					if (GameSettings.KERBIN_TIME)
-					{
-						return 9203545d;
-					}
-					else
-					{
-						return 31558149d;
+						// Earth year, rounded
+						case VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE:
+						case VOID_TimeScale.ROUNDED_SCALE:
+							return 60 * 60 * 24 * 365;
+						// Kerbin year, rounded
+						case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE:
+						case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.ROUNDED_SCALE:
+							return 60 * 60 * 6 * 426;
+						// Earth year, solar time
+						case VOID_TimeScale.SOLAR_DAY:
+							return 31556925.2507328;
+						// Earth year, sidereal time
+						case 0:
+							return 31558149.7635456d;
+						// Kerbin year, solar & sidereal time
+						default:
+							return 9203544.61750141d;
 					}
 				}
 			}
@@ -545,6 +570,7 @@
 
 			public UnpackedTime() : this(0, 0, 0, 0, 0d) {}
 		}
+		#endregion
 
 		public static string UppercaseFirst(string s)
 		{
@@ -678,8 +704,8 @@
 
 		public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target)   //calculates phase angle between the current body and target body
 		{
-			Vector3d vecthis = new Vector3d();
-			Vector3d vectarget = new Vector3d();
+			Vector3 vecthis = new Vector3();
+			Vector3 vectarget = new Vector3();
 			vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
 
 			if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))
@@ -691,15 +717,15 @@
 				vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
 			}
 
-			vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);
-			vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);
-
-			Vector3d prograde = new Vector3d();
-			prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;
-
-			double phase = Vector3d.Angle(vecthis, vectarget);
-
-			if (Vector3d.Angle(prograde, vectarget) > 90)
+			vecthis = Vector3.Project(new Vector3(vecthis.x, 0, vecthis.z), vecthis);
+			vectarget = Vector3.Project(new Vector3(vectarget.x, 0, vectarget.z), vectarget);
+
+			Vector3 prograde = new Vector3();
+			prograde = Quaternion.AngleAxis(90, Vector3.forward) * vecthis;
+
+			double phase = Vector3.Angle(vecthis, vectarget);
+
+			if (Vector3.Angle(prograde, vectarget) > 90)
 				phase = 360 - phase;
 
 			return (phase + 360) % 360;
@@ -991,75 +1017,75 @@
 	{
 		public int Compare(CelestialBody bodyA, CelestialBody bodyB)
 		{
-			Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB);
+			Logging.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB);
 
 			if (bodyA == null && bodyB == null)
 			{
-				Tools.PostDebugMessage(this, "both bodies are null, returning 0");
+				Logging.PostDebugMessage(this, "both bodies are null, returning 0");
 				return 0;
 			}
 			if (bodyA == null)
 			{
-				Tools.PostDebugMessage(this, "bodyA is null, returning -1");
+				Logging.PostDebugMessage(this, "bodyA is null, returning -1");
 				return -1;
 			}
 			if (bodyB == null)
 			{
-				Tools.PostDebugMessage(this, "bodyB is null, returning 1");
+				Logging.PostDebugMessage(this, "bodyB is null, returning 1");
 				return 1;
 			}
 
-			Tools.PostDebugMessage(this, "bodies are not null, carrying on");
+			Logging.PostDebugMessage(this, "bodies are not null, carrying on");
 
 			if (object.ReferenceEquals(bodyA, bodyB))
 			{
-				Tools.PostDebugMessage(this, "bodies are equal, returning 0");
+				Logging.PostDebugMessage(this, "bodies are equal, returning 0");
 				return 0;
 			}
 
-			Tools.PostDebugMessage(this, "bodies are not equal, carrying on");
+			Logging.PostDebugMessage(this, "bodies are not equal, carrying on");
 
 			if (bodyA.orbitDriver == null)
 			{
-				Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1");
+				Logging.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1");
 				return 1;
 			}
 			if (bodyB.orbitDriver == null)
 			{
-				Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1");
+				Logging.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1");
 				return -1;
 			}
 
-			Tools.PostDebugMessage(this, "orbits are not null, carrying on");
+			Logging.PostDebugMessage(this, "orbits are not null, carrying on");
 
 			if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody)
 			{
-				Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs");
+				Logging.PostDebugMessage(this, "bodies share a parent, comparing SMAs");
 				return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis);
 			}
 
-			Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on");
+			Logging.PostDebugMessage(this, "orbits do not share a parent, carrying on");
 
 			if (bodyA.hasAncestor(bodyB))
 			{
-				Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1");
+				Logging.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1");
 				return -1;
 			}
 			if (bodyB.hasAncestor(bodyA))
 			{
-				Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1");
+				Logging.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1");
 				return 1;
 			}
 
-			Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one");
+			Logging.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one");
 
 			if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB))
 			{
-				Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName);
+				Logging.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName);
 				return this.Compare(bodyA, bodyB);
 			}
 
-			Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName);
+			Logging.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName);
 
 			return 0;
 		}

--- a/VOID.csproj
+++ b/VOID.csproj
@@ -106,13 +106,16 @@
     <Compile Include="Tools\VOID_DataValue.cs" />
     <Compile Include="Tools\VOID_SaveValue.cs" />
     <Compile Include="API\VOID_HUDModule.cs" />
-    <Compile Include="API\VOID_SingletonModule.cs" />
     <Compile Include="API\Attributes\VOID_ScenesAttribute.cs" />
     <Compile Include="API\Attributes\AVOID_SaveValue.cs" />
     <Compile Include="API\VOIDMaster.cs" />
     <Compile Include="API\Attributes\VOID_GameModesAttribute.cs" />
     <Compile Include="VOID_ConfigWindow.cs" />
     <Compile Include="Tools\VOID_Localization.cs" />
+    <Compile Include="Tools\VOID_StageExtensions.cs" />
+    <Compile Include="API\VOID_SingletonCore.cs" />
+    <Compile Include="API\VOID_SingletonWindow.cs" />
+    <Compile Include="API\Enums.cs" />
   </ItemGroup>
   <ProjectExtensions>
     <MonoDevelop>
@@ -132,6 +135,15 @@
     </Reference>
     <Reference Include="UnityEngine">
       <HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath>
+    </Reference>
+    <Reference Include="KSPUtil">
+      <HintPath>..\_KSPAssemblies\KSPUtil.dll</HintPath>
+    </Reference>
+    <Reference Include="UnityEngine.UI">
+      <HintPath>..\_KSPAssemblies\UnityEngine.UI.dll</HintPath>
+    </Reference>
+    <Reference Include="Assembly-CSharp-firstpass">
+      <HintPath>..\_KSPAssemblies\Assembly-CSharp-firstpass.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup>

--- a/VOIDCore_Editor.cs
+++ b/VOIDCore_Editor.cs
@@ -30,8 +30,6 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
@@ -39,6 +37,15 @@
 	[VOID_Scenes(GameScenes.EDITOR)]
 	public class VOIDCore_Editor : VOIDCore_Generic<VOIDCore_Editor>
 	{
+		public override string SceneKey
+		{
+			get
+			{
+				return "EDITOR";
+			}
+		}
+
+
 		public override void FixedUpdate() {}
 	}
 }

--- a/VOIDCore_Flight.cs
+++ b/VOIDCore_Flight.cs
@@ -29,18 +29,27 @@
 using KSP;
 using System;
 using UnityEngine;
-using ToadicusTools;
+using ToadicusTools.GUIUtils;
 
 namespace VOID
 {
 	[VOID_Scenes(GameScenes.FLIGHT)]
 	public class VOIDCore_Flight : VOIDCore_Generic<VOIDCore_Flight>
 	{
+		public override string SceneKey
+		{
+			get
+			{
+				return "FLIGHT";
+			}
+		}
+
+
 		public override void DrawConfigurables()
 		{
 			if (HighLogic.LoadedSceneIsFlight)
 			{
-				this.consumeResource.value = GUITools.Toggle(this.consumeResource, "Consume Resources");
+				this.consumeResource.value = Layout.Toggle(this.consumeResource, "Consume Resources");
 			}
 
 			base.DrawConfigurables();

--- a/VOIDCore_Generic.cs
+++ b/VOIDCore_Generic.cs
@@ -26,18 +26,24 @@
 // 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 KerbalEngineer.Editor;
+using KerbalEngineer.Helpers;
 using KerbalEngineer.VesselSimulator;
 using KSP;
+using KSP.UI.Screens;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Text;
 using ToadicusTools;
+using ToadicusTools.DebugTools;
+using ToadicusTools.Extensions;
+using ToadicusTools.GUIUtils;
+using ToadicusTools.Wrappers;
 using UnityEngine;
 
 namespace VOID
 {
-	public abstract class VOIDCore_Generic<T> : VOID_SingletonModule<T>, IVOID_Module, IDisposable
+	public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable
 		where T : VOID_Module, new()
 	{
 		/*
@@ -58,7 +64,8 @@
 		protected string VOIDIconOffActivePath;
 		protected string VOIDIconOffInactivePath;
 
-		private bool _useToolbarManager;
+		[AVOID_SaveValue("useToolbarManager")]
+		protected VOID_SaveValue<bool> useToolbarManager;
 
 		protected GUIStyle iconStyle;
 
@@ -90,8 +97,12 @@
 		[AVOID_SaveValue("vesselSimActive")]
 		protected VOID_SaveValue<bool> vesselSimActive;
 
-		// Vessel Type Housekeeping
+		[AVOID_SaveValue("timeScaleFlags")]
+		protected VOID_SaveValue<UInt32> timeScaleFlags;
+
+		// Load-up housekeeping
 		protected bool vesselTypesLoaded = false;
+		protected bool simManagerLoaded = false;
 
 		protected string defaultSkin = "KSP window 2";
 
@@ -100,7 +111,7 @@
 		protected int skinIdx;
 
 		protected Dictionary<string, GUISkin> validSkins;
-		protected string[] skinNames;
+		protected List<string> skinNames;
 		protected string[] forbiddenSkins =
 			{
 				"PlaqueDialogSkin",
@@ -119,19 +130,27 @@
 
 		public override bool configDirty { get; set; }
 
-		internal IButton ToolbarButton;
-
-		internal ApplicationLauncherButton AppLauncherButton;
+		protected IButton ToolbarButton;
+		protected ApplicationLauncherButton AppLauncherButton;
+		protected IconState iconState;
 
 		/*
 		 * Properties
 		 * */
-
-		public override IList<CelestialBody> AllBodies
+		public override bool Active
 		{
 			get
 			{
-				return FlightGlobals.Bodies.AsReadOnly();
+				return base.Active;
+			}
+			set
+			{
+				if (value != base.Active)
+				{
+					this.SetIconTexture(this.powerState | this.activeState);
+				}
+
+				base.Active = value;
 			}
 		}
 
@@ -242,6 +261,18 @@
 			protected set;
 		}
 
+		public override VOID_TimeScale TimeScale
+		{
+			get
+			{
+				return (VOID_TimeScale)this.timeScaleFlags.value;
+			}
+			protected set
+			{
+				this.timeScaleFlags.value = (UInt32)value;
+			}
+		}
+
 		protected IconState activeState
 		{
 			get
@@ -279,58 +310,34 @@
 			get
 			{
 				return HighLogic.LoadedScene.ToAppScenes();
-			}
-		}
-
-		protected bool useToolbarManager
-		{
-			get
-			{
-				return _useToolbarManager & ToolbarManager.ToolbarAvailable;
-			}
-			set
-			{
-				if (_useToolbarManager == value)
-				{
-					return;
-				}
-
-				if (value == false && this.ToolbarButton != null)
-				{
-					this.ToolbarButton.Destroy();
-					this.ToolbarButton = null;
-				}
-				if (value == true)
-				{
-					if (this.AppLauncherButton != null)
-					{
-						ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
-						this.AppLauncherButton = null;
-					}
-
-					this.InitializeToolbarButton();
-				}
-
-				_useToolbarManager = value;
 			}
 		}
 
 		/*
 		 * Events
 		 * */
+		// public 
 		public override event VOIDEventHandler onApplicationQuit;
 		public override event VOIDEventHandler onSkinChanged;
+		public override event VOIDEventHandler onUpdate;
+
+		public override event VOIDEventHandler onPreForEach;
+		public override event VOIDForEachPartHandler onForEachPart;
+		public override event VOIDForEachPartModuleHandler onForEachModule;
+		public override event VOIDEventHandler onPostForEach;
 
 		/*
 		 * Methods
 		 * */
-		public override void DrawGUI()
+		public override void DrawGUI(object sender)
 		{
 			this.windowID = this.windowBaseID;
 
 			if (!this.modulesLoaded)
 			{
 				this.LoadModulesOfType<IVOID_Module>();
+
+				FireOnModulesLoaded(this);
 			}
 
 			if (!this.skinsLoaded)
@@ -344,38 +351,26 @@
 			{
 				this.LoadGUIStyles();
 
-				Tools.PostDebugMessage(
+				Logging.PostDebugMessage(
 					this,
 					"ToolbarAvailable: {0}, UseToobarManager: {1}",
 					ToolbarManager.ToolbarAvailable,
 					this.useToolbarManager);
 			}
 
-			if (!this.useToolbarManager)
-			{
-				if (this.AppLauncherButton == null)
-				{
-					Tools.PostDebugMessage(this,
-						"UseToolbarManager = false (ToolbarAvailable = {0}) and " +
-						"AppLauncherButton is null, making AppLauncher button.",
-						ToolbarManager.ToolbarAvailable
-					);
-					this.InitializeAppLauncherButton();
-				}
-			}
-			else if (this.ToolbarButton == null)
-			{
-				Tools.PostDebugMessage(this,
-					"UseToolbarManager = true (ToolbarAvailable = {0}) and " +
-					"ToolbarButton is null, making Toolbar button.",
-					ToolbarManager.ToolbarAvailable
-				);
-				this.InitializeToolbarButton();
+			if (
+				this.iconState != (this.powerState | this.activeState) ||
+				(this.VOIDIconTexture == null && this.AppLauncherButton != null)
+			)
+			{
+				this.iconState = this.powerState | this.activeState;
+
+				this.SetIconTexture(this.iconState);
 			}
 
 			if (this.Active)
 			{
-				base.DrawGUI();
+				base.DrawGUI(sender);
 			}
 		}
 
@@ -395,17 +390,72 @@
 				)
 			)
 			{
-				Tools.PostDebugMessage(this, "Updating SimManager.");
+				Logging.PostDebugMessage(this, "Updating SimManager.");
 				this.UpdateSimManager();
-			}
-
-			if (!this.GUIRunning)
+
+				VOIDForEachPartArgs partArgs;
+				VOIDForEachPartModuleArgs moduleArgs;
+
+				Part part;
+				PartModule partModule;
+
+				bool doForEachPart = this.onForEachPart != null;
+				bool doForEachModule = this.onForEachModule != null;
+
+				if (
+					(doForEachPart || doForEachModule) &&
+					(this.Vessel != null) &&
+					(this.Vessel.parts != null) &&
+					this.timeToUpdate
+				)
+				{
+					if (this.onPreForEach != null)
+					{
+						this.onPreForEach(this);
+					}
+
+					for (int pIdx = 0; pIdx < this.Vessel.parts.Count; pIdx++)
+					{
+						part = this.Vessel.parts[pIdx];
+						partArgs = new VOIDForEachPartArgs(part);
+
+						if (doForEachPart)
+						{
+							this.onForEachPart(this, partArgs);
+						}
+
+						if (doForEachModule && part.Modules != null)
+						{
+							for (int mIdx = 0; mIdx < part.Modules.Count; mIdx++)
+							{
+								partModule = part.Modules[mIdx];
+								moduleArgs = new VOIDForEachPartModuleArgs(partModule);
+
+								if (doForEachModule)
+								{
+									this.onForEachModule(this, moduleArgs);
+								}
+							}
+						}
+					}
+
+					if (this.onPostForEach!= null)
+					{
+						this.onPostForEach(this);
+					}
+				}
+			}
+
+			if (!this.GUIRunning && !this.gameUIHidden)
 			{
 				this.StartGUI();
 			}
 
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				if (
 					!module.GUIRunning &&
 					module.Active &&
@@ -441,7 +491,84 @@
 				}
 			}
 
-			this.CheckAndSave();
+			if (ToolbarManager.ToolbarAvailable && this.useToolbarManager)
+			{
+				if (this.ToolbarButton == null)
+				{
+					this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");
+					this.ToolbarButton.Text = this.VoidName;
+					this.SetIconTexture(this.powerState | this.activeState);
+
+					this.ToolbarButton.Visible = true;
+
+					this.ToolbarButton.OnClick += 
+						(e) =>
+						{
+							this.ToggleMainWindow();
+						};
+
+					Logging.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));
+				}
+
+				if (this.AppLauncherButton != null)
+				{
+					ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
+					this.AppLauncherButton = null;
+				}
+			}
+			else
+			{
+				if (this.AppLauncherButton == null)
+				{
+					if (ApplicationLauncher.Instance != null)
+					{
+						this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication(
+							this.ToggleMainWindow, this.ToggleMainWindow,
+							this.appIconVisibleScenes,
+							this.VOIDIconTexture
+						);
+
+						Logging.PostDebugMessage(
+							this,
+							"AppLauncherButton initialized in {0}",
+							Enum.GetName(
+								typeof(GameScenes),
+								HighLogic.LoadedScene
+							)
+						);
+					}
+				}
+
+				if (this.ToolbarButton != null)
+				{
+					this.ToolbarButton.Destroy();
+					this.ToolbarButton = null;
+				}
+			}
+
+			if (this.onUpdate != null)
+			{
+				this.onUpdate(this);
+			}
+
+			this.saveTimer += Time.deltaTime;
+
+			if (this.modulesLoaded && this.saveTimer > 2f)
+			{
+				if (this.configDirty)
+				{
+
+					Logging.PostDebugMessage(string.Format(
+							"{0}: Time to save, checking if configDirty: {1}",
+							this.GetType().Name,
+							this.configDirty
+						));
+
+					this.SaveConfig();
+					this.saveTimer = 0;
+				}
+			}
+
 			this.UpdateTimer += Time.deltaTime;
 		}
 
@@ -470,12 +597,14 @@
 				if (this.powerAvailable != newPowerState)
 				{
 					this.powerAvailable = newPowerState;
-					this.SetIconTexture(this.powerState | this.activeState);
-				}
-			}
-
-			foreach (IVOID_Module module in this.modules)
-			{
+				}
+			}
+
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				if (module is IVOID_BehaviorModule)
 				{
 					((IVOID_BehaviorModule)module).FixedUpdate();
@@ -485,14 +614,19 @@
 
 		public void OnDestroy()
 		{
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				if (module is IVOID_BehaviorModule)
 				{
 					((IVOID_BehaviorModule)module).OnDestroy();
 				}
 			}
 
+			FireOnModulesDestroyed(this);
+
 			this.Dispose();
 		}
 
@@ -510,7 +644,8 @@
 		{
 			if (!this.GUIRunning)
 			{
-				RenderingManager.AddToPostDrawQueue(3, this.DrawGUI);
+				Logging.PostDebugMessage(this, "Adding DrawGUI to onGui");
+				this.onPostRender += this.DrawGUI;
 			}
 		}
 
@@ -518,8 +653,11 @@
 		{
 			this.StopGUI();
 
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				module.StopGUI();
 				module.StartGUI();
 			}
@@ -541,20 +679,22 @@
 					if (GUILayout.Button("Power " + str))
 					{
 						togglePower.value = !togglePower;
-						this.SetIconTexture(this.powerState | this.activeState);
 					}
 				}
 
 				if (togglePower || !HighLogic.LoadedSceneIsFlight)
 				{
-					foreach (IVOID_Module module in this.modules)
+					IVOID_Module module;
+					for (int idx = 0; idx < this.modules.Count; idx++)
 					{
+						module = this.modules[idx];
+
 						if (module is VOID_ConfigWindow)
 						{
 							continue;
 						}
 
-						module.Active = GUITools.Toggle(module.Active, module.Name);
+						module.Active = Layout.Toggle(module.Active, module.Name);
 					}
 				}
 			}
@@ -563,7 +703,7 @@
 				GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
 			}
 
-			VOID_ConfigWindow.Instance.Active = GUITools.Toggle(
+			VOID_ConfigWindow.Instance.Active = Layout.Toggle(
 				VOID_ConfigWindow.Instance.Active,
 				"Configuration"
 			);
@@ -577,10 +717,61 @@
 		{
 			GUIContent _content;
 
-			this.useToolbarManager = GUITools.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available");
-
-			this.vesselSimActive.value = GUITools.Toggle(this.vesselSimActive.value,
+			this.useToolbarManager.value = Layout.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available");
+
+			this.vesselSimActive.value = Layout.Toggle(this.vesselSimActive.value,
 				"Enable Engineering Calculations");
+
+			bool useEarthTime = (this.TimeScale & VOID_TimeScale.KERBIN_TIME) == 0u;
+			bool useSiderealTime = (this.TimeScale & VOID_TimeScale.SOLAR_DAY) == 0u;
+			bool useRoundedScale = (this.TimeScale & VOID_TimeScale.ROUNDED_SCALE) != 0u;
+
+			useEarthTime = Layout.Toggle(useEarthTime, "Use Earth Time (changes KSP option)");
+
+			GameSettings.KERBIN_TIME = !useEarthTime;
+
+			useSiderealTime = Layout.Toggle(
+				useSiderealTime,
+				string.Format(
+					"Time Scale: {0}",
+					useSiderealTime ? "Sidereal" : "Solar"
+				)
+			);
+
+			useRoundedScale = Layout.Toggle(
+				useRoundedScale,
+				string.Format(
+					"Time Scale: {0}",
+					useRoundedScale ? "Rounded" : "True"
+				)
+			);
+
+			if (useEarthTime)
+			{
+				this.TimeScale &= ~VOID_TimeScale.KERBIN_TIME;
+			}
+			else
+			{
+				this.TimeScale |= VOID_TimeScale.KERBIN_TIME;
+			}
+
+			if (useSiderealTime)
+			{
+				this.TimeScale &= ~VOID_TimeScale.SOLAR_DAY;
+			}
+			else
+			{
+				this.TimeScale |= VOID_TimeScale.SOLAR_DAY;
+			}
+
+			if (useRoundedScale)
+			{
+				this.TimeScale |= VOID_TimeScale.ROUNDED_SCALE;
+			}
+			else
+			{
+				this.TimeScale &= ~VOID_TimeScale.ROUNDED_SCALE;
+			}
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 
@@ -593,7 +784,7 @@
 			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
 			{
 				this.skinIdx--;
-				Tools.PostDebugMessage(string.Format(
+				Logging.PostDebugMessage(string.Format(
 					"{0}: new this.skinIdx = {1} :: skin_list.Count = {2}",
 					this.GetType().Name,
 					this.skinName,
@@ -610,7 +801,7 @@
 			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
 			{
 				this.skinIdx++;
-				Tools.PostDebugMessage(string.Format(
+				Logging.PostDebugMessage(string.Format(
 					"{0}: new this.skinIdx = {1} :: skin_list.Count = {2}",
 					this.GetType().Name,
 					this.skinName,
@@ -618,10 +809,10 @@
 				));
 			}
 
-			this.skinIdx %= this.skinNames.Length;
+			this.skinIdx %= this.skinNames.Count;
 			if (this.skinIdx < 0)
 			{
-				this.skinIdx += this.skinNames.Length;
+				this.skinIdx += this.skinNames.Count;
 			}
 
 			if (this.skinName != skinNames[this.skinIdx])
@@ -648,112 +839,125 @@
 			}
 			GUILayout.EndHorizontal();
 
-			foreach (IVOID_Module mod in this.modules)
-			{
-				mod.DrawConfigurables();
-			}
-
-			this.FactoryReset = GUITools.Toggle(this.FactoryReset, "Factory Reset");
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
+				module.DrawConfigurables();
+			}
+
+			this.FactoryReset = Layout.Toggle(this.FactoryReset, "Factory Reset");
 		}
 
 		protected void UpdateSimManager()
 		{
-			if (SimManager.ResultsReady())
-			{
-				if (HighLogic.LoadedSceneIsEditor)
-				{
-					SimManager.Gravity = VOID_Data.KerbinGee;
-				}
-				else
-				{
-					double radius = this.Vessel.Radius();
-					SimManager.Gravity = this.Vessel.mainBody.gravParameter / (radius * radius);
-				}
-
-				SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)(this.UpdatePeriod * 1000d));
-
-				SimManager.TryStartSimulation();
-			}
+			if (HighLogic.LoadedSceneIsFlight)
+			{
+				double radius = this.Vessel.Radius();
+				SimManager.Gravity = this.Vessel.mainBody.gravParameter / (radius * radius);
+				SimManager.Atmosphere = this.Vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres;
+				SimManager.Mach = this.Vessel.mach;
+				BuildAdvanced.Altitude = this.Vessel.altitude;
+				CelestialBodies.SelectedBody = this.Vessel.mainBody;
+			}
+
 			#if DEBUG
-			else
-			{
-				Tools.PostDebugMessage(this, "VesselSimulator results not ready.");
-			}
+			SimManager.logOutput = true;
 			#endif
+
+			SimManager.TryStartSimulation();
+
+			Logging.PostDebugMessage(this, "Started Engineer simulation with Atmosphere={0} atm and Gravity={1} m/s²",
+				SimManager.Atmosphere,
+				SimManager.Gravity
+			);
 		}
 
 		protected void GetSimManagerResults()
 		{
-			Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
+			Logging.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
 
 			this.Stages = SimManager.Stages;
 
-			if (this.Stages != null)
-			{
-				this.LastStage = this.Stages.Last();
+			if (this.Stages != null && this.Stages.Length > 0)
+			{
+				this.LastStage = this.Stages[this.Stages.Length - 1];
 			}
 		}
 
 		protected void LoadModulesOfType<U>()
 		{
-			Tools.DebugLogger sb = Tools.DebugLogger.New(this);
-			sb.AppendLine("Loading modules...");
-
-			foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies)
-			{
-				foreach (Type loadedType in assy.assembly.GetExportedTypes())
-				{
-					if (
-						loadedType.IsInterface ||
-						loadedType.IsAbstract ||
-						!typeof(U).IsAssignableFrom(loadedType) ||
-						typeof(VOIDCore).IsAssignableFrom(loadedType)
-					)
+			using (PooledDebugLogger sb = PooledDebugLogger.New(this))
+			{
+				sb.AppendLine("Loading modules...");
+
+				AssemblyLoader.LoadedAssembly assy;
+				for (int aIdx = 0; aIdx < AssemblyLoader.loadedAssemblies.Count; aIdx++)
+				{
+					assy = AssemblyLoader.loadedAssemblies[aIdx];
+
+					Type[] loadedTypes = assy.assembly.GetExportedTypes();
+					Type loadedType;
+					for (int tIdx = 0; tIdx < loadedTypes.Length; tIdx++)
 					{
-						continue;
+						loadedType = loadedTypes[tIdx];
+
+						if (
+							loadedType.IsInterface ||
+							loadedType.IsAbstract ||
+							!typeof(U).IsAssignableFrom(loadedType) ||
+							typeof(VOIDCore).IsAssignableFrom(loadedType))
+						{
+							continue;
+						}
+
+						sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name);
+
+						try
+						{
+							this.LoadModule(loadedType);
+							sb.AppendLine("Success.");
+						}
+						catch (Exception ex)
+						{
+							sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name);
+
+							#if DEBUG
+						Debug.LogException(ex);
+							#endif
+						}
 					}
-
-					sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name);
-
-					try
-					{
-						this.LoadModule(loadedType);
-						sb.AppendLine("Success.");
-					}
-					catch (Exception ex)
-					{
-						sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name);
-
-						#if DEBUG
-						Debug.LogException(ex);
-						#endif
-					}
-				}
-			}
-
-			this.modulesLoaded = true;
-
-			sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count);
-
-			sb.Print();
+				}
+
+				this.LoadConfig();
+
+				this.modulesLoaded = true;
+
+				sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count);
+
+				sb.Print();
+			}
 		}
 
 		protected void LoadModule(Type T)
 		{
-			var existingModules = this.modules.Where(mod => mod.GetType().Name == T.Name);
-			if (existingModules.Any())
-			{
-				Tools.PostDebugMessage(string.Format(
-					"{0}: refusing to load {1}: already loaded",
-					this.GetType().Name,
-					T.Name
-				));
-				return;
+			/*var existingModules = this.modules.Where(mod => mod.GetType().Name == T.Name);
+			if (existingModules.Any())*/
+			for (int mIdx = 0; mIdx < this.modules.Count; mIdx++)
+			{
+				if (this.modules[mIdx].Name == T.Name)
+				{
+					Logging.PostErrorMessage("{0}: refusing to load {1}: already loaded", this.GetType().Name, T.Name);
+					return;
+				}
 			}
 
 			var InstanceProperty = T.GetProperty(
 				"Instance",
-				System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public
+				System.Reflection.BindingFlags.Static |
+				System.Reflection.BindingFlags.Public |
+				System.Reflection.BindingFlags.FlattenHierarchy
 			);
 
 			object modInstance = null;
@@ -775,46 +979,52 @@
 
 			if (module.InValidGame && module.InValidScene)
 			{
-				module.LoadConfig();
 				this.modules.Add(module);
 
-				Tools.PostDebugMessage(string.Format(
+				Logging.PostDebugMessage(string.Format(
 						"{0}: loaded module {1}.",
 						this.GetType().Name,
 						T.Name
 					));
 			}
+			else
+			{
+				if (module is IDisposable)
+				{
+					(module as IDisposable).Dispose();
+				}
+			}
 		}
 
 		protected void LoadSkins()
 		{
-			Tools.PostDebugMessage("AssetBase has skins: \n" +
-				string.Join("\n\t",
-					Resources.FindObjectsOfTypeAll(typeof(GUISkin))
-					.Select(s => s.ToString())
-					.ToArray()
-				)
-			);
-
-			this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
-				.Where(s => !this.forbiddenSkins.Contains(s.name))
-				.Select(s => s as GUISkin)
-				.GroupBy(s => s.name)
-				.Select(g => g.First())
-				.ToDictionary(s => s.name);
-
-			Tools.PostDebugMessage(string.Format(
+			this.validSkins = new Dictionary<string, GUISkin>();
+			this.skinNames = new List<string>();
+
+			UnityEngine.Object[] skins = Resources.FindObjectsOfTypeAll(typeof(GUISkin));
+			GUISkin skin;
+			for (int sIdx = 0; sIdx < skins.Length; sIdx++)
+			{
+				skin = (GUISkin)skins[sIdx];
+
+				if (!this.forbiddenSkins.Contains(skin.name))
+				{
+					this.validSkins[skin.name] = skin;
+					this.skinNames.Add(skin.name);
+				}
+			}
+
+			Logging.PostDebugMessage(string.Format(
 				"{0}: loaded {1} GUISkins.",
 				this.GetType().Name,
 				this.validSkins.Count
 			));
 
-			this.skinNames = this.validSkins.Keys.ToArray();
-			Array.Sort(this.skinNames);
+			this.skinNames.Sort();
 
 			int defaultIdx = int.MinValue;
 
-			for (int i = 0; i < this.skinNames.Length; i++)
+			for (int i = 0; i < this.skinNames.Count; i++)
 			{
 				if (this.skinNames[i] == this.skinName)
 				{
@@ -835,7 +1045,7 @@
 				this.skinIdx = defaultIdx;
 			}
 
-			Tools.PostDebugMessage(string.Format(
+			Logging.PostDebugMessage(string.Format(
 				"{0}: _skinIdx = {1}.",
 				this.GetType().Name,
 				this.skinName.ToString()
@@ -856,17 +1066,19 @@
 			this.GUIStylesLoaded = true;
 		}
 
-		protected void LoadVesselTypes()
-		{
-			this.AllVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToArray();
-			this.vesselTypesLoaded = true;
-		}
-
 		protected void LoadBeforeUpdate()
 		{
 			if (!this.vesselTypesLoaded)
 			{
-				this.LoadVesselTypes();
+				Array typeObjs = Enum.GetValues(typeof(VesselType));
+				this.AllVesselTypes = new VesselType[typeObjs.Length];
+
+				for (int idx = 0; idx < typeObjs.Length; idx++)
+				{
+					this.AllVesselTypes[idx] = (VesselType)typeObjs.GetValue(idx);
+				}
+
+				this.vesselTypesLoaded = true;
 			}
 
 			if (this.SortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
@@ -874,61 +1086,25 @@
 				this.SortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies);
 				this.SortedBodyList.Sort(new CBListComparer());
 				this.SortedBodyList.Reverse();
-
-				Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.SortedBodyList.Select(b => b.bodyName).ToArray())));
-			}
-
-		}
-
-		protected void InitializeToolbarButton()
-		{
-			// Do nothing if (the Toolbar is not available.
-			if (!ToolbarManager.ToolbarAvailable)
-			{
-				Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false");
-				return;
-			}
-
-			this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");
-			this.ToolbarButton.Text = this.VoidName;
-			this.SetIconTexture(this.powerState | this.activeState);
-
-			this.ToolbarButton.Visible = true;
-
-			this.ToolbarButton.OnClick += 
-				(e) =>
-			{
-				this.ToggleMainWindow();
-			};
-
-			Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));
-		}
-
-		protected void InitializeAppLauncherButton()
-		{
-			if (ApplicationLauncher.Ready)
-			{
-				this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication(
-					this.ToggleMainWindow, this.ToggleMainWindow,
-					this.appIconVisibleScenes,
-					this.VOIDIconTexture
-				);
-
-				Tools.PostDebugMessage(
-					this,
-					"AppLauncherButton initialized in {0}",
-					Enum.GetName(
-						typeof(GameScenes),
-						HighLogic.LoadedScene
-					)
-				);
+			}
+
+			// SimManager initialization that we don't necessarily want to repeat every Update.
+			if (!this.simManagerLoaded && this.HomeBody != null)
+			{
+				SimManager.Gravity = VOID_Data.KerbinGee;
+				SimManager.Atmosphere = 0d;
+				SimManager.Mach = 1d;
+				CelestialBodies.SelectedBody = this.HomeBody;
+				BuildAdvanced.Altitude = 0d;
+				SimManager.OnReady += this.GetSimManagerResults;
+
+				this.simManagerLoaded = true;
 			}
 		}
 
 		protected void ToggleMainWindow()
 		{
 			this.Active = !this.Active;
-			this.SetIconTexture(this.powerState | this.activeState);
 		}
 
 		protected void SetIconTexture(IconState state)
@@ -954,49 +1130,55 @@
 
 		protected void SetIconTexture(string texturePath)
 		{
+			if (texturePath == null)
+			{
+				return;
+			}
+
 			if (this.ToolbarButton != null)
 			{
 				this.ToolbarButton.TexturePath = texturePath;
 			}
 
-			this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
-
 			if (this.AppLauncherButton != null)
 			{
+				this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
+
 				this.AppLauncherButton.SetTexture(VOIDIconTexture);
 			}
 		}
 
-		protected virtual void CheckAndSave()
-		{
-			this.saveTimer += Time.deltaTime;
-
-			if (this.saveTimer > 2f)
-			{
-				if (!this.configDirty)
-				{
-					return;
-				}
-
-				Tools.PostDebugMessage(string.Format(
-					"{0}: Time to save, checking if configDirty: {1}",
-					this.GetType().Name,
-					this.configDirty
-				));
-
-				this.SaveConfig();
-				this.saveTimer = 0;
-			}
-		}
-
-		public override void LoadConfig()
-		{
-			base.LoadConfig();
-
-			foreach (IVOID_Module module in this.modules)
-			{
-				module.LoadConfig();
-			}
+		public void LoadConfig()
+		{
+
+			if (!System.IO.File.Exists(this.VOIDSettingsPath) && KSP.IO.File.Exists<VOID_Module>("config.xml"))
+			{
+				Logging.PostLogMessage(
+					"VOID: No per-save config file but old file detected; copying from old file."
+				);
+
+				System.IO.File.Copy(
+					KSP.IO.IOUtils.GetFilePathFor(typeof(VOID_Module), "config.xml"),
+					this.VOIDSettingsPath
+				);
+			}
+
+			this.LoadConfig(new PluginConfiguration(this.VOIDSettingsPath));
+		}
+
+		public override void LoadConfig(KSP.IO.PluginConfiguration config)
+		{
+			base.LoadConfig(config);
+
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
+				module.LoadConfig(config);
+			}
+
+			this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u;
 		}
 
 		public override void SaveConfig()
@@ -1004,17 +1186,21 @@
 			if (this.configNeedsUpdate && this is VOIDCore_Flight)
 			{
 				KSP.IO.File.Delete<T>("config.xml");
-			}
-
-			var config = KSP.IO.PluginConfiguration.CreateForType<T>();
+				System.IO.File.Delete(this.VOIDSettingsPath);
+			}
+
+			KSP.IO.PluginConfiguration config = new PluginConfiguration(this.VOIDSettingsPath);
 
 			config.load();
 
-			this.Save(config);
-
-			foreach (IVOID_Module module in this.modules)
-			{
-				module.Save(config);
+			this.Save(config, this.SceneKey);
+
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
+				module.Save(config, this.SceneKey);
 			}
 
 			config.save();
@@ -1046,21 +1232,30 @@
 			this.UpdateTimer = 0f;
 
 			this.vesselSimActive = (VOID_SaveValue<bool>)true;
-			SimManager.Atmosphere = 0d;
-			SimManager.OnReady += this.GetSimManagerResults;
-
-			this.useToolbarManager = ToolbarManager.ToolbarAvailable;
-
-			this.LoadConfig();
-
-			this.configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
-			
-			this.SetIconTexture(this.powerState | this.activeState);
+
+			this.useToolbarManager = (VOID_SaveValue<bool>)ToolbarManager.ToolbarAvailable;
+
+			this.SaveGamePath = string.Format("{0}saves/{1}", IOTools.KSPRootPath, HighLogic.SaveFolder);
+			this.VOIDSettingsPath = string.Format("{0}/VOIDConfig.xml", this.SaveGamePath);
 
 			this.FactoryReset = false;
-		}
-
-		public virtual void Dispose()
+
+			GameEvents.onHideUI.Add(() =>
+				{
+					this.gameUIHidden = true;
+					this.StopGUI();
+				}
+			);
+
+			GameEvents.onShowUI.Add(() =>
+				{
+					this.gameUIHidden = false;
+					this.StartGUI();
+				}
+			);
+		}
+
+		public override void Dispose()
 		{
 			this.StopGUI();
 
@@ -1080,14 +1275,6 @@
 			_instance = null;
 			_initialized = false;
 		}
-
-		protected enum IconState
-		{
-			PowerOff = 1,
-			PowerOn = 2,
-			Inactive = 4,
-			Active = 8
-		}
 	}
 }
 

--- a/VOIDCore_SpaceCentre.cs
+++ b/VOIDCore_SpaceCentre.cs
@@ -32,6 +32,14 @@
 	[VOID_Scenes(GameScenes.SPACECENTER)]
 	public class VOIDCore_SpaceCentre : VOIDCore_Generic<VOIDCore_SpaceCentre>
 	{
+		public override string SceneKey
+		{
+			get
+			{
+				return "SPACECENTER";
+			}
+		}
+
 		public override void FixedUpdate() {}
 	}
 }

--- a/VOIDMaster_Editor.cs
+++ b/VOIDMaster_Editor.cs
@@ -43,7 +43,7 @@
 using KerbalEngineer.VesselSimulator;
 using KSP;
 using System;
-using ToadicusTools;
+using ToadicusTools.Extensions;
 using UnityEngine;
 
 namespace VOID
@@ -53,10 +53,10 @@
 	{
 		public override void Awake()
 		{
-			Tools.PostDebugMessage ("VOIDEditorMaster: Waking up.");
+			this.LogDebug("VOIDEditorMaster: Waking up.");
 			this.Core = VOIDCore_Editor.Instance;
 			this.Core.ResetGUI ();
-			Tools.PostDebugMessage ("VOIDEditorMaster: Awake.");
+			this.LogDebug("VOIDEditorMaster: Awake.");
 		}
 	}
 }

--- a/VOIDMaster_Flight.cs
+++ b/VOIDMaster_Flight.cs
@@ -43,7 +43,7 @@
 using System;
 using UnityEngine;
 using KerbalEngineer.VesselSimulator;
-using ToadicusTools;
+using ToadicusTools.Extensions;
 
 namespace VOID
 {

--- a/VOIDMaster_SpaceCentre.cs
+++ b/VOIDMaster_SpaceCentre.cs
@@ -43,7 +43,7 @@
 using System;
 using UnityEngine;
 using KerbalEngineer.VesselSimulator;
-using ToadicusTools;
+using ToadicusTools.Extensions;
 
 namespace VOID
 {

--- a/VOID_CBInfoBrowser.cs
+++ b/VOID_CBInfoBrowser.cs
@@ -29,7 +29,7 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using ToadicusTools;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -73,6 +73,12 @@
 		{
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 
+			if (this.core.SortedBodyList.Count < 1)
+			{
+				GUILayout.Label("Non-positive number of CelestialBodies here, bailing out.");
+				GUILayout.EndHorizontal();
+			}
+
 			GUILayout.BeginVertical(GUILayout.Width(150));
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			GUILayout.Label("", GUILayout.ExpandWidth(true));
@@ -82,8 +88,28 @@
 
 			GUILayout.BeginVertical(GUILayout.Width(150));
 
-			selectedBody1 = this.core.AllBodies[selectedBodyIdx1];
-			selectedBody2 = this.core.AllBodies[selectedBodyIdx2];
+			if (selectedBodyIdx1 >= this.core.SortedBodyList.Count)
+			{
+				selectedBodyIdx1.value %= this.core.SortedBodyList.Count;
+			}
+
+			if (selectedBodyIdx1 < 0)
+			{
+				selectedBodyIdx1.value += this.core.SortedBodyList.Count;
+			}
+
+			if (selectedBodyIdx2 >= this.core.SortedBodyList.Count)
+			{
+				selectedBodyIdx2.value %= this.core.SortedBodyList.Count;
+			}
+
+			if (selectedBodyIdx2 < 0)
+			{
+				selectedBodyIdx2.value += this.core.SortedBodyList.Count;
+			}
+
+			selectedBody1 = this.core.SortedBodyList[selectedBodyIdx1];
+			selectedBody2 = this.core.SortedBodyList[selectedBodyIdx2];
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			if (GUILayout.Button("<", GUILayout.ExpandWidth(false)))
@@ -91,14 +117,14 @@
 				selectedBodyIdx1.value--;
 				if (selectedBodyIdx1 < 0)
 				{
-					selectedBodyIdx1.value = this.core.AllBodies.Count - 1;
+					selectedBodyIdx1.value = this.core.SortedBodyList.Count - 1;
 				}
 			}
-			GUILayout.Label(this.core.AllBodies[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
+			GUILayout.Label(this.core.SortedBodyList[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
 			if (GUILayout.Button(">", GUILayout.ExpandWidth(false)))
 			{
 				selectedBodyIdx1.value++;
-				if (selectedBodyIdx1 > this.core.AllBodies.Count - 1)
+				if (selectedBodyIdx1 > this.core.SortedBodyList.Count - 1)
 				{
 					selectedBodyIdx1.value = 0;
 				}
@@ -113,14 +139,14 @@
 				selectedBodyIdx2.value--;
 				if (selectedBodyIdx2 < 0)
 				{
-					selectedBodyIdx2.value = this.core.AllBodies.Count - 1;
+					selectedBodyIdx2.value = this.core.SortedBodyList.Count - 1;
 				}
 			}
-			GUILayout.Label(this.core.AllBodies[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
+			GUILayout.Label(this.core.SortedBodyList[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
 			if (GUILayout.Button(">", GUILayout.ExpandWidth(false)))
 			{
 				selectedBodyIdx2.value++;
-				if (selectedBodyIdx2 > this.core.AllBodies.Count - 1)
+				if (selectedBodyIdx2 > this.core.SortedBodyList.Count - 1)
 				{
 					selectedBodyIdx2.value = 0;
 				}
@@ -203,7 +229,7 @@
 				GUILayout.Label("Natural satellites:");
 				GUILayout.Label("Artificial satellites:");
 				GUILayout.Label("Surface gravity:");
-				GUILayout.Label("Atmosphere altitude:");
+				GUILayout.Label("Atmosphere Depth:");
 				GUILayout.Label("Atmospheric O\u2082:");
 				GUILayout.Label("Has ocean:");
 
@@ -373,15 +399,19 @@
 
 			GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
 
-			if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
-			else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
+			if (body.bodyName == "Sun") GUILayout.Label(SIFormatProvider.ToSI(body.sphereOfInfluence, 3), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
+			else GUILayout.Label(SIFormatProvider.ToSI(body.sphereOfInfluence, 3), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
 
 			GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
 
 			//show # artificial satellites
 			int num_art_sats = 0;
-			foreach (Vessel v in FlightGlobals.Vessels)
-			{
+
+			Vessel v;
+			for (int idx = 0; idx < FlightGlobals.Vessels.Count; idx++)
+			{
+				v = FlightGlobals.Vessels[idx];
+
 				if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++;
 			}
 
@@ -389,11 +419,11 @@
 
 			double g_ASL = (VOIDCore.Constant_G * body.Mass) / (body.Radius * body.Radius);
 
-			GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
+			GUILayout.Label(SIFormatProvider.ToSI(g_ASL, 3) + "m/s²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true));
 
 			if (body.atmosphere)
 			{
-				GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m",
+				GUILayout.Label("≈ " + SIFormatProvider.ToSI(body.atmosphereDepth, 3) + "m",
 					VOID_Styles.labelRight,
 					GUILayout.ExpandWidth(true));
 

--- a/VOID_CareerStatus.cs
+++ b/VOID_CareerStatus.cs
@@ -30,29 +30,24 @@
 using System;
 using System.Text;
 using ToadicusTools;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
 {
 	[VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
 	[VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)]
-	public class VOID_CareerStatus : VOID_WindowModule
+	public class VOID_CareerStatus : VOID_SingletonWindow<VOID_CareerStatus>
 	{
-		public static VOID_CareerStatus Instance
-		{
-			get;
-			private set;
-		}
-
 		public static string formatDelta(double delta, string numberFormat)
 		{
 			if (delta > 0)
 			{
-				return string.Format("<color='lime'>{0}↑</color>", delta.ToString(numberFormat, Tools.SIFormatter));
+				return string.Format("<color='lime'>{0}↑</color>", delta.ToString(numberFormat, SIFormatProvider.SIFormatter));
 			}
 			else if (delta < 0)
 			{
-				return string.Format("<color='red'>{0}↓</color>", delta.ToString(numberFormat, Tools.SIFormatter));
+				return string.Format("<color='red'>{0}↓</color>", delta.ToString(numberFormat, SIFormatProvider.SIFormatter));
 			}
 			else
 			{
@@ -122,7 +117,7 @@
 		{
 			get
 			{
-				Tools.PostDebugMessage(
+				Logging.PostDebugMessage(
 					this,
 					"Checking init state:" +
 					"\n\tcurrentFunds={0}" +
@@ -141,14 +136,14 @@
 			}
 		}
 
-		public override void DrawGUI()
+		public override void DrawGUI(object sender)
 		{
 			if (Event.current.type != EventType.Layout && !this.currenciesInitialized)
 			{
 				this.initCurrencies();
 			}
 
-			base.DrawGUI();
+			base.DrawGUI(sender);
 		}
 
 		public override void ModuleWindow(int id)
@@ -207,7 +202,7 @@
 
 		private void initCurrencies()
 		{
-			Tools.PostDebugMessage(
+			Logging.PostDebugMessage(
 				this,
 				"Initializing currencies." +
 				"\n\tFunding.Instance={0}" +
@@ -233,11 +228,6 @@
 		 * */
 		public VOID_CareerStatus() : base()
 		{
-			if (this.InValidGame && this.InValidScene)
-			{
-				VOID_CareerStatus.Instance = this;
-			}
-
 			this.Name = "Career Status";
 
 			GameEvents.OnFundsChanged.Add(this.onFundsChange);
@@ -269,14 +259,19 @@
 			this.currentReputation = float.NaN;
 		}
 
-		~VOID_CareerStatus()
+		public override void Dispose()
 		{
 			GameEvents.OnFundsChanged.Remove(this.onFundsChange);
 			GameEvents.OnReputationChanged.Remove(this.onRepChange);
 			GameEvents.OnScienceChanged.Remove(this.onScienceChange);
 			GameEvents.onGameStateLoad.Remove(this.onGameStateLoad);
 
-			VOID_CareerStatus.Instance = null;
+			base.Dispose();
+		}
+
+		~VOID_CareerStatus()
+		{
+			this.Dispose();
 		}
 	}
 }

--- a/VOID_ConfigWindow.cs
+++ b/VOID_ConfigWindow.cs
@@ -28,19 +28,12 @@
 
 using KSP;
 using System;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
 {
-	public class VOID_ConfigWindow : VOID_WindowModule
+	public class VOID_ConfigWindow : VOID_SingletonWindow<VOID_ConfigWindow>
 	{
-		public static VOID_ConfigWindow Instance
-		{
-			get;
-			private set;
-		}
-
 		public override bool InValidScene
 		{
 			get
@@ -59,8 +52,6 @@
 
 		public VOID_ConfigWindow() : base()
 		{
-			VOID_ConfigWindow.Instance = this;
-
 			this.Name = "VOID Configuration";
 		}
 
@@ -71,12 +62,13 @@
 			this.core.DrawConfigurables();
 
 			GUILayout.EndVertical();
-			GUI.DragWindow();
+
+			base.ModuleWindow(id);
 		}
 
 		~VOID_ConfigWindow()
 		{
-			VOID_ConfigWindow.Instance = null;
+			this.Dispose();
 		}
 	}
 }

--- a/VOID_Data.cs
+++ b/VOID_Data.cs
@@ -31,6 +31,8 @@
 using System;
 using System.Collections.Generic;
 using ToadicusTools;
+using ToadicusTools.Extensions;
+using ToadicusTools.MuMechTools;
 using UnityEngine;
 
 namespace VOID
@@ -38,6 +40,7 @@
 	public static class VOID_Data
 	{
 		private static Dictionary<int, IVOID_DataValue> dataValues = new Dictionary<int, IVOID_DataValue>();
+
 		public static Dictionary<int, IVOID_DataValue> DataValues
 		{
 			get
@@ -115,29 +118,29 @@
 		public static readonly VOID_DoubleValue atmDensity =
 			new VOID_DoubleValue(
 				"Atmosphere Density",
-				new Func<double>(() => Core.Vessel.atmDensity * 1000f),
+				new Func<double>(() => Core.Vessel.atmDensity * 1000d),
 				"g/m³"
 			);
 
-		public static readonly VOID_FloatValue atmLimit =
-			new VOID_FloatValue(
-				"Atmosphere Limit",
-				new Func<float>(() => Core.Vessel.mainBody.maxAtmosphereAltitude),
+		public static readonly VOID_DoubleValue atmLimit =
+			new VOID_DoubleValue(
+				"Atmosphere Depth",
+				new Func<double>(() => Core.Vessel.mainBody.atmosphereDepth),
 				"m"
 			);
 
 		public static readonly VOID_DoubleValue atmPressure =
 			new VOID_DoubleValue(
-				"Pressure",
-				new Func<double>(() => Core.Vessel.staticPressure),
-				"atm"
-			);
-
-		public static readonly VOID_FloatValue temperature =
-			new VOID_FloatValue(
+				"Static Pressure",
+				new Func<double>(() => Core.Vessel.staticPressurekPa * 1000d),
+				"Pa"
+			);
+
+		public static readonly VOID_DoubleValue temperature =
+			new VOID_DoubleValue(
 				"Temperature",
-				new Func<float>(() => Core.Vessel.flightIntegrator.getExternalTemperature()),
-				"°C"
+				new Func<double>(() => Core.Vessel.atmosphericTemperature),
+				"K"
 			);
 
 		#endregion
@@ -229,8 +232,8 @@
 		public static readonly VOID_FloatValue mainThrottle =
 			new VOID_FloatValue(
 				"Throttle",
-				new Func<float>(() => Core.Vessel.ctrlState.mainThrottle * 100f),
-				"%"
+				new Func<float>(() => Core.Vessel.ctrlState.mainThrottle),
+				""
 			);
 
 		#endregion
@@ -268,22 +271,22 @@
 						return double.NaN;
 					}
 
+					return Core.LastStage.totalResourceMass;
+				},
+				"tons"
+			);
+
+		public static readonly VOID_DoubleValue stageResourceMass =
+			new VOID_DoubleValue(
+				"Resource Mass (Stage)",
+				delegate()
+				{
+					if (Core.LastStage == null)
+					{
+						return double.NaN;
+					}
+
 					return Core.LastStage.resourceMass;
-				},
-				"tons"
-			);
-
-		public static readonly VOID_DoubleValue stageResourceMass =
-			new VOID_DoubleValue(
-				"Resource Mass (Stage)",
-				delegate()
-				{
-					if (Core.LastStage == null)
-					{
-						return double.NaN;
-					}
-
-					return Core.LastStage.totalResourceMass;
 				},
 				"tons"
 			);
@@ -351,6 +354,19 @@
 				}
 			);
 
+		public static readonly VOID_DoubleValue currThrust =
+			new VOID_DoubleValue(
+				"Current Thrust",
+				delegate()
+				{
+					if (Core.Stages == null || Core.LastStage == null)
+						return double.NaN;
+
+					return Core.LastStage.actualThrust;
+				},
+				"kN"
+			);
+
 		public static readonly VOID_StrValue currmaxThrust =
 			new VOID_StrValue(
 				"Thrust (curr/max)",
@@ -380,19 +396,7 @@
 						return double.NaN;
 					}
 
-					double stageIsp = Core.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);
+					return Core.LastStage.MassFlow();
 				},
 				"Mg/s"
 			);
@@ -407,14 +411,7 @@
 						return double.NaN;
 					}
 
-					if (Core.LastStage.actualThrust == 0d)
-					{
-						return Core.LastStage.thrust;
-					}
-					else
-					{
-						return Core.LastStage.actualThrust;
-					}
+					return Core.LastStage.NominalThrust();
 				},
 				"kN"
 			);
@@ -481,7 +478,7 @@
 					double maxThrust = Core.LastStage.thrust;
 					double mass = Core.LastStage.totalMass;
 					double gravity = (VOIDCore.Constant_G * Core.Vessel.mainBody.Mass) /
-					               (Core.Vessel.mainBody.Radius * Core.Vessel.mainBody.Radius);
+					                 (Core.Vessel.mainBody.Radius * Core.Vessel.mainBody.Radius);
 					double weight = mass * gravity;
 
 					return maxThrust / weight;
@@ -489,90 +486,95 @@
 				""
 			);
 
-		public static readonly VOID_Vector3dValue vesselThrustOffset =
-			new VOID_Vector3dValue(
+		private static Vector3 thrustPos;
+		private static Vector3 thrustDir;
+		private static float thrust;
+
+		private static void thrustOffsetPreForEach(object sender)
+		{
+			thrustPos = Vector3.zero;
+			thrustDir = Vector3.zero;
+			thrust = 0;
+		}
+
+		private static void thrustOffSetPerModule(object sender, VOIDForEachPartModuleArgs args)
+		{
+			PartModule module = args.Data;
+
+			float moduleThrust = 0;
+
+			switch (module.moduleName)
+			{
+				case "ModuleEngines":
+				case "ModuleEnginesFX":
+					break;
+				default:
+					return;
+			}
+
+			if (!module.isEnabled)
+			{
+				return;
+			}
+
+			CenterOfThrustQuery cotQuery = new CenterOfThrustQuery();
+
+			if (module is ModuleEngines)
+			{
+				ModuleEngines engineModule = module as ModuleEngines;
+
+				moduleThrust = engineModule.finalThrust;
+
+				engineModule.OnCenterOfThrustQuery(cotQuery);
+			}
+			else // engine is ModuleEnginesFX
+			{
+				ModuleEnginesFX engineFXModule = module 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;
+		}
+
+		public static readonly VOID_Vector3Value vesselThrustOffset =
+			new VOID_Vector3Value(
 				"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;
-					}
+					Vector3 pos = thrustPos;
+					Vector3 dir = thrustDir;
 
 					if (thrust != 0)
 					{
-						thrustPos /= thrust;
-						thrustDir /= thrust;
+						pos /= thrust;
+						dir /= 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,
+					pos = vesselTransform.InverseTransformPoint(pos);
+					dir = vesselTransform.InverseTransformDirection(dir);
+
+					Vector3 thrustOffset = VectorTools.PointDistanceToLine(
+						pos, dir.normalized, Core.Vessel.findLocalCenterOfMass());
+
+					Logging.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" +
+					"\tthrustPos: {0}\n" +
+					"\tthrustDir: {1}\n" +
+					"\tthrustOffset: {2}\n" +
+					"\tvessel.CoM: {3}",
+						pos,
+						dir.normalized,
 						thrustOffset,
 						Core.Vessel.findWorldCenterOfMass()
 					);
@@ -586,84 +588,106 @@
 
 		#region Air Breathing
 
+		private static double airFlowCurrent;
+		private static double airFlowRequired;
+		private static string intakeAirString;
+
+		private static void intakeAirPreForEach(object sender)
+		{
+			airFlowCurrent = 0d;
+			airFlowRequired = 0d;
+			intakeAirString = string.Empty;
+		}
+
+		private static void intakeAirForEachModule(object sender, VOIDForEachPartModuleArgs args)
+		{
+			PartModule module = args.Data;
+			List<Propellant> propellantList = null;
+
+			if (!module.part.enabled)
+			{
+				return;
+			}
+
+			if (module is ModuleEngines)
+			{
+				propellantList = ((ModuleEngines)module).propellants;
+			}
+			else if (module is ModuleEnginesFX)
+			{
+				propellantList = ((ModuleEnginesFX)module).propellants;
+			}
+			else if (module is ModuleResourceIntake)
+			{
+				ModuleResourceIntake intakeModule = (ModuleResourceIntake)module;
+
+				if (intakeModule.resourceName == "IntakeAir")
+				{
+					airFlowCurrent += intakeModule.airFlow;
+				}
+			}
+
+			if (propellantList != null)
+			{
+				Propellant propellant;
+				for (int propIdx = 0; propIdx < propellantList.Count; propIdx++)
+				{
+					propellant = propellantList[propIdx];
+
+					if (propellant.name == "IntakeAir")
+					{
+						airFlowRequired += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
+						break;
+					}
+				}
+			}
+		}
+
 		public static readonly VOID_StrValue intakeAirStatus =
 			new VOID_StrValue(
 				"Intake Air (Curr / Req)",
 				delegate()
 				{
-					double currentAmount;
-					double currentRequirement;
-
-					currentAmount = 0d;
-					currentRequirement = 0d;
-
-					foreach (Part part in Core.Vessel.Parts)
-					{
-						if (part.enabled)
-						{
-							ModuleEngines engineModule;
-							ModuleEnginesFX enginesFXModule;
-							List<Propellant> propellantList = null;
-
-							if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule))
-							{
-								propellantList = engineModule.propellants;
-							}
-							else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(out enginesFXModule))
-								{
-									propellantList = enginesFXModule.propellants;
-								}
-
-							if (propellantList != null)
-							{
-								foreach (Propellant propellant in propellantList)
-								{
-									if (propellant.name == "IntakeAir")
-									{
-										currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
-										break;
-									}
-								}
-							}
-						}
-
-						ModuleResourceIntake intakeModule;
-
-						if (part.enabled && part.tryGetFirstModuleOfType<ModuleResourceIntake>(out intakeModule))
-						{
-							if (intakeModule.resourceName == "IntakeAir")
-							{
-								currentAmount += intakeModule.airFlow;
-							}
-						}
-					}
-
-					if (currentAmount == 0 && currentRequirement == 0)
-					{
-						return "N/A";
-					}
-
-					return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement);
+					if (airFlowCurrent == 0 && airFlowRequired == 0)
+					{
+						intakeAirString = "N/A";
+					}
+					else
+					{
+						intakeAirString = string.Format("{0:F3} / {1:F3}", airFlowCurrent, airFlowRequired);
+					}
+
+					return intakeAirString;
 				}
 			);
 
 		#endregion
 
 		#region Crew
+
+		private static int crewCount;
+		private static int crewCapacity;
+
+		private static void crewCountPreForEach(object sender)
+		{
+			crewCount = 0;
+			crewCapacity = 0;
+		}
+
+		private static void crewCountPerPart(object sender, VOIDForEachPartArgs args)
+		{
+			Part part = args.Data;
+
+			crewCount += part.protoModuleCrew.Count;
+			crewCapacity += part.CrewCapacity;
+		}
 
 		public static readonly VOID_IntValue vesselCrewCount =
 			new VOID_IntValue(
 				"Crew Onboard",
 				delegate()
 				{
-					if (Core.Vessel != null)
-					{
-						return Core.Vessel.GetCrewCount();
-					}
-					else
-					{
-						return 0;
-					}
+					return crewCount;
 				},
 				""
 			);
@@ -673,14 +697,7 @@
 				"Crew Capacity",
 				delegate()
 				{
-					if (Core.Vessel != null)
-					{
-						return Core.Vessel.GetCrewCapacity();
-					}
-					else
-					{
-						return 0;
-					}
+					return crewCapacity;
 				},
 				""
 			);
@@ -701,8 +718,8 @@
 				{
 
 					if (Core.Vessel == null ||
-					  Planetarium.fetch == null ||
-					  Core.Vessel.mainBody != Planetarium.fetch.Home)
+					    Planetarium.fetch == null ||
+					    Core.Vessel.mainBody != Planetarium.fetch.Home)
 					{
 						return double.NaN;
 					}
@@ -710,36 +727,80 @@
 					double vesselLongitude = Core.Vessel.longitude * Math.PI / 180d;
 					double vesselLatitude = Core.Vessel.latitude * Math.PI / 180d;
 
-					double diffLon = vesselLongitude - kscLongitude;
-					double diffLat = vesselLatitude - kscLatitude;
-
-					double sinHalfDiffLat = Math.Sin(diffLat / 2d);
-					double sinHalfDiffLon = Math.Sin(diffLon / 2d);
-
-					double cosVesselLon = Math.Cos(vesselLongitude);
-					double cosKSCLon = Math.Cos(kscLongitude);
-
-					double haversine =
-						sinHalfDiffLat * sinHalfDiffLat +
-						cosVesselLon * cosKSCLon * sinHalfDiffLon * sinHalfDiffLon;
-
-					double arc = 2d * Math.Atan2(Math.Sqrt(haversine), Math.Sqrt(1d - haversine));
-
-					return Core.Vessel.mainBody.Radius * arc;
+					double diffLon = Math.Abs(vesselLongitude - kscLongitude);
+
+					double cosVesselLatitude = Math.Cos(vesselLatitude);
+					double sinDiffLon = Math.Sin(diffLon);
+
+					double term1 = cosVesselLatitude * sinDiffLon;
+
+					double cosKSCLatitude = Math.Cos(kscLatitude);
+					double sinVesselLatitude = Math.Sin(vesselLatitude);
+					double sinKSCLatitude = Math.Sin(kscLatitude);
+					double cosDiffLon = Math.Cos(diffLon);
+
+					double term2 = cosKSCLatitude * sinVesselLatitude - sinKSCLatitude * cosVesselLatitude * cosDiffLon;
+
+					double term3 = sinKSCLatitude * sinVesselLatitude + cosKSCLatitude * cosVesselLatitude * cosDiffLon;
+
+					double arc = Math.Atan2(Math.Sqrt(term1 * term1 + term2 * term2), term3);
+
+					return arc * Core.Vessel.mainBody.Radius;
 				},
 				"m"
 			);
 
-		public static readonly VOID_StrValue surfLatitude =
+		public static readonly VOID_StrValue surfLatitudeString =
 			new VOID_StrValue(
 				"Latitude",
 				new Func<string>(() => VOID_Tools.GetLatitudeString(Core.Vessel))
 			);
 
-		public static readonly VOID_StrValue surfLongitude =
+		public static readonly VOID_DoubleValue surfLatitude =
+			new VOID_DoubleValue(
+				"Latitude",
+				delegate()
+				{
+					if (CoreInitialized && Core.Vessel != null)
+					{
+						return Core.Vessel.latitude;
+					}
+					return double.NaN;
+				},
+				"°"
+			);
+
+		public static readonly VOID_StrValue surfLongitudeString =
 			new VOID_StrValue(
 				"Longitude",
 				new Func<string>(() => VOID_Tools.GetLongitudeString(Core.Vessel))
+			);
+
+		public static readonly VOID_DoubleValue surfLongitude =
+			new VOID_DoubleValue(
+				"Longitude",
+				delegate()
+				{
+					if (CoreInitialized && Core.Vessel != null)
+					{
+						double longitude = Core.Vessel.longitude;
+
+						longitude = VOID_Tools.FixDegreeDomain(longitude);
+
+						if (longitude < -180d)
+						{
+							longitude += 360d;
+						}
+						if (longitude >= 180)
+						{
+							longitude -= 360d;
+						}
+
+						return longitude;
+					}
+					return double.NaN;
+				},
+				"°"
 			);
 
 		public static readonly VOID_DoubleValue trueAltitude =
@@ -771,7 +832,10 @@
 		public static readonly VOID_DoubleValue horzVelocity =
 			new VOID_DoubleValue(
 				"Horizontal speed",
-				new Func<double>(() => Core.Vessel.horizontalSrfSpeed),
+				delegate
+				{
+					return Core.Vessel.horizontalSrfSpeed;
+				},
 				"m/s"
 			);
 
@@ -955,14 +1019,12 @@
 				"Total Burn Time",
 				delegate()
 				{
-					if (Core.LastStage == null || currManeuverDeltaV.Value == double.NaN)
-					{
-						return double.NaN;
-					}
-
-					double stageThrust = stageNominalThrust;
-
-					return burnTime(currManeuverDeltaV.Value, totalMass, stageMassFlow, stageThrust);
+					if (currManeuverDeltaV.Value == double.NaN)
+					{
+						return double.NaN;
+					}
+
+					return realVesselBurnTime(currManeuverDeltaV.Value);
 				},
 				"s"
 			);
@@ -972,14 +1034,12 @@
 				"Burn Time Remaining",
 				delegate()
 				{
-					if (Core.LastStage == null || currManeuverDVRemaining == double.NaN)
-					{
-						return double.NaN;
-					}
-
-					double stageThrust = stageNominalThrust;
-
-					return burnTime(currManeuverDVRemaining, totalMass, stageMassFlow, stageThrust);
+					if (currManeuverDVRemaining.Value == double.NaN)
+					{
+						return double.NaN;
+					}
+
+					return realVesselBurnTime(currManeuverDVRemaining.Value);
 				},
 				"s"
 			);
@@ -989,14 +1049,12 @@
 				"Half Burn Time",
 				delegate()
 				{
-					if (Core.LastStage == null || currManeuverDeltaV.Value == double.NaN)
-					{
-						return double.NaN;
-					}
-
-					double stageThrust = stageNominalThrust;
-
-					return burnTime(currManeuverDeltaV.Value / 2d, totalMass, stageMassFlow, stageThrust);
+					if (currManeuverDeltaV.Value == double.NaN)
+					{
+						return double.NaN;
+					}
+
+					return realVesselBurnTime(currManeuverDeltaV.Value / 2d);
 				},
 				"s"
 			);
@@ -1088,7 +1146,7 @@
 				delegate()
 				{
 					double orbitRadius = Core.Vessel.mainBody.Radius +
-					                   Core.Vessel.mainBody.GetAltitude(Core.Vessel.findWorldCenterOfMass());
+					                     Core.Vessel.mainBody.GetAltitude(Core.Vessel.findWorldCenterOfMass());
 					return (VOIDCore.Constant_G * Core.Vessel.mainBody.Mass) /
 					(orbitRadius * orbitRadius);
 				},
@@ -1125,7 +1183,7 @@
 		public static readonly VOID_DoubleValue trueAnomaly = 
 			new VOID_DoubleValue(
 				"True Anomaly",
-				new Func<double>(() => Core.Vessel.orbit.trueAnomaly),
+				new Func<double>(() => Core.Vessel.orbit.trueAnomaly * 180d / Math.PI),
 				"°"
 			);
 
@@ -1157,9 +1215,9 @@
 				{
 					double trueAnomalyAscNode = 360d - argumentPeriapsis;
 					double dTAscNode = Core.Vessel.orbit.GetDTforTrueAnomaly(
-						trueAnomalyAscNode * Mathf.Deg2Rad,
-						Core.Vessel.orbit.period
-					);
+						                   trueAnomalyAscNode * Mathf.Deg2Rad,
+						                   Core.Vessel.orbit.period
+					                   );
 
 					dTAscNode %= Core.Vessel.orbit.period;
 
@@ -1179,9 +1237,9 @@
 				{
 					double trueAnomalyAscNode = 180d - argumentPeriapsis;
 					double dTDescNode = Core.Vessel.orbit.GetDTforTrueAnomaly(
-						trueAnomalyAscNode * Mathf.Deg2Rad,
-						Core.Vessel.orbit.period
-					);
+						                    trueAnomalyAscNode * Mathf.Deg2Rad,
+						                    Core.Vessel.orbit.period
+					                    );
 
 					dTDescNode %= Core.Vessel.orbit.period;
 
@@ -1198,7 +1256,7 @@
 			new VOID_DoubleValue(
 				"Local Sidereal Longitude",
 				new Func<double>(() => VOID_Tools.FixDegreeDomain(
-						Core.Vessel.longitude + Core.Vessel.orbit.referenceBody.rotationAngle)),
+					Core.Vessel.longitude + Core.Vessel.orbit.referenceBody.rotationAngle)),
 				"°"
 			);
 
@@ -1243,11 +1301,11 @@
 
 		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",
+			Logging.PostDebugMessage(typeof(VOID_Data), "calculating burnTime from:\n" +
+			"\tdeltaV: {0}\n" +
+			"\tinitialMass: {1}\n" +
+			"\tmassFlow: {2}\n" +
+			"\tthrust: {3}\n",
 				deltaV,
 				initialMass,
 				massFlow,
@@ -1255,6 +1313,86 @@
 			);
 			return initialMass / massFlow * (1d - Math.Exp(-deltaV * massFlow / thrust));
 		}
+
+		private static double dVfromBurnTime(double time, double initialMass, double massFlow, double thrust)
+		{
+			return -thrust / massFlow * Math.Log(1d - time * massFlow / initialMass);
+		}
+
+		private static double realVesselBurnTime(double deltaV)
+		{
+			if (Core.Stages == null || Core.Stages.Length < 1)
+			{
+				return double.NaN;
+			}
+
+			double burntime = 0d;
+			double dVRemaining = deltaV;
+
+			int stageIdx = Core.Stages.Length - 1;
+
+			while (dVRemaining > double.Epsilon)
+			{
+				if (stageIdx < 0)
+				{
+					return double.PositiveInfinity;
+				}
+
+				Stage stage = Core.Stages[stageIdx];
+
+				if (stage.deltaV > 0)
+				{
+					double stageDVUsed = Math.Min(stage.deltaV, dVRemaining);
+
+					burntime += burnTime(stageDVUsed, stage.totalMass, stage.MassFlow(), stage.NominalThrust());
+					dVRemaining -= stageDVUsed;
+				}
+
+				stageIdx--;
+			}
+
+			return burntime;
+		}
+
+		private static void onFlightModulesLoaded(object sender)
+		{
+			if (sender is VOIDCore_Flight)
+			{
+				VOIDCore_Flight flightCore = sender as VOIDCore_Flight;
+
+				flightCore.onPreForEach += thrustOffsetPreForEach;
+				flightCore.onForEachModule += thrustOffSetPerModule;
+
+				flightCore.onPreForEach += intakeAirPreForEach;
+				flightCore.onForEachModule += intakeAirForEachModule;
+
+				flightCore.onPreForEach += crewCountPreForEach;
+				flightCore.onForEachPart += crewCountPerPart;
+			}
+		}
+
+		private static void onFlightModulesDestroyed(object sender)
+		{
+			if (sender is VOIDCore_Flight)
+			{
+				VOIDCore_Flight flightCore = sender as VOIDCore_Flight;
+
+				flightCore.onPreForEach -= thrustOffsetPreForEach;
+				flightCore.onForEachModule -= thrustOffSetPerModule;
+
+				flightCore.onPreForEach -= intakeAirPreForEach;
+				flightCore.onForEachModule -= intakeAirForEachModule;
+
+				flightCore.onPreForEach -= crewCountPreForEach;
+				flightCore.onForEachPart -= crewCountPerPart;
+			}
+		}
+
+		static VOID_Data()
+		{
+			VOIDCore_Flight.onModulesLoaded += onFlightModulesLoaded;
+			VOIDCore_Flight.onModulesDestroyed += onFlightModulesDestroyed;
+		}
 	}
 }
 

--- a/VOID_DataLogger.cs
+++ b/VOID_DataLogger.cs
@@ -32,6 +32,9 @@
 using System.IO;
 using System.Text;
 using ToadicusTools;
+using ToadicusTools.DebugTools;
+using ToadicusTools.GUIUtils;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -103,14 +106,11 @@
 			{
 				if (this._fileName == null || this._fileName == string.Empty)
 				{
-					this._fileName = KSP.IO.IOUtils.GetFilePathFor(
-						typeof(VOIDCore),
-						string.Format(
-							"{0}_{1}",
-							this.Vessel.vesselName,
-							"data.csv"
-						),
-						null
+					this._fileName = string.Format(
+						"{0}/{1}_{2}",
+						this.core.SaveGamePath,
+						this.Vessel.vesselName,
+						"data.csv"
 					);
 				}
 
@@ -124,44 +124,46 @@
 			{
 				if (this._outputFile == null)
 				{
-					Tools.DebugLogger logger = Tools.DebugLogger.New(this);
-					logger.AppendFormat("Initializing output file '{0}' with mode ", this.fileName);
-
-					if (File.Exists(this.fileName))
+					using (PooledDebugLogger logger = PooledDebugLogger.New(this))
 					{
-						logger.Append("append");
-						this._outputFile = new FileStream(
-							this.fileName,
-							FileMode.Append,
-							FileAccess.Write,
-							FileShare.Read,
-							512,
-							true
-						);
+						logger.AppendFormat("Initializing output file '{0}' with mode ", this.fileName);
+
+						if (File.Exists(this.fileName))
+						{
+							logger.Append("append");
+							this._outputFile = new FileStream(
+								this.fileName,
+								FileMode.Append,
+								FileAccess.Write,
+								FileShare.Read,
+								512,
+								true
+							);
+						}
+						else
+						{
+							logger.Append("create");
+							this._outputFile = new FileStream(
+								this.fileName,
+								FileMode.Create,
+								FileAccess.Write,
+								FileShare.Read,
+								512,
+								true
+							);
+
+							byte[] byteOrderMark = utf8Encoding.GetPreamble();
+
+							logger.Append(" and writing preamble");
+							this._outputFile.Write(byteOrderMark, 0, byteOrderMark.Length);
+						}
+
+						logger.Append('.');
+
+						logger.AppendFormat("  File is {0}opened asynchronously.", this._outputFile.IsAsync ? "" : "not ");
+
+						logger.Print();
 					}
-					else
-					{
-						logger.Append("create");
-						this._outputFile = new FileStream(
-							this.fileName,
-							FileMode.Create,
-							FileAccess.Write,
-							FileShare.Read,
-							512,
-							true
-						);
-
-						byte[] byteOrderMark = utf8Encoding.GetPreamble();
-
-						logger.Append(" and writing preamble");
-						this._outputFile.Write(byteOrderMark, 0, byteOrderMark.Length);
-					}
-
-					logger.Append('.');
-
-					logger.AppendFormat("  File is {0}opened asynchronously.", this._outputFile.IsAsync ? "" : "not ");
-
-					logger.Print();
 				}
 
 				return this._outputFile;
@@ -216,23 +218,24 @@
 
 		public void OnDestroy()
 		{
-			Tools.DebugLogger logger = Tools.DebugLogger.New(this);
-
-			logger.Append("Destroying...");
-
-			this.CloseFileIfOpen();
-
-			logger.Append(" Done.");
-			logger.Print(false);
+			using (PooledDebugLogger logger = PooledDebugLogger.New(this))
+			{
+				logger.Append("Destroying...");
+
+				this.CloseFileIfOpen();
+
+				logger.Append(" Done.");
+				logger.Print(false);
+			}
 		}
 
 		#endregion
 
 		#region VOID_Module Overrides
 
-		public override void LoadConfig()
-		{
-			base.LoadConfig();
+		public override void LoadConfig(KSP.IO.PluginConfiguration config)
+		{
+			base.LoadConfig(config);
 
 			this.logIntervalStr = this.logInterval.value.ToString("#.0##");
 		}
@@ -258,14 +261,14 @@
 				activeLabelStyle = VOID_Styles.labelGreen;
 			}
 
-			this.loggingActive = GUITools.Toggle(
+			this.loggingActive = Layout.Toggle(
 				loggingActive,
 				string.Format("Data logging: {0}", activeLabelText),
 				null,
 				activeLabelStyle
 			);
 
-			this.waitForLaunch.value = GUITools.Toggle(
+			this.waitForLaunch.value = Layout.Toggle(
 				this.waitForLaunch,
 				"Wait for launch"
 			);
@@ -305,99 +308,125 @@
 			//called if logging is on and interval has passed
 			//writes one line to the csvList
 
-			StringBuilder line = new StringBuilder();
-
-			if (firstWrite)
-			{
-				firstWrite = false;
-				line.Append(
-					"\"Kerbin Universal Time (s)\"," +
-					"\"Mission Elapsed Time (s)\t\"," +
-					"\"Altitude ASL (m)\"," +
-					"\"Altitude above terrain (m)\"," +
-					"\"Surface Latitude (°)\"," +
-					"\"Surface Longitude (°)\"," +
-					"\"Orbital Velocity (m/s)\"," +
-					"\"Surface Velocity (m/s)\"," +
-					"\"Vertical Speed (m/s)\"," +
-					"\"Horizontal Speed (m/s)\"," +
-					"\"Gee Force (gees)\"," +
-					"\"Temperature (°C)\"," +
-					"\"Gravity (m/s²)\"," +
-					"\"Atmosphere Density (g/m³)\"," +
-					"\"Downrange Distance  (m)\"," +
-					"\n"
-				);
-			}
-
-			// Universal time
-			line.Append(Planetarium.GetUniversalTime().ToString("F2"));
-			line.Append(',');
-
-			//Mission time
-			line.Append(Vessel.missionTime.ToString("F3"));
-			line.Append(',');
-
-			//Altitude ASL
-			line.Append(VOID_Data.orbitAltitude.Value.ToString("F3"));
-			line.Append(',');
-
-			//Altitude (true)
-			line.Append(VOID_Data.trueAltitude.Value.ToString("F3"));
-			line.Append(',');
-
-			// Surface Latitude
-			line.Append('"');
-			line.Append(VOID_Data.surfLatitude.Value);
-			line.Append('"');
-			line.Append(',');
-
-			// Surface Longitude
-			line.Append('"');
-			line.Append(VOID_Data.surfLongitude.Value);
-			line.Append('"');
-			line.Append(',');
-
-			//Orbital velocity
-			line.Append(VOID_Data.orbitVelocity.Value.ToString("F3"));
-			line.Append(',');
-
-			//surface velocity
-			line.Append(VOID_Data.surfVelocity.Value.ToString("F3"));
-			line.Append(',');
-
-			//vertical speed
-			line.Append(VOID_Data.vertVelocity.Value.ToString("F3"));
-			line.Append(',');
-
-			//horizontal speed
-			line.Append(VOID_Data.horzVelocity.Value.ToString("F3"));
-			line.Append(',');
-
-			//gee force
-			line.Append(VOID_Data.geeForce.Value.ToString("F3"));
-			line.Append(',');
-
-			//temperature
-			line.Append(VOID_Data.temperature.Value.ToString("F2"));
-			line.Append(',');
-
-			//gravity
-			line.Append(VOID_Data.gravityAccel.Value.ToString("F3"));
-			line.Append(',');
-
-			//atm density
-			line.Append(VOID_Data.atmDensity.Value.ToString("G3"));
-			line.Append(',');
-
-			// Downrange Distance
-			line.Append((VOID_Data.downrangeDistance.Value.ToString("G3")));
-
-			line.Append('\n');
-
-			csvBytes.AddRange(this.utf8Encoding.GetBytes(line.ToString()));
-
-			this.csvCollectTimer = 0f;
+			using (PooledStringBuilder line = PooledStringBuilder.Get())
+			{
+				if (firstWrite)
+				{
+					firstWrite = false;
+					line.Append(
+						"\"Kerbin Universal Time (s)\"," +
+						"\"Mission Elapsed Time (s)\t\"," +
+						"\"Altitude ASL (m)\"," +
+						"\"Altitude above terrain (m)\"," +
+						"\"Surface Latitude (°)\"," +
+						"\"Surface Longitude (°)\"," +
+						"\"Apoapsis Altitude (m)\"," +
+						"\"Periapsis Altitude (m)\"," +
+						"\"Orbital Inclination (°)\"," +
+						"\"Orbital Velocity (m/s)\"," +
+						"\"Surface Velocity (m/s)\"," +
+						"\"Vertical Speed (m/s)\"," +
+						"\"Horizontal Speed (m/s)\"," +
+						"\"Current Thrust (kN)\"," +
+						"\"Gee Force (gees)\"," +
+						"\"Temperature (°C)\"," +
+						"\"Gravity (m/s²)\"," +
+						"\"Atmosphere Density (g/m³)\"," +
+						"\"Downrange Distance  (m)\"," +
+						"\"Main Throttle\"," +
+						"\n"
+					);
+				}
+
+				// Universal time
+				line.Append(Planetarium.GetUniversalTime().ToString("F2"));
+				line.Append(',');
+
+				//Mission time
+				line.Append(Vessel.missionTime.ToString("F3"));
+				line.Append(',');
+
+				//Altitude ASL
+				line.Append(VOID_Data.orbitAltitude.Value.ToString("G9"));
+				line.Append(',');
+
+				//Altitude (true)
+				line.Append(VOID_Data.trueAltitude.Value.ToString("G9"));
+				line.Append(',');
+
+				// Surface Latitude
+				line.Append('"');
+				line.Append(VOID_Data.surfLatitude.Value.ToString("F3"));
+				line.Append('"');
+				line.Append(',');
+
+				// Surface Longitude
+				line.Append('"');
+				line.Append(VOID_Data.surfLongitude.Value.ToString("F3"));
+				line.Append('"');
+				line.Append(',');
+
+				// Apoapsis Altitude
+				line.Append(VOID_Data.orbitApoAlt.Value.ToString("G9"));
+				line.Append(',');
+
+				// Periapsis Altitude
+				line.Append(VOID_Data.oribtPeriAlt.Value.ToString("G9"));
+				line.Append(',');
+
+				// Orbital Inclination
+				line.Append(VOID_Data.orbitInclination.Value.ToString("F2"));
+				line.Append(',');
+
+				//Orbital velocity
+				line.Append(VOID_Data.orbitVelocity.Value.ToString("G9"));
+				line.Append(',');
+
+				//surface velocity
+				line.Append(VOID_Data.surfVelocity.Value.ToString("G9"));
+				line.Append(',');
+
+				//vertical speed
+				line.Append(VOID_Data.vertVelocity.Value.ToString("G9"));
+				line.Append(',');
+
+				//horizontal speed
+				line.Append(VOID_Data.horzVelocity.Value.ToString("G9"));
+				line.Append(',');
+
+				// Current Thrust
+				line.Append(VOID_Data.currThrust.Value.ToString("G9"));
+				line.Append(',');
+
+				//gee force
+				line.Append(VOID_Data.geeForce.Value.ToString("G9"));
+				line.Append(',');
+
+				//temperature
+				line.Append(VOID_Data.temperature.Value.ToString("F3"));
+				line.Append(',');
+
+				//gravity
+				line.Append(VOID_Data.gravityAccel.Value.ToString("G9"));
+				line.Append(',');
+
+				//atm density
+				line.Append(VOID_Data.atmDensity.Value.ToString("G9"));
+				line.Append(',');
+
+				// Downrange Distance
+				line.Append((VOID_Data.downrangeDistance.Value.ToString("G9")));
+				line.Append(',');
+
+				// Main Throttle
+				line.Append(VOID_Data.mainThrottle.Value.ToString("P2"));
+
+				line.Append('\n');
+
+				csvBytes.AddRange(this.utf8Encoding.GetBytes(line.ToString()));
+
+				this.csvCollectTimer = 0f;
+			}
 		}
 
 		#endregion
@@ -406,7 +435,7 @@
 
 		protected void AsyncWriteCallback(IAsyncResult result)
 		{
-			Tools.PostDebugMessage(this, "Got async callback, IsCompleted = {0}", result.IsCompleted);
+			Logging.PostDebugMessage(this, "Got async callback, IsCompleted = {0}", result.IsCompleted);
 
 			this.outputFile.EndWrite(result);
 			this.outstandingWrites--;
@@ -429,31 +458,32 @@
 
 		private void CloseFileIfOpen()
 		{
-			Tools.DebugLogger logger = Tools.DebugLogger.New(this);
-
-			logger.AppendFormat("Cleaning up file {0}...", this.fileName);
-
-			if (this.csvBytes != null && this.csvBytes.Count > 0)
-			{
-				logger.Append(" Writing remaining data...");
-				this.AsyncWriteData();
-			}
-
-			logger.Append(" Waiting for writes to finish.");
-			while (this.outstandingWrites > 0)
-			{
-				logger.Append('.');
-				System.Threading.Thread.Sleep(10);
-			}
-
-			if (this._outputFile != null)
-			{
-				this._outputFile.Close();
-				this._outputFile = null;
-				logger.Append(" File closed.");
-			}
-
-			logger.Print(false);
+			using (PooledDebugLogger logger = PooledDebugLogger.New(this))
+			{
+				logger.AppendFormat("Cleaning up file {0}...", this.fileName);
+
+				if (this.csvBytes != null && this.csvBytes.Count > 0)
+				{
+					logger.Append(" Writing remaining data...");
+					this.AsyncWriteData();
+				}
+
+				logger.Append(" Waiting for writes to finish.");
+				while (this.outstandingWrites > 0)
+				{
+					logger.Append('.');
+					System.Threading.Thread.Sleep(10);
+				}
+
+				if (this._outputFile != null)
+				{
+					this._outputFile.Close();
+					this._outputFile = null;
+					logger.Append(" File closed.");
+				}
+
+				logger.Print(false);
+			}
 		}
 
 		#endregion

--- a/VOID_EditorHUD.cs
+++ b/VOID_EditorHUD.cs
@@ -28,11 +28,12 @@
 
 using KerbalEngineer.VesselSimulator;
 using KSP;
+using KSP.UI.Screens;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Text;
 using ToadicusTools;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -58,9 +59,12 @@
 			{
 				if (this._vesselOverlays == null)
 				{
-					this._vesselOverlays = (EditorVesselOverlays)Resources
-						.FindObjectsOfTypeAll(typeof(EditorVesselOverlays))
-						.FirstOrDefault();
+					UnityEngine.Object[] overlayObjs = Resources.FindObjectsOfTypeAll(typeof(EditorVesselOverlays));
+
+					if (overlayObjs.Length > 0)
+					{
+						this._vesselOverlays = (EditorVesselOverlays)overlayObjs[0];
+					}
 				}
 
 				return this._vesselOverlays;
@@ -107,123 +111,122 @@
 			this.ehudWindow = new HUDWindow(
 				"editorHUD",
 				this.ehudWindowFunc,
-				new Rect(EditorPanels.Instance.partsPanelWidth + 10f, 125f, 300f, 64f)
+				new Rect(10f, 125f, 300f, 64f)
 			);
 			this.Windows.Add(this.ehudWindow);
 
-			Tools.PostDebugMessage (this.GetType().Name + ": Constructed.");
+			Logging.PostDebugMessage (this.GetType().Name + ": Constructed.");
 		}
 
 		public void ehudWindowFunc(int id)
 		{
-			StringBuilder hudString = new StringBuilder();
-
-			if (this.core.LastStage == null)
-			{
+			using (PooledStringBuilder hudString = PooledStringBuilder.Get())
+			{
+				if (this.core.LastStage == null)
+				{
+					return;
+				}
+
+				VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft;
+
+				hudString.Append("Total Mass: ");
+				hudString.Append(this.core.LastStage.totalMass.ToString("F3"));
+				hudString.Append('t');
+
+				hudString.Append(' ');
+
+				hudString.Append("Part Count: ");
+				hudString.Append(EditorLogic.SortedShipList.Count);
+
+				hudString.Append('\n');
+
+				hudString.Append("Total Delta-V: ");
+				hudString.Append(SIFormatProvider.ToSI(this.core.LastStage.totalDeltaV));
+				hudString.Append("m/s");
+
+				hudString.Append('\n');
+
+				hudString.Append("Bottom Stage Delta-V: ");
+				hudString.Append(SIFormatProvider.ToSI(this.core.LastStage.deltaV));
+				hudString.Append("m/s");
+
+				hudString.Append('\n');
+
+				hudString.Append("Bottom Stage T/W Ratio: ");
+				hudString.Append(this.core.LastStage.thrustToWeight.ToString("F3"));
+
+				Logging.PostDebugMessage(this,
+					"CoMmarker.gameObject.activeInHierarchy: {0};" +
+					"CoTmarker.gameObject.activeInHierarchy: {1}",
+					this.CoMmarker.gameObject.activeInHierarchy,
+					this.CoTmarker.gameObject.activeInHierarchy
+				);
+
+				if (this.CoMmarker.gameObject.activeInHierarchy && this.CoTmarker.gameObject.activeInHierarchy)
+				{
+					Logging.PostDebugMessage(this, "CoM and CoT markers are active, doing thrust offset.");
+					hudString.Append('\n');
+
+					hudString.Append("Thrust Offset: ");
+					hudString.Append(
+						Vector3.Cross(
+							this.CoTmarker.dirMarkerObject.transform.forward,
+							this.CoMmarker.posMarkerObject.transform.position - this.CoTmarker.posMarkerObject.transform.position
+						).ToString("F3"));
+				}
+				#if DEBUG
+			else
+			{
+				Logging.PostDebugMessage(this, "CoM and CoT markers are not active, thrust offset skipped.");
+			}
+				#endif
+
+				GUILayout.Label(
+					hudString.ToString(),
+					VOID_Styles.labelHud,
+					GUILayout.ExpandWidth(true),
+					GUILayout.ExpandHeight(true)
+				);
+
+				if (!this.positionsLocked)
+				{
+					GUI.DragWindow();
+				}
+
+				GUI.BringWindowToBack(id);
+			}
+		}
+
+		public override void DrawGUI(object sender)
+		{
+			float hudLeft;
+
+			try
+			{
+				switch (EditorLogic.fetch.editorScreen)
+				{
+					case EditorScreen.Parts:
+						hudLeft = 16f + EditorPanels.Instance.partsEditor.panelTransform.rect.width +
+							EditorPanels.Instance.partcategorizerModes.transform.localPosition.x;
+						break;
+					case EditorScreen.Actions:
+						hudLeft = EditorPanels.Instance.actions.transform.localPosition.x + 464f;
+						break;
+					default:
+						return;
+				}
+			}
+			catch (NullReferenceException)
+			{
+				Logging.PostErrorMessage(
+					"[{0}]: Something was null when fetching panel geometry; skipping frame.",
+					this.GetType().FullName
+				);
+
 				return;
 			}
 
-			VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft;
-
-			hudString.Append("Total Mass: ");
-			hudString.Append(this.core.LastStage.totalMass.ToString("F3"));
-			hudString.Append('t');
-
-			hudString.Append(' ');
-
-			hudString.Append("Part Count: ");
-			hudString.Append(EditorLogic.SortedShipList.Count);
-
-			hudString.Append('\n');
-
-			hudString.Append("Total Delta-V: ");
-			hudString.Append(Tools.MuMech_ToSI(this.core.LastStage.totalDeltaV));
-			hudString.Append("m/s");
-
-			hudString.Append('\n');
-
-			hudString.Append("Bottom Stage Delta-V");
-			hudString.Append(Tools.MuMech_ToSI(this.core.LastStage.deltaV));
-			hudString.Append("m/s");
-
-			hudString.Append('\n');
-
-			hudString.Append("Bottom Stage T/W Ratio: ");
-			hudString.Append(this.core.LastStage.thrustToWeight.ToString("F3"));
-
-			Tools.PostDebugMessage(this,
-				"CoMmarker.gameObject.activeInHierarchy: {0};" +
-				"CoTmarker.gameObject.activeInHierarchy: {1}",
-				this.CoMmarker.gameObject.activeInHierarchy,
-				this.CoTmarker.gameObject.activeInHierarchy
-			);
-
-			if (this.CoMmarker.gameObject.activeInHierarchy && this.CoTmarker.gameObject.activeInHierarchy)
-			{
-				Tools.PostDebugMessage(this, "CoM and CoT markers are active, doing thrust offset.");
-				hudString.Append('\n');
-
-				hudString.Append("Thrust Offset: ");
-				hudString.Append(
-					Vector3.Cross(
-						this.CoTmarker.dirMarkerObject.transform.forward,
-						this.CoMmarker.posMarkerObject.transform.position - this.CoTmarker.posMarkerObject.transform.position
-					).ToString("F3"));
-			}
-			#if DEBUG
-			else
-			{
-				Tools.PostDebugMessage(this, "CoM and CoT markers are not active, thrust offset skipped.");
-			}
-			#endif
-
-			GUILayout.Label(
-				hudString.ToString(),
-				VOID_Styles.labelHud,
-				GUILayout.ExpandWidth(true),
-				GUILayout.ExpandHeight(true)
-			);
-
-			if (!this.positionsLocked)
-			{
-				GUI.DragWindow();
-			}
-
-			GUI.BringWindowToBack(id);
-		}
-
-		public override void DrawGUI()
-		{
-			float hudLeft;
-
-			if (EditorLogic.fetch.editorScreen == EditorScreen.Parts)
-			{
-				hudLeft = EditorPanels.Instance.partsPanelWidth + 10f;
-				hudLeft += EditorPartList.Instance.transformTopLeft.position.x -
-					EditorPartList.Instance.transformTopLeft.parent.parent.position.x -
-					72f;
-			}
-			else if (EditorLogic.fetch.editorScreen == EditorScreen.Actions)
-			{
-				hudLeft = EditorPanels.Instance.actionsPanelWidth + 10f;
-			}
-			else
-			{
-				return;
-			}
-
-			Tools.PostDebugMessage(this,
-				"EditorPartList topLeft.parent.parent.position: {0}\n" +
-				"EditorPartList topLeft.parent.position: {1}\n" +
-				"EditorPartList topLeft.position: {2}\n" +
-				"snapToEdge: {3} (pos.Xmin: {4}; hudLeft: {5})",
-				EditorPartList.Instance.transformTopLeft.parent.parent.position,
-				EditorPartList.Instance.transformTopLeft.parent.position,
-				EditorPartList.Instance.transformTopLeft.position,
-				this.snapToLeft, this.ehudWindow.WindowPos.xMin, hudLeft
-			);
-
-			base.DrawGUI();
+			base.DrawGUI(this);
 
 			Rect hudPos = this.ehudWindow.WindowPos;
 

--- a/VOID_HUD.cs
+++ b/VOID_HUD.cs
@@ -32,6 +32,7 @@
 using System.Collections.Generic;
 using System.Text;
 using ToadicusTools;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -57,131 +58,128 @@
 
 			this.Active = true;
 
-			this.leftHUD = new HUDWindow("leftHUD", this.leftHUDWindow, new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f));
+			this.leftHUD = new HUDWindow("leftHUD", this.leftHUDWindow, new Rect((float)Screen.width * .375f - 300f, 0f, 300f, 90f));
 			this.Windows.Add(this.leftHUD);
 
-			this.rightHUD = new HUDWindow("rightHUD", this.rightHUDWindow, new Rect(Screen.width * .625f, 0f, 300f, 90f));
+			this.rightHUD = new HUDWindow("rightHUD", this.rightHUDWindow, new Rect((float)Screen.width * .625f, 0f, 300f, 90f));
 			this.Windows.Add(this.rightHUD);
 
-			Tools.PostDebugMessage ("VOID_HUD: Constructed.");
+			Logging.PostDebugMessage ("VOID_HUD: Constructed.");
 		}
 
 		protected void leftHUDWindow(int id)
 		{
-			StringBuilder leftHUD;
+			using (PooledStringBuilder leftHUD = PooledStringBuilder.Get())
+			{
+				VOID_Styles.labelHud.alignment = TextAnchor.UpperRight;
 
-			leftHUD = new StringBuilder();
+				if (this.core.powerAvailable)
+				{
+					leftHUD.AppendFormat("Primary: {0} Inc: {1}",
+						VOID_Data.primaryName.ValueUnitString(),
+						VOID_Data.orbitInclination.ValueUnitString("F3")
+					);
+					leftHUD.AppendFormat("\nObt Alt: {0} Obt Vel: {1}",
+						VOID_Data.orbitAltitude.ToSIString(),
+						VOID_Data.orbitVelocity.ToSIString()
+					);
+					leftHUD.AppendFormat("\nAp: {0} ETA {1}",
+						VOID_Data.orbitApoAlt.ToSIString(),
+						VOID_Data.timeToApo.ValueUnitString()
+					);
+					leftHUD.AppendFormat("\nPe: {0} ETA {1}",
+						VOID_Data.oribtPeriAlt.ToSIString(),
+						VOID_Data.timeToPeri.ValueUnitString()
+					);
+					leftHUD.AppendFormat("\nTot Δv: {0} Stg Δv: {1}",
+						VOID_Data.totalDeltaV.ToSIString(2),
+						VOID_Data.stageDeltaV.ToSIString(2)
+					);
+				}
+				else
+				{
+					VOID_Styles.labelHud.normal.textColor = Color.red;
+					leftHUD.Append(string.Intern("-- POWER LOST --"));
+				}
 
-			VOID_Styles.labelHud.alignment = TextAnchor.UpperRight;
+				GUILayout.Label(
+					leftHUD.ToString(),
+					VOID_Styles.labelHud,
+					GUILayout.ExpandWidth(true),
+					GUILayout.ExpandHeight(true)
+				);
 
-			if (this.core.powerAvailable)
-			{
-				leftHUD.AppendFormat("Primary: {0} Inc: {1}",
-					VOID_Data.primaryName.ValueUnitString(),
-					VOID_Data.orbitInclination.ValueUnitString("F3")
-				);
-				leftHUD.AppendFormat("\nObt Alt: {0} Obt Vel: {1}",
-					VOID_Data.orbitAltitude.ToSIString(),
-					VOID_Data.orbitVelocity.ToSIString()
-				);
-				leftHUD.AppendFormat("\nAp: {0} ETA {1}",
-					VOID_Data.orbitApoAlt.ToSIString(),
-					VOID_Data.timeToApo.ValueUnitString()
-				);
-				leftHUD.AppendFormat("\nPe: {0} ETA {1}",
-					VOID_Data.oribtPeriAlt.ToSIString(),
-					VOID_Data.timeToPeri.ValueUnitString()
-				);
-				leftHUD.AppendFormat("\nTot Δv: {0} Stg Δv: {1}",
-					VOID_Data.totalDeltaV.ToSIString(2),
-					VOID_Data.stageDeltaV.ToSIString(2)
-				);
+				if (!this.positionsLocked)
+				{
+					GUI.DragWindow();
+				}
+
+				GUI.BringWindowToBack(id);
 			}
-			else
-			{
-				VOID_Styles.labelHud.normal.textColor = Color.red;
-				leftHUD.Append(string.Intern("-- POWER LOST --"));
-			}
-
-			GUILayout.Label(
-				leftHUD.ToString(),
-				VOID_Styles.labelHud,
-				GUILayout.ExpandWidth(true),
-				GUILayout.ExpandHeight(true)
-			);
-
-			if (!this.positionsLocked)
-			{
-				GUI.DragWindow();
-			}
-
-			GUI.BringWindowToBack(id);
 		}
 
 		protected void rightHUDWindow(int id)
 		{
-			StringBuilder rightHUD;
+			using (PooledStringBuilder rightHUD = PooledStringBuilder.Get())
+			{
+				VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft;
 
-			rightHUD = new StringBuilder();
+				if (this.core.powerAvailable)
+				{
+					rightHUD.AppendFormat("Biome: {0} Sit: {1}",
+						VOID_Data.currBiome.ValueUnitString(),
+						VOID_Data.expSituation.ValueUnitString()
+					);
+					rightHUD.AppendFormat("\nSrf Alt: {0} Srf Vel: {1}",
+						VOID_Data.trueAltitude.ToSIString(),
+						VOID_Data.surfVelocity.ToSIString()
+					);
+					rightHUD.AppendFormat("\nVer: {0} Hor: {1}",
+						VOID_Data.vertVelocity.ToSIString(),
+						VOID_Data.horzVelocity.ToSIString()
+					);
+					rightHUD.AppendFormat("\nLat: {0} Lon: {1}",
+						VOID_Data.surfLatitudeString.ValueUnitString(),
+						VOID_Data.surfLongitudeString.ValueUnitString()
+					);
+					rightHUD.AppendFormat("\nHdg: {0} Pit: {1}",
+						VOID_Data.vesselHeading.ValueUnitString(),
+						VOID_Data.vesselPitch.ToSIString(2)
+					);
 
-			VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft;
+					if (
+						this.core.Vessel.mainBody == this.core.HomeBody &&
+						(
+						    this.core.Vessel.situation == Vessel.Situations.FLYING ||
+						    this.core.Vessel.situation == Vessel.Situations.SUB_ORBITAL ||
+						    this.core.Vessel.situation == Vessel.Situations.LANDED ||
+						    this.core.Vessel.situation == Vessel.Situations.SPLASHED
+						))
+					{
+						rightHUD.AppendFormat("\nRange to KSC: {0}", VOID_Data.downrangeDistance.ValueUnitString(2));
+					}
+				}
+				else
+				{
+					VOID_Styles.labelHud.normal.textColor = Color.red;
+					rightHUD.Append(string.Intern("-- POWER LOST --"));
+				}
 
-			if (this.core.powerAvailable)
-			{
-				rightHUD.AppendFormat("Biome: {0} Sit: {1}",
-					VOID_Data.currBiome.ValueUnitString(),
-					VOID_Data.expSituation.ValueUnitString()
-				);
-				rightHUD.AppendFormat("\nSrf Alt: {0} Srf Vel: {1}",
-					VOID_Data.trueAltitude.ToSIString(),
-					VOID_Data.surfVelocity.ToSIString()
-				);
-				rightHUD.AppendFormat("\nVer: {0} Hor: {1}",
-					VOID_Data.vertVelocity.ToSIString(),
-					VOID_Data.horzVelocity.ToSIString()
-				);
-				rightHUD.AppendFormat("\nLat: {0} Lon: {1}",
-					VOID_Data.surfLatitude.ValueUnitString(),
-					VOID_Data.surfLongitude.ValueUnitString()
-				);
-				rightHUD.AppendFormat("\nHdg: {0} Pit: {1}",
-					VOID_Data.vesselHeading.ValueUnitString(),
-					VOID_Data.vesselPitch.ToSIString(2)
+
+				GUILayout.Label(
+					rightHUD.ToString(),
+					VOID_Styles.labelHud,
+					GUILayout.ExpandWidth(true),
+					GUILayout.ExpandHeight(true)
 				);
 
-				if (
-					this.core.Vessel.mainBody == this.core.HomeBody &&
-					(
-						this.core.Vessel.situation == Vessel.Situations.FLYING ||
-						this.core.Vessel.situation == Vessel.Situations.SUB_ORBITAL ||
-						this.core.Vessel.situation == Vessel.Situations.LANDED ||
-						this.core.Vessel.situation == Vessel.Situations.SPLASHED
-					)
-				)
+				if (!this.positionsLocked)
 				{
-					rightHUD.AppendFormat("\nRange to KSC: {0}", VOID_Data.downrangeDistance.ValueUnitString(2));
+					GUI.DragWindow();
 				}
+
+				GUI.BringWindowToBack(id);
 			}
-			else
-			{
-				VOID_Styles.labelHud.normal.textColor = Color.red;
-				rightHUD.Append(string.Intern("-- POWER LOST --"));
-			}
-
-
-			GUILayout.Label(
-				rightHUD.ToString(),
-				VOID_Styles.labelHud,
-				GUILayout.ExpandWidth(true),
-				GUILayout.ExpandHeight(true)
-			);
-
-			if (!this.positionsLocked)
-			{
-				GUI.DragWindow();
-			}
-
-			GUI.BringWindowToBack(id);
 		}
 	}
 }

--- a/VOID_HUDAdvanced.cs
+++ b/VOID_HUDAdvanced.cs
@@ -30,9 +30,10 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Text;
 using ToadicusTools;
+using ToadicusTools.GUIUtils;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -79,7 +80,7 @@
 			this.leftHUD = new HUDWindow("leftHUD",
 				this.leftHUDWindow,
 				new Rect(
-					Screen.width * .5f - (float)GameSettings.UI_SIZE * .25f - 300f,
+					Screen.width * .5f - 300f - 220f * GameSettings.UI_SCALE,
 					Screen.height - 200f,
 					300f, 90f)
 			);
@@ -89,7 +90,7 @@
 				"rightHUD",
 				this.rightHUDWindow,
 				new Rect(
-					Screen.width * .5f + (float)GameSettings.UI_SIZE * .25f,
+					Screen.width * .5f + 180f * GameSettings.UI_SCALE,
 					Screen.height - 200f,
 					300f, 90f)
 			);
@@ -97,143 +98,144 @@
 
 			this.positionsLocked.value = true;
 
-			Tools.PostDebugMessage (this, "Constructed.");
+			Logging.PostDebugMessage (this, "Constructed.");
 		}
 
 		protected void leftHUDWindow(int id)
 		{
-			StringBuilder leftHUD;
-
-			leftHUD = new StringBuilder();
-
-			VOID_Styles.labelHud.alignment = TextAnchor.UpperRight;
-
-			if (this.core.powerAvailable)
-			{
-				leftHUD.AppendFormat(
-					string.Intern("Mass: {0}\n"),
-					VOID_Data.totalMass.ToSIString(2)
+			using (PooledStringBuilder leftHUD = PooledStringBuilder.Get())
+			{
+				VOID_Styles.labelHud.alignment = TextAnchor.UpperRight;
+
+				if (this.core.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_Styles.labelHud.normal.textColor = Color.red;
+					leftHUD.Append(string.Intern("-- POWER LOST --"));
+				}
+
+				GUILayout.Label(
+					leftHUD.ToString(),
+					VOID_Styles.labelHud,
+					GUILayout.ExpandWidth(true),
+					GUILayout.ExpandHeight(true)
 				);
 
-				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")
+				if (!this.positionsLocked)
+				{
+					GUI.DragWindow();
+				}
+
+				GUI.BringWindowToBack(id);
+			}
+		}
+
+		protected void rightHUDWindow(int id)
+		{
+			using (PooledStringBuilder rightHUD = PooledStringBuilder.Get())
+			{
+				VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft;
+
+				if (this.core.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.FormatInterval(VOID_Data.currentNodeBurnRemaining.Value),
+						VOID_Tools.FormatInterval(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_Styles.labelHud.normal.textColor = Color.red;
+					rightHUD.Append(string.Intern("-- POWER LOST --"));
+				}
+
+				GUILayout.Label(
+					rightHUD.ToString(),
+					VOID_Styles.labelHud,
+					GUILayout.ExpandWidth(true),
+					GUILayout.ExpandHeight(true)
 				);
 
-				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_Styles.labelHud.normal.textColor = Color.red;
-				leftHUD.Append(string.Intern("-- POWER LOST --"));
-			}
-
-			GUILayout.Label(
-				leftHUD.ToString(),
-				VOID_Styles.labelHud,
-				GUILayout.ExpandWidth(true),
-				GUILayout.ExpandHeight(true)
-			);
-
-			if (!this.positionsLocked)
-			{
-				GUI.DragWindow();
-			}
-
-			GUI.BringWindowToBack(id);
-		}
-
-		protected void rightHUDWindow(int id)
-		{
-			StringBuilder rightHUD;
-
-			rightHUD = new StringBuilder();
-
-			VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft;
-
-			if (this.core.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.FormatInterval(VOID_Data.currentNodeBurnRemaining.Value),
-					VOID_Tools.FormatInterval(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_Styles.labelHud.normal.textColor = Color.red;
-				rightHUD.Append(string.Intern("-- POWER LOST --"));
-			}
-
-			GUILayout.Label(
-				rightHUD.ToString(),
-				VOID_Styles.labelHud,
-				GUILayout.ExpandWidth(true),
-				GUILayout.ExpandHeight(true)
-			);
-
-			if (!this.positionsLocked)
-			{
-				GUI.DragWindow();
-			}
-
-			GUI.BringWindowToBack(id);
-		}
-
-		public override void DrawGUI()
+				if (!this.positionsLocked)
+				{
+					GUI.DragWindow();
+				}
+
+				GUI.BringWindowToBack(id);
+			}
+		}
+
+		public override void DrawGUI(object sender)
 		{
 			if (this.primaryHUD == null)
 			{
-				foreach (IVOID_Module module in this.core.Modules)
-				{
+				IVOID_Module module;
+				for (int idx = 0; idx < this.core.Modules.Count; idx++)
+				{
+					module = this.core.Modules[idx];
+
 					if (module is VOID_HUD)
 					{
 						this.primaryHUD = module as VOID_HUD;
@@ -250,22 +252,23 @@
 				this.Windows.Add(this.rightHUD);
 			}
 
-			base.DrawGUI();
+			base.DrawGUI(sender);
 		}
 
 		public override void DrawConfigurables()
 		{
-			base.DrawConfigurables();
-
 			if (GUILayout.Button(string.Intern("Reset Advanced HUD Positions"), GUILayout.ExpandWidth(false)))
 			{
-				foreach (HUDWindow window in this.Windows)
-				{
+				HUDWindow window;
+				for (int idx = 0; idx < this.Windows.Count; idx++)
+				{
+					window = this.Windows[idx];
+
 					window.WindowPos = new Rect(window.defaultWindowPos);
 				}
 			}
 
-			this.positionsLocked.value = GUITools.Toggle(this.positionsLocked, string.Intern("Lock Advanced HUD Positions"));
+			this.positionsLocked.value = Layout.Toggle(this.positionsLocked, string.Intern("Lock Advanced HUD Positions"));
 		}
 	}
 }

--- a/VOID_Orbital.cs
+++ b/VOID_Orbital.cs
@@ -29,6 +29,7 @@
 using KSP;
 using System;
 using ToadicusTools;
+using ToadicusTools.GUIUtils;
 using UnityEngine;
 
 namespace VOID
@@ -39,7 +40,7 @@
 		protected VOID_SaveValue<bool> toggleExtended;
 
 		[AVOID_SaveValue("precisionValues")]
-		protected long _precisionValues;
+		protected VOID_SaveValue<long> _precisionValues;
 		protected IntCollection precisionValues;
 
 		public VOID_Orbital()
@@ -51,7 +52,7 @@
 
 			this.toggleExtended = (VOID_SaveValue<bool>)false;
 
-			this._precisionValues = 230584300921369395;
+			this._precisionValues = (VOID_SaveValue<long>)384307168202282325;
 		}
 
 		public override void ModuleWindow(int id)
@@ -83,7 +84,7 @@
 			this.precisionValues [idx]= (ushort)VOID_Data.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]);
 			idx++;
 
-			this.toggleExtended.value = GUITools.Toggle(this.toggleExtended, "Extended info");
+			this.toggleExtended.value = Layout.Toggle(this.toggleExtended, "Extended info");
 
 			if (this.toggleExtended)
             {
@@ -112,24 +113,23 @@
             }
 
             GUILayout.EndVertical();
-            
+
 			base.ModuleWindow(id);
 		}
 
-		public override void LoadConfig ()
+		public override void LoadConfig(KSP.IO.PluginConfiguration config)
 		{
-			base.LoadConfig ();
+			base.LoadConfig(config);
 
 			this.precisionValues = new IntCollection (4, this._precisionValues);
 		}
 
-		public override void Save (KSP.IO.PluginConfiguration config)
+		public override void Save (KSP.IO.PluginConfiguration config, string sceneKey)
 		{
-			this._precisionValues = this.precisionValues.collection;
+			this._precisionValues.value = this.precisionValues.collection;
 
-			base.Save (config);
+			base.Save (config, sceneKey);
 		}
 	}
 }
 
-

--- a/VOID_Rendezvous.cs
+++ b/VOID_Rendezvous.cs
@@ -29,8 +29,9 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using ToadicusTools;
+using ToadicusTools.GUIUtils;
+using ToadicusTools.Text;
 using UnityEngine;
 
 namespace VOID
@@ -58,12 +59,19 @@
 
 		public override void ModuleWindow(int id)
 		{
-			Vessel rendezvessel = new Vessel();
-			CelestialBody rendezbody = new CelestialBody();
+			Vessel rendezvessel;
+			CelestialBody rendezbody;
 
 			if (this.RegisterModule == null)
 			{
-				this.RegisterModule = this.core.Modules.Where(m => typeof(VOID_VesselRegister).IsAssignableFrom(m.GetType())).FirstOrDefault() as VOID_VesselRegister;
+				for (int idx = 0; idx < this.core.Modules.Count; idx++)
+				{
+					if (this.core.Modules[idx] is VOID_VesselRegister)
+					{
+						this.RegisterModule = this.core.Modules[idx] as VOID_VesselRegister;
+						break;
+					}
+				}
 			}
 
 			GUILayout.BeginVertical();
@@ -90,7 +98,7 @@
 				if (GUILayout.Button("Unset Target", GUILayout.ExpandWidth(false)))
 				{
 					FlightGlobals.fetch.SetVesselTarget(null);
-					Tools.PostDebugMessage("VOID_Rendezvous: KSP Target set to null");
+					Logging.PostDebugMessage("VOID_Rendezvous: KSP Target set to null");
 				}
 
 			}
@@ -117,7 +125,7 @@
 						if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false)))
 						{
 							FlightGlobals.fetch.SetVesselTarget(rendezvessel);
-							Tools.PostDebugMessage("[VOID] KSP Target set to " + rendezvessel.vesselName);
+							Logging.PostDebugMessage("[VOID] KSP Target set to " + rendezvessel.vesselName);
 						}
 					}
 				}
@@ -129,7 +137,7 @@
 				}
 			}
 
-			untoggleRegisterInfo.value = GUITools.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info");
+			untoggleRegisterInfo.value = Layout.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info");
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			GUILayout.Label(" ", GUILayout.ExpandWidth(true));
@@ -160,12 +168,12 @@
 					//display orbital info for orbiting/flying/suborbital/escaping vessels only
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Ap/Pe:");
-					GUILayout.Label(Tools.MuMech_ToSI(v.orbit.ApA) + "m / " + Tools.MuMech_ToSI(v.orbit.PeA) + "m", GUILayout.ExpandWidth(false));
+					GUILayout.Label(SIFormatProvider.ToSI(v.orbit.ApA, 3) + "m / " + SIFormatProvider.ToSI(v.orbit.PeA, 3) + "m", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Altitude:");
-					GUILayout.Label(Tools.MuMech_ToSI(v.orbit.altitude) + "m", GUILayout.ExpandWidth(false));
+					GUILayout.Label(SIFormatProvider.ToSI(v.orbit.altitude, 3) + "m", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
@@ -177,24 +185,24 @@
 					{
 						GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 						GUILayout.Label("Relative inclination:");
-						GUILayout.Label(Vector3d.Angle(Vessel.orbit.GetOrbitNormal(), v.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false));
+						GUILayout.Label(Vector3.Angle(Vessel.orbit.GetOrbitNormal(), v.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false));
 						GUILayout.EndHorizontal();
 					}
 					//if (debugging) Debug.Log("[CHATR] v -> v relative incl OK");
 
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Velocity:");
-					GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false));
+					GUILayout.Label(SIFormatProvider.ToSI(v.orbit.vel.magnitude, 3) + "m/s", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Relative velocity:");
-					GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude - Vessel.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false));
+					GUILayout.Label(SIFormatProvider.ToSI(v.orbit.vel.magnitude - Vessel.orbit.vel.magnitude, 3) + "m/s", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Distance:");
-					GUILayout.Label(Tools.MuMech_ToSI((Vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false));
+					GUILayout.Label(SIFormatProvider.ToSI((Vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude, 3) + "m", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 
 					// Toadicus edit: added local sidereal longitude.
@@ -203,7 +211,7 @@
 					GUILayout.Label(LSL.ToString("F3") + "°", VOID_Styles.labelRight);
 					GUILayout.EndHorizontal();
 
-					toggleExtendedOrbital.value = GUITools.Toggle(toggleExtendedOrbital, "Extended info");
+					toggleExtendedOrbital.value = Layout.Toggle(toggleExtendedOrbital, "Extended info");
 
 					if (toggleExtendedOrbital)
 					{
@@ -264,7 +272,7 @@
 
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Distance:");
-					GUILayout.Label(Tools.MuMech_ToSI((Vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false));
+					GUILayout.Label(SIFormatProvider.ToSI((Vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude, 3) + "m", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 				}
 			}
@@ -275,7 +283,7 @@
 
 				GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 				GUILayout.Label("Ap/Pe:");
-				GUILayout.Label(Tools.MuMech_ToSI(cb.orbit.ApA) + "m / " + Tools.MuMech_ToSI(cb.orbit.PeA) + "m", GUILayout.ExpandWidth(false));
+				GUILayout.Label(SIFormatProvider.ToSI(cb.orbit.ApA, 3) + "m / " + SIFormatProvider.ToSI(cb.orbit.PeA, 3) + "m", GUILayout.ExpandWidth(false));
 				GUILayout.EndHorizontal();
 				//if (debugging) Debug.Log("[VOID] Ap/Pe OK");
 
@@ -289,14 +297,14 @@
 				{
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					GUILayout.Label("Relative inclination:");
-					GUILayout.Label(Vector3d.Angle(Vessel.orbit.GetOrbitNormal(), cb.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false));
+					GUILayout.Label(Vector3.Angle(Vessel.orbit.GetOrbitNormal(), cb.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false));
 					GUILayout.EndHorizontal();
 					//if (debugging) Debug.Log("[VOID] cb Relative inclination OK");
 				}
 
 				GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 				GUILayout.Label("Distance:");
-				GUILayout.Label(Tools.MuMech_ToSI((Vessel.mainBody.position - cb.position).magnitude) + "m", GUILayout.ExpandWidth(false));
+				GUILayout.Label(SIFormatProvider.ToSI((Vessel.mainBody.position - cb.position).magnitude, 3) + "m", GUILayout.ExpandWidth(false));
 				GUILayout.EndHorizontal();
 
 				//if (debugging) Debug.Log("[VOID] Distance OK");

--- a/VOID_StageInfo.cs
+++ b/VOID_StageInfo.cs
@@ -7,8 +7,7 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using ToadicusTools;
+using ToadicusTools.GUIUtils;
 using UnityEngine;
 
 namespace VOID
@@ -33,9 +32,7 @@
 		private bool showBodyList;
 		private Rect bodyListPos;
 
-		private bool showColumnSelection;
-
-		private CelestialBody selectedBody;
+		private CelestialBody _selectedBody;
 		[AVOID_SaveValue("bodyIdx")]
 		private VOID_SaveValue<int> bodyIdx;
 		private int lastIdx;
@@ -46,6 +43,19 @@
 		private VOID_SaveValue<bool> useSeaLevel;
 		private GUIContent seaLevelToggle;
 
+		private CelestialBody selectedBody
+		{
+			get
+			{
+				return this._selectedBody;
+			}
+			set
+			{
+				this._selectedBody = value;
+				KerbalEngineer.Helpers.CelestialBodies.SelectedBody = value;
+			}
+		}
+
 		public VOID_StageInfo() : base()
 		{
 			this.Name = "Stage Information";
@@ -54,7 +64,6 @@
 
 			this.stylesApplied = false;
 			this.showBodyList = false;
-			this.showColumnSelection = false;
 
 			this.bodyListPos = new Rect();
 
@@ -104,9 +113,9 @@
 			);
 		}
 
-		public override void DrawGUI()
-		{
-			base.DrawGUI();
+		public override void DrawGUI(object sender)
+		{
+			base.DrawGUI(sender);
 
 			if (this.showBodyList)
 			{
@@ -151,15 +160,18 @@
 
 			if (HighLogic.LoadedSceneIsEditor && this.selectedBody.atmosphere && this.useSeaLevel)
 			{
-				SimManager.Atmosphere = this.selectedBody.atmosphereMultiplier * 101.325d;
+				SimManager.Atmosphere = this.selectedBody.GetPressure(0) * PhysicsGlobals.KpaToAtmospheres;
 			}
 			else
 			{
 				SimManager.Atmosphere = 0d;
 			}
 
-			foreach (Stage stage in core.Stages)
-			{
+			Stage stage;
+			for (int idx = 0; idx < core.Stages.Length; idx++)
+			{
+				stage = core.Stages[idx];
+
 				if (stage.deltaV == 0 && stage.mass == 0)
 				{
 					continue;
@@ -244,7 +256,7 @@
 			{
 				GUILayout.BeginHorizontal();
 
-				this.useSeaLevel.value = GUITools.Toggle(this.useSeaLevel, this.seaLevelToggle, false);
+				this.useSeaLevel.value = Layout.Toggle(this.useSeaLevel, this.seaLevelToggle, false);
 
 				GUILayout.EndHorizontal();
 			}
@@ -266,17 +278,15 @@
 
 		public override void DrawConfigurables()
 		{
-			this.showColumnSelection = GUILayout.Toggle(
-				this.showColumnSelection,
-				"Select StageInfo Columns",
-				GUI.skin.button
-			);
+			
 		}
 
 		private void BodyPickerWindow(int _)
 		{
-			foreach (CelestialBody body in core.SortedBodyList)
-			{
+			CelestialBody body;
+			for (int idx = 0; idx < core.SortedBodyList.Count; idx++)
+			{
+				body = core.SortedBodyList[idx];
 				if (GUILayout.Button(body.bodyName, VOID_Styles.labelDefault))
 				{
 					Debug.Log("Picked new body focus: " + body.bodyName);

--- a/VOID_Styles.cs
+++ b/VOID_Styles.cs
@@ -33,12 +33,6 @@
 {
 	public static class VOID_Styles
 	{
-		public static bool Ready
-		{
-			get;
-			private set;
-		}
-
 		public static GUIStyle labelDefault
 		{
 			get;
@@ -115,17 +109,12 @@
 
 			labelGreen = new GUIStyle(GUI.skin.label);
 			labelGreen.normal.textColor = Color.green;
-
-			Ready = true;
 		}
 
 		static VOID_Styles()
 		{
 			OnSkinChanged();
-
-			Ready = false;
 		}
 	}
 }
 
-

--- a/VOID_SurfAtmo.cs
+++ b/VOID_SurfAtmo.cs
@@ -41,12 +41,12 @@
 
 		public VOID_SurfAtmo()
 		{
-			this.Name = "Surface & Atmospheric Information";
+			this.Name = "Surface & Atmospheric Info";
 
 			this.WindowPos.x = Screen.width - 260f;
 			this.WindowPos.y = 85;
 
-			this._precisionValues = (VOID_SaveValue<long>)230584300921369395;
+			this._precisionValues = (VOID_SaveValue<long>)384307168202282325;
 		}
 
 		public override void ModuleWindow(int id)
@@ -55,60 +55,61 @@
 
 			GUILayout.BeginVertical();
 
-			this.precisionValues [idx]= (ushort)VOID_Data.trueAltitude.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.trueAltitude.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
-			VOID_Data.surfLatitude.DoGUIHorizontal ();
+			VOID_Data.surfLatitudeString.DoGUIHorizontal();
 
-			VOID_Data.surfLongitude.DoGUIHorizontal ();
+			VOID_Data.surfLongitudeString.DoGUIHorizontal();
 
-			VOID_Data.vesselHeading.DoGUIHorizontal ();
+			VOID_Data.vesselHeading.DoGUIHorizontal();
 
-			this.precisionValues [idx]= (ushort)VOID_Data.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.terrainElevation.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
 			this.precisionValues[idx] = (ushort)VOID_Data.downrangeDistance.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
-			this.precisionValues [idx]= (ushort)VOID_Data.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.surfVelocity.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
-			this.precisionValues [idx]= (ushort)VOID_Data.vertVelocity.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.vertVelocity.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
-			this.precisionValues [idx]= (ushort)VOID_Data.horzVelocity.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.horzVelocity.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
-			VOID_Data.temperature.DoGUIHorizontal ("F2");
+			VOID_Data.temperature.DoGUIHorizontal("F2");
 
-			this.precisionValues [idx]= (ushort)VOID_Data.atmDensity.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.atmDensity.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
-			VOID_Data.atmPressure.DoGUIHorizontal ("F2");
+			this.precisionValues[idx] = (ushort)VOID_Data.atmPressure.DoGUIHorizontal(this.precisionValues[idx]);
+			idx++;
 
-			this.precisionValues [idx]= (ushort)VOID_Data.atmLimit.DoGUIHorizontal (this.precisionValues [idx]);
+			this.precisionValues[idx] = (ushort)VOID_Data.atmLimit.DoGUIHorizontal(this.precisionValues[idx]);
 			idx++;
 
 			// Toadicus edit: added Biome
-			VOID_Data.currBiome.DoGUIHorizontal ();
+			VOID_Data.currBiome.DoGUIHorizontal();
 
 			GUILayout.EndVertical();
 
 			base.ModuleWindow(id);
 		}
 
-		public override void LoadConfig ()
+		public override void LoadConfig(KSP.IO.PluginConfiguration config)
 		{
-			base.LoadConfig ();
+			base.LoadConfig(config);
 
-			this.precisionValues = new IntCollection (4, this._precisionValues);
+			this.precisionValues = new IntCollection(4, this._precisionValues);
 		}
 
-		public override void Save (KSP.IO.PluginConfiguration config)
+		public override void Save(KSP.IO.PluginConfiguration config, string sceneKey)
 		{
 			this._precisionValues.value = this.precisionValues.collection;
 
-			base.Save (config);
+			base.Save(config, sceneKey);
 		}
 	}
 }

--- a/VOID_TWR.cs
+++ b/VOID_TWR.cs
@@ -3,11 +3,9 @@
 // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
 // copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
 
+using KerbalEngineer.VesselSimulator;
 using KSP;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
@@ -28,7 +26,7 @@
 				(TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)
 			)
 			{
-				KerbalEngineer.VesselSimulator.SimManager.RequestSimulation();
+				SimManager.RequestSimulation();
 			}
 
 			GUILayout.BeginVertical();
@@ -43,8 +41,11 @@
 			}
 			else
 			{
-				foreach (CelestialBody body in core.SortedBodyList)
+				CelestialBody body;
+				for (int idx = 0; idx < core.SortedBodyList.Count; idx++)
 				{
+					body = core.SortedBodyList[idx];
+
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 
 					GUILayout.Label(body.bodyName);

--- a/VOID_Transfer.cs
+++ b/VOID_Transfer.cs
@@ -29,7 +29,6 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using ToadicusTools;
 using UnityEngine;
 
@@ -50,12 +49,16 @@
 
 		public override void ModuleWindow(int id)
 		{
+			CelestialBody body;
+
 			GUILayout.BeginVertical();
 
 			if (Vessel.mainBody.name == "Sun")  //Vessel is orbiting the Sun
 			{
-			    foreach (CelestialBody body in Vessel.mainBody.orbitingBodies)
+			    for (int idx = 0; idx < Vessel.mainBody.orbitingBodies.Count; idx++)
 			    {
+					body = Vessel.mainBody.orbitingBodies[idx];
+
 					GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 					if (GUILayout.Button(body.bodyName))
 					{
@@ -75,8 +78,9 @@
 			}
 			else if (Vessel.mainBody.referenceBody.name == "Sun")	//Vessel is orbiting a planet
 			{
-			    foreach (CelestialBody body in Vessel.mainBody.referenceBody.orbitingBodies)
-			    {
+			    for (int idx = 0; idx < Vessel.mainBody.referenceBody.orbitingBodies.Count; idx++)
+				{
+					body = Vessel.mainBody.referenceBody.orbitingBodies[idx];
 			        if (body.name != Vessel.mainBody.name)	// show other planets
 			        {
 			            GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
@@ -96,8 +100,10 @@
 			            }
 			        }
 			    }
-			    foreach (CelestialBody body in Vessel.mainBody.orbitingBodies)	// show moons
+			    for (int moonIdx = 0; moonIdx < Vessel.mainBody.orbitingBodies.Count; moonIdx++)
 			    {
+					body = Vessel.mainBody.orbitingBodies[moonIdx];
+
 			        GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			        if (GUILayout.Button(body.bodyName))
 			        {
@@ -117,8 +123,10 @@
 			}
 			else if (Vessel.mainBody.referenceBody.referenceBody.name == "Sun")	// Vessel is orbiting a moon
 			{
-			    foreach (CelestialBody body in Vessel.mainBody.referenceBody.orbitingBodies)
+			    for (int idx = 0; idx < Vessel.mainBody.referenceBody.orbitingBodies.Count; idx++)
 			    {
+					body = Vessel.mainBody.referenceBody.orbitingBodies[idx];
+
 					if (body.name != Vessel.mainBody.name)	// show other moons
 					{
 						GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
@@ -155,7 +163,7 @@
 		            if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false)))
 		            {
 		                FlightGlobals.fetch.SetVesselTarget(body);
-						Tools.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName);
+						Logging.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName);
 		            }
 		        }
 		        else if ((CelestialBody)FlightGlobals.fetch.VesselTarget == body)
@@ -163,7 +171,7 @@
 		            if (GUILayout.Button("Unset Target", GUILayout.ExpandWidth(false)))
 		            {
 		                FlightGlobals.fetch.SetVesselTarget(null);
-		                Tools.PostDebugMessage("[VOID] KSP Target set to null");
+		                Logging.PostDebugMessage("[VOID] KSP Target set to null");
 		            }
 		        }
 		    }
@@ -173,7 +181,7 @@
 		        if (GUILayout.Button("Set Target", GUILayout.ExpandWidth(false)))
 		        {
 		            FlightGlobals.fetch.SetVesselTarget(body);
-		            Tools.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName);
+		            Logging.PostDebugMessage("[VOID] KSP Target set to CelestialBody " + body.bodyName);
 		        }
 		    }
 		}

--- a/VOID_VesselInfo.cs
+++ b/VOID_VesselInfo.cs
@@ -31,7 +31,6 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
@@ -60,27 +59,27 @@
 				VOID_Styles.labelCenterBold,
 				GUILayout.ExpandWidth(true));
 
-			VOID_Data.geeForce.DoGUIHorizontal ("F2");
+			VOID_Data.geeForce.DoGUIHorizontal("F2");
 
-			VOID_Data.partCount.DoGUIHorizontal ();
+			VOID_Data.partCount.DoGUIHorizontal();
 
-			VOID_Data.totalMass.DoGUIHorizontal ("F3");
+			VOID_Data.totalMass.DoGUIHorizontal("F3");
 
-			VOID_Data.stageResourceMass.DoGUIHorizontal("F2");
+			VOID_Data.stageResourceMass.DoGUIHorizontal("F3");
 
-			VOID_Data.resourceMass.DoGUIHorizontal("F2");
+			VOID_Data.resourceMass.DoGUIHorizontal("F3");
 
-			VOID_Data.stageDeltaV.DoGUIHorizontal (3, false);
+			VOID_Data.stageDeltaV.DoGUIHorizontal(3, false);
 
-			VOID_Data.totalDeltaV.DoGUIHorizontal (3, false);
+			VOID_Data.totalDeltaV.DoGUIHorizontal(3, false);
 
-			VOID_Data.mainThrottle.DoGUIHorizontal ("F0");
+			VOID_Data.mainThrottle.DoGUIHorizontal("P0");
 
-			VOID_Data.currmaxThrust.DoGUIHorizontal ();
+			VOID_Data.currmaxThrust.DoGUIHorizontal();
 
-			VOID_Data.currmaxThrustWeight.DoGUIHorizontal ();
+			VOID_Data.currmaxThrustWeight.DoGUIHorizontal();
 
-			VOID_Data.surfaceThrustWeight.DoGUIHorizontal ("F2");
+			VOID_Data.surfaceThrustWeight.DoGUIHorizontal("F2");
 
 			VOID_Data.intakeAirStatus.DoGUIHorizontal();
 

--- a/VOID_VesselRegister.cs
+++ b/VOID_VesselRegister.cs
@@ -28,8 +28,6 @@
 
 using KSP;
 using System;
-using System.Linq;
-using ToadicusTools;
 using UnityEngine;
 
 namespace VOID
@@ -76,9 +74,19 @@
 
 		public override void ModuleWindow(int id)
 		{
-			if (!this.core.AllVesselTypes.Any())
+			if (this.core.AllVesselTypes.Length < 1)
 			{
 				return;
+			}
+
+			if (selectedBodyIdx >= this.core.SortedBodyList.Count)
+			{
+				selectedBodyIdx.value %= this.core.SortedBodyList.Count;
+			}
+
+			if (selectedBodyIdx < 0)
+			{
+				selectedBodyIdx.value += this.core.SortedBodyList.Count;
 			}
 
 			GUILayout.BeginVertical();
@@ -89,21 +97,21 @@
 				selectedBodyIdx.value--;
 				if (selectedBodyIdx < 0)
 				{
-					selectedBodyIdx.value = this.core.AllBodies.Count - 1;
+					selectedBodyIdx.value = this.core.SortedBodyList.Count - 1;
 				}
 			}
-			GUILayout.Label(this.core.AllBodies[selectedBodyIdx].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
+			GUILayout.Label(this.core.SortedBodyList[selectedBodyIdx].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true));
 			if (GUILayout.Button(">"))
 			{
 				selectedBodyIdx.value++;
-				if (selectedBodyIdx > this.core.AllBodies.Count - 1)
+				if (selectedBodyIdx > this.core.SortedBodyList.Count - 1)
 				{
 					selectedBodyIdx.value = 0;
 				}
 			}
 			GUILayout.EndHorizontal();
 
-			seletedBody = this.core.AllBodies[selectedBodyIdx];
+			seletedBody = this.core.SortedBodyList[selectedBodyIdx];
 
 			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
 			if (GUILayout.Button("<"))
@@ -141,8 +149,11 @@
 
 			selectorScrollPos = GUILayout.BeginScrollView(selectorScrollPos, false, false);
 
-			foreach (Vessel v in FlightGlobals.Vessels)
+			Vessel v;
+			for (int idx = 0; idx < FlightGlobals.Vessels.Count; idx++)
 			{
+				v = FlightGlobals.Vessels[idx];
+
 				if (v != Vessel && v.vesselType == selectedVesselType && v.mainBody == seletedBody)
 				{
 					if ((vesselSituation == "Landed" &&