예제 #1
0
        /// <summary> get the stock ExperimentSituation for our ScienceSituation value </summary>
        // Note: any modification in this should be reflected in ValidateSituationBitMask()
        public static ScienceSituation ToValidStockSituation(this ScienceSituation situation)
        {
            switch (situation)
            {
            case ScienceSituation.SrfLanded:   return(ScienceSituation.SrfLanded);

            case ScienceSituation.SrfSplashed: return(ScienceSituation.SrfSplashed);

            case ScienceSituation.FlyingLow:   return(ScienceSituation.FlyingLow);

            case ScienceSituation.FlyingHigh:  return(ScienceSituation.FlyingHigh);

            case ScienceSituation.InSpaceLow:  return(ScienceSituation.InSpaceLow);

            case ScienceSituation.InSpaceHigh: return(ScienceSituation.InSpaceHigh);

            case ScienceSituation.Surface:     return(ScienceSituation.SrfLanded);

            case ScienceSituation.Flying:      return(ScienceSituation.FlyingHigh);

            case ScienceSituation.Space:
            case ScienceSituation.BodyGlobal:
            default:                           return(ScienceSituation.InSpaceLow);
            }
        }
예제 #2
0
            public void RemoveSubject(ExperimentInfo expInfo, int bodyIndex, ScienceSituation scienceSituation, int biomeIndex, SubjectData subjectData)
            {
                BodiesSituationsBiomesSubject bodiesSituationsBiomesSubject;

                if (!TryGetValue(expInfo, out bodiesSituationsBiomesSubject))
                {
                    return;
                }

                SituationsBiomesSubject situationsBiomesSubject;

                if (!bodiesSituationsBiomesSubject.TryGetValue(bodyIndex, out situationsBiomesSubject))
                {
                    return;
                }

                BiomesSubject biomesSubject;

                if (!situationsBiomesSubject.TryGetValue(scienceSituation, out biomesSubject))
                {
                    return;
                }

                List <SubjectData> subjectDataList;

                if (!biomesSubject.TryGetValue(biomeIndex, out subjectDataList))
                {
                    return;
                }

                subjectDataList.Remove(subjectData);
            }
예제 #3
0
        public static bool IsAvailableOnBody(this ScienceSituation situation, CelestialBody body)
        {
            switch (situation)
            {
            case ScienceSituation.SrfLanded:
            case ScienceSituation.Surface:
                if (!body.hasSolidSurface)
                {
                    return(false);
                }
                break;

            case ScienceSituation.SrfSplashed:
                if (!body.ocean || !body.hasSolidSurface)
                {
                    return(false);
                }
                break;

            case ScienceSituation.FlyingLow:
            case ScienceSituation.FlyingHigh:
            case ScienceSituation.Flying:
                if (!body.atmosphere)
                {
                    return(false);
                }
                break;

            case ScienceSituation.None:
                return(false);
            }
            return(true);
        }
예제 #4
0
        public static string Serialize(this ScienceSituation situation)
        {
            switch (situation)
            {
            case ScienceSituation.SrfLanded:     return("SrfLanded");

            case ScienceSituation.SrfSplashed:   return("SrfSplashed");

            case ScienceSituation.FlyingLow:     return("FlyingLow");

            case ScienceSituation.FlyingHigh:    return("FlyingHigh");

            case ScienceSituation.InSpaceLow:    return("InSpaceLow");

            case ScienceSituation.InSpaceHigh:   return("InSpaceHigh");

            case ScienceSituation.Surface:       return("Surface");

            case ScienceSituation.Flying:        return("Flying");

            case ScienceSituation.Space:         return("Space");

            case ScienceSituation.BodyGlobal:    return("BodyGlobal");

            default:                             return("None");
            }
        }
예제 #5
0
            public void AddSubject(int bodyIndex, ScienceSituation scienceSituation, int biomeIndex, SubjectData subjectData)
            {
                SituationsBiomesSubjects situationsBiomesSubjects;

                if (!TryGetValue(bodyIndex, out situationsBiomesSubjects))
                {
                    situationsBiomesSubjects = new SituationsBiomesSubjects();
                    Add(bodyIndex, situationsBiomesSubjects);
                }

                BiomesSubjects biomesSubjects;

                if (!situationsBiomesSubjects.TryGetValue(scienceSituation, out biomesSubjects))
                {
                    biomesSubjects = new BiomesSubjects();
                    situationsBiomesSubjects.Add(scienceSituation, biomesSubjects);
                }

                List <SubjectData> subjects;

                if (!biomesSubjects.TryGetValue(biomeIndex, out subjects))
                {
                    subjects = new List <SubjectData>();
                    biomesSubjects.Add(biomeIndex, subjects);
                }

                if (subjectData != null)
                {
                    subjects.Add(subjectData);
                }
            }
예제 #6
0
        public static uint BitValue(this ScienceSituation situation)
        {
            switch (situation)
            {
            case ScienceSituation.None:          return(0);

            case ScienceSituation.SrfLanded:     return(1);                        // 1 << 0

            case ScienceSituation.SrfSplashed:   return(2);                        // 1 << 1

            case ScienceSituation.FlyingLow:     return(4);                        // 1 << 2

            case ScienceSituation.FlyingHigh:    return(8);                        // 1 << 3

            case ScienceSituation.InSpaceLow:    return(16);                       // 1 << 4

            case ScienceSituation.InSpaceHigh:   return(32);                       // 1 << 5

            case ScienceSituation.Surface:       return(2048);                     // 1 << 11

            case ScienceSituation.Flying:        return(4096);                     // 1 << 12

            case ScienceSituation.Space:         return(8192);                     // 1 << 13

            case ScienceSituation.BodyGlobal:    return(16384);                    // 1 << 14

            default:                             return(0);
            }
        }
예제 #7
0
        public static string Title(this ScienceSituation situation)
        {
            switch (situation)
            {
            case ScienceSituation.None:          return(Local.Situation_None);                   //"none"

            case ScienceSituation.SrfLanded:     return(Local.Situation_Landed);                 //"landed"

            case ScienceSituation.SrfSplashed:   return(Local.Situation_Splashed);               //"splashed"

            case ScienceSituation.FlyingLow:     return(Local.Situation_Flyinglow);              //"flying low"

            case ScienceSituation.FlyingHigh:    return(Local.Situation_Flyinghigh);             //"flying high"

            case ScienceSituation.InSpaceLow:    return(Local.Situation_Spacelow);               //"space low"

            case ScienceSituation.InSpaceHigh:   return(Local.Situation_SpaceHigh);              //"space high"

            case ScienceSituation.Surface:       return(Local.Situation_Surface);                //"surface"

            case ScienceSituation.Flying:        return(Local.Situation_Flying);                 //"flying"

            case ScienceSituation.Space:         return(Local.Situation_Space);                  //"space"

            case ScienceSituation.BodyGlobal:    return(Local.Situation_BodyGlobal);             //"global"

            default:                             return(Local.Situation_None);                   //"none"
            }
        }
예제 #8
0
            public void RemoveSubject(int bodyIndex, ScienceSituation scienceSituation, int biomeIndex, SubjectData subjectData)
            {
                SituationsBiomesSubjects situationsBiomesSubjects;

                if (!TryGetValue(bodyIndex, out situationsBiomesSubjects))
                {
                    return;
                }

                BiomesSubjects biomesSubjects;

                if (!situationsBiomesSubjects.TryGetValue(scienceSituation, out biomesSubjects))
                {
                    return;
                }

                List <SubjectData> subjects;

                if (!biomesSubjects.TryGetValue(biomeIndex, out subjects))
                {
                    return;
                }

                subjects.Remove(subjectData);
            }
예제 #9
0
        public Situation GetExperimentSituation(ExperimentInfo expInfo)
        {
            ScienceSituation expSituation = ScienceSituation.None;

            foreach (ScienceSituation situation in situations)
            {
                if (situation.IsAvailableForExperiment(expInfo))
                {
                    expSituation = situation;
                    break;
                }
            }

            int expBiomeIndex = biomeIndex;

            if (expSituation.IsVirtualBiomesRelevantForExperiment(expInfo))
            {
                foreach (VirtualBiome virtualBiome in virtualBiomes)
                {
                    if (expInfo.VirtualBiomes.Contains(virtualBiome))
                    {
                        expBiomeIndex = (int)virtualBiome;
                        break;
                    }
                }
            }

            return(new Situation(body.flightGlobalsIndex, expSituation, expBiomeIndex));
        }
예제 #10
0
        public static int FieldsToId(int bodyIndex, ScienceSituation situation, int biomeIndex = -1)
        {
            if (biomeIndex < 0)
            {
                biomeIndex = agnosticBiomeIndex;
            }

            return(((byte)biomeIndex << 8 | (byte)situation) << 16 | (ushort)bodyIndex);
        }
예제 #11
0
        public static int GetBiomeAgnosticIdForExperiment(int situationId, ExperimentInfo expInfo)
        {
            ScienceSituation sit = (ScienceSituation)(byte)(situationId >> 16);

            if (!sit.IsBiomesRelevantForExperiment(expInfo))
            {
                return(situationId | (agnosticBiomeIndex << 24));
            }
            return(situationId);
        }
예제 #12
0
 private static void SetSituationBitInMask(ref uint mask, ScienceSituation situation, bool value)
 {
     if (value)
     {
         mask = (uint)((int)mask | (1 << (int)situation));
     }
     else
     {
         mask = (uint)((int)mask & ~(1 << (int)situation));
     }
 }
예제 #13
0
 public string GetTitleForExperiment(ExperimentInfo expInfo)
 {
     if (ScienceSituation.IsBiomesRelevantForExperiment(expInfo))
     {
         return(Lib.BuildString(BodyTitle, " ", ScienceSituationTitle, " ", BiomeTitle));
     }
     else
     {
         return(Lib.BuildString(BodyTitle, " ", ScienceSituationTitle));
     }
 }
예제 #14
0
 public string GetStockIdForExperiment(ExperimentInfo expInfo)
 {
     if (ScienceSituation.IsBiomesRelevantForExperiment(expInfo))
     {
         return(Lib.BuildString(BodyName, StockScienceSituationName, BiomeName));
     }
     else
     {
         return(Lib.BuildString(BodyName, StockScienceSituationName));
     }
 }
예제 #15
0
        public Situation(int bodyIndex, ScienceSituation situation, int biomeIndex = -1)
        {
            ScienceSituation = situation;
            Body             = FlightGlobals.Bodies[bodyIndex];

            if (biomeIndex >= 0)
            {
                if (biomeIndex >= ScienceSituationUtils.minVirtualBiome)
                {
                    VirtualBiome = (VirtualBiome)biomeIndex;
                }
                else if (Body.BiomeMap != null)
                {
                    Biome = Body.BiomeMap.Attributes[biomeIndex];
                }
            }

            Id = FieldsToId(bodyIndex, situation, biomeIndex);
        }
예제 #16
0
            public void AddSubject(ExperimentInfo expInfo, int bodyIndex, ScienceSituation scienceSituation, int biomeIndex, SubjectData subjectData)
            {
                BodiesSituationsBiomesSubject bodiesSituationsBiomesSubject;

                if (!TryGetValue(expInfo, out bodiesSituationsBiomesSubject))
                {
                    bodiesSituationsBiomesSubject = new BodiesSituationsBiomesSubject();
                    Add(expInfo, bodiesSituationsBiomesSubject);
                }

                SituationsBiomesSubject situationsBiomesSubject;

                if (!bodiesSituationsBiomesSubject.TryGetValue(bodyIndex, out situationsBiomesSubject))
                {
                    situationsBiomesSubject = new SituationsBiomesSubject();
                    bodiesSituationsBiomesSubject.Add(bodyIndex, situationsBiomesSubject);
                }

                BiomesSubject biomesSubject;

                if (!situationsBiomesSubject.TryGetValue(scienceSituation, out biomesSubject))
                {
                    biomesSubject = new BiomesSubject();
                    situationsBiomesSubject.Add(scienceSituation, biomesSubject);
                }

                List <SubjectData> subjectDataList;

                if (!biomesSubject.TryGetValue(biomeIndex, out subjectDataList))
                {
                    subjectDataList = new List <SubjectData>();
                    biomesSubject.Add(biomeIndex, subjectDataList);
                }

                if (subjectData != null)
                {
                    subjectDataList.Add(subjectData);
                }
            }
예제 #17
0
        public static float BodyMultiplier(this ScienceSituation situation, CelestialBody body)
        {
            float result = 0f;

            switch (situation)
            {
            case ScienceSituation.Surface:
            case ScienceSituation.SrfLanded:
                result = body.scienceValues.LandedDataValue; break;

            case ScienceSituation.SrfSplashed:
                result = body.scienceValues.SplashedDataValue; break;

            case ScienceSituation.FlyingLow:
                result = body.scienceValues.FlyingLowDataValue; break;

            case ScienceSituation.Flying:
            case ScienceSituation.FlyingHigh:
                result = body.scienceValues.FlyingHighDataValue; break;

            case ScienceSituation.BodyGlobal:
            case ScienceSituation.Space:
            case ScienceSituation.InSpaceLow:
                result = body.scienceValues.InSpaceLowDataValue; break;

            case ScienceSituation.InSpaceHigh:
                result = body.scienceValues.InSpaceHighDataValue; break;
            }

            if (result == 0f)
            {
                Lib.Log("Science: invalid/unknown situation " + situation.ToString(), Lib.LogLevel.Error);
                return(1f);                // returning 0 will result in NaN values
            }
            return(result);
        }
예제 #18
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);
        }
예제 #19
0
 public static bool IsVirtualBiomesRelevantForExperiment(this ScienceSituation situation, ExperimentInfo experiment)
 {
     return((experiment.VirtualBiomeMask & situation.BitValue()) != 0);
 }
예제 #20
0
 private static bool MaskHasSituation(uint mask, ScienceSituation situation)
 {
     return((mask & situation.BitValue()) != 0);
 }
        public ExperimentInfo(ScienceExperiment stockDef, ConfigNode expInfoNode)
        {
            // if we have a custom "KERBALISM_EXPERIMENT" definition for the experiment, load it, else just use an empty node to avoid nullrefs
            if (expInfoNode == null)
            {
                expInfoNode = new ConfigNode();
            }

            this.stockDef = stockDef;
            ExperimentId  = stockDef.id;

            // We have some custom handling for breaking ground ROC experiments
            IsROC = ExperimentId.StartsWith("ROCScience");

            if (IsROC)
            {
                Title = "ROC: " + stockDef.experimentTitle;                     // group ROC together in the science archive (sorted by Title)
            }
            else
            {
                Title = stockDef.experimentTitle;
            }

            // A new bool field was added in 1.7 for serenity : applyScienceScale
            // if not specified, the default is `true`, which is the case for all non-serenity science defs
            // serenity ground experiments and ROCs have applyScienceScale = false.
            // for ground experiment, baseValue = science generated per hour
            // for ROC experiments, it doesn't change anything because they are all configured with baseValue = scienceCap
            if (this.stockDef.applyScienceScale)
            {
                DataSize = this.stockDef.baseValue * this.stockDef.dataScale;
            }
            else
            {
                DataSize = this.stockDef.scienceCap * this.stockDef.dataScale;
            }

            // load the included experiments ids in a string array, we will populate the list after
            // all ExperimentInfos are created. (can't do it here as they may not exist yet)
            includedExperimentsId = expInfoNode.GetValues("IncludeExperiment");

            UnlockResourceSurvey = Lib.ConfigValue(expInfoNode, "UnlockResourceSurvey", false);
            SampleMass           = Lib.ConfigValue(expInfoNode, "SampleMass", 0.0);
            IsSample             = SampleMass > 0.0;
            if (IsSample)
            {
                // make sure we don't produce NaN values down the line because of odd/wrong configs
                if (DataSize <= 0.0)
                {
                    Lib.Log(ExperimentId + " has DataSize=" + DataSize + ", your configuration is broken!", Lib.LogLevel.Warning);
                    DataSize = 1.0;
                }
                MassPerMB = SampleMass / DataSize;
            }
            else
            {
                MassPerMB = 0.0;
            }

            // Patch stock science def restrictions as BodyAllowed/BodyNotAllowed restrictions
            if (!(expInfoNode.HasValue("BodyAllowed") || expInfoNode.HasValue("BodyNotAllowed")))
            {
                if (IsROC)
                {
                    // Parse the ROC definition name to find which body it's available on
                    // This rely on the ROC definitions having the body name in the ExperimentId
                    foreach (CelestialBody body in FlightGlobals.Bodies)
                    {
                        if (ExperimentId.IndexOf(body.name, StringComparison.OrdinalIgnoreCase) != -1)
                        {
                            expInfoNode.AddValue("BodyAllowed", body.name);
                            break;
                        }
                    }
                }

                // parse the stock atmosphere restrictions into our own
                if (stockDef.requireAtmosphere)
                {
                    expInfoNode.AddValue("BodyAllowed", "Atmospheric");
                }
                else if (stockDef.requireNoAtmosphere)
                {
                    expInfoNode.AddValue("BodyNotAllowed", "Atmospheric");
                }
            }

            ExpBodyConditions = new BodyConditions(expInfoNode);

            foreach (string virtualBiomeStr in expInfoNode.GetValues("VirtualBiome"))
            {
                if (Enum.IsDefined(typeof(VirtualBiome), virtualBiomeStr))
                {
                    VirtualBiomes.Add((VirtualBiome)Enum.Parse(typeof(VirtualBiome), virtualBiomeStr));
                }
                else
                {
                    Lib.Log("Experiment definition `{0}` has unknown VirtualBiome={1}", Lib.LogLevel.Warning, ExperimentId, virtualBiomeStr);
                }
            }

            IgnoreBodyRestrictions = Lib.ConfigValue(expInfoNode, "IgnoreBodyRestrictions", false);

            uint situationMask    = 0;
            uint biomeMask        = 0;
            uint virtualBiomeMask = 0;

            // if defined, override stock situation / biome mask
            if (expInfoNode.HasValue("Situation"))
            {
                foreach (string situation in expInfoNode.GetValues("Situation"))
                {
                    string[] sitAtBiome = situation.Split(new char[] { '@' }, StringSplitOptions.RemoveEmptyEntries);
                    if (sitAtBiome.Length == 0 || sitAtBiome.Length > 2)
                    {
                        continue;
                    }

                    ScienceSituation scienceSituation = ScienceSituationUtils.ScienceSituationDeserialize(sitAtBiome[0]);

                    if (scienceSituation != ScienceSituation.None)
                    {
                        situationMask += scienceSituation.BitValue();

                        if (sitAtBiome.Length == 2)
                        {
                            if (sitAtBiome[1].Equals("Biomes", StringComparison.OrdinalIgnoreCase))
                            {
                                biomeMask += scienceSituation.BitValue();
                            }
                            else if (sitAtBiome[1].Equals("VirtualBiomes", StringComparison.OrdinalIgnoreCase) && VirtualBiomes.Count > 0)
                            {
                                virtualBiomeMask += scienceSituation.BitValue();
                            }
                        }
                    }
                    else
                    {
                        Lib.Log("Experiment definition `{0}` has unknown situation : `{1}`", Lib.LogLevel.Warning, ExperimentId, sitAtBiome[0]);
                    }
                }
            }
            else
            {
                situationMask = stockDef.situationMask;
                biomeMask     = stockDef.biomeMask;
            }

            if (situationMask == 0)
            {
                Lib.Log("Experiment definition `{0}` : `0` situationMask is unsupported, patching to `BodyGlobal`", Lib.LogLevel.Message, ExperimentId);
                situationMask = ScienceSituation.BodyGlobal.BitValue();
                HasDBSubjects = false;
            }
            else
            {
                HasDBSubjects = !Lib.ConfigValue(expInfoNode, "IsGeneratingSubjects", false);
            }

            string error;
            uint   stockSituationMask;
            uint   stockBiomeMask;

            if (!ScienceSituationUtils.ValidateSituationBitMask(ref situationMask, biomeMask, out stockSituationMask, out stockBiomeMask, out error))
            {
                Lib.Log("Experiment definition `{0}` is incorrect :\n{1}", Lib.LogLevel.Error, ExperimentId, error);
            }

            SituationMask          = situationMask;
            BiomeMask              = biomeMask;
            VirtualBiomeMask       = virtualBiomeMask;
            stockDef.situationMask = stockSituationMask;
            stockDef.biomeMask     = stockBiomeMask;
        }
예제 #22
0
 public static bool IsAvailableForExperiment(this ScienceSituation situation, ExperimentInfo experiment)
 {
     return((experiment.SituationMask & situation.BitValue()) != 0);
 }