Beispiel #1
0
        /// <summary> return the subject information for the given experiment and situation, or null if the situation isn't available. </summary>
        public static SubjectData GetSubjectData(ExperimentInfo expInfo, Situation situation)
        {
            int situationId;

            if (!situation.ScienceSituation.IsBiomesRelevantForExperiment(expInfo))
            {
                situationId = situation.GetBiomeAgnosticId();
            }
            else
            {
                situationId = situation.Id;
            }

            SubjectData subjectData;

            if (!subjectByExpThenSituationId[expInfo].TryGetValue(situationId, out subjectData))
            {
                return(null);
            }

            return(subjectData);
        }
Beispiel #2
0
        /// <summary>
        /// Create our SubjectData by parsing the stock "experiment@situation" subject id string.
        /// Used for asteroid samples, for compatibility with RnD archive data of removed mods and for converting stock ScienceData into SubjectData
        /// </summary>
        public static SubjectData GetSubjectDataFromStockId(string stockSubjectId, ScienceSubject RnDSubject = null)
        {
            SubjectData subjectData = null;

            if (unknownSubjectDatas.TryGetValue(stockSubjectId, out subjectData))
            {
                return(subjectData);
            }

            string[] expAndSit = stockSubjectId.Split(new char[] { '@' }, StringSplitOptions.RemoveEmptyEntries);

            if (expAndSit.Length != 2)
            {
                Lib.Log("Could not parse the SubjectData from subjectId '" + stockSubjectId + "' : bad format");
                return(null);
            }

            // the recovery experiment subject are created in ResearchAndDevelopment.reverseEngineerRecoveredVessel, called on the vessel recovery event
            // it use a non-standard situation system ("body" + a situation enum "RecoverySituations"). We ignore those.
            if (expAndSit[0] == "recovery")
            {
                return(null);
            }

            ExperimentInfo expInfo = GetExperimentInfo(expAndSit[0]);

            if (expInfo == null)
            {
                Lib.Log("Could not parse the SubjectData from subjectId '" + stockSubjectId + "' : the experiment id '" + expAndSit[0] + "' doesn't exists");
                return(null);
            }

            // for subject ids created with the ResearchAndDevelopment.GetExperimentSubject overload that take a "sourceUId" string,
            // the sourceUId is added to the situation after a "_"
            // in stock this seems to be used only for asteroids, and I don't think any mod use it.
            string extraSituationInfo = string.Empty;

            if (expAndSit[1].Contains("_"))
            {
                string[] sitAndAsteroid = expAndSit[1].Split('_');
                // remove
                expAndSit[1] = sitAndAsteroid[0];
                // asteroid are saved as "part.partInfo.name + part.flightID", and the part name always end with a randomly generated "AAA-000" string
                extraSituationInfo = Regex.Match(sitAndAsteroid[1], ".*?-[0-9][0-9][0-9]").Value;
                // if no match, just use the unmodified string
                if (extraSituationInfo == string.Empty)
                {
                    extraSituationInfo = sitAndAsteroid[1];
                }
            }

            string[] bodyAndBiome = expAndSit[1].Split(ScienceSituationUtils.validSituationsStrings, StringSplitOptions.RemoveEmptyEntries);
            string   situation;

            if (bodyAndBiome.Length == 1)
            {
                situation = expAndSit[1].Substring(bodyAndBiome[0].Length);
            }
            else if (bodyAndBiome.Length == 2)
            {
                situation = expAndSit[1].Substring(bodyAndBiome[0].Length, expAndSit[1].Length - bodyAndBiome[0].Length - bodyAndBiome[1].Length);
            }
            else
            {
                Lib.Log("Could not parse the SubjectData from subjectId '" + stockSubjectId + "' : the situation doesn't exists");
                return(null);
            }

            CelestialBody subjectBody = null;

            foreach (CelestialBody body in FlightGlobals.Bodies)
            {
                if (body.name == bodyAndBiome[0])
                {
                    subjectBody = body;
                    break;
                }
            }

            if (subjectBody == null)
            {
                // TODO : DMOS asteroid experiments are doing : "magScan@AsteroidInSpaceLowCarbonaceous7051371", those subjects will be discarded entirely here
                // because the body "Asteroid" doesn't exists, consequently it's impossible to create the Situation object.
                // To handle that, maybe we could implement a derived class "UnknownSituation" from Situation that can handle a completely random subject format
                Lib.Log("Could not parse the SubjectData from subjectId '" + stockSubjectId + "' : the body '" + bodyAndBiome[0] + "' doesn't exist");
                return(null);
            }

            ScienceSituation scienceSituation = ScienceSituationUtils.ScienceSituationDeserialize(situation);

            int biomeIndex = -1;

            if (bodyAndBiome.Length == 2 && ScienceSituationUtils.IsBodyBiomesRelevantForExperiment(scienceSituation, expInfo) && subjectBody.BiomeMap != null)
            {
                for (int i = 0; i < subjectBody.BiomeMap.Attributes.Length; i++)
                {
                    // Note : a stock subject has its spaces in the biome name removed but prior versions of kerbalism didn't do that,
                    // so we try to fix it, in order not to create duplicates in the RnD archives.

                    // TODO : also, we need to remove the "reentry" subjects, as stock is failing to parse them, altough this is in a try/catch block and handled gracefully.
                    string sanitizedBiome = bodyAndBiome[1].Replace(" ", string.Empty);
                    if (RnDSubject != null && extraSituationInfo == string.Empty && sanitizedBiome != bodyAndBiome[1])
                    {
                        string correctedSubjectId = expAndSit[0] + "@" + bodyAndBiome[0] + situation + sanitizedBiome;
                        RnDSubject.id = correctedSubjectId;

                        Dictionary <string, ScienceSubject> stockSubjects = Lib.ReflectionValue <Dictionary <string, ScienceSubject> >(ResearchAndDevelopment.Instance, "scienceSubjects");
                        if (stockSubjects.Remove(stockSubjectId) && !stockSubjects.ContainsKey(correctedSubjectId))
                        {
                            stockSubjects.Add(correctedSubjectId, RnDSubject);
                        }

                        Lib.Log("RnD subject load : misformatted subject '" + stockSubjectId + "' was corrected to '" + correctedSubjectId + "'");
                    }

                    if (subjectBody.BiomeMap.Attributes[i].name.Replace(" ", string.Empty).Equals(sanitizedBiome, StringComparison.OrdinalIgnoreCase))
                    {
                        biomeIndex = i;
                        break;
                    }
                }
            }

            int       bodyIndex       = subjectBody.flightGlobalsIndex;
            Situation vesselSituation = new Situation(bodyIndex, scienceSituation, biomeIndex);

            // if the subject is a "doable" subject, we should have it in the DB.
            if (extraSituationInfo == string.Empty)
            {
                subjectData = GetSubjectData(expInfo, vesselSituation);
            }

            // else create the subjectdata. this can happen either because :
            // - it's a subject using the stock "extra id" system (asteroid samples)
            // - the subject was created in RnD prior to an experiment definition config change
            // - it was created by a mod that does things in a non-stock way (ex : DMOS anomaly scans uses the anomaly name as biomes)
            if (subjectData == null)
            {
                if (bodyAndBiome.Length == 2 && bodyAndBiome[1] != string.Empty && string.IsNullOrEmpty(extraSituationInfo))
                {
                    extraSituationInfo = bodyAndBiome[1];
                }

                UnknownSubjectData unknownSubjectData = new UnknownSubjectData(expInfo, vesselSituation, stockSubjectId, RnDSubject, extraSituationInfo);
                subjectData = unknownSubjectData;
                unknownSubjectDatas.Add(stockSubjectId, unknownSubjectData);
                expBodiesSituationsBiomesSubject.AddSubject(subjectData.ExpInfo, bodyIndex, scienceSituation, biomeIndex, subjectData);
            }

            return(subjectData);
        }
Beispiel #3
0
        public static void Load(ConfigNode node)
        {
            // RnD subjects don't exists in sandbox
            if (!Science.GameHasRnD)
            {
                // load sandbox science subjects
                sandboxSubjects.Clear();
                if (node.HasNode("sandboxScienceSubjects"))
                {
                    foreach (var subjectNode in node.GetNode("sandboxScienceSubjects").GetNodes())
                    {
                        ScienceSubject subject = new ScienceSubject(subjectNode);
                        sandboxSubjects.Add(subject.id, subject);
                    }
                }
            }
            else
            {
                // Load API subjects (require RnD)
                subjectsReceivedBuffer.Clear();
                subjectsReceivedValueBuffer.Clear();
                ConfigNode APISubjects = new ConfigNode();
                if (node.TryGetNode("APISubjects", ref APISubjects))
                {
                    foreach (ConfigNode subjectNode in APISubjects.GetNodes("Subject"))
                    {
                        string         subjectId = Lib.ConfigValue(subjectNode, "subjectId", string.Empty);
                        ScienceSubject subject   = ResearchAndDevelopment.GetSubjectByID(subjectId);
                        if (subject == null)
                        {
                            Lib.Log($"Warning : API subject '{subjectId}' not found in ResearchAndDevelopment");
                            continue;
                        }
                        subjectsReceivedBuffer.Add(subject);
                        subjectsReceivedValueBuffer.Add(Lib.ConfigValue(subjectNode, "science", 0.0));
                    }
                }
            }

            // load uncredited science (transmission buffer)
            uncreditedScience = Lib.ConfigValue(node, "uncreditedScience", 0.0);

            // Rebuild the list of persisted subjects
            persistedSubjects.Clear();
            foreach (ExperimentInfo expInfo in experiments.Values)
            {
                foreach (SubjectData subjectData in subjectByExpThenSituationId[expInfo].Values)
                {
                    subjectData.CheckRnD();
                    subjectData.ClearDataCollectedInFlight();
                }
            }

            // load science subjects persisted data
            if (node.HasNode("subjectData"))
            {
                foreach (var subjectNode in node.GetNode("subjectData").GetNodes())
                {
                    string      integerSubjectId = DB.From_safe_key(subjectNode.name);
                    SubjectData subjectData      = GetSubjectData(integerSubjectId);
                    if (subjectData != null)
                    {
                        subjectData.Load(subjectNode);
                    }
                }
            }

            //if (ResearchAndDevelopment.Instance == null)
            //	Lib.Log("ERROR : ResearchAndDevelopment.Instance is null on subjects load !");

            // remove unknown subjects from the database
            foreach (SubjectData subjectData in unknownSubjectDatas.Values)
            {
                int bodyIndex;
                int scienceSituation;
                int biomeIndex;

                Situation.IdToFields(subjectData.Situation.Id, out bodyIndex, out scienceSituation, out biomeIndex);

                expBodiesSituationsBiomesSubject.RemoveSubject(subjectData.ExpInfo, bodyIndex, (ScienceSituation)scienceSituation, biomeIndex, subjectData);
            }

            // clear the list
            unknownSubjectDatas.Clear();


            // find them again
            IEnumerable <ScienceSubject> stockSubjects;

            if (Science.GameHasRnD)
            {
                stockSubjects = ResearchAndDevelopment.GetSubjects();
            }
            else
            {
                stockSubjects = sandboxSubjects.Values;
            }

            foreach (ScienceSubject stockSubject in stockSubjects)
            {
                if (!knownStockSubjectsId.Contains(stockSubject.id))
                {
                    GetSubjectDataFromStockId(stockSubject.id, stockSubject);
                }
            }
        }
Beispiel #4
0
        public static void Init()
        {
            Lib.Log("ScienceDB init started");
            int    subjectCount = 0;
            double totalScience = 0.0;

            // get our extra defintions
            ConfigNode[] expDefNodes = GameDatabase.Instance.GetConfigNodes("EXPERIMENT_DEFINITION");

            // create our subject database
            // Note : GetExperimentIDs will force the creation of all ScienceExperiment objects,
            // no matter if the RnD instance is null or not because the ScienceExperiment dictionary is static.
            foreach (string experimentId in ResearchAndDevelopment.GetExperimentIDs())
            {
                if (experimentId == "recovery")
                {
                    continue;
                }

                ConfigNode kerbalismExpNode = null;
                foreach (ConfigNode expDefNode in expDefNodes)
                {
                    string id = string.Empty;
                    if (expDefNode.TryGetValue("id", ref id) && id == experimentId)
                    {
                        kerbalismExpNode = expDefNode.GetNode("KERBALISM_EXPERIMENT");                         // return null if not found
                        break;
                    }
                }

                ScienceExperiment stockDef = ResearchAndDevelopment.GetExperiment(experimentId);
                if (stockDef == null)
                {
                    Lib.Log("ScienceExperiment is null for experiment Id=" + experimentId + ", skipping...", Lib.LogLevel.Warning);
                    continue;
                }

                ExperimentInfo expInfo = new ExperimentInfo(stockDef, kerbalismExpNode);
                if (!experiments.ContainsKey(experimentId))
                {
                    experiments.Add(experimentId, expInfo);
                }
                if (!subjectByExpThenSituationId.ContainsKey(expInfo))
                {
                    subjectByExpThenSituationId.Add(expInfo, new Dictionary <int, SubjectData>());
                }

                for (int bodyIndex = 0; bodyIndex < FlightGlobals.Bodies.Count; bodyIndex++)
                {
                    CelestialBody body = FlightGlobals.Bodies[bodyIndex];

                    if (!expInfo.IgnoreBodyRestrictions && !expInfo.ExpBodyConditions.IsBodyAllowed(body))
                    {
                        continue;
                    }

                    // ScienceSituationUtils.validSituations is all situations in the enum, apart from the "None" value
                    foreach (ScienceSituation scienceSituation in ScienceSituationUtils.validSituations)
                    {
                        // test the ScienceExperiment situation mask
                        if (!scienceSituation.IsAvailableForExperiment(expInfo))
                        {
                            continue;
                        }

                        // don't add impossible body / situation combinations
                        if (!expInfo.IgnoreBodyRestrictions && !scienceSituation.IsAvailableOnBody(body))
                        {
                            continue;
                        }

                        // virtual biomes always have priority over normal biomes :
                        if (scienceSituation.IsVirtualBiomesRelevantForExperiment(expInfo))
                        {
                            foreach (VirtualBiome virtualBiome in expInfo.VirtualBiomes)
                            {
                                if (!virtualBiome.IsAvailableOnBody(body))
                                {
                                    continue;
                                }

                                SubjectData subjectData = null;
                                if (expInfo.HasDBSubjects)
                                {
                                    Situation situation = new Situation(bodyIndex, scienceSituation, (int)virtualBiome);
                                    subjectData = new SubjectData(expInfo, situation);
                                    subjectByExpThenSituationId[expInfo].Add(situation.Id, subjectData);
                                    knownStockSubjectsId.Add(subjectData.StockSubjectId);
                                    subjectCount++;
                                    totalScience += subjectData.ScienceMaxValue;
                                }

                                expBodiesSituationsBiomesSubject.AddSubject(expInfo, bodyIndex, scienceSituation, (int)virtualBiome, subjectData);
                            }
                        }
                        // if the biome mask says the situation is biome dependant :
                        else if (scienceSituation.IsBodyBiomesRelevantForExperiment(expInfo) && body.BiomeMap != null && body.BiomeMap.Attributes.Length > 1)
                        {
                            for (int biomeIndex = 0; biomeIndex < body.BiomeMap.Attributes.Length; biomeIndex++)
                            {
                                SubjectData subjectData = null;
                                if (expInfo.HasDBSubjects)
                                {
                                    Situation situation = new Situation(bodyIndex, scienceSituation, biomeIndex);
                                    subjectData = new SubjectData(expInfo, situation);
                                    subjectByExpThenSituationId[expInfo].Add(situation.Id, subjectData);
                                    knownStockSubjectsId.Add(subjectData.StockSubjectId);
                                    subjectCount++;
                                    totalScience += subjectData.ScienceMaxValue;
                                }

                                expBodiesSituationsBiomesSubject.AddSubject(expInfo, bodyIndex, scienceSituation, biomeIndex, subjectData);
                            }
                        }
                        // else generate the global, biome agnostic situation
                        else
                        {
                            SubjectData subjectData = null;
                            if (expInfo.HasDBSubjects)
                            {
                                Situation situation = new Situation(bodyIndex, scienceSituation);
                                subjectData = new SubjectData(expInfo, situation);
                                subjectByExpThenSituationId[expInfo].Add(situation.Id, subjectData);
                                knownStockSubjectsId.Add(subjectData.StockSubjectId);
                                subjectCount++;
                                totalScience += subjectData.ScienceMaxValue;
                            }

                            expBodiesSituationsBiomesSubject.AddSubject(expInfo, bodyIndex, scienceSituation, -1, subjectData);
                        }
                    }
                }
            }

            // cache that call
            IEnumerable <ExperimentInfo> experimentInfosCache = ExperimentInfos;

            // first parse all the IncludeExperiment configs
            foreach (ExperimentInfo experimentInfo in experimentInfosCache)
            {
                experimentInfo.ParseIncludedExperiments();
            }

            // then check for infinite recursion from bad configs
            List <ExperimentInfo> chainedExperiments = new List <ExperimentInfo>();

            foreach (ExperimentInfo experimentInfo in experimentInfosCache)
            {
                chainedExperiments.Clear();
                ExperimentInfo.CheckIncludedExperimentsRecursion(experimentInfo, chainedExperiments);
            }

            // now we are sure all the include experiment chains are valid
            foreach (ExperimentInfo experimentInfo in experimentInfosCache)
            {
                // populate the included experiments chains at the subject level
                foreach (KeyValuePair <int, SubjectData> subjectInfo in subjectByExpThenSituationId[experimentInfo])
                {
                    foreach (ExperimentInfo includedInfo in experimentInfo.IncludedExperiments)
                    {
                        SubjectData subjectToInclude = GetSubjectData(includedInfo, subjectInfo.Key);

                        if (subjectToInclude != null)
                        {
                            subjectInfo.Value.IncludedSubjects.Add(subjectToInclude);
                        }
                    }
                }

                // Get the experiment description that will be shown in the science archive by calling GetInfo() on the first found partmodule using it
                // TODO: this isn't ideal, if there are several modules with different values (ex : data rate, ec rate...), the archive info will use the first found one.
                // Ideally we should revamp the whole handling of that (because it's a mess from the partmodule side too)
                experimentInfo.CompileModuleInfos();
            }

            Lib.Log($"ScienceDB init done : {subjectCount} subjects found, total science points : {totalScience.ToString("F1")}");
        }
Beispiel #5
0
        public static void Init()
        {
            Lib.Log("ScienceDB init started");
            int subjectCount = 0;

            // get our extra defintions
            ConfigNode[] expDefNodes = GameDatabase.Instance.GetConfigNodes("EXPERIMENT_DEFINITION");

            // create our subject database
            // Note : GetExperimentIDs will force the creation of all ScienceExperiment objects,
            // no matter if the RnD instance is null or not because the ScienceExperiment dictionary is static.
            foreach (string experimentId in ResearchAndDevelopment.GetExperimentIDs())
            {
                if (experimentId == "recovery")
                {
                    continue;
                }

                ConfigNode kerbalismExpNode = null;
                foreach (ConfigNode expDefNode in expDefNodes)
                {
                    string id = string.Empty;
                    if (expDefNode.TryGetValue("id", ref id) && id == experimentId)
                    {
                        kerbalismExpNode = expDefNode.GetNode("KERBALISM_EXPERIMENT");                         // return null if not found
                        break;
                    }
                }

                ScienceExperiment stockDef = ResearchAndDevelopment.GetExperiment(experimentId);
                if (stockDef == null)
                {
                    Lib.Log("ScienceExperiment is null for experiment Id=" + experimentId + ", skipping...", Lib.LogLevel.Warning);
                    continue;
                }

                ExperimentInfo expInfo = new ExperimentInfo(stockDef, kerbalismExpNode);
                if (!experiments.ContainsKey(experimentId))
                {
                    experiments.Add(experimentId, expInfo);
                }
                if (!subjectByExpThenSituationId.ContainsKey(expInfo))
                {
                    subjectByExpThenSituationId.Add(expInfo, new Dictionary <int, SubjectData>());
                }

                for (int bodyIndex = 0; bodyIndex < FlightGlobals.Bodies.Count; bodyIndex++)
                {
                    CelestialBody body = FlightGlobals.Bodies[bodyIndex];

                    if (!expInfo.IgnoreBodyRestrictions && !expInfo.ExpBodyConditions.IsBodyAllowed(body))
                    {
                        continue;
                    }

                    // ScienceSituationUtils.validSituations is all situations in the enum, apart from the "None" value
                    foreach (ScienceSituation scienceSituation in ScienceSituationUtils.validSituations)
                    {
                        // test the ScienceExperiment situation mask
                        if (!scienceSituation.IsAvailableForExperiment(expInfo))
                        {
                            continue;
                        }

                        // don't add impossible body / situation combinations
                        if (!expInfo.IgnoreBodyRestrictions && !scienceSituation.IsAvailableOnBody(body))
                        {
                            continue;
                        }

                        // virtual biomes always have priority over normal biomes :
                        if (scienceSituation.IsVirtualBiomesRelevantForExperiment(expInfo))
                        {
                            foreach (VirtualBiome virtualBiome in expInfo.VirtualBiomes)
                            {
                                if (!virtualBiome.IsAvailableOnBody(body))
                                {
                                    continue;
                                }

                                SubjectData subjectData = null;
                                if (expInfo.HasDBSubjects)
                                {
                                    Situation situation = new Situation(bodyIndex, scienceSituation, (int)virtualBiome);
                                    subjectData = new SubjectData(expInfo, situation);
                                    subjectByExpThenSituationId[expInfo].Add(situation.Id, subjectData);
                                    knownStockSubjectsId.Add(subjectData.StockSubjectId);
                                    subjectCount++;
                                }

                                expBodiesSituationsBiomesSubject.AddSubject(expInfo, bodyIndex, scienceSituation, (int)virtualBiome, subjectData);
                                bodiesSituationsBiomesSubjects.AddSubject(bodyIndex, scienceSituation, (int)virtualBiome, subjectData);
                            }
                        }
                        // if the biome mask says the situation is biome dependant :
                        else if (scienceSituation.IsBodyBiomesRelevantForExperiment(expInfo) && body.BiomeMap != null && body.BiomeMap.Attributes.Length > 1)
                        {
                            for (int biomeIndex = 0; biomeIndex < body.BiomeMap.Attributes.Length; biomeIndex++)
                            {
                                SubjectData subjectData = null;
                                if (expInfo.HasDBSubjects)
                                {
                                    Situation situation = new Situation(bodyIndex, scienceSituation, biomeIndex);
                                    subjectData = new SubjectData(expInfo, situation);
                                    subjectByExpThenSituationId[expInfo].Add(situation.Id, subjectData);
                                    knownStockSubjectsId.Add(subjectData.StockSubjectId);
                                    subjectCount++;
                                }

                                expBodiesSituationsBiomesSubject.AddSubject(expInfo, bodyIndex, scienceSituation, biomeIndex, subjectData);
                                bodiesSituationsBiomesSubjects.AddSubject(bodyIndex, scienceSituation, biomeIndex, subjectData);
                            }
                        }
                        // else generate the global, biome agnostic situation
                        else
                        {
                            SubjectData subjectData = null;
                            if (expInfo.HasDBSubjects)
                            {
                                Situation situation = new Situation(bodyIndex, scienceSituation);
                                subjectData = new SubjectData(expInfo, situation);
                                subjectByExpThenSituationId[expInfo].Add(situation.Id, subjectData);
                                knownStockSubjectsId.Add(subjectData.StockSubjectId);
                                subjectCount++;
                            }

                            expBodiesSituationsBiomesSubject.AddSubject(expInfo, bodyIndex, scienceSituation, -1, subjectData);
                            bodiesSituationsBiomesSubjects.AddSubject(bodyIndex, scienceSituation, -1, subjectData);
                        }
                    }
                }
            }

            Lib.Log("ScienceDB init done : " + subjectCount + " subjects found");
        }
Beispiel #6
0
 public SubjectData(ExperimentInfo expInfo, Situation situation)
 {
     ExpInfo   = expInfo;
     Situation = situation;
     Id        = Lib.BuildString(ExpInfo.ExperimentId, "@", Situation.Id.ToString());
 }
Beispiel #7
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>>)
                        }
                    }
                }
            }
        }
Beispiel #8
0
        public static void Load(ConfigNode node)
        {
            // RnD subjects don't exists in sandbox
            if (!Science.GameHasRnD)
            {
                return;
            }

            // load uncredited science (transmission buffer)
            uncreditedScience = Lib.ConfigValue(node, "uncreditedScience", 0.0);

            // Rebuild the list of persisted subjects
            persistedSubjects.Clear();
            foreach (ExperimentInfo expInfo in experiments.Values)
            {
                foreach (SubjectData subjectData in subjectByExpThenSituationId[expInfo].Values)
                {
                    subjectData.CheckRnD();
                    subjectData.ClearDataCollectedInFlight();
                }
            }

            // load science subjects persisted data
            if (node.HasNode("subjectData"))
            {
                foreach (var subjectNode in node.GetNode("subjectData").GetNodes())
                {
                    string      integerSubjectId = DB.From_safe_key(subjectNode.name);
                    SubjectData subjectData      = GetSubjectData(integerSubjectId);
                    if (subjectData != null)
                    {
                        subjectData.Load(subjectNode);
                    }
                }
            }

            if (ResearchAndDevelopment.Instance == null)
            {
                Lib.Log("ERROR : ResearchAndDevelopment.Instance is null on subjects load !");
            }

            // remove unknown subjects from the database
            foreach (SubjectData subjectData in unknownSubjectDatas.Values)
            {
                int bodyIndex;
                int scienceSituation;
                int biomeIndex;

                Situation.IdToFields(subjectData.Situation.Id, out bodyIndex, out scienceSituation, out biomeIndex);

                expBodiesSituationsBiomesSubject.RemoveSubject(subjectData.ExpInfo, bodyIndex, (ScienceSituation)scienceSituation, biomeIndex, subjectData);
                bodiesSituationsBiomesSubjects.RemoveSubject(bodyIndex, (ScienceSituation)scienceSituation, biomeIndex, subjectData);
            }

            // clear the list
            unknownSubjectDatas.Clear();


            // find them again
            foreach (ScienceSubject stockSubject in ResearchAndDevelopment.GetSubjects())
            {
                if (!knownStockSubjectsId.Contains(stockSubject.id))
                {
                    GetSubjectDataFromStockId(stockSubject.id, stockSubject);
                }
            }
        }