public override bool MeetRequirements() { // stop checking when requirements are met if (!meet_requirements) { ProgressTracking progress = ProgressTracking.Instance; if (progress == null) { return(false); } int known = 0; foreach (var body_progress in progress.celestialBodyNodes) { known += body_progress.flyBy != null && body_progress.flyBy.IsComplete ? 1 : 0; } bool end_game = known > FlightGlobals.Bodies.Count / 2; meet_requirements = Features.Radiation && // radiation is enabled end_game && // entered SOI of half the bodies Radiation.Info(FlightGlobals.Bodies[0]).model.has_pause && // there is an actual heliopause !DB.landmarks.heliopause_crossing; // heliopause never crossed before } return(meet_requirements); }
public void Analyze(CelestialBody body, double altitude_mult, bool sunlight) { // shortcuts CelestialBody sun = FlightGlobals.Bodies[0]; this.body = body; altitude = body.Radius * altitude_mult; landed = altitude <= double.Epsilon; breathable = Sim.Breathable(body) && landed; atmo_factor = Sim.AtmosphereFactor(body, 0.7071); sun_dist = Sim.Apoapsis(Lib.PlanetarySystem(body)) - sun.Radius - body.Radius; Vector3d sun_dir = (sun.position - body.position).normalized; solar_flux = sunlight ? Sim.SolarFlux(sun_dist) * (landed ? atmo_factor : 1.0) : 0.0; albedo_flux = sunlight ? Sim.AlbedoFlux(body, body.position + sun_dir * (body.Radius + altitude)) : 0.0; body_flux = Sim.BodyFlux(body, altitude); total_flux = solar_flux + albedo_flux + body_flux + Sim.BackgroundFlux(); temperature = !landed || !body.atmosphere ? Sim.BlackBodyTemperature(total_flux) : body.GetTemperature(0.0); temp_diff = Sim.TempDiff(temperature, body, landed); orbital_period = Sim.OrbitalPeriod(body, altitude); shadow_period = Sim.ShadowPeriod(body, altitude); shadow_time = shadow_period / orbital_period; zerog = !landed && (!body.atmosphere || body.atmosphereDepth < altitude); RadiationBody rb = Radiation.Info(body); RadiationBody sun_rb = Radiation.Info(sun); gamma_transparency = Sim.GammaTransparency(body, 0.0); extern_rad = PreferencesStorm.Instance.ExternRadiation; heliopause_rad = extern_rad + sun_rb.radiation_pause; magnetopause_rad = heliopause_rad + rb.radiation_pause; inner_rad = magnetopause_rad + rb.radiation_inner; outer_rad = magnetopause_rad + rb.radiation_outer; surface_rad = magnetopause_rad * gamma_transparency; storm_rad = heliopause_rad + PreferencesStorm.Instance.StormRadiation * (solar_flux > double.Epsilon ? 1.0 : 0.0); }
///<summary> Add radiation sub-panel, including tooltips </summary> private static void AddSubPanelRadiation(Panel p) { // get first radiation rule // - guaranteed to exist, as this panel is not rendered if it doesn't // - even without crew, it is safe to evaluate the modifiers that use it Rule rule = Profile.rules.Find(k => k.modifiers.Contains("radiation")); // detect if it use shielding bool use_shielding = rule.modifiers.Contains("shielding"); // calculate various radiation levels double[] levels = new[] { Math.Max(Radiation.Nominal, (env_analyzer.surface_rad + vessel_analyzer.emitted)), // surface Math.Max(Radiation.Nominal, (env_analyzer.magnetopause_rad + vessel_analyzer.emitted)), // inside magnetopause Math.Max(Radiation.Nominal, (env_analyzer.inner_rad + vessel_analyzer.emitted)), // inside inner belt Math.Max(Radiation.Nominal, (env_analyzer.outer_rad + vessel_analyzer.emitted)), // inside outer belt Math.Max(Radiation.Nominal, (env_analyzer.heliopause_rad + vessel_analyzer.emitted)), // interplanetary Math.Max(Radiation.Nominal, (env_analyzer.extern_rad + vessel_analyzer.emitted)), // interstellar Math.Max(Radiation.Nominal, (env_analyzer.storm_rad + vessel_analyzer.emitted)) // storm }; // evaluate modifiers (except radiation) List <string> modifiers_except_radiation = new List <string>(); foreach (string s in rule.modifiers) { if (s != "radiation") { modifiers_except_radiation.Add(s); } } double mod = Modifiers.Evaluate(env_analyzer, vessel_analyzer, resource_sim, modifiers_except_radiation); // calculate life expectancy at various radiation levels double[] estimates = new double[7]; for (int i = 0; i < 7; ++i) { estimates[i] = rule.fatal_threshold / (rule.degeneration * mod * levels[i]); } // generate tooltip RadiationModel mf = Radiation.Info(env_analyzer.body).model; string tooltip = Lib.BuildString ( "<align=left />", String.Format("{0,-20}\t<b>{1}</b>\n", Local.Planner_surface, Lib.HumanReadableDuration(estimates[0])), //"surface" mf.has_pause ? String.Format("{0,-20}\t<b>{1}</b>\n", Local.Planner_magnetopause, Lib.HumanReadableDuration(estimates[1])) : "", //"magnetopause" mf.has_inner ? String.Format("{0,-20}\t<b>{1}</b>\n", Local.Planner_innerbelt, Lib.HumanReadableDuration(estimates[2])) : "", //"inner belt" mf.has_outer ? String.Format("{0,-20}\t<b>{1}</b>\n", Local.Planner_outerbelt, Lib.HumanReadableDuration(estimates[3])) : "", //"outer belt" String.Format("{0,-20}\t<b>{1}</b>\n", Local.Planner_interplanetary, Lib.HumanReadableDuration(estimates[4])), //"interplanetary" String.Format("{0,-20}\t<b>{1}</b>\n", Local.Planner_interstellar, Lib.HumanReadableDuration(estimates[5])), //"interstellar" String.Format("{0,-20}\t<b>{1}</b>", Local.Planner_storm, Lib.HumanReadableDuration(estimates[6])) //"storm" ); // render the panel p.AddSection(Local.Planner_RADIATION, string.Empty, //"RADIATION" () => { p.Prev(ref special_index, panel_special.Count); enforceUpdate = true; }, () => { p.Next(ref special_index, panel_special.Count); enforceUpdate = true; }); p.AddContent(Local.Planner_surface, Lib.HumanReadableRadiation(env_analyzer.surface_rad + vessel_analyzer.emitted), tooltip); //"surface" p.AddContent(Local.Planner_orbit, Lib.HumanReadableRadiation(env_analyzer.magnetopause_rad), tooltip); //"orbit" if (vessel_analyzer.emitted >= 0.0) { p.AddContent(Local.Planner_emission, Lib.HumanReadableRadiation(vessel_analyzer.emitted), tooltip); //"emission" } else { p.AddContent(Local.Planner_activeshielding, Lib.HumanReadableRadiation(-vessel_analyzer.emitted), tooltip); //"active shielding" } p.AddContent(Local.Planner_shielding, rule.modifiers.Contains("shielding") ? Habitat.Shielding_to_string(vessel_analyzer.shielding) : "N/A", tooltip); //"shielding" }
public void Analyze(CelestialBody body, double altitude_mult, Planner.SunlightState sunlight) { this.body = body; CelestialBody mainSun; Vector3d sun_dir; solar_flux = Sim.SolarFluxAtBody(body, true, out mainSun, out sun_dir, out sun_dist); altitude = body.Radius * altitude_mult; landed = altitude <= double.Epsilon; atmo_factor = Sim.AtmosphereFactor(body, 0.7071); solar_flux = sunlight == Planner.SunlightState.Shadow ? 0.0 : solar_flux * (landed ? atmo_factor : 1.0); breathable = Sim.Breathable(body) && landed; albedo_flux = sunlight == Planner.SunlightState.Shadow ? 0.0 : Sim.AlbedoFlux(body, body.position + sun_dir * (body.Radius + altitude)); body_flux = Sim.BodyFlux(body, altitude); total_flux = solar_flux + albedo_flux + body_flux + Sim.BackgroundFlux(); temperature = !landed || !body.atmosphere ? Sim.BlackBodyTemperature(total_flux) : body.GetTemperature(0.0); temp_diff = Sim.TempDiff(temperature, body, landed); orbital_period = Sim.OrbitalPeriod(body, altitude); shadow_period = Sim.ShadowPeriod(body, altitude); shadow_time = shadow_period / orbital_period; zerog = !landed && (!body.atmosphere || body.atmosphereDepth < altitude); RadiationBody rb = Radiation.Info(body); RadiationBody sun_rb = Radiation.Info(mainSun); // TODO Kopernicus support: not sure if/how this work with multiple suns/stars gamma_transparency = Sim.GammaTransparency(body, 0.0); // add gamma radiation emitted by body and its sun var gamma_radiation = Radiation.DistanceRadiation(rb.radiation_r0, altitude) / 3600.0; #if DEBUG_RADIATION Lib.Log("Planner/EA: " + body + " sun " + mainSun + " alt " + altitude + " sol flux " + solar_flux + " aalbedo flux " + albedo_flux + " body flux " + body_flux + " total flux " + total_flux); Lib.Log("Planner/EA: body surface radiation " + Lib.HumanReadableRadiation(gamma_radiation, false)); #endif var b = body; while (b != null && b.orbit != null && b != mainSun) { if (b == b.referenceBody) { break; } var dist = b.orbit.semiMajorAxis; b = b.referenceBody; gamma_radiation += Radiation.DistanceRadiation(Radiation.Info(b).radiation_r0, dist) / 3600.0; #if DEBUG_RADIATION Lib.Log("Planner/EA: with gamma radiation from " + b + " " + Lib.HumanReadableRadiation(gamma_radiation, false)); Lib.Log("Planner/EA: semi major axis " + dist); #endif } extern_rad = Settings.ExternRadiation / 3600.0; heliopause_rad = gamma_radiation + extern_rad + sun_rb.radiation_pause; magnetopause_rad = gamma_radiation + heliopause_rad + rb.radiation_pause; inner_rad = gamma_radiation + magnetopause_rad + rb.radiation_inner; outer_rad = gamma_radiation + magnetopause_rad + rb.radiation_outer; surface_rad = magnetopause_rad * gamma_transparency + rb.radiation_surface / 3600.0; storm_rad = heliopause_rad + PreferencesRadiation.Instance.StormRadiation * (solar_flux > double.Epsilon ? 1.0 : 0.0); #if DEBUG_RADIATION Lib.Log("Planner/EA: extern_rad " + Lib.HumanReadableRadiation(extern_rad, false)); Lib.Log("Planner/EA: heliopause_rad " + Lib.HumanReadableRadiation(heliopause_rad, false)); Lib.Log("Planner/EA: magnetopause_rad " + Lib.HumanReadableRadiation(magnetopause_rad, false)); Lib.Log("Planner/EA: inner_rad " + Lib.HumanReadableRadiation(inner_rad, false)); Lib.Log("Planner/EA: outer_rad " + Lib.HumanReadableRadiation(outer_rad, false)); Lib.Log("Planner/EA: surface_rad " + Lib.HumanReadableRadiation(surface_rad, false)); Lib.Log("Planner/EA: storm_rad " + Lib.HumanReadableRadiation(storm_rad, false)); #endif }