Exemple #1
0
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                return;
            }

            bool manual_upgrade = false;

            if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
            {
                if (upgradeTechReq != null)
                {
                    if (PluginHelper.hasTech(upgradeTechReq))
                    {
                        hasrequiredupgrade = true;
                    }
                    else if (upgradeTechReq == "none")
                    {
                        manual_upgrade = true;
                    }
                }
                else
                {
                    manual_upgrade = true;
                }
            }
            else
            {
                hasrequiredupgrade = true;
            }

            if (coreInit == false)
            {
                coreInit = true;
                if (hasrequiredupgrade)
                {
                    isupgraded = true;
                }
            }

            if (manual_upgrade)
            {
                hasrequiredupgrade = true;
            }

            if (isupgraded)
            {
                computercoreType = upgradedName;
                if (nameStr == "")
                {
                    ConfigNode[] namelist = ComputerCore.getNames();
                    Random       rands    = new Random();
                    ConfigNode   myName   = namelist[rands.Next(0, namelist.Length)];
                    nameStr = myName.GetValue("name");
                }

                double now                 = Planetarium.GetUniversalTime();
                double time_diff           = now - last_active_time;
                float  altitude_multiplier = (float)(vessel.altitude / (vessel.mainBody.Radius));
                altitude_multiplier = Math.Max(altitude_multiplier, 1);

                double science_to_add = baseScienceRate * time_diff / 86400 * electrical_power_ratio * PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed) / ((float)Math.Sqrt(altitude_multiplier));
                science_awaiting_addition = science_to_add;

                var curReaction = this.part.Modules["ModuleReactionWheel"] as ModuleReactionWheel;
                curReaction.PitchTorque = 5;
                curReaction.RollTorque  = 5;
                curReaction.YawTorque   = 5;
            }
            else
            {
                computercoreType = originalName;
            }


            this.part.force_activate();
        }
        public override void OnUpdate()
        {
            bool inAtmos = false;

            if (vessel.altitude <= PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody))
            {
                telescopeIsEnabled = false;
                inAtmos            = true;
            }
            Events["beginOberservations"].active = !inAtmos && !telescopeIsEnabled;
            Events["stopOberservations"].active  = telescopeIsEnabled;
            Fields["sciencePerDay"].guiActive    = telescopeIsEnabled;
            performPcnt   = (perform_factor_d * 100).ToString("0.0") + "%";
            sciencePerDay = (science_rate * 86400).ToString("0.00") + " Science/Day";
            double current_au = Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position) / Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position);

            if (vessel.FindPartModulesImplementing <ScienceModule>().Count > 0 || vessel.FindPartModulesImplementing <ComputerCore>().Count > 0)
            {
                List <ComputerCore>  cores        = vessel.FindPartModulesImplementing <ComputerCore>();
                List <ScienceModule> science_labs = vessel.FindPartModulesImplementing <ScienceModule>();
                bool upgraded_core = false;
                bool crewed_lab    = false;
                foreach (ComputerCore core in cores)
                {
                    upgraded_core = upgraded_core ? upgraded_core : core.isupgraded;
                }
                foreach (ScienceModule science_lab in science_labs)
                {
                    crewed_lab = crewed_lab ? crewed_lab : (science_lab.part.protoModuleCrew.Count > 0);
                }

                if (current_au >= 548 && !inAtmos && (crewed_lab || upgraded_core))
                {
                    if (vessel.orbit.eccentricity < 0.8)
                    {
                        Events["beginOberservations2"].active = true;
                        if (telescopeIsEnabled && dpo)
                        {
                            gLensStr = "Ongoing.";
                        }
                        else
                        {
                            gLensStr = "Available.";
                        }
                    }
                    else
                    {
                        Events["beginOberservations2"].active = false;
                        gLensStr = "Eccentricity: " + vessel.orbit.eccentricity.ToString("0.0") + "; < 0.8 Required";
                    }
                }
                else
                {
                    Events["beginOberservations2"].active = false;
                    gLensStr = current_au.ToString("0.0") + " AU; Required 548 AU";
                }
            }
            else
            {
                Events["beginOberservations2"].active = false;
                gLensStr = "Science Lab/Computer Core required";
            }

            if (helium_time_scale <= 0)
            {
                performPcnt = "Helium Coolant Deprived.";
            }
        }
 private void UpdateAmounts()
 {
     capacityStr  = PluginHelper.formatMassStr(antimatterResource.amount * antimatterDensity);
     maxAmountStr = PluginHelper.formatMassStr(antimatterResource.maxAmount * antimatterDensity);
 }
Exemple #4
0
 public static bool HasTechRequirementAndNotEmpty(string techName)
 {
     return(techName != String.Empty && PluginHelper.upgradeAvailable(techName));
 }
        public void onVesselAboutToBeDestroyed(EventReport report)
        {
            Debug.Log("[KSP Interstellar] Handling Impactor");

            ConfigNode config;
            ConfigNode science_node;

            Vessel vessel = report.origin.vessel;
            float  vesselMass;
            int    science_experiment_number = 0;

            string vessel_impact_node_string  = string.Concat("IMPACT_", vessel.id.ToString());
            string vessel_seismic_node_string = string.Concat("SEISMIC_SCIENCE_", vessel.mainBody.name.ToUpper());

            // Do nothing if we don't have a vessel.  This seems improbable, but who knows.
            if (vessel == null)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored because the vessel is undefined.");
                return;
            }

            // Do nothing if we have recorded an impact less than 10 physics updates ago.  This probably means this call
            // is a duplicate of a previous call.
            if (Planetarium.GetUniversalTime() - this.lastImpactTime < TimeWarp.fixedDeltaTime * 10f)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored because we've just recorded an impact.");
                return;
            }

            // Do nothing if we are a debris item less than ten physics-updates old.  That probably means we were
            // generated by a recently-recorded impact.
            if (vessel.vesselType == VesselType.Debris && vessel.missionTime < Time.fixedDeltaTime * 10f)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel being brand-new debris.");
                return;
            }

            vesselMass = vessel.GetTotalMass();

            // Do nothing if we aren't very near the terrain.  Note that using heightFromTerrain probably allows
            // impactors against the ocean floor... good luck.
            float vesselDimension = vessel.MOI.magnitude / vesselMass;

            if (vessel.heightFromSurface > Mathf.Max(vesselDimension, 0.75f))
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel altitude being too high.");
                return;
            }

            // Do nothing if we aren't impacting the surface.
            if (!(
                    report.other.ToLower().Contains(string.Intern("surface")) ||
                    report.other.ToLower().Contains(string.Intern("terrain")) ||
                    report.other.ToLower().Contains(vessel.mainBody.name.ToLower())
                    ))
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to not impacting the surface.");
                return;
            }

            /*
             * NOTE: This is a deviation from current KSPI behavior.  KSPI currently registers an impact over 40 m/s
             * regardless of its mass; this means that trivially light impactors (single instruments, even) could
             * trigger the experiment.
             *
             * The guard below requires that the impactor have at least as much vertical impact energy as a 1 Mg
             * object traveling at 40 m/s.  This means that nearly-tangential impacts or very light impactors will need
             * to be much faster, but that heavier impactors may be slower.
             *
             * */
            if ((Math.Pow(vessel.verticalSpeed, 2d) * vesselMass / 2d < 800d) && vessel.verticalSpeed > 20d)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel imparting too little impact energy.");
                return;
            }

            config = PluginHelper.getPluginSaveFile();
            if (config.HasNode(vessel_seismic_node_string))
            {
                science_node = config.GetNode(vessel_seismic_node_string);
                science_experiment_number = science_node.nodes.Count;

                if (science_node.HasNode(vessel_impact_node_string))
                {
                    Debug.Log("[KSP Interstellar] Impactor: Ignored because this vessel's impact has already been recorded.");
                    return;
                }
            }
            else
            {
                science_node = config.AddNode(vessel_seismic_node_string);
                science_node.AddValue("name", "interstellarseismicarchive");
            }

            int      body                = vessel.mainBody.flightGlobalsIndex;
            Vector3d net_vector          = Vector3d.zero;
            bool     first               = true;
            double   distribution_factor = 0;

            foreach (Vessel conf_vess in FlightGlobals.Vessels)
            {
                String vessel_probe_node_string = string.Concat("VESSEL_SEISMIC_PROBE_", conf_vess.id.ToString());

                if (config.HasNode(vessel_probe_node_string))
                {
                    ConfigNode probe_node = config.GetNode(vessel_probe_node_string);

                    // If the seismometer is inactive, skip it.
                    bool is_active = false;
                    if (probe_node.HasValue("is_active"))
                    {
                        bool.TryParse(probe_node.GetValue("is_active"), out is_active);
                        if (!is_active)
                        {
                            continue;
                        }
                    }

                    // If the seismometer is on another planet, skip it.
                    int planet = -1;
                    if (probe_node.HasValue("celestial_body"))
                    {
                        int.TryParse(probe_node.GetValue("celestial_body"), out planet);
                        if (planet != body)
                        {
                            continue;
                        }
                    }

                    // do sciency stuff
                    Vector3d surface_vector = (conf_vess.transform.position - FlightGlobals.Bodies[body].transform.position);
                    surface_vector = surface_vector.normalized;
                    if (first)
                    {
                        first               = false;
                        net_vector          = surface_vector;
                        distribution_factor = 1;
                    }
                    else
                    {
                        distribution_factor += 1.0 - Vector3d.Dot(surface_vector, net_vector.normalized);
                        net_vector           = net_vector + surface_vector;
                    }
                }
            }

            distribution_factor = Math.Min(distribution_factor, 3.5); // no more than 3.5x boost to science by using multiple detectors
            if (distribution_factor > 0 && !double.IsInfinity(distribution_factor) && !double.IsNaN(distribution_factor))
            {
                ScreenMessages.PostScreenMessage("Impact Recorded, science report can now be accessed from one of your accelerometers deployed on this body.", 5f, ScreenMessageStyle.UPPER_CENTER);
                this.lastImpactTime = Planetarium.GetUniversalTime();
                Debug.Log("[KSP Interstellar] Impactor: Impact registered!");

                ConfigNode impact_node = new ConfigNode(vessel_impact_node_string);
                impact_node.AddValue(string.Intern("transmitted"), bool.FalseString);
                impact_node.AddValue(string.Intern("vesselname"), vessel.vesselName);
                impact_node.AddValue(string.Intern("distribution_factor"), distribution_factor);
                science_node.AddNode(impact_node);

                config.Save(PluginHelper.PluginSaveFilePath);
            }
        }
        private void ScoopAthmosphere(double deltaTimeInSeconds, bool offlineCollecting)
        {
            string ors_atmospheric_resource_name = AtmosphericResourceHandler.getAtmosphericResourceName(vessel.mainBody, currentresource);
            string resourceDisplayName           = AtmosphericResourceHandler.getAtmosphericResourceDisplayName(vessel.mainBody, currentresource);

            if (ors_atmospheric_resource_name == null)
            {
                resflowf      = 0;
                recievedPower = "error";
                densityFractionOfUpperAthmosphere = "error";
                return;
            }

            // map ors resource to kspi resource
            if (PluginHelper.OrsResourceMappings == null || !PluginHelper.OrsResourceMappings.TryGetValue(ors_atmospheric_resource_name, out resourceStoragename))
            {
                resourceStoragename = ors_atmospheric_resource_name;
            }
            else if (!PartResourceLibrary.Instance.resourceDefinitions.Contains(resourceStoragename))
            {
                resourceStoragename = ors_atmospheric_resource_name;
            }

            var definition = PartResourceLibrary.Instance.GetDefinition(resourceStoragename);

            if (definition == null)
            {
                return;
            }

            double resourcedensity       = (double)(decimal)definition.density;
            double maxAltitudeAtmosphere = PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody);

            double upperAtmospherFraction = Math.Max(0, (vessel.altitude - maxAltitudeAtmosphere) / Math.Max(0.000001, maxAltitudeAtmosphere * PluginHelper.MaxAtmosphericAltitudeMult - maxAltitudeAtmosphere));
            double upperatmosphereDensity = 1 - upperAtmospherFraction;

            double airDensity = part.vessel.atmDensity + (PluginHelper.MinAtmosphericAirDensity * upperatmosphereDensity);

            atmosphericDensity = airDensity.ToString("0.00000000");

            var hydrogenTax = 0.4 * Math.Sin(upperAtmospherFraction * Math.PI * 0.5);
            var heliumTax   = 0.2 * Math.Sin(upperAtmospherFraction * Math.PI);

            double rescourceFraction = (1.0 - hydrogenTax - heliumTax) * AtmosphericResourceHandler.getAtmosphericResourceContent(vessel.mainBody, currentresource);

            // increase density hydrogen
            if (resourceDisplayName == "Hydrogen")
            {
                rescourceFraction += hydrogenTax;
            }
            else if (resourceDisplayName == "Helium")
            {
                rescourceFraction += heliumTax;
            }

            densityFractionOfUpperAthmosphere = (upperatmosphereDensity * 100).ToString("0.000") + "%";
            rescourcePercentage = rescourceFraction * 100;
            if (rescourceFraction <= 0 || vessel.altitude > (PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody) * PluginHelper.MaxAtmosphericAltitudeMult))
            {
                resflowf      = 0;
                recievedPower = "off";
                densityFractionOfUpperAthmosphere = "too high";
                rescourcePercentage = 0;
                return;
            }

            double airspeed            = part.vessel.srf_velocity.magnitude + 40;
            double air                 = airspeed * (airDensity / 1000) * scoopair / resourcedensity;
            double scoopedAtm          = air * rescourceFraction;
            double powerrequirementsMW = (scoopair / 0.15) * 6 * PluginHelper.PowerConsumptionMultiplier * powerReqMult;

            if (scoopedAtm > 0 && part.GetResourceSpareCapacity(resourceStoragename) > 0)
            {
                var powerRequest = powerrequirementsMW * TimeWarp.fixedDeltaTime;

                // calculate available power
                double powerreceivedMW = CheatOptions.InfiniteElectricity
                    ? powerRequest
                    : Math.Max(consumeFNResource(powerRequest, ResourceManager.FNRESOURCE_MEGAJOULES, TimeWarp.fixedDeltaTime), 0);

                double normalisedRevievedPowerMW = powerreceivedMW / TimeWarp.fixedDeltaTime;

                // if power requirement sufficiently low, retreive power from KW source
                if (powerrequirementsMW < 2 && normalisedRevievedPowerMW <= powerrequirementsMW)
                {
                    var requiredKW = (powerrequirementsMW - normalisedRevievedPowerMW) * 1000;
                    var recievedKW = part.RequestResource(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, requiredKW * TimeWarp.fixedDeltaTime);
                    powerreceivedMW += (recievedKW / 1000);
                }

                last_power_percentage = offlineCollecting ? last_power_percentage : powerreceivedMW / powerrequirementsMW / TimeWarp.fixedDeltaTime;
            }
            else
            {
                last_power_percentage = 0;
                powerrequirementsMW   = 0;
            }

            recievedPower = powerrequirementsMW < 2
                ? (last_power_percentage * powerrequirementsMW * 1000).ToString("0.0") + " KW / " + (powerrequirementsMW * 1000).ToString("0.0") + " KW"
                : (last_power_percentage * powerrequirementsMW).ToString("0.0") + " MW / " + powerrequirementsMW.ToString("0.0") + " MW";

            double resourceChange = scoopedAtm * last_power_percentage * deltaTimeInSeconds;

            if (offlineCollecting)
            {
                string numberformat = resourceChange > 100 ? "0" : "0.00";
                ScreenMessages.PostScreenMessage("Atmospheric Scoop collected " + resourceChange.ToString(numberformat) + " " + resourceStoragename, 10.0f, ScreenMessageStyle.LOWER_CENTER);
            }

            resflowf = part.RequestResource(resourceStoragename, -resourceChange);
            resflowf = -resflowf / TimeWarp.fixedDeltaTime;
            UpdateResourceFlow();
        }
Exemple #7
0
        public override void OnUpdate()
        {
            base.OnUpdate();

            if (ResearchAndDevelopment.Instance != null)
            {
                Events["RetrofitCore"].active = !isupgraded && ResearchAndDevelopment.Instance.Science >= upgradeCost;
            }
            else
            {
                Events["RetrofitCore"].active = false;
            }

            Fields["upgradeCostStr"].guiActive = !isupgraded;
            Fields["nameStr"].guiActive        = isupgraded;
            Fields["scienceRate"].guiActive    = isupgraded;

            float scienceratetmp = (float)(science_rate_f * GameConstants.KEBRIN_DAY_SECONDS) * PluginHelper.getScienceMultiplier(vessel);

            scienceRate = scienceratetmp.ToString("0.000") + "/Day";

            if (ResearchAndDevelopment.Instance != null)
            {
                upgradeCostStr = ResearchAndDevelopment.Instance.Science + "/" + upgradeCost.ToString("0") + " Science";
            }
        }
Exemple #8
0
        protected override bool generateScienceData()
        {
            ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment("FNSeismicProbeExperiment");

            if (experiment == null)
            {
                return(false);
            }
            //ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, "surface");
            //if (subject == null) {
            //    return false;
            //}
            //subject.scientificValue = 1;
            //subject.scienceCap = float.MaxValue;
            //subject.science = 1;
            //subject.subjectValue = 1;
            result_title   = "Impactor Experiment";
            result_string  = "No useful seismic data has been recorded.";
            transmit_value = 0;
            recovery_value = 0;
            data_size      = 0;
            xmit_scalar    = 1;
            ref_value      = 1;

            // science_data = new ScienceData(0, 1, 0, subject.id, "data");

            ConfigNode config = PluginHelper.getPluginSaveFile();

            if (config.HasNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()))
            {
                ConfigNode planet_data = config.GetNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper());
                foreach (ConfigNode probe_data in planet_data.nodes)
                {
                    if (probe_data.name.Contains("IMPACT_"))
                    {
                        science_vess_ref = probe_data.name;
                        bool   transmitted    = false;
                        string vessel_name    = "";
                        float  science_amount = 0;
                        int    exp_number     = 1;

                        if (probe_data.HasValue("transmitted"))
                        {
                            transmitted = bool.Parse(probe_data.GetValue("transmitted"));
                        }
                        if (probe_data.HasValue("vesselname"))
                        {
                            vessel_name = probe_data.GetValue("vesselname");
                        }
                        if (probe_data.HasValue("science"))
                        {
                            science_amount = float.Parse(probe_data.GetValue("science"));
                        }
                        if (probe_data.HasValue("number"))
                        {
                            exp_number = int.Parse(probe_data.GetValue("number"));
                        }

                        if (!transmitted)
                        {
                            ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, vessel.mainBody.name + "'s surface.");
                            if (subject == null)
                            {
                                return(false);
                            }
                            result_string           = vessel_name + " impacted into " + vessel.mainBody.name + " producing seismic activity.  From this data, information on the structure of " + vessel.mainBody.name + "'s crust can be determined.";
                            transmit_value          = science_amount;
                            recovery_value          = science_amount;
                            subject.subjectValue    = 1;
                            subject.scientificValue = 1;
                            subject.scienceCap      = 50 * 10 * PluginHelper.getScienceMultiplier(vessel); //PluginHelper.getImpactorScienceMultiplier(vessel.mainBody.flightGlobalsIndex);
                            //subject.science = 0;
                            data_size    = science_amount * 2.5f;
                            science_data = new ScienceData(science_amount, 1, 0, subject.id, "Impactor Data");
                            ref_value    = 50 * PluginHelper.getScienceMultiplier(vessel); // PluginHelper.getImpactorScienceMultiplier(vessel.mainBody.flightGlobalsIndex);
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
        public override void OnUpdate()
        {
            base.OnUpdate();
            Events["BeginResearch"].active        = isupgraded && !IsEnabled;
            Events["ReprocessFuel"].active        = !IsEnabled;
            Events["ActivateFactory"].active      = isupgraded && !IsEnabled;
            Events["ActivateElectrolysis"].active = false;
            Events["ActivateCentrifuge"].active   = isupgraded && !IsEnabled && vessel.Splashed;
            Events["StopActivity"].active         = isupgraded && IsEnabled;
            Fields["statusTitle"].guiActive       = isupgraded;

            // only show retrofit btoon if we can actualy upgrade
            Events["RetrofitEngine"].active = ResearchAndDevelopment.Instance == null ? false : !isupgraded && ResearchAndDevelopment.Instance.Science >= upgradeCost && hasrequiredupgrade;

            if (IsEnabled)
            {
                //anim [animName1].normalizedTime = 1f;
                statusTitle = modes[active_mode] + "...";
                Fields["scienceRate"].guiActive = false;

                Fields["collectedScience"].guiActive = false;
                Fields["reprocessingRate"].guiActive = false;
                Fields["antimatterRate"].guiActive   = false;
                Fields["electrolysisRate"].guiActive = false;
                Fields["centrifugeRate"].guiActive   = false;
                Fields["antimatterProductionEfficiency"].guiActive = false;
                Fields["powerStr"].guiActive = true;

                double currentpowertmp = electrical_power_ratio * PluginHelper.BasePowerConsumption * powerReqMult;
                powerStr = currentpowertmp.ToString("0.0000") + "MW / " + (powerReqMult * PluginHelper.BasePowerConsumption).ToString("0.0000") + "MW";
                if (active_mode == 0) // Research
                {
                    Fields["scienceRate"].guiActive      = true;
                    Fields["collectedScience"].guiActive = true;
                    double scienceratetmp = science_rate_f * PluginHelper.SecondsInDay * PluginHelper.getScienceMultiplier(vessel);
                    scienceRate      = scienceratetmp.ToString("0.0000") + "/Day";
                    collectedScience = science_to_add.ToString("0.000000");
                }
                else if (active_mode == 1) // Fuel Reprocessing
                {
                    Fields["reprocessingRate"].guiActive = true;
                    reprocessingRate = reprocessing_rate_f.ToString("0.0") + " Hours Remaining";
                }
                else if (active_mode == 2) // Antimatter
                {
                    currentpowertmp = electrical_power_ratio * PluginHelper.BaseAMFPowerConsumption * powerReqMult;
                    Fields["antimatterRate"].guiActive = true;
                    Fields["antimatterProductionEfficiency"].guiActive = true;
                    powerStr = currentpowertmp.ToString("0.00") + "MW / " + (powerReqMult * PluginHelper.BaseAMFPowerConsumption).ToString("0.00") + "MW";
                    antimatterProductionEfficiency = (anti_factory.getAntimatterProductionEfficiency() * 100).ToString("0.0000") + "%";
                    double antimatter_rate_per_day = antimatter_rate_f * PluginHelper.SecondsInDay;

                    if (antimatter_rate_per_day > 0.1)
                    {
                        antimatterRate = (antimatter_rate_per_day).ToString("0.0000") + " mg/day";
                    }
                    else
                    {
                        if (antimatter_rate_per_day > 0.1e-3)
                        {
                            antimatterRate = (antimatter_rate_per_day * 1e3).ToString("0.0000") + " ug/day";
                        }
                        else
                        {
                            antimatterRate = (antimatter_rate_per_day * 1e6).ToString("0.0000") + " ng/day";
                        }
                    }
                }
                else if (active_mode == 3) // Electrolysis
                {
                    currentpowertmp = electrical_power_ratio * PluginHelper.BaseELCPowerConsumption * powerReqMult;
                    Fields["electrolysisRate"].guiActive = true;
                    double electrolysisratetmp = -electrolysis_rate_f * PluginHelper.SecondsInDay;
                    electrolysisRate = electrolysisratetmp.ToString("0.0") + "mT/day";
                    powerStr         = currentpowertmp.ToString("0.00") + "MW / " + (powerReqMult * PluginHelper.BaseELCPowerConsumption).ToString("0.00") + "MW";
                }
                else if (active_mode == 4) // Centrifuge
                {
                    currentpowertmp = electrical_power_ratio * PluginHelper.BaseCentriPowerConsumption * powerReqMult;
                    Fields["centrifugeRate"].guiActive = true;
                    powerStr = currentpowertmp.ToString("0.00") + "MW / " + (powerReqMult * PluginHelper.BaseCentriPowerConsumption).ToString("0.00") + "MW";
                    double deut_per_hour = deut_rate_f * 3600;
                    centrifugeRate = deut_per_hour.ToString("0.00") + " Kg Deuterium/Hour";
                }
                else
                {
                    // nothing
                }
            }
            else
            {
                if (play_down)
                {
                    anim[animName1].speed          = -1;
                    anim[animName1].normalizedTime = 1;
                    anim.Blend(animName1, 2);
                    anim2[animName2].speed          = -1;
                    anim2[animName2].normalizedTime = 1;
                    anim2.Blend(animName2, 2);
                    play_down = false;
                }

                //anim [animName1].normalizedTime = 0;
                Fields["scienceRate"].guiActive      = false;
                Fields["collectedScience"].guiActive = false;
                Fields["reprocessingRate"].guiActive = false;
                Fields["antimatterRate"].guiActive   = false;
                Fields["powerStr"].guiActive         = false;
                Fields["centrifugeRate"].guiActive   = false;
                Fields["electrolysisRate"].guiActive = false;
                Fields["antimatterProductionEfficiency"].guiActive = false;

                if (crew_capacity_ratio > 0)
                {
                    statusTitle = "Idle";
                }
                else
                {
                    statusTitle = "Not enough crew";
                }
            }
        }
        public override void OnStart(PartModule.StartState state)
        {
            String[] resources_to_supply = { FNResourceManager.FNRESOURCE_MEGAJOULES, FNResourceManager.FNRESOURCE_WASTEHEAT, FNResourceManager.FNRESOURCE_THERMALPOWER };
            this.resources_to_supply = resources_to_supply;
            base.OnStart(state);
            if (state == StartState.Editor)
            {
                return;
            }

            if (part.FindModulesImplementing <MicrowavePowerTransmitter>().Count == 1)
            {
                part_transmitter = part.FindModulesImplementing <MicrowavePowerTransmitter>().First();
                has_transmitter  = true;
            }

            if (animTName != null)
            {
                animT = part.FindModelAnimators(animTName).FirstOrDefault();
                if (animT != null)
                {
                    animT[animTName].layer          = 1;
                    animT[animTName].normalizedTime = 0f;
                    animT[animTName].speed          = 0.001f;
                    animT.Play();
                }
            }

            if (animName != null)
            {
                anim = part.FindModelAnimators(animName).FirstOrDefault();
                if (anim != null)
                {
                    anim[animName].layer = 1;
                    if (connectedsatsi > 0 || connectedrelaysi > 0)
                    {
                        anim[animName].normalizedTime = 1f;
                        anim[animName].speed          = -1f;
                    }
                    else
                    {
                        anim[animName].normalizedTime = 0f;
                        anim[animName].speed          = 1f;
                    }
                    anim.Play();
                }
            }
            vmps = new List <VesselMicrowavePersistence>();
            vrps = new List <VesselRelayPersistence>();
            foreach (Vessel vess in FlightGlobals.Vessels)
            {
                String vesselID = vess.id.ToString();

                if (vess.isActiveVessel == false && vess.vesselName.ToLower().IndexOf("debris") == -1)
                {
                    ConfigNode config = PluginHelper.getPluginSaveFile();
                    if (config.HasNode("VESSEL_MICROWAVE_POWER_" + vesselID))
                    {
                        ConfigNode power_node    = config.GetNode("VESSEL_MICROWAVE_POWER_" + vesselID);
                        double     nuclear_power = 0;
                        double     solar_power   = 0;
                        if (power_node.HasValue("nuclear_power"))
                        {
                            nuclear_power = double.Parse(power_node.GetValue("nuclear_power"));
                        }
                        if (power_node.HasValue("solar_power"))
                        {
                            solar_power = double.Parse(power_node.GetValue("solar_power"));
                        }
                        if (nuclear_power > 0 || solar_power > 0)
                        {
                            VesselMicrowavePersistence vmp = new VesselMicrowavePersistence(vess);
                            vmp.setSolarPower(solar_power);
                            vmp.setNuclearPower(nuclear_power);
                            vmps.Add(vmp);
                        }
                    }

                    if (config.HasNode("VESSEL_MICROWAVE_RELAY_" + vesselID))
                    {
                        ConfigNode relay_node = config.GetNode("VESSEL_MICROWAVE_RELAY_" + vesselID);
                        if (relay_node.HasValue("relay"))
                        {
                            bool relay = bool.Parse(relay_node.GetValue("relay"));
                            if (relay)
                            {
                                VesselRelayPersistence vrp = new VesselRelayPersistence(vess);
                                vrp.setActive(relay);
                                vrps.Add(vrp);
                            }
                        }
                    }
                }
            }
            penaltyFreeDistance = Math.Sqrt(1 / ((microwaveAngleTan * microwaveAngleTan) / collectorArea));

            this.part.force_activate();
        }
        public static List <ElectricEnginePropellant> GetPropellantsEngineForType(int type)
        {
            ConfigNode[] propellantlist = GameDatabase.Instance.GetConfigNodes("ELECTRIC_PROPELLANT");
            List <ElectricEnginePropellant> propellant_list;

            if (propellantlist.Length == 0)
            {
                PluginHelper.showInstallationErrorMessage();
                propellant_list = new List <ElectricEnginePropellant>();
            }
            else
            {
                propellant_list = propellantlist.Select(prop => new ElectricEnginePropellant(prop))
                                  .Where(eep => (eep.SupportedEngines & type) == type && PluginHelper.HasTechRequirementOrEmpty(eep.TechRequirement)).ToList();
            }

            // initialize resource Defnitionions
            foreach (var propellant in propellant_list)
            {
                propellant.resourceDefinition = PartResourceLibrary.Instance.GetDefinition(propellant.propellant.name);
            }

            return(propellant_list);
        }
Exemple #12
0
        /// <summary>
        /// Returns transmitters which to which this vessel can connect, route efficiency and relays used for each one.
        /// </summary>
        /// <param name="maxHops">Maximum number of relays which can be used for connection to transmitter</param>
        protected IDictionary <VesselMicrowavePersistence, KeyValuePair <double, IEnumerable <VesselRelayPersistence> > > GetConnectedTransmitters(int maxHops = 25)
        {
            //these two dictionaries store transmitters and relays and best currently known route to them which is replaced if better one is found.

            var transmitterRouteDictionary = new Dictionary <VesselMicrowavePersistence, MicrowaveRoute>(); // stores all transmitter we can have a connection with
            var relayRouteDictionary       = new Dictionary <VesselRelayPersistence, MicrowaveRoute>();

            var transmittersToCheck = new List <VesselMicrowavePersistence>();//stores all transmiters to which we want to connect


            foreach (VesselMicrowavePersistence transmitter in MicrowaveSources.instance.transmitters.Values)
            {
                //first check for direct connection from current vessel to transmitters, will always be optimal
                if (transmitter.getAvailablePower() <= 0)
                {
                    continue;
                }

                // get transmitting vessel
                var transmitterVessel = transmitter.getVessel();

                //ignore if no power or transmitter is on the same vessel
                if (isInlineReceiver && transmitterVessel == vessel)
                {
                    continue;
                }

                if (PluginHelper.HasLineOfSightWith(this.vessel, transmitterVessel))
                {
                    double distance                 = ComputeDistance(this.vessel, transmitterVessel);
                    double facingFactor             = ComputeFacingFactor(transmitterVessel);
                    double distanceFacingEfficiency = ComputeDistanceFacingEfficiency(distance, facingFactor);
                    double atmosphereEfficency      = GetAtmosphericEfficiency(transmitterVessel);
                    double transmitterEfficency     = distanceFacingEfficiency * atmosphereEfficency;
                    transmitterRouteDictionary[transmitter] = new MicrowaveRoute(transmitterEfficency, distance, facingFactor); //store in dictionary that optimal route to this transmitter is direct connection, can be replaced if better route is found
                }
                transmittersToCheck.Add(transmitter);
            }

            //this algorithm processes relays in groups in which elements of the first group must be visible from receiver,
            //elements from the second group must be visible by at least one element from previous group and so on...

            var relaysToCheck     = new List <VesselRelayPersistence>();                      //relays which we have to check - all active relays will be here
            var currentRelayGroup = new List <KeyValuePair <VesselRelayPersistence, int> >(); //relays which are in line of sight, and we have not yet checked what they can see. Their index in relaysToCheck is also stored

            int relayIndex = 0;

            foreach (VesselRelayPersistence relay in MicrowaveSources.instance.relays.Values)
            {
                if (!relay.isActive())
                {
                    continue;
                }

                var relayVessel = relay.getVessel();

                //if (lineOfSightTo(relay.getVessel()))
                if (PluginHelper.HasLineOfSightWith(this.vessel, relayVessel))
                {
                    double distance                 = ComputeDistance(vessel, relayVessel);
                    double facingFactor             = ComputeFacingFactor(relayVessel);
                    double distanceFacingEfficiency = ComputeDistanceFacingEfficiency(distance, facingFactor);
                    double atmosphereEfficency      = GetAtmosphericEfficiency(relayVessel);
                    double transmitterEfficency     = distanceFacingEfficiency * atmosphereEfficency;
                    relayRouteDictionary[relay] = new MicrowaveRoute(transmitterEfficency, distance, facingFactor);//store in dictionary that optimal route to this relay is direct connection, can be replaced if better route is found
                    currentRelayGroup.Add(new KeyValuePair <VesselRelayPersistence, int>(relay, relayIndex));
                }
                relaysToCheck.Add(relay);
                relayIndex++;
            }

            int hops = 0; //number of hops between relays

            //pre-compute distances and visibility thus limiting number of checks to (Nr^2)/2 + NrNt +Nr + Nt
            if (hops < maxHops && transmittersToCheck.Any())
            {
                double[,] relayToRelayDistances       = new double[relaysToCheck.Count, relaysToCheck.Count];
                double[,] relayToTransmitterDistances = new double[relaysToCheck.Count, transmittersToCheck.Count];

                for (int i = 0; i < relaysToCheck.Count; i++)
                {
                    var relay = relaysToCheck[i];
                    for (int j = i + 1; j < relaysToCheck.Count; j++)
                    {
                        double visibilityAndDistance = ComputeVisibilityAndDistance(relay, relaysToCheck[j].getVessel());
                        relayToRelayDistances[i, j] = visibilityAndDistance;
                        relayToRelayDistances[j, i] = visibilityAndDistance;
                    }
                    for (int t = 0; t < transmittersToCheck.Count; t++)
                    {
                        relayToTransmitterDistances[i, t] = ComputeVisibilityAndDistance(relay, transmittersToCheck[t].getVessel());
                    }
                }

                HashSet <int> coveredRelays = new HashSet <int>();

                //runs as long as there is any relay to which we can connect and maximum number of hops have not been breached
                while (hops < maxHops && currentRelayGroup.Any())
                {
                    var nextRelayGroup = new List <KeyValuePair <VesselRelayPersistence, int> >(); //will put every relay which is in line of sight of any relay from currentRelayGroup here
                    foreach (var relayEntry in currentRelayGroup)                                  //relays visible from receiver in first iteration, then relays visible from them etc....
                    {
                        var            relay                  = relayEntry.Key;
                        MicrowaveRoute relayRoute             = relayRouteDictionary[relay]; // current best route for this relay
                        double         relayRouteFacingFactor = relayRoute.FacingFactor;     // it's always facing factor from the beggining of the route

                        for (int t = 0; t < transmittersToCheck.Count; t++)                  //check if this relay can connect to transmitters
                        {
                            double transmitterDistance = relayToTransmitterDistances[relayEntry.Value, t];

                            //it's >0 if it can see
                            if (transmitterDistance <= 0)
                            {
                                continue;
                            }

                            double         newDistance           = relayRoute.Distance + transmitterDistance;                            // total distance from receiver by this relay to transmitter
                            double         efficiencyByThisRelay = ComputeDistanceFacingEfficiency(newDistance, relayRouteFacingFactor); //efficiency
                            MicrowaveRoute currentOptimalRoute;

                            var transmitter = transmittersToCheck[t];

                            //this will return true if there is already a route to this transmitter
                            if (transmitterRouteDictionary.TryGetValue(transmitter, out currentOptimalRoute))
                            {
                                if (currentOptimalRoute.Efficiency < efficiencyByThisRelay)
                                {
                                    //if route using this relay is better then replace the old route
                                    transmitterRouteDictionary[transmitter] = new MicrowaveRoute(efficiencyByThisRelay, newDistance, relayRouteFacingFactor, relay);
                                }
                            }
                            else
                            {
                                //there is no other route to this transmitter yet known so algorithm puts this one as optimal
                                transmitterRouteDictionary[transmitter] = new MicrowaveRoute(efficiencyByThisRelay, newDistance, relayRouteFacingFactor, relay);
                            }
                        }

                        for (int r = 0; r < relaysToCheck.Count; r++)
                        {
                            var nextRelay = relaysToCheck[r];
                            if (nextRelay == relay)
                            {
                                continue;
                            }

                            double distanceToNextRelay = relayToRelayDistances[relayEntry.Value, r];

                            if (distanceToNextRelay <= 0)
                            {
                                continue;
                            }


                            double relayToNextRelayDistance = relayRoute.Distance + distanceToNextRelay;
                            double efficiencyByThisRelay    = ComputeDistanceFacingEfficiency(relayToNextRelayDistance, relayRouteFacingFactor);

                            MicrowaveRoute currentOptimalPredecessor;

                            if (relayRouteDictionary.TryGetValue(nextRelay, out currentOptimalPredecessor))
                            //this will return true if there is already a route to next relay
                            {
                                if (currentOptimalPredecessor.Efficiency < efficiencyByThisRelay)
                                {
                                    //if route using this relay is better

                                    relayRouteDictionary[nextRelay] = new MicrowaveRoute(efficiencyByThisRelay, relayToNextRelayDistance, relayRoute.FacingFactor, relay);
                                }
                                //we put it in dictionary as optimal
                            }
                            else //there is no other route to this relay yet known so we put this one as optimal
                            {
                                relayRouteDictionary[nextRelay] = new MicrowaveRoute(efficiencyByThisRelay, relayToNextRelayDistance, relayRoute.FacingFactor, relay);
                            }

                            if (!coveredRelays.Contains(r))
                            {
                                nextRelayGroup.Add(new KeyValuePair <VesselRelayPersistence, int>(nextRelay, r));
                                //in next iteration we will check what next relay can see
                                coveredRelays.Add(r);
                            }
                        }
                    }
                    currentRelayGroup = nextRelayGroup;
                    //we don't have to check old relays so we just replace whole List
                    hops++;
                }
            }

            //building final result
            var resultDictionary = new Dictionary <VesselMicrowavePersistence, KeyValuePair <double, IEnumerable <VesselRelayPersistence> > >();

            foreach (var transmitterEntry in transmitterRouteDictionary)
            {
                Stack <VesselRelayPersistence> relays = new Stack <VesselRelayPersistence>();//Last in, first out so relay visible from receiver will always be first
                VesselRelayPersistence         relay  = transmitterEntry.Value.PreviousRelay;
                while (relay != null)
                {
                    relays.Push(relay);
                    relay = relayRouteDictionary[relay].PreviousRelay;
                }
                resultDictionary.Add(transmitterEntry.Key, new KeyValuePair <double, IEnumerable <VesselRelayPersistence> >(transmitterEntry.Value.Efficiency, relays));
            }

            return(resultDictionary); //connectedTransmitters;
        }
Exemple #13
0
 protected double ComputeDistance(Vessel v1, Vessel v2)
 {
     return(Vector3d.Distance(PluginHelper.getVesselPos(v1), PluginHelper.getVesselPos(v2)));
 }
Exemple #14
0
 protected double ComputeVisibilityAndDistance(VesselRelayPersistence r, Vessel v)
 {
     return(PluginHelper.HasLineOfSightWith(r.getVessel(), v, 0)
         ? Vector3d.Distance(PluginHelper.getVesselPos(r.getVessel()), PluginHelper.getVesselPos(v))
         : -1);
 }
Exemple #15
0
        private void Window(int windowID)
        {
            bold_label = new GUIStyle(GUI.skin.label)
            {
                fontStyle = FontStyle.Bold
            };

            if (GUI.Button(new Rect(windowPosition.width - 20, 2, 18, 18), "x"))
            {
                render_window = false;
            }

            GUILayout.BeginVertical();
            if (vessel.altitude < PluginHelper.GetMaxAtmosphericAltitude(vessel.mainBody))
            {
                if (analysis_count > analysis_length)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(Localizer.Format("#LOC_KSPIE_FNMassSpectrometer_Gas"), bold_label, GUILayout.Width(150));     //"Gas"
                    GUILayout.Label(Localizer.Format("#LOC_KSPIE_MassSpectrometer_Abundance"), bold_label, GUILayout.Width(150)); //"Abundance"
                    GUILayout.EndHorizontal();
                    GUILayout.Space(5);
                    foreach (var atmospheric_resource in AtmosphericResourceHandler.GetAtmosphericCompositionForBody(vessel.mainBody).Values)
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.Label(atmospheric_resource.DisplayName, GUILayout.Width(150));
                        string resource_abundance_str;
                        if (atmospheric_resource.ResourceAbundance > 0.001)
                        {
                            resource_abundance_str = (atmospheric_resource.ResourceAbundance * 100.0) + "%";
                        }
                        else
                        {
                            if (atmospheric_resource.ResourceAbundance > 0.000001)
                            {
                                resource_abundance_str = (atmospheric_resource.ResourceAbundance * 1e6) + " ppm";
                            }
                            else
                            {
                                resource_abundance_str = (atmospheric_resource.ResourceAbundance * 1e9) + " ppb";
                            }
                        }
                        GUILayout.Label(resource_abundance_str, GUILayout.Width(150));
                        GUILayout.EndHorizontal();
                    }
                }
                else
                {
                    double percent_analysed = (double)analysis_count / analysis_length * 100;
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(Localizer.Format("#LOC_KSPIE_MassSpectrometer_Analysing"), GUILayout.Width(150));//"Analysing..."
                    GUILayout.Label(percent_analysed.ToString("0.00") + "%", GUILayout.Width(150));
                    GUILayout.EndHorizontal();
                }
            }
            else
            {
                GUILayout.Label(Localizer.Format("#LOC_KSPIE_FNLCMassSpectrometer_NoAtomspheretoSample"), GUILayout.ExpandWidth(true));//"--No Atmosphere to Sample--"
                analysis_count = 0;
            }
            GUILayout.EndVertical();
            GUI.DragWindow();
        }
        public override void OnFixedUpdate()
        {
            String[] resources_to_supply = { FNResourceManager.FNRESOURCE_MEGAJOULES, FNResourceManager.FNRESOURCE_WASTEHEAT };
            this.resources_to_supply = resources_to_supply;

            base.OnFixedUpdate();

            ConfigNode config          = PluginHelper.getPluginSaveFile();
            float      powerInputIncr  = 0;
            float      powerInputRelay = 0;
            int        activeSatsIncr  = 0;
            float      rangelosses     = 0;

            if (config != null && IsEnabled)
            {
                if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.95)
                {
                    IsEnabled = false;
                    deactivate_timer++;
                    if (FlightGlobals.ActiveVessel == vessel && deactivate_timer > 2)
                    {
                        ScreenMessages.PostScreenMessage("Warning Dangerous Overheating Detected: Emergency microwave power shutdown occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                    }
                    return;
                }
                deactivate_timer = 0;

                //Check to see if active vessel is a relay - for now we do not want a relay to connect to another relay to prevent energy loops
                String aid = vessel.id.ToString();
                if (config.HasValue(aid) == true)
                {
                    String agenType = config.GetValue(aid + "type");
                    if (agenType == "relay")
                    {
                        aIsRelay = true;
                    }
                    else
                    {
                        aIsRelay = false;
                    }
                }

                //if (activeCount % 100 == 0) {
                List <Vessel> vessels = FlightGlobals.Vessels;
                //print(vessels.Count.ToString() + "\n");

                //loop through vessels and attempt to add any active sattilites
                foreach (Vessel vess in vessels)
                {
                    String vid   = vess.id.ToString();
                    String vname = vess.vesselName.ToString().ToLower();
                    //print(vid + "\n");

                    //prevent adding active vessel as sat, skip calculations on debris, only add vessels with config value and line of sight to active vessel
                    if (vess.isActiveVessel == false && vname.IndexOf("debris") == -1 && config.HasValue(vid) == true && lineOfSightTo(vess) == true)
                    {
                        String powerinputsat = config.GetValue(vid);
                        String vgenType      = config.GetValue(vid + "type");
                        // if sat is not relay/nuclear check that it has line of site to sun
                        // NOTE: we need to add a check for relay to check lineOfSiteToSource(vess), and if solar a lineOfSiteFromSourceToSun - to check that the source which it is relaying is still attached to it, and if it is a solar source that it is recieving solar energy
                        if ((vgenType == "solar" && PluginHelper.lineOfSightToSun(vess)) || vgenType == "relay" || vgenType == "nuclear")
                        {
                            float inputPowerFixedAlt = 0;                                    // = float.Parse (powerinputsat) * PluginHelper.getSatFloatCurve ().Evaluate ((float)FlightGlobals.Bodies [0].GetAltitude (vess.transform.position));
                            float distance           = (float)Vector3d.Distance(vessel.transform.position, vess.transform.position);
                            float powerdissip        = (float)(Math.Tan(angle) * distance * Math.Tan(angle) * distance);
                            powerdissip = Math.Max(powerdissip / collectorArea, 1);
                            if (vgenType != "relay" && inputPowerFixedAlt > 0)
                            {
                                rangelosses += powerdissip;
                                //Scale energy reception based on angle of reciever to transmitter
                                Vector3d direction_vector = (vess.transform.position - vessel.transform.position).normalized;
                                float    facing_factor    = Vector3.Dot(part.transform.up, direction_vector);
                                facing_factor   = Mathf.Max(0, facing_factor);
                                powerInputIncr += inputPowerFixedAlt / powerdissip * facing_factor;
                                activeSatsIncr++;
                                connectedrelaysf = 0;
                                //print ("warp: sat added - genType: " + vgenType);
                            }
                            // only attach to one relay IF no sattilites are available for direct connection
                            else if (aIsRelay == false && activeSatsIncr < 1 && inputPowerFixedAlt > 0)
                            {
                                rangelosses = powerdissip;
                                //Scale energy reception based on angle of reciever to transmitter
                                Vector3d direction_vector = (vess.transform.position - vessel.transform.position).normalized;
                                float    facing_factor    = Vector3.Dot(part.transform.up, direction_vector);
                                facing_factor    = Mathf.Max(0, facing_factor);
                                powerInputRelay  = inputPowerFixedAlt / powerdissip * facing_factor;
                                connectedrelaysf = 1;
                                activeSatsIncr   = 0;
                                //print ("warp: relay added");
                            }
                        }
                    }
                }

                float atmosphericefficiency = (float)Math.Exp(-FlightGlobals.getStaticPressure(vessel.transform.position) / 5);

                if (activeSatsIncr > 0 && powerInputIncr > 0)
                {
                    this.rangelosses = rangelosses / activeSatsIncr;
                    totefff          = efficiency * atmosphericefficiency * 100 / rangelosses;
                    powerInput       = powerInputIncr * efficiency * atmosphericefficiency;
                    connectedsatsf   = activeSatsIncr;
                    //print ("warp: connected sat");
                }
                else if (connectedrelaysf > 0 && powerInputRelay > 0)
                {
                    this.rangelosses = rangelosses / connectedrelaysf;
                    totefff          = efficiency * atmosphericefficiency * 100 / rangelosses;
                    powerInput       = powerInputRelay * efficiency * atmosphericefficiency;
                    connectedsatsf   = 0;
                    //print("warp: connected relay");
                }
                else
                {
                    connectedrelaysf = 0;
                    connectedsatsf   = 0;
                    powerInput       = 0;
                    //print ("warp: no active sats or relays available");
                }
                //}
            }
            else
            {
                connectedrelaysf = 0;
                connectedsatsf   = 0;
                powerInput       = 0;
            }


            float powerInputMegajoules = powerInput / 1000.0f;

            supplyFNResource(powerInputMegajoules * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
            float waste_head_production = powerInput / 1000.0f / efficiency * (1.0f - efficiency);

            supplyFNResource(waste_head_production * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT);
            //activeCount++;
        }
        public override void OnStart(PartModule.StartState state)
        {
            Actions["ToggleToggleResourceAction"].guiName = Events["ToggleResource"].guiName = String.Format("Toggle Resource");

            if (state == StartState.Editor)
            {
                return;
            }

            this.part.force_activate();

            // verify if body has atmosphere at all
            if (!vessel.mainBody.atmosphere)
            {
                return;
            }

            // verify scoop was enabled
            if (!scoopIsEnabled)
            {
                return;
            }

            // verify a timestamp is available
            if (last_active_time == 0)
            {
                return;
            }

            // verify any power was avaialble in previous save
            if (last_power_percentage < 0.01)
            {
                return;
            }

            // verify altitude is not too high
            if (vessel.altitude > (PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody) * PluginHelper.MaxAtmosphericAltitudeMult))
            {
                ScreenMessages.PostScreenMessage("Vessel is too high for resource accumulation", 10, ScreenMessageStyle.LOWER_CENTER);
                return;
            }

            // verify altitude is not too low
            if (vessel.altitude < (PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody)))
            {
                ScreenMessages.PostScreenMessage("Vessel is too low for resource accumulation", 10, ScreenMessageStyle.LOWER_CENTER);
                return;
            }

            // verify eccentricity
            if (vessel.orbit.eccentricity > 0.1)
            {
                string message = "Eccentricity of " + vessel.orbit.eccentricity.ToString("0.0000") + " is too High for resource accumulations";
                ScreenMessages.PostScreenMessage(message, 10.0f, ScreenMessageStyle.LOWER_CENTER);
                return;
            }

            // verify that an electric or Thermal engine is available with high enough ISP
            var highIspEngine = part.vessel.parts.Find(p =>
                                                       p.FindModulesImplementing <ElectricEngineControllerFX>().Any(e => e.baseISP > 4200) ||
                                                       p.FindModulesImplementing <ThermalEngineController>().Any(e => e.AttachedReactor.CoreTemperature > 40000));

            if (highIspEngine == null)
            {
                ScreenMessages.PostScreenMessage("No engine available, with high enough Isp and propelant switch ability to compensate for atmospheric drag", 10, ScreenMessageStyle.LOWER_CENTER);
                return;
            }

            // calcualte time past since last frame
            double time_diff = (Planetarium.GetUniversalTime() - last_active_time) * 55;

            // scoop athmosphere for entire durration
            ScoopAthmosphere(time_diff, true);
        }
        public override void OnUpdate()
        {
            base.OnUpdate();
            if (!isSwappingFuelMode && (!CheatOptions.InfiniteElectricity && getDemandStableSupply(FNResourceManager.FNRESOURCE_MEGAJOULES) > 1.01) && IsEnabled && !fusion_alert)
            {
                fusionAlertFrames++;
            }
            else
            {
                fusion_alert      = false;
                fusionAlertFrames = 0;
            }

            if (fusionAlertFrames > 2)
            {
                ScreenMessages.PostScreenMessage("Warning: Fusion Reactor plasma heating cannot be guaranteed, reducing power requirements is recommended.", 0.1f, ScreenMessageStyle.UPPER_CENTER);
                fusion_alert = true;
            }

            electricPowerMaintenance = PluginHelper.getFormattedPowerString(power_consumed) + " / " + PluginHelper.getFormattedPowerString(HeatingPowerRequirements);
        }
 void OnGameStateSaved(Game game)
 {
     Debug.Log("[KSPI]: GameEventSubscriber - detected OnGameStateSaved");
     PluginHelper.LoadSaveFile();
 }
        public override void OnStart(PartModule.StartState state)
        {
            Actions["DeployRadiatorAction"].guiName  = Events["DeployRadiator"].guiName = String.Format("Deploy Radiator");
            Actions["RetractRadiatorAction"].guiName = Events["RetractRadiator"].guiName = String.Format("Retract Radiator");
            Actions["ToggleRadiatorAction"].guiName  = String.Format("Toggle Radiator");

            if (state == StartState.Editor)
            {
                if (hasTechsRequiredToUpgrade())
                {
                    isupgraded         = true;
                    hasrequiredupgrade = true;
                    isupgraded         = true;
                }
                return;
            }


            FNRadiator.list_of_radiators.Add(this);

            anim = part.FindModelAnimators(animName).FirstOrDefault();
            //orig_emissive_colour = part.renderer.material.GetTexture (emissive_property_name);
            if (anim != null)
            {
                anim [animName].layer = 1;

                if (radiatorIsEnabled)
                {
                    anim.Blend(animName, 1, 0);
                }
                else
                {
                    //anim.Blend (animName, 0, 0);
                }
                //anim.Play ();
            }

            if (isDeployable)
            {
                pivot           = part.FindModelTransform("suntransform");
                original_eulers = pivot.transform.localEulerAngles;
            }
            else
            {
                radiatorIsEnabled = true;
            }

            if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
            {
                if (PluginHelper.hasTech(upgradeTechReq))
                {
                    hasrequiredupgrade = true;
                }
            }
            else
            {
                hasrequiredupgrade = true;
            }

            if (radiatorInit == false)
            {
                radiatorInit = true;
            }

            if (!isupgraded)
            {
                radiatorType = originalName;
            }
            else
            {
                radiatorType = upgradedName;
                radiatorTemp = upgradedRadiatorTemp;
            }


            radiatorTempStr = radiatorTemp + "K";
            this.part.force_activate();
        }
Exemple #21
0
 void onGameStateSaved(Game game)
 {
     Debug.Log("[KSP Interstellar] GameEventSubscriber - detected onGameStateSaved");
     PluginHelper.LoadSaveFile();
 }
        public override void OnFixedUpdate()
        {
            float atmosphere_height = vessel.mainBody.maxAtmosphereAltitude;
            float vessel_height     = (float)vessel.mainBody.GetAltitude(vessel.transform.position);
            float conv_power_dissip = 0;

            if (vessel.altitude <= PluginHelper.getMaxAtmosphericAltitude(vessel.mainBody))
            {
                float pressure         = (float)FlightGlobals.getStaticPressure(vessel.transform.position);
                float dynamic_pressure = (float)(0.5 * pressure * 1.2041 * vessel.srf_velocity.sqrMagnitude / 101325.0);
                pressure += dynamic_pressure;
                float low_temp = FlightGlobals.getExternalTemperature(vessel.transform.position);

                float delta_temp = Mathf.Max(0, radiatorTemp - low_temp);
                conv_power_dissip = pressure * delta_temp * radiatorArea * rad_const_h / 1e6f * TimeWarp.fixedDeltaTime * convectiveBonus;
                if (!radiatorIsEnabled)
                {
                    conv_power_dissip = conv_power_dissip / 2.0f;
                }
                convectedThermalPower = consumeFNResource(conv_power_dissip, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime;

                if (radiatorIsEnabled && dynamic_pressure > 1.4854428818159388107574636072046e-3 && isDeployable)
                {
                    part.deactivate();

                    //part.breakingForce = 1;
                    //part.breakingTorque = 1;
                    part.decouple(1);
                }
            }


            if (radiatorIsEnabled)
            {
                if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 1 && current_rad_temp >= radiatorTemp)
                {
                    explode_counter++;
                    if (explode_counter > 25)
                    {
                        part.explode();
                    }
                }
                else
                {
                    explode_counter = 0;
                }

                double radiator_temperature_temp_val = radiatorTemp * Math.Pow(getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT), 0.25);
                if (FNReactor.hasActiveReactors(vessel))
                {
                    radiator_temperature_temp_val = Math.Min(FNReactor.getTemperatureofColdestReactor(vessel) / 1.01, radiator_temperature_temp_val);
                }

                double thermal_power_dissip = (GameConstants.stefan_const * radiatorArea * Math.Pow(radiator_temperature_temp_val, 4) / 1e6) * TimeWarp.fixedDeltaTime;
                radiatedThermalPower = consumeFNResource(thermal_power_dissip, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime;
                double instantaneous_rad_temp = (Math.Min(Math.Pow(radiatedThermalPower * 1e6 / (GameConstants.stefan_const * radiatorArea), 0.25), radiatorTemp));
                instantaneous_rad_temp = Math.Max(instantaneous_rad_temp, Math.Max(FlightGlobals.getExternalTemperature((float)vessel.altitude, vessel.mainBody) + 273.16, 2.7));
                if (current_rad_temp <= 0)
                {
                    current_rad_temp = instantaneous_rad_temp;
                }
                else
                {
                    current_rad_temp = instantaneous_rad_temp * alpha + (1.0 - alpha) * instantaneous_rad_temp;
                }

                if (isDeployable)
                {
                    Vector3 pivrot = pivot.rotation.eulerAngles;

                    pivot.Rotate(Vector3.up * 5f * TimeWarp.fixedDeltaTime * directionrotate);

                    Vector3 sunpos             = FlightGlobals.Bodies [0].transform.position;
                    Vector3 flatVectorToTarget = sunpos - transform.position;

                    flatVectorToTarget = flatVectorToTarget.normalized;
                    float dot = Mathf.Asin(Vector3.Dot(pivot.transform.right, flatVectorToTarget)) / Mathf.PI * 180.0f;

                    float anglediff = -dot;
                    oldangle = dot;
                    //print (dot);
                    directionrotate = anglediff / 5 / TimeWarp.fixedDeltaTime;
                    directionrotate = Mathf.Min(3, directionrotate);
                    directionrotate = Mathf.Max(-3, directionrotate);

                    part.maximum_drag = 0.8f;
                    part.minimum_drag = 0.8f;
                }
            }
            else
            {
                if (isDeployable)
                {
                    pivot.transform.localEulerAngles = original_eulers;
                }

                double radiator_temperature_temp_val = radiatorTemp * Math.Pow(getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT), 0.25);
                if (FNReactor.hasActiveReactors(vessel))
                {
                    radiator_temperature_temp_val = Math.Min(FNReactor.getTemperatureofColdestReactor(vessel) / 1.01, radiator_temperature_temp_val);
                }

                double thermal_power_dissip = (GameConstants.stefan_const * radiatorArea * Math.Pow(radiator_temperature_temp_val, 4) / 1e7) * TimeWarp.fixedDeltaTime;
                radiatedThermalPower = consumeFNResource(thermal_power_dissip, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime;
                double instantaneous_rad_temp = (Math.Min(Math.Pow(radiatedThermalPower * 1e7 / (GameConstants.stefan_const * radiatorArea), 0.25), radiatorTemp));
                instantaneous_rad_temp = Math.Max(instantaneous_rad_temp, Math.Max(FlightGlobals.getExternalTemperature((float)vessel.altitude, vessel.mainBody) + 273.16, 2.7));
                if (current_rad_temp <= 0)
                {
                    current_rad_temp = instantaneous_rad_temp;
                }
                else
                {
                    current_rad_temp = instantaneous_rad_temp * alpha + (1.0 - alpha) * instantaneous_rad_temp;
                }

                part.maximum_drag = 0.2f;
                part.minimum_drag = 0.2f;
            }
        }
Exemple #23
0
 public static bool HasTechRequirmentOrEmpty(string techName)
 {
     return(techName == String.Empty || PluginHelper.upgradeAvailable(techName));
 }
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                if (this.HasTechsRequiredToUpgrade())
                {
                    isupgraded = true;
                    upgradePartModule();
                }
                return;
            }

            if (isupgraded)
            {
                upgradePartModule();
            }
            else
            {
                if (this.HasTechsRequiredToUpgrade())
                {
                    hasrequiredupgrade = true;
                }
            }

            // update gui names
            Events["BeginResearch"].guiName = beginResearchName;

            reprocessor  = new NuclearFuelReprocessor(part);
            anti_factory = new AntimatterFactory(part);
            ConfigNode config = PluginHelper.getPluginSaveFile();

            part.force_activate();

            anim  = part.FindModelAnimators(animName1).FirstOrDefault();
            anim2 = part.FindModelAnimators(animName2).FirstOrDefault();
            if (anim != null && anim2 != null)
            {
                anim[animName1].layer  = 1;
                anim2[animName2].layer = 1;
                if (IsEnabled)
                {
                    //anim [animName1].normalizedTime = 1f;
                    //anim2 [animName2].normalizedTime = 1f;
                    //anim [animName1].speed = -1f;
                    //anim2 [animName2].speed = -1f;
                    anim.Blend(animName1, 1, 0);
                    anim2.Blend(animName2, 1, 0);
                }
                else
                {
                    //anim [animName1].normalizedTime = 0f;
                    //anim2 [animName2].normalizedTime = 0f;
                    //anim [animName1].speed = 1f;
                    //anim2 [animName2].speed = 1f;
                    //anim.Blend (animName1, 0, 0);global_rate_multipliers
                    //anim2.Blend (animName2, 0, 0);
                    play_down = false;
                }
                //anim.Play ();
                //anim2.Play ();
            }

            if (IsEnabled && last_active_time != 0)
            {
                float global_rate_multipliers = 1;
                crew_capacity_ratio     = ((float)part.protoModuleCrew.Count) / ((float)part.CrewCapacity);
                global_rate_multipliers = global_rate_multipliers * crew_capacity_ratio;

                if (active_mode == 0) // Science persistence
                {
                    double time_diff                 = Planetarium.GetUniversalTime() - last_active_time;
                    float  altitude_multiplier       = Math.Max((float)(vessel.altitude / (vessel.mainBody.Radius)), 1);
                    float  kerbalResearchSkillFactor = part.protoModuleCrew.Sum(proto_crew_member => GetKerbalScienceFactor(proto_crew_member) / 2f);

                    double science_to_increment = kerbalResearchSkillFactor * GameConstants.baseScienceRate * time_diff
                                                  / GameConstants.EARH_DAY_SECONDS * electrical_power_ratio * global_rate_multipliers * PluginHelper.getScienceMultiplier(vessel) //PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed)
                                                  / ((float)Math.Sqrt(altitude_multiplier));

                    science_to_increment = (double.IsNaN(science_to_increment) || double.IsInfinity(science_to_increment)) ? 0 : science_to_increment;
                    science_to_add      += (float)science_to_increment;
                }
                else if (active_mode == 2) // Antimatter persistence
                {
                    double time_diff = Planetarium.GetUniversalTime() - last_active_time;

                    List <PartResource> antimatter_resources = part.GetConnectedResources(InterstellarResourcesConfiguration.Instance.Antimatter).ToList();
                    float currentAntimatter_missing          = (float)antimatter_resources.Sum(ar => ar.maxAmount - ar.amount);

                    float  total_electrical_power_provided = (float)(electrical_power_ratio * (PluginHelper.BaseAMFPowerConsumption + PluginHelper.BasePowerConsumption) * 1E6);
                    double antimatter_mass = total_electrical_power_provided / GameConstants.warpspeed / GameConstants.warpspeed * 1E6 / 20000.0;
                    float  antimatter_peristence_to_add = (float)-Math.Min(currentAntimatter_missing, antimatter_mass * time_diff);
                    part.RequestResource("Antimatter", antimatter_peristence_to_add);
                }
            }
        }
Exemple #25
0
 public void UpdateGUI()
 {
     if (_bold_label == null)
     {
         _bold_label           = new GUIStyle(GUI.skin.label);
         _bold_label.fontStyle = FontStyle.Bold;
     }
     GUILayout.BeginHorizontal();
     GUILayout.Label("Power", _bold_label, GUILayout.Width(150));
     GUILayout.Label(PluginHelper.getFormattedPowerString(CurrentPower) + "/" + PluginHelper.getFormattedPowerString(PowerRequirements), GUILayout.Width(150));
     GUILayout.EndHorizontal();
     GUILayout.BeginHorizontal();
     GUILayout.Label("Hydrogen Consumption Rate", _bold_label, GUILayout.Width(150));
     GUILayout.Label(_hydrogen_consumption_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150));
     GUILayout.EndHorizontal();
     GUILayout.BeginHorizontal();
     GUILayout.Label("Methane Production Rate", _bold_label, GUILayout.Width(150));
     GUILayout.Label(_methane_production_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150));
     GUILayout.EndHorizontal();
     GUILayout.BeginHorizontal();
     GUILayout.Label("Oxygen Production Rate", _bold_label, GUILayout.Width(150));
     GUILayout.Label(_oxygen_production_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150));
     GUILayout.EndHorizontal();
 }
        public override void OnFixedUpdate()
        {
            float global_rate_multipliers = 1;

            crew_capacity_ratio     = ((float)part.protoModuleCrew.Count) / ((float)part.CrewCapacity);
            global_rate_multipliers = global_rate_multipliers * crew_capacity_ratio;

            if (!IsEnabled)
            {
                return;
            }

            if (active_mode == 0)  // Research
            {
                double electrical_power_provided = consumeFNResource(powerReqMult * PluginHelper.BasePowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
                electrical_power_ratio  = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BasePowerConsumption / powerReqMult);
                global_rate_multipliers = global_rate_multipliers * electrical_power_ratio;

                float kerbalScienceSkillFactor = part.protoModuleCrew.Sum(proto_crew_member => GetKerbalScienceFactor(proto_crew_member) / 2f);
                float altitude_multiplier      = Math.Max((float)(vessel.altitude / (vessel.mainBody.Radius)), 1);

                science_rate_f = (float)(kerbalScienceSkillFactor * GameConstants.baseScienceRate * PluginHelper.getScienceMultiplier(vessel) //PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed)
                                         / GameConstants.EARH_DAY_SECONDS * global_rate_multipliers
                                         / (Mathf.Sqrt(altitude_multiplier)));

                if (ResearchAndDevelopment.Instance != null && !double.IsNaN(science_rate_f) && !double.IsInfinity(science_rate_f))
                {
                    //ResearchAndDevelopment.Instance.Science = ResearchAndDevelopment.Instance.Science + science_rate_f * TimeWarp.fixedDeltaTime;
                    science_to_add += science_rate_f * TimeWarp.fixedDeltaTime;
                }
            }
            else if (active_mode == 1) // Fuel Reprocessing
            {
                double electrical_power_provided = consumeFNResource(powerReqMult * PluginHelper.BasePowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
                electrical_power_ratio  = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BasePowerConsumption / powerReqMult);
                global_rate_multipliers = global_rate_multipliers * electrical_power_ratio;
                reprocessor.UpdateFrame(global_rate_multipliers, true);

                if (reprocessor.getActinidesRemovedPerHour() > 0)
                {
                    reprocessing_rate_f = (float)(reprocessor.getRemainingAmountToReprocess() / reprocessor.getActinidesRemovedPerHour());
                }
                else
                {
                    IsEnabled = false;
                }
            }
            else if (active_mode == 2) //Antimatter
            {
                double electrical_power_provided = consumeFNResource(powerReqMult * PluginHelper.BaseAMFPowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
                electrical_power_ratio  = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BaseAMFPowerConsumption / powerReqMult);
                global_rate_multipliers = crew_capacity_ratio * electrical_power_ratio;
                anti_factory.produceAntimatterFrame(global_rate_multipliers);
                antimatter_rate_f = (float)anti_factory.getAntimatterProductionRate();
            }
            else if (active_mode == 3)
            {
                IsEnabled = false;
            }
            else if (active_mode == 4) // Centrifuge
            {
                if (vessel.Splashed)
                {
                    float electrical_power_provided = (float)consumeFNResource(powerReqMult * PluginHelper.BaseCentriPowerConsumption * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
                    electrical_power_ratio  = (float)(electrical_power_provided / TimeWarp.fixedDeltaTime / PluginHelper.BaseCentriPowerConsumption / powerReqMult);
                    global_rate_multipliers = global_rate_multipliers * electrical_power_ratio;
                    float deut_produced = (float)(global_rate_multipliers * GameConstants.deuterium_timescale * GameConstants.deuterium_abudance * 1000.0f);
                    deut_rate_f = -ORSHelper.fixedRequestResource(part, InterstellarResourcesConfiguration.Instance.Deuterium, -deut_produced * TimeWarp.fixedDeltaTime) / TimeWarp.fixedDeltaTime;
                }
                else
                {
                    ScreenMessages.PostScreenMessage("You must be splashed down to perform this activity.", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                    IsEnabled = false;
                }
            }

            if (electrical_power_ratio <= 0)
            {
                deut_rate_f         = 0;
                electrolysis_rate_f = 0;
                science_rate_f      = 0;
                antimatter_rate_f   = 0;
                reprocessing_rate_f = 0;
            }

            last_active_time = (float)Planetarium.GetUniversalTime();
        }
        public override void OnStart(PartModule.StartState state)
        {
            var exoticMatterResource = part.Resources.list.FirstOrDefault(r => r.resourceName == InterstellarResourcesConfiguration.Instance.ExoticMatter);

            // reset Exotic Matter Capacity
            if (exoticMatterResource != null)
            {
                part.mass = partMass;
                var ratio = Math.Min(1, Math.Max(0, exoticMatterResource.amount / exoticMatterResource.maxAmount));
                exoticMatterResource.maxAmount = 0.001;
                exoticMatterResource.amount    = exoticMatterResource.maxAmount * ratio;
            }

            InstanceID = GetInstanceID();

            if (IsSlave)
            {
                UnityEngine.Debug.Log("KSPI - AlcubierreDrive Slave " + InstanceID + " Started");
            }
            else
            {
                UnityEngine.Debug.Log("KSPI - AlcubierreDrive Master " + InstanceID + " Started");
            }

            if (!String.IsNullOrEmpty(AnimationName))
            {
                animationState = SetUpAnimation(AnimationName, this.part);
            }

            try
            {
                Events["StartCharging"].active       = !IsSlave;
                Events["StopCharging"].active        = !IsSlave;
                Events["ActivateWarpDrive"].active   = !IsSlave;
                Events["DeactivateWarpDrive"].active = !IsSlave;
                Events["ToggleWarpSpeedUp"].active   = !IsSlave;
                Events["ToggleWarpSpeedDown"].active = !IsSlave;
                Events["ReduceWarpPower"].active     = !IsSlave;

                Fields["exotic_power_required"].guiActive            = !IsSlave;
                Fields["WarpEngineThrottle"].guiActive               = !IsSlave;
                Fields["warpToMassRatio"].guiActive                  = !IsSlave;
                Fields["vesselTotalMass"].guiActive                  = !IsSlave;
                Fields["DriveStatus"].guiActive                      = !IsSlave;
                Fields["minPowerRequirementForLightSpeed"].guiActive = !IsSlave;
                Fields["currentPowerRequirementForWarp"].guiActive   = !IsSlave;
                Fields["sumOfAlcubierreDrives"].guiActive            = !IsSlave;

                Actions["StartChargingAction"].guiName       = Events["StartCharging"].guiName = String.Format("Start Charging");
                Actions["StopChargingAction"].guiName        = Events["StopCharging"].guiName = String.Format("Stop Charging");
                Actions["ToggleChargingAction"].guiName      = String.Format("Toggle Charging");
                Actions["ActivateWarpDriveAction"].guiName   = Events["ActivateWarpDrive"].guiName = String.Format("Activate Warp Drive");
                Actions["DeactivateWarpDriveAction"].guiName = Events["DeactivateWarpDrive"].guiName = String.Format("Deactivate Warp Drive");
                Actions["ToggleWarpSpeedUpAction"].guiName   = Events["ToggleWarpSpeedUp"].guiName = String.Format("Warp Speed (+)");
                Actions["ToggleWarpSpeedDownAction"].guiName = Events["ToggleWarpSpeedDown"].guiName = String.Format("Warp Speed (-)");

                if (state == StartState.Editor)
                {
                    return;
                }

                if (!IsSlave)
                {
                    UnityEngine.Debug.Log("KSPI - AlcubierreDrive Create Slaves");
                    alcubierreDrives = part.vessel.FindPartModulesImplementing <AlcubierreDrive>();
                    foreach (var drive in alcubierreDrives)
                    {
                        var driveId = drive.GetInstanceID();
                        if (driveId != InstanceID)
                        {
                            drive.IsSlave = true;
                            UnityEngine.Debug.Log("KSPI - AlcubierreDrive " + driveId + " != " + InstanceID);
                        }
                    }
                }

                UnityEngine.Debug.Log("KSPI - AlcubierreDrive OnStart step C ");

                this.part.force_activate();
                if (serialisedwarpvector != null)
                {
                    heading_act = ConfigNode.ParseVector3D(serialisedwarpvector);
                }

                warp_effect  = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                warp_effect2 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);

                warp_effect.collider.enabled  = false;
                warp_effect2.collider.enabled = false;

                Vector3 ship_pos     = new Vector3(part.transform.position.x, part.transform.position.y, part.transform.position.z);
                Vector3 end_beam_pos = ship_pos + transform.up * warp_size;
                Vector3 mid_pos      = (ship_pos - end_beam_pos) / 2.0f;

                warp_effect.transform.localScale = new Vector3(effectSize1, mid_pos.magnitude, effectSize1);
                warp_effect.transform.position   = new Vector3(mid_pos.x, ship_pos.y + mid_pos.y, mid_pos.z);
                warp_effect.transform.rotation   = part.transform.rotation;

                warp_effect2.transform.localScale = new Vector3(effectSize2, mid_pos.magnitude, effectSize2);
                warp_effect2.transform.position   = new Vector3(mid_pos.x, ship_pos.y + mid_pos.y, mid_pos.z);
                warp_effect2.transform.rotation   = part.transform.rotation;

                //warp_effect.layer = LayerMask.NameToLayer("Ignore Raycast");
                //warp_effect.renderer.material = new Material(KSP.IO.File.ReadAllText<AlcubierreDrive>("AlphaSelfIllum.shader"));

                warp_effect.renderer.material.shader  = Shader.Find("Unlit/Transparent");
                warp_effect2.renderer.material.shader = Shader.Find("Unlit/Transparent");

                warp_textures = new Texture[33];

                const string warp_tecture_path = "WarpPlugin/ParticleFX/warp";
                for (int i = 0; i < 11; i++)
                {
                    warp_textures[i] = GameDatabase.Instance.GetTexture((i > 0)
                                                ? warp_tecture_path + (i + 1).ToString()
                                                : warp_tecture_path, false);
                }

                warp_textures[11] = GameDatabase.Instance.GetTexture("WarpPlugin/ParticleFX/warp10", false);
                for (int i = 12; i < 33; i++)
                {
                    int j = i > 17 ? 34 - i : i;
                    warp_textures[i] = GameDatabase.Instance.GetTexture(j > 1 ?
                                                                        warp_tecture_path + (j + 1).ToString() : warp_tecture_path, false);
                }

                warp_textures2 = new Texture[33];

                const string warpr_tecture_path = "WarpPlugin/ParticleFX/warpr";
                for (int i = 0; i < 11; i++)
                {
                    warp_textures2[i] = GameDatabase.Instance.GetTexture((i > 0)
                                                ? warpr_tecture_path + (i + 1).ToString()
                                                : warpr_tecture_path, false);
                }

                warp_textures2[11] = GameDatabase.Instance.GetTexture("WarpPlugin/ParticleFX/warpr10", false);
                for (int i = 12; i < 33; i++)
                {
                    int j = i > 17 ? 34 - i : i;
                    warp_textures2[i] = GameDatabase.Instance.GetTexture(j > 1 ?
                                                                         warpr_tecture_path + (j + 1).ToString() : warpr_tecture_path, false);
                }

                warp_effect.renderer.material.color       = new Color(Color.cyan.r, Color.cyan.g, Color.cyan.b, 0.5f);
                warp_effect2.renderer.material.color      = new Color(Color.red.r, Color.red.g, Color.red.b, 0.1f);
                warp_effect.renderer.material.mainTexture = warp_textures[0];
                warp_effect.renderer.receiveShadows       = false;
                //warp_effect.layer = LayerMask.NameToLayer ("Ignore Raycast");
                //warp_effect.collider.isTrigger = true;
                warp_effect2.renderer.material.mainTexture       = warp_textures2[0];
                warp_effect2.renderer.receiveShadows             = false;
                warp_effect2.renderer.material.mainTextureOffset = new Vector2(-0.2f, -0.2f);
                //warp_effect2.layer = LayerMask.NameToLayer ("Ignore Raycast");
                //warp_effect2.collider.isTrigger = true;
                warp_effect2.renderer.material.renderQueue = 1000;
                warp_effect.renderer.material.renderQueue  = 1001;

                /*gameObject.AddComponent<Light>();
                 * gameObject.light.color = Color.cyan;
                 * gameObject.light.intensity = 1f;
                 * gameObject.light.range = 4000f;
                 * gameObject.light.type = LightType.Spot;
                 * gameObject.light.transform.position = end_beam_pos;
                 * gameObject.light.cullingMask = ~0;*/

                //light.

                warp_sound             = gameObject.AddComponent <AudioSource>();
                warp_sound.clip        = GameDatabase.Instance.GetAudioClip("WarpPlugin/Sounds/warp_sound");
                warp_sound.volume      = GameSettings.SHIP_VOLUME;
                warp_sound.panLevel    = 0;
                warp_sound.rolloffMode = AudioRolloffMode.Linear;
                warp_sound.Stop();

                if (IsEnabled)
                {
                    warp_sound.Play();
                    warp_sound.loop = true;
                }

                bool manual_upgrade = false;
                if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
                {
                    if (upgradeTechReq != null)
                    {
                        if (PluginHelper.hasTech(upgradeTechReq))
                        {
                            hasrequiredupgrade = true;
                        }
                        else if (upgradeTechReq == "none")
                        {
                            manual_upgrade = true;
                        }
                    }
                    else
                    {
                        manual_upgrade = true;
                    }
                }
                else
                {
                    hasrequiredupgrade = true;
                }

                if (warpInit == false)
                {
                    warpInit = true;
                    if (hasrequiredupgrade)
                    {
                        isupgraded = true;
                    }
                }

                if (manual_upgrade)
                {
                    hasrequiredupgrade = true;
                }


                if (isupgraded)
                {
                    warpdriveType = upgradedName;
                }
                else
                {
                    warpdriveType = originalName;
                }

                //warp_effect.transform.localScale.y = 2.5f;
                //warp_effect.transform.localScale.z = 200f;

                // disable charging at startup
                IsCharging = false;
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError("KSPI - AlcubierreDrive OnStart 1 Exception " + e.Message);
            }

            try
            {
                warpdriveType           = originalName;
                minimum_selected_factor = engine_throtle.ToList().IndexOf(engine_throtle.First(w => w == 1f));
                if (selected_factor == -1)
                {
                    selected_factor = minimum_selected_factor;
                }
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError("KSPI - AlcubierreDrive OnStart 2 Exception " + e.Message);
            }
        }
        public InterstellarResourcesConfiguration(ConfigNode plugin_settings)
        {
            if (plugin_settings != null)
            {
                if (plugin_settings.HasValue("AluminiumResourceName"))
                {
                    _aluminium = plugin_settings.GetValue("AluminiumResourceName");
                    Debug.Log("[KSP Interstellar] Aluminium resource name set to " + Aluminium);
                }
                if (plugin_settings.HasValue("AmmoniaResourceName"))
                {
                    _ammonia = plugin_settings.GetValue("AmmoniaResourceName");
                    Debug.Log("[KSP Interstellar] Ammonia resource name set to " + Ammonia);
                }
                if (plugin_settings.HasValue("ArgonResourceName"))
                {
                    _argon = plugin_settings.GetValue("ArgonResourceName");
                    Debug.Log("[KSP Interstellar] Argon resource name set to " + Argon);
                }
                if (plugin_settings.HasValue("CarbonDioxideResourceName"))
                {
                    _carbonDioxide = plugin_settings.GetValue("CarbonDioxideResourceName");
                    Debug.Log("[KSP Interstellar] CarbonDioxide resource name set to " + CarbonDioxide);
                }
                if (plugin_settings.HasValue("CarbonMonoxideResourceName"))
                {
                    _carbonMoxoxide = plugin_settings.GetValue("CarbonMonoxideResourceName");
                    Debug.Log("[KSP Interstellar] CarbonMonoxide resource name set to " + CarbonMoxoxide);
                }
                if (plugin_settings.HasValue("HeliumResourceName"))
                {
                    _helium4 = plugin_settings.GetValue("HeliumResourceName");
                    Debug.Log("[KSP Interstellar] Helium4 resource name set to " + Helium);
                }
                if (plugin_settings.HasValue("Helium3ResourceName"))
                {
                    _helium3 = plugin_settings.GetValue("Helium3ResourceName");
                    Debug.Log("[KSP Interstellar] Helium3 resource name set to " + Helium3);
                }

                if (plugin_settings.HasValue("HydrazineResourceName"))
                {
                    _hydrazine = plugin_settings.GetValue("HydrazineResourceName");
                    Debug.Log("[KSP Interstellar] Hydrazine resource name set to " + Hydrazine);
                }
                if (plugin_settings.HasValue("HydrogenResourceName"))
                {
                    _hydrogen = plugin_settings.GetValue("HydrogenResourceName");
                    Debug.Log("[KSP Interstellar] Hydrogen resource name set to " + Hydrogen);
                }
                if (plugin_settings.HasValue("HydrogenPeroxideResourceName"))
                {
                    _hydrogen_peroxide = plugin_settings.GetValue("HydrogenPeroxideResourceName");
                    Debug.Log("[KSP Interstellar] Hydrogen Peroxide resource name set to " + HydrogenPeroxide);
                }

                if (plugin_settings.HasValue("MethaneResourceName"))
                {
                    _methane = plugin_settings.GetValue("MethaneResourceName");
                    Debug.Log("[KSP Interstellar] Methane resource name set to " + Methane);
                }
                if (plugin_settings.HasValue("NitrogenResourceName"))
                {
                    _nitrogen = plugin_settings.GetValue("NitrogenResourceName");
                    Debug.Log("[KSP Interstellar] Nitrogen resource name set to " + Nitrogen);
                }
                if (plugin_settings.HasValue("OxygenResourceName"))
                {
                    _oxygen = plugin_settings.GetValue("OxygenResourceName");
                    Debug.Log("[KSP Interstellar] Oxygen resource name set to " + Oxygen);
                }

                if (plugin_settings.HasValue("TritiumResourceName"))
                {
                    _tritium = plugin_settings.GetValue("TritiumResourceName");
                    Debug.Log("[KSP Interstellar] Tritium resource name set to " + _tritium);
                }
                if (plugin_settings.HasValue("UraniumTetraflourideName"))
                {
                    _uranium_TerraFloride = plugin_settings.GetValue("UraniumTetraflourideName");
                    Debug.Log("[KSP Interstellar] UraniumTetraflouride resource name set to " + _uranium_TerraFloride);
                }
                if (plugin_settings.HasValue("WaterResourceName"))
                {
                    _water = plugin_settings.GetValue("WaterResourceName");
                    Debug.Log("[KSP Interstellar] Water resource name set to " + Water);
                }
            }
            else
            {
                PluginHelper.showInstallationErrorMessage();
            }
        }
 public void UpdateGUI()
 {
     if (_bold_label == null)
     {
         _bold_label           = new GUIStyle(GUI.skin.label);
         _bold_label.fontStyle = FontStyle.Bold;
     }
     GUILayout.BeginHorizontal();
     GUILayout.Label("Power", _bold_label, GUILayout.Width(150));
     GUILayout.Label(PluginHelper.getFormattedPowerString(CurrentPower) + "/" + PluginHelper.getFormattedPowerString(PowerRequirements), GUILayout.Width(150));
     GUILayout.EndHorizontal();
     GUILayout.BeginHorizontal();
     GUILayout.Label("Ammona Consumption Rate", _bold_label, GUILayout.Width(150));
     GUILayout.Label(_ammonia_consumption_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150));
     GUILayout.EndHorizontal();
     GUILayout.BeginHorizontal();
     GUILayout.Label("Uranium Tetraflouride Consumption Rate", _bold_label, GUILayout.Width(150));
     GUILayout.Label(_uranium_tetraflouride_consumption_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150));
     GUILayout.EndHorizontal();
     GUILayout.BeginHorizontal();
     GUILayout.Label("Uranium Nitride Production Rate", _bold_label, GUILayout.Width(150));
     GUILayout.Label(_uranium_nitride_production_rate * GameConstants.HOUR_SECONDS + " mT/hour", GUILayout.Width(150));
     GUILayout.EndHorizontal();
 }
        public void update(long counter)
        {
            var timeWarpFixedDeltaTime = TimeWarpFixedDeltaTime;

            IsUpdatedAtLeastOnce = true;
            Counter = counter;

            stored_supply                = currentPowerSupply;
            stored_stable_supply         = stable_supply;
            stored_resource_demand       = current_resource_demand;
            stored_current_demand        = current_resource_demand;
            stored_current_hp_demand     = high_priority_resource_demand;
            stored_current_charge_demand = charge_resource_demand;
            stored_charge_demand         = charge_resource_demand;
            stored_total_power_supplied  = total_power_distributed;

            current_resource_demand       = 0;
            high_priority_resource_demand = 0;
            charge_resource_demand        = 0;
            total_power_distributed       = 0;

            double availableResourceAmount;
            double maxResouceAmount;

            my_part.GetConnectedResourceTotals(resourceDefinition.id, out availableResourceAmount, out maxResouceAmount);

            if (maxResouceAmount > 0 && !double.IsNaN(maxResouceAmount) && !double.IsNaN(availableResourceAmount))
            {
                resource_bar_ratio_end = availableResourceAmount / maxResouceAmount;
            }
            else
            {
                resource_bar_ratio_end = 0.0001;
            }

            double missingResourceAmount = maxResouceAmount - availableResourceAmount;

            currentPowerSupply += availableResourceAmount;

            double high_priority_demand_supply_ratio = high_priority_resource_demand > 0
                ? Math.Min((currentPowerSupply - stored_current_charge_demand) / stored_current_hp_demand, 1.0)
                : 1.0;

            double demand_supply_ratio = stored_current_demand > 0
                ? Math.Min((currentPowerSupply - stored_current_charge_demand - stored_current_hp_demand) / stored_current_demand, 1.0)
                : 1.0;

            //Prioritise supplying stock ElectricCharge resource
            if (resourceDefinition.id == megajouleResourceDefinition.id && stored_stable_supply > 0)
            {
                double amount;
                double maxAmount;

                my_part.GetConnectedResourceTotals(electricResourceDefinition.id, out amount, out maxAmount);
                double stock_electric_charge_needed = maxAmount - amount;

                double power_supplied = Math.Min(currentPowerSupply * 1000 * timeWarpFixedDeltaTime, stock_electric_charge_needed);
                if (stock_electric_charge_needed > 0)
                {
                    var deltaResourceDemand = stock_electric_charge_needed / 1000 / timeWarpFixedDeltaTime;
                    current_resource_demand += deltaResourceDemand;
                    charge_resource_demand  += deltaResourceDemand;
                }

                if (power_supplied > 0)
                {
                    double fixed_provided_electric_charge_in_MW = my_part.RequestResource(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, -power_supplied) / 1000;
                    var    provided_electric_charge_per_second  = fixed_provided_electric_charge_in_MW / timeWarpFixedDeltaTime;
                    total_power_distributed += -provided_electric_charge_per_second;
                    currentPowerSupply      += provided_electric_charge_per_second;
                }
            }

            power_supply_list_archive = power_produced.OrderByDescending(m => m.Value.maximumSupply).ToList();

            // store current supply and update average
            power_supply_list_archive.ForEach(m =>
            {
                Queue <double> queue;

                if (!power_produced_history.TryGetValue(m.Key, out queue))
                {
                    queue = new Queue <double>(10);
                    power_produced_history.Add(m.Key, queue);
                }

                if (queue.Count > 10)
                {
                    queue.Dequeue();
                }
                queue.Enqueue(m.Value.currentSupply);

                m.Value.averageSupply = queue.Average();
            });

            List <KeyValuePair <IResourceSuppliable, PowerDistribution> > power_draw_items = power_consumption.OrderBy(m => m.Value.Power_draw).ToList();

            power_draw_list_archive = power_draw_items.ToList();
            power_draw_list_archive.Reverse();

            // check priority 1 parts like reactors
            foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items)
            {
                IResourceSuppliable resourceSuppliable = power_kvp.Key;

                if (resourceSuppliable.getPowerPriority() == 1)
                {
                    double power = power_kvp.Value.Power_draw;
                    current_resource_demand       += power;
                    high_priority_resource_demand += power;

                    if (flow_type == FNRESOURCE_FLOWTYPE_EVEN)
                    {
                        power = power * high_priority_demand_supply_ratio;
                    }

                    double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0);

                    currentPowerSupply      -= power_supplied;
                    total_power_distributed += power_supplied;

                    //notify of supply
                    resourceSuppliable.receiveFNResource(power_supplied, this.resource_name);
                }
            }

            // check priority 2 parts like reactors
            foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items)
            {
                IResourceSuppliable resourceSuppliable = power_kvp.Key;

                if (resourceSuppliable.getPowerPriority() == 2)
                {
                    double power = power_kvp.Value.Power_draw;
                    current_resource_demand += power;

                    if (flow_type == FNRESOURCE_FLOWTYPE_EVEN)
                    {
                        power = power * demand_supply_ratio;
                    }

                    double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0);

                    currentPowerSupply      -= power_supplied;
                    total_power_distributed += power_supplied;

                    //notify of supply
                    resourceSuppliable.receiveFNResource(power_supplied, this.resource_name);
                }
            }

            // check priority 3 parts like engines and nuclear reactors
            foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items)
            {
                IResourceSuppliable resourceSuppliable = power_kvp.Key;

                if (resourceSuppliable.getPowerPriority() == 3)
                {
                    double power = power_kvp.Value.Power_draw;
                    current_resource_demand += power;

                    if (flow_type == FNRESOURCE_FLOWTYPE_EVEN)
                    {
                        power = power * demand_supply_ratio;
                    }

                    double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0);

                    currentPowerSupply      -= power_supplied;
                    total_power_distributed += power_supplied;

                    //notify of supply
                    resourceSuppliable.receiveFNResource(power_supplied, this.resource_name);
                }
            }

            // check priority 4 parts like antimatter reactors, engines and transmitters
            foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items)
            {
                IResourceSuppliable resourceSuppliable = power_kvp.Key;

                if (resourceSuppliable.getPowerPriority() == 4)
                {
                    double power = power_kvp.Value.Power_draw;
                    current_resource_demand += power;

                    if (flow_type == FNRESOURCE_FLOWTYPE_EVEN)
                    {
                        power = power * demand_supply_ratio;
                    }

                    double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0);

                    currentPowerSupply      -= power_supplied;
                    total_power_distributed += power_supplied;

                    //notify of supply
                    resourceSuppliable.receiveFNResource(power_supplied, this.resource_name);
                }
            }

            // check priority 5 parts and higher
            foreach (KeyValuePair <IResourceSuppliable, PowerDistribution> power_kvp in power_draw_items)
            {
                IResourceSuppliable resourceSuppliable = power_kvp.Key;

                if (resourceSuppliable.getPowerPriority() >= 5)
                {
                    double power = power_kvp.Value.Power_draw;
                    current_resource_demand += power;

                    if (flow_type == FNRESOURCE_FLOWTYPE_EVEN)
                    {
                        power = power * demand_supply_ratio;
                    }

                    double power_supplied = Math.Max(Math.Min(currentPowerSupply, power), 0.0);

                    currentPowerSupply      -= power_supplied;
                    total_power_distributed += power_supplied;

                    //notify of supply
                    resourceSuppliable.receiveFNResource(power_supplied, this.resource_name);
                }
            }

            // substract avaialble resource amount to get delta resource change
            currentPowerSupply         -= Math.Max(availableResourceAmount, 0.0);
            internl_power_extract_fixed = -currentPowerSupply * timeWarpFixedDeltaTime;

            if (resourceDefinition.id == wasteheatResourceDefinition.id)
            {
                // passive dissip of waste heat - a little bit of this
                double vessel_mass    = my_vessel.GetTotalMass();
                double passive_dissip = 2947.295521 * GameConstants.stefan_const * vessel_mass * 2;
                internl_power_extract_fixed += passive_dissip * TimeWarp.fixedDeltaTime;

                if (my_vessel.altitude <= PluginHelper.getMaxAtmosphericAltitude(my_vessel.mainBody))
                {
                    // passive convection - a lot of this
                    double pressure          = FlightGlobals.getStaticPressure(my_vessel.transform.position) * 0.01;
                    double conv_power_dissip = pressure * 40 * vessel_mass * GameConstants.rad_const_h / 1e6 * TimeWarp.fixedDeltaTime;
                    internl_power_extract_fixed += conv_power_dissip;
                }
            }

            if (internl_power_extract_fixed > 0)
            {
                internl_power_extract_fixed = Math.Min(internl_power_extract_fixed, availableResourceAmount);
            }
            else
            {
                internl_power_extract_fixed = Math.Max(internl_power_extract_fixed, -missingResourceAmount);
            }

            my_part.RequestResource(resourceDefinition.id, internl_power_extract_fixed);

            my_part.GetConnectedResourceTotals(resourceDefinition.id, out availableResourceAmount, out maxResouceAmount);

            if (maxResouceAmount > 0 && !double.IsNaN(maxResouceAmount) && !double.IsNaN(availableResourceAmount))
            {
                resource_bar_ratio_begin = availableResourceAmount / maxResouceAmount;
            }
            else
            {
                resource_bar_ratio_begin = resourceDefinition.id == wasteheatResourceDefinition.id ? 0.999 : 0;
            }

            //calculate total input and output
            //var total_current_supplied = power_produced.Sum(m => m.Value.currentSupply);
            //var total_current_provided = power_produced.Sum(m => m.Value.currentProvided);
            //var total_power_consumed = power_consumption.Sum(m => m.Value.Power_consume);
            //var total_power_min_supplied = power_produced.Sum(m => m.Value.minimumSupply);

            ////generate wasteheat from used thermal power + thermal store
            //if (!CheatOptions.IgnoreMaxTemperature && total_current_produced > 0 &&
            //    (resourceDefinition.id == thermalpowerResourceDefinition.id || resourceDefinition.id == chargedpowerResourceDefinition.id))
            //{
            //    var min_supplied_fixed = TimeWarp.fixedDeltaTime * total_power_min_supplied;
            //    var used_or_stored_power_fixed = TimeWarp.fixedDeltaTime * Math.Min(total_power_consumed, total_current_produced) + Math.Max(-actual_stored_power, 0);
            //    var wasteheat_produced_fixed = Math.Max(min_supplied_fixed, used_or_stored_power_fixed);

            //    var effective_wasteheat_ratio = Math.Max(wasteheat_produced_fixed / (total_current_produced * TimeWarp.fixedDeltaTime), 1);

            //    ORSResourceManager manager = ORSResourceOvermanager.getResourceOvermanagerForResource(ResourceManager.FNRESOURCE_WASTEHEAT).getManagerForVessel(my_vessel);

            //    foreach (var supplier_key_value in power_produced)
            //    {
            //        if (supplier_key_value.Value.currentSupply > 0)
            //        {
            //            manager.powerSupplyPerSecondWithMax(supplier_key_value.Key, supplier_key_value.Value.currentSupply * effective_wasteheat_ratio, supplier_key_value.Value.maximumSupply * effective_wasteheat_ratio);
            //        }
            //    }
            //}

            currentPowerSupply = 0;
            stable_supply      = 0;

            power_produced.Clear();
            power_consumption.Clear();
        }