diff --git a/plugin_template/localizations/english.csv b/plugin_template/localizations/english.csv index a22989c..8d6f07c 100644 --- a/plugin_template/localizations/english.csv +++ b/plugin_template/localizations/english.csv @@ -2,4 +2,6 @@ Key,Type,Desc,English WMCCModules/Pressurization/Suffocating,Text,,A Kerbal on board ""{0}"" is suffocating! WMCCModules/Pressurization/Killed,Text,,A Kerbal on board ""{0}"" died due to lack of pressurization WMCCModules/Pressurized,Text,,Pressurized -WMCCModules/ServiceCeiling,Text,,Service Ceiling \ No newline at end of file +WMCCModules/ServiceCeiling,Text,,Service Ceiling +WMCCModules/ControlRange,Text,,Control Range +WMCCModules/IsControllable,Text,,Is Controllable? \ No newline at end of file diff --git a/plugin_template/swinfo.json b/plugin_template/swinfo.json index 54f3184..571c99b 100644 --- a/plugin_template/swinfo.json +++ b/plugin_template/swinfo.json @@ -5,7 +5,7 @@ "name": "Where's My Crew Capsule (Modules)", "description": "The modules used for Where's My Crew Capsule", "source": "https://github.com/cheese3660/WMCCModules", - "version": "0.1.0", + "version": "0.2.0", "version_check": "https://raw.githubusercontent.com/cheese3660/WMCCModules/main/plugin_template/swinfo.json", "ksp2_version": { "min": "0.1.5", diff --git a/src/WMCCModules/Modules/Data_ControlRange.cs b/src/WMCCModules/Modules/Data_ControlRange.cs new file mode 100644 index 0000000..be3baea --- /dev/null +++ b/src/WMCCModules/Modules/Data_ControlRange.cs @@ -0,0 +1,30 @@ +using KSP.Game.Science; +using KSP.Sim; +using KSP.Sim.Definitions; + +namespace WMCCModules.Modules; + +public class Data_ControlRange : ModuleData +{ + public override Type ModuleType => typeof(Module_ControlRange); + + + public class ControlRangeDefinition + { + public List RequiredTechs; + public Dictionary> AllowedScienceSituations; + public string LocalizationKey; + } + + [KSPDefinition] + public List ControlRangeDefinitions; + + [KSPState] public Dictionary> UnlockedScienceSituations; + [KSPState] public string CurrentLocalizationKey; + + [LocalizedField("WMCCModules/ControlRange")] [PAMDisplayControl(SortIndex = 1)] + public ModuleProperty ControlRange = new("", true); + + [LocalizedField("WMCCModules/IsControllable")] [PAMDisplayControl(SortIndex = 2)] + public ModuleProperty IsControllable = new(false, true); +} \ No newline at end of file diff --git a/src/WMCCModules/Modules/Module_ControlRange.cs b/src/WMCCModules/Modules/Module_ControlRange.cs new file mode 100644 index 0000000..283a337 --- /dev/null +++ b/src/WMCCModules/Modules/Module_ControlRange.cs @@ -0,0 +1,59 @@ +using I2.Loc; +using KSP.Game; +using KSP.Game.Science; +using KSP.Sim.Definitions; + +namespace WMCCModules.Modules; + +public class Module_ControlRange : PartBehaviourModule +{ + public override Type PartComponentModuleType => typeof(PartComponentModule_ControlRange); + private Data_ControlRange _dataControlRange; + public override void AddDataModules() + { + base.AddDataModules(); + _dataControlRange ??= new Data_ControlRange(); + DataModules.TryAddUnique(_dataControlRange, out _dataControlRange); + } + + public override void OnInitialize() + { + if (PartBackingMode == PartBackingModes.Flight) + { + moduleIsEnabled = true; + _dataControlRange.SetVisible(_dataControlRange.IsControllable, true); + } + else + { + _dataControlRange.SetVisible(_dataControlRange.IsControllable, false); + foreach (var definition in _dataControlRange.ControlRangeDefinitions.Where(ComputeControllability)) + { + foreach (var (key, value) in definition.AllowedScienceSituations) + { + if (_dataControlRange.UnlockedScienceSituations.TryGetValue(key, out var hs)) + { + hs.UnionWith(value); + } + else + { + _dataControlRange.UnlockedScienceSituations.Add(key, new HashSet(value)); + } + + _dataControlRange.CurrentLocalizationKey = definition.LocalizationKey; + } + } + } + + var str = new LocalizedString(_dataControlRange.CurrentLocalizationKey).ToString() ?? + _dataControlRange.CurrentLocalizationKey; + if (str == "") str = _dataControlRange.CurrentLocalizationKey; + _dataControlRange.ControlRange.SetValue(str); + } + + private bool ComputeControllability(Data_ControlRange.ControlRangeDefinition definition) + { + if (!GameManager.Instance.GameModeManager.IsGameModeFeatureEnabled("SciencePoints")) return true; + var scienceManager = GameManager.Instance.Game.ScienceManager; + return definition.RequiredTechs.Count == 0 || definition.RequiredTechs.All(tech => scienceManager.IsNodeUnlocked(tech)); + } +} \ No newline at end of file diff --git a/src/WMCCModules/Modules/Module_Pressurization.cs b/src/WMCCModules/Modules/Module_Pressurization.cs index 169fcd8..dce226c 100644 --- a/src/WMCCModules/Modules/Module_Pressurization.cs +++ b/src/WMCCModules/Modules/Module_Pressurization.cs @@ -12,14 +12,14 @@ public class Module_Pressurization : PartBehaviourModule [SerializeField] protected Data_Pressurization _dataPressurization; public override Type PartComponentModuleType => typeof(PartComponentModule_Pressurization); - protected override void AddDataModules() + public override void AddDataModules() { base.AddDataModules(); _dataPressurization ??= new Data_Pressurization(); DataModules.TryAddUnique(_dataPressurization, out _dataPressurization); } - protected override void OnInitialize() + public override void OnInitialize() { base.OnInitialize(); if (PartBackingMode == PartBackingModes.Flight) diff --git a/src/WMCCModules/Modules/PartComponentModule_ControlRange.cs b/src/WMCCModules/Modules/PartComponentModule_ControlRange.cs new file mode 100644 index 0000000..c0fc1c9 --- /dev/null +++ b/src/WMCCModules/Modules/PartComponentModule_ControlRange.cs @@ -0,0 +1,43 @@ +using KSP.Game.Science; +using KSP.Sim.impl; + +namespace WMCCModules.Modules; + +public class PartComponentModule_ControlRange : PartComponentModule +{ + public override Type PartBehaviourModuleType => typeof(Module_ControlRange); + private ResearchLocation _lastResearchLocation = null; + public Data_ControlRange DataControlRange; + private PartComponentModule_Command _componentModuleCommand; + public override void OnStart(double universalTime) + { + if (!DataModules.TryGetByType(out DataControlRange)) + { + WMCCModulesPlugin.Instance.SWLogger.LogError( + $"Unable to find a Data_ControlRange in the PartComponentModule_ControlRange for {Part.PartName}"); + return; + } + + if (!Part.TryGetModule(out _componentModuleCommand)) + { + WMCCModulesPlugin.Instance.SWLogger.LogError( + $"Unable to find a PartComponentModule_Command for the PartComponentModule_ControlRange on {Part.PartName}"); + } + } + + public override void OnUpdate(double universalTime, double deltaUniversalTime) + { + var vessel = Part.PartOwner.SimulationObject.Vessel; + if (vessel.VesselScienceRegionSituation.ResearchLocation.Equals(_lastResearchLocation)) return; + _lastResearchLocation = vessel.VesselScienceRegionSituation.ResearchLocation; + var isControllable = false; + + if (DataControlRange.UnlockedScienceSituations.TryGetValue(_lastResearchLocation.BodyName, out var hs)) + { + isControllable = hs.Contains(_lastResearchLocation.ScienceSituation); + } + + DataControlRange.IsControllable.SetValue(isControllable); + _componentModuleCommand.UpdateControlStatus(); + } +} \ No newline at end of file diff --git a/src/WMCCModules/Patches/PartComponentModule_CommandPatch.cs b/src/WMCCModules/Patches/PartComponentModule_CommandPatch.cs new file mode 100644 index 0000000..bbf9a98 --- /dev/null +++ b/src/WMCCModules/Patches/PartComponentModule_CommandPatch.cs @@ -0,0 +1,23 @@ +using HarmonyLib; +using KSP.Sim.Definitions; +using KSP.Sim.impl; +using WMCCModules.Modules; + +namespace WMCCModules.Patches; + + +[HarmonyPatch(typeof(PartComponentModule_Command))] +public class PartComponentModule_CommandPatch +{ + [HarmonyPatch(nameof(PartComponentModule_Command.UpdateControlStatus))] + [HarmonyPrefix] + public static bool UpdateControlStatus(PartComponentModule_Command __instance) + { + if (!__instance.Part.Modules.TryGetValue(typeof(PartComponentModule_ControlRange), out var comp)) return true; + var mcr = comp as PartComponentModule_ControlRange; + if (mcr!.DataControlRange.IsControllable.GetValue()) return true; + __instance.dataCommand.controlStatus.SetValue(CommandControlState.NoCommNetConnection); + return false; + + } +} \ No newline at end of file diff --git a/src/WMCCModules/WMCCModules.csproj b/src/WMCCModules/WMCCModules.csproj index d0a6d64..fbb73a2 100644 --- a/src/WMCCModules/WMCCModules.csproj +++ b/src/WMCCModules/WMCCModules.csproj @@ -7,7 +7,7 @@ - +