A little refactoring and a new message to indicate if you are using a relay. Also fixed using distant relays instead of nearby Kerbin.
--- a/AntennaRange.cs
+++ /dev/null
@@ -1,387 +1,1 @@
-/*
- * AntennaRange © 2013 toadicus
- *
- * AntennaRange provides incentive and requirements for the use of the various antenna parts.
- * Nominally, the breakdown is as follows:
- *
- * Communotron 16 - Suitable up to Kerbalsynchronous Orbit
- * Comms DTS-M1 - Suitable throughout the Kerbin subsystem
- * Communotron 88-88 - Suitable throughout the Kerbol system.
- *
- * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
- * copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
- *
- * This software uses the ModuleManager library © 2013 ialdabaoth, used under a Creative Commons Attribution-ShareAlike
- * 3.0 Uported License.
- *
- * This software uses code from the MuMechLib library, © 2013 r4m0n, used under the GNU GPL version 3.
- *
- */
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using KSP;
-using UnityEngine;
-namespace AntennaRange
-{
- /*
- * ModuleLimitedDataTransmitter is designed as a drop-in replacement for ModuleDataTransmitter, and handles range-
- * finding, power scaling, and data scaling for antennas during science transmission. Its functionality varies with
- * three tunables: nominalRange, maxPowerFactor, and maxDataFactor, set in .cfg files.
- *
- * In general, the scaling functions assume the following relation:
- *
- * D² α P/R,
- *
- * where D is the total transmission distance, P is the transmission power, and R is the data rate.
- *
- * */
-
- /*
- * Fields
- * */
- public class ModuleLimitedDataTransmitter : ModuleDataTransmitter, IScienceDataTransmitter, IAntennaRelay
- {
- // Call this an antenna so that you don't have to.
- [KSPField(isPersistant = true)]
- protected bool IsAntenna = true;
-
- // Stores the packetResourceCost as defined in the .cfg file.
- protected float _basepacketResourceCost;
-
- // Stores the packetSize as defined in the .cfg file.
- protected float _basepacketSize;
-
- // Every antenna is a relay.
- protected AntennaRelay relay;
-
- // Keep track of vessels with transmitters for relay purposes.
- protected List<Vessel> _relayVessels;
-
- // Sometimes we will need to communicate errors; this is how we do it.
- protected ScreenMessage ErrorMsg;
-
- // Let's make the error text pretty!
- protected UnityEngine.GUIStyle ErrorStyle;
-
- // The distance from Kerbin at which the antenna will perform exactly as prescribed by packetResourceCost
- // and packetSize.
- [KSPField(isPersistant = false)]
- public float nominalRange;
-
- // The multiplier on packetResourceCost that defines the maximum power output of the antenna. When the power
- // cost exceeds packetResourceCost * maxPowerFactor, transmission will fail.
- [KSPField(isPersistant = false)]
- public float maxPowerFactor;
-
- // The multipler on packetSize that defines the maximum data bandwidth of the antenna.
- [KSPField(isPersistant = false)]
- public float maxDataFactor;
-
- // This field exists to get saved to the persistence file so that relays can be found on unloaded Vessels.
- [KSPField(isPersistant = true)]
- protected float ARmaxTransmitDistance;
-
- /*
- * Properties
- * */
- // Returns the parent vessel housing this antenna.
- public new Vessel vessel
- {
- get
- {
- return base.vessel;
- }
- }
-
- // Returns the distance to the nearest relay or Kerbin, whichever is closer.
- public double transmitDistance
- {
- get
- {
- return this.relay.transmitDistance;
- }
- }
-
- // Returns the maximum distance this module can transmit
- public float maxTransmitDistance
- {
- get
- {
- return this.ARmaxTransmitDistance;
- }
- }
-
- /*
- * The next two functions overwrite the behavior of the stock functions and do not perform equivalently, except
- * in that they both return floats. Here's some quick justification:
- *
- * The stock implementation of GetTransmitterScore (which I cannot override) is:
- * Score = (1 + DataResourceCost) / DataRate
- *
- * The stock DataRate and DataResourceCost are:
- * DataRate = packetSize / packetInterval
- * DataResourceCost = packetResourceCost / packetSize
- *
- * So, the resulting score is essentially in terms of joules per byte per baud. Rearranging that a bit, it
- * could also look like joule-seconds per byte per byte, or newton-meter-seconds per byte per byte. Either way,
- * that metric is not a very reasonable one.
- *
- * Two metrics that might make more sense are joules per byte or joules per byte per second. The latter case
- * would look like:
- * DataRate = packetSize / packetInterval
- * DataResourceCost = packetResourceCost
- *
- * The former case, which I've chosen to implement below, is:
- * DataRate = packetSize
- * DataResourceCost = packetResourceCost
- *
- * So... hopefully that doesn't screw with anything else.
- * */
- // Override ModuleDataTransmitter.DataRate to just return packetSize, because we want antennas to be scored in
- // terms of joules/byte
- public new float DataRate
- {
- get
- {
- this.PreTransmit_SetPacketSize();
- return this.packetSize;
- }
- }
-
- // Override ModuleDataTransmitter.DataResourceCost to just return packetResourceCost, because we want antennas
- // to be scored in terms of joules/byte
- public new float DataResourceCost
- {
- get
- {
- this.PreTransmit_SetPacketResourceCost();
-
- if (this.CanTransmit())
- {
- return this.packetResourceCost;
- }
- else
- {
- return float.PositiveInfinity;
- }
- }
- }
-
- // Reports whether this antenna has been checked as a viable relay already in the current FindNearestRelay.
- public bool relayChecked
- {
- get
- {
- return this.relay.relayChecked;
- }
- }
-
- /*
- * Methods
- * */
- // Build ALL the objects.
- public ModuleLimitedDataTransmitter () : base()
- {
- // Make the error posting prettier.
- this.ErrorStyle = new UnityEngine.GUIStyle();
- this.ErrorStyle.normal.textColor = (UnityEngine.Color)XKCDColors.OrangeRed;
- this.ErrorStyle.active.textColor = (UnityEngine.Color)XKCDColors.OrangeRed;
- this.ErrorStyle.hover.textColor = (UnityEngine.Color)XKCDColors.OrangeRed;
- this.ErrorStyle.fontStyle = UnityEngine.FontStyle.Bold;
- this.ErrorStyle.padding.top = 32;
-
- this.ErrorMsg = new ScreenMessage("", 4f, false, ScreenMessageStyle.UPPER_LEFT, this.ErrorStyle);
- }
-
- // At least once, when the module starts with a state on the launch pad or later, go find Kerbin.
- public override void OnStart (StartState state)
- {
- base.OnStart (state);
-
- if (state >= StartState.PreLaunch)
- {
- this.relay = new AntennaRelay(vessel);
- this.relay.maxTransmitDistance = this.maxTransmitDistance;
- }
-
- // Pre-set the transmit cost and packet size when loading.
- this.PreTransmit_SetPacketResourceCost();
- this.PreTransmit_SetPacketSize();
- }
-
- // When the module loads, fetch the Squad KSPFields from the base. This is necessary in part because
- // overloading packetSize and packetResourceCostinto a property in ModuleLimitedDataTransmitter didn't
- // work.
- public override void OnLoad(ConfigNode node)
- {
- this.Fields.Load(node);
- base.Fields.Load(node);
-
- this.ARmaxTransmitDistance = Mathf.Sqrt (this.maxPowerFactor) * this.nominalRange;
-
- base.OnLoad (node);
-
- this._basepacketSize = base.packetSize;
- this._basepacketResourceCost = base.packetResourceCost;
-
- Tools.PostDebugMessage(string.Format(
- "{0} loaded:\n" +
- "packetSize: {1}\n" +
- "packetResourceCost: {2}\n" +
- "nominalRange: {3}\n" +
- "maxPowerFactor: {4}\n" +
- "maxDataFactor: {5}\n",
- this.name,
- base.packetSize,
- this._basepacketResourceCost,
- this.nominalRange,
- this.maxPowerFactor,
- this.maxDataFactor
- ));
- }
-
- // Post an error in the communication messages describing the reason transmission has failed. Currently there
- // is only one reason for this.
- protected void PostCannotTransmitError()
- {
- string ErrorText = string.Format (
- "Unable to transmit: out of range! Maximum range = {0}m; Current range = {1}m.",
- Tools.MuMech_ToSI((double)this.ARmaxTransmitDistance, 2),
- Tools.MuMech_ToSI((double)this.transmitDistance, 2)
- );
-
- this.ErrorMsg.message = ErrorText;
-
- ScreenMessages.PostScreenMessage(this.ErrorMsg, true);
- }
-
- // Before transmission, set packetResourceCost. Per above, packet cost increases with the square of
- // distance. packetResourceCost maxes out at _basepacketResourceCost * maxPowerFactor, at which point
- // transmission fails (see CanTransmit).
- protected void PreTransmit_SetPacketResourceCost()
- {
- if (this.transmitDistance <= this.nominalRange)
- {
- base.packetResourceCost = this._basepacketResourceCost;
- }
- else
- {
- base.packetResourceCost = this._basepacketResourceCost
- * (float)Math.Pow (this.transmitDistance / this.nominalRange, 2);
- }
- }
-
- // Before transmission, set packetSize. Per above, packet size increases with the inverse square of
- // distance. packetSize maxes out at _basepacketSize * maxDataFactor.
- protected void PreTransmit_SetPacketSize()
- {
- if (this.transmitDistance >= this.nominalRange)
- {
- base.packetSize = this._basepacketSize;
- }
- else
- {
- base.packetSize = Math.Min(
- this._basepacketSize * (float)Math.Pow (this.nominalRange / this.transmitDistance, 2),
- this._basepacketSize * this.maxDataFactor);
- }
- }
-
- // Override ModuleDataTransmitter.GetInfo to add nominal and maximum range to the VAB description.
- public override string GetInfo()
- {
- string text = base.GetInfo();
- text += "Nominal Range: " + Tools.MuMech_ToSI((double)this.nominalRange, 2) + "m\n";
- text += "Maximum Range: " + Tools.MuMech_ToSI((double)this.ARmaxTransmitDistance, 2) + "m\n";
- return text;
- }
-
- // Override ModuleDataTransmitter.CanTransmit to return false when transmission is not possible.
- public new bool CanTransmit()
- {
- return this.relay.CanTransmit();
- }
-
- // Override ModuleDataTransmitter.TransmitData to check against CanTransmit and fail out when CanTransmit
- // returns false.
- public new void TransmitData(List<ScienceData> dataQueue)
- {
- if (this.CanTransmit())
- {
- base.TransmitData(dataQueue);
- }
- else
- {
- this.PostCannotTransmitError ();
- }
-
- Tools.PostDebugMessage (
- "distance: " + this.transmitDistance
- + " packetSize: " + this.packetSize
- + " packetResourceCost: " + this.packetResourceCost
- );
- }
-
- // Override ModuleDataTransmitter.StartTransmission to check against CanTransmit and fail out when CanTransmit
- // returns false.
- public new void StartTransmission()
- {
- PreTransmit_SetPacketSize ();
- PreTransmit_SetPacketResourceCost ();
-
- Tools.PostDebugMessage (
- "distance: " + this.transmitDistance
- + " packetSize: " + this.packetSize
- + " packetResourceCost: " + this.packetResourceCost
- );
- if (this.CanTransmit())
- {
- base.StartTransmission();
- }
- else
- {
- this.PostCannotTransmitError ();
- }
- }
-
- // When debugging, it's nice to have a button that just tells you everything.
- #if DEBUG
- [KSPEvent (guiName = "Show Debug Info", active = true, guiActive = true)]
- public void DebugInfo()
- {
- PreTransmit_SetPacketSize ();
- PreTransmit_SetPacketResourceCost ();
-
- string msg = string.Format(
- "'{0}'\n" +
- "_basepacketSize: {1}\n" +
- "packetSize: {2}\n" +
- "_basepacketResourceCost: {3}\n" +
- "packetResourceCost: {4}\n" +
- "maxTransmitDistance: {5}\n" +
- "transmitDistance: {6}\n" +
- "nominalRange: {7}\n" +
- "CanTransmit: {8}\n" +
- "DataRate: {9}\n" +
- "DataResourceCost: {10}\n" +
- "TransmitterScore: {11}",
- this.name,
- this._basepacketSize,
- base.packetSize,
- this._basepacketResourceCost,
- base.packetResourceCost,
- this.ARmaxTransmitDistance,
- this.transmitDistance,
- this.nominalRange,
- this.CanTransmit(),
- this.DataRate,
- this.DataResourceCost,
- ScienceUtil.GetTransmitterScore(this)
- );
- ScreenMessages.PostScreenMessage (new ScreenMessage (msg, 4f, ScreenMessageStyle.UPPER_RIGHT));
- }
- #endif
- }
-}
--- a/AntennaRelay.cs
+++ b/AntennaRelay.cs
@@ -20,6 +20,16 @@
}
/// <summary>
+ /// Gets or sets the nearest relay.
+ /// </summary>
+ /// <value>The nearest relay</value>
+ public IAntennaRelay nearestRelay
+ {
+ get;
+ protected set;
+ }
+
+ /// <summary>
/// Gets the transmit distance.
/// </summary>
/// <value>The transmit distance.</value>
@@ -27,7 +37,7 @@
{
get
{
- IAntennaRelay nearestRelay = this.FindNearestRelay();
+ this.nearestRelay = this.FindNearestRelay();
// If there is no available relay nearby...
if (nearestRelay == null)
@@ -94,8 +104,10 @@
.Where(v => (v.GetWorldPos3D() - vessel.GetWorldPos3D()).magnitude < this.maxTransmitDistance)
.ToList();
- Tools.PostDebugMessage(string.Format(
- "{0}: Vessels in range: {1}",
+ nearbyVessels.RemoveAll(v => v.vesselType == VesselType.Debris);
+
+ Tools.PostDebugMessage(string.Format(
+ "{0}: Non-debris vessels in range: {1}",
this.GetType().Name,
nearbyVessels.Count
));
@@ -141,14 +153,34 @@
nearbyRelays.Sort(new RelayComparer(this.vessel));
// Get the nearest available relay, or null if there are no available relays nearby.
- IAntennaRelay nearestRelay = nearbyRelays.FirstOrDefault();
+ IAntennaRelay _nearestRelay = nearbyRelays.FirstOrDefault();
+
+ // If we have a nearby relay...
+ if (_nearestRelay != null)
+ {
+ // ...but that relay is farther than Kerbin...
+ if (this.DistanceTo(_nearestRelay) > this.DistanceTo(Kerbin))
+ {
+ // ...just use Kerbin.
+ _nearestRelay = null;
+ }
+ }
// Now that we're done with our recursive CanTransmit checks, flag this relay as not checked so it can be
// used next time.
this.relayChecked = false;
// Return the nearest available relay, or null if there are no available relays nearby.
- return nearestRelay;
+ return _nearestRelay;
+ }
+
+ public override string ToString()
+ {
+ return string.Format(
+ "Antenna relay on vessel {0} (range to relay: {1}m)",
+ vessel,
+ Tools.MuMech_ToSI(transmitDistance)
+ );
}
/// <summary>
--- a/Extensions.cs
+++ b/Extensions.cs
@@ -34,7 +34,7 @@
/// </summary>
/// <param name="relay">This <see cref="IAntennaRelay"/></param>
/// <param name="Vessel">A <see cref="Vessel"/></param>
- public static double DistanceTo(this IAntennaRelay relay, Vessel Vessel)
+ public static double DistanceTo(this AntennaRelay relay, Vessel Vessel)
{
return relay.vessel.DistanceTo(Vessel);
}
@@ -44,7 +44,7 @@
/// </summary>
/// <param name="relay">This <see cref="IAntennaRelay"/></param>
/// <param name="body">A <see cref="CelestialBody"/></param>
- public static double DistanceTo(this IAntennaRelay relay, CelestialBody body)
+ public static double DistanceTo(this AntennaRelay relay, CelestialBody body)
{
return relay.vessel.DistanceTo(body);
}
@@ -54,7 +54,7 @@
/// </summary>
/// <param name="relayOne">This <see cref="IAntennaRelay"/></param>
/// <param name="relayTwo">Another <see cref="IAntennaRelay"/></param>
- public static double DistanceTo(this IAntennaRelay relayOne, IAntennaRelay relayTwo)
+ public static double DistanceTo(this AntennaRelay relayOne, IAntennaRelay relayTwo)
{
return relayOne.DistanceTo(relayTwo.vessel);
}
--- /dev/null
+++ b/ModuleLimitedDataTransmitter.cs
@@ -1,1 +1,400 @@
-
+/*
+ * AntennaRange © 2013 toadicus
+ *
+ * AntennaRange provides incentive and requirements for the use of the various antenna parts.
+ * Nominally, the breakdown is as follows:
+ *
+ * Communotron 16 - Suitable up to Kerbalsynchronous Orbit
+ * Comms DTS-M1 - Suitable throughout the Kerbin subsystem
+ * Communotron 88-88 - Suitable throughout the Kerbol system.
+ *
+ * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
+ * copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
+ *
+ * This software uses the ModuleManager library © 2013 ialdabaoth, used under a Creative Commons Attribution-ShareAlike
+ * 3.0 Uported License.
+ *
+ * This software uses code from the MuMechLib library, © 2013 r4m0n, used under the GNU GPL version 3.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using KSP;
+using UnityEngine;
+
+namespace AntennaRange
+{
+ /*
+ * ModuleLimitedDataTransmitter is designed as a drop-in replacement for ModuleDataTransmitter, and handles range-
+ * finding, power scaling, and data scaling for antennas during science transmission. Its functionality varies with
+ * three tunables: nominalRange, maxPowerFactor, and maxDataFactor, set in .cfg files.
+ *
+ * In general, the scaling functions assume the following relation:
+ *
+ * D² α P/R,
+ *
+ * where D is the total transmission distance, P is the transmission power, and R is the data rate.
+ *
+ * */
+
+ /*
+ * Fields
+ * */
+ public class ModuleLimitedDataTransmitter : ModuleDataTransmitter, IScienceDataTransmitter, IAntennaRelay
+ {
+ // Call this an antenna so that you don't have to.
+ [KSPField(isPersistant = true)]
+ protected bool IsAntenna;
+
+ // Stores the packetResourceCost as defined in the .cfg file.
+ protected float _basepacketResourceCost;
+
+ // Stores the packetSize as defined in the .cfg file.
+ protected float _basepacketSize;
+
+ // Every antenna is a relay.
+ protected AntennaRelay relay;
+
+ // Keep track of vessels with transmitters for relay purposes.
+ protected List<Vessel> _relayVessels;
+
+ // Sometimes we will need to communicate errors; this is how we do it.
+ protected ScreenMessage ErrorMsg;
+
+ // Let's make the error text pretty!
+ protected UnityEngine.GUIStyle ErrorStyle;
+
+ // The distance from Kerbin at which the antenna will perform exactly as prescribed by packetResourceCost
+ // and packetSize.
+ [KSPField(isPersistant = false)]
+ public float nominalRange;
+
+ // The multiplier on packetResourceCost that defines the maximum power output of the antenna. When the power
+ // cost exceeds packetResourceCost * maxPowerFactor, transmission will fail.
+ [KSPField(isPersistant = false)]
+ public float maxPowerFactor;
+
+ // The multipler on packetSize that defines the maximum data bandwidth of the antenna.
+ [KSPField(isPersistant = false)]
+ public float maxDataFactor;
+
+ // This field exists to get saved to the persistence file so that relays can be found on unloaded Vessels.
+ [KSPField(isPersistant = true)]
+ protected float ARmaxTransmitDistance;
+
+ /*
+ * Properties
+ * */
+ // Returns the parent vessel housing this antenna.
+ public new Vessel vessel
+ {
+ get
+ {
+ return base.vessel;
+ }
+ }
+
+ // Returns the distance to the nearest relay or Kerbin, whichever is closer.
+ public double transmitDistance
+ {
+ get
+ {
+ return this.relay.transmitDistance;
+ }
+ }
+
+ // Returns the maximum distance this module can transmit
+ public float maxTransmitDistance
+ {
+ get
+ {
+ return this.ARmaxTransmitDistance;
+ }
+ }
+
+ /*
+ * The next two functions overwrite the behavior of the stock functions and do not perform equivalently, except
+ * in that they both return floats. Here's some quick justification:
+ *
+ * The stock implementation of GetTransmitterScore (which I cannot override) is:
+ * Score = (1 + DataResourceCost) / DataRate
+ *
+ * The stock DataRate and DataResourceCost are:
+ * DataRate = packetSize / packetInterval
+ * DataResourceCost = packetResourceCost / packetSize
+ *
+ * So, the resulting score is essentially in terms of joules per byte per baud. Rearranging that a bit, it
+ * could also look like joule-seconds per byte per byte, or newton-meter-seconds per byte per byte. Either way,
+ * that metric is not a very reasonable one.
+ *
+ * Two metrics that might make more sense are joules per byte or joules per byte per second. The latter case
+ * would look like:
+ * DataRate = packetSize / packetInterval
+ * DataResourceCost = packetResourceCost
+ *
+ * The former case, which I've chosen to implement below, is:
+ * DataRate = packetSize
+ * DataResourceCost = packetResourceCost
+ *
+ * So... hopefully that doesn't screw with anything else.
+ * */
+ // Override ModuleDataTransmitter.DataRate to just return packetSize, because we want antennas to be scored in
+ // terms of joules/byte
+ public new float DataRate
+ {
+ get
+ {
+ this.PreTransmit_SetPacketSize();
+ return this.packetSize;
+ }
+ }
+
+ // Override ModuleDataTransmitter.DataResourceCost to just return packetResourceCost, because we want antennas
+ // to be scored in terms of joules/byte
+ public new float DataResourceCost
+ {
+ get
+ {
+ this.PreTransmit_SetPacketResourceCost();
+
+ if (this.CanTransmit())
+ {
+ return this.packetResourceCost;
+ }
+ else
+ {
+ return float.PositiveInfinity;
+ }
+ }
+ }
+
+ // Reports whether this antenna has been checked as a viable relay already in the current FindNearestRelay.
+ public bool relayChecked
+ {
+ get
+ {
+ return this.relay.relayChecked;
+ }
+ }
+
+ /*
+ * Methods
+ * */
+ // Build ALL the objects.
+ public ModuleLimitedDataTransmitter () : base()
+ {
+ // Make the error posting prettier.
+ this.ErrorStyle = new UnityEngine.GUIStyle();
+ this.ErrorStyle.normal.textColor = (UnityEngine.Color)XKCDColors.OrangeRed;
+ this.ErrorStyle.active.textColor = (UnityEngine.Color)XKCDColors.OrangeRed;
+ this.ErrorStyle.hover.textColor = (UnityEngine.Color)XKCDColors.OrangeRed;
+ this.ErrorStyle.fontStyle = UnityEngine.FontStyle.Normal;
+ this.ErrorStyle.padding.top = 32;
+
+ this.ErrorMsg = new ScreenMessage("", 4f, false, ScreenMessageStyle.UPPER_LEFT, this.ErrorStyle);
+ }
+
+ // At least once, when the module starts with a state on the launch pad or later, go find Kerbin.
+ public override void OnStart (StartState state)
+ {
+ base.OnStart (state);
+
+ if (state >= StartState.PreLaunch)
+ {
+ this.relay = new AntennaRelay(vessel);
+ this.relay.maxTransmitDistance = this.maxTransmitDistance;
+ }
+ }
+
+ // When the module loads, fetch the Squad KSPFields from the base. This is necessary in part because
+ // overloading packetSize and packetResourceCostinto a property in ModuleLimitedDataTransmitter didn't
+ // work.
+ public override void OnLoad(ConfigNode node)
+ {
+ this.Fields.Load(node);
+ base.Fields.Load(node);
+
+ this.ARmaxTransmitDistance = Mathf.Sqrt (this.maxPowerFactor) * this.nominalRange;
+ this.IsAntenna = true;
+
+ base.OnLoad (node);
+
+ this._basepacketSize = base.packetSize;
+ this._basepacketResourceCost = base.packetResourceCost;
+
+ Tools.PostDebugMessage(string.Format(
+ "{0} loaded:\n" +
+ "packetSize: {1}\n" +
+ "packetResourceCost: {2}\n" +
+ "nominalRange: {3}\n" +
+ "maxPowerFactor: {4}\n" +
+ "maxDataFactor: {5}\n",
+ this.name,
+ base.packetSize,
+ this._basepacketResourceCost,
+ this.nominalRange,
+ this.maxPowerFactor,
+ this.maxDataFactor
+ ));
+ }
+
+ // Post an error in the communication messages describing the reason transmission has failed. Currently there
+ // is only one reason for this.
+ protected void PostCannotTransmitError()
+ {
+ string ErrorText = string.Format (
+ "Unable to transmit: out of range! Maximum range = {0}m; Current range = {1}m.",
+ Tools.MuMech_ToSI((double)this.ARmaxTransmitDistance, 2),
+ Tools.MuMech_ToSI((double)this.transmitDistance, 2)
+ );
+
+ this.ErrorMsg.message = ErrorText;
+
+ ScreenMessages.PostScreenMessage(this.ErrorMsg, true);
+ }
+
+ // Before transmission, set packetResourceCost. Per above, packet cost increases with the square of
+ // distance. packetResourceCost maxes out at _basepacketResourceCost * maxPowerFactor, at which point
+ // transmission fails (see CanTransmit).
+ protected void PreTransmit_SetPacketResourceCost()
+ {
+ if (this.transmitDistance <= this.nominalRange)
+ {
+ base.packetResourceCost = this._basepacketResourceCost;
+ }
+ else
+ {
+ base.packetResourceCost = this._basepacketResourceCost
+ * (float)Math.Pow (this.transmitDistance / this.nominalRange, 2);
+ }
+ }
+
+ // Before transmission, set packetSize. Per above, packet size increases with the inverse square of
+ // distance. packetSize maxes out at _basepacketSize * maxDataFactor.
+ protected void PreTransmit_SetPacketSize()
+ {
+ if (this.transmitDistance >= this.nominalRange)
+ {
+ base.packetSize = this._basepacketSize;
+ }
+ else
+ {
+ base.packetSize = Math.Min(
+ this._basepacketSize * (float)Math.Pow (this.nominalRange / this.transmitDistance, 2),
+ this._basepacketSize * this.maxDataFactor);
+ }
+ }
+
+ // Override ModuleDataTransmitter.GetInfo to add nominal and maximum range to the VAB description.
+ public override string GetInfo()
+ {
+ string text = base.GetInfo();
+ text += "Nominal Range: " + Tools.MuMech_ToSI((double)this.nominalRange, 2) + "m\n";
+ text += "Maximum Range: " + Tools.MuMech_ToSI((double)this.ARmaxTransmitDistance, 2) + "m\n";
+ return text;
+ }
+
+ // Override ModuleDataTransmitter.CanTransmit to return false when transmission is not possible.
+ public new bool CanTransmit()
+ {
+ return this.relay.CanTransmit();
+ }
+
+ // Override ModuleDataTransmitter.TransmitData to check against CanTransmit and fail out when CanTransmit
+ // returns false.
+ public new void TransmitData(List<ScienceData> dataQueue)
+ {
+ if (this.CanTransmit())
+ {
+ base.TransmitData(dataQueue);
+ }
+ else
+ {
+ this.PostCannotTransmitError ();
+ }
+
+ Tools.PostDebugMessage (
+ "distance: " + this.transmitDistance
+ + " packetSize: " + this.packetSize
+ + " packetResourceCost: " + this.packetResourceCost
+ );
+ }
+
+ // Override ModuleDataTransmitter.StartTransmission to check against CanTransmit and fail out when CanTransmit
+ // returns false.
+ public new void StartTransmission()
+ {
+ PreTransmit_SetPacketSize ();
+ PreTransmit_SetPacketResourceCost ();
+
+ Tools.PostDebugMessage (
+ "distance: " + this.transmitDistance
+ + " packetSize: " + this.packetSize
+ + " packetResourceCost: " + this.packetResourceCost
+ );
+
+ if (this.CanTransmit())
+ {
+ this.ErrorMsg.message = "Beginning transmission ";
+
+ if (this.relay.nearestRelay == null)
+ {
+ this.ErrorMsg.message += "directly to Kerbin.";
+ }
+ else
+ {
+ this.ErrorMsg.message += "via relay " + this.relay.nearestRelay;
+ }
+
+ ScreenMessages.PostScreenMessage(this.ErrorMsg);
+
+ base.StartTransmission();
+ }
+ else
+ {
+ this.PostCannotTransmitError ();
+ }
+ }
+
+ // When debugging, it's nice to have a button that just tells you everything.
+ #if DEBUG
+ [KSPEvent (guiName = "Show Debug Info", active = true, guiActive = true)]
+ public void DebugInfo()
+ {
+ PreTransmit_SetPacketSize ();
+ PreTransmit_SetPacketResourceCost ();
+
+ string msg = string.Format(
+ "'{0}'\n" +
+ "_basepacketSize: {1}\n" +
+ "packetSize: {2}\n" +
+ "_basepacketResourceCost: {3}\n" +
+ "packetResourceCost: {4}\n" +
+ "maxTransmitDistance: {5}\n" +
+ "transmitDistance: {6}\n" +
+ "nominalRange: {7}\n" +
+ "CanTransmit: {8}\n" +
+ "DataRate: {9}\n" +
+ "DataResourceCost: {10}\n" +
+ "TransmitterScore: {11}\n" +
+ "NearestRelay: {12}",
+ this.name,
+ this._basepacketSize,
+ base.packetSize,
+ this._basepacketResourceCost,
+ base.packetResourceCost,
+ this.ARmaxTransmitDistance,
+ this.transmitDistance,
+ this.nominalRange,
+ this.CanTransmit(),
+ this.DataRate,
+ this.DataResourceCost,
+ ScienceUtil.GetTransmitterScore(this),
+ this.relay.FindNearestRelay()
+ );
+ ScreenMessages.PostScreenMessage (new ScreenMessage (msg, 4f, ScreenMessageStyle.UPPER_RIGHT));
+ }
+ #endif
+ }
+}