public static void Update(Vessel v, Vessel_info vi, VesselData vd, Resource_info ec, double elapsed_s)
        {
            // consume ec for internal transmitters (control and telemetry)
            ec.Consume(vi.connection.internal_cost * elapsed_s);

            // consume ec for external transmitters (don't consume for RemoteTech when loaded)
            if (!(RemoteTech.Enabled && v.loaded))
            {
                ec.Consume(vi.connection.external_cost * elapsed_s);
            }

            // do nothing if network is not ready
            if (!NetworkInitialized)
            {
                return;
            }

            // maintain and send messages
            // - do not send messages during/after solar storms
            // - do not send messages for EVA kerbals
            if (!v.isEVA && v.situation != Vessel.Situations.PRELAUNCH)
            {
                if (!vd.msg_signal && !vi.connection.linked)
                {
                    vd.msg_signal = true;
                    if (vd.cfg_signal)
                    {
                        string subtext = Localizer.Format("#KERBALISM_UI_transmissiondisabled");

                        switch (vi.connection.status)
                        {
                        case LinkStatus.plasma:
                            subtext = Localizer.Format("#KERBALISM_UI_Plasmablackout");
                            break;

                        case LinkStatus.storm:
                            subtext = Localizer.Format("#KERBALISM_UI_Stormblackout");
                            break;

                        default:
                            if (vi.crew_count == 0)
                            {
                                switch (Settings.UnlinkedControl)
                                {
                                case UnlinkedCtrl.none:
                                    subtext = Localizer.Format("#KERBALISM_UI_noctrl");
                                    break;

                                case UnlinkedCtrl.limited:
                                    subtext = Localizer.Format("#KERBALISM_UI_limitedcontrol");
                                    break;
                                }
                            }
                            break;
                        }

                        Message.Post(Severity.warning, Lib.BuildString(Localizer.Format("#KERBALISM_UI_signallost"), " <b>", v.vesselName, "</b>"), subtext);
                    }
                }
                else if (vd.msg_signal && vi.connection.linked)
                {
                    vd.msg_signal = false;
                    if (vd.cfg_signal)
                    {
                        Message.Post(Severity.relax, Lib.BuildString("<b>", v.vesselName, "</b> ", Localizer.Format("#KERBALISM_UI_signalback")),
                                     vi.connection.status == LinkStatus.direct_link ? Localizer.Format("#KERBALISM_UI_directlink") :
                                     Lib.BuildString(Localizer.Format("#KERBALISM_UI_relayby"), " <b>", vi.connection.target_name, "</b>"));
                    }
                }
            }
        }
示例#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;

                    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:                 ProcessHarvester(v, p, m, module_prefab as ModuleResourceHarvester, resources, elapsed_s);  break;

                    case module_type.AsteroidDrill:         ProcessAsteroidDrill(v, p, m, module_prefab as ModuleAsteroidDrill, resources, elapsed_s);  break;

                    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, elapsed_s);                              break;
                    }
                }
            }
        }
示例#3
0
        // consume EC for transmission, and transmit science data
        public static void Update(Vessel v, VesselData vd, ResourceInfo ec, double elapsed_s)
        {
            // do nothing if science system is disabled
            if (!Features.Science)
            {
                return;
            }

            // consume ec for transmitters
            ec.Consume(vd.Connection.ec_idle * elapsed_s, ResourceBroker.CommsIdle);

            // avoid corner-case when RnD isn't live during scene changes
            // - this avoid losing science if the buffer reach threshold during a scene change
            if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && ResearchAndDevelopment.Instance == null)
            {
                return;
            }

            // clear list of files transmitted
            vd.filesTransmitted.Clear();

            // check connection
            if (vd.Connection == null ||
                !vd.Connection.linked ||
                vd.Connection.rate <= 0.0 ||
                !vd.deviceTransmit ||
                ec.Amount < vd.Connection.ec_idle * elapsed_s)
            {
                // reset all files transmit rate
                foreach (Drive drive in Drive.GetDrives(vd, true))
                {
                    foreach (File f in drive.files.Values)
                    {
                        f.transmitRate = 0.0;
                    }
                }

                // do nothing else
                return;
            }

            double totalTransmitCapacity     = vd.Connection.rate * elapsed_s;
            double remainingTransmitCapacity = totalTransmitCapacity;
            double scienceCredited           = 0.0;

            GetFilesToTransmit(v, vd);

            if (xmitFiles.Count == 0)
            {
                return;
            }

            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.Science.Update-Loop");

            // traverse the list in reverse because :
            // - warp cache files are at the end, and they are always transmitted regerdless of transmit capacity
            // - others files are next, sorted in science value per MB ascending order
            for (int i = xmitFiles.Count - 1; i >= 0; i--)
            {
                XmitFile xmitFile = xmitFiles[i];

                if (xmitFile.file.size == 0.0)
                {
                    continue;
                }

                // always transmit everything in the warp cache
                if (!xmitFile.isInWarpCache && remainingTransmitCapacity <= 0.0)
                {
                    break;
                }

                // determine how much data is transmitted
                double transmitted = xmitFile.isInWarpCache ? xmitFile.file.size : Math.Min(xmitFile.file.size, remainingTransmitCapacity);

                if (transmitted == 0.0)
                {
                    continue;
                }

                // consume transmit capacity
                remainingTransmitCapacity -= transmitted;

                // get science value
                double xmitScienceValue = transmitted * xmitFile.sciencePerMB;

                // consume data in the file
                xmitFile.file.size -= transmitted;

                // remove science collected (ignoring final science value clamped to subject completion)
                xmitFile.file.subjectData.RemoveScienceCollectedInFlight(xmitScienceValue);

                // fire subject completed events
                int timesCompleted = xmitFile.file.subjectData.UpdateSubjectCompletion(xmitScienceValue);
                if (timesCompleted > 0)
                {
                    SubjectXmitCompleted(xmitFile.file, timesCompleted, v);
                }

                // save transmit rate for the file, and add it to the VesselData list of files being transmitted
                if (xmitFile.isInWarpCache && xmitFile.realDriveFile != null)
                {
                    xmitFile.realDriveFile.transmitRate = transmitted / elapsed_s;
                    vd.filesTransmitted.Add(xmitFile.realDriveFile);
                }
                else
                {
                    xmitFile.file.transmitRate = transmitted / elapsed_s;
                    vd.filesTransmitted.Add(xmitFile.file);
                }

                // clamp science value to subject max value
                xmitScienceValue = Math.Min(xmitScienceValue, xmitFile.file.subjectData.ScienceRemainingToRetrieve);

                if (xmitScienceValue > 0.0)
                {
                    // add credits
                    scienceCredited += xmitScienceValue;

                    // credit the subject
                    xmitFile.file.subjectData.AddScienceToRnDSubject(xmitScienceValue);
                }
            }

            UnityEngine.Profiling.Profiler.EndSample();

            vd.scienceTransmitted += scienceCredited;

            // consume EC cost for transmission (ec_idle is consumed above)
            double transmittedCapacity = totalTransmitCapacity - remainingTransmitCapacity;
            double transmissionCost    = (vd.Connection.ec - vd.Connection.ec_idle) * (transmittedCapacity / vd.Connection.rate);

            ec.Consume(transmissionCost, ResourceBroker.CommsXmit);

            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.Science.Update-AddScience");

            // Add science points, but wait until we have at least 0.1 points to add because AddScience is VERY slow
            // We don't use "TransactionReasons.ScienceTransmission" because AddScience fire multiple events not meant to be fired continuously
            // this avoid many side issues (ex : chatterer transmit sound playing continously, strategia "+0.0 science" popup...)
            ScienceDB.uncreditedScience += scienceCredited;
            if (ScienceDB.uncreditedScience > 0.1)
            {
                if (GameHasRnD)
                {
                    ResearchAndDevelopment.Instance.AddScience((float)ScienceDB.uncreditedScience, TransactionReasons.None);
                }

                ScienceDB.uncreditedScience = 0.0;
            }

            UnityEngine.Profiling.Profiler.EndSample();
        }
示例#4
0
        public void Execute(Vessel v, VesselData vd, VesselResources resources, double elapsed_s)
        {
            // store list of crew to kill
            List <ProtoCrewMember> deferred_kills = new List <ProtoCrewMember>();

            // get input resource handler
            ResourceInfo res = input.Length > 0 ? resources.GetResource(v, input) : null;

            // determine message variant
            uint variant = vd.EnvTemperature < Settings.LifeSupportSurvivalTemperature ? 0 : 1u;

            // get product of all environment modifiers
            double k = Modifiers.Evaluate(v, vd, resources, modifiers);

            bool lifetime_enabled = PreferencesRadiation.Instance.lifetime;

            // for each crew
            foreach (ProtoCrewMember c in Lib.CrewList(v))
            {
                // get kerbal data
                KerbalData kd = DB.Kerbal(c.name);

                // skip rescue kerbals
                if (kd.rescue)
                {
                    continue;
                }

                // skip disabled kerbals
                if (kd.disabled)
                {
                    continue;
                }

                // get kerbal property data from db
                RuleData rd = kd.Rule(name);
                rd.lifetime = lifetime_enabled && lifetime;

                // influence consumption by elapsed time
                double step = elapsed_s;

                // if interval-based
                if (interval > 0.0)
                {
                    // accumulate time
                    rd.time_since += elapsed_s;

                    // determine number of intervals that has passed (can be 2 or more if elapsed_s > interval * 2)
                    step = Math.Floor(rd.time_since / interval);

                    // consume time
                    rd.time_since -= step * interval;
                }

                // if there is a resource specified
                if (res != null && rate > double.Epsilon)
                {
                    // get rate including per-kerbal variance
                    double resRate =
                        rate                                                        // consumption rate
                        * Variance(name, c, individuality)                          // kerbal-specific variance
                        * k;                                                        // product of environment modifiers

                    // determine amount of resource to consume

                    double required = resRate * step;                           // seconds elapsed or interval amount

                    // remember if a meal is consumed/produced in this simulation step
                    if (interval > 0.0)
                    {
                        double ratePerStep = resRate / interval;
                        res.UpdateIntervalRule(-required, -ratePerStep, name);
                        if (output.Length > 0)
                        {
                            ResourceCache.GetResource(v, output).UpdateIntervalRule(required * ratio, ratePerStep * ratio, name);
                        }
                    }

                    // if continuous, or if one or more intervals elapsed
                    if (step > 0.0)
                    {
                        // if there is no output
                        if (output.Length == 0)
                        {
                            // simply consume (that is faster)
                            res.Consume(required, name);
                        }
                        // if there is an output
                        else
                        {
                            // transform input into output resource
                            // - rules always dump excess overboard (because it is waste)
                            ResourceRecipe recipe = new ResourceRecipe(name);
                            recipe.AddInput(input, required);
                            recipe.AddOutput(output, required * ratio, true);
                            resources.AddRecipe(recipe);
                        }
                    }
                }

                // if continuous, or if one or more intervals elapsed
                if (step > 0.0)
                {
                    // degenerate:
                    // - if the environment modifier is not telling to reset (by being zero)
                    // - if this rule is resource-less, or if there was not enough resource in the vessel
                    if (k > 0.0 && (input.Length == 0 || res.Amount <= double.Epsilon))
                    {
                        rd.problem += degeneration                                   // degeneration rate per-second or per-interval
                                      * k                                            // product of environment modifiers
                                      * step                                         // seconds elapsed or by number of steps
                                      * Variance(name, c, variance);                 // kerbal-specific variance
                    }
                    // else slowly recover
                    else
                    {
                        rd.problem *= 1.0 / (1.0 + Math.Max(interval, 1.0) * step * 0.002);
                    }
                }

                bool do_breakdown = false;

                if (breakdown)
                {
                    // don't do breakdowns and don't show stress message if disabled
                    if (!PreferencesComfort.Instance.stressBreakdowns)
                    {
                        return;
                    }

                    // stress level
                    double breakdown_probability = rd.problem / warning_threshold;
                    breakdown_probability = Lib.Clamp(breakdown_probability, 0.0, 1.0);

                    // use the stupidity of a kerbal.
                    // however, nobody is perfect - not even a kerbal with a stupidity of 0.
                    breakdown_probability *= c.stupidity * 0.6 + 0.4;

                    // apply the weekly error rate
                    breakdown_probability *= PreferencesComfort.Instance.stressBreakdownRate;

                    // now we have the probability for one failure per week, based on the
                    // individual stupidity and stress level of the kerbal.

                    breakdown_probability = (breakdown_probability * elapsed_s) / (Lib.DaysInYear * Lib.HoursInDay * 3600);
                    if (breakdown_probability > Lib.RandomDouble())
                    {
                        do_breakdown = true;

                        // we're stressed out and just made a major mistake, this further increases the stress level...
                        rd.problem += warning_threshold * 0.05;                         // add 5% of the warning treshold to current stress level
                    }
                }

                // kill kerbal if necessary
                if (rd.problem >= fatal_threshold)
                {
#if DEBUG || DEVBUILD
                    Lib.Log("Rule " + name + " kills " + c.name + " at " + rd.problem + " " + degeneration + "/" + k + "/" + step + "/" + Variance(name, c, variance));
#endif
                    if (fatal_message.Length > 0)
                    {
                        Message.Post(breakdown ? Severity.breakdown : Severity.fatality, Lib.ExpandMsg(fatal_message, v, c, variant));
                    }

                    if (breakdown)
                    {
                        do_breakdown = true;

                        // move back between warning and danger level
                        rd.problem = (warning_threshold + danger_threshold) * 0.5;

                        // make sure next danger message is shown
                        rd.message = 1;
                    }
                    else
                    {
                        deferred_kills.Add(c);
                    }
                }
                // show messages
                else if (rd.problem >= danger_threshold && rd.message < 2)
                {
                    if (danger_message.Length > 0)
                    {
                        Message.Post(Severity.danger, Lib.ExpandMsg(danger_message, v, c, variant));
                    }
                    rd.message = 2;
                }
                else if (rd.problem >= warning_threshold && rd.message < 1)
                {
                    if (warning_message.Length > 0)
                    {
                        Message.Post(Severity.warning, Lib.ExpandMsg(warning_message, v, c, variant));
                    }
                    rd.message = 1;
                }
                else if (rd.problem < warning_threshold && rd.message > 0)
                {
                    if (relax_message.Length > 0)
                    {
                        Message.Post(Severity.relax, Lib.ExpandMsg(relax_message, v, c, variant));
                    }
                    rd.message = 0;
                }

                if (do_breakdown)
                {
                    // trigger breakdown event
                    Misc.Breakdown(v, c);
                }
            }

            // execute the deferred kills
            foreach (ProtoCrewMember c in deferred_kills)
            {
                Misc.Kill(v, c);
            }
        }
示例#5
0
        static void ProcessScanner(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule scanner, Part part_prefab, VesselData vd, resource_info ec, double elapsed_s)
        {
            // get ec consumption rate
            double power = SCANsat.EcConsumption(scanner);

            // if the scanner doesn't require power to operate, we aren't interested in simulating it
            if (power <= double.Epsilon)
            {
                return;
            }

            // get scanner state
            bool is_scanning = Lib.Proto.GetBool(m, "scanning");

            // if its scanning
            if (is_scanning)
            {
                // consume ec
                ec.Consume(power * elapsed_s);

                // if there isn't ec
                // - comparing against amount in previous simulation step
                if (ec.amount <= double.Epsilon)
                {
                    // unregister scanner
                    SCANsat.stopScanner(v, m, part_prefab);
                    is_scanning = false;

                    // remember disabled scanner
                    vd.scansat_id.Add(p.flightID);

                    // give the user some feedback
                    if (vd.cfg_ec)
                    {
                        Message.Post(Lib.BuildString("SCANsat sensor was disabled on <b>", v.vesselName, "</b>"));
                    }
                }
            }
            // if it was disabled in background
            else if (vd.scansat_id.Contains(p.flightID))
            {
                // if there is enough ec
                // note: comparing against amount in previous simulation step
                if (ec.level > 0.25) //< re-enable at 25% EC
                {
                    // re-enable the scanner
                    SCANsat.resumeScanner(v, m, part_prefab);
                    is_scanning = true;

                    // give the user some feedback
                    if (vd.cfg_ec)
                    {
                        Message.Post(Lib.BuildString("SCANsat sensor resumed operations on <b>", v.vesselName, "</b>"));
                    }
                }
            }

            // forget active scanners
            if (is_scanning)
            {
                vd.scansat_id.Remove(p.flightID);
            }
        }
示例#6
0
        bool Render_Vessel(Panel p, Vessel v)
        {
            // get vessel info
            Vessel_Info vi = Cache.VesselInfo(v);

            // skip invalid vessels
            if (!vi.is_valid)
            {
                return(false);
            }

            if (!Lib.IsVessel(v))
            {
                return(false);
            }

            // get data from db
            VesselData vd = DB.Vessel(v);

            // determine if filter must be shown
            show_filter |= vd.group.Length > 0 && vd.group != "NONE";

            // skip filtered vessels
            if (Filtered() && vd.group != filter)
            {
                return(false);
            }

            // get resource handler
            Vessel_Resources resources = ResourceCache.Get(v);

            // get vessel crew
            List <ProtoCrewMember> crew = Lib.CrewList(v);

            // get vessel name
            string vessel_name = v.isEVA ? crew[0].name : v.vesselName;

            // get body name
            string body_name = v.mainBody.name.ToUpper();

            // render entry
            p.SetHeader
            (
                Lib.BuildString("<b>", Lib.Ellipsis(vessel_name, 20), "</b> <size=9><color=#cccccc>", Lib.Ellipsis(body_name, 8), "</color></size>"),
                string.Empty,
                () => { selected_id = selected_id != v.id ? v.id : Guid.Empty; }
            );

            // problem indicator
            Indicator_Problems(p, v, vi, crew);

            // battery indicator
            Indicator_EC(p, v, vi);

            // supply indicator
            if (Features.Supplies)
            {
                Indicator_Supplies(p, v, vi);
            }

            // reliability indicator
            if (Features.Reliability)
            {
                Indicator_Reliability(p, v, vi);
            }

            // signal indicator
            if (Features.Signal || Features.KCommNet || RemoteTech.Enabled())
            {
                Indicator_Signal(p, v, vi);
            }

            // done
            return(true);
        }
示例#7
0
        public static void Update(Vessel v, VesselData vd, VesselResources resources, double elapsed_s)
        {
            if (!Lib.IsVessel(v))
            {
                return;
            }

            // get most used resource handlers
            ResourceInfo ec = resources.GetResource(v, "ElectricCharge");

            List <ResourceInfo>         allResources       = resources.GetAllResources(v);
            Dictionary <string, double> availableResources = new Dictionary <string, double>();

            foreach (var ri in allResources)
            {
                availableResources[ri.ResourceName] = ri.Amount;
            }
            List <KeyValuePair <string, double> > resourceChangeRequests = new List <KeyValuePair <string, double> >();

            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, elapsed_s); break;

                case Module_type.Experiment: (e.module_prefab as Experiment).BackgroundUpdate(v, vd, e.m, ec, resources, elapsed_s); break;                         // experiments use the prefab as a singleton instead of a static method

                case Module_type.Greenhouse: Greenhouse.BackgroundUpdate(v, e.m, e.module_prefab as Greenhouse, vd, 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.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.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.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.SolarPanelFixer: SolarPanelFixer.BackgroundUpdate(v, e.m, e.module_prefab as SolarPanelFixer, vd, ec, elapsed_s); break;

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

                case Module_type.APIModule: ProcessApiModule(v, e.p, e.m, e.part_prefab, e.module_prefab, resources, availableResources, resourceChangeRequests, elapsed_s); break;
                }
            }
        }
示例#8
0
        // consume EC for transmission, and transmit science data
        public static void Update(Vessel v, Vessel_info vi, VesselData vd, Vessel_resources resources, double elapsed_s)
        {
            // do nothing if science system is disabled
            if (!Features.Science)
            {
                return;
            }

            // avoid corner-case when RnD isn't live during scene changes
            // - this avoid losing science if the buffer reach threshold during a scene change
            if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && ResearchAndDevelopment.Instance == null)
            {
                return;
            }

            // get connection info
            ConnectionInfo conn = vi.connection;

            if (conn == null || String.IsNullOrEmpty(vi.transmitting))
            {
                return;
            }

            // get filename of data being downloaded
            var exp_filename = vi.transmitting;

            var drive = FindDrive(vd, exp_filename);

            // if some data is being downloaded
            // - avoid cornercase at scene changes
            if (exp_filename.Length > 0 && drive != null)
            {
                // get file
                File file = drive.files[exp_filename];

                // determine how much data is transmitted
                double transmitted = Math.Min(file.size, conn.rate * elapsed_s);

                // consume data in the file
                file.size -= transmitted;

                // accumulate in the buffer
                file.buff += transmitted;

                // if buffer is full, or file was transmitted completely
                if (file.size <= double.Epsilon || file.buff > buffer_capacity)
                {
                    // collect the science data
                    Credit(exp_filename, file.buff, true, v.protoVessel);

                    // reset the buffer
                    file.buff = 0.0;
                }

                // if file was transmitted completely
                if (file.size <= double.Epsilon)
                {
                    // remove the file
                    drive.files.Remove(exp_filename);

                    // same file on another drive?
                    drive = FindDrive(vd, exp_filename);

                    if (!file.silentTransmission && drive == null)
                    {
                        // inform the user
                        Message.Post(
                            Lib.BuildString("<color=cyan><b>DATA RECEIVED</b></color>\nTransmission of <b>", Experiment(exp_filename).name, "</b> completed"),
                            Lib.TextVariant("Our researchers will jump on it right now", "The checksum is correct, data must be valid"));
                    }
                }
            }
        }
示例#9
0
        public static void Load(ConfigNode node)
        {
            // get version (or use current one for new savegames)
            string versionStr = Lib.ConfigValue(node, "version", Lib.KerbalismVersion.ToString());

            // sanitize old saves (pre 3.1) format (X.X.X.X) to new format (X.X)
            if (versionStr.Split('.').Length > 2)
            {
                versionStr = versionStr.Split('.')[0] + "." + versionStr.Split('.')[1];
            }
            version = new Version(versionStr);

            // if this is an unsupported version, print warning
            if (version <= new Version(1, 2))
            {
                Lib.Log("loading save from unsupported version " + version);
            }

            // get unique id (or generate one for new savegames)
            uid = Lib.ConfigValue(node, "uid", Lib.RandomInt(int.MaxValue));

            // load kerbals data
            kerbals = new Dictionary <string, KerbalData>();
            if (node.HasNode("kerbals"))
            {
                foreach (var kerbal_node in node.GetNode("kerbals").GetNodes())
                {
                    kerbals.Add(From_safe_key(kerbal_node.name), new KerbalData(kerbal_node));
                }
            }

            // load the science database, has to be before vessels are loaded
            ScienceDB.Load(node);

            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.DB.Load.Vessels");
            vessels.Clear();
            // flightstate will be null when first creating the game
            if (HighLogic.CurrentGame.flightState != null)
            {
                ConfigNode vesselsNode = node.GetNode("vessels2");
                if (vesselsNode == null)
                {
                    vesselsNode = new ConfigNode();
                }
                // HighLogic.CurrentGame.flightState.protoVessels is what is used by KSP to persist vessels
                // It is always available and synchronized in OnLoad, no matter the scene, excepted on the first OnLoad in a new game
                foreach (ProtoVessel pv in HighLogic.CurrentGame.flightState.protoVessels)
                {
                    if (pv.vesselID == Guid.Empty)
                    {
                        // It seems flags are saved with an empty GUID. skip them.
                        Lib.LogDebug("Skipping VesselData load for vessel with empty GUID :" + pv.vesselName);
                        continue;
                    }

                    VesselData vd = new VesselData(pv, vesselsNode.GetNode(pv.vesselID.ToString()));
                    vessels.Add(pv.vesselID, vd);
                    Lib.LogDebug("VesselData loaded for vessel " + pv.vesselName);
                }
            }
            UnityEngine.Profiling.Profiler.EndSample();

            // for compatibility with old saves, convert drives data (it's now saved in PartData)
            if (node.HasNode("drives"))
            {
                Dictionary <uint, PartData> allParts = new Dictionary <uint, PartData>();
                foreach (VesselData vesselData in vessels.Values)
                {
                    foreach (PartData partData in vesselData.PartDatas)
                    {
                        // we had a case of someone having a save with multiple parts having the same flightID
                        // 5 duplicates, all were asteroids.
                        if (!allParts.ContainsKey(partData.FlightId))
                        {
                            allParts.Add(partData.FlightId, partData);
                        }
                    }
                }

                foreach (var drive_node in node.GetNode("drives").GetNodes())
                {
                    uint driveId = Lib.Parse.ToUInt(drive_node.name);
                    if (allParts.ContainsKey(driveId))
                    {
                        allParts[driveId].Drive = new Drive(drive_node);
                    }
                }
            }

            // load bodies data
            storms = new Dictionary <string, StormData>();
            if (node.HasNode("bodies"))
            {
                foreach (var body_node in node.GetNode("bodies").GetNodes())
                {
                    storms.Add(From_safe_key(body_node.name), new StormData(body_node));
                }
            }

            // load landmark data
            if (node.HasNode("landmarks"))
            {
                landmarks = new LandmarkData(node.GetNode("landmarks"));
            }
            else
            {
                landmarks = new LandmarkData();
            }

            // load ui data
            if (node.HasNode("ui"))
            {
                ui = new UIData(node.GetNode("ui"));
            }
            else
            {
                ui = new UIData();
            }

            // if an old savegame was imported, log some debug info
            if (version != Lib.KerbalismVersion)
            {
                Lib.Log("savegame converted from version " + version + " to " + Lib.KerbalismVersion);
            }
        }
示例#10
0
 private static double HabitatRadiation(VesselData vd)
 {
     return((1.0 - vd.Shielding) * vd.EnvHabitatRadiation);
 }