Пример #1
0
        public static void Update(Vessel v, Vessel_info vi, VesselData vd, Vessel_resources resources, double elapsed_s)
        {
            // get most used resource handlers
            Resource_info ec = resources.Info(v, "ElectricCharge");

            // This is basically handled in cache. However, when accelerating time warp while
            // the vessel is in shadow, the cache logic doesn't kick in soon enough. So we double-check here
            if (TimeWarp.CurrentRate > 1000.0f || elapsed_s > 150)              // we're time warping fast...
            {
                vi.highspeedWarp(v);
            }

            foreach (var e in Background_PMs(v))
            {
                switch (e.type)
                {
                case Module_type.Reliability: Reliability.BackgroundUpdate(v, e.p, e.m, e.module_prefab as Reliability); break;

                case Module_type.Experiment: Experiment.BackgroundUpdate(v, e.m, e.module_prefab as Experiment, ec, resources, elapsed_s); break;

                case Module_type.Greenhouse: Greenhouse.BackgroundUpdate(v, e.m, e.module_prefab as Greenhouse, vi, resources, elapsed_s); break;

                case Module_type.GravityRing: GravityRing.BackgroundUpdate(v, e.p, e.m, e.module_prefab as GravityRing, ec, elapsed_s); break;

                case Module_type.Emitter: Emitter.BackgroundUpdate(v, e.p, e.m, e.module_prefab as Emitter, ec, elapsed_s); break;

                case Module_type.Harvester: Harvester.BackgroundUpdate(v, e.m, e.module_prefab as Harvester, elapsed_s); break;                         // Kerbalism ground and air harvester module

                case Module_type.Laboratory: Laboratory.BackgroundUpdate(v, e.p, e.m, e.module_prefab as Laboratory, ec, elapsed_s); break;

                case Module_type.Command: ProcessCommand(v, e.p, e.m, e.module_prefab as ModuleCommand, resources, elapsed_s); break;

                case Module_type.Panel: ProcessPanel(v, e.p, e.m, e.module_prefab as ModuleDeployableSolarPanel, vi, ec, elapsed_s); break;

                case Module_type.Generator: ProcessGenerator(v, e.p, e.m, e.module_prefab as ModuleGenerator, resources, elapsed_s); break;

                case Module_type.Converter: ProcessConverter(v, e.p, e.m, e.module_prefab as ModuleResourceConverter, resources, elapsed_s); break;

                case Module_type.Drill: ProcessDrill(v, e.p, e.m, e.module_prefab as ModuleResourceHarvester, resources, elapsed_s); break;                         // Stock ground harvester module

                case Module_type.AsteroidDrill: ProcessAsteroidDrill(v, e.p, e.m, e.module_prefab as ModuleAsteroidDrill, resources, elapsed_s); break;             // Stock asteroid harvester module

                case Module_type.StockLab: ProcessStockLab(v, e.p, e.m, e.module_prefab as ModuleScienceConverter, ec, elapsed_s); break;

                case Module_type.Light: ProcessLight(v, e.p, e.m, e.module_prefab as ModuleLight, ec, elapsed_s); break;

                case Module_type.Scanner: KerbalismScansat.BackgroundUpdate(v, e.p, e.m, e.module_prefab as KerbalismScansat, e.part_prefab, vd, ec, elapsed_s); break;

                case Module_type.CurvedPanel: ProcessCurvedPanel(v, e.p, e.m, e.module_prefab, e.part_prefab, vi, ec, elapsed_s); break;

                case Module_type.FissionGenerator: ProcessFissionGenerator(v, e.p, e.m, e.module_prefab, ec, elapsed_s); break;

                case Module_type.RadioisotopeGenerator: ProcessRadioisotopeGenerator(v, e.p, e.m, e.module_prefab, ec, elapsed_s); break;

                case Module_type.CryoTank: ProcessCryoTank(v, e.p, e.m, e.module_prefab, resources, ec, elapsed_s); break;

                case Module_type.FNGenerator: ProcessFNGenerator(v, e.p, e.m, e.module_prefab, ec, elapsed_s); break;

                case Module_type.NonRechargeBattery: ProcessNonRechargeBattery(v, e.p, e.m, e.module_prefab, ec, elapsed_s); break;
                }
            }
        }
Пример #2
0
        public static void Update(Vessel v, Vessel_info vi, VesselData vd, Vessel_resources resources, double elapsed_s)
        {
            // get most used resource handlers
            Resource_info ec = resources.Info(v, "ElectricCharge");

            // store data required to support multiple modules of same type in a part
            var PD = new Dictionary <string, Lib.Module_prefab_data>();

            // for each part
            foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots)
            {
                // get part prefab (required for module properties)
                Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab;

                // get all module prefabs
                var module_prefabs = part_prefab.FindModulesImplementing <PartModule>();

                // clear module indexes
                PD.Clear();

                // for each module
                foreach (ProtoPartModuleSnapshot m in p.modules)
                {
                    // get module type
                    // if the type is unknown, skip it
                    Module_type type = ModuleType(m.moduleName);
                    if (type == Module_type.Unknown)
                    {
                        continue;
                    }

                    // get the module prefab
                    // if the prefab doesn't contain this module, skip it
                    PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD);
                    if (!module_prefab)
                    {
                        continue;
                    }

                    // if the module is disabled, skip it
                    // note: this must be done after ModulePrefab is called, so that indexes are right
                    if (!Lib.Proto.GetBool(m, "isEnabled"))
                    {
                        continue;
                    }

                    // process modules
                    // note: this should be a fast switch, possibly compiled to a jump table
                    switch (type)
                    {
                    case Module_type.Reliability: Reliability.BackgroundUpdate(v, p, m, module_prefab as Reliability); break;

                    case Module_type.Experiment: Experiment.BackgroundUpdate(v, m, module_prefab as Experiment, ec, elapsed_s); break;

                    case Module_type.Greenhouse: Greenhouse.BackgroundUpdate(v, m, module_prefab as Greenhouse, vi, resources, elapsed_s); break;

                    case Module_type.GravityRing: GravityRing.BackgroundUpdate(v, p, m, module_prefab as GravityRing, ec, elapsed_s); break;

                    case Module_type.Emitter: Emitter.BackgroundUpdate(v, p, m, module_prefab as Emitter, ec, elapsed_s); break;

                    case Module_type.Harvester: Harvester.BackgroundUpdate(v, m, module_prefab as Harvester, elapsed_s); break;                             // Kerbalism ground and air harvester module

                    case Module_type.Laboratory: Laboratory.BackgroundUpdate(v, p, m, module_prefab as Laboratory, ec, elapsed_s); break;

                    case Module_type.Command: ProcessCommand(v, p, m, module_prefab as ModuleCommand, resources, elapsed_s); break;

                    case Module_type.Panel: ProcessPanel(v, p, m, module_prefab as ModuleDeployableSolarPanel, vi, ec, elapsed_s); break;

                    case Module_type.Generator: ProcessGenerator(v, p, m, module_prefab as ModuleGenerator, resources, elapsed_s); break;

                    case Module_type.Converter: ProcessConverter(v, p, m, module_prefab as ModuleResourceConverter, resources, elapsed_s); break;

                    case Module_type.Drill: ProcessDrill(v, p, m, module_prefab as ModuleResourceHarvester, resources, elapsed_s); break;                             // Stock ground harvester module

                    case Module_type.AsteroidDrill: ProcessAsteroidDrill(v, p, m, module_prefab as ModuleAsteroidDrill, resources, elapsed_s); break;                 // Stock asteroid harvester module

                    case Module_type.StockLab: ProcessStockLab(v, p, m, module_prefab as ModuleScienceConverter, ec, elapsed_s); break;

                    case Module_type.Light: ProcessLight(v, p, m, module_prefab as ModuleLight, ec, elapsed_s); break;

                    case Module_type.Scanner: ProcessScanner(v, p, m, module_prefab, part_prefab, vd, ec, elapsed_s); break;

                    case Module_type.CurvedPanel: ProcessCurvedPanel(v, p, m, module_prefab, part_prefab, vi, ec, elapsed_s); break;

                    case Module_type.FissionGenerator: ProcessFissionGenerator(v, p, m, module_prefab, ec, elapsed_s); break;

                    case Module_type.RadioisotopeGenerator: ProcessRadioisotopeGenerator(v, p, m, module_prefab, ec, elapsed_s); break;

                    case Module_type.CryoTank: ProcessCryoTank(v, p, m, module_prefab, resources, ec, elapsed_s); break;

                    case Module_type.FNGenerator: ProcessFNGenerator(v, p, m, module_prefab, ec, elapsed_s); break;
                    }
                }
            }
        }
Пример #3
0
 public ExperimentDevice(Experiment exp)
 {
     this.experiment = exp;
     this.exp_name   = (exp.sample_mass < float.Epsilon ? "sensor" : "experiment")
                       + ": " + Lib.SpacesOnCaps(ResearchAndDevelopment.GetExperiment(exp.experiment_id).experimentTitle).ToLower().Replace("e v a", "eva");
 }
Пример #4
0
        private static string TestForIssues(Vessel v, Resource_info ec, Experiment experiment, uint hdId, bool broken,
                                            double remainingSampleMass, bool didPrepare, bool isShrouded, bool noGroundContact, string last_subject_id)
        {
            var subject_id = Science.Generate_subject_id(experiment.experiment_id, v);

            if (broken)
            {
                return("broken");
            }

            if (isShrouded && !experiment.allow_shrouded)
            {
                return("shrouded");
            }

            bool needsReset = experiment.crew_reset.Length > 0 &&
                              !string.IsNullOrEmpty(last_subject_id) && subject_id != last_subject_id;

            if (needsReset)
            {
                return("reset required");
            }

            if (ec.amount < double.Epsilon && experiment.ec_rate > double.Epsilon)
            {
                return("no Electricity");
            }

            if (!string.IsNullOrEmpty(experiment.crew_operate))
            {
                var cs = new CrewSpecs(experiment.crew_operate);
                if (!cs && Lib.CrewCount(v) > 0)
                {
                    return("crew on board");
                }
                else if (cs && !cs.Check(v))
                {
                    return(cs.Warning());
                }
            }

            if (!experiment.sample_collecting && remainingSampleMass < double.Epsilon && experiment.sample_mass > double.Epsilon)
            {
                return("depleted");
            }

            if (!didPrepare && !string.IsNullOrEmpty(experiment.crew_prepare))
            {
                return("not prepared");
            }

            if (noGroundContact)
            {
                return("no ground contact");
            }

            string situationIssue = Science.TestRequirements(experiment.experiment_id, experiment.requires, v);

            if (situationIssue.Length > 0)
            {
                return(Science.RequirementText(situationIssue));
            }

            var    experimentSize = Science.Experiment(subject_id).max_amount;
            double chunkSize      = Math.Min(experiment.data_rate * Kerbalism.elapsed_s, experimentSize);
            Drive  drive          = GetDrive(experiment, v, hdId, chunkSize, subject_id);

            var    isFile    = experiment.sample_mass < double.Epsilon;
            double available = 0;

            if (isFile)
            {
                available  = drive.FileCapacityAvailable();
                available += Cache.WarpCache(v).FileCapacityAvailable();
            }
            else
            {
                available = drive.SampleCapacityAvailable(subject_id);
            }

            if (Math.Min(experiment.data_rate * Kerbalism.elapsed_s, experimentSize) > available)
            {
                return(insufficient_storage);
            }

            return(string.Empty);
        }
Пример #5
0
        public static void BackgroundUpdate(Vessel v, ProtoPartModuleSnapshot m, Experiment experiment, Resource_info ec, Vessel_resources resources, double elapsed_s)
        {
            bool   didPrepare          = Lib.Proto.GetBool(m, "didPrepare", false);
            bool   shrouded            = Lib.Proto.GetBool(m, "shrouded", false);
            string last_subject_id     = Lib.Proto.GetString(m, "last_subject_id", "");
            double remainingSampleMass = Lib.Proto.GetDouble(m, "remainingSampleMass", 0);
            bool   broken          = Lib.Proto.GetBool(m, "broken", false);
            bool   noGroundContact = Lib.Proto.GetBool(m, "noGroundContact", false);
            bool   forcedRun       = Lib.Proto.GetBool(m, "forcedRun", false);
            bool   recording       = Lib.Proto.GetBool(m, "recording", false);
            uint   privateHdId     = Lib.Proto.GetUInt(m, "privateHdId", 0);

            string issue = TestForIssues(v, ec, experiment, privateHdId, broken,
                                         remainingSampleMass, didPrepare, shrouded, noGroundContact, last_subject_id);

            if (string.IsNullOrEmpty(issue))
            {
                issue = TestForResources(v, KerbalismProcess.ParseResources(experiment.resources), elapsed_s, resources);
            }

            Lib.Proto.Set(m, "issue", issue);

            if (!string.IsNullOrEmpty(issue))
            {
                return;
            }

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

            Lib.Proto.Set(m, "last_subject_id", subject_id);

            double dataSampled = Lib.Proto.GetDouble(m, "dataSampled");

            if (last_subject_id != subject_id)
            {
                dataSampled = 0;
                Lib.Proto.Set(m, "forcedRun", false);
            }

            double scienceValue = Science.Value(last_subject_id);

            Lib.Proto.Set(m, "scienceValue", scienceValue);

            var state = GetState(scienceValue, issue, recording, forcedRun);

            if (state != State.RUNNING)
            {
                return;
            }
            if (dataSampled >= Science.Experiment(subject_id).max_amount)
            {
                return;
            }

            var stored = DoRecord(experiment, subject_id, v, ec, privateHdId,
                                  resources, KerbalismProcess.ParseResources(experiment.resources),
                                  remainingSampleMass, dataSampled, out dataSampled, out remainingSampleMass);

            if (!stored)
            {
                Lib.Proto.Set(m, "issue", insufficient_storage);
            }

            Lib.Proto.Set(m, "dataSampled", dataSampled);
            Lib.Proto.Set(m, "remainingSampleMass", remainingSampleMass);
        }
Пример #6
0
        private static bool DoRecord(Experiment experiment, string subject_id, Vessel vessel, Resource_info ec, uint hdId,
                                     Vessel_resources resources, List <KeyValuePair <string, double> > resourceDefs,
                                     double remainingSampleMass, double dataSampled,
                                     out double sampledOut, out double remainingSampleMassOut)
        {
            // default output values for early returns
            sampledOut             = dataSampled;
            remainingSampleMassOut = remainingSampleMass;

            var exp = Science.Experiment(subject_id);

            if (Done(exp, dataSampled))
            {
                return(true);
            }

            double elapsed   = Kerbalism.elapsed_s;
            double chunkSize = Math.Min(experiment.data_rate * elapsed, exp.max_amount);
            double massDelta = experiment.sample_mass * chunkSize / exp.max_amount;

            Drive drive = GetDrive(experiment, vessel, hdId, chunkSize, subject_id);

            // on high time warp this chunk size could be too big, but we could store a sizable amount if we process less
            bool   isFile      = experiment.sample_mass < float.Epsilon;
            double maxCapacity = isFile ? drive.FileCapacityAvailable() : drive.SampleCapacityAvailable(subject_id);

            Drive warpCacheDrive = null;

            if (isFile)
            {
                if (drive.GetFileSend(subject_id))
                {
                    warpCacheDrive = Cache.WarpCache(vessel);
                }
                if (warpCacheDrive != null)
                {
                    maxCapacity += warpCacheDrive.FileCapacityAvailable();
                }
            }

            double factor = Rate(vessel, chunkSize, maxCapacity, elapsed, ec, experiment.ec_rate, resources, resourceDefs);

            if (factor < double.Epsilon)
            {
                return(false);
            }

            chunkSize *= factor;
            massDelta *= factor;
            elapsed   *= factor;

            bool stored = false;

            if (chunkSize > double.Epsilon)
            {
                if (isFile)
                {
                    if (warpCacheDrive != null)
                    {
                        double s = Math.Min(chunkSize, warpCacheDrive.FileCapacityAvailable());
                        stored = warpCacheDrive.Record_file(subject_id, s, true);

                        if (chunkSize > s)                        // only write to persisted drive if the data cannot be transmitted in this tick
                        {
                            stored &= drive.Record_file(subject_id, chunkSize - s, true);
                        }
                    }
                    else
                    {
                        stored = drive.Record_file(subject_id, chunkSize, true);
                    }
                }
                else
                {
                    stored = drive.Record_sample(subject_id, chunkSize, massDelta);
                }
            }

            if (!stored)
            {
                return(false);
            }

            // consume resources
            ec.Consume(experiment.ec_rate * elapsed, "experiment");
            foreach (var p in resourceDefs)
            {
                resources.Consume(vessel, p.Key, p.Value * elapsed, "experiment");
            }

            dataSampled += chunkSize;
            dataSampled  = Math.Min(dataSampled, exp.max_amount);
            sampledOut   = dataSampled;
            if (!experiment.sample_collecting)
            {
                remainingSampleMass -= massDelta;
                remainingSampleMass  = Math.Max(remainingSampleMass, 0);
            }
            remainingSampleMassOut = remainingSampleMass;
            return(true);
        }
Пример #7
0
 public ExperimentDevice(Experiment exp)
 {
     this.exp      = exp;
     this.exp_name = Lib.SpacesOnCaps(ResearchAndDevelopment.GetExperiment(exp.experiment).experimentTitle).ToLower().Replace("e v a", "eva");
 }