updated for 1.1.3
updated for 1.1.3

file:b/.gitignore (new)
--- /dev/null
+++ b/.gitignore
@@ -1,1 +1,248 @@
-
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+[Xx]64/
+[Xx]86/
+[Bb]uild/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+
+# TODO: Un-comment the next line if you do not want to checkin 
+# your web deploy settings because they may include unencrypted
+# passwords
+#*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Microsoft Azure ApplicationInsights config file
+ApplicationInsights.config
+
+# Windows Store app package directory
+AppPackages/
+BundleArtifacts/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# LightSwitch generated files
+GeneratedArtifacts/
+ModelManifest.xml
+
+# Paket dependency manager
+.paket/paket.exe
+
+# FAKE - F# Make
+.fake/
+
+*.dll
+

--- a/ARConfiguration.cs
+++ b/ARConfiguration.cs
@@ -6,6 +6,8 @@
 using KSP;
 using KSP.UI.Screens;
 using System;
+using System.Collections.Generic;
+using System.Reflection;
 using ToadicusTools.Extensions;
 using ToadicusTools.Text;
 using ToadicusTools.GUIUtils;
@@ -130,6 +132,8 @@
 
 #pragma warning disable 1591
 
+		private static MethodInfo partLoader_CompilePartInfo;
+
 		private bool showConfigWindow;
 		private Rect configWindowPos;
 
@@ -230,6 +234,16 @@
 					this.trackingStationRanges.SPrint());
 			}
 
+			if (partLoader_CompilePartInfo == null)
+			{
+				partLoader_CompilePartInfo = typeof(PartLoader).GetMethod(
+					"CompilePartInfo",
+					BindingFlags.NonPublic | BindingFlags.Instance
+				);
+
+				this.Log("Fetched PartLoader.CompilePartInfo: {0}", partLoader_CompilePartInfo);
+			}
+
 			this.runOnce = true;
 
 			this.LogDebug("Awake.");
@@ -245,6 +259,7 @@
 				this.runOnce = false;
 
 				this.SetKerbinRelayRange();
+				this.updateModuleInfos();
 			}
 		}
 
@@ -352,6 +367,8 @@
 			{
 				ARConfiguration.FixedPowerCost = fixedPowerCost;
 				this.SaveConfigValue(FIXED_POWER_KEY, fixedPowerCost);
+
+				this.updateModuleInfos();
 			}
 
 			GUILayout.EndHorizontal();
@@ -363,6 +380,8 @@
 			{
 				ARConfiguration.UseAdditiveRanges = useAdditive;
 				this.SaveConfigValue(USE_ADDITIVE_KEY, useAdditive);
+
+				this.updateModuleInfos();
 			}
 
 			GUILayout.EndHorizontal();
@@ -468,6 +487,92 @@
 			{
 				this.Log("Caught onFacilityUpgraded for {0} at level {1}", fac.id, lvl);
 				this.SetKerbinRelayRange();
+
+				this.updateModuleInfos();
+			}
+		}
+
+		private void updateModuleInfos()
+		{
+			if (PartLoader.Instance != null && PartLoader.Instance.parts != null)
+			{
+				this.Log("Updating module infos in PartLoader");
+				this.updateModuleInfos(PartLoader.Instance.parts);
+			}
+
+			if (RDTestSceneLoader.Instance != null && RDTestSceneLoader.Instance.partsList != null)
+			{
+				this.Log("Updating module infos in RDTestSceneLoader");
+				this.updateModuleInfos(RDTestSceneLoader.Instance.partsList);
+			}
+		}
+
+		private void updateModuleInfos(List<AvailablePart> partsList)
+		{
+			if (partLoader_CompilePartInfo == null)
+			{
+				this.LogError("Cannot recompile part info; partLoader_CompilePartInfo not found.");
+				return;
+			}
+
+			if (PartLoader.Instance == null)
+			{
+				this.LogError("Cannot recompile part info; PartLoader.Instance is null.");
+				return;
+			}
+
+			// We need to go find all of the prefabs and update them, because Squad broke IModuleInfo.
+			AvailablePart availablePart;
+			Part partPrefab;
+			PartModule modulePrefab;
+			object[] compileArgs = new object[2];
+
+			this.Log("Updating module infos...");
+
+			for (int apIdx = 0; apIdx < partsList.Count; apIdx++)
+			{
+				availablePart = partsList[apIdx];
+
+				if (availablePart == null)
+				{
+					continue;
+				}
+
+				partPrefab = availablePart.partPrefab;
+
+				if (partPrefab == null || partPrefab.Modules == null)
+				{
+					continue;
+				}
+
+				for (int pmIdx = 0; pmIdx < partPrefab.Modules.Count; pmIdx++)
+				{
+					modulePrefab = partPrefab.Modules[pmIdx];
+
+					if (modulePrefab == null)
+					{
+						continue;
+					}
+
+					if (modulePrefab is IAntennaRelay)
+					{
+						this.Log("Found prefab IAntennaRelay {0}", modulePrefab);
+
+						this.Log("Recompiling part and module info for {0}", availablePart.name);
+
+						availablePart.moduleInfos.Clear();
+						availablePart.resourceInfos.Clear();
+
+						compileArgs[0] = availablePart;
+						compileArgs[1] = partPrefab;
+                        if (PartLoader.Instance != null)
+                            partLoader_CompilePartInfo.Invoke(PartLoader.Instance, compileArgs);
+                        else
+                            this.Log("PartLoader.Instance is null");
+
+						break;
+					}
+				}
 			}
 		}
 

--- a/ARFlightController.cs
+++ b/ARFlightController.cs
@@ -157,8 +157,9 @@
 				this.toolbarButton.TexturePath = this.toolbarTextures[ConnectionStatus.None];
 				this.toolbarButton.Text = "AntennaRange";
 				this.toolbarButton.Visibility = new GameScenesVisibility(GameScenes.FLIGHT);
-				this.toolbarButton.OnClick += (e) => (this.buttonToggle());
-			}
+                this.toolbarButton.OnClick += (e) => { this.buttonToggle(); };
+                
+            }
 
 			GameEvents.onGameSceneLoadRequested.Add(this.onSceneChangeRequested);
 			GameEvents.onVesselChange.Add(this.onVesselChange);
@@ -173,7 +174,7 @@
 
 			VesselCommand availableCommand;
 
-			if (ARConfiguration.RequireConnectionForControl)
+			if (ARConfiguration.RequireConnectionForControl && this.vessel != null)
 			{
 				availableCommand = this.vessel.CurrentCommand();
 			}

--- a/AntennaRange.csproj
+++ b/AntennaRange.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration>
@@ -85,28 +85,24 @@
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
     <Reference Include="Assembly-CSharp">
-      <HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>R:\KSP_1.1.3_dev\KSP_x64_Data\Managed\Assembly-CSharp.dll</HintPath>
+    </Reference>
+    <Reference Include="KSPUtil">
+      <HintPath>R:\KSP_1.1.3_dev\KSP_x64_Data\Managed\KSPUtil.dll</HintPath>
     </Reference>
     <Reference Include="System">
       <HintPath>..\_KSPAssemblies\System.dll</HintPath>
       <Private>False</Private>
     </Reference>
+    <Reference Include="ToadicusTools">
+      <HintPath>R:\KSP_1.1.3_dev\GameData\ToadicusTools\ToadicusTools.dll</HintPath>
+    </Reference>
     <Reference Include="UnityEngine">
-      <HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath>
-    </Reference>
-    <Reference Include="KSPUtil">
-      <HintPath>..\_KSPAssemblies\KSPUtil.dll</HintPath>
+      <HintPath>R:\KSP_1.1.3_dev\KSP_x64_Data\Managed\UnityEngine.dll</HintPath>
     </Reference>
     <Reference Include="UnityEngine.UI">
-      <HintPath>..\_KSPAssemblies\UnityEngine.UI.dll</HintPath>
+      <HintPath>R:\KSP_1.1.3_dev\KSP_x64_Data\Managed\UnityEngine.UI.dll</HintPath>
     </Reference>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj">
-      <Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project>
-      <Name>ToadicusTools</Name>
-    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <None Include="GameData\AntennaRange\AntennaRange.cfg" />

file:b/AntennaRange.sln (new)
--- /dev/null
+++ b/AntennaRange.sln
@@ -1,1 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AntennaRange", "AntennaRange.csproj", "{B36F2C11-962E-4A75-9F41-61AD56D11493}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug_linux|Any CPU = Debug_linux|Any CPU
+		Debug_win|Any CPU = Debug_win|Any CPU
+		Release_linux|Any CPU = Release_linux|Any CPU
+		Release_win|Any CPU = Release_win|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Debug_linux|Any CPU.ActiveCfg = Debug_linux|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Debug_linux|Any CPU.Build.0 = Debug_linux|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Debug_win|Any CPU.ActiveCfg = Debug_win|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Debug_win|Any CPU.Build.0 = Debug_win|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Release_linux|Any CPU.ActiveCfg = Release_linux|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Release_linux|Any CPU.Build.0 = Release_linux|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Release_win|Any CPU.ActiveCfg = Release_win|Any CPU
+		{B36F2C11-962E-4A75-9F41-61AD56D11493}.Release_win|Any CPU.Build.0 = Release_win|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
 

--- a/AntennaRelay.cs
+++ b/AntennaRelay.cs
@@ -489,9 +489,15 @@
 
 				// Find the distance from here to the vessel...
 				log.Append("\n\tgetting cost to potential vessel");
-				potentialRelayRate = potentialBestRelay.CurrentNetworkLinkCost + this.GetPotentialLinkCost(potentialBestRelay);
-
-				log.AppendFormat("\n\tpotentialRelayRate = {0} ({1} + {2})", potentialRelayRate, potentialBestRelay.CurrentNetworkLinkCost, this.GetPotentialLinkCost(potentialBestRelay));
+				potentialRelayRate = potentialBestRelay.CurrentNetworkLinkCost +
+					this.GetPotentialLinkCost(potentialBestRelay);
+
+				log.AppendFormat(
+					"\n\tpotentialRelayRate = {0} ({1} + {2})",
+					potentialRelayRate,
+					potentialBestRelay.CurrentNetworkLinkCost,
+					this.GetPotentialLinkCost(potentialBestRelay)
+				);
 
 				#if BENCH
 				startLOSVesselTicks = performanceTimer.ElapsedTicks;
@@ -528,7 +534,7 @@
 						potentialBestRelay.CanTransmit()
 					)
 					{
-						log.Append("\n\t\t...vessel is cheapest and close enough and potentialBestRelay can transmit");
+						log.Append("\n\t\t...vessel is cheapest and in range and potentialBestRelay can transmit");
 						log.AppendFormat("\n\t\t...{0} found new best occluded relay {1}", this, potentialBestRelay);
 
 						this.bestOccludedRelay = potentialBestRelay;
@@ -727,7 +733,7 @@
 						// Since cheapestRelayRate is infinity if there are no nearby relays, this is safe.
 						if (cheapestRelayRate < cheapestOccludedRelayRate)
 						{
-							log.AppendFormat("\n\t\t\t\t...but the nearest relay is cheaper ({0} < {1}), so picking it.",
+							log.AppendFormat("\n\t\t\t\t...but the cheapest relay is cheaper ({0} < {1}), so picking it.",
 								cheapestRelayRate, cheapestOccludedRelayRate);
 							
 							this.targetRelay = this.nearestRelay;
@@ -851,7 +857,7 @@
 							// Since cheapestRelayRate is infinity if there are no nearby relays, this is safe.
 							if (cheapestRelayRate < cheapestOccludedRelayRate)
 							{
-								log.AppendFormat("\n\t\t\t\t...but the nearest relay is cheaper ({0} < {1}), so picking it.",
+								log.AppendFormat("\n\t\t\t\t...but the cheapest relay is cheaper ({0} < {1}), so picking it.",
 									cheapestRelayRate, cheapestOccludedRelayRate);
 								
 								this.targetRelay = this.nearestRelay;
@@ -860,7 +866,7 @@
 							// Otherwise, target the best occluded relay.
 							else
 							{
-								log.AppendFormat("\n\t\t\t\t...and cheaper than the nearest relay ({0} >= {1}), so picking it.",
+								log.AppendFormat("\n\t\t\t\t...and cheaper than the cheapest relay ({0} >= {1}), so picking it.",
 									cheapestRelayRate, cheapestOccludedRelayRate);
 								
 								this.targetRelay = bestOccludedRelay;

--- a/ModuleLimitedDataTransmitter.cs
+++ b/ModuleLimitedDataTransmitter.cs
@@ -52,18 +52,12 @@
 		: ModuleDataTransmitter, IScienceDataTransmitter, IAntennaRelay, IModuleInfo
 	{
 		private const string tooltipSkinName = "PartTooltipSkin";
-		private static GUISkin partTooltipSkin;
-		private static GUIStyle partTooltipBodyStyle;
-		private static GUIStyle partTooltipHeaderStyle;
 
 		// Every antenna is a relay.
 		private AntennaRelay relay;
 
 		// Sometimes we will need to communicate errors; this is how we do it.
 		private ScreenMessage ErrorMsg;
-
-		// Used in module info panes for part tooltips in the editor and R&D
-		private GUIContent moduleInfoContent;
 
 		/// <summary>
 		/// When additive ranges are enabled, the distance from Kerbin at which the antenna will perform exactly as
@@ -479,16 +473,13 @@
 			this.packetThrottle = 100f;
 		}
 
+		#if DEBUG
 		/// <summary>
 		/// PartModule OnAwake override; runs at Unity Awake.
 		/// </summary>
 		public override void OnAwake()
 		{
 			base.OnAwake();
-
-			this.BaseLinkCost = new RelayDataCost(base.packetSize, base.packetResourceCost);
-
-			this.moduleInfoContent = new GUIContent();
 
 			this.LogDebug("{0} loaded:\n" +
 				"packetSize: {1}\n" +
@@ -504,6 +495,7 @@
 				this.maxDataFactor
 			);
 		}
+		#endif
 
 		/// <summary>
 		/// PartModule OnStart override; runs at Unity Start.
@@ -511,9 +503,10 @@
 		/// <param name="state">State.</param>
 		public override void OnStart (StartState state)
 		{
+			this.BaseLinkCost = new RelayDataCost(base.packetResourceCost, base.packetSize);
+			this.RecalculateMaxRange();
+
 			base.OnStart (state);
-
-			this.RecalculateMaxRange();
 
 			if (state >= StartState.PreLaunch)
 			{
@@ -541,6 +534,7 @@
 
 			base.OnLoad (node);
 
+			this.BaseLinkCost = new RelayDataCost(base.packetResourceCost, base.packetSize);
 			this.RecalculateMaxRange();
 		}
 
@@ -564,6 +558,9 @@
 		// HACK: Currently hacks around Squad's extraneous layout box, see KSPModders issue #5118
 		private void drawTooltipWidget(Rect rect)
 		{
+			/*
+			 * Removed all this because Squad doesn't even call it anymore.
+			 *
 			this.moduleInfoContent.text = this.GetInfo();
 
 			if (partTooltipSkin == null)
@@ -605,7 +602,7 @@
 			GUILayout.Space(height - orgHeight
 				- partTooltipBodyStyle.padding.bottom - partTooltipBodyStyle.padding.top
 				- 2f * (partTooltipBodyStyle.margin.bottom + partTooltipBodyStyle.margin.top)
-			);
+			);*/
 		}
 
 		/// <summary>
@@ -623,16 +620,12 @@
 		{
 			using (PooledStringBuilder sb = PooledStringBuilder.Get())
 			{
-				string text;
-
-				sb.Append(base.GetInfo());
-
 				if (ARConfiguration.UseAdditiveRanges)
 				{
-					sb.AppendFormat("Nominal Range to Kerbin: {0:S3}m\n",
+					sb.AppendFormat("<b>Nominal Range to Kerbin: </b>{0:S3}m\n",
 						Math.Sqrt(this.nominalTransmitDistance * ARConfiguration.KerbinNominalRange)
 					);
-					sb.AppendFormat("Maximum Range to Kerbin: {0:S3}m",
+					sb.AppendFormat("<b>Maximum Range to Kerbin: </b>{0:S3}m\n",
 						Math.Sqrt(
 							this.nominalTransmitDistance * Math.Sqrt(this.maxPowerFactor) *
 							ARConfiguration.KerbinRelayRange
@@ -641,13 +634,69 @@
 				}
 				else
 				{
-					sb.AppendFormat("Nominal Range: {0:S3}m\n", this.nominalTransmitDistance);
-					sb.AppendFormat("Maximum Range: {0:S3}m", this.maxTransmitDistance);
-				}
-
-				text = sb.ToString();
-
-				return text;
+					sb.AppendFormat("<b>Nominal Range: </b>{0:S3}m\n", this.nominalTransmitDistance);
+					sb.AppendFormat("<b>Maximum Range: </b>{0:S3}m\n", this.maxTransmitDistance);
+				}
+
+				sb.AppendLine();
+
+				sb.AppendFormat("<b>Nominal Packet Size: </b>{0:S2}iT\n", this.BaseLinkCost.PacketSize * 1000000f);
+				sb.AppendFormat(
+					"<b>Nominal Data Rate: </b>{0:S2}iT/sec\n",
+					this.BaseLinkCost.PacketSize / this.packetInterval * 1000000f
+				);
+
+				sb.AppendLine();
+
+				sb.AppendFormat("<b>Within Nominal Range...\n...Maximum Speedup:</b> {0:P0}\n", this.maxDataFactor);
+
+				if (ARConfiguration.FixedPowerCost)
+				{
+					sb.AppendLine();
+
+					sb.AppendFormat(
+						"<b>Outside Nominal Range...\n...Maximum Slowdown:</b> {0:P1}\n",
+						1f / this.maxPowerFactor
+					);
+
+					sb.AppendLine();
+
+					sb.AppendFormat(
+						"<b>Packet Cost:</b> {0:0.0#} {1}\n",
+						this.BaseLinkCost.PacketResourceCost,
+						this.requiredResource == "ElectricCharge" ? "EC" : this.requiredResource
+					);
+					sb.AppendFormat(
+						"<b>Power Drain:</b> {0:0.0#} {1}/s\n",
+						this.BaseLinkCost.PacketResourceCost / this.packetInterval,
+						this.requiredResource == "ElectricCharge" ? "EC" : this.requiredResource
+					);
+				}
+				else
+				{
+					sb.AppendLine();
+
+					sb.AppendFormat(
+						"<b>Nominal Packet Cost:</b> {0:0.0#} {1}\n",
+						this.BaseLinkCost.PacketResourceCost,
+						this.requiredResource == "ElectricCharge" ? "EC" : this.requiredResource
+					);
+					sb.AppendFormat(
+						"<b>Nominal Power Drain:</b> {0:0.0#} {1}/s\n",
+						this.BaseLinkCost.PacketResourceCost / this.packetInterval,
+						this.requiredResource == "ElectricCharge" ? "EC" : this.requiredResource
+					);
+
+					sb.AppendLine();
+
+					sb.AppendFormat(
+						"<b>Outside Nominal Range...\n...Maximum Power Drain:</b> {0:0.0#} {1}/s\n",
+						this.BaseLinkCost.PacketResourceCost / this.packetInterval * this.maxPowerFactor,
+						this.requiredResource == "ElectricCharge" ? "EC" : this.requiredResource
+					);
+				}
+
+				return sb.ToString();
 			}
 		}
 

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

--- a/RelayDatabase.cs
+++ b/RelayDatabase.cs
@@ -419,6 +419,8 @@
 			GameEvents.onVesselWasModified.Add(this.onVesselEvent);
 			GameEvents.onVesselChange.Add(this.onVesselEvent);
 			GameEvents.onVesselDestroy.Add(this.onVesselEvent);
+			GameEvents.onVesselGoOnRails.Add(this.onVesselEvent);
+			GameEvents.onVesselGoOffRails.Add(this.onVesselEvent);
 			GameEvents.onGameSceneLoadRequested.Add(this.onSceneChange);
 			GameEvents.onPartCouple.Add(this.onFromPartToPartEvent);
 			GameEvents.onPartUndock.Add(this.onPartEvent);
@@ -431,6 +433,8 @@
 			GameEvents.onVesselWasModified.Remove(this.onVesselEvent);
 			GameEvents.onVesselChange.Remove(this.onVesselEvent);
 			GameEvents.onVesselDestroy.Remove(this.onVesselEvent);
+			GameEvents.onVesselGoOnRails.Remove(this.onVesselEvent);
+			GameEvents.onVesselGoOffRails.Add(this.onVesselEvent);
 			GameEvents.onGameSceneLoadRequested.Remove(this.onSceneChange);
 			GameEvents.onPartCouple.Remove(this.onFromPartToPartEvent);
 			GameEvents.onPartUndock.Remove(this.onPartEvent);