Removed Linq
Removed Linq

--- a/ARConfiguration.cs
+++ b/ARConfiguration.cs
@@ -10,38 +10,59 @@
 
 namespace AntennaRange
 {
+	/// <summary>
+	/// A <see cref="UnityEngine.MonoBehaviour"/> responsible for managing configuration items for AntennaRange.
+	/// </summary>
 	[KSPAddon(KSPAddon.Startup.SpaceCentre, false)]
 	public class ARConfiguration : MonoBehaviour
 	{
+		/// <summary>
+		/// Indicates whether connections require line of sight.
+		/// </summary>
 		public static bool RequireLineOfSight
 		{
 			get;
 			private set;
 		}
 
+		/// <summary>
+		/// A "fudge factor" ratio that pretends planets and moons are slightly smaller than reality to make
+		/// building communication constellations easier.
+		/// </summary>
 		public static double RadiusRatio
 		{
 			get;
 			private set;
 		}
 
+		/// <summary>
+		/// Indicates whether unmanned vessels require a connection for control.
+		/// </summary>
 		public static bool RequireConnectionForControl
 		{
 			get;
 			private set;
 		}
 
+		/// <summary>
+		/// If true, relays will fix their power cost when above nominal range, decreasing data rate instead.
+		/// </summary>
 		public static bool FixedPowerCost
 		{
 			get;
 			private set;
 		}
 
+		/// <summary>
+		/// Indicates whether this AntennaRange will draw pretty lines in map view.
+		/// </summary>
 		public static bool PrettyLines
 		{
 			get;
 			private set;
 		}
+
+#pragma warning disable 1591
 
 		private bool showConfigWindow;
 		private Rect configWindowPos;

--- a/ARFlightController.cs
+++ b/ARFlightController.cs
@@ -25,6 +25,8 @@
 // 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.
+
+#pragma warning disable 1591
 
 using KSP;
 using System;

--- a/ARMapRenderer.cs
+++ b/ARMapRenderer.cs
@@ -26,6 +26,8 @@
 // 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.
 
+#pragma warning disable 1591
+
 using KSP;
 using System;
 using System.Collections.Generic;
@@ -39,7 +41,12 @@
 		#region Fields
 		private Dictionary<Guid, LineRenderer> vesselLineRenderers;
 		private Dictionary<Guid, bool> vesselFrameCache;
+
+		#pragma warning disable 414
 		private bool dumpBool;
+		private Color lastColor;
+		private Color thisColor;
+		#pragma warning restore 414
 		#endregion
 
 		#region Properties
@@ -118,8 +125,10 @@
 				{
 					log.AppendLine("FlightGlobals ready and Vessels list not null.");
 
-					foreach (Vessel vessel in FlightGlobals.Vessels)
-					{
+					for (int i = 0; i < FlightGlobals.Vessels.Count; i++)
+					{
+						Vessel vessel = FlightGlobals.Vessels[i];
+
 						if (vessel == null)
 						{
 							log.AppendFormat("Skipping vessel {0} altogether because it is null.\n");
@@ -174,10 +183,10 @@
 		}
 		#endregion
 
+		#region Utility
 		private void SetRelayVertices(IAntennaRelay relay)
 		{
-			Color lastColor = default(Color);
-			Color thisColor;
+			lastColor = default(Color);
 
 			LineRenderer renderer = this[relay.vessel.id];
 			Vector3d start = ScaledSpace.LocalToScaledSpace(relay.vessel.GetWorldPos3D());
@@ -262,12 +271,16 @@
 			}
 		}
 
-		public void Cleanup()
+		private void Cleanup()
 		{
 			if (this.vesselLineRenderers != null && this.vesselLineRenderers.Count > 0)
 			{
-				foreach (LineRenderer lineRenderer in this.vesselLineRenderers.Values)
-				{
+				IEnumerator<LineRenderer> enumerator = this.vesselLineRenderers.Values.GetEnumerator();
+				LineRenderer lineRenderer;
+
+				while (enumerator.MoveNext())
+				{
+					lineRenderer = enumerator.Current;
 					lineRenderer.enabled = false;
 					GameObject.Destroy(lineRenderer.gameObject);
 				}
@@ -279,7 +292,7 @@
 				this.vesselFrameCache.Clear();
 			}
 		}
+		#endregion
 	}
 }
 
-

--- a/AntennaRange.csproj
+++ b/AntennaRange.csproj
@@ -40,6 +40,7 @@
         <Command type="AfterBuild" command="xcopy /y ${TargetFile} ${ProjectDir}\GameData\AntennaRange\" />
       </CustomCommands>
     </CustomCommands>
+    <DocumentationFile>bin\Release\AntennaRange.xml</DocumentationFile>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>

--- a/AntennaRelay.cs
+++ b/AntennaRelay.cs
@@ -28,7 +28,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using ToadicusTools;
 
 namespace AntennaRange
@@ -182,9 +181,6 @@
 				return;
 			}
 
-			Tools.PostDebugMessage("{0}: Updating at {1}ms, {2}ms since last search.",
-				this.ToString(), searchTime, timeSinceLast);
-
 			this.lastSearch = searchTime;
 
 			// Skip vessels that have already been checked for a nearest relay this pass.
@@ -193,15 +189,14 @@
 				return;
 			}
 
-			if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-			{
-				Tools.PostDebugMessage(string.Format(
-					"{0}: finding nearest relay for {1}",
-					this.GetType().Name,
-					this.ToString()
-				));
-			}
-
+			Tools.DebugLogger log;
+			#if DEBUG
+			log = Tools.DebugLogger.New(this);
+			#endif
+
+			log.AppendFormat("{0}: Target search started at {1} ms ({2} ms since last search).",
+				this.ToString(), searchTime, timeSinceLast);
+			
 			// Set this vessel as checked, so that we don't check it again.
 			RelayDatabase.Instance.CheckedVesselsTable[vessel.id] = true;
 
@@ -210,6 +205,9 @@
 			this.bestOccludedRelay = null;
 			this.targetRelay = null;
 			this.nearestRelay = null;
+
+			// Default to KerbinDirect = true in case something in here doesn't work right.
+			this.KerbinDirect = true;
 
 			CelestialBody bodyOccludingBestOccludedRelay = null;
 
@@ -223,8 +221,11 @@
 			 * and that can transmit.  Once we find a suitable candidate, assign it to nearestRelay for comparison
 			 * against future finds.
 			 * */
-			foreach (Vessel potentialVessel in FlightGlobals.Vessels)
-			{
+			Vessel potentialVessel;
+			IList<IAntennaRelay> vesselRelays;
+			for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++)
+			{
+				potentialVessel = FlightGlobals.Vessels[vIdx];
 				// Skip vessels of the wrong type.
 				switch (potentialVessel.vesselType)
 				{
@@ -246,6 +247,7 @@
 
 				// Find the distance from here to the vessel...
 				double potentialSqrDistance = this.sqrDistanceTo(potentialVessel);
+				vesselRelays = potentialVessel.GetAntennaRelays();
 
 				CelestialBody fob = null;
 
@@ -257,58 +259,45 @@
 				{
 					this.firstOccludingBody = fob;
 
-					if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-					{
-						Tools.PostDebugMessage("{6}: Vessel {0} discarded because we do not have line of sight." +
-							"\npotentialSqrDistance: {1}, bestOccludedSqrDistance: {2}, maxTransmitSqrDistance: {3}" +
-							"\npotentialSqrDistance < bestOccludedSqrDistance: {4}" +
-							"\npotentialSqrDistance < (this.maxTransmitDistance * this.maxTransmitDistance): {5}",
-							potentialVessel.vesselName,
-							potentialSqrDistance, bestOccludedSqrDistance, this.maxTransmitDistance * this.maxTransmitDistance,
-							potentialSqrDistance < bestOccludedSqrDistance,
-							potentialSqrDistance < (this.maxTransmitDistance * this.maxTransmitDistance),
-							this.ToString()
-						);
-					}
+					log.AppendFormat("\n\t{0}: Vessel {1} not in line of sight.",
+						this.ToString(), potentialVessel.vesselName);
 
 					if (
 						(potentialSqrDistance < bestOccludedSqrDistance) &&
 						(potentialSqrDistance < maxTransmitSqrDistance)
 					)
 					{
-						if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-						{
-							Tools.PostDebugMessage("{0}: Checking {1} relays on {2}.",
-								this.ToString(),
-								potentialVessel.GetAntennaRelays().Count(),
-								potentialVessel
+						
+						log.AppendFormat("\n\t\t{0}: Checking {1} relays on occluded vessel {2}.",
+							this.ToString(),
+							potentialVessel.GetAntennaRelays().Count,
+							potentialVessel
+						);
+
+						IAntennaRelay occludedRelay;
+						for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
+						{
+							occludedRelay = vesselRelays[rIdx];
+
+							log.AppendFormat(
+								"\n\t\t{0}: Checking candidate for bestOccludedRelay: {1}" +
+								"\n\t\tCanTransmit: {2}",
+								this.ToString(), occludedRelay, occludedRelay.CanTransmit()
 							);
-						}
-
-						foreach (IAntennaRelay occludedRelay in potentialVessel.GetAntennaRelays())
-						{
-							if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-							{
-								Tools.PostDebugMessage(this.ToString() +  " Checking candidate for bestOccludedRelay: {0}" +
-									"\n\tCanTransmit: {1}", occludedRelay, occludedRelay.CanTransmit());
-							}
-
+							
 							if (occludedRelay.CanTransmit())
 							{
 								this.bestOccludedRelay = occludedRelay;
 								bodyOccludingBestOccludedRelay = fob;
 								bestOccludedSqrDistance = potentialSqrDistance;
 
-								if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-								{
-									Tools.PostDebugMessage(this.ToString() + " Found new bestOccludedRelay: {0}" +
-										"\nfirstOccludingBody: {1}" +
-										"\nbestOccludedSqrDistance: {2}",
-										occludedRelay,
-										fob,
-										potentialSqrDistance
-									);
-								}
+								log.AppendFormat("\n\t{0}: Found new bestOccludedRelay: {1}" +
+									" (blocked by {2}; distance: {3} m)",
+									this.ToString(),
+									occludedRelay.ToString(),
+									fob,
+									potentialSqrDistance
+								);
 								break;
 							}
 						}
@@ -322,31 +311,32 @@
 				 * */
 				if (potentialSqrDistance > nearestRelaySqrDistance)
 				{
-					if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-					{
-						Tools.PostDebugMessage("{0}: Vessel {1} discarded because it is out of range, or farther than another relay.",
-							this.ToString(),
-							potentialVessel.vesselName
-						);
-					}
+					
+					log.AppendFormat("\n\t{0}: Vessel {1} discarded because it is farther than another the nearest relay.",
+						this.ToString(),
+						potentialVessel.vesselName
+					);
 					continue;
 				}
 
-				nearestRelaySqrDistance = potentialSqrDistance;
-
-				foreach (IAntennaRelay potentialRelay in potentialVessel.GetAntennaRelays())
-				{
+				IAntennaRelay potentialRelay;
+				for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
+				{
+					potentialRelay = vesselRelays[rIdx];
+
 					if (potentialRelay.CanTransmit() && potentialRelay.targetRelay != this)
 					{
+						// @TODO: Moved this here from outside the loop; why was it there?
+						nearestRelaySqrDistance = potentialSqrDistance;
 						this.nearestRelay = potentialRelay;
 
 						if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
 						{
-							Tools.PostDebugMessage(string.Format("{0}: found new best relay {1} ({2})",
+							log.AppendFormat("\n\t{0}: found new nearest relay {1} ({2}m)",
 								this.ToString(),
 								this.nearestRelay.ToString(),
-								this.nearestRelay.vessel.id
-							));
+								Math.Sqrt(nearestRelaySqrDistance)
+							);
 						}
 						break;
 					}
@@ -358,9 +348,7 @@
 			double kerbinSqrDistance = this.vessel.DistanceTo(Kerbin) - Kerbin.Radius;
 			kerbinSqrDistance *= kerbinSqrDistance;
 
-			Tools.DebugLogger log = Tools.DebugLogger.New(this);
-
-			log.AppendFormat("{0} ({1}): Search done, figuring status.", this.ToString(), this.GetType().Name);
+			log.AppendFormat("\n{0} ({1}): Search done, figuring status.", this.ToString(), this.GetType().Name);
 
 			// If we don't have LOS to Kerbin, focus on relays
 			if (!this.vessel.hasLineOfSightTo(Kerbin, out bodyOccludingKerbin, ARConfiguration.RadiusRatio))
@@ -371,7 +359,7 @@
 				// Therefore, this will only be true if a valid relay is in range.
 				if (nearestRelaySqrDistance <= maxTransmitSqrDistance)
 				{
-					log.AppendFormat("\n\tCan transmit to nearby relay {0} ({1} <= {2}).",
+					log.AppendFormat("\n\t\tCan transmit to nearby relay {0} ({1} <= {2}).",
 						this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
 							nearestRelaySqrDistance, maxTransmitSqrDistance);
 
@@ -382,7 +370,7 @@
 				// If this isn't true, we can't transmit, but pick a second best of bestOccludedRelay and Kerbin anyway
 				else
 				{
-					log.AppendFormat("\n\tCan't transmit to nearby relay {0} ({1} > {2}).",
+					log.AppendFormat("\n\t\tCan't transmit to nearby relay {0} ({1} > {2}).",
 						this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
 							nearestRelaySqrDistance, maxTransmitSqrDistance);
 
@@ -392,18 +380,27 @@
 					// Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe
 					if (bestOccludedSqrDistance < kerbinSqrDistance)
 					{
+						log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})",
+							bestOccludedRelay, kerbinSqrDistance);
+						
 						this.KerbinDirect = false;
 
 						// If the nearest relay is closer than the best occluded relay, pick it.
 						// Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
 						if (nearestRelaySqrDistance < bestOccludedSqrDistance)
 						{
+							log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
+								nearestRelaySqrDistance, bestOccludedSqrDistance);
+							
 							this.targetRelay = nearestRelay;
 							this.firstOccludingBody = null;
 						}
 						// Otherwise, target the best occluded relay.
 						else
 						{
+							log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
+								nearestRelaySqrDistance, bestOccludedSqrDistance);
+							
 							this.targetRelay = bestOccludedRelay;
 							this.firstOccludingBody = bodyOccludingBestOccludedRelay;
 						}
@@ -412,18 +409,27 @@
 					// Since we have LOS, blank the first occluding body.
 					else
 					{
+						log.AppendFormat("\n\t\t\tKerbin is closer than the best occluded relay ({0} >= {1})",
+							bestOccludedRelay, kerbinSqrDistance);
+						
 						this.firstOccludingBody = null;
 
 						// If the nearest relay is closer than Kerbin, pick it.
 						// Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
 						if (nearestRelaySqrDistance < kerbinSqrDistance)
 						{
+							log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
+								nearestRelaySqrDistance, kerbinSqrDistance);
+							
 							this.KerbinDirect = false;
 							this.targetRelay = nearestRelay;
 						}
 						// Otherwise, pick Kerbin.
 						else
 						{
+							log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
+								nearestRelaySqrDistance, kerbinSqrDistance);
+							
 							this.KerbinDirect = true;
 							this.targetRelay = null;
 						}
@@ -438,7 +444,7 @@
 				// If the nearest relay is closer than Kerbin and in range, transmit to it.
 				if (nearestRelaySqrDistance <= maxTransmitSqrDistance)
 				{
-					log.AppendFormat("\n\tCan transmit to nearby relay {0} ({1} <= {2}).",
+					log.AppendFormat("\n\t\tCan transmit to nearby relay {0} ({1} <= {2}).",
 						this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
 							nearestRelaySqrDistance, maxTransmitSqrDistance);
 
@@ -447,7 +453,7 @@
 					// If the nearestRelay is closer than Kerbin, use it.
 					if (nearestRelaySqrDistance < kerbinSqrDistance)
 					{
-						log.AppendFormat("\n\tPicking relay {0} over Kerbin ({1} < {2}).",
+						log.AppendFormat("\n\t\t\tPicking relay {0} over Kerbin ({1} < {2}).",
 							this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
 							nearestRelaySqrDistance, kerbinSqrDistance);
 
@@ -457,7 +463,7 @@
 					// Otherwise, Kerbin is closer, so use it.
 					else
 					{
-						log.AppendFormat("\n\tBut picking Kerbin over nearby relay {0} ({1} >= {2}).",
+						log.AppendFormat("\n\t\t\tBut picking Kerbin over nearby relay {0} ({1} >= {2}).",
 							this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
 								nearestRelaySqrDistance, kerbinSqrDistance);
 
@@ -468,14 +474,14 @@
 				// If the nearest relay is out of range, we still need to check on Kerbin.
 				else
 				{
-					log.AppendFormat("\n\tCan't transmit to nearby relay {0} ({1} > {2}).",
+					log.AppendFormat("\n\t\tCan't transmit to nearby relay {0} ({1} > {2}).",
 						this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
 							nearestRelaySqrDistance, maxTransmitSqrDistance);
 
 					// If Kerbin is in range, use it.
 					if (kerbinSqrDistance <= maxTransmitSqrDistance)
 					{
-						log.AppendFormat("\n\tCan transmit to Kerbin ({0} <= {1}).",
+						log.AppendFormat("\n\t\t\tCan transmit to Kerbin ({0} <= {1}).",
 							kerbinSqrDistance, maxTransmitSqrDistance);
 
 						this.canTransmit = true;
@@ -486,7 +492,7 @@
 					// Kerbin and bestOccludedRelay
 					else
 					{
-						log.AppendFormat("\n\tCan't transmit to Kerbin ({0} > {1}).",
+						log.AppendFormat("\n\t\t\tCan't transmit to Kerbin ({0} > {1}).",
 							kerbinSqrDistance, maxTransmitSqrDistance);
 
 						this.canTransmit = false;
@@ -495,18 +501,27 @@
 						// Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe
 						if (bestOccludedSqrDistance < kerbinSqrDistance)
 						{
+							log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})",
+								bestOccludedRelay, kerbinSqrDistance);
+							
 							this.KerbinDirect = false;
 
 							// If the nearest relay is closer than the best occluded relay, pick it.
 							// Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
 							if (nearestRelaySqrDistance < bestOccludedSqrDistance)
 							{
+								log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
+									nearestRelaySqrDistance, bestOccludedSqrDistance);
+								
 								this.targetRelay = nearestRelay;
 								this.firstOccludingBody = null;
 							}
 							// Otherwise, target the best occluded relay.
 							else
 							{
+								log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
+									nearestRelaySqrDistance, bestOccludedSqrDistance);
+								
 								this.targetRelay = bestOccludedRelay;
 								this.firstOccludingBody = bodyOccludingBestOccludedRelay;
 							}
@@ -515,18 +530,27 @@
 						// Since we have LOS, blank the first occluding body.
 						else
 						{
+							log.AppendFormat("\n\t\t\tKerbin is closer than the best occluded relay ({0} >= {1})",
+								bestOccludedRelay, kerbinSqrDistance);
+							
 							this.firstOccludingBody = null;
 
 							// If the nearest relay is closer than Kerbin, pick it.
 							// Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
 							if (nearestRelaySqrDistance < kerbinSqrDistance)
 							{
+								log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
+									nearestRelaySqrDistance, kerbinSqrDistance);
+								
 								this.KerbinDirect = false;
 								this.targetRelay = nearestRelay;
 							}
 							// Otherwise, pick Kerbin.
 							else
 							{
+								log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
+									nearestRelaySqrDistance, kerbinSqrDistance);
+								
 								this.KerbinDirect = true;
 								this.targetRelay = null;
 							}
@@ -535,9 +559,12 @@
 				}
 			}
 
+			log.AppendFormat("{0}: Target search completed at {1} ms ({2} ms elapsed).",
+				this.ToString(), searchTimer.ElapsedMilliseconds, searchTimer.ElapsedMilliseconds - searchTime);;
+
 			log.AppendFormat("\n{0}: Status determination complete.", this.ToString());
 
-			log.Print();
+			log.Print(false);
 
 			// Now that we're done with our recursive CanTransmit checks, flag this relay as not checked so it can be
 			// used next time.

--- a/ModuleLimitedDataTransmitter.cs
+++ b/ModuleLimitedDataTransmitter.cs
@@ -29,7 +29,6 @@
 using KSP;
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Text;
 using ToadicusTools;
 using UnityEngine;
@@ -460,8 +459,12 @@
 
 				var logger = Tools.DebugLogger.New(this);
 
-				foreach (ModuleScienceContainer	scienceContainer in this.vessel.getModulesOfType<ModuleScienceContainer>())
-				{
+				IList<ModuleScienceContainer> vesselContainers = this.vessel.getModulesOfType<ModuleScienceContainer>();
+				ModuleScienceContainer scienceContainer;
+				for (int cIdx = 0; cIdx < vesselContainers.Count; cIdx++)
+				{
+					scienceContainer = vesselContainers[cIdx];
+
 					logger.AppendFormat("Checking ModuleScienceContainer in {0}\n",
 						scienceContainer.part.partInfo.title);
 
@@ -476,8 +479,10 @@
 
 					List<ScienceData> dataStored = new List<ScienceData>();
 
-					foreach (ScienceData data in dataQueue)
+					ScienceData data;
+					for (int dIdx = 0; dIdx < dataQueue.Count; dIdx++)
 					{
+						data = dataQueue[dIdx];
 						if (!scienceContainer.allowRepeatedSubjects && scienceContainer.HasData(data))
 						{
 							logger.Append("\tAlready contains subject and repeated subjects not allowed, skipping.\n");
@@ -515,8 +520,10 @@
 					msg.AppendFormat("]: {0} data items could not be saved: no space available in data containers.\n");
 					msg.Append("Data to be discarded:\n");
 
-					foreach (ScienceData data in dataQueue)
+					ScienceData data;
+					for (int dIdx = 0; dIdx < dataQueue.Count; dIdx++)
 					{
+						data = dataQueue[dIdx];
 						msg.AppendFormat("\t{0}\n", data.title);
 					}
 
@@ -807,8 +814,10 @@
 
 			sb.Append("Dumping FlightGlobals.Vessels:");
 
-			foreach (Vessel vessel in FlightGlobals.Vessels)
-			{
+			Vessel vessel;
+			for (int i = 0; i < FlightGlobals.Vessels.Count; i++)
+			{
+				vessel = FlightGlobals.Vessels[i];
 				sb.AppendFormat("\n'{0} ({1})'", vessel.vesselName, vessel.id);
 			}
 

--- a/ProtoAntennaRelay.cs
+++ b/ProtoAntennaRelay.cs
@@ -28,15 +28,14 @@
 
 using KSP;
 using System;
-using System.Linq;
 using ToadicusTools;
 
 namespace AntennaRange
 {
-	/*
-	 * Wrapper class for ProtoPartModuleSnapshot extending AntennaRelay and implementing IAntennaRelay.
-	 * This is used for finding relays in unloaded Vessels.
-	 * */
+	/// <summary>
+	/// Wrapper class for ProtoPartModuleSnapshot extending AntennaRelay and implementing IAntennaRelay.
+	/// This is used for finding relays in unloaded Vessels.
+	/// </summary>
 	public class ProtoAntennaRelay : AntennaRelay, IAntennaRelay
 	{
 		// Stores the prototype part so we can make sure we haven't exploded or so.
@@ -139,21 +138,14 @@
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="AntennaRange.ProtoAntennaRelay"/> class.
+		/// Initializes a new instance of the <see cref="AntennaRange.AntennaRelay"/> class.
 		/// </summary>
-		/// <param name="ms">The ProtoPartModuleSnapshot to wrap</param>
-		/// <param name="vessel">The parent Vessel</param>
+		/// <param name="prefabRelay">The module reference underlying this AntennaRelay,
+		/// as an <see cref="AntennaRange.IAntennaRelay"/></param>
+		/// <param name="pps">The prototype partreference on which the module resides.</param>
 		public ProtoAntennaRelay(IAntennaRelay prefabRelay, ProtoPartSnapshot pps) : base(prefabRelay)
 		{
 			this.protoPart = pps;
-		}
-
-		~ProtoAntennaRelay()
-		{
-			Tools.PostDebugMessage(string.Format(
-				"{0}: destroyed",
-				this.ToString()
-			));
 		}
 	}
 }

--- a/RelayDatabase.cs
+++ b/RelayDatabase.cs
@@ -25,6 +25,8 @@
 // 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.
+
+#pragma warning disable 1591
 
 using KSP;
 using System;
@@ -64,7 +66,7 @@
 		 * Fields
 		 * */
 		// Vessel.id-keyed hash table of Part.GetHashCode()-keyed tables of relay objects.
-		protected Dictionary<Guid, Dictionary<int, IAntennaRelay>> relayDatabase;
+		protected Dictionary<Guid, List<IAntennaRelay>> relayDatabase;
 
 		// Vessel.id-keyed hash table of part counts, used for caching
 		protected Dictionary<Guid, int> vesselPartCountTable;
@@ -79,7 +81,7 @@
 		 * Properties
 		 * */
 		// Gets the Part-hashed table of relays in a given vessel
-		public Dictionary<int, IAntennaRelay> this [Vessel vessel]
+		public IList<IAntennaRelay> this [Vessel vessel]
 		{
 			get
 			{
@@ -104,7 +106,7 @@
 				}
 
 				// Return the Part-hashed table of relays for this vessel
-				return relayDatabase[vessel.id];
+				return relayDatabase[vessel.id].AsReadOnly();
 			}
 		}
 
@@ -133,7 +135,7 @@
 			else
 			{
 				// Build an empty table...
-				this.relayDatabase[vessel.id] = new Dictionary<int, IAntennaRelay>();
+				this.relayDatabase[vessel.id] = new List<IAntennaRelay>();
 
 				// Update the empty index
 				this.UpdateVessel(vessel);
@@ -157,7 +159,7 @@
 				));
 			}
 
-			Dictionary<int, IAntennaRelay> vesselTable = this.relayDatabase[vessel.id];
+			List<IAntennaRelay> vesselTable = this.relayDatabase[vessel.id];
 
 			// Actually build and assign the table
 			this.getVesselRelays(vessel, ref vesselTable);
@@ -241,7 +243,7 @@
 		}
 
 		// Produce a Part-hashed table of relays for the given vessel
-		protected void getVesselRelays(Vessel vessel, ref Dictionary<int, IAntennaRelay> relays)
+		protected void getVesselRelays(Vessel vessel, ref List<IAntennaRelay> relays)
 		{
 			// We're going to completely regen this table, so dump the current contents.
 			relays.Clear();
@@ -261,16 +263,22 @@
 				));
 
 				// Loop through the Parts in the Vessel...
-				foreach (Part part in vessel.Parts)
-				{
+				Part part;
+				for (int partIdx = 0; partIdx < vessel.Parts.Count; partIdx++)
+				{
+					part = vessel.Parts[partIdx];
+
 					// ...loop through the PartModules in the Part...
-					foreach (PartModule module in part.Modules)
+					PartModule module;
+					for (int modIdx = 0; modIdx < part.Modules.Count; modIdx++)
 					{
+						module = part.Modules[modIdx];
+
 						// ...if the module is a relay...
 						if (module is IAntennaRelay)
 						{
 							// ...add the module to the table
-							relays.Add(part.GetHashCode(), module as IAntennaRelay);
+							relays.Add(module as IAntennaRelay);
 							// ...neglect relay objects after the first in each part.
 							break;
 						}
@@ -287,8 +295,11 @@
 				));
 
 				// Loop through the ProtoPartModuleSnapshots in the Vessel...
-				foreach (ProtoPartSnapshot pps in vessel.protoVessel.protoPartSnapshots)
-				{
+				ProtoPartSnapshot pps;
+				for (int ppsIdx = 0; ppsIdx < vessel.protoVessel.protoPartSnapshots.Count; ppsIdx++)
+				{
+					pps = vessel.protoVessel.protoPartSnapshots[ppsIdx];
+
 					Tools.PostDebugMessage(string.Format(
 						"{0}: Searching in protopartsnapshot {1}",
 						this.GetType().Name,
@@ -306,8 +317,11 @@
 					));
 
 					// ...loop through the PartModules in the prefab...
-					foreach (PartModule module in partPrefab.Modules)
+					PartModule module;
+					for (int modIdx = 0; modIdx < partPrefab.Modules.Count; modIdx++)
 					{
+						module = partPrefab.Modules[modIdx];
+
 						Tools.PostDebugMessage(string.Format(
 							"{0}: Searching in partmodule {1}",
 							this.GetType().Name,
@@ -324,7 +338,7 @@
 							));
 
 							// ...build a new ProtoAntennaRelay and add it to the table
-							relays.Add(pps.GetHashCode(), new ProtoAntennaRelay(module as IAntennaRelay, pps));
+							relays.Add(new ProtoAntennaRelay(module as IAntennaRelay, pps));
 							// ...neglect relay objects after the first in each part.
 							break;
 						}
@@ -345,7 +359,7 @@
 		protected RelayDatabase()
 		{
 			// Initialize the databases
-			this.relayDatabase = new Dictionary<Guid, Dictionary<int, IAntennaRelay>>();
+			this.relayDatabase = new Dictionary<Guid, List<IAntennaRelay>>();
 			this.vesselPartCountTable = new Dictionary<Guid, int>();
 			this.CheckedVesselsTable = new Dictionary<Guid, bool>();
 
@@ -389,12 +403,17 @@
 
 			sb.Append("Dumping RelayDatabase:");
 
-			foreach (Guid id in this.relayDatabase.Keys)
-			{
-				sb.AppendFormat("\nVessel {0}:", id);
-
-				foreach (IAntennaRelay relay in this.relayDatabase[id].Values)
-				{
+			var dbEnum = this.relayDatabase.GetEnumerator();
+			IList<IAntennaRelay> vesselRelays;
+			while (dbEnum.MoveNext())
+			{
+				sb.AppendFormat("\nVessel {0}:", dbEnum.Current.Key);
+
+				vesselRelays = dbEnum.Current.Value;
+				IAntennaRelay relay;
+				for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
+				{
+					relay = vesselRelays[rIdx];
 					sb.AppendFormat("\n\t{0}", relay.ToString());
 				}
 			}

--- a/RelayExtensions.cs
+++ b/RelayExtensions.cs
@@ -28,14 +28,13 @@
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using ToadicusTools;
 
 namespace AntennaRange
 {
-	/*
-	 * A class of utility extensions for Vessels and Relays to help find a relay path back to Kerbin.
-	 * */
+	/// <summary>
+	/// A class of utility extensions for Vessels and Relays to help find a relay path back to Kerbin.
+	/// </summary>
 	public static class RelayExtensions
 	{
 		/// <summary>
@@ -68,16 +67,31 @@
 			return relayOne.DistanceTo(relayTwo.vessel);
 		}
 
+		/// <summary>
+		/// Returns the square of the distance between this IAntennaRelay and a Vessel
+		/// </summary>
+		/// <param name="relay">This <see cref="IAntennaRelay"/></param>
+		/// <param name="vessel">A <see cref="Vessel"/></param>
 		public static double sqrDistanceTo(this AntennaRelay relay, Vessel vessel)
 		{
 			return relay.vessel.sqrDistanceTo(vessel);
 		}
 
+		/// <summary>
+		/// Returns the square of the distance between this IAntennaRelay and a CelestialBody
+		/// </summary>
+		/// <param name="relay">This <see cref="IAntennaRelay"/></param>
+		/// <param name="body">A <see cref="CelestialBody"/></param>
 		public static double sqrDistanceTo(this AntennaRelay relay, CelestialBody body)
 		{
 			return relay.vessel.sqrDistanceTo(body);
 		}
 
+		/// <summary>
+		/// Returns the square of the distance between this IAntennaRelay and another IAntennaRelay
+		/// </summary>
+		/// <param name="relayOne">This <see cref="IAntennaRelay"/></param>
+		/// <param name="relayTwo">Another <see cref="IAntennaRelay"/></param>
 		public static double sqrDistanceTo(this AntennaRelay relayOne, IAntennaRelay relayTwo)
 		{
 			return relayOne.vessel.sqrDistanceTo(relayTwo.vessel);
@@ -87,9 +101,9 @@
 		/// Returns all of the PartModules or ProtoPartModuleSnapshots implementing IAntennaRelay in this Vessel.
 		/// </summary>
 		/// <param name="vessel">This <see cref="Vessel"/></param>
-		public static IEnumerable<IAntennaRelay> GetAntennaRelays (this Vessel vessel)
-		{
-			return RelayDatabase.Instance[vessel].Values.ToList().AsReadOnly();
+		public static IList<IAntennaRelay> GetAntennaRelays (this Vessel vessel)
+		{
+			return RelayDatabase.Instance[vessel];
 		}
 
 		/// <summary>
@@ -99,8 +113,11 @@
 		/// <param name="vessel"></param>
 		public static bool HasConnectedRelay(this Vessel vessel)
 		{
-			foreach (IAntennaRelay relay in RelayDatabase.Instance[vessel].Values)
-			{
+			IList<IAntennaRelay> vesselRelays = RelayDatabase.Instance[vessel];
+			IAntennaRelay relay;
+			for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
+			{
+				relay = vesselRelays[rIdx];
 				if (relay.CanTransmit())
 				{
 					return true;
@@ -110,12 +127,19 @@
 			return false;
 		}
 
+		/// <summary>
+		/// Gets the <see cref="AntennaRange.ConnectionStatus"/> for this <see cref="Vessel"/>
+		/// </summary>
+		/// <param name="vessel">This <see cref="Vessel"/></param>
 		public static ConnectionStatus GetConnectionStatus(this Vessel vessel)
 		{
 			bool canTransmit = false;
 
-			foreach (IAntennaRelay relay in RelayDatabase.Instance[vessel].Values)
-			{
+			IList<IAntennaRelay> vesselRelays = RelayDatabase.Instance[vessel];
+			IAntennaRelay relay;
+			for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
+			{
+				relay = vesselRelays[rIdx];
 				if (relay.CanTransmit())
 				{
 					canTransmit = true;
@@ -136,14 +160,21 @@
 			}
 		}
 
+		/// <summary>
+		/// Gets the best relay on this Vessel.  The best relay may not be able to transmit.
+		/// </summary>
+		/// <param name="vessel">This <see cref="Vessel"/></param>
 		public static IAntennaRelay GetBestRelay(this Vessel vessel)
 		{
 			IAntennaRelay bestRelay = null;
 			double bestScore = double.PositiveInfinity;
 			double relayScore = double.NaN;
 
-			foreach (IAntennaRelay relay in vessel.GetAntennaRelays())
-			{
+			IList<IAntennaRelay> vesselRelays = RelayDatabase.Instance[vessel];
+			IAntennaRelay relay;
+			for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
+			{
+				relay = vesselRelays[rIdx];
 				relayScore = relay.transmitDistance / relay.maxTransmitDistance;
 
 				if (relayScore < bestScore)
@@ -157,6 +188,10 @@
 		}
 	}
 
+	#pragma warning disable 1591
+	/// <summary>
+	/// An Enum describing the connection status of a vessel or relay.
+	/// </summary>
 	public enum ConnectionStatus
 	{
 		None,