Example #1
0
 // return true if a solar storm is in progress at the vessel position
 public static bool StormInProgress(Vessel v)
 {
     if (!Features.SpaceWeather)
     {
         return(false);
     }
     return(Cache.VesselInfo(v).is_valid&& Storm.InProgress(v));
 }
Example #2
0
 void Problem_storm(Vessel v, ref List <Texture2D> icons, ref List <string> tooltips)
 {
     if (Storm.Incoming(v))
     {
         icons.Add(Icons.storm_yellow);
         tooltips.Add(Lib.BuildString("Coronal mass ejection incoming <i>(", Lib.HumanReadableDuration(Storm.TimeBeforeCME(v)), ")</i>"));
     }
     if (Storm.InProgress(v))
     {
         icons.Add(Icons.storm_red);
         tooltips.Add(Lib.BuildString("Solar storm in progress <i>(", Lib.HumanReadableDuration(Storm.TimeLeftCME(v)), ")</i>"));
     }
 }
Example #3
0
 void problem_storm(Vessel v, ref List<Texture> icons, ref List<string> tooltips)
 {
   if (Storm.Incoming(v.mainBody))
   {
     icons.Add(icon_storm_warning);
     tooltips.Add("Coronal mass ejection incoming <i>(" + Lib.HumanReadableDuration(Storm.TimeBeforeCME(v.mainBody)) + ")</i>");
   }
   if (Storm.InProgress(v.mainBody))
   {
     icons.Add(icon_storm_danger);
     tooltips.Add("Solar storm in progress <i>(" + Lib.HumanReadableDuration(Storm.TimeLeftCME(v.mainBody)) + ")</i>");
   }
 }
Example #4
0
        void Problem_storm(Vessel v, ref List <Texture2D> icons, ref List <string> tooltips)
        {
            if (Storm.Incoming(v))
            {
                icons.Add(Textures.storm_yellow);

                var bd  = Lib.IsSun(v.mainBody) ? v.KerbalismData().stormData : DB.Storm(Lib.GetParentPlanet(v.mainBody).name);
                var tti = bd.storm_time - Planetarium.GetUniversalTime();
                tooltips.Add(Lib.BuildString(Lib.Color(Local.Monitor_ejectionincoming, Lib.Kolor.Orange), "\n<i>", Local.Monitor_TimetoimpactCoronalmass, Lib.HumanReadableDuration(tti), "</i>"));                //"Coronal mass ejection incoming"Time to impact:
            }
            if (Storm.InProgress(v))
            {
                icons.Add(Textures.storm_red);

                var bd = Lib.IsSun(v.mainBody) ? v.KerbalismData().stormData : DB.Storm(Lib.GetParentPlanet(v.mainBody).name);
                var remainingDuration = bd.storm_time + bd.displayed_duration - Planetarium.GetUniversalTime();
                tooltips.Add(Lib.BuildString(Lib.Color(Local.Monitor_Solarstorminprogress, Lib.Kolor.Red), "\n<i>", Local.Monitor_SolarstormRemaining, Lib.HumanReadableDuration(remainingDuration), "</i>"));                //"Solar storm in progress"Remaining duration:
            }
        }
Example #5
0
 // hook: StormInProgress()
 public static bool hook_StormInProgress(Vessel v)
 {
     return(Cache.VesselInfo(v).is_valid&& Storm.InProgress(v));
 }
        // return the total environent radiation at position specified
        public static double Compute(Vessel v, Vector3d position, double gamma_transparency, double sunlight, out bool blackout,
                                     out bool magnetosphere, out bool inner_belt, out bool outer_belt, out bool interstellar)
        {
            // prepare out parameters
            blackout      = false;
            magnetosphere = false;
            inner_belt    = false;
            outer_belt    = false;
            interstellar  = false;

            // no-op when Radiation is disabled
            if (!Features.Radiation)
            {
                return(0.0);
            }

            // store stuff
            Space   gsm;
            Vector3 p;
            float   D;

            // transform to local space once
            position = ScaledSpace.LocalToScaledSpace(position);

            // accumulate radiation
            double        radiation = 0.0;
            CelestialBody body      = v.mainBody;

            while (body != null)
            {
                RadiationBody  rb = Info(body);
                RadiationModel mf = rb.model;
                if (mf.Has_field())
                {
                    // generate radii-normalized GSM space
                    gsm = Gsm_space(rb.body, FlightGlobals.Bodies[rb.reference]);

                    // move the poing in GSM space
                    p = gsm.Transform_in(position);

                    // accumulate radiation and determine pause/belt flags
                    if (mf.has_inner)
                    {
                        D           = mf.Inner_func(p);
                        radiation  += Lib.Clamp(D / -0.0666f, 0.0f, 1.0f) * rb.radiation_inner;
                        inner_belt |= D < 0.0f;
                    }
                    if (mf.has_outer)
                    {
                        D           = mf.Outer_func(p);
                        radiation  += Lib.Clamp(D / -0.0333f, 0.0f, 1.0f) * rb.radiation_outer;
                        outer_belt |= D < 0.0f;
                    }
                    if (mf.has_pause)
                    {
                        D              = mf.Pause_func(p);
                        radiation     += Lib.Clamp(D / -0.1332f, 0.0f, 1.0f) * rb.radiation_pause;
                        magnetosphere |= D < 0.0f && rb.body.flightGlobalsIndex != 0;                        //< ignore heliopause
                        interstellar  |= D > 0.0f && rb.body.flightGlobalsIndex == 0;                        //< outside heliopause
                    }
                }

                // avoid loops in the chain
                body = (body.referenceBody != null && body.referenceBody.referenceBody == body) ? null : body.referenceBody;
            }

            // add extern radiation
            radiation += PreferencesStorm.Instance.ExternRadiation;

            // add emitter radiation
            radiation += Emitter.Total(v);

            // if there is a storm in progress
            if (Storm.InProgress(v))
            {
                // inside a magnetopause (except heliosphere), blackout the signal
                // outside, add storm radiations modulated by sun visibility
                if (magnetosphere)
                {
                    blackout = true;
                }
                else
                {
                    radiation += PreferencesStorm.Instance.StormRadiation * sunlight;
                }
            }

            // clamp radiation to positive range
            // note: we avoid radiation going to zero by using a small positive value
            radiation = Math.Max(radiation, Nominal);

            // return radiation, scaled by gamma transparency if inside atmosphere
            return(radiation * gamma_transparency);
        }
Example #7
0
 // return true if vessel is inside a magnetosphere and there is a storm in progress
 public static bool Blackout(Vessel v)
 {
     return(Storm.InProgress(v.mainBody) && Radiation.InsideMagnetosphere(v));
 }
Example #8
0
        // return solar storm radiation hitting the vessel, in rad/s
        public static double StormRadiation(Vessel v, bool sunlight)
        {
            double storm_k = Storm.InProgress(v.mainBody) && !InsideMagnetosphere(v) && sunlight ? 1.0 : 0.0;

            return(Settings.StormRadiation * storm_k);
        }
Example #9
0
        private void EvaluateEnvironment(double elapsedSeconds)
        {
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.VesselData.EvaluateStatus");
            // we use analytic mode if more than 2 minutes of game time has passed since last evaluation (~ x6000 timewarp speed)
            isAnalytic = elapsedSeconds > 120.0;

            // get vessel position
            Vector3d position = Lib.VesselPosition(Vessel);

            // this should never happen again
            if (Vector3d.Distance(position, Vessel.mainBody.position) < 1.0)
            {
                throw new Exception("Shit hit the fan for vessel " + Vessel.vesselName);
            }

            // situation
            underwater = Sim.Underwater(Vessel);
            breathable = Sim.Breathable(Vessel, EnvUnderwater);
            landed     = Lib.Landed(Vessel);

            inAtmosphere = Vessel.mainBody.atmosphere && Vessel.altitude < Vessel.mainBody.atmosphereDepth;
            zeroG        = !EnvLanded && !inAtmosphere;

            visibleBodies = Sim.GetLargeBodies(position);

            // get solar info (with multiple stars / Kopernicus support)
            // get the 'visibleBodies' and 'sunsInfo' lists, the 'mainSun', 'solarFluxTotal' variables.
            // require the situation variables to be evaluated first
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.VesselData.Sunlight");
            SunInfo.UpdateSunsInfo(this, position);
            UnityEngine.Profiling.Profiler.EndSample();
            sunBodyAngle = Sim.SunBodyAngle(Vessel, position, mainSun.SunData.body);

            // temperature at vessel position
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.VesselData.Temperature");
            temperature = Sim.Temperature(Vessel, position, solarFluxTotal, out albedoFlux, out bodyFlux, out totalFlux);
            tempDiff    = Sim.TempDiff(EnvTemperature, Vessel.mainBody, EnvLanded);
            UnityEngine.Profiling.Profiler.EndSample();

            // radiation
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.VesselData.Radiation");
            gammaTransparency = Sim.GammaTransparency(Vessel.mainBody, Vessel.altitude);

            bool new_innerBelt, new_outerBelt, new_magnetosphere;

            radiation = Radiation.Compute(Vessel, position, EnvGammaTransparency, mainSun.SunlightFactor, out blackout, out new_magnetosphere, out new_innerBelt, out new_outerBelt, out interstellar, out shieldedRadiation);

            if (new_innerBelt != innerBelt || new_outerBelt != outerBelt || new_magnetosphere != magnetosphere)
            {
                innerBelt     = new_innerBelt;
                outerBelt     = new_outerBelt;
                magnetosphere = new_magnetosphere;
                if (Evaluated)
                {
                    API.OnRadiationFieldChanged.Notify(Vessel, innerBelt, outerBelt, magnetosphere);
                }
            }
            UnityEngine.Profiling.Profiler.EndSample();

            thermosphere = Sim.InsideThermosphere(Vessel);
            exosphere    = Sim.InsideExosphere(Vessel);
            inStorm      = Storm.InProgress(Vessel);
            vesselSituations.Update();

            // other stuff
            gravioli = Sim.Graviolis(Vessel);
            UnityEngine.Profiling.Profiler.EndSample();
        }
Example #10
0
        // return the total environent radiation at position specified
        public static double Compute(Vessel v, Vector3d position, double gamma_transparency, double sunlight, out bool blackout,
                                     out bool magnetosphere, out bool inner_belt, out bool outer_belt, out bool interstellar, out double shieldedRadiation)
        {
            // prepare out parameters
            blackout          = false;
            magnetosphere     = false;
            inner_belt        = false;
            outer_belt        = false;
            interstellar      = false;
            shieldedRadiation = 0.0;

            // no-op when Radiation is disabled
            if (!Features.Radiation)
            {
                return(0.0);
            }

            // store stuff
            Space   gsm;
            Vector3 p;
            double  D;
            double  r;

            // accumulate radiation
            double        radiation = 0.0;
            CelestialBody body      = v.mainBody;

            while (body != null)
            {
                // Compute radiation values from overlapping 3d fields (belts + magnetospheres)

                RadiationBody  rb = Info(body);
                RadiationModel mf = rb.model;

                // activity is [-0.15..1.05]
                var activity = rb.SolarActivity(false);

                if (mf.Has_field())
                {
                    // transform to local space once
                    var scaled_position = ScaledSpace.LocalToScaledSpace(position);

                    // generate radii-normalized GSM space
                    gsm = Gsm_space(rb, true);

                    // move the point in GSM space
                    p = gsm.Transform_in(scaled_position);

                    // accumulate radiation and determine pause/belt flags
                    if (mf.has_inner)
                    {
                        D           = mf.Inner_func(p);
                        inner_belt |= D < 0;

                        // allow for radiation field to grow/shrink with solar activity
                        D         -= activity * 0.25 / mf.inner_radius;
                        r          = RadiationInBelt(D, mf.inner_radius, rb.radiation_inner_gradient);
                        radiation += r * rb.radiation_inner * (1 + activity * 0.3);
                    }
                    if (mf.has_outer)
                    {
                        D           = mf.Outer_func(p);
                        outer_belt |= D < 0;

                        // allow for radiation field to grow/shrink with solar activity
                        D         -= activity * 0.25 / mf.outer_radius;
                        r          = RadiationInBelt(D, mf.outer_radius, rb.radiation_outer_gradient);
                        radiation += r * rb.radiation_outer * (1 + activity * 0.3);
                    }
                    if (mf.has_pause)
                    {
                        gsm = Gsm_space(rb, false);
                        p   = gsm.Transform_in(scaled_position);
                        D   = mf.Pause_func(p);

                        radiation += Lib.Clamp(D / -0.1332f, 0.0f, 1.0f) * rb.RadiationPause();

                        magnetosphere |= D < 0.0f && !Lib.IsSun(rb.body); //< ignore heliopause
                        interstellar  |= D > 0.0f && Lib.IsSun(rb.body);  //< outside heliopause
                    }
                }

                if (rb.radiation_surface > 0 && body != v.mainBody)
                {
                    Vector3d direction;
                    double   distance;
                    if (Sim.IsBodyVisible(v, position, body, v.KerbalismData().EnvVisibleBodies, out direction, out distance))
                    {
                        var r0 = RadiationR0(rb);
                        var r1 = DistanceRadiation(r0, distance);

                        // clamp to max. surface radiation. when loading on a rescaled system, the vessel can appear to be within the sun for a few ticks
                        radiation += Math.Min(r1, rb.radiation_surface);
#if DEBUG_RADIATION
                        if (v.loaded)
                        {
                            Lib.Log("Radiation " + v + " from surface of " + body + ": " + Lib.HumanReadableRadiation(radiation) + " gamma: " + Lib.HumanReadableRadiation(r1));
                        }
#endif
                    }
                }

                // avoid loops in the chain
                body = (body.referenceBody != null && body.referenceBody.referenceBody == body) ? null : body.referenceBody;
            }

            // add extern radiation
            radiation += Settings.ExternRadiation / 3600.0;

#if DEBUG_RADIATION
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " extern: " + Lib.HumanReadableRadiation(radiation) + " gamma: " + Lib.HumanReadableRadiation(Settings.ExternRadiation));
            }
#endif

            // apply gamma transparency if inside atmosphere
            radiation *= gamma_transparency;

#if DEBUG_RADIATION
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " after gamma: " + Lib.HumanReadableRadiation(radiation) + " transparency: " + gamma_transparency);
            }
#endif
            // add surface radiation of the body itself
            if (Lib.IsSun(v.mainBody) && v.altitude < v.mainBody.Radius)
            {
                if (v.altitude > v.mainBody.Radius)
                {
                    radiation += DistanceRadiation(RadiationR0(Info(v.mainBody)), v.altitude);
                }
            }

#if DEBUG_RADIATION
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " from current main body: " + Lib.HumanReadableRadiation(radiation) + " gamma: " + Lib.HumanReadableRadiation(DistanceRadiation(RadiationR0(Info(v.mainBody)), v.altitude)));
            }
#endif

            shieldedRadiation = radiation;

            // if there is a storm in progress
            if (Storm.InProgress(v))
            {
                // inside a magnetopause (except heliosphere), blackout the signal
                // outside, add storm radiations modulated by sun visibility
                if (magnetosphere)
                {
                    blackout = true;
                }
                else
                {
                    var vd = v.KerbalismData();

                    var activity = Info(vd.EnvMainSun.SunData.body).SolarActivity(false) / 2.0;
                    var strength = PreferencesRadiation.Instance.StormRadiation * sunlight * (activity + 0.5);

                    radiation         += strength;
                    shieldedRadiation += vd.EnvHabitatInfo.AverageHabitatRadiation(strength);
                }
            }

            // add emitter radiation after atmosphere transparency
            var emitterRadiation = Emitter.Total(v);
            radiation         += emitterRadiation;
            shieldedRadiation += emitterRadiation;

#if DEBUG_RADIATION
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " after emitters: " + Lib.HumanReadableRadiation(radiation) + " shielded " + Lib.HumanReadableRadiation(shieldedRadiation));
            }
#endif

            // for EVAs, add the effect of nearby emitters
            if (v.isEVA)
            {
                var nearbyEmitters = Emitter.Nearby(v);
                radiation         += nearbyEmitters;
                shieldedRadiation += nearbyEmitters;
#if DEBUG_RADIATION
                if (v.loaded)
                {
                    Lib.Log("Radiation " + v + " nearby emitters " + Lib.HumanReadableRadiation(nearbyEmitters));
                }
#endif
            }

            var passiveShielding = PassiveShield.Total(v);
            shieldedRadiation -= passiveShielding;

#if DEBUG_RADIATION
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " passiveShielding " + Lib.HumanReadableRadiation(passiveShielding));
            }
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " before clamp: " + Lib.HumanReadableRadiation(radiation) + " shielded " + Lib.HumanReadableRadiation(shieldedRadiation));
            }
#endif

            // clamp radiation to positive range
            // note: we avoid radiation going to zero by using a small positive value
            radiation         = Math.Max(radiation, Nominal);
            shieldedRadiation = Math.Max(shieldedRadiation, Nominal);

#if DEBUG_RADIATION
            if (v.loaded)
            {
                Lib.Log("Radiation " + v + " after clamp: " + Lib.HumanReadableRadiation(radiation) + " shielded " + Lib.HumanReadableRadiation(shieldedRadiation));
            }
#endif
            // return radiation
            return(radiation);
        }