Пример #1
0
 // calculate a cache entry for the vessel
 static vessel_info Compute(Vessel v)
 {
   vessel_info info = new vessel_info();
   info.position = Lib.VesselPosition(v);
   info.sunlight = Sim.RaytraceBody(v, Sim.Sun(), out info.sun_dir, out info.sun_dist);
   info.temperature = Sim.Temperature(v, info.sunlight);
   info.cosmic_radiation = Radiation.CosmicRadiation(v);
   info.belt_radiation = Radiation.BeltRadiation(v);
   info.storm_radiation = Radiation.StormRadiation(v, info.sunlight);
   info.env_radiation = info.cosmic_radiation + info.belt_radiation + info.storm_radiation;
   info.breathable = Sim.Breathable(v);
   foreach(var p in Kerbalism.rules)
   {
     Rule r = p.Value;
     if (r.resource_name.Length > 0)
     {
       var vmon = new vmon_cache();
       vmon.depletion = r.EstimateLifetime(v);
       double amount = Lib.GetResourceAmount(v, r.resource_name);
       double capacity = Lib.GetResourceCapacity(v, r.resource_name);
       vmon.level = capacity > double.Epsilon ? amount / capacity : 1.0; //< level is 1 with no capacity
       info.vmon.Add(p.Value.name, vmon);
     }
   }
   return info;
 }
Пример #2
0
        /// <summary>Calculate the average radiation effect to all habitats. returns true if successful.</summary>
        public bool CalculateRadiationImpact()
        {
            if (radiation < 0)
            {
                radiation_impact = 1.0;
                return(true);
            }

            if (habitatInfos == null)
            {
                BuildHabitatInfos();
            }
            if (habitatInfos == null)
            {
                return(false);
            }

            radiation_impact = 0.0;
            int habitatCount = 0;

            foreach (var hi in habitatInfos)
            {
                radiation_impact += Radiation.DistanceRadiation(1.0, hi.distance);
                habitatCount++;
            }

            if (habitatCount > 1)
            {
                radiation_impact /= habitatCount;
            }

            return(true);
        }
Пример #3
0
  void Start()
  {
    // create subsystems
    cache           = new Cache();
    resource_cache  = new ResourceCache();
    background      = new Background();
    signal          = new Signal();
    storm           = new Storm();
    launcher        = new Launcher();
    info            = new Info();
    body_info       = new BodyInfo();
    message         = new Message();
    console         = new Console();
    editor          = new Editor();
    Radiation.init();
    LineRenderer.init();
    ParticleRenderer.init();

    // prepare storm data
    foreach(CelestialBody body in FlightGlobals.Bodies)
    {
      if (Storm.skip_body(body)) continue;
      storm_data sd = new storm_data();
      sd.body = body;
      storm_bodies.Add(sd);
    }
  }
Пример #4
0
        public override void OnLoad(ConfigNode node)
        {
            // deserialize data
            DB.load(node);

            // initialize everything just once
            if (!initialized)
            {
                // add supply resources to pods
                Profile.SetupPods();

                // initialize subsystems
                Cache.init();
                ResourceCache.init();
                Radiation.init();
                Science.init();
                LineRenderer.init();
                ParticleRenderer.init();
                Highlighter.init();
                UI.init();

                // prepare storm data
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (Storm.skip_body(body))
                    {
                        continue;
                    }
                    storm_data sd = new storm_data();
                    sd.body = body;
                    storm_bodies.Add(sd);
                }

                // various tweaks to the part icons in the editor
                Misc.TweakPartIcons();

                // setup callbacks
                callbacks = new Callbacks();

                // everything was initialized
                initialized = true;
            }

            // detect if this is a different savegame
            if (DB.uid != savegame_uid)
            {
                // clear caches
                Cache.clear();
                ResourceCache.clear();

                // sync main window pos from db
                UI.sync();

                // remember savegame id
                savegame_uid = DB.uid;
            }

            // force CommNet off when signal is enabled
            HighLogic.fetch.currentGame.Parameters.Difficulty.EnableCommNet &= !Features.Signal;
        }
Пример #5
0
		private static void RadiationLevels(CelestialBody body, out string inner, out string outer, out string pause)
		{
			// TODO cache this information in RadiationBody

			double rad = PreferencesStorm.Instance.externRadiation;
			var rbSun = Radiation.Info(FlightGlobals.Bodies[0]);
			rad += rbSun.radiation_pause;

			var rb = Radiation.Info(body);

			if (rb.inner_visible)
				inner = rb.model.has_inner ? "~" + Lib.HumanReadableRadiation(Math.Max(0, rad + rb.radiation_inner) / 3600.0) : "n/a";
			else
				inner = "unknown";

			if (rb.outer_visible)
				outer = rb.model.has_outer ? "~" + Lib.HumanReadableRadiation(Math.Max(0, rad + rb.radiation_outer) / 3600.0) : "n/a";
			else
				outer = "unknown";

			if (rb.pause_visible)
				pause = rb.model.has_pause ? "~" + Lib.HumanReadableRadiation(Math.Max(0, rad + rb.radiation_pause) / 3600.0) : "n/a";
			else
				pause = "unknown";
		}
Пример #6
0
  public static radiation_data analyze_radiation(List<Part> parts, environment_data env, crew_data crew)
  {
    // store data
    radiation_data radiation = new radiation_data();

    // scan the parts
    foreach(Part p in parts)
    {
      // accumulate shielding amount and capacity
      radiation.shielding_amount += Lib.GetResourceAmount(p, "Shielding");
      radiation.shielding_capacity += Lib.GetResourceCapacity(p, "Shielding");
    }

    // calculate radiation data
    double shielding = Radiation.Shielding(radiation.shielding_amount, radiation.shielding_capacity);
    double belt_strength = Settings.BeltRadiation * Radiation.Dynamo(env.body) * 0.5; //< account for the 'ramp'
    if (crew.capacity > 0)
    {
      radiation.life_expectancy = new double[]
      {
        Settings.RadiationFatalThreshold / (Settings.CosmicRadiation * (1.0 - shielding)),
        Settings.RadiationFatalThreshold / (Settings.StormRadiation * (1.0 - shielding)),
        Radiation.HasBelt(env.body) ? Settings.RadiationFatalThreshold / (belt_strength * (1.0 - shielding)) : double.NaN
      };
    }
    else
    {
      radiation.life_expectancy = new double[]{double.NaN, double.NaN, double.NaN};
    }

    // return data
    return radiation;
  }
Пример #7
0
        public override void OnLoad(ConfigNode node)
        {
            // deserialize data
            DB.Load(node);

            // initialize everything just once
            if (!initialized)
            {
                // add supply resources to pods
                Profile.SetupPods();

                // initialize subsystems
                Cache.Init();
                ResourceCache.Init();
                Radiation.Init();
                Science.Init();
                LineRenderer.Init();
                ParticleRenderer.Init();
                Highlighter.Init();
                UI.Init();

                // prepare storm data
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (Storm.Skip_body(body))
                    {
                        continue;
                    }
                    Storm_data sd = new Storm_data
                    {
                        body = body
                    };
                    storm_bodies.Add(sd);
                }

                // various tweaks to the part icons in the editor
                Misc.TweakPartIcons();

                // setup callbacks
                callbacks = new Callbacks();

                // everything was initialized
                initialized = true;
            }

            // detect if this is a different savegame
            if (DB.uid != savegame_uid)
            {
                // clear caches
                Cache.Clear();
                ResourceCache.Clear();

                // sync main window pos from db
                UI.Sync();

                // remember savegame id
                savegame_uid = DB.uid;
            }
        }
Пример #8
0
        // ctor
        Radiation()
        {
            // enable global access
            instance = this;

            // keep it alive
            DontDestroyOnLoad(this);

            // compute magnetosphere of bodies
            CelestialBody home           = FlightGlobals.GetHomeBody();
            double        home_surfspeed = Sim.SurfaceSpeed(home);
            double        home_surfgrav  = Sim.SurfaceGravity(home);

            foreach (CelestialBody body in FlightGlobals.Bodies)
            {
                // skip the sun
                if (body.flightGlobalsIndex == 0)
                {
                    continue;
                }

                // get body parameters and normalize them against home body
                double surfspeed      = Sim.SurfaceSpeed(body);
                double surfgrav       = Sim.SurfaceGravity(body);
                double norm_radius    = body.Radius / home.Radius;
                double norm_surfspeed = surfspeed / home_surfspeed;
                double norm_surfgrav  = surfgrav / home_surfgrav;

                // store magnetosphere info
                body_info info = new body_info();

                // deduce magnetic strength from body parameters
                info.dynamo = norm_radius * norm_surfspeed * norm_surfgrav / (Math.Min(norm_radius, Math.Min(norm_surfspeed, norm_surfgrav)));

                // deduce magnetopause from body parameters
                // - if magnetic strength is below a threshold, there is no magnetosphere
                // - magnetopause has to be higher than double the atmosphere (if any)
                // - magnetopause has to be higher than 1/2 radii
                info.magn_altitude = info.dynamo > 0.0666 ? Math.Max(surfspeed * 33.33 * norm_surfgrav * 1000.0, Math.Max(body.atmosphereDepth * 2.0, body.Radius * 0.5)) : 0.0;

                // deduce radiation belt
                // - if magnetic strength is below a threshold, there is no belt
                // - if magnetopause is lower than 2 radii, there is no belt
                info.belt_altitude = info.dynamo > 0.1888 && info.magn_altitude > body.Radius * 2.0 ? body.Radius : 0.0;

                // add magnetosphere info to the cache
                bodies.Add(body.flightGlobalsIndex, info);
            }
        }
Пример #9
0
  void OnPostRender()
  {
    // do nothing if DB isn't ready for whatever reason
    if (!DB.Ready()) return;

    // do nothing when not in map view
    if (!MapView.MapIsEnabled) return;

    // commit all geometry
    Signal.render();
    Radiation.render();

    // render all committed geometry
    LineRenderer.render();
    ParticleRenderer.render();
  }
Пример #10
0
        void OnPostRender()
        {
            // do nothing when not in map view
            // - avoid weird situation when in some user installation MapIsEnabled is true in the space center
            if (!MapView.MapIsEnabled || HighLogic.LoadedScene == GameScenes.SPACECENTER)
            {
                return;
            }

            // commit all geometry
            Radiation.Render();

            // render all committed geometry
            LineRenderer.Render();
            ParticleRenderer.Render();
        }
Пример #11
0
        private static void RadiationLevels(CelestialBody body, out string inner, out string outer, out string pause, out double activity, out double cycle)
        {
            // TODO cache this information somewhere

            var    rb    = Radiation.Info(body);
            double rad   = Settings.ExternRadiation / 3600.0;
            var    rbSun = Radiation.Info(Lib.GetParentSun(body));

            rad += rbSun.radiation_pause;

            if (rb.inner_visible)
            {
                inner = rb.model.has_inner ? "~" + Lib.HumanReadableRadiation(Math.Max(0, rad + rb.radiation_inner)) : "n/a";
            }
            else
            {
                inner = "unknown";
            }

            if (rb.outer_visible)
            {
                outer = rb.model.has_outer ? "~" + Lib.HumanReadableRadiation(Math.Max(0, rad + rb.radiation_outer)) : "n/a";
            }
            else
            {
                outer = "unknown";
            }

            if (rb.pause_visible)
            {
                pause = rb.model.has_pause ? "∆" + Lib.HumanReadableRadiation(Math.Abs(rb.radiation_pause)) : "n/a";
            }
            else
            {
                pause = "unknown";
            }

            activity = -1;
            cycle    = rb.solar_cycle;
            if (cycle > 0)
            {
                activity = rb.SolarActivity();
            }
        }
Пример #12
0
        /// <summary>
        /// get the total radiation emitted by nearby emitters (used for EVAs). only works for loaded vessels.
        /// </summary>
        public static double Nearby(Vessel v)
        {
            if (!v.loaded || !v.isEVA)
            {
                return(0.0);
            }
            var evaPosition = v.rootPart.transform.position;

            double result = 0.0;

            foreach (Vessel n in FlightGlobals.VesselsLoaded)
            {
                var vd = n.KerbalismData();
                if (!vd.IsSimulated)
                {
                    continue;
                }

                foreach (var emitter in Lib.FindModules <Emitter>(n))
                {
                    if (emitter.part == null || emitter.part.transform == null)
                    {
                        continue;
                    }
                    if (emitter.radiation <= 0)
                    {
                        continue;                                             // ignore shielding effects here
                    }
                    if (!emitter.running)
                    {
                        continue;
                    }

                    var emitterPosition = emitter.part.transform.position;
                    var vector          = evaPosition - emitterPosition;
                    var distance        = vector.magnitude;

                    result += Radiation.DistanceRadiation(emitter.radiation, distance);
                }
            }

            return(result);
        }
Пример #13
0
        void updateConnectedSpaces(Vessel v, vessel_info vi)
        {
            // get CLS handler
            var cls = CLS.get();

            // calculate whole-space
            if (cls == null)
            {
                double living_space  = QualityOfLife.LivingSpace((uint)vi.crew_count, (uint)vi.crew_capacity);
                double entertainment = QualityOfLife.Entertainment(v);
                double shielding     = Radiation.Shielding(v);

                foreach (var c in v.loaded ? v.GetVesselCrew() : v.protoVessel.GetVesselCrew())
                {
                    kerbal_data kd = DB.KerbalData(c.name);
                    kd.living_space  = living_space;
                    kd.entertainment = entertainment;
                    kd.shielding     = shielding;
                    kd.space_name    = "";
                }
            }
            // calculate connected-space
            // note: avoid problem at scene change
            else if (cls.Vessel != null && cls.Vessel.Spaces.Count > 0)
            {
                // calculate internal spaces
                foreach (var space in cls.Vessel.Spaces)
                {
                    double living_space  = QualityOfLife.LivingSpace(space);
                    double entertainment = QualityOfLife.Entertainment(v, space);
                    double shielding     = Radiation.Shielding(space);

                    foreach (var c in space.Crew)
                    {
                        kerbal_data kd = DB.KerbalData(c.Kerbal.name);
                        kd.living_space  = living_space;
                        kd.entertainment = entertainment;
                        kd.shielding     = shielding;
                        kd.space_name    = space.Name;
                    }
                }
            }
        }
Пример #14
0
        public static bool IsAvailableOnBody(this VirtualBiome virtualBiome, CelestialBody body)
        {
            switch (virtualBiome)
            {
            case VirtualBiome.InnerBelt:
                if (!Radiation.Info(body).model.has_inner)
                {
                    return(false);
                }
                break;

            case VirtualBiome.OuterBelt:
                if (!Radiation.Info(body).model.has_outer)
                {
                    return(false);
                }
                break;

            case VirtualBiome.Magnetosphere:
                if (!Radiation.Info(body).model.has_pause)
                {
                    return(false);
                }
                break;

            case VirtualBiome.Interstellar:
                if (!Lib.IsSun(body))
                {
                    return(false);
                }
                break;

            case VirtualBiome.Reentry:
                if (!body.atmosphere)
                {
                    return(false);
                }
                break;
            }
            return(true);
        }
Пример #15
0
        public double AverageHabitatRadiation(double radiation)
        {
            if (habitatShieldings.Count < 1)
            {
                return(radiation);
            }

            var result = 0.0;

            foreach (var shieldingPartsList in habitatShieldings.Values)
            {
                var remainingRadiation = radiation;

                foreach (var shieldingInfo in shieldingPartsList)
                {
                    // for a 500 keV gamma ray, halfing thickness for aluminium is 3.05cm. But...
                    // Solar energetic particles (SEP) are high-energy particles coming from the Sun.
                    // They consist of protons, electrons and HZE ions with energy ranging from a few tens of keV
                    // to many GeV (the fastest particles can approach the speed of light, as in a
                    // "ground-level event"). This is why they are such a big problem for interplanetary space travel.

                    // Beer-Lambert law: Remaining radiation = radiation * e^-ux.  Not exact for SEP, but close enough to loosely fit observed curves.
                    // linear attenuation coefficent u.  Asssuming an average CME event energy Al shielding 10 ~= 30 g/cm^2.
                    // Averaged from NASA plots of large CME events vs Al shielding projections.
                    var linearAttenuation = 10;

                    // However, what you lose in particle radiation you gain in gamma radiation (Bremsstrahlung)

                    var incomingRadiation = remainingRadiation;
                    remainingRadiation *= Math.Exp(shieldingInfo.thickness * linearAttenuation * -1);
                    var bremsstrahlung = incomingRadiation - remainingRadiation;

                    result += Radiation.DistanceRadiation(bremsstrahlung, Math.Max(1, shieldingInfo.distance)) / 10;                    //Gamma radiation has 1/10 the quality factor of SEP
                }

                result += remainingRadiation;
            }

            return(result / habitatShieldings.Count);
        }
Пример #16
0
  void render_internal_space(Vessel v, vessel_info vi, List<ProtoCrewMember> crew)
  {
    // do not render internal space info for eva vessels
    if (v.isEVA) return;

    // if there is no crew, no space will be found, so do nothing in that case
    if (crew.Count == 0) return;

    // collect set of spaces
    // note: this is guaranteed to get at least a space (because there is at least one crew member)
    List<space_details> spaces = new List<space_details>();
    foreach(var c in crew)
    {
      kerbal_data kd = DB.KerbalData(c.name);
      space_details sd = spaces.Find(k => k.name == kd.space_name);
      if (sd == null)
      {
        sd = new space_details();
        sd.name = kd.space_name;
        sd.living_space = kd.living_space;
        sd.entertainment = kd.entertainment;
        sd.shielding = kd.shielding;
        spaces.Add(sd);
      }
      ++sd.crew_count;
    }

    // select a space
    space_details space = spaces[space_index % spaces.Count];

    // render it
    string radiation_txt = vi.radiation > double.Epsilon
      ? Lib.BuildString(" <i>(", Lib.HumanReadableRadiationRate(vi.radiation * (1.0 - space.shielding)), ")</i>")
      : "";
    render_title(space.name.Length > 0 && spaces.Count > 1 ? Lib.Epsilon(space.name.ToUpper(), 20) : "VESSEL", ref space_index, spaces.Count);
    render_content("living space", QualityOfLife.LivingSpaceToString(space.living_space));
    render_content("entertainment", QualityOfLife.EntertainmentToString(space.entertainment));
    render_content("shielding", Lib.BuildString(Radiation.ShieldingToString(space.shielding), radiation_txt));
    render_space();
  }
Пример #17
0
        public double AverageHabitatRadiation(double radiation)
        {
            if (habitatShieldings.Count < 1)
            {
                return(radiation);
            }

            var result = 0.0;

            foreach (var shieldingPartsList in habitatShieldings.Values)
            {
                var remainingRadiation = radiation;

                foreach (var shieldingInfo in shieldingPartsList)
                {
                    // for a 500 keV gamma ray, halfing thickness for aluminium is 3.05cm. But...
                    // Solar energetic particles (SEP) are high-energy particles coming from the Sun.
                    // They consist of protons, electrons and HZE ions with energy ranging from a few tens of keV
                    // to many GeV (the fastest particles can approach the speed of light, as in a
                    // "ground-level event"). This is why they are such a big problem for interplanetary space travel.

                    // We just assume a big halfing thickness for that kind of ionized radiation.
                    var halfingThickness = 1.0;

                    // halfing factor h = part thickness / halfing thickness
                    // remaining radiation = radiation / (2^h)
                    // However, what you loose in particle radiation you gain in gamma radiation (Bremsstrahlung)

                    var bremsstrahlung = remainingRadiation / Math.Pow(2, shieldingInfo.thickness / halfingThickness);
                    remainingRadiation -= bremsstrahlung;

                    result += Radiation.DistanceRadiation(bremsstrahlung, shieldingInfo.distance);
                }

                result += remainingRadiation;
            }

            return(result / habitatShieldings.Count);
        }
Пример #18
0
  // get vessel info from the cache, or compute a new one and add it to the cache
  public static vessel_info VesselInfo(Vessel v)
  {
    // get the info from the cache, if it exist
    vessel_info info;
    if (instance.vessels.TryGetValue(v.id, out info)) return info;

    // compute vessel info
    info = new vessel_info();
    info.position = Lib.VesselPosition(v);
    info.sunlight = Sim.RaytraceBody(v, Sim.Sun(), out info.sun_dir, out info.sun_dist);
    info.temperature = Sim.Temperature(v, info.sunlight);
    info.cosmic_radiation = Radiation.CosmicRadiation(v);
    info.belt_radiation = Radiation.BeltRadiation(v);
    info.storm_radiation = Radiation.StormRadiation(v, info.sunlight);
    info.radiation = (info.cosmic_radiation + info.belt_radiation + info.storm_radiation) * (1.0 - Radiation.Shielding(v));

    // store vessel info in the cache
    instance.vessels.Add(v.id, info);

    // return the vessel info
    return info;
  }
Пример #19
0
  void render_radiation(radiation_data radiation, environment_data env, crew_data crew)
  {
    string magnetosphere_str = Radiation.HasMagnetosphere(env.body) ? Lib.HumanReadableRange(Radiation.MagnAltitude(env.body)) : "none";
    string belt_strength_str = Radiation.HasBelt(env.body) ? " (" + (Radiation.Dynamo(env.body) * Settings.BeltRadiation * (60.0 * 60.0)).ToString("F0") + " rad/h)" : "";
    string belt_str = Radiation.HasBelt(env.body) ? Lib.HumanReadableRange(Radiation.BeltAltitude(env.body)) : "none";
    string shield_str = Radiation.ShieldingToString(radiation.shielding_amount, radiation.shielding_capacity);
    string shield_tooltip = radiation.shielding_capacity > 0 ? "average over the vessel" : "";
    string life_str = Lib.HumanReadableDuration(radiation.life_expectancy[0]) + "</b> / <b>" + Lib.HumanReadableDuration(radiation.life_expectancy[1]);
    string life_tooltip = "cosmic / storm";
    if (Radiation.HasBelt(env.body))
    {
      life_str += "</b> / <b>" + Lib.HumanReadableDuration(radiation.life_expectancy[2]);
      life_tooltip += " / belt";
    }

    render_title("RADIATION");
    render_content("magnetosphere", magnetosphere_str, "protect from cosmic radiation");
    render_content("radiation belt", belt_str, "abnormal radiation zone" + belt_strength_str);
    render_content("shielding", shield_str, shield_tooltip);
    render_content("life expectancy", crew.capacity > 0 ? life_str : "perpetual", crew.capacity > 0 ? life_tooltip : "");
    render_space();
  }
Пример #20
0
        public static void Body_info(this Panel p)
        {
            // only show in mapview
            if (!MapView.MapIsEnabled)
            {
                return;
            }

            // only show if there is a selected body and that body is not the sun
            CelestialBody body = Lib.MapViewSelectedBody();

            if (body == null || (Lib.IsSun(body) && !Features.Radiation))
            {
                return;
            }

            // calculate radiation at body surface
            double surfaceRadiation = Radiation.ComputeSurface(body, Sim.GammaTransparency(body, 0.0));

            // for all bodies except sun(s)
            if (!Lib.IsSun(body))
            {
                CelestialBody mainSun;
                Vector3d      sun_dir;
                double        sun_dist;
                double        solar_flux = Sim.SolarFluxAtBody(body, false, out mainSun, out sun_dir, out sun_dist);
                solar_flux *= Sim.AtmosphereFactor(body, 0.7071);

                // calculate simulation values
                double albedo_flux = Sim.AlbedoFlux(body, body.position + sun_dir * body.Radius);
                double body_flux   = Sim.BodyFlux(body, 0.0);
                double total_flux  = solar_flux + albedo_flux + body_flux + Sim.BackgroundFlux();
                double temperature = body.atmosphere ? body.GetTemperature(0.0) : Sim.BlackBodyTemperature(total_flux);

                // calculate night-side temperature
                double total_flux_min  = Sim.AlbedoFlux(body, body.position - sun_dir * body.Radius) + body_flux + Sim.BackgroundFlux();
                double temperature_min = Sim.BlackBodyTemperature(total_flux_min);

                // surface panel
                string temperature_str = body.atmosphere
                                  ? Lib.HumanReadableTemp(temperature)
                                  : Lib.BuildString(Lib.HumanReadableTemp(temperature_min), " / ", Lib.HumanReadableTemp(temperature));
                p.AddSection(Local.BodyInfo_SURFACE);                                      //"SURFACE"
                p.AddContent(Local.BodyInfo_temperature, temperature_str);                 //"temperature"
                p.AddContent(Local.BodyInfo_solarflux, Lib.HumanReadableFlux(solar_flux)); //"solar flux"
                if (Features.Radiation)
                {
                    p.AddContent(Local.BodyInfo_radiation, Lib.HumanReadableRadiation(surfaceRadiation));                                    //"radiation"
                }
                // atmosphere panel
                if (body.atmosphere)
                {
                    p.AddSection(Local.BodyInfo_ATMOSPHERE);                                                                                      //"ATMOSPHERE"
                    p.AddContent(Local.BodyInfo_breathable, Sim.Breathable(body) ? Local.BodyInfo_breathable_yes : Local.BodyInfo_breathable_no); //"breathable""yes""no"
                    p.AddContent(Local.BodyInfo_lightabsorption, Lib.HumanReadablePerc(1.0 - Sim.AtmosphereFactor(body, 0.7071)));                //"light absorption"
                    if (Features.Radiation)
                    {
                        p.AddContent(Local.BodyInfo_gammaabsorption, Lib.HumanReadablePerc(1.0 - Sim.GammaTransparency(body, 0.0)));                                        //"gamma absorption"
                    }
                }
            }

            // radiation panel
            if (Features.Radiation)
            {
                p.AddSection(Local.BodyInfo_RADIATION);                //"RADIATION"

                string inner, outer, pause;
                double activity, cycle;
                RadiationLevels(body, out inner, out outer, out pause, out activity, out cycle);

                if (Storm.sun_observation_quality > 0.5 && activity > -1)
                {
                    string title = Local.BodyInfo_solaractivity;                    //"solar activity"

                    if (Storm.sun_observation_quality > 0.7)
                    {
                        title = Lib.BuildString(title, ": ", Lib.Color(Local.BodyInfo_stormcycle.Format(Lib.HumanReadableDuration(cycle)), Lib.Kolor.LightGrey));                        // <<1>> cycle
                    }

                    p.AddContent(title, Lib.HumanReadablePerc(activity));
                }

                if (Storm.sun_observation_quality > 0.8)
                {
                    p.AddContent(Local.BodyInfo_radiationonsurface, Lib.HumanReadableRadiation(surfaceRadiation));                    //"radiation on surface:"
                }

                p.AddContent(Lib.BuildString(Local.BodyInfo_innerbelt, " ", Lib.Color(inner, Lib.Kolor.LightGrey)),                                                                                           //"inner belt: "
                             Radiation.show_inner ? Lib.Color(Local.BodyInfo_show, Lib.Kolor.Green) : Lib.Color(Local.BodyInfo_hide, Lib.Kolor.Red), string.Empty, () => p.Toggle(ref Radiation.show_inner)); //"show""hide"
                p.AddContent(Lib.BuildString(Local.BodyInfo_outerbelt, " ", Lib.Color(outer, Lib.Kolor.LightGrey)),                                                                                           //"outer belt: "
                             Radiation.show_outer ? Lib.Color(Local.BodyInfo_show, Lib.Kolor.Green) : Lib.Color(Local.BodyInfo_hide, Lib.Kolor.Red), string.Empty, () => p.Toggle(ref Radiation.show_outer)); //"show""hide"
                p.AddContent(Lib.BuildString(Local.BodyInfo_magnetopause, " ", Lib.Color(pause, Lib.Kolor.LightGrey)),                                                                                        //"magnetopause: "
                             Radiation.show_pause ? Lib.Color(Local.BodyInfo_show, Lib.Kolor.Green) : Lib.Color(Local.BodyInfo_hide, Lib.Kolor.Red), string.Empty, () => p.Toggle(ref Radiation.show_pause)); //"show""hide"
            }

            // explain the user how to toggle the BodyInfo window
            p.AddContent(string.Empty);
            p.AddContent("<i>" + Local.BodyInfo_BodyInfoToggleHelp.Format("<b>B</b>") + "</i>");            //"Press <<1>> to open this window again"

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(body.bodyName, Styles.ScaleStringLength(24)), " ", Lib.Color(Local.BodyInfo_title, Lib.Kolor.LightGrey)));            //"BODY INFO"
        }
Пример #21
0
        public Vessel_info(Vessel v, UInt64 vessel_id, UInt64 inc)
        {
            // NOTE: anything used here can't in turn use cache, unless you know what you are doing

            // NOTE: you can't cache vessel position
            // at any point in time all vessel/body positions are relative to a different frame of reference
            // so comparing the current position of a vessel, with the cached one of another make no sense

            // associate with an unique incremental id
            this.inc = inc;

            // determine if this is a valid vessel
            is_vessel = Lib.IsVessel(v);
            if (!is_vessel)
            {
                return;
            }

            // determine if this is a rescue mission vessel
            is_rescue = Misc.IsRescueMission(v);
            if (is_rescue)
            {
                return;
            }

            // dead EVA are not valid vessels
            if (EVA.IsDead(v))
            {
                return;
            }

            // shortcut for common tests
            is_valid = true;

            // generate id once
            id = vessel_id;

            // calculate crew info for the vessel
            crew_count    = Lib.CrewCount(v);
            crew_capacity = Lib.CrewCapacity(v);

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

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

            // determine if there is enough EC for a powered state
            powered = ResourceCache.Info(v, "ElectricCharge").amount > double.Epsilon;

            // determine if in sunlight, calculate sun direction and distance
            sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

            // environment stuff
            atmo_factor        = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
            gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
            underwater         = Sim.Underwater(v);
            breathable         = Sim.Breathable(v, underwater);
            landed             = Lib.Landed(v);
            zerog = !landed && (!v.mainBody.atmosphere || v.mainBody.atmosphereDepth < v.altitude);

            if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f)
            {
                highspeedWarp(v);
            }

            // temperature at vessel position
            temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);
            temp_diff   = Sim.TempDiff(temperature, v.mainBody, landed);

            // radiation
            radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar);

            // extended atmosphere
            thermosphere = Sim.InsideThermosphere(v);
            exosphere    = Sim.InsideExosphere(v);

            // malfunction stuff
            malfunction = Reliability.HasMalfunction(v);
            critical    = Reliability.HasCriticalFailure(v);

            // communications info
            connection   = new ConnectionInfo(v, powered, blackout);
            transmitting = Science.Transmitting(v, connection.linked && connection.rate > double.Epsilon);

            // habitat data
            volume          = Habitat.Tot_volume(v);
            surface         = Habitat.Tot_surface(v);
            pressure        = Habitat.Pressure(v);
            evas            = (uint)(Math.Max(0, ResourceCache.Info(v, "Nitrogen").amount - 330) / PreferencesLifeSupport.Instance.evaAtmoLoss);
            poisoning       = Habitat.Poisoning(v);
            humidity        = Habitat.Humidity(v);
            shielding       = Habitat.Shielding(v);
            living_space    = Habitat.Living_space(v);
            volume_per_crew = Habitat.Volume_per_crew(v);
            comforts        = new Comforts(v, landed, crew_count > 1, connection.linked && connection.rate > double.Epsilon);

            // data about greenhouses
            greenhouses = Greenhouse.Greenhouses(v);

            // other stuff
            gravioli = Sim.Graviolis(v);
        }
Пример #22
0
        void FixedUpdate()
        {
            // remove control locks in any case
            Misc.clearLocks();

            // do nothing if paused
            if (Lib.IsPaused())
            {
                return;
            }

            // maintain elapsed_s, converting to double only once
            // and detect warp blending
            double fixedDeltaTime = TimeWarp.fixedDeltaTime;

            if (Math.Abs(fixedDeltaTime - elapsed_s) > double.Epsilon)
            {
                warp_blending = 0;
            }
            else
            {
                ++warp_blending;
            }
            elapsed_s = fixedDeltaTime;

            // evict oldest entry from vessel cache
            Cache.update();

            // store info for oldest unloaded vessel
            double           last_time      = 0.0;
            Vessel           last_v         = null;
            vessel_info      last_vi        = null;
            VesselData       last_vd        = null;
            vessel_resources last_resources = null;

            // for each vessel
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // get vessel info from the cache
                vessel_info vi = Cache.VesselInfo(v);

                // set locks for active vessel
                if (v.isActiveVessel)
                {
                    Misc.setLocks(v, vi);
                }

                // maintain eva dead animation and helmet state
                if (v.loaded && v.isEVA)
                {
                    EVA.update(v);
                }

                // keep track of rescue mission kerbals, and gift resources to their vessels on discovery
                if (v.loaded && vi.is_vessel)
                {
                    // manage rescue mission mechanics
                    Misc.manageRescueMission(v);
                }

                // do nothing else for invalid vessels
                if (!vi.is_valid)
                {
                    continue;
                }

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

                // get resource cache
                vessel_resources resources = ResourceCache.Get(v);

                // if loaded
                if (v.loaded)
                {
                    // show belt warnings
                    Radiation.beltWarnings(v, vi, vd);

                    // update storm data
                    Storm.update(v, vi, vd, elapsed_s);

                    // show signal warnings
                    Signal.update(v, vi, vd, elapsed_s);

                    // consume ec for transmission, and transmit science data
                    Science.update(v, vi, vd, resources, elapsed_s);

                    // apply rules
                    Profile.Execute(v, vi, vd, resources, elapsed_s);

                    // apply deferred requests
                    resources.Sync(v, elapsed_s);

                    // call automation scripts
                    vd.computer.automate(v, vi, resources);

                    // remove from unloaded data container
                    unloaded.Remove(vi.id);
                }
                // if unloaded
                else
                {
                    // get unloaded data, or create an empty one
                    unloaded_data ud;
                    if (!unloaded.TryGetValue(vi.id, out ud))
                    {
                        ud = new unloaded_data();
                        unloaded.Add(vi.id, ud);
                    }

                    // accumulate time
                    ud.time += elapsed_s;

                    // maintain oldest entry
                    if (ud.time > last_time)
                    {
                        last_time      = ud.time;
                        last_v         = v;
                        last_vi        = vi;
                        last_vd        = vd;
                        last_resources = resources;
                    }
                }
            }


            // if the oldest unloaded vessel was selected
            if (last_v != null)
            {
                // show belt warnings
                Radiation.beltWarnings(last_v, last_vi, last_vd);

                // update storm data
                Storm.update(last_v, last_vi, last_vd, last_time);

                // show signal warnings
                Signal.update(last_v, last_vi, last_vd, last_time);

                // consume ec for transmission, and transmit science
                Science.update(last_v, last_vi, last_vd, last_resources, last_time);

                // apply rules
                Profile.Execute(last_v, last_vi, last_vd, last_resources, last_time);

                // simulate modules in background
                Background.update(last_v, last_vi, last_vd, last_resources, last_time);

                // apply deferred requests
                last_resources.Sync(last_v, last_time);

                // call automation scripts
                last_vd.computer.automate(last_v, last_vi, last_resources);

                // remove from unloaded data container
                unloaded.Remove(last_vi.id);
            }

            // update storm data for one body per-step
            if (storm_bodies.Count > 0)
            {
                storm_bodies.ForEach(k => k.time += elapsed_s);
                storm_data sd = storm_bodies[storm_index];
                Storm.update(sd.body, sd.time);
                sd.time     = 0.0;
                storm_index = (storm_index + 1) % storm_bodies.Count;
            }
        }
Пример #23
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));
 }
Пример #24
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();
        }
Пример #25
0
        void FixedUpdate()
        {
            // remove control locks in any case
            Misc.ClearLocks();

            // do nothing if paused
            if (Lib.IsPaused())
            {
                return;
            }

            // maintain elapsed_s, converting to double only once
            // and detect warp blending
            double fixedDeltaTime = TimeWarp.fixedDeltaTime;

            if (Math.Abs(fixedDeltaTime - elapsed_s) > double.Epsilon)
            {
                warp_blending = 0;
            }
            else
            {
                ++warp_blending;
            }
            elapsed_s = fixedDeltaTime;

            // evict oldest entry from vessel cache
            Cache.Update();

            // vvvv------- This code tests for a theroy that could cause #313
            // If KSP itself has the same vessel more than once in the
            // FlightGlobals.Vessels list, it would cause processes to run too many times.
            // The other possible cause was a Vessel ID collision in Lib.VesselID(), which
            // only used 4 bytes of a 16 byte GUID to create an ID from.
            //
            // If the BUG TRIGGERED message is never observed in the wild,
            // it is safe to remove this chunk of code.
            Dictionary <UInt64, Vessel> vessels = new Dictionary <UInt64, Vessel>();

            foreach (Vessel v in FlightGlobals.Vessels)
            {
                if (vessels.ContainsKey(Lib.VesselID(v)))
                {
                    Lib.Log("THIS SHOULD NOT BE HAPPENING: Vessel " + v.name + " already seen in FlightGlobals.Vessels");
                    Message.Post(Lib.BuildString(Lib.Color("red", "BUG TRIGGERED", true), "\n",
                                                 v.name + " duplicated in FlightGlobals.Vessels. Please report this on GitHub."));
                }
                else
                {
                    vessels.Add(Lib.VesselID(v), v);
                }
            }
            // ^^^^-------- end theory test code

            // store info for oldest unloaded vessel
            double           last_time      = 0.0;
            Vessel           last_v         = null;
            Vessel_info      last_vi        = null;
            VesselData       last_vd        = null;
            Vessel_resources last_resources = null;

            // for each vessel
            //foreach (Vessel v in FlightGlobals.Vessels)
            foreach (Vessel v in vessels.Values)
            {
                // get vessel info from the cache
                Vessel_info vi = Cache.VesselInfo(v);

                // set locks for active vessel
                if (v.isActiveVessel)
                {
                    Misc.SetLocks(v, vi);
                }

                // maintain eva dead animation and helmet state
                if (v.loaded && v.isEVA)
                {
                    EVA.Update(v);
                }

                // keep track of rescue mission kerbals, and gift resources to their vessels on discovery
                if (v.loaded && vi.is_vessel)
                {
                    // manage rescue mission mechanics
                    Misc.ManageRescueMission(v);
                }

                // do nothing else for invalid vessels
                if (!vi.is_valid)
                {
                    continue;
                }

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

                // get resource cache
                Vessel_resources resources = ResourceCache.Get(v);

                // if loaded
                if (v.loaded)
                {
                    // get most used resource
                    Resource_info ec = resources.Info(v, "ElectricCharge");

                    // show belt warnings
                    Radiation.BeltWarnings(v, vi, vd);

                    // update storm data
                    Storm.Update(v, vi, vd, elapsed_s);

                    Communications.Update(v, vi, vd, ec, elapsed_s);

                    // Habitat equalization
                    ResourceBalance.Equalizer(v);

                    // transmit science data
                    Science.Update(v, vi, vd, resources, elapsed_s);

                    // apply rules
                    Profile.Execute(v, vi, vd, resources, elapsed_s);

                    // apply deferred requests
                    resources.Sync(v, elapsed_s);

                    // call automation scripts
                    vd.computer.Automate(v, vi, resources);

                    // remove from unloaded data container
                    unloaded.Remove(vi.id);
                }
                // if unloaded
                else
                {
                    // get unloaded data, or create an empty one
                    Unloaded_data ud;
                    if (!unloaded.TryGetValue(vi.id, out ud))
                    {
                        ud = new Unloaded_data();
                        unloaded.Add(vi.id, ud);
                    }

                    // accumulate time
                    ud.time += elapsed_s;

                    // maintain oldest entry
                    if (ud.time > last_time)
                    {
                        last_time      = ud.time;
                        last_v         = v;
                        last_vi        = vi;
                        last_vd        = vd;
                        last_resources = resources;
                    }
                }
            }

            // at most one vessel gets background processing per physics tick
            // if there is a vessel that is not the currently loaded vessel, then
            // we will update the vessel whose most recent background update is the oldest
            if (last_v != null)
            {
                // get most used resource
                Resource_info last_ec = last_resources.Info(last_v, "ElectricCharge");

                // show belt warnings
                Radiation.BeltWarnings(last_v, last_vi, last_vd);

                // update storm data
                Storm.Update(last_v, last_vi, last_vd, last_time);

                Communications.Update(last_v, last_vi, last_vd, last_ec, last_time);

                // transmit science	data
                Science.Update(last_v, last_vi, last_vd, last_resources, last_time);

                // apply rules
                Profile.Execute(last_v, last_vi, last_vd, last_resources, last_time);

                // simulate modules in background
                Background.Update(last_v, last_vi, last_vd, last_resources, last_time);

                // apply deferred requests
                last_resources.Sync(last_v, last_time);

                // call automation scripts
                last_vd.computer.Automate(last_v, last_vi, last_resources);

                // remove from unloaded data container
                unloaded.Remove(last_vi.id);
            }

            // update storm data for one body per-step
            if (storm_bodies.Count > 0)
            {
                storm_bodies.ForEach(k => k.time += elapsed_s);
                Storm_data sd = storm_bodies[storm_index];
                Storm.Update(sd.body, sd.time);
                sd.time     = 0.0;
                storm_index = (storm_index + 1) % storm_bodies.Count;
            }
        }
Пример #26
0
        void FixedUpdate()
        {
            // remove control locks in any case
            Misc.ClearLocks();

            // do nothing if paused
            if (Lib.IsPaused())
            {
                return;
            }

            // convert elapsed time to double only once
            double fixedDeltaTime = TimeWarp.fixedDeltaTime;

            // and detect warp blending
            if (Math.Abs(fixedDeltaTime - elapsed_s) < 0.001)
            {
                warp_blending = 0;
            }
            else
            {
                ++warp_blending;
            }

            // update elapsed time
            elapsed_s = fixedDeltaTime;

            // store info for oldest unloaded vessel
            double          last_time      = 0.0;
            Guid            last_id        = Guid.Empty;
            Vessel          last_v         = null;
            VesselData      last_vd        = null;
            VesselResources last_resources = null;

            foreach (VesselData vd in DB.VesselDatas)
            {
                vd.EarlyUpdate();
            }

            // for each vessel
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // get vessel data
                VesselData vd = v.KerbalismData();

                // update the vessel data validity
                vd.Update(v);

                // set locks for active vessel
                if (v.isActiveVessel)
                {
                    Misc.SetLocks(v);
                }

                // maintain eva dead animation and helmet state
                if (v.loaded && v.isEVA)
                {
                    EVA.Update(v);
                }

                // keep track of rescue mission kerbals, and gift resources to their vessels on discovery
                if (v.loaded && vd.is_vessel)
                {
                    // manage rescue mission mechanics
                    Misc.ManageRescueMission(v);
                }

                // do nothing else for invalid vessels
                if (!vd.IsSimulated)
                {
                    continue;
                }

                // get resource cache
                VesselResources resources = ResourceCache.Get(v);

                // if loaded
                if (v.loaded)
                {
                    //UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.VesselDataEval");
                    // update the vessel info
                    vd.Evaluate(false, elapsed_s);
                    //UnityEngine.Profiling.Profiler.EndSample();

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

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Radiation");
                    // show belt warnings
                    Radiation.BeltWarnings(v, vd);

                    // update storm data
                    Storm.Update(v, vd, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Comms");
                    Communications.Update(v, vd, ec, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    // Habitat equalization
                    ResourceBalance.Equalizer(v);

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Science");
                    // transmit science data
                    Science.Update(v, vd, ec, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Profile");
                    // apply rules
                    Profile.Execute(v, vd, resources, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Profile");
                    // part module resource updates
                    vd.ResourceUpdate(resources, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Loaded.Resource");
                    // apply deferred requests
                    resources.Sync(v, vd, elapsed_s);
                    UnityEngine.Profiling.Profiler.EndSample();

                    // call automation scripts
                    vd.computer.Automate(v, vd, resources);

                    // remove from unloaded data container
                    unloaded.Remove(vd.VesselId);
                }
                // if unloaded
                else
                {
                    // get unloaded data, or create an empty one
                    Unloaded_data ud;
                    if (!unloaded.TryGetValue(vd.VesselId, out ud))
                    {
                        ud = new Unloaded_data();
                        unloaded.Add(vd.VesselId, ud);
                    }

                    // accumulate time
                    ud.time += elapsed_s;

                    // maintain oldest entry
                    if (ud.time > last_time)
                    {
                        last_time      = ud.time;
                        last_v         = v;
                        last_vd        = vd;
                        last_resources = resources;
                    }
                }
            }

            // at most one vessel gets background processing per physics tick :
            // if there is a vessel that is not the currently loaded vessel, then
            // we will update the vessel whose most recent background update is the oldest
            if (last_v != null)
            {
                //UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.VesselDataEval");
                // update the vessel info (high timewarp speeds reevaluation)
                last_vd.Evaluate(false, last_time);
                //UnityEngine.Profiling.Profiler.EndSample();

                // get most used resource
                ResourceInfo last_ec = last_resources.GetResource(last_v, "ElectricCharge");

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Radiation");
                // show belt warnings
                Radiation.BeltWarnings(last_v, last_vd);

                // update storm data
                Storm.Update(last_v, last_vd, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Comms");
                Communications.Update(last_v, last_vd, last_ec, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Profile");
                // apply rules
                Profile.Execute(last_v, last_vd, last_resources, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Background");
                // simulate modules in background
                Background.Update(last_v, last_vd, last_resources, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Science");
                // transmit science	data
                Science.Update(last_v, last_vd, last_ec, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.FixedUpdate.Unloaded.Resource");
                // apply deferred requests
                last_resources.Sync(last_v, last_vd, last_time);
                UnityEngine.Profiling.Profiler.EndSample();

                // call automation scripts
                last_vd.computer.Automate(last_v, last_vd, last_resources);

                // remove from unloaded data container
                unloaded.Remove(last_vd.VesselId);
            }

            // update storm data for one body per-step
            if (storm_bodies.Count > 0)
            {
                storm_bodies.ForEach(k => k.time += elapsed_s);
                Storm_data sd = storm_bodies[storm_index];
                Storm.Update(sd.body, sd.time);
                sd.time     = 0.0;
                storm_index = (storm_index + 1) % storm_bodies.Count;
            }
        }
Пример #27
0
        public override void OnLoad(ConfigNode node)
        {
            // everything in there will be called only one time : the first time a game is loaded from the main menu
            if (!IsCoreGameInitDone)
            {
                // core game systems
                Sim.Init();                         // find suns (Kopernicus support)
                Radiation.Init();                   // create the radiation fields
                ScienceDB.Init();                   // build the science database (needs Sim.Init() and Radiation.Init() first)
                Science.Init();                     // register the science hijacker

                // static graphic components
                LineRenderer.Init();
                ParticleRenderer.Init();
                Highlighter.Init();

                // UI
                Textures.Init();                                      // set up the icon textures
                UI.Init();                                            // message system, main gui, launcher
                KsmGui.KsmGuiMasterController.Init();                 // setup the new gui framework

                // part prefabs hacks
                Profile.SetupPods();                 // add supply resources to pods
                Misc.TweakPartIcons();               // various tweaks to the part icons in the editor

                // Create KsmGui windows
                new ScienceArchiveWindow();

                // GameEvents callbacks
                Callbacks = new Callbacks();

                IsCoreGameInitDone = true;
            }

            // everything in there will be called every time a savegame (or a new game) is loaded from the main menu
            if (!IsSaveGameInitDone)
            {
                Cache.Init();
                ResourceCache.Init();

                // prepare storm data
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (Storm.Skip_body(body))
                    {
                        continue;
                    }
                    Storm_data sd = new Storm_data {
                        body = body
                    };
                    storm_bodies.Add(sd);
                }

                IsSaveGameInitDone = true;
            }

            // eveything else will be called on every OnLoad() call :
            // - save/load
            // - every scene change
            // - in various semi-random situations (thanks KSP)

            // Fix for background IMGUI textures being dropped on scene changes since KSP 1.8
            Styles.ReloadBackgroundStyles();

            // always clear the caches
            Cache.Clear();
            ResourceCache.Clear();

            // deserialize our database
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.DB.Load");
            DB.Load(node);
            UnityEngine.Profiling.Profiler.EndSample();

            // I'm smelling the hacky mess in here.
            Communications.NetworkInitialized  = false;
            Communications.NetworkInitializing = false;

            // detect if this is a different savegame
            if (DB.uid != savegame_uid)
            {
                // clear caches
                Message.all_logs.Clear();

                // sync main window pos from db
                UI.Sync();

                // remember savegame id
                savegame_uid = DB.uid;
            }

            Kerbalism.gameLoadTime = Time.time;
        }
Пример #28
0
        internal static void CreateStorm(StormData bd, CelestialBody body, double distanceToSun)
        {
            // do nothing if storms are disabled
            if (!Features.SpaceWeather)
            {
                return;
            }

            var now = Planetarium.GetUniversalTime();

            if (bd.storm_generation < now)
            {
                var sun         = Lib.GetParentSun(body);
                var avgDuration = PreferencesRadiation.Instance.AvgStormDuration;

                // retry after 3 * average storm duration + jitter (to avoid recalc spikes)
                bd.storm_generation = now + avgDuration * 3 + avgDuration * Lib.RandomDouble();

                var rb       = Radiation.Info(sun);
                var activity = rb.solar_cycle > 0 ? rb.SolarActivity() : 1.0;

                if (Lib.RandomDouble() < activity * PreferencesRadiation.Instance.stormFrequency)
                {
                    // storm duration depends on current solar activity
                    bd.storm_duration = avgDuration / 2.0 + avgDuration * activity * 2;

                    // if further out, the storm lasts longer (but is weaker)
                    bd.storm_duration /= Storm_frequency(distanceToSun);

                    // set a start time to give enough time for warning
                    bd.storm_time = now + Time_to_impact(distanceToSun);

                    // delay next storm generation by duration of this one
                    bd.storm_generation += bd.storm_duration;

                    // add a random error to the estimated storm duration if we don't observe the sun too well
                    var error = bd.storm_duration * 3 * Lib.RandomDouble() * (1 - sun_observation_quality);
                    bd.displayed_duration = bd.storm_duration + error;

                    // show warning message only if you're lucky...
                    bd.display_warning = Lib.RandomFloat() < sun_observation_quality;


#if DEBUG_RADIATION
                    Lib.Log("Storm on " + body + " will start in " + Lib.HumanReadableDuration(bd.storm_time - now) + " and last for " + Lib.HumanReadableDuration(bd.storm_duration));
                }
                else
                {
                    Lib.Log("No storm on " + body + ", will retry in " + Lib.HumanReadableDuration(bd.storm_generation - now));
#endif
                }
            }

            if (bd.storm_time + bd.storm_duration < now)
            {
                // storm is over
                bd.Reset();
            }
            else if (bd.storm_time < now && bd.storm_time + bd.storm_duration > now)
            {
                // storm in progress
                bd.storm_state = 2;
            }
            else if (bd.storm_time > now)
            {
                // storm incoming
                bd.storm_state = 1;
            }
        }
Пример #29
0
 /// <summary>
 /// Return vessel shielding factor.
 /// </summary>
 public static double Shielding(Vessel v)
 {
     return(Radiation.ShieldingEfficiency(ResourceCache.GetResource(v, "Shielding").Level));
 }
Пример #30
0
  public vessel_info(Vessel v, uint vessel_id, UInt64 inc)
  {
    // NOTE: anything used here can't in turn use cache, unless you know what you are doing

    // NOTE: you can't cache vessel position
    // at any point in time all vessel/body positions are relative to a different frame of reference
    // so comparing the current position of a vessel, with the cached one of another make no sense

    // associate with an unique incremental id
    this.inc = inc;

    // determine if this is a valid vessel
    is_vessel = Lib.IsVessel(v);
    if (!is_vessel) return;

    // determine if this is a rescue mission vessel
    is_rescue = Misc.IsRescueMission(v);
    if (is_rescue) return;

    // dead EVA are not valid vessels
    if (EVA.IsDead(v)) return;

    // shortcut for common tests
    is_valid = true;

    // generate id once
    id = vessel_id;

    // calculate crew info for the vessel
    crew_count = Lib.CrewCount(v);
    crew_capacity = Lib.CrewCapacity(v);

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

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

    // determine if in sunlight, calculate sun direction and distance
    sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

    // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
    // the quantization error first became noticeable, and then exceed 100%
    // to solve this, we switch to an analytical estimation of the portion of orbit that was in sunlight
    // - we check against timewarp rate, instead of index, to avoid issues during timewarp blending
    if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f)
    {
      sunlight = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
    }

    // environment stuff
    atmo_factor = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
    gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
    underwater = Sim.Underwater(v);
    breathable = Sim.Breathable(v, underwater);
    landed = Lib.Landed(v);

    // temperature at vessel position
    temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);
    temp_diff = Sim.TempDiff(temperature, v.mainBody, landed);

    // radiation
    radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar);

    // extended atmosphere
    thermosphere = Sim.InsideThermosphere(v);
    exosphere = Sim.InsideExosphere(v);

    // malfunction stuff
    malfunction = Reliability.HasMalfunction(v);
    critical = Reliability.HasCriticalFailure(v);

    // signal info
    antenna = new AntennaInfo(v);
    avoid_inf_recursion.Add(v.id);
    connection = Signal.connection(v, position, antenna, blackout, avoid_inf_recursion);
    transmitting = Science.transmitting(v, connection.linked);
    relaying = Signal.relaying(v, avoid_inf_recursion);
    avoid_inf_recursion.Remove(v.id);

    // habitat data
    volume = Habitat.tot_volume(v);
    surface = Habitat.tot_surface(v);
    pressure = Habitat.pressure(v);
    poisoning = Habitat.poisoning(v);
    shielding = Habitat.shielding(v);
    living_space = Habitat.living_space(v);
    comforts = new Comforts(v, landed, crew_count > 1, connection.linked);

    // data about greenhouses
    greenhouses = Greenhouse.Greenhouses(v);

    // other stuff
    gravioli = Sim.Graviolis(v);
  }