Beispiel #1
0
 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);
 }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        // 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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        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
        }
Beispiel #8
0
        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();
        }
Beispiel #9
0
        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"));
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
            }
        }
Beispiel #12
0
        // 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));
        }
Beispiel #13
0
        // 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);
            }
        }
Beispiel #15
0
        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);
            }
        }
Beispiel #16
0
        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);
                    }
                }
            }
        }
Beispiel #19
0
        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;
        }
Beispiel #20
0
        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;
            }
        }
Beispiel #21
0
        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>>)
                        }
                    }
                }
            }
        }