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; }
private static bool MaskHasSituation(uint mask, ScienceSituation situation) { return((mask & situation.BitValue()) != 0); }
public static bool IsVirtualBiomesRelevantForExperiment(this ScienceSituation situation, ExperimentInfo experiment) { return((experiment.VirtualBiomeMask & situation.BitValue()) != 0); }
public static bool IsAvailableForExperiment(this ScienceSituation situation, ExperimentInfo experiment) { return((experiment.SituationMask & situation.BitValue()) != 0); }