public override void OnUpdate() { issue = Lib.Proto.GetString(protoModule, "issue"); status = Lib.Proto.GetEnum(protoModule, "status", Experiment.ExpStatus.Stopped); subject = ScienceDB.GetSubjectData(expInfo, Lib.Proto.GetInt(protoModule, "situationId")); scienceValue = Experiment.ScienceValue(subject); }
public static File Load(string integerSubjectId, ConfigNode node) { SubjectData subjectData; string stockSubjectId = Lib.ConfigValue(node, "stockSubjectId", string.Empty); // the stock subject id is stored only if this is an asteroid sample, or a non-standard subject id if (stockSubjectId != string.Empty) { subjectData = ScienceDB.GetSubjectDataFromStockId(stockSubjectId); } else { subjectData = ScienceDB.GetSubjectData(integerSubjectId); } if (subjectData == null) { return(null); } double size = Lib.ConfigValue(node, "size", 0.0); if (double.IsNaN(size)) { Lib.LogStack($"File has a NaN size on load : {subjectData.DebugStateInfo}", Lib.LogLevel.Error); return(null); } string resultText = Lib.ConfigValue(node, "resultText", ""); bool useStockCrediting = Lib.ConfigValue(node, "useStockCrediting", false); return(new File(subjectData, size, useStockCrediting, resultText)); }
// this is a fallback loading method for pre 3.1 / pre build 7212 files saved used the stock subject id public static Sample LoadOldFormat(string stockSubjectId, ConfigNode node) { SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(stockSubjectId); if (subjectData == null) { return(null); } double size = Lib.ConfigValue(node, "size", 0.0); if (double.IsNaN(size)) { Lib.LogStack($"Sample has a NaN size on load : {subjectData.DebugStateInfo}", Lib.LogLevel.Error); return(null); } string resultText = Lib.ConfigValue(node, "resultText", ""); bool useStockCrediting = Lib.ConfigValue(node, "useStockCrediting", false); Sample sample = new Sample(subjectData, size, useStockCrediting, resultText); sample.analyze = Lib.ConfigValue(node, "analyze", false); sample.mass = Lib.ConfigValue(node, "mass", 0.0); return(sample); }
public static Sample Load(string integerSubjectId, ConfigNode node) { SubjectData subjectData; string stockSubjectId = Lib.ConfigValue(node, "stockSubjectId", string.Empty); // the stock subject id is stored only if this is an asteroid sample, or a non-standard subject id if (stockSubjectId != string.Empty) { subjectData = ScienceDB.GetSubjectDataFromStockId(stockSubjectId); } else { subjectData = ScienceDB.GetSubjectData(integerSubjectId); } if (subjectData == null) { return(null); } double size = Lib.ConfigValue(node, "size", 0.0); string resultText = Lib.ConfigValue(node, "resultText", ""); bool useStockCrediting = Lib.ConfigValue(node, "useStockCrediting", false); Sample sample = new Sample(subjectData, size, useStockCrediting, resultText); sample.analyze = Lib.ConfigValue(node, "analyze", false); sample.mass = Lib.ConfigValue(node, "mass", 0.0); return(sample); }
public MetaData(ScienceData data, Part host, float xmitScalar) { // find the part containing the data part = host; // get the vessel vessel = part.vessel; subjectData = ScienceDB.GetSubjectDataFromStockId(data.subjectID); if (subjectData == null) { return; } // get the container module storing the data container = Science.Container(part, subjectData.ExpInfo.ExperimentId); // get the stock experiment module storing the data (if that's the case) experiment = container != null ? container as ModuleScienceExperiment : null; // determine if data is supposed to be removable from the part is_collectable = experiment == null || experiment.dataIsCollectable; // determine if this is a sample (non-transmissible) // - if this is a third-party data container/experiment module, we assume it is transmissible // - stock experiment modules are considered sample if xmit scalar is below a threshold instead is_sample = xmitScalar < Science.maxXmitDataScalarForSample; // determine if the container/experiment can collect the data multiple times // - if this is a third-party data container/experiment, we assume it can collect multiple times is_rerunnable = experiment == null || experiment.rerunnable; }
public override void OnStart(StartState state) { if (Lib.DisableScenario(this)) { return; } if (Lib.IsEditor()) { return; } foreach (var module in part.Modules) { if (module.moduleName == "SCANsat" || module.moduleName == "ModuleSCANresourceScanner") { scanner = module; break; } } if (scanner == null) { return; } sensorType = Lib.ReflectionValue <int>(scanner, "sensorType"); expInfo = ScienceDB.GetExperimentInfo(experimentType); }
static bool Prefix(DeployedScienceExperiment __instance, ref bool __result) { // get private vars ScienceSubject subject = Lib.ReflectionValue <ScienceSubject>(__instance, "subject"); float storedScienceData = Lib.ReflectionValue <float>(__instance, "storedScienceData"); float transmittedScienceData = Lib.ReflectionValue <float>(__instance, "transmittedScienceData"); Vessel ControllerVessel = Lib.ReflectionValue <Vessel>(__instance, "ControllerVessel"); //Lib.Log("SendDataToComms!: " + subject.title); if (__instance.Experiment != null && !(__instance.ExperimentVessel == null) && subject != null && !(__instance.Cluster == null) && __instance.sciencePart.Enabled && !(storedScienceData <= 0f) && __instance.ExperimentSituationValid) { /* if (!__instance.TimeToSendStoredData()) * { * __result = true; * Lib.Log(Lib.BuildString("BREAKING GROUND bailout 1")); * return false; * } */ if (ControllerVessel == null && __instance.Cluster != null) { Lib.ReflectionCall(__instance, "SetControllerVessel"); ControllerVessel = Lib.ReflectionValue <Vessel>(__instance, "ControllerVessel"); } /* * Part control; * FlightGlobals.FindLoadedPart(__instance.Cluster.ControlModulePartId, out control); * if(control == null) { * //Lib.Log("DeployedScienceExperiment: couldn't find control module"); * __result = true; * Lib.Log(Lib.BuildString("BREAKING GROUND bailout 2")); * return false; * } */ List <Drive> drives = Drive.GetDrives(ControllerVessel, false); SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(subject.id); foreach (Drive drive in drives) { //Lib.Log(Lib.BuildString("BREAKING GROUND -- ", subject.id, " | ", storedScienceData.ToString())); if (drive.Record_file(subjectData, storedScienceData, true)) { //Lib.Log("BREAKING GROUND -- file recorded!"); Lib.ReflectionValue <float>(__instance, "transmittedScienceData", transmittedScienceData + storedScienceData); Lib.ReflectionValue <float>(__instance, "storedScienceData", 0f); break; } else { //Lib.Log("BREAKING GROUND -- file NOT recorded!"); __result = true; return(false); } } __result = false; } return(false); // always return false so we don't continue to the original code }
public ProtoExperimentDevice(Experiment prefab, ProtoPartSnapshot protoPart, ProtoPartModuleSnapshot protoModule, Vessel vessel) : base(prefab, protoPart, protoModule) { this.vessel = vessel; expInfo = ScienceDB.GetExperimentInfo(prefab.experiment_id); icon = new DeviceIcon(expInfo.SampleMass > 0f ? Textures.sample_scicolor : Textures.file_scicolor, "open experiment info", () => new ExperimentPopup(vessel, prefab, protoPart.flightID, prefab.part.partInfo.title, protoModule)); sb = new StringBuilder(); OnUpdate(); }
public static void Save(ConfigNode node) { // save version node.AddValue("version", Lib.KerbalismVersion.ToString()); // save unique id node.AddValue("uid", uid); // save kerbals data var kerbals_node = node.AddNode("kerbals"); foreach (var p in kerbals) { p.Value.Save(kerbals_node.AddNode(To_safe_key(p.Key))); } // only persist vessels that exists in KSP own vessel persistence // this prevent creating junk data without going into the mess of using gameevents UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.DB.Save.Vessels"); ConfigNode vesselsNode = node.AddNode("vessels2"); foreach (ProtoVessel pv in HighLogic.CurrentGame.flightState.protoVessels) { if (pv.vesselID == Guid.Empty) { // It seems flags are saved with an empty GUID. skip them. Lib.LogDebug("Skipping VesselData save for vessel with empty GUID :" + pv.vesselName); continue; } VesselData vd = pv.KerbalismData(); ConfigNode vesselNode = vesselsNode.AddNode(pv.vesselID.ToString()); vd.Save(vesselNode); } UnityEngine.Profiling.Profiler.EndSample(); // save the science database ScienceDB.Save(node); // save bodies data var bodies_node = node.AddNode("bodies"); foreach (var p in storms) { p.Value.Save(bodies_node.AddNode(To_safe_key(p.Key))); } // save landmark data landmarks.Save(node.AddNode("landmarks")); // save ui data ui.Save(node.AddNode("ui")); }
static bool Prefix(ModuleComet __instance, ref ScienceExperiment ___experiment) { // Patch only if science is enabled if (!Features.Science) { return(true); } // stock ModuleAsteroid.performSampleExperiment code : get situation and check availablility ExperimentSituations experimentSituation = ScienceUtil.GetExperimentSituation(__instance.vessel); string message = string.Empty; if (!ScienceUtil.RequiredUsageExternalAvailable(__instance.vessel, FlightGlobals.ActiveVessel, (ExperimentUsageReqs)__instance.experimentUsageMask, ___experiment, ref message)) { ScreenMessages.PostScreenMessage("<b><color=orange>" + message + "</color></b>", 6f, ScreenMessageStyle.UPPER_LEFT); return(false); } if (!___experiment.IsAvailableWhile(experimentSituation, __instance.vessel.mainBody)) { ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_230133", ___experiment.experimentTitle), 5f, ScreenMessageStyle.UPPER_CENTER); return(false); } // stock ModuleAsteroid.performSampleExperiment code : create subject ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(___experiment, experimentSituation, __instance.part.partInfo.name + __instance.part.flightID, __instance.part.partInfo.title, __instance.vessel.mainBody, string.Empty, string.Empty); // put the data on the EVA kerbal drive. if (FlightGlobals.ActiveVessel == null) { return(false); } double size = ___experiment.baseValue * ___experiment.dataScale; Drive drive = Drive.SampleDrive(FlightGlobals.ActiveVessel.KerbalismData(), size); if (drive != null) { double mass = size * Settings.AsteroidSampleMassPerMB; SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(subject.id, null, __instance.part.partInfo.title); drive.Record_sample(subjectData, size, mass, true); Message.Post(Lib.BuildString("<b><color=ffffff>", subject.title, "</color></b>\n", (mass * 1000.0).ToString("F1"), "<b><i> Kg of sample stored</i></b>")); } else { Message.Post("Not enough sample storage available"); } // don't call TakeSampleEVAEvent() (this will also prevent the call to ModuleAsteroid.performSampleExperiment) return(false); }
public void DumpData(ScienceData data) { SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(data.subjectID); // remove the data if (data.baseTransmitValue > float.Epsilon || data.transmitBonus > float.Epsilon) { drive.Delete_file(subjectData, data.dataAmount); } else { drive.Delete_sample(subjectData, data.dataAmount); } }
// this is a fallback loading method for pre 3.1 / pre build 7212 files saved used the stock subject id public static File LoadOldFormat(string stockSubjectId, ConfigNode node) { SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(stockSubjectId); if (subjectData == null) { return(null); } double size = Lib.ConfigValue(node, "size", 0.0); string resultText = Lib.ConfigValue(node, "resultText", ""); bool useStockCrediting = Lib.ConfigValue(node, "useStockCrediting", false); return(new File(subjectData, size, useStockCrediting, resultText)); }
// TODO do something about limited capacity... // EVAs returning should get a warning if needed // TODO : this should not be used for EVA boarding, too much information is lost in the conversion public void ReturnData(ScienceData data) { SubjectData subjectData = ScienceDB.GetSubjectDataFromStockId(data.subjectID); if (subjectData == null) { return; } if (data.baseTransmitValue > Science.maxXmitDataScalarForSample || data.transmitBonus > Science.maxXmitDataScalarForSample) { drive.Record_file(subjectData, data.dataAmount); } else { drive.Record_sample(subjectData, data.dataAmount, subjectData.ExpInfo.MassPerMB * data.dataAmount); } }
public void ParseIncludedExperiments() { foreach (string expId in includedExperimentsId) { ExperimentInfo includedInfo = ScienceDB.GetExperimentInfo(expId); if (includedInfo == null) { Lib.Log($"Experiment `{ExperimentId}` define a IncludedExperiment `{expId}`, but that experiment doesn't exist", Lib.LogLevel.Warning); continue; } // early prevent duplicated entries if (includedInfo.ExperimentId == ExperimentId || IncludedExperiments.Contains(includedInfo)) { continue; } IncludedExperiments.Add(includedInfo); } }
public static void Load(ConfigNode node) { // get version (or use current one for new savegames) string versionStr = Lib.ConfigValue(node, "version", Lib.KerbalismVersion.ToString()); // sanitize old saves (pre 3.1) format (X.X.X.X) to new format (X.X) if (versionStr.Split('.').Length > 2) { versionStr = versionStr.Split('.')[0] + "." + versionStr.Split('.')[1]; } version = new Version(versionStr); // if this is an unsupported version, print warning if (version <= new Version(1, 2)) { Lib.Log("loading save from unsupported version " + version); } // get unique id (or generate one for new savegames) uid = Lib.ConfigValue(node, "uid", Lib.RandomInt(int.MaxValue)); // load kerbals data kerbals = new Dictionary <string, KerbalData>(); if (node.HasNode("kerbals")) { foreach (var kerbal_node in node.GetNode("kerbals").GetNodes()) { kerbals.Add(From_safe_key(kerbal_node.name), new KerbalData(kerbal_node)); } } // load the science database, has to be before vessels are loaded ScienceDB.Load(node); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.DB.Load.Vessels"); vessels.Clear(); // flightstate will be null when first creating the game if (HighLogic.CurrentGame.flightState != null) { ConfigNode vesselsNode = node.GetNode("vessels2"); if (vesselsNode == null) { vesselsNode = new ConfigNode(); } // HighLogic.CurrentGame.flightState.protoVessels is what is used by KSP to persist vessels // It is always available and synchronized in OnLoad, no matter the scene, excepted on the first OnLoad in a new game foreach (ProtoVessel pv in HighLogic.CurrentGame.flightState.protoVessels) { if (pv.vesselID == Guid.Empty) { // It seems flags are saved with an empty GUID. skip them. Lib.LogDebug("Skipping VesselData load for vessel with empty GUID :" + pv.vesselName); continue; } VesselData vd = new VesselData(pv, vesselsNode.GetNode(pv.vesselID.ToString())); vessels.Add(pv.vesselID, vd); Lib.LogDebug("VesselData loaded for vessel " + pv.vesselName); } } UnityEngine.Profiling.Profiler.EndSample(); // for compatibility with old saves, convert drives data (it's now saved in PartData) if (node.HasNode("drives")) { Dictionary <uint, PartData> allParts = new Dictionary <uint, PartData>(); foreach (VesselData vesselData in vessels.Values) { foreach (PartData partData in vesselData.PartDatas) { // we had a case of someone having a save with multiple parts having the same flightID // 5 duplicates, all were asteroids. if (!allParts.ContainsKey(partData.FlightId)) { allParts.Add(partData.FlightId, partData); } } } foreach (var drive_node in node.GetNode("drives").GetNodes()) { uint driveId = Lib.Parse.ToUInt(drive_node.name); if (allParts.ContainsKey(driveId)) { allParts[driveId].Drive = new Drive(drive_node); } } } // load bodies data storms = new Dictionary <string, StormData>(); if (node.HasNode("bodies")) { foreach (var body_node in node.GetNode("bodies").GetNodes()) { storms.Add(From_safe_key(body_node.name), new StormData(body_node)); } } // load landmark data if (node.HasNode("landmarks")) { landmarks = new LandmarkData(node.GetNode("landmarks")); } else { landmarks = new LandmarkData(); } // load ui data if (node.HasNode("ui")) { ui = new UIData(node.GetNode("ui")); } else { ui = new UIData(); } // if an old savegame was imported, log some debug info if (version != Lib.KerbalismVersion) { Lib.Log("savegame converted from version " + version + " to " + Lib.KerbalismVersion); } }
public static void BackgroundUpdate(Vessel vessel, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, KerbalismScansat kerbalismScansat, Part part_prefab, VesselData vd, ResourceInfo ec, double elapsed_s) { List <ProtoPartModuleSnapshot> scanners = Cache.VesselObjectsCache <List <ProtoPartModuleSnapshot> >(vessel, "scansat_" + p.flightID); if (scanners == null) { scanners = Lib.FindModules(p, "SCANsat"); if (scanners.Count == 0) { scanners = Lib.FindModules(p, "ModuleSCANresourceScanner"); } Cache.SetVesselObjectsCache(vessel, "scansat_" + p.flightID, scanners); } if (scanners.Count == 0) { return; } var scanner = scanners[0]; bool is_scanning = Lib.Proto.GetBool(scanner, "scanning"); if (is_scanning && kerbalismScansat.ec_rate > double.Epsilon) { ec.Consume(kerbalismScansat.ec_rate * elapsed_s, ResourceBroker.Scanner); } if (!Features.Science) { if (is_scanning && ec.Amount < double.Epsilon) { SCANsat.StopScanner(vessel, scanner, part_prefab); is_scanning = false; // remember disabled scanner vd.scansat_id.Add(p.flightID); // give the user some feedback if (vd.cfg_ec) { Message.Post(Local.Scansat_sensordisabled.Format("<b>" + vessel.vesselName + "</b>")); //Lib.BuildString("SCANsat sensor was disabled on <<1>>) } } else if (vd.scansat_id.Contains(p.flightID)) { // if there is enough ec // note: comparing against amount in previous simulation step // re-enable at 25% EC if (ec.Level > 0.25) { // re-enable the scanner SCANsat.ResumeScanner(vessel, m, part_prefab); is_scanning = true; // give the user some feedback if (vd.cfg_ec) { Message.Post(Local.Scansat_sensorresumed.Format("<b>" + vessel.vesselName + "</b>")); //Lib.BuildString("SCANsat sensor resumed operations on <<1>>) } } } // forget active scanners if (is_scanning) { vd.scansat_id.Remove(p.flightID); } return; } // if(!Feature.Science) string body_name = Lib.Proto.GetString(m, "body_name"); int sensorType = (int)Lib.Proto.GetUInt(m, "sensorType"); double body_coverage = Lib.Proto.GetDouble(m, "body_coverage"); double warp_buffer = Lib.Proto.GetDouble(m, "warp_buffer"); double new_coverage = SCANsat.Coverage(sensorType, vessel.mainBody); if (body_name == vessel.mainBody.name && new_coverage < body_coverage) { // SCANsat sometimes reports a coverage of 0, which is wrong new_coverage = body_coverage; } if (vessel.mainBody.name != body_name) { body_name = vessel.mainBody.name; body_coverage = new_coverage; } else { double coverage_delta = new_coverage - body_coverage; body_coverage = new_coverage; if (is_scanning) { ExperimentInfo expInfo = ScienceDB.GetExperimentInfo(kerbalismScansat.experimentType); SubjectData subject = ScienceDB.GetSubjectData(expInfo, vd.VesselSituations.GetExperimentSituation(expInfo)); if (subject == null) { return; } double size = expInfo.DataSize * coverage_delta / 100.0; // coverage is 0-100% size += warp_buffer; if (size > double.Epsilon) { // store what we can foreach (var d in Drive.GetDrives(vd)) { var available = d.FileCapacityAvailable(); var chunk = Math.Min(size, available); if (!d.Record_file(subject, chunk, true)) { break; } size -= chunk; if (size < double.Epsilon) { break; } } } if (size > double.Epsilon) { // we filled all drives up to the brim but were unable to store everything if (warp_buffer < double.Epsilon) { // warp buffer is empty, so lets store the rest there warp_buffer = size; size = 0; } else { // warp buffer not empty. that's ok if we didn't get new data if (coverage_delta < double.Epsilon) { size = 0; } // else we're scanning too fast. stop. } } // we filled all drives up to the brim but were unable to store everything // cancel scanning and annoy the user if (size > double.Epsilon || ec.Amount < double.Epsilon) { warp_buffer = 0; SCANsat.StopScanner(vessel, scanner, part_prefab); vd.scansat_id.Add(p.flightID); if (vd.cfg_ec) { Message.Post(Local.Scansat_sensordisabled.Format("<b>" + vessel.vesselName + "</b>")); //Lib.BuildString("SCANsat sensor was disabled on <<1>>) } } } else if (vd.scansat_id.Contains(p.flightID)) { if (ec.Level >= 0.25 && (vd.DrivesFreeSpace / vd.DrivesCapacity > 0.9)) { SCANsat.ResumeScanner(vessel, scanner, part_prefab); vd.scansat_id.Remove(p.flightID); if (vd.cfg_ec) { Message.Post(Local.Scansat_sensorresumed.Format("<b>" + vessel.vesselName + "</b>")); //Lib.BuildString("SCANsat sensor resumed operations on <<1>>) } } } } Lib.Proto.Set(m, "warp_buffer", warp_buffer); Lib.Proto.Set(m, "body_coverage", body_coverage); Lib.Proto.Set(m, "body_name", body_name); }
private static void UpdateResearchedFilter() { researchedExpInfos.Clear(); ExperimentInfo asteroidSample = ScienceDB.GetExperimentInfo("asteroidSample"); if (asteroidSample != null) { researchedExpInfos.Add(asteroidSample); } foreach (AvailablePart availablePart in PartLoader.LoadedPartsList) { // EVA kerbals have no tech required if (!string.IsNullOrEmpty(availablePart.TechRequired) && !ResearchAndDevelopment.PartModelPurchased(availablePart)) { continue; } List <Experiment> configureResearchedExperiments = new List <Experiment>(); foreach (PartModule partModule in availablePart.partPrefab.Modules) { if (partModule is Configure configure) { foreach (ConfigureSetup setup in configure.GetUnlockedSetups()) { foreach (ConfigureModule configureModule in setup.modules) { if (configureModule.type == "Experiment") { PartModule configuredModule = configure.Find_module(configureModule); if (configuredModule != null && configuredModule is Experiment configureExperiment) { configureResearchedExperiments.Add(configureExperiment); } } } } } } foreach (PartModule partModule in availablePart.partPrefab.Modules) { if (partModule is Experiment experiment) { if (researchedExpInfos.Contains(experiment.ExpInfo)) { continue; } bool isResearched = false; if (configureResearchedExperiments.Count > 0) { if (configureResearchedExperiments.Contains(experiment)) { isResearched = true; } } else { isResearched = true; } if (isResearched && experiment.Requirements.TestProgressionRequirements()) { researchedExpInfos.Add(experiment.ExpInfo); } } else if (partModule is ModuleScienceExperiment stockExperiment) { ExperimentInfo expInfo = ScienceDB.GetExperimentInfo(stockExperiment.experimentID); if (expInfo != null) { researchedExpInfos.Add(expInfo); } } #if !KSP15_16 else if (partModule is ModuleGroundExperiment groundExp) { ExperimentInfo expInfo = ScienceDB.GetExperimentInfo(groundExp.experimentId); if (expInfo != null) { researchedExpInfos.Add(expInfo); } } #endif } } // ROCs are always researched foreach (ExperimentInfo experimentInfo in ScienceDB.ExperimentInfos) { if (experimentInfo.IsROC) { researchedExpInfos.Add(experimentInfo); } } }
private static void UpdateVesselFilter() { vesselExpInfos.Clear(); bool hasROCScience = false; foreach (Part part in vesselParts) { foreach (PartModule partModule in part.Modules) { if (!partModule.enabled || !partModule.isEnabled) { continue; } if (partModule is Experiment experiment) { vesselExpInfos.Add(experiment.ExpInfo); } else if (partModule is ModuleScienceExperiment stockExperiment) { if (stockExperiment.experimentID == "ROCScience") { hasROCScience = true; } else { ExperimentInfo expInfo = ScienceDB.GetExperimentInfo(stockExperiment.experimentID); if (expInfo != null) { vesselExpInfos.Add(expInfo); } } } #if !KSP15_16 else if (partModule is ModuleInventoryPart inventory) { foreach (string inventoryPartName in inventory.InventoryPartsList) { Part groundPart = PartLoader.getPartInfoByName(inventoryPartName)?.partPrefab; if (groundPart == null) { continue; } foreach (PartModule groundmodule in groundPart.Modules) { if (groundmodule is ModuleGroundExperiment groundExp) { ExperimentInfo expInfo = ScienceDB.GetExperimentInfo(groundExp.experimentId); if (expInfo != null) { vesselExpInfos.Add(expInfo); } } } } } #endif } } if (hasROCScience) { foreach (ExperimentInfo experimentInfo in ScienceDB.ExperimentInfos) { if (experimentInfo.IsROC) { vesselExpInfos.Add(experimentInfo); } } } }
public override void OnLoad(ConfigNode node) { // everything in there will be called only one time : the first time a game is loaded from the main menu if (!IsCoreGameInitDone) { // core game systems Sim.Init(); // find suns (Kopernicus support) Radiation.Init(); // create the radiation fields ScienceDB.Init(); // build the science database (needs Sim.Init() and Radiation.Init() first) Science.Init(); // register the science hijacker // static graphic components LineRenderer.Init(); ParticleRenderer.Init(); Highlighter.Init(); // UI Textures.Init(); // set up the icon textures UI.Init(); // message system, main gui, launcher KsmGui.KsmGuiMasterController.Init(); // setup the new gui framework // part prefabs hacks Profile.SetupPods(); // add supply resources to pods Misc.TweakPartIcons(); // various tweaks to the part icons in the editor // Create KsmGui windows new ScienceArchiveWindow(); // GameEvents callbacks Callbacks = new Callbacks(); IsCoreGameInitDone = true; } // everything in there will be called every time a savegame (or a new game) is loaded from the main menu if (!IsSaveGameInitDone) { Cache.Init(); ResourceCache.Init(); // prepare storm data foreach (CelestialBody body in FlightGlobals.Bodies) { if (Storm.Skip_body(body)) { continue; } Storm_data sd = new Storm_data { body = body }; storm_bodies.Add(sd); } IsSaveGameInitDone = true; } // eveything else will be called on every OnLoad() call : // - save/load // - every scene change // - in various semi-random situations (thanks KSP) // Fix for background IMGUI textures being dropped on scene changes since KSP 1.8 Styles.ReloadBackgroundStyles(); // always clear the caches Cache.Clear(); ResourceCache.Clear(); // deserialize our database UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.DB.Load"); DB.Load(node); UnityEngine.Profiling.Profiler.EndSample(); // I'm smelling the hacky mess in here. Communications.NetworkInitialized = false; Communications.NetworkInitializing = false; // detect if this is a different savegame if (DB.uid != savegame_uid) { // clear caches Message.all_logs.Clear(); // sync main window pos from db UI.Sync(); // remember savegame id savegame_uid = DB.uid; } Kerbalism.gameLoadTime = Time.time; }
void FixedUpdate() { // remove control locks in any case Misc.ClearLocks(); // do nothing if paused if (Lib.IsPaused()) { return; } // convert elapsed time to double only once double fixedDeltaTime = TimeWarp.fixedDeltaTime; // and detect warp blending if (Math.Abs(fixedDeltaTime - elapsed_s) < 0.001) { warp_blending = 0; } else { ++warp_blending; } // update elapsed time elapsed_s = fixedDeltaTime; // store info for oldest unloaded vessel double last_time = 0.0; Guid last_id = Guid.Empty; Vessel last_v = null; VesselData last_vd = null; VesselResources last_resources = null; // credit science at regular interval ScienceDB.CreditScienceBuffers(elapsed_s); foreach (VesselData vd in DB.VesselDatas) { vd.EarlyUpdate(); } // for each vessel foreach (Vessel v in FlightGlobals.Vessels) { // get vessel data VesselData vd = v.KerbalismData(); // update the vessel data validity vd.Update(v); // set locks for active vessel if (v.isActiveVessel) { Misc.SetLocks(v); } // maintain eva dead animation and helmet state if (v.loaded && v.isEVA) { EVA.Update(v); } // keep track of rescue mission kerbals, and gift resources to their vessels on discovery if (v.loaded && vd.is_vessel) { // manage rescue mission mechanics Misc.ManageRescueMission(v); } // do nothing else for invalid vessels if (!vd.IsSimulated) { continue; } // get resource cache VesselResources resources = ResourceCache.Get(v); // if loaded if (v.loaded) { //UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.VesselDataEval"); // update the vessel info vd.Evaluate(false, elapsed_s); //UnityEngine.Profiling.Profiler.EndSample(); // get most used resource ResourceInfo ec = resources.GetResource(v, "ElectricCharge"); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Radiation"); // show belt warnings Radiation.BeltWarnings(v, vd); // update storm data Storm.Update(v, vd, elapsed_s); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Comms"); Communications.Update(v, vd, ec, elapsed_s); UnityEngine.Profiling.Profiler.EndSample(); // Habitat equalization ResourceBalance.Equalizer(v); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Science"); // transmit science data Science.Update(v, vd, ec, elapsed_s); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Profile"); // apply rules Profile.Execute(v, vd, resources, elapsed_s); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Profile"); // part module resource updates vd.ResourceUpdate(resources, elapsed_s); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Resource"); // apply deferred requests resources.Sync(v, vd, elapsed_s); UnityEngine.Profiling.Profiler.EndSample(); // call automation scripts vd.computer.Automate(v, vd, resources); // remove from unloaded data container unloaded.Remove(vd.VesselId); } // if unloaded else { // get unloaded data, or create an empty one Unloaded_data ud; if (!unloaded.TryGetValue(vd.VesselId, out ud)) { ud = new Unloaded_data(); unloaded.Add(vd.VesselId, ud); } // accumulate time ud.time += elapsed_s; // maintain oldest entry if (ud.time > last_time) { last_time = ud.time; last_v = v; last_vd = vd; last_resources = resources; } } } // at most one vessel gets background processing per physics tick : // if there is a vessel that is not the currently loaded vessel, then // we will update the vessel whose most recent background update is the oldest if (last_v != null) { //UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.VesselDataEval"); // update the vessel info (high timewarp speeds reevaluation) last_vd.Evaluate(false, last_time); //UnityEngine.Profiling.Profiler.EndSample(); // get most used resource ResourceInfo last_ec = last_resources.GetResource(last_v, "ElectricCharge"); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Radiation"); // show belt warnings Radiation.BeltWarnings(last_v, last_vd); // update storm data Storm.Update(last_v, last_vd, last_time); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Comms"); Communications.Update(last_v, last_vd, last_ec, last_time); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Profile"); // apply rules Profile.Execute(last_v, last_vd, last_resources, last_time); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Background"); // simulate modules in background Background.Update(last_v, last_vd, last_resources, last_time); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Science"); // transmit science data Science.Update(last_v, last_vd, last_ec, last_time); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Resource"); // apply deferred requests last_resources.Sync(last_v, last_vd, last_time); UnityEngine.Profiling.Profiler.EndSample(); // call automation scripts last_vd.computer.Automate(last_v, last_vd, last_resources); // remove from unloaded data container unloaded.Remove(last_vd.VesselId); } // update storm data for one body per-step if (storm_bodies.Count > 0) { storm_bodies.ForEach(k => k.time += elapsed_s); Storm_data sd = storm_bodies[storm_index]; Storm.Update(sd.body, sd.time); sd.time = 0.0; storm_index = (storm_index + 1) % storm_bodies.Count; } }
public void FixedUpdate() { if (scanner == null) { return; } if (!Features.Science) { return; } IsScanning = SCANsat.IsScanning(scanner); double new_coverage = SCANsat.Coverage(sensorType, vessel.mainBody); if (body_name == vessel.mainBody.name && new_coverage < body_coverage) { // SCANsat sometimes reports a coverage of 0, which is wrong new_coverage = body_coverage; } if (vessel.mainBody.name != body_name) { body_name = vessel.mainBody.name; body_coverage = new_coverage; } else { double coverage_delta = new_coverage - body_coverage; body_coverage = new_coverage; VesselData vd = vessel.KerbalismData(); if (IsScanning) { Situation scanSatSituation = new Situation(vessel.mainBody.flightGlobalsIndex, ScienceSituation.InSpaceHigh); SubjectData subject = ScienceDB.GetSubjectData(expInfo, scanSatSituation); if (subject == null) { return; } double size = expInfo.DataSize * coverage_delta / 100.0; // coverage is 0-100% size += warp_buffer; size = Drive.StoreFile(vessel, subject, size); if (size > double.Epsilon) { // we filled all drives up to the brim but were unable to store everything if (warp_buffer < double.Epsilon) { // warp buffer is empty, so lets store the rest there warp_buffer = size; size = 0; } else { // warp buffer not empty. that's ok if we didn't get new data if (coverage_delta < double.Epsilon) { size = 0; } // else we're scanning too fast. stop. } // cancel scanning and annoy the user if (size > double.Epsilon) { warp_buffer = 0; StopScan(); vd.scansat_id.Add(part.flightID); Message.Post(Lib.Color(Local.Scansat_Scannerhalted, Lib.Kolor.Red, true), Local.Scansat_Scannerhalted_text.Format("<b>" + vessel.vesselName + "</b>")); //"Scanner halted""Scanner halted on <<1>>. No storage left on vessel." } } } else if (vd.scansat_id.Contains(part.flightID)) { if (vd.DrivesFreeSpace / vd.DrivesCapacity > 0.9) // restart when 90% of capacity is available { StartScan(); vd.scansat_id.Remove(part.flightID); if (vd.cfg_ec) { Message.Post(Local.Scansat_sensorresumed.Format("<b>" + vessel.vesselName + "</b>")); //Lib.BuildString("SCANsat sensor resumed operations on <<1>>) } } } } }