Esempio n. 1
0
        // Simulate resources production/consumption for unloaded vessel
        public static string BackgroundUpdate(Vessel v, ProtoPartSnapshot part_snapshot, ProtoPartModuleSnapshot module_snapshot, PartModule proto_part_module, Part proto_part, Dictionary <string, double> availableResources, List <KeyValuePair <string, double> > resourceChangeRequest, double elapsed_s)
        {
            ProtoPartModuleSnapshot reactor = KSHUtils.FindPartModuleSnapshot(part_snapshot, engineModuleName);

            if (reactor != null)
            {
                if (Lib.Proto.GetBool(reactor, "Enabled") && Lib.Proto.GetBool(module_snapshot, "GeneratesElectricity"))
                {
                    float curThrottle       = Lib.Proto.GetFloat(reactor, "CurrentReactorThrottle") / 100f;
                    float minThrottle       = Lib.Proto.GetFloat(module_snapshot, "MinThrottle");
                    float maxThrottle       = Lib.Proto.GetFloat(module_snapshot, "MaxThrottle");
                    float maxECGeneration   = Lib.Proto.GetFloat(module_snapshot, "MaxECGeneration");
                    bool  needToStopReactor = false;
                    if (maxECGeneration > 0)
                    {
                        VesselResources resources = KERBALISM.ResourceCache.Get(v);
                        if (!(proto_part_module as SystemHeatFissionEngineKerbalismUpdater).resourcesListParsed)
                        {
                            (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).ParseResourcesList(proto_part);
                        }

                        // Mininum reactor throttle
                        // Some input/output resources will always be consumed/produced as long as minThrottle > 0
                        if (minThrottle > 0)
                        {
                            ResourceRecipe recipe = new ResourceRecipe(KERBALISM.ResourceBroker.GetOrCreate(
                                                                           brokerName,
                                                                           KERBALISM.ResourceBroker.BrokerCategory.Converter,
                                                                           brokerTitle));
                            foreach (ResourceRatio ir in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).inputs)
                            {
                                recipe.AddInput(ir.ResourceName, ir.Ratio * minThrottle * elapsed_s);
                                if (resources.GetResource(v, ir.ResourceName).Amount < double.Epsilon)
                                {
                                    // Input resource amount is zero - stop reactor
                                    needToStopReactor = true;
                                }
                            }
                            foreach (ResourceRatio or in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).outputs)
                            {
                                recipe.AddOutput(or.ResourceName, or.Ratio * minThrottle * elapsed_s, dump: false);
                                if (1 - resources.GetResource(v, or.ResourceName).Level < double.Epsilon)
                                {
                                    // Output resource is at full capacity
                                    needToStopReactor = true;
                                    Message.Post(
                                        Severity.warning,
                                        Localizer.Format(
                                            "#LOC_KerbalismSystemHeat_ReactorOutputResourceFull",
                                            or.ResourceName,
                                            v.GetDisplayName(),
                                            part_snapshot.partName)
                                        );
                                }
                            }
                            recipe.AddOutput("ElectricCharge", minThrottle * maxECGeneration * elapsed_s, dump: true);
                            resources.AddRecipe(recipe);
                        }

                        if (!needToStopReactor)
                        {
                            if (!Lib.Proto.GetBool(reactor, "ManualControl"))
                            {
                                // Automatic reactor throttle mode
                                curThrottle = maxThrottle;
                            }
                            curThrottle -= minThrottle;
                            if (curThrottle > 0)
                            {
                                ResourceRecipe recipe = new ResourceRecipe(KERBALISM.ResourceBroker.GetOrCreate(
                                                                               brokerName,
                                                                               KERBALISM.ResourceBroker.BrokerCategory.Converter,
                                                                               brokerTitle));
                                foreach (ResourceRatio ir in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).inputs)
                                {
                                    recipe.AddInput(ir.ResourceName, ir.Ratio * curThrottle * elapsed_s);
                                    if (resources.GetResource(v, ir.ResourceName).Amount < double.Epsilon)
                                    {
                                        // Input resource amount is zero - stop reactor
                                        needToStopReactor = true;
                                    }
                                }
                                foreach (ResourceRatio or in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).outputs)
                                {
                                    recipe.AddOutput(or.ResourceName, or.Ratio * curThrottle * elapsed_s, dump: false);
                                    if (1 - resources.GetResource(v, or.ResourceName).Level < double.Epsilon)
                                    {
                                        // Output resource is at full capacity
                                        needToStopReactor = true;
                                        Message.Post(
                                            Severity.warning,
                                            Localizer.Format(
                                                "#LOC_KerbalismSystemHeat_ReactorOutputResourceFull",
                                                or.ResourceName,
                                                v.GetDisplayName(),
                                                part_snapshot.partName)
                                            );
                                    }
                                }
                                recipe.AddOutput("ElectricCharge", curThrottle * maxECGeneration * elapsed_s, dump: false);
                                resources.AddRecipe(recipe);
                            }
                        }
                    }

                    // Disable reactor
                    if (needToStopReactor)
                    {
                        Lib.Proto.Set(reactor, "Enabled", false);
                    }
                }
                else
                {
                    // Reactor disabled - radiation decay mechanics
                    if (Features.Radiation &&
                        Lib.Proto.GetBool(module_snapshot, "ReactorHasStarted") &&
                        Lib.Proto.GetDouble(module_snapshot, "ReactorStoppedTimestamp") > 0 &&
                        Lib.Proto.GetDouble(module_snapshot, "MinEmissionPercent") < 100)
                    {
                        ProtoPartModuleSnapshot emitter = KSHUtils.FindPartModuleSnapshot(part_snapshot, "Emitter");
                        if (emitter != null)
                        {
                            double EmitterMaxRadiation = Lib.Proto.GetDouble(module_snapshot, "EmitterMaxRadiation");
                            double MinEmissionPercent  = Lib.Proto.GetDouble(module_snapshot, "MinEmissionPercent");
                            double EmissionDecayRate   = Lib.Proto.GetDouble(module_snapshot, "EmissionDecayRate");
                            double MinRadiation        = EmitterMaxRadiation * MinEmissionPercent / 100;
                            if (EmissionDecayRate <= 0)
                            {
                                Lib.Proto.Set(emitter, "radiation", MinRadiation);
                                Lib.Proto.Set(module_snapshot, "ReactorStoppedTimestamp", 0d);
                            }
                            else
                            {
                                double secondsPassed = Planetarium.GetUniversalTime() - Lib.Proto.GetDouble(module_snapshot, "ReactorStoppedTimestamp");
                                if (secondsPassed > 0)
                                {
                                    double NewRadiation = EmitterMaxRadiation * (100 - secondsPassed / EmissionDecayRate) / 100;
                                    if (NewRadiation <= MinRadiation)
                                    {
                                        NewRadiation = MinRadiation;
                                        Lib.Proto.Set(module_snapshot, "ReactorStoppedTimestamp", 0d);
                                    }
                                    Lib.Proto.Set(emitter, "radiation", NewRadiation);
                                }
                            }
                        }
                    }
                }
                // Prevent resource consumption in ModuleSystemHeatFissionReactor.DoCatchup()
                // by setting LastUpdate to current time
                Lib.Proto.Set(reactor, "LastUpdateTime", Planetarium.GetUniversalTime());
                return(brokerTitle);
            }
            return("ERR: no engine");
        }