Relicensed to Modified BSD.
[AntennaRange.git] / AntennaRelay.cs
blob:a/AntennaRelay.cs -> blob:b/AntennaRelay.cs
--- a/AntennaRelay.cs
+++ b/AntennaRelay.cs
@@ -29,11 +29,14 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using ToadicusTools;
 
 namespace AntennaRange
 {
 	public class AntennaRelay
 	{
+		public static bool requireLineOfSight;
+
 		// We don't have a Bard, so we'll hide Kerbin here.
 		protected CelestialBody Kerbin;
 
@@ -129,7 +132,10 @@
 		/// <returns><c>true</c> if this instance can transmit; otherwise, <c>false</c>.</returns>
 		public virtual bool CanTransmit()
 		{
-			if (this.transmitDistance > this.maxTransmitDistance)
+			if (
+				this.transmitDistance > this.maxTransmitDistance ||
+				(requireLineOfSight && this.nearestRelay == null && !this.vessel.hasLineOfSightTo(this.Kerbin))
+			)
 			{
 				return false;
 			}
@@ -168,7 +174,7 @@
 			// Set this vessel as checked, so that we don't check it again.
 			RelayDatabase.Instance.CheckedVesselsTable[vessel.id] = true;
 
-			double nearestDistance = double.PositiveInfinity;
+			double nearestSqrDistance = double.PositiveInfinity;
 			IAntennaRelay _nearestRelay = null;
 
 			/*
@@ -180,14 +186,10 @@
 			foreach (Vessel potentialVessel in FlightGlobals.Vessels)
 			{
 				// Skip vessels that have already been checked for a nearest relay this pass.
-				try
-				{
-					if (RelayDatabase.Instance.CheckedVesselsTable[potentialVessel.id])
-					{
-						continue;
-					}
-				}
-				catch (KeyNotFoundException) { /* If the key doesn't exist, don't skip it. */}
+				if (RelayDatabase.Instance.CheckedVesselsTable.ContainsKey(potentialVessel.id))
+				{
+					continue;
+				}
 
 				// Skip vessels of the wrong type.
 				switch (potentialVessel.vesselType)
@@ -208,19 +210,41 @@
 					continue;
 				}
 
+				// Skip vessels to which we do not have line of sight.
+				if (requireLineOfSight && !this.vessel.hasLineOfSightTo(potentialVessel))
+				{
+					Tools.PostDebugMessage(
+						this,
+						"Vessel {0} discarded because we do not have line of sight.",
+						potentialVessel.vesselName
+					);
+					continue;
+				}
+
 				// Find the distance from here to the vessel...
-				double potentialDistance = (potentialVessel.GetWorldPos3D() - vessel.GetWorldPos3D()).magnitude;
+				double potentialSqrDistance = (potentialVessel.GetWorldPos3D() - vessel.GetWorldPos3D()).sqrMagnitude;
 
 				/*
 				 * ...so that we can skip the vessel if it is further away than Kerbin, our transmit distance, or a
 				 * vessel we've already checked.
 				 * */
-				if (potentialDistance > Tools.Min(this.maxTransmitDistance, nearestDistance, vessel.DistanceTo(Kerbin)))
-				{
+				if (
+					potentialSqrDistance > Tools.Min(
+						this.maxTransmitDistance * this.maxTransmitDistance,
+						nearestSqrDistance,
+						this.vessel.sqrDistanceTo(Kerbin)
+					)
+				)
+				{
+					Tools.PostDebugMessage(
+						this,
+						"Vessel {0} discarded because it is out of range, or farther than another relay.",
+						potentialVessel.vesselName
+					);
 					continue;
 				}
 
-				nearestDistance = potentialDistance;
+				nearestSqrDistance = potentialSqrDistance;
 
 				foreach (IAntennaRelay potentialRelay in potentialVessel.GetAntennaRelays())
 				{
@@ -260,6 +284,17 @@
 			// we hope it is safe enough.
 			this.Kerbin = FlightGlobals.Bodies.FirstOrDefault(b => b.name == "Kerbin");
 		}
+
+		static AntennaRelay()
+		{
+			var config = KSP.IO.PluginConfiguration.CreateForType<AntennaRelay>();
+
+			config.load();
+
+			AntennaRelay.requireLineOfSight = config.GetValue<bool>("requireLineOfSight", false);
+
+			config.save();
+		}
 	}
 }