public string GetNetworkInfo() { if (!(HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor)) { return("Empty"); } string info = FlightGlobals.GetHomeBody().displayName + " Relay Constellation\n"; homeworldRadius = FlightGlobals.GetHomeBody().Radius; homeworldTopOfAtmo = FlightGlobals.GetHomeBody().atmosphereDepth; double rp = FlightGlobals.GetHomeBody().rotationPeriod; double GM = FlightGlobals.GetHomeBody().gravParameter; double geoAlt = Math.Pow(Math.Pow(rp / (2 * Math.PI), 2) * GM, 1.0 / 3.0) - homeworldRadius; double commPower = 0; //info += "Radius: " + (homeworldRadius / 1000).ToString("n0") + "km" + "\n"; //info += "Atmosphere Height: " + (homeworldTopOfAtmo / 1000).ToString("n0") + "km" + "\n"; // CommNet Math https://wiki.kerbalspaceprogram.com/wiki/CommNet double combStrongestPower = 0; double combSumOfPowers = 0; double combWeightedSumOfPowers = 0; double strongestPower = 0; ICommAntenna strongestAntenna = null; bool thisPartCombinable = false; bool combinableNotStrongest = false; List <ICommAntenna> antennas; if (HighLogic.LoadedSceneIsFlight) { antennas = vessel.FindPartModulesImplementing <ICommAntenna>(); } else { antennas = new List <ICommAntenna>(); foreach (Part p in EditorLogic.fetch.ship.parts) { antennas.AddRange(p.FindModulesImplementing <ICommAntenna>()); } } foreach (ICommAntenna antenna in antennas) { if (antenna.CommType == AntennaType.RELAY) { if (antenna.CommPower > strongestPower) { strongestAntenna = antenna; strongestPower = antenna.CommPower; } if (antenna.CommCombinable) { if (antenna.CommPower > combStrongestPower) { combStrongestPower = antenna.CommPower; } combSumOfPowers += antenna.CommPower; combWeightedSumOfPowers += antenna.CommPower * antenna.CommCombinableExponent; } } } if (combStrongestPower > 0) { double combAvgCombExponent = combWeightedSumOfPowers / combSumOfPowers; commPower = combStrongestPower * Math.Pow(combSumOfPowers / combStrongestPower, combAvgCombExponent); } if (commPower < strongestPower) { combinableNotStrongest = true; commPower = strongestPower; } if (commPower > 0) { // Right triangle // a = 1/2 power // b = homeworld core to midpoint between sats // c = homeworldRadius + sat altitude // double a = commPower / 2 * 0.8042; // 10% signal strength double b = homeworldRadius; double c = Math.Sqrt(Math.Pow(b, 2) + Math.Pow(a, 2)); if (c < homeworldRadius + homeworldTopOfAtmo) { c = homeworldRadius + homeworldTopOfAtmo; b = Math.Sqrt(Math.Pow(a, 2) + Math.Pow(c, 2)); } double angleA = Math.Asin(a / c); int minSats = (int)Math.Ceiling(Math.PI / angleA); double basicPower = 500000 * (homeworldRadius / 600000); // Scaled Communotron 16 info += "\n<b>Min Sats:</b> " + minSats.ToString("n0") + "\n"; info += "<b>Best* Alt:</b> " + FormatAltitudeKM(c - homeworldRadius) + "km\n"; info += "<b>Signal loss to " + FormatAltitudeKM(basicPower) + "K ant:</b> " + FormatAltitudeKM(Math.Sqrt(basicPower * commPower)) + "km\n"; info += "<b>Geosync:</b> " + Math.Round(geoAlt / 1000, 3).ToString("n3") + "km\n\n"; c = homeworldRadius + commPower * 0.8042; angleA = Math.Asin(a / c); int maxSats = (int)Math.Ceiling(Math.PI / angleA); info += "<color=green># Sats: Min / Max Alt / Signal to " + FormatAltitudeKM(basicPower) + "K antenna</color>\n"; for (int i = minSats; i <= maxSats + 1; i++) { //info += "\n"; info += GetNetworkInfoLine(i, commPower, basicPower) + "\n"; } info += "\n<i>*Best alt is the altitude where a constellation member can connect to any other member that is over the horizon.</i>"; } else { info += "No relay antennas found!\n"; info += "commPower: " + commPower.ToString("n") + "\n"; info += "antennas: " + antennas.Count.ToString("n") + "\n"; } return(info); }
/// <summary> /// Read the part data of an unloaded/loaded vessel and store in data structures /// </summary> protected List <CNCAntennaPartInfo> readAntennaData() { List <CNCAntennaPartInfo> antennas = new List <CNCAntennaPartInfo>(); int numParts = (!this.vessel.loaded) ? this.vessel.protoVessel.protoPartSnapshots.Count : this.vessel.Parts.Count; //inspect each part for (int partIndex = 0; partIndex < numParts; partIndex++) { Part thisPart; ProtoPartSnapshot partSnapshot = null; if (this.Vessel.loaded) { thisPart = this.vessel.Parts[partIndex]; } else { partSnapshot = this.vessel.protoVessel.protoPartSnapshots[partIndex]; thisPart = partSnapshot.partInfo.partPrefab; } bool populatedAntennaInfo = false; CNCAntennaPartInfo newAntennaPartInfo = new CNCAntennaPartInfo();; ProtoPartModuleSnapshot partModuleSnapshot = null; //inspect each module of the part for (int moduleIndex = 0; moduleIndex < thisPart.Modules.Count; moduleIndex++) { PartModule thisPartModule = thisPart.Modules[moduleIndex]; if (thisPartModule is CNConstellationAntennaModule) // is it CNConstellationAntennaModule? { if (!this.Vessel.loaded) { partModuleSnapshot = partSnapshot.FindModule(thisPartModule, moduleIndex); newAntennaPartInfo.frequency = short.Parse(partModuleSnapshot.moduleValues.GetValue("Frequency")); string oname = partModuleSnapshot.moduleValues.GetValue("OptionalName"); newAntennaPartInfo.name = (oname.Length == 0) ? partSnapshot.partInfo.title : oname; newAntennaPartInfo.inUse = bool.Parse(partModuleSnapshot.moduleValues.GetValue("InUse")); newAntennaPartInfo.CosAngle = double.Parse(partModuleSnapshot.moduleValues.GetValue("CosAngle")); } else { CNConstellationAntennaModule antennaMod = (CNConstellationAntennaModule)thisPartModule; newAntennaPartInfo.frequency = antennaMod.Frequency; newAntennaPartInfo.name = antennaMod.Name; newAntennaPartInfo.inUse = antennaMod.InUse; } populatedAntennaInfo = true; } else if (thisPartModule is ICommAntenna) // is it ModuleDataTransmitter? { ICommAntenna thisAntenna = thisPartModule as ICommAntenna; if (!this.Vessel.loaded) { partModuleSnapshot = partSnapshot.FindModule(thisPartModule, moduleIndex); } newAntennaPartInfo.antennaPower = (!this.vessel.loaded) ? thisAntenna.CommPowerUnloaded(partModuleSnapshot) : thisAntenna.CommPower; newAntennaPartInfo.antennaCombinable = thisAntenna.CommCombinable; newAntennaPartInfo.antennaCombinableExponent = thisAntenna.CommCombinableExponent; newAntennaPartInfo.antennaType = thisAntenna.CommType; newAntennaPartInfo.partReference = thisPart; //unique ID for part is not available newAntennaPartInfo.partSnapshotReference = partSnapshot; newAntennaPartInfo.canComm = (!this.vessel.loaded) ? thisAntenna.CanCommUnloaded(partModuleSnapshot) : thisAntenna.CanComm(); populatedAntennaInfo = true; } } if (populatedAntennaInfo) // valid info? { antennas.Add(newAntennaPartInfo); CNCLog.Debug("CommNet Vessel '{0}' has antenna '{1}' of {2} and {3} power (w/o range modifier)", this.Vessel.GetName(), newAntennaPartInfo.name, newAntennaPartInfo.frequency, newAntennaPartInfo.antennaPower); } } return(antennas); }
public Antenna_Info(Vessel v) { List <AntennaPartInfo> adaptorsInfoList = new List <AntennaPartInfo>(); int numParts = (!v.loaded) ? v.protoVessel.protoPartSnapshots.Count : v.Parts.Count; for (int partIndex = 0; partIndex < numParts; partIndex++) { Part part; ProtoPartSnapshot protoPart = null; if (v.loaded) { part = v.Parts[partIndex]; } else { protoPart = v.protoVessel.protoPartSnapshots[partIndex]; part = PartLoader.getPartInfoByName(protoPart.partName).partPrefab; } bool hasInfo = false; AntennaPartInfo antennaPartInfo = new AntennaPartInfo(); ProtoPartModuleSnapshot protoPartModule = null; // Inspect each module of the part for (int moduleIndex = 0; moduleIndex < part.Modules.Count; moduleIndex++) { NetworkAdaptor antennaMod = new NetworkAdaptor(); PartModule pModule = part.Modules[moduleIndex]; if (pModule is NetworkAdaptor) { if (v.loaded) { antennaMod = (NetworkAdaptor)pModule; antennaPartInfo.frequency = antennaMod.frequency; antennaPartInfo.ecCost = antennaMod.ecCost; antennaPartInfo.rate = antennaMod.rate; antennaPartInfo.name = part.partInfo.title; } else { ProtoPartModuleSnapshot netAdaptor = FlightGlobals.FindProtoPartByID(protoPart.flightID).FindModule("NetworkAdaptor"); antennaPartInfo.frequency = Lib.Proto.GetShort(netAdaptor, "frequency"); antennaPartInfo.ecCost = Lib.Proto.GetDouble(netAdaptor, "ecCost"); antennaPartInfo.rate = Lib.Proto.GetDouble(netAdaptor, "rate"); antennaPartInfo.name = protoPart.partInfo.title; } hasInfo = true; } else if (pModule is ICommAntenna) { ICommAntenna antenna = pModule as ICommAntenna; // This method only works when v.Loaded, otherwise this brings a wrong deployState ModuleDeployableAntenna anim = part.FindModuleImplementing <ModuleDeployableAntenna>(); // Assume extended if there is no animator if (anim != null) { if (!v.loaded) { // This method works to !v.Loaded ProtoPartModuleSnapshot deployState = FlightGlobals.FindProtoPartByID(protoPart.flightID).FindModule("ModuleDeployableAntenna"); antennaPartInfo.deployState = Lib.KCOMMNET.String_to_DeployState(Lib.Proto.GetString(deployState, "deployState")); } else { antennaPartInfo.deployState = anim.deployState; } } else { antennaPartInfo.deployState = ModuleDeployablePart.DeployState.EXTENDED; } if (!v.loaded) { protoPartModule = protoPart.FindModule(pModule, moduleIndex); } antennaPartInfo.antennaPower = (!v.loaded) ? antenna.CommPowerUnloaded(protoPartModule) : antenna.CommPower; antennaPartInfo.antennaCombinable = antenna.CommCombinable; antennaPartInfo.antennaCombinableExponent = antenna.CommCombinableExponent; antennaPartInfo.antennaType = antenna.CommType; //antennaPartInfo.partReference = part; //antennaPartInfo.partSnapshotReference = protoPart; antennaPartInfo.canComm = (!v.loaded) ? antenna.CanCommUnloaded(protoPartModule) : antenna.CanComm(); hasInfo = true; } } if (hasInfo) { adaptorsInfoList.Add(antennaPartInfo); } } freqSortedList = adaptorsInfoList.OrderBy(a => a.frequency).ToList(); // order by frequency adaptorsSortedList = adaptorsInfoList.OrderBy(a => a.name).ToList(); // order by device name AntennaCalc(freqSortedList); }