AntennaRelay: Don't quit on exceptions even in debug mode unless we really want to.
AntennaRelay: Don't quit on exceptions even in debug mode unless we really want to.

<?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"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B36F2C11-962E-4A75-9F41-61AD56D11493}</ProjectGuid> <ProjectGuid>{B36F2C11-962E-4A75-9F41-61AD56D11493}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>AntennaRange</RootNamespace> <RootNamespace>AntennaRange</RootNamespace>
<AssemblyName>AntennaRange</AssemblyName> <AssemblyName>AntennaRange</AssemblyName>
<ReleaseVersion>1.3</ReleaseVersion> <ReleaseVersion>1.3</ReleaseVersion>
<SynchReleaseVersion>false</SynchReleaseVersion> <SynchReleaseVersion>false</SynchReleaseVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<UseMSBuildEngine>False</UseMSBuildEngine> <UseMSBuildEngine>False</UseMSBuildEngine>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;</DefineConstants> <DefineConstants>DEBUG;TRACE;</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="xcopy /y ${TargetFile} ${ProjectDir}\GameData\AntennaRange\" /> <Command type="AfterBuild" command="xcopy /y ${TargetFile} ${ProjectDir}\GameData\AntennaRange\" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' ">
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="xcopy /y ${TargetFile} ${ProjectDir}\GameData\AntennaRange\" /> <Command type="AfterBuild" command="xcopy /y ${TargetFile} ${ProjectDir}\GameData\AntennaRange\" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
<DocumentationFile>bin\Release\AntennaRange.xml</DocumentationFile> <DocumentationFile>bin\Release\AntennaRange.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;</DefineConstants> <DefineConstants>DEBUG;TRACE;</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/GameData/${ProjectName}/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/GameData/${ProjectName}/" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' ">
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/GameData/${ProjectName}/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} ${ProjectDir}/GameData/${ProjectName}/" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="IAntennaRelay.cs" /> <Compile Include="IAntennaRelay.cs" />
<Compile Include="ModuleLimitedDataTransmitter.cs" /> <Compile Include="ModuleLimitedDataTransmitter.cs" />
<Compile Include="AntennaRelay.cs" /> <Compile Include="AntennaRelay.cs" />
<Compile Include="ProtoAntennaRelay.cs" /> <Compile Include="ProtoAntennaRelay.cs" />
<Compile Include="RelayDatabase.cs" /> <Compile Include="RelayDatabase.cs" />
<Compile Include="RelayExtensions.cs" /> <Compile Include="RelayExtensions.cs" />
<Compile Include="ARConfiguration.cs" /> <Compile Include="ARConfiguration.cs" />
<Compile Include="ARFlightController.cs" /> <Compile Include="ARFlightController.cs" />
<Compile Include="ARMapRenderer.cs" /> <Compile Include="ARMapRenderer.cs" />
<Compile Include="VesselCache.cs" />  
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath> <HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System"> <Reference Include="System">
<HintPath>..\_KSPAssemblies\System.dll</HintPath> <HintPath>..\_KSPAssemblies\System.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath> <HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj"> <ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj">
<Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project> <Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project>
<Name>ToadicusTools</Name> <Name>ToadicusTools</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="GameData\AntennaRange\AntennaRange.cfg" /> <None Include="GameData\AntennaRange\AntennaRange.cfg" />
<None Include="GameData\AntennaRange\ATM_AntennaRange.cfg" /> <None Include="GameData\AntennaRange\ATM_AntennaRange.cfg" />
</ItemGroup> </ItemGroup>
</Project> </Project>
// AntennaRange // AntennaRange
// //
// AntennaRelay.cs // AntennaRelay.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ToadicusTools; using ToadicusTools;
   
namespace AntennaRange namespace AntennaRange
{ {
/// <summary> /// <summary>
/// Relay code at the heart of AntennaRange /// Relay code at the heart of AntennaRange
/// </summary> /// </summary>
public class AntennaRelay public class AntennaRelay
{ {
public static readonly System.Diagnostics.Stopwatch searchTimer = new System.Diagnostics.Stopwatch(); public static readonly System.Diagnostics.Stopwatch searchTimer = new System.Diagnostics.Stopwatch();
public const long millisecondsBetweenSearches = 125L; public const long millisecondsBetweenSearches = 125L;
   
// We don't have a Bard, so we'll hide Kerbin here. // We don't have a Bard, so we'll hide Kerbin here.
private static CelestialBody _Kerbin; private static CelestialBody _Kerbin;
   
/// <summary> /// <summary>
/// Fetches, caches, and returns a <see cref="CelestialBody"/> reference to Kerbin /// Fetches, caches, and returns a <see cref="CelestialBody"/> reference to Kerbin
/// </summary> /// </summary>
public static CelestialBody Kerbin public static CelestialBody Kerbin
{ {
get get
{ {
if (_Kerbin == null && FlightGlobals.ready) if (_Kerbin == null && FlightGlobals.ready)
{ {
_Kerbin = FlightGlobals.GetHomeBody(); _Kerbin = FlightGlobals.GetHomeBody();
} }
   
return _Kerbin; return _Kerbin;
} }
} }
   
private long lastSearch; private long lastSearch;
   
private bool canTransmit; private bool canTransmit;
private bool isChecked; private bool isChecked;
   
private IAntennaRelay nearestRelay; private IAntennaRelay nearestRelay;
private IAntennaRelay bestOccludedRelay; private IAntennaRelay bestOccludedRelay;
   
/// <summary> /// <summary>
/// The <see cref="AntennaRange.ModuleLimitedDataTransmitter"/> reference underlying this AntennaRelay, as an /// The <see cref="AntennaRange.ModuleLimitedDataTransmitter"/> reference underlying this AntennaRelay, as an
/// <see cref="AntennaRange.IAntennaRelay"/> /// <see cref="AntennaRange.IAntennaRelay"/>
/// </summary> /// </summary>
protected IAntennaRelay moduleRef; protected IAntennaRelay moduleRef;
   
/// <summary> /// <summary>
/// Gets the parent Vessel. /// Gets the parent Vessel.
/// </summary> /// </summary>
/// <value>The parent Vessel.</value> /// <value>The parent Vessel.</value>
public virtual Vessel vessel public virtual Vessel vessel
{ {
get get
{ {
return this.moduleRef.vessel; return this.moduleRef.vessel;
} }
} }
   
/// <summary> /// <summary>
/// Gets the target <see cref="AntennaRange.IAntennaRelay"/>relay. /// Gets the target <see cref="AntennaRange.IAntennaRelay"/>relay.
/// </summary> /// </summary>
public IAntennaRelay targetRelay public IAntennaRelay targetRelay
{ {
get; get;
protected set; protected set;
} }
   
/// <summary> /// <summary>
/// Gets the first <see cref="CelestialBody"/> found to be blocking line of sight. /// Gets the first <see cref="CelestialBody"/> found to be blocking line of sight.
/// </summary> /// </summary>
public virtual CelestialBody firstOccludingBody public virtual CelestialBody firstOccludingBody
{ {
get; get;
protected set; protected set;
} }
   
/// <summary> /// <summary>
/// Gets the transmit distance. /// Gets the transmit distance.
/// </summary> /// </summary>
/// <value>The transmit distance.</value> /// <value>The transmit distance.</value>
public double transmitDistance public double transmitDistance
{ {
get get
{ {
if (this.KerbinDirect || this.targetRelay == null) if (this.KerbinDirect || this.targetRelay == null)
{ {
return this.DistanceTo(Kerbin); return this.DistanceTo(Kerbin);
} }
else else
{ {
return this.DistanceTo(this.targetRelay); return this.DistanceTo(this.targetRelay);
} }
} }
} }
   
/// <summary> /// <summary>
/// Gets the nominal transmit distance at which the Antenna behaves just as prescribed by Squad's config. /// Gets the nominal transmit distance at which the Antenna behaves just as prescribed by Squad's config.
/// </summary> /// </summary>
public virtual double nominalTransmitDistance public virtual double nominalTransmitDistance
{ {
get; get;
set; set;
} }
   
/// <summary> /// <summary>
/// The maximum distance at which this relay can operate. /// The maximum distance at which this relay can operate.
/// </summary> /// </summary>
/// <value>The max transmit distance.</value> /// <value>The max transmit distance.</value>
public virtual double maxTransmitDistance public virtual double maxTransmitDistance
{ {
get; get;
set; set;
} }
   
/// <summary> /// <summary>
/// Gets a value indicating whether this <see cref="AntennaRange.IAntennaRelay"/> Relay is communicating /// Gets a value indicating whether this <see cref="AntennaRange.IAntennaRelay"/> Relay is communicating
/// directly with Kerbin. /// directly with Kerbin.
/// </summary> /// </summary>
public virtual bool KerbinDirect public virtual bool KerbinDirect
{ {
get; get;
protected set; protected set;
} }
   
/// <summary> /// <summary>
/// Determines whether this instance can transmit. /// Determines whether this instance can transmit.
/// </summary> /// </summary>
/// <returns><c>true</c> if this instance can transmit; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if this instance can transmit; otherwise, <c>false</c>.</returns>
public virtual bool CanTransmit() public virtual bool CanTransmit()
{ {
return this.canTransmit; return this.canTransmit;
} }
   
/// <summary> /// <summary>
/// Finds the nearest relay. /// Finds the nearest relay.
/// </summary> /// </summary>
/// <returns>The nearest relay or null, if no relays in range.</returns> /// <returns>The nearest relay or null, if no relays in range.</returns>
public void FindNearestRelay() public void FindNearestRelay()
{ {
if (!FlightGlobals.ready) if (!FlightGlobals.ready)
{ {
return; return;
} }
   
if (!searchTimer.IsRunning) if (!searchTimer.IsRunning)
{ {
searchTimer.Start(); searchTimer.Start();
} }
   
Tools.DebugLogger log; Tools.DebugLogger log;
#if DEBUG #if DEBUG
log = Tools.DebugLogger.New(this); log = Tools.DebugLogger.New(this);
#endif #endif
   
long searchTime = searchTimer.ElapsedMilliseconds; long searchTime = searchTimer.ElapsedMilliseconds;
long timeSinceLast = searchTime - this.lastSearch; long timeSinceLast = searchTime - this.lastSearch;
   
if (timeSinceLast < millisecondsBetweenSearches) if (timeSinceLast < millisecondsBetweenSearches)
{ {
log.AppendFormat( log.AppendFormat(
"{0}: Target search skipped because it's not time to search again yet ({1} - {2}) < {3})", "{0}: Target search skipped because it's not time to search again yet ({1} - {2}) < {3})",
this, searchTime, this.lastSearch, millisecondsBetweenSearches this, searchTime, this.lastSearch, millisecondsBetweenSearches
); );
log.Print(); log.Print();
return; return;
} }
   
// Skip vessels that have already been checked for a nearest relay this pass. // Skip vessels that have already been checked for a nearest relay this pass.
if (this.isChecked) if (this.isChecked)
{ {
log.AppendFormat("{0}: Target search skipped because our vessel has been checked already this search.", log.AppendFormat("{0}: Target search skipped because our vessel has been checked already this search.",
this); this);
log.Print(); log.Print();
return; return;
} }
   
log.AppendFormat("{0}: Target search started at {1} ms ({2} ms since last search).", log.AppendFormat("{0}: Target search started at {1} ms ({2} ms since last search).",
this.ToString(), searchTime, timeSinceLast); this.ToString(), searchTime, timeSinceLast);
   
#if DEBUG #if DEBUG
try { try {
#endif #endif
// Set this vessel as checked, so that we don't check it again. // Set this vessel as checked, so that we don't check it again.
this.isChecked = true; this.isChecked = true;
   
this.lastSearch = searchTime; this.lastSearch = searchTime;
   
// Blank everything we're trying to find before the search. // Blank everything we're trying to find before the search.
this.firstOccludingBody = null; this.firstOccludingBody = null;
this.bestOccludedRelay = null; this.bestOccludedRelay = null;
this.targetRelay = null; this.targetRelay = null;
this.nearestRelay = null; this.nearestRelay = null;
   
// Default to KerbinDirect = true in case something in here doesn't work right. // Default to KerbinDirect = true in case something in here doesn't work right.
this.KerbinDirect = true; this.KerbinDirect = true;
   
CelestialBody bodyOccludingBestOccludedRelay = null; CelestialBody bodyOccludingBestOccludedRelay = null;
   
double nearestRelaySqrDistance = double.PositiveInfinity; double nearestRelaySqrDistance = double.PositiveInfinity;
double bestOccludedSqrDistance = double.PositiveInfinity; double bestOccludedSqrDistance = double.PositiveInfinity;
double maxTransmitSqrDistance = this.maxTransmitDistance * this.maxTransmitDistance; double maxTransmitSqrDistance = this.maxTransmitDistance * this.maxTransmitDistance;
   
/* /*
* Loop through all the vessels and exclude this vessel, vessels of the wrong type, and vessels that are too * Loop through all the vessels and exclude this vessel, vessels of the wrong type, and vessels that are too
* far away. When we find a candidate, get through its antennae for relays which have not been checked yet * far away. When we find a candidate, get through its antennae for relays which have not been checked yet
* and that can transmit. Once we find a suitable candidate, assign it to nearestRelay for comparison * and that can transmit. Once we find a suitable candidate, assign it to nearestRelay for comparison
* against future finds. * against future finds.
* */ * */
Vessel potentialVessel; Vessel potentialVessel;
IList<IAntennaRelay> vesselRelays; IList<IAntennaRelay> vesselRelays;
for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++) for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++)
{ {
log.AppendFormat("\nFetching vessel at index {0}", vIdx); log.AppendFormat("\nFetching vessel at index {0}", vIdx);
potentialVessel = FlightGlobals.Vessels[vIdx]; potentialVessel = FlightGlobals.Vessels[vIdx];
if (potentialVessel == null) if (potentialVessel == null)
{ {
log.AppendFormat("\n\tSkipping vessel at index {0} because it is null.", vIdx); log.AppendFormat("\n\tSkipping vessel at index {0} because it is null.", vIdx);
log.Print(); log.Print();
return; return;
} }
#if DEBUG #if DEBUG
else else
{ {
log.AppendFormat("\n\tGot vessel {0}", potentialVessel); log.AppendFormat("\n\tGot vessel {0}", potentialVessel);
} }
#endif #endif
   
// Skip vessels of the wrong type. // Skip vessels of the wrong type.
log.Append("\n\tchecking vessel type"); log.Append("\n\tchecking vessel type");
switch (potentialVessel.vesselType) switch (potentialVessel.vesselType)
{ {
case VesselType.Debris: case VesselType.Debris:
case VesselType.Flag: case VesselType.Flag:
case VesselType.EVA: case VesselType.EVA:
case VesselType.SpaceObject: case VesselType.SpaceObject:
case VesselType.Unknown: case VesselType.Unknown:
log.Append("\n\tSkipping because vessel is the wrong type."); log.Append("\n\tSkipping because vessel is the wrong type.");
continue; continue;
default: default:
break; break;
} }
log.Append("\n\tchecking if vessel is this vessel"); log.Append("\n\tchecking if vessel is this vessel");
// Skip vessels with the wrong ID // Skip vessels with the wrong ID
if (potentialVessel.id == vessel.id) if (potentialVessel.id == vessel.id)
{ {
log.Append("\n\tSkipping because vessel is this vessel."); log.Append("\n\tSkipping because vessel is this vessel.");
continue; continue;
} }
   
// Find the distance from here to the vessel... // Find the distance from here to the vessel...
log.Append("\n\tgetting distance to potential vessel"); log.Append("\n\tgetting distance to potential vessel");
double potentialSqrDistance = this.sqrDistanceTo(potentialVessel); double potentialSqrDistance = this.sqrDistanceTo(potentialVessel);
log.Append("\n\tgetting vessel relays"); log.Append("\n\tgetting vessel relays");
vesselRelays = potentialVessel.GetAntennaRelays(); vesselRelays = potentialVessel.GetAntennaRelays();
log.AppendFormat("\n\t\tvesselRelays: {0}", log.AppendFormat("\n\t\tvesselRelays: {0}",
vesselRelays == null ? "null" : vesselRelays.Count.ToString()); vesselRelays == null ? "null" : vesselRelays.Count.ToString());
   
CelestialBody fob = null; CelestialBody fob = null;
log.Append("\n\tdoing LOS check"); log.Append("\n\tdoing LOS check");
// Skip vessels to which we do not have line of sight. // Skip vessels to which we do not have line of sight.
if ( if (
ARConfiguration.RequireLineOfSight && ARConfiguration.RequireLineOfSight &&
!this.vessel.hasLineOfSightTo(potentialVessel, out fob, ARConfiguration.RadiusRatio) !this.vessel.hasLineOfSightTo(potentialVessel, out fob, ARConfiguration.RadiusRatio)
) )
{ {
log.Append("\n\tfailed LOS check"); log.Append("\n\tfailed LOS check");
this.firstOccludingBody = fob; this.firstOccludingBody = fob;
log.AppendFormat("\n\t{0}: Vessel {1} not in line of sight.", log.AppendFormat("\n\t{0}: Vessel {1} not in line of sight.",
this.ToString(), potentialVessel.vesselName); this.ToString(), potentialVessel.vesselName);
log.AppendFormat("\n\t\tpotentialSqrDistance: {0}", potentialSqrDistance); log.AppendFormat("\n\t\tpotentialSqrDistance: {0}", potentialSqrDistance);
log.AppendFormat("\n\t\tbestOccludedSqrDistance: {0}", bestOccludedSqrDistance); log.AppendFormat("\n\t\tbestOccludedSqrDistance: {0}", bestOccludedSqrDistance);
log.AppendFormat("\n\t\tmaxTransmitSqrDistance: {0}", maxTransmitSqrDistance); log.AppendFormat("\n\t\tmaxTransmitSqrDistance: {0}", maxTransmitSqrDistance);
   
if ( if (
(potentialSqrDistance < bestOccludedSqrDistance) && (potentialSqrDistance < bestOccludedSqrDistance) &&
(potentialSqrDistance < maxTransmitSqrDistance) (potentialSqrDistance < maxTransmitSqrDistance)
) )
{ {
log.Append("\n\t\t...vessel is close enough to check for occluded relays"); log.Append("\n\t\t...vessel is close enough to check for occluded relays");
log.AppendFormat("\n\t\tthis: {0}", this); log.AppendFormat("\n\t\tthis: {0}", this);
log.AppendFormat("\n\t\tpotentialVessel: {0}", log.AppendFormat("\n\t\tpotentialVessel: {0}",
potentialVessel == null ? "null" : potentialVessel.ToString()); potentialVessel == null ? "null" : potentialVessel.ToString());
log.AppendFormat("\n\t\tvesselRelays: {0}", log.AppendFormat("\n\t\tvesselRelays: {0}",
vesselRelays == null ? "null" : vesselRelays.ToString()); vesselRelays == null ? "null" : vesselRelays.ToString());
   
log.AppendFormat("\n\t\t{0}: Checking {1} relays on occluded vessel {2}.", log.AppendFormat("\n\t\t{0}: Checking {1} relays on occluded vessel {2}.",
this.ToString(), this.ToString(),
vesselRelays.Count, vesselRelays.Count,
potentialVessel potentialVessel
); );
   
IAntennaRelay occludedRelay; IAntennaRelay occludedRelay;
for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++) for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
{ {
occludedRelay = vesselRelays[rIdx]; occludedRelay = vesselRelays[rIdx];
   
log.AppendFormat( log.AppendFormat(
"\n\t\t{0}: Checking candidate for bestOccludedRelay: {1}" + "\n\t\t{0}: Checking candidate for bestOccludedRelay: {1}" +
"\n\t\tCanTransmit: {2}", "\n\t\tCanTransmit: {2}",
this.ToString(), occludedRelay, occludedRelay.CanTransmit() this.ToString(), occludedRelay, occludedRelay.CanTransmit()
); );
if (occludedRelay.CanTransmit()) if (occludedRelay.CanTransmit())
{ {
this.bestOccludedRelay = occludedRelay; this.bestOccludedRelay = occludedRelay;
bodyOccludingBestOccludedRelay = fob; bodyOccludingBestOccludedRelay = fob;
bestOccludedSqrDistance = potentialSqrDistance; bestOccludedSqrDistance = potentialSqrDistance;
   
log.AppendFormat("\n\t{0}: Found new bestOccludedRelay: {1}" + log.AppendFormat("\n\t{0}: Found new bestOccludedRelay: {1}" +
" (blocked by {2}; distance: {3} m)", " (blocked by {2}; distance: {3} m)",
this.ToString(), this.ToString(),
occludedRelay.ToString(), occludedRelay.ToString(),
fob, fob,
potentialSqrDistance potentialSqrDistance
); );
break; break;
} }
} }
} }
log.Append("\n\t\t...vessel is not close enough to check for occluded relays, carrying on"); log.Append("\n\t\t...vessel is not close enough to check for occluded relays, carrying on");
continue; continue;
} }
   
log.Append("\n\tpassed LOS check"); log.Append("\n\tpassed LOS check");
   
/* /*
* ...so that we can skip the vessel if it is further away than a vessel we've already checked. * ...so that we can skip the vessel if it is further away than a vessel we've already checked.
* */ * */
if (potentialSqrDistance > nearestRelaySqrDistance) if (potentialSqrDistance > nearestRelaySqrDistance)
{ {
log.AppendFormat("\n\t{0}: Vessel {1} discarded because it is farther than another the nearest relay.", log.AppendFormat("\n\t{0}: Vessel {1} discarded because it is farther than another the nearest relay.",
this.ToString(), this.ToString(),
potentialVessel.vesselName potentialVessel.vesselName
); );
continue; continue;
} }
   
log.Append("\n\tpassed distance check"); log.Append("\n\tpassed distance check");
   
IAntennaRelay potentialRelay; IAntennaRelay potentialRelay;
for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++) for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
{ {
log.AppendFormat("\n\t\tfetching vessel relay at index {0}", rIdx); log.AppendFormat("\n\t\tfetching vessel relay at index {0}", rIdx);
potentialRelay = vesselRelays[rIdx]; potentialRelay = vesselRelays[rIdx];
log.AppendFormat("\n\t\tgot relay {0}", potentialRelay == null ? "null" : potentialRelay.ToString()); log.AppendFormat("\n\t\tgot relay {0}", potentialRelay == null ? "null" : potentialRelay.ToString());
   
if (potentialRelay == null) if (potentialRelay == null)
{ {
log.Append("\n\t\t...skipping null relay"); log.Append("\n\t\t...skipping null relay");
continue; continue;
} }
   
if ( if (
potentialRelay.CanTransmit() && potentialRelay.CanTransmit() &&
(potentialRelay.targetRelay == null || potentialRelay.targetRelay.vessel != this.vessel)) (potentialRelay.targetRelay == null || potentialRelay.targetRelay.vessel != this.vessel))
{ {
// @TODO: Moved this here from outside the loop; why was it there? // @TODO: Moved this here from outside the loop; why was it there?
nearestRelaySqrDistance = potentialSqrDistance; nearestRelaySqrDistance = potentialSqrDistance;
this.nearestRelay = potentialRelay; this.nearestRelay = potentialRelay;
   
log.AppendFormat("\n\t{0}: found new nearest relay {1} ({2}m)", log.AppendFormat("\n\t{0}: found new nearest relay {1} ({2}m)",
this.ToString(), this.ToString(),
this.nearestRelay.ToString(), this.nearestRelay.ToString(),
Math.Sqrt(nearestRelaySqrDistance) Math.Sqrt(nearestRelaySqrDistance)
); );
break; break;
} }
} }
} }
   
CelestialBody bodyOccludingKerbin = null; CelestialBody bodyOccludingKerbin = null;
   
double kerbinSqrDistance = this.vessel.DistanceTo(Kerbin) - Kerbin.Radius; double kerbinSqrDistance = this.vessel.DistanceTo(Kerbin) - Kerbin.Radius;
kerbinSqrDistance *= kerbinSqrDistance; kerbinSqrDistance *= kerbinSqrDistance;
   
log.AppendFormat("\n{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 we don't have LOS to Kerbin, focus on relays
if (!this.vessel.hasLineOfSightTo(Kerbin, out bodyOccludingKerbin, ARConfiguration.RadiusRatio)) if (!this.vessel.hasLineOfSightTo(Kerbin, out bodyOccludingKerbin, ARConfiguration.RadiusRatio))
{ {
log.AppendFormat("\n\tKerbin LOS is blocked by {0}.", bodyOccludingKerbin.bodyName); log.AppendFormat("\n\tKerbin LOS is blocked by {0}.", bodyOccludingKerbin.bodyName);
   
// nearestRelaySqrDistance will be infinity if all relays are occluded or none exist. // nearestRelaySqrDistance will be infinity if all relays are occluded or none exist.
// Therefore, this will only be true if a valid relay is in range. // Therefore, this will only be true if a valid relay is in range.
if (nearestRelaySqrDistance <= maxTransmitSqrDistance) if (nearestRelaySqrDistance <= maxTransmitSqrDistance)
{ {
log.AppendFormat("\n\t\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(), this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
nearestRelaySqrDistance, maxTransmitSqrDistance); nearestRelaySqrDistance, maxTransmitSqrDistance);
   
this.KerbinDirect = false; this.KerbinDirect = false;
this.canTransmit = true; this.canTransmit = true;
this.targetRelay = this.nearestRelay; this.targetRelay = this.nearestRelay;
} }
// If this isn't true, we can't transmit, but pick a second best of bestOccludedRelay and Kerbin anyway // If this isn't true, we can't transmit, but pick a second best of bestOccludedRelay and Kerbin anyway
else else
{ {
log.AppendFormat("\n\t\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(), this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
nearestRelaySqrDistance, maxTransmitSqrDistance); nearestRelaySqrDistance, maxTransmitSqrDistance);
   
this.canTransmit = false; this.canTransmit = false;
   
// If the best occluded relay is closer than Kerbin, check it against the nearest relay. // If the best occluded relay is closer than Kerbin, check it against the nearest relay.
// Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe // Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe
if (bestOccludedSqrDistance < kerbinSqrDistance) if (bestOccludedSqrDistance < kerbinSqrDistance)
{ {
log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})", log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})",
bestOccludedRelay, kerbinSqrDistance); bestOccludedRelay, kerbinSqrDistance);
this.KerbinDirect = false; this.KerbinDirect = false;
   
// If the nearest relay is closer than the best occluded relay, pick it. // 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. // Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
if (nearestRelaySqrDistance < bestOccludedSqrDistance) if (nearestRelaySqrDistance < bestOccludedSqrDistance)
{ {
log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
nearestRelaySqrDistance, bestOccludedSqrDistance); nearestRelaySqrDistance, bestOccludedSqrDistance);
this.targetRelay = nearestRelay; this.targetRelay = nearestRelay;
this.firstOccludingBody = null; this.firstOccludingBody = null;
} }
// Otherwise, target the best occluded relay. // Otherwise, target the best occluded relay.
else else
{ {
log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
nearestRelaySqrDistance, bestOccludedSqrDistance); nearestRelaySqrDistance, bestOccludedSqrDistance);
this.targetRelay = bestOccludedRelay; this.targetRelay = bestOccludedRelay;
this.firstOccludingBody = bodyOccludingBestOccludedRelay; this.firstOccludingBody = bodyOccludingBestOccludedRelay;
} }
} }
// Otherwise, check Kerbin against the nearest relay. // Otherwise, check Kerbin against the nearest relay.
// Since we have LOS, blank the first occluding body. // Since we have LOS, blank the first occluding body.
else else
{ {
log.AppendFormat("\n\t\t\tKerbin is closer than the best occluded relay ({0} >= {1})", log.AppendFormat("\n\t\t\tKerbin is closer than the best occluded relay ({0} >= {1})",
bestOccludedRelay, kerbinSqrDistance); bestOccludedRelay, kerbinSqrDistance);
this.firstOccludingBody = null; this.firstOccludingBody = null;
   
// If the nearest relay is closer than Kerbin, pick it. // If the nearest relay is closer than Kerbin, pick it.
// Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe. // Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
if (nearestRelaySqrDistance < kerbinSqrDistance) if (nearestRelaySqrDistance < kerbinSqrDistance)
{ {
log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
nearestRelaySqrDistance, kerbinSqrDistance); nearestRelaySqrDistance, kerbinSqrDistance);
this.KerbinDirect = false; this.KerbinDirect = false;
this.targetRelay = nearestRelay; this.targetRelay = nearestRelay;
} }
// Otherwise, pick Kerbin. // Otherwise, pick Kerbin.
else else
{ {
log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
nearestRelaySqrDistance, kerbinSqrDistance); nearestRelaySqrDistance, kerbinSqrDistance);
this.KerbinDirect = true; this.KerbinDirect = true;
this.targetRelay = null; this.targetRelay = null;
} }
} }
} }
} }
// If we do have LOS to Kerbin, try to prefer the closest of nearestRelay and Kerbin // If we do have LOS to Kerbin, try to prefer the closest of nearestRelay and Kerbin
else else
{ {
log.AppendFormat("\n\tKerbin is in LOS."); log.AppendFormat("\n\tKerbin is in LOS.");
   
// If the nearest relay is closer than Kerbin and in range, transmit to it. // If the nearest relay is closer than Kerbin and in range, transmit to it.
if (nearestRelaySqrDistance <= maxTransmitSqrDistance) if (nearestRelaySqrDistance <= maxTransmitSqrDistance)
{ {
log.AppendFormat("\n\t\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(), this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
nearestRelaySqrDistance, maxTransmitSqrDistance); nearestRelaySqrDistance, maxTransmitSqrDistance);
   
this.canTransmit = true; this.canTransmit = true;
   
// If the nearestRelay is closer than Kerbin, use it. // If the nearestRelay is closer than Kerbin, use it.
if (nearestRelaySqrDistance < kerbinSqrDistance) if (nearestRelaySqrDistance < kerbinSqrDistance)
{ {
log.AppendFormat("\n\t\t\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(), this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
nearestRelaySqrDistance, kerbinSqrDistance); nearestRelaySqrDistance, kerbinSqrDistance);
   
this.KerbinDirect = false; this.KerbinDirect = false;
this.targetRelay = this.nearestRelay; this.targetRelay = this.nearestRelay;
} }
// Otherwise, Kerbin is closer, so use it. // Otherwise, Kerbin is closer, so use it.
else else
{ {
log.AppendFormat("\n\t\t\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(), this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
nearestRelaySqrDistance, kerbinSqrDistance); nearestRelaySqrDistance, kerbinSqrDistance);
   
this.KerbinDirect = true; this.KerbinDirect = true;
this.targetRelay = null; this.targetRelay = null;
} }
} }
// If the nearest relay is out of range, we still need to check on Kerbin. // If the nearest relay is out of range, we still need to check on Kerbin.
else else
{ {
log.AppendFormat("\n\t\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(), this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
nearestRelaySqrDistance, maxTransmitSqrDistance); nearestRelaySqrDistance, maxTransmitSqrDistance);
   
// If Kerbin is in range, use it. // If Kerbin is in range, use it.
if (kerbinSqrDistance <= maxTransmitSqrDistance) if (kerbinSqrDistance <= maxTransmitSqrDistance)
{ {
log.AppendFormat("\n\t\t\tCan transmit to Kerbin ({0} <= {1}).", log.AppendFormat("\n\t\t\tCan transmit to Kerbin ({0} <= {1}).",
kerbinSqrDistance, maxTransmitSqrDistance); kerbinSqrDistance, maxTransmitSqrDistance);
   
this.canTransmit = true; this.canTransmit = true;
this.KerbinDirect = true; this.KerbinDirect = true;
this.targetRelay = null; this.targetRelay = null;
} }
// If Kerbin is out of range and the nearest relay is out of range, pick a second best between // If Kerbin is out of range and the nearest relay is out of range, pick a second best between
// Kerbin and bestOccludedRelay // Kerbin and bestOccludedRelay
else else
{ {
log.AppendFormat("\n\t\t\tCan't transmit to Kerbin ({0} > {1}).", log.AppendFormat("\n\t\t\tCan't transmit to Kerbin ({0} > {1}).",
kerbinSqrDistance, maxTransmitSqrDistance); kerbinSqrDistance, maxTransmitSqrDistance);
   
this.canTransmit = false; this.canTransmit = false;
   
// If the best occluded relay is closer than Kerbin, check it against the nearest relay. // If the best occluded relay is closer than Kerbin, check it against the nearest relay.
// Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe // Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe
if (bestOccludedSqrDistance < kerbinSqrDistance) if (bestOccludedSqrDistance < kerbinSqrDistance)
{ {
log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})", log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})",
bestOccludedRelay, kerbinSqrDistance); bestOccludedRelay, kerbinSqrDistance);
this.KerbinDirect = false; this.KerbinDirect = false;
   
// If the nearest relay is closer than the best occluded relay, pick it. // 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. // Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
if (nearestRelaySqrDistance < bestOccludedSqrDistance) if (nearestRelaySqrDistance < bestOccludedSqrDistance)
{ {
log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
nearestRelaySqrDistance, bestOccludedSqrDistance); nearestRelaySqrDistance, bestOccludedSqrDistance);
this.targetRelay = nearestRelay; this.targetRelay = nearestRelay;
this.firstOccludingBody = null; this.firstOccludingBody = null;
} }
// Otherwise, target the best occluded relay. // Otherwise, target the best occluded relay.
else else
{ {
log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
nearestRelaySqrDistance, bestOccludedSqrDistance); nearestRelaySqrDistance, bestOccludedSqrDistance);
this.targetRelay = bestOccludedRelay; this.targetRelay = bestOccludedRelay;
this.firstOccludingBody = bodyOccludingBestOccludedRelay; this.firstOccludingBody = bodyOccludingBestOccludedRelay;
} }
} }
// Otherwise, check Kerbin against the nearest relay. // Otherwise, check Kerbin against the nearest relay.
// Since we have LOS, blank the first occluding body. // Since we have LOS, blank the first occluding body.
else else
{ {
log.AppendFormat("\n\t\t\tKerbin is closer than the best occluded relay ({0} >= {1})", log.AppendFormat("\n\t\t\tKerbin is closer than the best occluded relay ({0} >= {1})",
bestOccludedRelay, kerbinSqrDistance); bestOccludedRelay, kerbinSqrDistance);
this.firstOccludingBody = null; this.firstOccludingBody = null;
   
// If the nearest relay is closer than Kerbin, pick it. // If the nearest relay is closer than Kerbin, pick it.
// Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe. // Since nearestRelaySqrDistane is infinity if there are no nearby relays, this is safe.
if (nearestRelaySqrDistance < kerbinSqrDistance) if (nearestRelaySqrDistance < kerbinSqrDistance)
{ {
log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...but the nearest relay is closer ({0} < {1}), so picking it.",
nearestRelaySqrDistance, kerbinSqrDistance); nearestRelaySqrDistance, kerbinSqrDistance);
this.KerbinDirect = false; this.KerbinDirect = false;
this.targetRelay = nearestRelay; this.targetRelay = nearestRelay;
} }
// Otherwise, pick Kerbin. // Otherwise, pick Kerbin.
else else
{ {
log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.", log.AppendFormat("\n\t\t\t\t...and closer than the nearest relay ({0} >= {1}), so picking it.",
nearestRelaySqrDistance, kerbinSqrDistance); nearestRelaySqrDistance, kerbinSqrDistance);
this.KerbinDirect = true; this.KerbinDirect = true;
this.targetRelay = null; this.targetRelay = null;
} }
} }
} }
} }
} }
   
log.AppendFormat("{0}: Target search completed at {1} ms ({2} ms elapsed).", log.AppendFormat("{0}: Target search completed at {1} ms ({2} ms elapsed).",
this.ToString(), searchTimer.ElapsedMilliseconds, searchTimer.ElapsedMilliseconds - searchTime);; this.ToString(), searchTimer.ElapsedMilliseconds, searchTimer.ElapsedMilliseconds - searchTime);;
   
log.AppendFormat("\n{0}: Status determination complete.", this.ToString()); log.AppendFormat("\n{0}: Status determination complete.", this.ToString());
#if DEBUG #if DEBUG
} catch (Exception ex) { } catch (Exception ex) {
log.AppendFormat("\nCaught {0}: {1}\n{2}", ex.GetType().FullName, ex.ToString(), ex.StackTrace); log.AppendFormat("\nCaught {0}: {1}\n{2}", ex.GetType().FullName, ex.ToString(), ex.StackTrace);
  #if QUIT_ON_EXCEPTION
UnityEngine.Application.Quit(); UnityEngine.Application.Quit();
  #endif
} finally { } finally {
#endif #endif
log.Print(false); log.Print(false);
#if DEBUG #if DEBUG
} }
#endif #endif
// Now that we're done with our recursive CanTransmit checks, flag this relay as not checked so it can be // Now that we're done with our recursive CanTransmit checks, flag this relay as not checked so it can be
// used next time. // used next time.
this.isChecked = false; this.isChecked = false;
} }
   
/// <summary> /// <summary>
/// Returns a <see cref="System.String"/> that represents the current <see cref="AntennaRange.AntennaRelay"/>. /// Returns a <see cref="System.String"/> that represents the current <see cref="AntennaRange.AntennaRelay"/>.
/// </summary> /// </summary>
/// <returns>A <see cref="System.String"/> that represents the current <see cref="AntennaRange.AntennaRelay"/>.</returns> /// <returns>A <see cref="System.String"/> that represents the current <see cref="AntennaRange.AntennaRelay"/>.</returns>
public override string ToString() public override string ToString()
{ {
if (this is ProtoAntennaRelay) if (this is ProtoAntennaRelay)
{ {
return (this as ProtoAntennaRelay).ToString(); return (this as ProtoAntennaRelay).ToString();
} }
return this.moduleRef.ToString(); return this.moduleRef.ToString();
} }
   
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="AntennaRange.AntennaRelay"/> class. /// Initializes a new instance of the <see cref="AntennaRange.AntennaRelay"/> class.
/// </summary> /// </summary>
/// <param name="module">The module reference underlying this AntennaRelay, /// <param name="module">The module reference underlying this AntennaRelay,
/// as an <see cref="AntennaRange.IAntennaRelay"/></param> /// as an <see cref="AntennaRange.IAntennaRelay"/></param>
public AntennaRelay(IAntennaRelay module) public AntennaRelay(IAntennaRelay module)
{ {
this.moduleRef = module; this.moduleRef = module;
this.isChecked = false; this.isChecked = false;
   
Tools.PostLogMessage("{0}: constructed {1}", this.GetType().Name, this.ToString()); Tools.PostLogMessage("{0}: constructed {1}", this.GetType().Name, this.ToString());
} }
} }
} }