// 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; }
/// <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); }
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); } }
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; }
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"; }
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; }
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; } }
// 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); } }
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(); }
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(); }
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(); } }
/// <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); }
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; } } } }
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); }
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); }
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(); }
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); }
// 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; }
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(); }
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" }
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); }
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; } }
// 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)); }
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(); }
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; } }
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; } }
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; }
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; } }
/// <summary> /// Return vessel shielding factor. /// </summary> public static double Shielding(Vessel v) { return(Radiation.ShieldingEfficiency(ResourceCache.GetResource(v, "Shielding").Level)); }
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); }