diff --git a/GameData/RealAntennas/KSPCommunityFixes.cfg b/GameData/RealAntennas/KSPCommunityFixes.cfg
new file mode 100644
index 0000000..f5784d7
--- /dev/null
+++ b/GameData/RealAntennas/KSPCommunityFixes.cfg
@@ -0,0 +1,4 @@
+@KSP_COMMUNITY_FIXES:FOR[RealAntennas]
+{
+ @ModUpgradePipeline = true
+}
diff --git a/src/RealAntennasProject/ModuleRealAntenna.cs b/src/RealAntennasProject/ModuleRealAntenna.cs
index d0fc912..1cca000 100644
--- a/src/RealAntennasProject/ModuleRealAntenna.cs
+++ b/src/RealAntennasProject/ModuleRealAntenna.cs
@@ -6,14 +6,27 @@
namespace RealAntennas
{
+ [Flags]
+ public enum AntennaCondition
+ {
+ Enabled = 1 << 0,
+ Disabled = 1 << 1,
+ PermanentShutdown = 1 << 2,
+ Broken = 1 << 3
+ }
+
public class ModuleRealAntenna : ModuleDataTransmitter, IPartCostModifier, IPartMassModifier
{
private const string PAWGroup = "RealAntennas";
private const string PAWGroupPlanner = "Antenna Planning";
- [KSPField(guiActiveEditor = true, guiName = "Antenna", isPersistant = true, groupName = PAWGroup, groupDisplayName = PAWGroup),
+
+ [KSPField(guiActiveEditor = true, guiName = "Antenna", groupName = PAWGroup, groupDisplayName = PAWGroup),
UI_Toggle(disabledText = "Disabled", enabledText = "Enabled", scene = UI_Scene.Editor)]
public bool _enabled = true;
+ [KSPField(guiActiveEditor = false, guiActive = true, guiName = "Condition", isPersistant = true, groupName = PAWGroup, groupDisplayName = PAWGroup)]
+ public AntennaCondition Condition = AntennaCondition.Enabled;
+
[KSPField(guiActive = true, guiActiveEditor = true, guiName = "Gain", guiUnits = " dBi", guiFormat = "F1", groupName = PAWGroup, groupDisplayName = PAWGroup)]
public float Gain; // Physical directionality, measured in dBi
@@ -136,6 +149,8 @@ public override void OnStart(StartState state)
Fields[nameof(_enabled)].uiControlEditor.onFieldChanged = OnAntennaEnableChange;
(Fields[nameof(TxPower)].uiControlEditor as UI_FloatRange).maxValue = MaxTxPower;
+ _enabled = Condition != AntennaCondition.Disabled;
+
actualMaxTechLevel = maxTechLevel; // maxTechLevel value can come from applied PartUpgrades
int maxLvlFromParams = HighLogic.CurrentGame.Parameters.CustomParams().MaxTechLevel;
if (HighLogic.CurrentGame.Mode != Game.Modes.CAREER)
@@ -164,13 +179,13 @@ public override void OnStart(StartState state)
ConfigBandOptions();
SetupIdlePower();
RecalculateFields();
- SetFieldVisibility(_enabled);
+ SetFieldVisibility();
ApplyTLColoring();
if (HighLogic.LoadedSceneIsFlight)
{
- isEnabled = _enabled;
- if (_enabled)
+ isEnabled = Condition != AntennaCondition.Disabled;
+ if (isEnabled)
GameEvents.OnGameSettingsApplied.Add(ApplyGameSettings);
}
else if (HighLogic.LoadedSceneIsEditor)
@@ -181,10 +196,10 @@ public override void OnStart(StartState state)
private void SetupIdlePower()
{
- if (HighLogic.LoadedSceneIsFlight && _enabled)
+ if (HighLogic.LoadedSceneIsFlight && Condition != AntennaCondition.Disabled)
{
var electricCharge = resHandler.inputResources.First(x => x.id == PartResourceLibrary.ElectricityHashcode);
- electricCharge.rate = (Kerbalism.Kerbalism.KerbalismAssembly is null) ? RAAntenna.IdlePowerDraw : 0;
+ electricCharge.rate = Condition != AntennaCondition.PermanentShutdown && (Kerbalism.Kerbalism.KerbalismAssembly is null) ? RAAntenna.IdlePowerDraw : 0;
string err = "";
resHandler.UpdateModuleResourceInputs(ref err, 1, 1, false, false);
}
@@ -192,7 +207,7 @@ private void SetupIdlePower()
public void FixedUpdate()
{
- if (HighLogic.LoadedSceneIsFlight && _enabled)
+ if (HighLogic.LoadedSceneIsFlight && Condition != AntennaCondition.Disabled && Condition != AntennaCondition.PermanentShutdown)
{
RAAntenna.AMWTemp = (AMWTemp > 0) ? AMWTemp : Convert.ToSingle(part.temperature);
//part.AddThermalFlux(req / Time.fixedDeltaTime);
@@ -231,16 +246,24 @@ private void SetupBaseFields()
if (Fields[nameof(powerText)] is BaseField bf) bf.guiActive = bf.guiActiveEditor = false; // "Antenna Rating"
}
- private void SetFieldVisibility(bool en)
+ private void SetFieldVisibility()
{
- Fields[nameof(Gain)].guiActiveEditor = Fields[nameof(Gain)].guiActive = en;
- Fields[nameof(TxPower)].guiActiveEditor = Fields[nameof(TxPower)].guiActive = en;
- Fields[nameof(TechLevel)].guiActiveEditor = Fields[nameof(TechLevel)].guiActive = en;
- Fields[nameof(RFBand)].guiActiveEditor = Fields[nameof(RFBand)].guiActive = en;
- Fields[nameof(sActivePowerConsumed)].guiActiveEditor = Fields[nameof(sActivePowerConsumed)].guiActive = en;
- Fields[nameof(sIdlePowerConsumed)].guiActiveEditor = Fields[nameof(sIdlePowerConsumed)].guiActive = en;
- Fields[nameof(sAntennaTarget)].guiActive = en;
+ bool showFields = Condition != AntennaCondition.Disabled && Condition != AntennaCondition.PermanentShutdown;
+ Fields[nameof(Gain)].guiActiveEditor = Fields[nameof(Gain)].guiActive = showFields;
+ Fields[nameof(TxPower)].guiActiveEditor = Fields[nameof(TxPower)].guiActive = showFields;
+ Fields[nameof(TechLevel)].guiActiveEditor = Fields[nameof(TechLevel)].guiActive = showFields;
+ Fields[nameof(RFBand)].guiActiveEditor = Fields[nameof(RFBand)].guiActive = showFields;
+ Fields[nameof(sActivePowerConsumed)].guiActiveEditor = Fields[nameof(sActivePowerConsumed)].guiActive = showFields;
+ Fields[nameof(sIdlePowerConsumed)].guiActiveEditor = Fields[nameof(sIdlePowerConsumed)].guiActive = showFields;
+ Fields[nameof(sAntennaTarget)].guiActive = showFields;
Fields[nameof(plannerActiveTxTime)].guiActiveEditor = Kerbalism.Kerbalism.KerbalismAssembly is System.Reflection.Assembly;
+ Actions[nameof(PermanentShutdownAction)].active = showFields;
+ Events[nameof(PermanentShutdownEvent)].guiActive = showFields;
+ Events[nameof(PermanentShutdownEvent)].active = showFields;
+ Events[nameof(AntennaPlanningGUI)].active = showFields;
+ Events[nameof(AntennaPlanningGUI)].guiActive = showFields;
+ Events[nameof(DebugAntenna)].active = showFields;
+ Events[nameof(DebugAntenna)].guiActive = showFields;
}
private void SetupUICallbacks()
@@ -263,7 +286,12 @@ private void UpdateMaxTechLevelInUI()
}
private void OnPlannerActiveTxTimeChanged(BaseField field, object obj) => RecalculatePlannerECConsumption();
- private void OnAntennaEnableChange(BaseField field, object obj) { SetFieldVisibility(_enabled); RecalculatePlannerECConsumption(); }
+ private void OnAntennaEnableChange(BaseField field, object obj)
+ {
+ Condition = _enabled ? AntennaCondition.Enabled : AntennaCondition.Disabled;
+ SetFieldVisibility();
+ RecalculatePlannerECConsumption();
+ }
private void OnRFBandChange(BaseField f, object obj) => RecalculateFields();
private void OnTxPowerChange(BaseField f, object obj) => RecalculateFields();
private void OnTechLevelChange(BaseField f, object obj) // obj is the OLD value
@@ -277,6 +305,29 @@ private void OnTechLevelChange(BaseField f, object obj) // obj is the OLD va
private void OnTechLevelChangeSymmetry(BaseField f, object obj) => ConfigBandOptions();
+ [KSPEvent(guiActive = true, guiActiveEditor = false, guiName = "Disable antenna permanently", groupName = PAWGroup)]
+ public void PermanentShutdownEvent()
+ {
+ var options = new DialogGUIBase[] {
+ new DialogGUIButton("Yes", () => PermanentShutdownAction(null)),
+ new DialogGUIButton("No", () => {})
+ };
+ var dialog = new MultiOptionDialog("ConfirmDisableAntenna", "Are you sure you want to permanently disable the antenna? Doing this will prevent it from consuming power but the operation is irreversible.", "Disable antenna", HighLogic.UISkin, 300, options);
+ PopupDialog.SpawnPopupDialog(dialog, true, HighLogic.UISkin);
+ }
+
+ [KSPAction("Disable antenna permanently")]
+ public void PermanentShutdownAction(KSPActionParam _)
+ {
+ _enabled = false;
+ Condition = AntennaCondition.PermanentShutdown;
+ SetFieldVisibility();
+ SetupIdlePower();
+ GameEvents.onVesselWasModified.Fire(vessel); // Need to notify RACommNetVessel about disabling antennas
+ RACommNetScenario scen = RACommNetScenario.Instance as RACommNetScenario;
+ scen?.Network?.ResetNetwork();
+ }
+
private void ApplyGameSettings()
{
StockRateModifier = HighLogic.CurrentGame.Parameters.CustomParams().StockRateModifier;
@@ -343,7 +394,7 @@ public override string GetInfo()
return res;
}
- public override bool CanComm() => base.CanComm() && (!Deployable || Deployed);
+ public override bool CanComm() => Condition == AntennaCondition.Enabled && (!Deployable || Deployed) && base.CanComm();
public override string ToString() => RAAntenna.ToString();
@@ -419,9 +470,9 @@ private IEnumerator StockScienceFixer()
#region Cost and Mass Modifiers
public float GetModuleCost(float defaultCost, ModifierStagingSituation sit) =>
- _enabled ? RAAntenna.TechLevelInfo.BaseCost + (RAAntenna.TechLevelInfo.CostPerWatt * RATools.LinearScale(TxPower)/1000) : 0;
+ Condition != AntennaCondition.Disabled ? RAAntenna.TechLevelInfo.BaseCost + (RAAntenna.TechLevelInfo.CostPerWatt * RATools.LinearScale(TxPower)/1000) : 0;
public float GetModuleMass(float defaultMass, ModifierStagingSituation sit) =>
- _enabled && applyMassModifier ? (RAAntenna.TechLevelInfo.BaseMass + (RAAntenna.TechLevelInfo.MassPerWatt * RATools.LinearScale(TxPower) / 1000)) / 1000 : 0;
+ Condition != AntennaCondition.Disabled && applyMassModifier ? (RAAntenna.TechLevelInfo.BaseMass + (RAAntenna.TechLevelInfo.MassPerWatt * RATools.LinearScale(TxPower) / 1000)) / 1000 : 0;
public ModifierChangeWhen GetModuleCostChangeWhen() => ModifierChangeWhen.FIXED;
public ModifierChangeWhen GetModuleMassChangeWhen() => ModifierChangeWhen.FIXED;
#endregion
@@ -435,8 +486,9 @@ public string PlannerUpdate(List> resources, Celest
}
private void RecalculatePlannerECConsumption()
{
+ bool consumesPower = Condition != AntennaCondition.Disabled && Condition != AntennaCondition.PermanentShutdown;
// RAAntenna.IdlePowerDraw is in kW (ec/s), PowerDrawLinear is in mW
- double ec = _enabled ? RAAntenna.IdlePowerDraw + (RAAntenna.PowerDrawLinear * 1e-6 * plannerActiveTxTime) : 0;
+ double ec = consumesPower ? RAAntenna.IdlePowerDraw + (RAAntenna.PowerDrawLinear * 1e-6 * plannerActiveTxTime) : 0;
plannerECConsumption = new KeyValuePair("ElectricCharge", -ec);
}
@@ -455,7 +507,7 @@ public virtual bool Validate(out string validationError, out bool canBeResolved,
costToResolve = 0;
techToResolve = string.Empty;
- if (!_enabled || techLevel <= actualMaxTechLevel) return true;
+ if (Condition == AntennaCondition.Disabled || techLevel <= actualMaxTechLevel) return true;
PartUpgradeHandler.Upgrade upgd = GetUpgradeForTL(techLevel);
if (PartUpgradeManager.Handler.IsAvailableToUnlock(upgd.name))
diff --git a/src/RealAntennasProject/Properties/AssemblyInfo.cs b/src/RealAntennasProject/Properties/AssemblyInfo.cs
index 38988fc..b0ec8f3 100644
--- a/src/RealAntennasProject/Properties/AssemblyInfo.cs
+++ b/src/RealAntennasProject/Properties/AssemblyInfo.cs
@@ -32,7 +32,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.4.0.0")]
+[assembly: AssemblyVersion("2.6.0.0")]
#if CIBUILD
[assembly: AssemblyFileVersion("@MAJOR@.@MINOR@.@PATCH@.@BUILD@")]
[assembly: KSPAssembly("RealAntennas", @MAJOR@, @MINOR@)]
diff --git a/src/RealAntennasProject/RACommNetVessel.cs b/src/RealAntennasProject/RACommNetVessel.cs
index 322dab3..b08150c 100644
--- a/src/RealAntennasProject/RACommNetVessel.cs
+++ b/src/RealAntennasProject/RACommNetVessel.cs
@@ -175,7 +175,7 @@ protected List DiscoverAntennas()
{
foreach (ModuleRealAntenna ant in Vessel.FindPartModulesImplementing().ToList())
{
- if (ant._enabled)
+ if (ant.Condition == AntennaCondition.Enabled)
{
ant.RAAntenna.ParentNode = Comm;
if (DeployedLoaded(ant.part)) antennaList.Add(ant.RAAntenna);
@@ -192,7 +192,10 @@ protected List DiscoverAntennas()
foreach (ProtoPartModuleSnapshot snap in part.modules.Where(x => x.moduleName == ModuleRealAntenna.ModuleName))
{
bool _enabled = true;
- snap.moduleValues.TryGetValue(nameof(ModuleRealAntenna._enabled), ref _enabled);
+ string sState = null;
+ if (snap.moduleValues.TryGetValue(nameof(ModuleRealAntenna.Condition), ref sState))
+ _enabled = sState == AntennaCondition.Enabled.ToString();
+
// Doesn't get the correct PartModule if multiple, but the only impact is the name, which defaults to the part anyway.
if (_enabled && part.partInfo.partPrefab.FindModuleImplementing() is ModuleRealAntenna mra && mra.CanCommUnloaded(snap))
{
diff --git a/src/RealAntennasProject/RealAntennas.csproj b/src/RealAntennasProject/RealAntennas.csproj
index 2822697..e19f7cb 100644
--- a/src/RealAntennasProject/RealAntennas.csproj
+++ b/src/RealAntennasProject/RealAntennas.csproj
@@ -88,6 +88,7 @@
+
diff --git a/src/RealAntennasProject/UpgradeScripts/v2_6_AntennaState.cs b/src/RealAntennasProject/UpgradeScripts/v2_6_AntennaState.cs
new file mode 100644
index 0000000..8558b15
--- /dev/null
+++ b/src/RealAntennasProject/UpgradeScripts/v2_6_AntennaState.cs
@@ -0,0 +1,65 @@
+using SaveUpgradePipeline;
+using System;
+
+namespace RealAntennas.UpgradeScripts
+{
+ [UpgradeModule(LoadContext.SFS | LoadContext.Craft, sfsNodeUrl = "GAME/FLIGHTSTATE/VESSEL/PART", craftNodeUrl = "PART")]
+ public class v2_6_AntennaState : UpgradeScript
+ {
+ public override string Name => "RealAntennas Antenna Condition upgrader";
+ public override string Description => "Update crafts to use new condition enum";
+ public override Version EarliestCompatibleVersion => new Version(1, 0, 0);
+ public override Version TargetVersion => new Version(2, 6, 0);
+
+ public override TestResult OnTest(ConfigNode node, LoadContext loadContext, ref string nodeName)
+ {
+ nodeName = NodeUtil.GetPartNodeNameValue(node, loadContext);
+ if (node.GetNode("MODULE", "name", nameof(ModuleRealAntenna)) is ConfigNode mecNode)
+ return TestResult.Upgradeable;
+ return TestResult.Pass;
+ }
+
+ public override void OnUpgrade(ConfigNode node, LoadContext loadContext, ConfigNode parentNode)
+ {
+ var pmNode = node.GetNode("MODULE", "name", nameof(ModuleRealAntenna));
+ var v = pmNode.GetValue("_enabled");
+ var newState = string.Equals(v, "false", StringComparison.OrdinalIgnoreCase) ? AntennaCondition.Disabled : AntennaCondition.Enabled;
+ pmNode.AddValue(nameof(ModuleRealAntenna.Condition), newState.ToString());
+ pmNode.RemoveValue("_enabled");
+ }
+ }
+
+ public class v2_6_AntennaState_KCTBase : v2_6_AntennaState
+ {
+ public override string Name { get => $"{base.Name} KCT-{nodeUrlSFS}"; }
+ public override TestResult OnTest(ConfigNode node, LoadContext loadContext, ref string nodeName) =>
+ loadContext == LoadContext.Craft ? TestResult.Pass : base.OnTest(node, loadContext, ref nodeName);
+ }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/VABList/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT1 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/SPHList/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT2 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/VABWarehouse/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT3 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/SPHWarehouse/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT4 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/VABPlans/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT5 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/SPHPlans/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT6 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/LaunchComplex/BuildList/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT7 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/LaunchComplex/Warehouse/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT8 : v2_6_AntennaState_KCTBase { }
+
+ [UpgradeModule(LoadContext.SFS, sfsNodeUrl = "GAME/SCENARIO/KSC/LaunchComplex/Plans/KCTVessel/ShipNode/PART")]
+ public class v2_6_AntennaState_KCT9 : v2_6_AntennaState_KCTBase { }
+}