Пример #1
0
        public static string TestRequirements(string experiment_id, string requirements, Vessel v)
        {
            CelestialBody body = v.mainBody;
            Vessel_info   vi   = Cache.VesselInfo(v);

            List <string> list = Lib.Tokenize(requirements, ',');

            foreach (string s in list)
            {
                var parts = Lib.Tokenize(s, ':');

                var    condition = parts[0];
                string value     = string.Empty;
                if (parts.Count > 1)
                {
                    value = parts[1];
                }

                bool good = true;
                switch (condition)
                {
                case "OrbitMinInclination": good = Math.Abs(v.orbit.inclination) >= double.Parse(value); break;

                case "OrbitMaxInclination": good = Math.Abs(v.orbit.inclination) <= double.Parse(value); break;

                case "OrbitMinEccentricity": good = v.orbit.eccentricity >= double.Parse(value); break;

                case "OrbitMaxEccentricity": good = v.orbit.eccentricity <= double.Parse(value); break;

                case "OrbitMinArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis >= double.Parse(value); break;

                case "OrbitMaxArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis <= double.Parse(value); break;

                case "TemperatureMin": good = vi.temperature >= double.Parse(value); break;

                case "TemperatureMax": good = vi.temperature <= double.Parse(value); break;

                case "AltitudeMin": good = v.altitude >= double.Parse(value); break;

                case "AltitudeMax": good = v.altitude <= double.Parse(value); break;

                case "RadiationMin": good = vi.radiation >= double.Parse(value); break;

                case "RadiationMax": good = vi.radiation <= double.Parse(value); break;

                case "Microgravity": good = vi.zerog; break;

                case "Body": good = TestBody(v.mainBody.name, value); break;

                case "Shadow": good = vi.sunlight < double.Epsilon; break;

                case "Sunlight": good = vi.sunlight > 0.5; break;

                case "CrewMin": good = vi.crew_count >= int.Parse(value); break;

                case "CrewMax": good = vi.crew_count <= int.Parse(value); break;

                case "CrewCapacityMin": good = vi.crew_capacity >= int.Parse(value); break;

                case "CrewCapacityMax": good = vi.crew_capacity <= int.Parse(value); break;

                case "VolumePerCrewMin": good = vi.volume_per_crew >= double.Parse(value); break;

                case "VolumePerCrewMax": good = vi.volume_per_crew <= double.Parse(value); break;

                case "Greenhouse": good = vi.greenhouses.Count > 0; break;

                case "Surface": good = Lib.Landed(v); break;

                case "Atmosphere": good = body.atmosphere && v.altitude < body.atmosphereDepth; break;

                case "AtmosphereBody": good = body.atmosphere; break;

                case "AtmosphereAltMin": good = body.atmosphere && (v.altitude / body.atmosphereDepth) >= double.Parse(value); break;

                case "AtmosphereAltMax": good = body.atmosphere && (v.altitude / body.atmosphereDepth) <= double.Parse(value); break;

                case "BodyWithAtmosphere": good = body.atmosphere; break;

                case "BodyWithoutAtmosphere": good = !body.atmosphere; break;

                case "SunAngleMin": good = Lib.IsSun(v.mainBody) || Lib.SunBodyAngle(v) >= double.Parse(value); break;

                case "SunAngleMax": good = Lib.IsSun(v.mainBody) || Lib.SunBodyAngle(v) <= double.Parse(value); break;

                case "Vacuum": good = !body.atmosphere || v.altitude > body.atmosphereDepth; break;

                case "Ocean": good = body.ocean && v.altitude < 0.0; break;

                case "PlanetarySpace": good = body.flightGlobalsIndex != 0 && !Lib.Landed(v) && v.altitude > body.atmosphereDepth; break;

                case "AbsoluteZero": good = vi.temperature < 30.0; break;

                case "InnerBelt": good = vi.inner_belt; break;

                case "OuterBelt": good = vi.outer_belt; break;

                case "MagneticBelt": good = vi.inner_belt || vi.outer_belt; break;

                case "Magnetosphere": good = vi.magnetosphere; break;

                case "Thermosphere": good = vi.thermosphere; break;

                case "Exosphere": good = vi.exosphere; break;

                case "InterPlanetary": good = body.flightGlobalsIndex == 0 && !vi.interstellar; break;

                case "InterStellar": good = body.flightGlobalsIndex == 0 && vi.interstellar; break;

                case "SurfaceSpeedMin": good = v.srfSpeed >= double.Parse(value); break;

                case "SurfaceSpeedMax": good = v.srfSpeed <= double.Parse(value); break;

                case "VerticalSpeedMin": good = v.verticalSpeed >= double.Parse(value); break;

                case "VerticalSpeedMax": good = v.verticalSpeed <= double.Parse(value); break;

                case "SpeedMin": good = v.speed >= double.Parse(value); break;

                case "SpeedMax": good = v.speed <= double.Parse(value); break;

                case "DynamicPressureMin": good = v.dynamicPressurekPa >= double.Parse(value); break;

                case "DynamicPressureMax": good = v.dynamicPressurekPa <= double.Parse(value); break;

                case "StaticPressureMin": good = v.staticPressurekPa >= double.Parse(value); break;

                case "StaticPressureMax": good = v.staticPressurekPa <= double.Parse(value); break;

                case "AtmDensityMin": good = v.atmDensity >= double.Parse(value); break;

                case "AtmDensityMax": good = v.atmDensity <= double.Parse(value); break;

                case "AltAboveGroundMin": good = v.heightFromTerrain >= double.Parse(value); break;

                case "AltAboveGroundMax": good = v.heightFromTerrain <= double.Parse(value); break;

                case "Part": good = Lib.HasPart(v, value); break;

                case "Module": good = Lib.FindModules(v.protoVessel, value).Count > 0; break;

                case "AstronautComplexLevelMin":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "AstronautComplexLevelMax":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "TrackingStationLevelMin":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "TrackingStationLevelMax":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "MissionControlLevelMin":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "MissionControlLevelMax":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "AdministrationLevelMin":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) >= (double.Parse(value) - 1) / 2.0;
                    break;

                case "AdministrationLevelMax":
                    good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) <= (double.Parse(value) - 1) / 2.0;
                    break;

                case "MaxAsteroidDistance": good = AsteroidDistance(v) <= double.Parse(value); break;
                }

                if (!good)
                {
                    return(s);
                }
            }

            var subject_id = Science.Generate_subject_id(experiment_id, v);

            var exp = Science.Experiment(subject_id);
            var sit = GetExperimentSituation(v);

            if (!v.loaded && sit.AtmosphericFlight())
            {
                return("Background flight");
            }

            if (!sit.IsAvailable(exp))
            {
                return("Invalid situation");
            }


            // At this point we know the situation is valid and the experiment can be done
            // create it in R&D
            Science.Generate_subject(experiment_id, v);

            return(string.Empty);
        }
Пример #2
0
        public bool TestRequirements(Vessel v, out RequireResult[] results, bool testAll = false)
        {
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.ExperimentRequirements.TestRequirements");
            VesselData vd = v.KerbalismData();

            results = new RequireResult[Requires.Length];

            bool good = true;

            for (int i = 0; i < Requires.Length; i++)
            {
                results[i] = new RequireResult(Requires[i]);
                switch (Requires[i].require)
                {
                case Require.OrbitMinInclination: TestReq((c, r) => c >= r, v.orbit.inclination, (double)Requires[i].value, results[i]); break;

                case Require.OrbitMaxInclination: TestReq((c, r) => c <= r, v.orbit.inclination, (double)Requires[i].value, results[i]); break;

                case Require.OrbitMinEccentricity: TestReq((c, r) => c >= r, v.orbit.eccentricity, (double)Requires[i].value, results[i]); break;

                case Require.OrbitMaxEccentricity: TestReq((c, r) => c <= r, v.orbit.eccentricity, (double)Requires[i].value, results[i]); break;

                case Require.OrbitMinArgOfPeriapsis: TestReq((c, r) => c >= r, v.orbit.argumentOfPeriapsis, (double)Requires[i].value, results[i]); break;

                case Require.OrbitMaxArgOfPeriapsis: TestReq((c, r) => c <= r, v.orbit.argumentOfPeriapsis, (double)Requires[i].value, results[i]); break;

                case Require.TemperatureMin: TestReq((c, r) => c >= r, vd.EnvTemperature, (double)Requires[i].value, results[i]); break;

                case Require.TemperatureMax: TestReq((c, r) => c <= r, vd.EnvTemperature, (double)Requires[i].value, results[i]); break;

                case Require.AltitudeMin: TestReq((c, r) => c >= r, v.altitude, (double)Requires[i].value, results[i]); break;

                case Require.AltitudeMax: TestReq((c, r) => c <= r, v.altitude, (double)Requires[i].value, results[i]); break;

                case Require.RadiationMin: TestReq((c, r) => c >= r, vd.EnvRadiation, (double)Requires[i].value, results[i]); break;

                case Require.RadiationMax: TestReq((c, r) => c <= r, vd.EnvRadiation, (double)Requires[i].value, results[i]); break;

                case Require.VolumePerCrewMin: TestReq((c, r) => c >= r, vd.VolumePerCrew, (double)Requires[i].value, results[i]); break;

                case Require.VolumePerCrewMax: TestReq((c, r) => c <= r, vd.VolumePerCrew, (double)Requires[i].value, results[i]); break;

                case Require.SunAngleMin: TestReq((c, r) => c >= r, vd.EnvSunBodyAngle, (double)Requires[i].value, results[i]); break;

                case Require.SunAngleMax: TestReq((c, r) => c <= r, vd.EnvSunBodyAngle, (double)Requires[i].value, results[i]); break;

                case Require.SurfaceSpeedMin: TestReq((c, r) => c >= r, v.srfSpeed, (double)Requires[i].value, results[i]); break;

                case Require.SurfaceSpeedMax: TestReq((c, r) => c <= r, v.srfSpeed, (double)Requires[i].value, results[i]); break;

                case Require.VerticalSpeedMin: TestReq((c, r) => c >= r, v.verticalSpeed, (double)Requires[i].value, results[i]); break;

                case Require.VerticalSpeedMax: TestReq((c, r) => c <= r, v.verticalSpeed, (double)Requires[i].value, results[i]); break;

                case Require.SpeedMin: TestReq((c, r) => c >= r, v.speed, (double)Requires[i].value, results[i]); break;

                case Require.SpeedMax: TestReq((c, r) => c <= r, v.speed, (double)Requires[i].value, results[i]); break;

                case Require.DynamicPressureMin: TestReq((c, r) => c >= r, v.dynamicPressurekPa, (double)Requires[i].value, results[i]); break;

                case Require.DynamicPressureMax: TestReq((c, r) => c <= r, v.dynamicPressurekPa, (double)Requires[i].value, results[i]); break;

                case Require.StaticPressureMin: TestReq((c, r) => c >= r, v.staticPressurekPa, (double)Requires[i].value, results[i]); break;

                case Require.StaticPressureMax: TestReq((c, r) => c <= r, v.staticPressurekPa, (double)Requires[i].value, results[i]); break;

                case Require.AtmDensityMin: TestReq((c, r) => c >= r, v.atmDensity, (double)Requires[i].value, results[i]); break;

                case Require.AtmDensityMax: TestReq((c, r) => c <= r, v.atmDensity, (double)Requires[i].value, results[i]); break;

                case Require.AltAboveGroundMin: TestReq((c, r) => c >= r, v.heightFromTerrain, (double)Requires[i].value, results[i]); break;

                case Require.AltAboveGroundMax: TestReq((c, r) => c <= r, v.heightFromTerrain, (double)Requires[i].value, results[i]); break;

                case Require.MaxAsteroidDistance: TestReq((c, r) => c <= r, TestAsteroidDistance(v), (double)Requires[i].value, results[i]); break;

                case Require.AtmosphereAltMin: TestReq((c, r) => c >= r, v.mainBody.atmosphere ? v.altitude / v.mainBody.atmosphereDepth : double.NaN, (double)Requires[i].value, results[i]); break;

                case Require.AtmosphereAltMax: TestReq((c, r) => c <= r, v.mainBody.atmosphere ? v.altitude / v.mainBody.atmosphereDepth : double.NaN, (double)Requires[i].value, results[i]); break;

                case Require.CrewMin: TestReq((c, r) => c >= r, vd.CrewCount, (int)Requires[i].value, results[i]); break;

                case Require.CrewMax: TestReq((c, r) => c <= r, vd.CrewCount, (int)Requires[i].value, results[i]); break;

                case Require.CrewCapacityMin: TestReq((c, r) => c >= r, vd.CrewCapacity, (int)Requires[i].value, results[i]); break;

                case Require.CrewCapacityMax: TestReq((c, r) => c <= r, vd.CrewCapacity, (int)Requires[i].value, results[i]); break;

                case Require.AstronautComplexLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.AstronautComplex), (int)Requires[i].value, results[i]); break;

                case Require.AstronautComplexLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.AstronautComplex), (int)Requires[i].value, results[i]); break;

                case Require.TrackingStationLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.TrackingStation), (int)Requires[i].value, results[i]); break;

                case Require.TrackingStationLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.TrackingStation), (int)Requires[i].value, results[i]); break;

                case Require.MissionControlLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.MissionControl), (int)Requires[i].value, results[i]); break;

                case Require.MissionControlLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.MissionControl), (int)Requires[i].value, results[i]); break;

                case Require.AdministrationLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.Administration), (int)Requires[i].value, results[i]); break;

                case Require.AdministrationLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.Administration), (int)Requires[i].value, results[i]); break;

                case Require.Shadow: TestReq(() => vd.EnvInFullShadow, results[i]); break;

                case Require.Sunlight: TestReq(() => vd.EnvInSunlight, results[i]); break;

                case Require.Greenhouse: TestReq(() => vd.Greenhouses.Count > 0, results[i]); break;

                case Require.AbsoluteZero: TestReq(() => vd.EnvTemperature < 30.0, results[i]); break;

                case Require.InnerBelt: TestReq(() => vd.EnvInnerBelt, results[i]); break;

                case Require.OuterBelt: TestReq(() => vd.EnvOuterBelt, results[i]); break;

                case Require.MagneticBelt: TestReq(() => vd.EnvInnerBelt || vd.EnvOuterBelt, results[i]); break;

                case Require.Magnetosphere: TestReq(() => vd.EnvMagnetosphere, results[i]); break;

                case Require.InterStellar: TestReq(() => Lib.IsSun(v.mainBody) && vd.EnvInterstellar, results[i]); break;

                case Require.Part: TestReq(() => Lib.HasPart(v, (string)Requires[i].value), results[i]); break;

                case Require.Module: TestReq(() => Lib.FindModules(v.protoVessel, (string)Requires[i].value).Count > 0, results[i]); break;

                default: results[i].isValid = true; break;
                }

                if (!testAll && !results[i].isValid)
                {
                    UnityEngine.Profiling.Profiler.EndSample();
                    return(false);
                }

                good &= results[i].isValid;
            }

            UnityEngine.Profiling.Profiler.EndSample();
            return(good);
        }