private static void ShowPopup(string modName) { string title = "Kerbalism compatibility notice"; string msg = Lib.Color($"{modName} has been detected in your game.\n\nFor it to be compatible with Kerbalism, the \"Unloaded Vessel Processing\" {modName} difficulty setting option has been automatically disabled.", Lib.Kolor.Yellow, true); PopupDialog.SpawnPopupDialog ( new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog(modName, msg, title, HighLogic.UISkin, 350f, new DialogGUIButton("OK", null, true)), false, HighLogic.UISkin, true, string.Empty ); }
// transfer data between two vessels public static void Transfer(Vessel src, Vessel dst, bool samples) { double dataAmount = 0.0; int sampleSlots = 0; foreach (var drive in GetDrives(src, true)) { dataAmount += drive.FilesSize(); sampleSlots += drive.SamplesSize(); } if (dataAmount < double.Epsilon && (sampleSlots == 0 || !samples)) { return; } var allSrc = GetDrives(src, true); bool allMoved = false; foreach (var a in allSrc) { if (Transfer(a, dst, samples)) { allMoved = true; break; } } // inform the user if (allMoved) { Message.Post ( Lib.HumanReadableDataSize(dataAmount) + " " + Local.Science_ofdatatransfer, Lib.BuildString(Local.Generic_FROM, " <b>", src.vesselName, "</b> ", Local.Generic_TO, " <b>", dst.vesselName, "</b>") ); } else { Message.Post ( Lib.Color(Lib.BuildString("WARNING: not evering copied"), Lib.Kolor.Red, true), Lib.BuildString(Local.Generic_FROM, " <b>", src.vesselName, "</b> ", Local.Generic_TO, " <b>", dst.vesselName, "</b>") ); } }
static void Render_sample(Panel p, uint partId, Sample sample, Drive drive, bool short_strings) { // render experiment name string exp_label = Lib.BuildString ( "<b>", Lib.Ellipsis(sample.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)), "</b> <size=", Styles.ScaleInteger(10).ToString(), ">", Lib.Ellipsis(sample.subjectData.SituationTitle, Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(sample.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)), "</size>" ); string exp_tooltip = Lib.BuildString ( sample.subjectData.ExperimentTitle, "\n", Lib.Color(sample.subjectData.SituationTitle, Lib.Kolor.LightGrey) ); double exp_value = sample.size * sample.subjectData.SciencePerMB; if (exp_value >= 0.1) { exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value, false), "</b>"); } if (sample.mass > Double.Epsilon) { exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableMass(sample.mass), "</b>"); } if (!string.IsNullOrEmpty(sample.resultText)) { exp_tooltip = Lib.BuildString(exp_tooltip, "\n", Lib.WordWrapAtLength(sample.resultText, 50)); } p.AddContent(exp_label, Lib.HumanReadableSampleSize(sample.size), exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan)); p.AddRightIcon(sample.analyze ? Textures.lab_cyan : Textures.lab_black, Local.FILEMANAGER_analysis, () => { sample.analyze = !sample.analyze; }); //"Flag the file for analysis in a <b>laboratory</b>" p.AddRightIcon(Textures.toggle_red, Local.FILEMANAGER_Dumpsample, () => //"Dump the sample" { Lib.Popup(Local.FILEMANAGER_Warning_title, //"Warning!" Local.FILEMANAGER_DumpConfirm.Format(sample.subjectData.FullTitle), //"Do you really want to dump <<1>>?", new DialogGUIButton(Local.FILEMANAGER_DumpConfirm_button1, () => drive.Delete_sample(sample.subjectData)), //"Dump it" new DialogGUIButton(Local.FILEMANAGER_DumpConfirm_button2, () => { })); //"Keep it" } ); }
static bool Prefix(ModuleDataTransmitter __instance, ref string __result) { // Patch only if science is enabled if (!Features.Science) { return(true); } string text = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(__instance.antennaType.displayDescription()); // Antenna type: direct string result = Localizer.Format("#autoLOC_7001005", text); // Antenna rating: 500km result += Localizer.Format("#autoLOC_7001006", Lib.HumanReadableDistance(__instance.antennaPower)); result += "\n"; var dsn1 = CommNet.CommNetScenario.RangeModel.GetMaximumRange(__instance.antennaPower, GameVariables.Instance.GetDSNRange(0f)); var dsn2 = CommNet.CommNetScenario.RangeModel.GetMaximumRange(__instance.antennaPower, GameVariables.Instance.GetDSNRange(0.5f)); var dsn3 = CommNet.CommNetScenario.RangeModel.GetMaximumRange(__instance.antennaPower, GameVariables.Instance.GetDSNRange(1f)); result += Lib.BuildString(Localizer.Format("#autoLOC_236834"), " ", Lib.HumanReadableDistance(dsn1)); result += Lib.BuildString(Localizer.Format("#autoLOC_236835"), " ", Lib.HumanReadableDistance(dsn2)); result += Lib.BuildString(Localizer.Format("#autoLOC_236836"), " ", Lib.HumanReadableDistance(dsn3)); double ec = __instance.DataResourceCost * __instance.DataRate; Specifics specs = new Specifics(); specs.Add(Local.DataTransmitter_ECidle, Lib.Color(Lib.HumanReadableRate(ec * Settings.TransmitterPassiveEcFactor), Lib.Kolor.Orange)); //"EC (idle)" if (__instance.antennaType != AntennaType.INTERNAL) { specs.Add(Local.DataTransmitter_ECTX, Lib.Color(Lib.HumanReadableRate(ec * Settings.TransmitterActiveEcFactor), Lib.Kolor.Orange)); //"EC (transmitting)" specs.Add(""); specs.Add(Local.DataTransmitter_Maxspeed, Lib.HumanReadableDataRate(__instance.DataRate)); //"Max. speed" } __result = Lib.BuildString(result, "\n\n", specs.Info()); // don't call default implementation return(false); }
void Problem_storm(Vessel v, ref List <Texture2D> icons, ref List <string> tooltips) { if (Storm.Incoming(v)) { icons.Add(Textures.storm_yellow); var bd = Lib.IsSun(v.mainBody) ? v.KerbalismData().stormData : DB.Storm(Lib.GetParentPlanet(v.mainBody).name); var tti = bd.storm_time - Planetarium.GetUniversalTime(); tooltips.Add(Lib.BuildString(Lib.Color(Local.Monitor_ejectionincoming, Lib.Kolor.Orange), "\n<i>", Local.Monitor_TimetoimpactCoronalmass, Lib.HumanReadableDuration(tti), "</i>")); //"Coronal mass ejection incoming"Time to impact: } if (Storm.InProgress(v)) { icons.Add(Textures.storm_red); var bd = Lib.IsSun(v.mainBody) ? v.KerbalismData().stormData : DB.Storm(Lib.GetParentPlanet(v.mainBody).name); var remainingDuration = bd.storm_time + bd.displayed_duration - Planetarium.GetUniversalTime(); tooltips.Add(Lib.BuildString(Lib.Color(Local.Monitor_Solarstorminprogress, Lib.Kolor.Red), "\n<i>", Local.Monitor_SolarstormRemaining, Lib.HumanReadableDuration(remainingDuration), "</i>")); //"Solar storm in progress"Remaining duration: } }
static void render_habitat(Panel p, Vessel v, vessel_info vi) { // if habitat feature is disabled, do not show the panel if (!Features.Habitat) return; // if vessel is unmanned, do not show the panel if (vi.crew_count == 0) return; // render panel, add some content based on enabled features p.section("HABITAT"); if (Features.Poisoning) p.content("co2 level", Lib.Color(Lib.HumanReadablePerc(vi.poisoning, "F2"), vi.poisoning > Settings.PoisoningThreshold, "yellow")); if (!v.isEVA) { if (Features.Pressure) p.content("pressure", Lib.HumanReadablePressure(vi.pressure * Sim.PressureAtSeaLevel())); if (Features.Shielding) p.content("shielding", Habitat.shielding_to_string(vi.shielding)); if (Features.LivingSpace) p.content("living space", Habitat.living_space_to_string(vi.living_space)); if (Features.Comfort) p.content("comfort", vi.comforts.summary(), vi.comforts.tooltip()); } }
public void StoreData() { // disable for dead eva kerbals Vessel v = FlightGlobals.ActiveVessel; if (v == null || EVA.IsDead(v)) { return; } // transfer data if (!Drive.Transfer(v, drive, PreferencesScience.Instance.sampleTransfer || Lib.CrewCount(v) > 0)) { Message.Post ( Lib.Color(Lib.BuildString("WARNING: not evering copied"), Lib.Kolor.Red, true), Lib.BuildString("Storage is at capacity") ); } }
static void Render_greenhouse(Panel p, VesselData vd) { // do nothing without greenhouses if (vd.Greenhouses.Count == 0) { return; } // panel section p.AddSection(Local.TELEMETRY_GREENHOUSE); //"GREENHOUSE" // for each greenhouse for (int i = 0; i < vd.Greenhouses.Count; ++i) { var greenhouse = vd.Greenhouses[i]; // state string string state = greenhouse.issue.Length > 0 ? Lib.Color(greenhouse.issue, Lib.Kolor.Yellow) : greenhouse.growth >= 0.99 ? Lib.Color(Local.TELEMETRY_readytoharvest, Lib.Kolor.Green) //"ready to harvest" : Local.TELEMETRY_growing; //"growing" // tooltip with summary string tooltip = greenhouse.growth < 0.99 ? Lib.BuildString ( "<align=left />", Local.TELEMETRY_timetoharvest, "\t<b>", Lib.HumanReadableDuration(greenhouse.tta), "</b>\n", //"time to harvest" Local.TELEMETRY_growth, "\t\t<b>", Lib.HumanReadablePerc(greenhouse.growth), "</b>\n", //"growth" Local.TELEMETRY_naturallighting, "\t<b>", Lib.HumanReadableFlux(greenhouse.natural), "</b>\n", //"natural lighting" Local.TELEMETRY_artificiallighting, "\t<b>", Lib.HumanReadableFlux(greenhouse.artificial), "</b>" //"artificial lighting" ) : string.Empty; // render it p.AddContent(Lib.BuildString(Local.TELEMETRY_crop, " #", (i + 1).ToString()), state, tooltip); //"crop" // issues too, why not p.AddRightIcon(greenhouse.issue.Length == 0 ? Textures.plant_white : Textures.plant_yellow, tooltip); } }
internal static double RecordData(ScienceData data, MetaData meta) { double remaining = data.dataAmount; foreach (var drive in Drive.GetDrives(meta.vessel.KerbalismData(), false)) { var size = Math.Min(remaining, drive.FileCapacityAvailable()); if (size > 0) { drive.Record_file(meta.subjectData, size, true, true); remaining -= size; } } if (remaining > 0) { Message.Post( Lib.Color(Lib.BuildString(meta.subjectData.FullTitle, " stored partially"), Lib.Kolor.Orange), "Not enough space on hard drive" ); } return(remaining); }
// add a message public static void Post(Severity severity, string text, string subtext = "") { // ignore the message if muted if (instance.muted) { return; } string title = ""; switch (severity) { case Severity.relax: title = Lib.BuildString(Lib.Color(Local.Message_RELAX, Lib.Kolor.Green, true), "\n"); break; //"RELAX" case Severity.warning: title = Lib.BuildString(Lib.Color(Local.Message_WARNING, Lib.Kolor.Yellow, true), "\n"); Lib.StopWarp(); break; //"WARNING" case Severity.danger: title = Lib.BuildString(Lib.Color(Local.Message_DANGER, Lib.Kolor.Red, true), "\n"); Lib.StopWarp(); break; //"DANGER" case Severity.fatality: title = Lib.BuildString(Lib.Color(Local.Message_FATALITY, Lib.Kolor.Red, true), "\n"); Lib.StopWarp(); break; //"FATALITY" case Severity.breakdown: title = Lib.BuildString(Lib.Color(Local.Message_BREAKDOWN, Lib.Kolor.Orange, true), "\n"); Lib.StopWarp(); break; //"BREAKDOWN" } if (subtext.Length == 0) { Post(Lib.BuildString(title, text)); } else { Post(Lib.BuildString(title, text, "\n<i>", subtext, "</i>")); } all_logs.Add(new MessageObject { title = title, msg = Lib.BuildString(text, "\n<i>", subtext, "</i>"), }); TruncateLogs(); }
public string ConditionsToString() { ExpInfoSB.Length = 0; if (bodiesAllowed.Count > 0) { ExpInfoSB.Append(Lib.Color(Local.Experimentinfo_Bodiesallowed + "\n", Lib.Kolor.Cyan, true)); //Bodies allowed: for (int i = bodiesAllowed.Count - 1; i >= 0; i--) { ExpInfoSB.Append(bodiesAllowed[i].Title); if (i > 0) { ExpInfoSB.Append(", "); } } if (bodiesNotAllowed.Count > 0) { ExpInfoSB.Append("\n"); } } if (bodiesNotAllowed.Count > 0) { ExpInfoSB.Append(Lib.Color(Local.Experimentinfo_Bodiesnotallowed + "\n", Lib.Kolor.Cyan, true)); //Bodies not allowed: for (int i = bodiesNotAllowed.Count - 1; i >= 0; i--) { ExpInfoSB.Append(bodiesNotAllowed[i].Title); if (i > 0) { ExpInfoSB.Append(", "); } } } return(ExpInfoSB.ToString()); }
void Indicator_supplies(Panel p, Vessel v, VesselData vd) { List <string> tooltips = new List <string>(); uint max_severity = 0; if (vd.CrewCount > 0) { foreach (Supply supply in Profile.supplies.FindAll(k => k.resource != "ElectricCharge")) { ResourceInfo res = ResourceCache.GetResource(v, supply.resource); double depletion = res.DepletionTime(); if (res.Capacity > double.Epsilon) { if (tooltips.Count == 0) { tooltips.Add(String.Format("<align=left /><b>{0,-18}\t" + Local.Monitor_level + "\t" + Local.Monitor_duration + "</b>", Local.Monitor_name)); //level"duration"name" } tooltips.Add(Lib.Color( String.Format("{0,-18}\t{1}\t{2}", supply.resource, Lib.HumanReadablePerc(res.Level), depletion <= double.Epsilon ? Local.Monitor_depleted : Lib.HumanReadableDuration(depletion)), //"depleted" res.Level <= 0.005 ? Lib.Kolor.Red : res.Level <= supply.low_threshold ? Lib.Kolor.Orange : Lib.Kolor.None )); uint severity = res.Level <= 0.005 ? 2u : res.Level <= supply.low_threshold ? 1u : 0; max_severity = Math.Max(max_severity, severity); } } } Texture2D image = max_severity == 2 ? Textures.box_red : max_severity == 1 ? Textures.box_yellow : Textures.box_white; p.AddRightIcon(image, string.Join("\n", tooltips.ToArray())); }
public static void PostMultipleRunsMessage(string title, string vesselName) { Message.Post(Lib.Color("yellow", "ALREADY RUNNING", true), "Can't start " + title + " a second time on vessel " + vesselName); }
public void Update() { var exp = Science.Experiment(experiment_id); // in flight if (Lib.IsFlight()) { Vessel v = FlightGlobals.ActiveVessel; if (v == null || EVA.IsDead(v)) { return; } // get info from cache Vessel_info vi = Cache.VesselInfo(vessel); // do nothing if vessel is invalid if (!vi.is_valid) { return; } var sampleSize = exp.max_amount; var eta = data_rate < double.Epsilon || Done(exp, dataSampled) ? " done" : " " + Lib.HumanReadableCountdown((sampleSize - dataSampled) / data_rate); // update ui var title = Lib.Ellipsis(exp.name, Styles.ScaleStringLength(24)); if (scienceValue > 0.1) { title += " •<b>" + scienceValue.ToString("F1") + "</b>"; } string statusString = string.Empty; switch (state) { case State.ISSUE: statusString = Lib.Color("yellow", issue); break; case State.RUNNING: statusString = Lib.HumanReadablePerc(dataSampled / sampleSize) + eta; break; case State.WAITING: statusString = "waiting" + eta; break; case State.STOPPED: statusString = "stopped"; break; } Events["Toggle"].guiName = Lib.StatusToggle(title, statusString); Events["Toggle"].active = (prepare_cs == null || didPrepare); Events["Prepare"].guiName = Lib.BuildString("Prepare <b>", exp.name, "</b>"); Events["Prepare"].active = !didPrepare && prepare_cs != null && string.IsNullOrEmpty(last_subject_id); Events["Reset"].guiName = Lib.BuildString("Reset <b>", exp.name, "</b>"); // we need a reset either if we have recorded data or did a setup bool resetActive = (reset_cs != null || prepare_cs != null) && !string.IsNullOrEmpty(last_subject_id); Events["Reset"].active = resetActive; if (issue.Length > 0 && hide_when_unavailable && issue != insufficient_storage) { Events["Toggle"].active = false; } } // in the editor else if (Lib.IsEditor()) { // update ui Events["Toggle"].guiName = Lib.StatusToggle(exp.name, recording ? "recording" : "stopped"); Events["Reset"].active = false; Events["Prepare"].active = false; } }
/// <summary> /// parts that have experiments can't get their module info (what is shown in the VAB tooltip) correctly setup /// because the ExperimentInfo database isn't available at loading time, so we recompile their info manually. /// </summary> public void SetupPrefabs() { if (PartLoader.LoadedPartsList == null) { Lib.Log("Dazed and confused: PartLoader.LoadedPartsList == null"); return; } foreach (AvailablePart ap in PartLoader.LoadedPartsList) { if (ap == null || ap.partPrefab == null) { Lib.Log("AvailablePart is null or without prefab: " + ap); continue; } bool partHasExperimentModule = false; foreach (PartModule module in ap.partPrefab.Modules) { if (module is Experiment expModule) { if (expModule.experiment_id == ExperimentId) { expModule.ExpInfo = this; // works inside the ExperimentInfo ctor, but make sure it's called at the end of it. partHasExperimentModule = true; // get module info for the ExperimentInfo, once if (string.IsNullOrEmpty(ModuleInfo)) { ModuleInfo = Lib.Color(Title, Lib.Kolor.Cyan, true); ModuleInfo += "\n"; ModuleInfo += expModule.GetInfo(); } } } if (!string.IsNullOrEmpty(ModuleInfo)) { continue; } if (module is ModuleScienceExperiment stockExpModule) { if (stockExpModule.experimentID == ExperimentId) { ModuleInfo = Lib.Color(Title, Lib.Kolor.Cyan, true); ModuleInfo += "\nData size: "; ModuleInfo += Lib.HumanReadableDataSize(DataSize); if (stockExpModule.xmitDataScalar < Science.maxXmitDataScalarForSample) { ModuleInfo += "\nWill generate a sample."; ModuleInfo += "\nSample size: "; ModuleInfo += Lib.HumanReadableSampleSize(DataSize); } ModuleInfo += "\n\n"; ModuleInfo += Lib.Color("Situations:\n", Lib.Kolor.Cyan, true); foreach (string s in AvailableSituations()) { ModuleInfo += Lib.BuildString("• <b>", s, "</b>\n"); } ModuleInfo += "\n"; ModuleInfo += stockExpModule.GetInfo(); } } #if !KSP15_16 else if (module is ModuleGroundExperiment groundExpModule) { if (groundExpModule.experimentId == ExperimentId) { ModuleInfo = Lib.Color(Title, Lib.Kolor.Cyan, true); ModuleInfo += "\nData size: "; ModuleInfo += Lib.HumanReadableDataSize(DataSize); ModuleInfo += "\n\n"; ModuleInfo += groundExpModule.GetInfo(); } } #endif } // special cases if (ExperimentId == "asteroidSample") { ModuleInfo = "Asteroid samples can be taken by kerbals on EVA"; ModuleInfo += "\nSample size: "; ModuleInfo += Lib.HumanReadableSampleSize(DataSize); ModuleInfo += "\nSample mass: "; ModuleInfo += Lib.HumanReadableMass(DataSize * Settings.AsteroidSampleMassPerMB); } #if !KSP15_16 else if (IsROC) { string rocType = ExperimentId.Substring(ExperimentId.IndexOf('_') + 1); ROCDefinition rocDef = ROCManager.Instance.rocDefinitions.Find(p => p.type == rocType); if (rocDef != null) { ModuleInfo = Lib.Color(rocDef.displayName, Lib.Kolor.Cyan, true); ModuleInfo += "\n- Analyse with a scanner arm"; ModuleInfo += "\n Data size: "; ModuleInfo += Lib.HumanReadableDataSize(DataSize); if (rocDef.smallRoc) { ModuleInfo += "\n- Collectable on EVA as a sample"; ModuleInfo += "\nSample size: "; ModuleInfo += Lib.HumanReadableSampleSize(DataSize); } else { ModuleInfo += "\n- Can't be collected on EVA"; } foreach (RocCBDefinition body in rocDef.myCelestialBodies) { ModuleInfo += Lib.Color("\n\nFound on " + body.name + "'s :", Lib.Kolor.Cyan, true); foreach (string biome in body.biomes) { ModuleInfo += "\n- "; ModuleInfo += biome; } } } } #endif if (partHasExperimentModule && !ap.name.StartsWith("kerbalEVA")) { ap.moduleInfos.Clear(); ap.resourceInfos.Clear(); try { Lib.ReflectionCall(PartLoader.Instance, "CompilePartInfo", new Type[] { typeof(AvailablePart), typeof(Part) }, new object[] { ap, ap.partPrefab }); } catch (Exception ex) { Lib.Log("Could not patch the moduleInfo for part " + ap.name + " - " + ex.Message + "\n" + ex.StackTrace); } } } }
static void Render_crew(Panel p, List <ProtoCrewMember> crew) { // do nothing if there isn't a crew, or if there are no rules if (crew.Count == 0 || Profile.rules.Count == 0) { return; } // panel section p.AddSection(Local.TELEMETRY_VITALS); //"VITALS" // for each crew foreach (ProtoCrewMember kerbal in crew) { // get kerbal data from DB KerbalData kd = DB.Kerbal(kerbal.name); // analyze issues UInt32 health_severity = 0; UInt32 stress_severity = 0; // generate tooltip List <string> tooltips = new List <string>(); foreach (Rule r in Profile.rules) { // get rule data RuleData rd = kd.Rule(r.name); // add to the tooltip tooltips.Add(Lib.BuildString("<b>", Lib.HumanReadablePerc(rd.problem / r.fatal_threshold), "</b>\t", r.title)); // analyze issue if (rd.problem > r.danger_threshold) { if (!r.breakdown) { health_severity = Math.Max(health_severity, 2); } else { stress_severity = Math.Max(stress_severity, 2); } } else if (rd.problem > r.warning_threshold) { if (!r.breakdown) { health_severity = Math.Max(health_severity, 1); } else { stress_severity = Math.Max(stress_severity, 1); } } } string tooltip = Lib.BuildString("<align=left />", String.Join("\n", tooltips.ToArray())); // generate kerbal name string name = kerbal.name.ToLower().Replace(" kerman", string.Empty); // render selectable title p.AddContent(Lib.Ellipsis(name, Styles.ScaleStringLength(30)), kd.disabled ? Lib.Color(Local.TELEMETRY_HYBERNATED, Lib.Kolor.Cyan) : string.Empty); //"HYBERNATED" p.AddRightIcon(health_severity == 0 ? Textures.health_white : health_severity == 1 ? Textures.health_yellow : Textures.health_red, tooltip); p.AddRightIcon(stress_severity == 0 ? Textures.brain_white : stress_severity == 1 ? Textures.brain_yellow : Textures.brain_red, tooltip); } }
static void Render_supplies(Panel p, Vessel v, VesselData vd, VesselResources resources) { int supplies = 0; // for each supply foreach (Supply supply in Profile.supplies) { // get resource info ResourceInfo res = resources.GetResource(v, supply.resource); // only show estimate if the resource is present if (res.Capacity <= 1e-10) { continue; } // render panel title, if not done already if (supplies == 0) { p.AddSection(Local.TELEMETRY_SUPPLIES); //"SUPPLIES" } // determine label var resource = PartResourceLibrary.Instance.resourceDefinitions[supply.resource]; string label = Lib.SpacesOnCaps(resource.displayName).ToLower(); StringBuilder sb = new StringBuilder(); sb.Append("<align=left />"); if (res.AverageRate != 0.0) { sb.Append(Lib.Color(res.AverageRate > 0.0, Lib.BuildString("+", Lib.HumanReadableRate(Math.Abs(res.AverageRate))), Lib.Kolor.PosRate, Lib.BuildString("-", Lib.HumanReadableRate(Math.Abs(res.AverageRate))), Lib.Kolor.NegRate, true)); } else { sb.Append("<b>"); sb.Append(Local.TELEMETRY_nochange); //no change sb.Append("</b>"); } if (res.AverageRate < 0.0 && res.Level < 0.0001) { sb.Append(" <i>"); sb.Append(Local.TELEMETRY_empty); //(empty) sb.Append("</i>"); } else if (res.AverageRate > 0.0 && res.Level > 0.9999) { sb.Append(" <i>"); sb.Append(Local.TELEMETRY_full); //(full) sb.Append("</i>"); } else { sb.Append(" "); // spaces to prevent alignement issues } sb.Append("\t"); sb.Append(res.Amount.ToString("F1")); sb.Append("/"); sb.Append(res.Capacity.ToString("F1")); sb.Append(" ("); sb.Append(res.Level.ToString("P0")); sb.Append(")"); List <SupplyData.ResourceBrokerRate> brokers = vd.Supply(supply.resource).ResourceBrokers; if (brokers.Count > 0) { sb.Append("\n<b>------------ \t------------</b>"); foreach (SupplyData.ResourceBrokerRate rb in brokers) { sb.Append("\n"); sb.Append(Lib.Color(rb.rate > 0.0, Lib.BuildString("+", Lib.HumanReadableRate(Math.Abs(rb.rate)), " "), Lib.Kolor.PosRate, // spaces to mitigate alignement issues Lib.BuildString("-", Lib.HumanReadableRate(Math.Abs(rb.rate)), " "), Lib.Kolor.NegRate, // spaces to mitigate alignement issues true)); sb.Append("\t"); sb.Append(rb.broker.Title); } } string rate_tooltip = sb.ToString(); // finally, render resource supply p.AddContent(label, Lib.HumanReadableDuration(res.DepletionTime()), rate_tooltip); ++supplies; } }
public static void TelemetryPanel(this Panel p, Vessel v) { // avoid corner-case when this is called in a lambda after scene changes v = FlightGlobals.FindVessel(v.id); // if vessel doesn't exist anymore, leave the panel empty if (v == null) { return; } // get vessel data VesselData vd = v.KerbalismData(); // if not a valid vessel, leave the panel empty if (!vd.IsSimulated) { return; } // set metadata p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(20)), " ", Lib.Color(Local.TELEMETRY_title, Lib.Kolor.LightGrey))); //"TELEMETRY" p.Width(Styles.ScaleWidthFloat(355.0f)); p.paneltype = Panel.PanelType.telemetry; // time-out simulation if (p.Timeout(vd)) { return; } // get resources VesselResources resources = ResourceCache.Get(v); // get crew var crew = Lib.CrewList(v); // draw the content Render_crew(p, crew); if (Features.Science) { Render_science(p, v, vd); } Render_greenhouse(p, vd); Render_supplies(p, v, vd, resources); Render_habitat(p, v, vd); Render_environment(p, v, vd); // collapse eva kerbal sections into one if (v.isEVA) { p.Collapse(Local.TELEMETRY_EVASUIT); //"EVA SUIT" } }
void Indicator_signal(Panel p, Vessel v, VesselData vd) { ConnectionInfo conn = vd.Connection; // signal strength var strength = Math.Ceiling(conn.strength * 10000) / 10000; string signal_str = strength > 0.001 ? Lib.HumanReadablePerc(strength, "F2") : Lib.Color(Lib.Italic(Local.Generic_NO), Lib.Kolor.Orange); // target name string target_str = conn.linked ? conn.target_name : Local.Generic_NONE; // transmitting info string comms_str; if (!conn.linked) { comms_str = Local.Generic_NOTHING; } else if (vd.filesTransmitted.Count == 0) { comms_str = Local.UI_telemetry; } else { comms_str = Lib.BuildString(vd.filesTransmitted.Count.ToString(), vd.filesTransmitted.Count > 1 ? " files" : " file"); } // create tooltip string tooltip = Lib.BuildString ( "<align=left />", String.Format("{0,-14}\t<b>{1}</b>\n", Local.UI_DSNconnected, conn.linked ? Lib.Color(Local.Generic_YES, Lib.Kolor.Green) : Lib.Color(Lib.Italic(Local.Generic_NO), Lib.Kolor.Orange)), String.Format("{0,-14}\t<b>{1}</b>\n", Local.UI_sciencerate, Lib.HumanReadableDataRate(conn.rate)), String.Format("{0,-14}\t<b>{1}</b>\n", Local.UI_strength, signal_str), String.Format("{0,-14}\t<b>{1}</b>\n", Local.UI_target, target_str), String.Format("{0,-14}\t<b>{1}</b>", Local.UI_transmitting, comms_str) ); // create icon status Texture2D image = Textures.signal_red; switch (conn.status) { case LinkStatus.direct_link: image = conn.strength > 0.05 ? Textures.signal_white : Textures.iconSwitch(Textures.signal_yellow, image); // or 5% signal strength break; case LinkStatus.indirect_link: image = conn.strength > 0.05 ? Textures.signal_white : Textures.iconSwitch(Textures.signal_yellow, image); // or 5% signal strength tooltip += Lib.Color("\n" + Local.UI_Signalrelayed, Lib.Kolor.Yellow); break; case LinkStatus.plasma: tooltip += Lib.Color(Lib.Italic("\n" + Local.UI_Plasmablackout), Lib.Kolor.Red); break; case LinkStatus.storm: tooltip += Lib.Color(Lib.Italic("\n" + Local.UI_Stormblackout), Lib.Kolor.Red); break; } p.AddRightIcon(image, tooltip, () => UI.Open((p2) => p2.ConnMan(v))); }
public void Update() { // in flight if (Lib.IsFlight()) { Vessel v = FlightGlobals.ActiveVessel; if (v == null || EVA.IsDead(v)) { return; } // get info from cache Vessel_info vi = Cache.VesselInfo(vessel); // do nothing if vessel is invalid if (!vi.is_valid) { return; } var sampleSize = (exp.scienceCap * exp.dataScale); var recordedPercent = Lib.HumanReadablePerc(dataSampled / sampleSize); var eta = data_rate < double.Epsilon || dataSampled >= sampleSize ? " done" : " T-" + Lib.HumanReadableDuration((sampleSize - dataSampled) / data_rate); // update ui Events["Toggle"].guiName = Lib.StatusToggle(exp.experimentTitle, !recording ? "stopped" : Lib.Color(issue.Length > 0 ? "#ffff00":"", Lib.HumanReadablePerc(dataSampled / sampleSize) + "...")); Events["Toggle"].active = (prepare_cs == null || didPrepare); Events["Prepare"].guiName = Lib.BuildString("Prepare <b>", exp.experimentTitle, "</b>"); Events["Prepare"].active = !didPrepare && prepare_cs != null && string.IsNullOrEmpty(last_subject_id); Events["Reset"].guiName = Lib.BuildString("Reset <b>", exp.experimentTitle, "</b>"); // we need a reset either if we have recorded data or did a setup bool resetActive = sample_mass < float.Epsilon && (reset_cs != null || prepare_cs != null) && !string.IsNullOrEmpty(last_subject_id); Events["Reset"].active = resetActive; Fields["ExperimentStatus"].guiName = exp.experimentTitle; Fields["ExperimentStatus"].guiActive = true; if (issue.Length > 0) { ExperimentStatus = Lib.BuildString("<color=#ffff00>", issue, "</color>"); } else if (dataSampled > 0) { string a = string.Empty; string b = string.Empty; if (sample_mass < float.Epsilon) { a = Lib.HumanReadableDataSize(dataSampled); b = Lib.HumanReadableDataSize(sampleSize); } else { a = Lib.SampleSizeToSlots(dataSampled).ToString(); b = Lib.HumanReadableSampleSize(sampleSize); if (remainingSampleMass > double.Epsilon) { b += " " + Lib.HumanReadableMass(remainingSampleMass) + " left"; } } ExperimentStatus = Lib.BuildString(a, "/", b, eta); } else { var size = sample_mass < double.Epsilon ? Lib.HumanReadableDataSize(sampleSize) : Lib.HumanReadableSampleSize(sampleSize); ExperimentStatus = Lib.BuildString("ready ", size, " in ", Lib.HumanReadableDuration(sampleSize / data_rate)); } } // in the editor else if (Lib.IsEditor()) { // update ui Events["Toggle"].guiName = Lib.StatusToggle(exp.experimentTitle, recording ? "recording" : "stopped"); Events["Reset"].active = false; Events["Prepare"].active = false; } }
public static void PostMultipleRunsMessage(string title) { Message.Post(Lib.Color("red", "ALREADY RUNNING", true), "Can't start " + title + " a second time on the same vessel"); }
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" }
bool Render_vessel(Panel p, Vessel v, bool selected = false) { // get vessel info Vessel_info vi = Cache.VesselInfo(v); // skip invalid vessels if (!vi.is_valid) { return(false); } // get data from db VesselData vd = DB.Vessel(v); // get vessel crew List <ProtoCrewMember> crew = Lib.CrewList(v); // get vessel name string vessel_name = v.isEVA ? crew[0].name : v.vesselName; // get body name string body_name = v.mainBody.name.ToUpper(); // skip filtered vessels if (!Filter_match(v.vesselType, vd.group + " " + body_name + " " + vessel_name)) { return(false); } // render entry p.AddHeader ( Lib.BuildString("<b>", Lib.Ellipsis(vessel_name, Styles.ScaleStringLength(((page == MonitorPage.data || page == MonitorPage.log || selected_id == Guid.Empty) && !Lib.IsFlight()) ? 45 : 25)), "</b> <size=", Styles.ScaleInteger(9).ToString(), ">", Lib.Color("#cccccc", Lib.Ellipsis(body_name, Styles.ScaleStringLength(8))), "</size>"), string.Empty, () => { selected_id = selected_id != v.id ? v.id : Guid.Empty; } ); // vessel type icon if (!selected) { p.SetIcon(GetVesselTypeIcon(v.vesselType), v.vesselType.displayDescription(), () => { selected_id = selected_id != v.id ? v.id : Guid.Empty; }); } else { if (FlightGlobals.ActiveVessel != v) { if (Lib.IsFlight()) { p.SetIcon(GetVesselTypeIcon(v.vesselType), "Go to vessel!", () => Lib.Popup ("Warning!", Lib.BuildString("Do you really want go to ", vessel_name, " vessel?"), new DialogGUIButton("Go", () => { GotoVessel.JumpToVessel(v); }), new DialogGUIButton("Target", () => { GotoVessel.SetVesselAsTarget(v); }), new DialogGUIButton("Stay", () => { }))); } else { p.SetIcon(GetVesselTypeIcon(v.vesselType), "Go to vessel!", () => Lib.Popup ("Warning!", Lib.BuildString("Do you really want go to ", vessel_name, " vessel?"), new DialogGUIButton("Go", () => { GotoVessel.JumpToVessel(v); }), new DialogGUIButton("Stay", () => { }))); } } else { p.SetIcon(GetVesselTypeIcon(v.vesselType), v.vesselType.displayDescription(), () => { }); } } // problem indicator Indicator_problems(p, v, vi, crew); // battery indicator Indicator_ec(p, v, vi); // supply indicator if (Features.Supplies) { Indicator_supplies(p, v, vi); } // reliability indicator if (Features.Reliability) { Indicator_reliability(p, v, vi); } // signal indicator if (API.Comm.handlers.Count > 0 || HighLogic.fetch.currentGame.Parameters.Difficulty.EnableCommNet) { Indicator_signal(p, v, vi); } // done return(true); }
// analyze a sample private static Status Analyze(Vessel v, SubjectData subject, double amount) { Sample sample = null; Drive sampleDrive = null; foreach (var d in Drive.GetDrives(v, true)) { if (d.samples.ContainsKey(subject) && d.samples[subject].analyze) { sample = d.samples[subject]; sampleDrive = d; break; } } bool completed = false; if (sample != null) { completed = amount > sample.size; amount = Math.Min(amount, sample.size); } Drive fileDrive = Drive.FileDrive(v.KerbalismData(), amount); if (fileDrive == null) { return(Status.NO_STORAGE); } if (sample != null) { bool recorded = fileDrive.Record_file(subject, amount, false); double massRemoved = 0.0; if (recorded) { massRemoved = sampleDrive.Delete_sample(subject, amount); } else { Message.Post( Lib.Color(Lib.BuildString(Localizer.Format("#KERBALISM_Laboratory_Analysis"), " stopped"), Lib.Kolor.Red), "Not enough space on hard drive" ); return(Status.NO_STORAGE); } // return sample mass to experiment if needed if (massRemoved > 0.0) { RestoreSampleMass(v, subject, massRemoved); } } // if the analysis is completed if (completed) { if (!PreferencesScience.Instance.analyzeSamples) { // only inform the user if auto-analyze is turned off // otherwise we could be spamming "Analysis complete" messages Message.Post(Lib.BuildString(Lib.Color(Localizer.Format("#KERBALISM_Laboratory_Analysis"), Lib.Kolor.Science, true), "\n", Localizer.Format("#KERBALISM_Laboratory_Analyzed", Lib.Bold(v.vesselName), Lib.Bold(subject.FullTitle))), localized_results); } if (PreferencesScience.Instance.transmitScience) { fileDrive.Send(subject.Id, true); } // record landmark event if (!Lib.Landed(v)) { DB.landmarks.space_analysis = true; } } return(Status.RUNNING); }
/// <summary> /// parts that have experiments can't get their module info (what is shown in the VAB tooltip) correctly setup /// because the ExperimentInfo database isn't available at loading time, so we recompile their info manually. /// </summary> public void CompileModuleInfos() { if (PartLoader.LoadedPartsList == null) { Lib.Log("Dazed and confused: PartLoader.LoadedPartsList == null"); return; } foreach (AvailablePart ap in PartLoader.LoadedPartsList) { if (ap == null || ap.partPrefab == null) { Lib.Log("AvailablePart is null or without prefab: " + ap); continue; } foreach (PartModule module in ap.partPrefab.Modules) { if (module is Experiment expModule) { // don't show configurable experiments if (!expModule.isConfigurable && expModule.experiment_id == ExperimentId) { expModule.ExpInfo = this; // get module info for the ExperimentInfo, once if (string.IsNullOrEmpty(ModuleInfo)) { ModuleInfo = Lib.Color(Title, Lib.Kolor.Cyan, true); ModuleInfo += "\n"; ModuleInfo += expModule.GetInfo(); } } } if (!string.IsNullOrEmpty(ModuleInfo)) { continue; } if (module is ModuleScienceExperiment stockExpModule) { if (stockExpModule.experimentID == ExperimentId) { ModuleInfo = Lib.Color(Title, Lib.Kolor.Cyan, true); ModuleInfo += "\n" + Local.Experimentinfo_Datasize + ": "; //Data size ModuleInfo += Lib.HumanReadableDataSize(DataSize); if (stockExpModule.xmitDataScalar < Science.maxXmitDataScalarForSample) { ModuleInfo += "\n" + Local.Experimentinfo_generatesample; //Will generate a sample. ModuleInfo += "\n" + Local.Experimentinfo_Samplesize + " "; //Sample size: ModuleInfo += Lib.HumanReadableSampleSize(DataSize); } ModuleInfo += "\n\n"; ModuleInfo += Lib.Color(Local.Experimentinfo_Situations, Lib.Kolor.Cyan, true); //"Situations:\n" foreach (string s in AvailableSituations()) { ModuleInfo += Lib.BuildString("• <b>", s, "</b>\n"); } ModuleInfo += "\n"; ModuleInfo += stockExpModule.GetInfo(); } } else if (module is ModuleGroundExperiment groundExpModule) { if (groundExpModule.experimentId == ExperimentId) { ModuleInfo = Lib.Color(Title, Lib.Kolor.Cyan, true); ModuleInfo += "\n" + Local.Experimentinfo_Datasize + ": "; //Data size ModuleInfo += Lib.HumanReadableDataSize(DataSize); ModuleInfo += "\n\n"; ModuleInfo += groundExpModule.GetInfo(); } } } // special cases if (ExperimentId == "asteroidSample" || ExperimentId.StartsWith("cometSample_", StringComparison.Ordinal)) { ModuleInfo = Local.Experimentinfo_Asteroid; //"Asteroid samples can be taken by kerbals on EVA" ModuleInfo += "\n" + Local.Experimentinfo_Samplesize + " "; //Sample size: ModuleInfo += Lib.HumanReadableSampleSize(DataSize); ModuleInfo += "\n" + Local.Experimentinfo_Samplemass + " "; //Sample mass: ModuleInfo += Lib.HumanReadableMass(DataSize * Settings.AsteroidSampleMassPerMB); } else if (IsROC) { string rocType = ExperimentId.Substring(ExperimentId.IndexOf('_') + 1); ROCDefinition rocDef = ROCManager.Instance.rocDefinitions.Find(p => p.type == rocType); if (rocDef != null) { ModuleInfo = Lib.Color(rocDef.displayName, Lib.Kolor.Cyan, true); ModuleInfo += "\n- " + Local.Experimentinfo_scannerarm; //Analyse with a scanner arm ModuleInfo += "\n " + Local.Experimentinfo_Datasize + ": "; //Data size ModuleInfo += Lib.HumanReadableDataSize(DataSize); if (rocDef.smallRoc) { ModuleInfo += "\n- " + Local.Experimentinfo_smallRoc; //Collectable on EVA as a sample" ModuleInfo += "\n" + Local.Experimentinfo_Samplesize + " "; //Sample size: ModuleInfo += Lib.HumanReadableSampleSize(DataSize); } else { ModuleInfo += "\n- " + Local.Experimentinfo_smallRoc2; //Can't be collected on EVA } foreach (RocCBDefinition body in rocDef.myCelestialBodies) { ModuleInfo += Lib.Color("\n\n" + Local.Experimentinfo_smallRoc3.Format(body.name), Lib.Kolor.Cyan, true); //"Found on <<1>>'s :" foreach (string biome in body.biomes) { ModuleInfo += "\n- "; ModuleInfo += biome; } } } } } }
void Indicator_signal(Panel p, Vessel v, Vessel_info vi) { ConnectionInfo conn = vi.connection; bool remotetech = RemoteTech.Enabled; // signal strength or when using RemoteTech signal delay string signal_str = remotetech ? !conn.linked ? "----" : conn.strength > Double.Epsilon ? KSPUtil.dateTimeFormatter.PrintTimeStampCompact(conn.strength) : Localizer.Format("#KERBALISM_Generic_NONE") : Lib.HumanReadablePerc(conn.strength, "F2"); // target name string target_str = conn.linked ? conn.target_name : Localizer.Format("#KERBALISM_Generic_NONE"); // transmitting info string comms_str = conn.linked ? Localizer.Format("#KERBALISM_UI_telemetry") : Localizer.Format("#KERBALISM_Generic_NOTHING"); if (vi.transmitting.Length > 0) { ExperimentInfo exp = Science.Experiment(vi.transmitting); comms_str = exp.name; } // create tooltip string tooltip = Lib.BuildString ( "<align=left />", String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_DSNconnected"), conn.linked ? Lib.Color("green", Localizer.Format("#KERBALISM_Generic_YES")) : Lib.Color("#ffaa00", Lib.Italic(Localizer.Format("#KERBALISM_Generic_NO")))), String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_sciencerate"), Lib.HumanReadableDataRate(conn.rate)), String.Format("{0,-14}\t<b>{1}</b>\n", remotetech ? Localizer.Format("#KERBALISM_UI_delay") : Localizer.Format("#KERBALISM_UI_strength"), signal_str), String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_target"), target_str), String.Format("{0,-14}\t<b>{1}</b>", Localizer.Format("#KERBALISM_UI_transmitting"), comms_str) ); // create icon status Texture2D image = Icons.signal_red; switch (conn.status) { case LinkStatus.direct_link: image = remotetech ? conn.strength <15.0 ? Icons.signal_white : Icons.signal_yellow : // 15 seconds for RemoteTech signal delay conn.strength> 0.05 ? Icons.signal_white : Icons.signal_yellow; // or 5% signal strength break; case LinkStatus.indirect_link: image = remotetech ? conn.strength <15.0 ? Icons.signal_white: Icons.signal_yellow : // 15 seconds for RemoteTech signal delay conn.strength> 0.05 ? Icons.signal_white : Icons.signal_yellow; // or 5% signal strength tooltip += Lib.Color("yellow", "\n" + Localizer.Format("#KERBALISM_UI_Signalrelayed")); break; case LinkStatus.plasma: tooltip += Lib.Color("red", Lib.Italic("\n" + Localizer.Format("#KERBALISM_UI_Plasmablackout"))); break; case LinkStatus.storm: tooltip += Lib.Color("red", Lib.Italic("\n" + Localizer.Format("#KERBALISM_UI_Stormblackout"))); break; } p.AddIcon(image, tooltip); }
public void FixedUpdate() { if (scanner == null) { return; } if (!Features.Science) { return; } IsScanning = SCANsat.IsScanning(scanner); double new_coverage = SCANsat.Coverage(sensorType, vessel.mainBody); if (body_name == vessel.mainBody.name && new_coverage < body_coverage) { // SCANsat sometimes reports a coverage of 0, which is wrong new_coverage = body_coverage; } if (vessel.mainBody.name != body_name) { body_name = vessel.mainBody.name; body_coverage = new_coverage; } else { double coverage_delta = new_coverage - body_coverage; body_coverage = new_coverage; var vd = DB.Vessel(vessel); if (IsScanning) { Science.Generate_subject(experimentType, vessel); var subject_id = Science.Generate_subject_id(experimentType, vessel); var exp = Science.Experiment(subject_id); double size = exp.max_amount * coverage_delta / 100.0; // coverage is 0-100% size += warp_buffer; size = Drive.StoreFile(vessel, subject_id, size); if (size > double.Epsilon) { // we filled all drives up to the brim but were unable to store everything if (warp_buffer < double.Epsilon) { // warp buffer is empty, so lets store the rest there warp_buffer = size; size = 0; } else { // warp buffer not empty. that's ok if we didn't get new data if (coverage_delta < double.Epsilon) { size = 0; } // else we're scanning too fast. stop. } // cancel scanning and annoy the user if (size > double.Epsilon) { warp_buffer = 0; StopScan(); vd.scansat_id.Add(part.flightID); Message.Post(Lib.Color("red", "Scanner halted", true), "Scanner halted on <b>" + vessel.vesselName + "</b>. No storage left on vessel."); } } } else if (vd.scansat_id.Contains(part.flightID)) { var vi = Cache.VesselInfo(vessel); if (vi.free_capacity / vi.total_capacity > 0.9) // restart when 90% of capacity is available { StartScan(); vd.scansat_id.Remove(part.flightID); if (vd.cfg_ec) { Message.Post(Lib.BuildString("SCANsat sensor resumed operations on <b>", vessel.vesselName, "</b>")); } } } } }
public void Update() { // reset panel panel.Clear(); if (Lib.IsDevBuild) { panel.AddHeader(Lib.Color("KERBALISM DEV BUILD " + Lib.KerbalismDevBuild, Lib.Kolor.Orange)); } // get vessel selected_v = selected_id == Guid.Empty ? null : FlightGlobals.FindVessel(selected_id); // if nothing is selected, or if the selected vessel doesn't exist // anymore, or if it has become invalid for whatever reason if (selected_v == null || !selected_v.KerbalismIsValid()) { // forget the selected vessel, if any selected_id = Guid.Empty; // used to detect when no vessels are in list bool setup = false; // draw active vessel if any if (FlightGlobals.ActiveVessel != null) { setup |= Render_vessel(panel, FlightGlobals.ActiveVessel); } // for each vessel foreach (Vessel v in FlightGlobals.Vessels) { // skip active vessel if (v == FlightGlobals.ActiveVessel) { continue; } // draw the vessel setup |= Render_vessel(panel, v); } // empty vessel case if (!setup) { panel.AddHeader("<i>" + Local.Monitor_novessels + "</i>"); //no vessels } } // if a vessel is selected else { // header act as title Render_vessel(panel, selected_v, true); // update page content switch (page) { case MonitorPage.telemetry: panel.TelemetryPanel(selected_v); break; case MonitorPage.data: panel.Fileman(selected_v, true); break; // Using short_strings parameter to stop overlapping when inflight. case MonitorPage.scripts: panel.Devman(selected_v); break; case MonitorPage.config: panel.Config(selected_v); break; case MonitorPage.log: panel.Logman(selected_v); break; case MonitorPage.failures: panel.Failman(selected_v); break; } } }
void Indicator_signal(Panel p, Vessel v, Vessel_info vi) { ConnectionInfo conn = vi.connection; // signal strength string signal_str = conn.strength > Double.Epsilon ? Lib.HumanReadablePerc(Math.Ceiling(conn.strength * 10000) / 10000, "F2") : Lib.Color("#ffaa00", Lib.Italic(Localizer.Format("#KERBALISM_Generic_NO"))); // target name string target_str = conn.linked ? conn.target_name : Localizer.Format("#KERBALISM_Generic_NONE"); // transmitting info string comms_str = conn.linked ? Localizer.Format("#KERBALISM_UI_telemetry") : Localizer.Format("#KERBALISM_Generic_NOTHING"); if (vi.transmitting.Length > 0) { ExperimentInfo exp = Science.Experiment(vi.transmitting); comms_str = exp.name; } // create tooltip string tooltip = Lib.BuildString ( "<align=left />", String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_DSNconnected"), conn.linked ? Lib.Color("green", Localizer.Format("#KERBALISM_Generic_YES")) : Lib.Color("#ffaa00", Lib.Italic(Localizer.Format("#KERBALISM_Generic_NO")))), String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_sciencerate"), Lib.HumanReadableDataRate(conn.rate)), String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_strength"), signal_str), String.Format("{0,-14}\t<b>{1}</b>\n", Localizer.Format("#KERBALISM_UI_target"), target_str), String.Format("{0,-14}\t<b>{1}</b>", Localizer.Format("#KERBALISM_UI_transmitting"), comms_str) ); // create icon status Texture2D image = Icons.signal_red; switch (conn.status) { case LinkStatus.direct_link: image = conn.strength > 0.05 ? Icons.signal_white : Icons.iconSwitch(Icons.signal_yellow, image); // or 5% signal strength break; case LinkStatus.indirect_link: image = conn.strength > 0.05 ? Icons.signal_white : Icons.iconSwitch(Icons.signal_yellow, image); // or 5% signal strength tooltip += Lib.Color("yellow", "\n" + Localizer.Format("#KERBALISM_UI_Signalrelayed")); break; case LinkStatus.plasma: tooltip += Lib.Color("red", Lib.Italic("\n" + Localizer.Format("#KERBALISM_UI_Plasmablackout"))); break; case LinkStatus.storm: tooltip += Lib.Color("red", Lib.Italic("\n" + Localizer.Format("#KERBALISM_UI_Stormblackout"))); break; } p.AddIcon(image, tooltip, () => UI.Open((p2) => p2.ConnMan(v))); }
void Render_menu(Vessel v) { VesselData vd = v.KerbalismData(); GUILayout.BeginHorizontal(Styles.entry_container); GUILayout.Label(new GUIContent(Lib.Color(page == MonitorPage.telemetry, " " + Local.Monitor_INFO, Lib.Kolor.Green, Lib.Kolor.None, true), Textures.small_info, Local.Monitor_INFO_desc + Local.Monitor_tooltip), config_style); //INFO"Telemetry readings" if (Lib.IsClicked()) { page = MonitorPage.telemetry; } else if (Lib.IsClicked(2)) { if (UI.window.PanelType == Panel.PanelType.telemetry) { UI.window.Close(); } else { UI.Open((p) => p.TelemetryPanel(v)); } } if (Features.Science) { GUILayout.Label(new GUIContent(Lib.Color(page == MonitorPage.data, " " + Local.Monitor_DATA, Lib.Kolor.Green, Lib.Kolor.None, true), Textures.small_folder, Local.Monitor_DATA_desc + Local.Monitor_tooltip), config_style); //DATA"Stored files and samples" if (Lib.IsClicked()) { page = MonitorPage.data; } else if (Lib.IsClicked(2)) { if (UI.window.PanelType == Panel.PanelType.data) { UI.window.Close(); } else { UI.Open((p) => p.Fileman(v)); } } } if (Features.Automation) { GUILayout.Label(new GUIContent(Lib.Color(page == MonitorPage.scripts, " " + Local.Monitor_AUTO, Lib.Kolor.Green, Lib.Kolor.None, true), Textures.small_console, Local.Monitor_AUTO_desc + Local.Monitor_tooltip), config_style); //AUTO"Control and automate components" if (Lib.IsClicked()) { page = MonitorPage.scripts; } else if (Lib.IsClicked(2)) { if (UI.window.PanelType == Panel.PanelType.scripts) { UI.window.Close(); } else { UI.Open((p) => p.Devman(v)); } } } if (Features.Reliability) { GUILayout.Label(new GUIContent(Lib.Color(page == MonitorPage.failures, " " + Local.Monitor_FAILURES, Lib.Kolor.Green, Lib.Kolor.None, true), Textures.small_wrench, Local.Monitor_FAILURES_desc + Local.Monitor_tooltip), config_style); //FAILURES"See failures and maintenance state" if (Lib.IsClicked()) { page = MonitorPage.failures; } else if (Lib.IsClicked(2)) { if (UI.window.PanelType == Panel.PanelType.failures) { UI.window.Close(); } else { UI.Open((p) => p.Failman(v)); } } } if (PreferencesMessages.Instance.stockMessages != true) { GUILayout.Label(new GUIContent(Lib.Color(page == MonitorPage.log, " " + Local.Monitor_LOG, Lib.Kolor.Green, Lib.Kolor.None, true), Textures.small_notes, Local.Monitor_LOG_desc + Local.Monitor_tooltip), config_style); //LOG"See previous notifications" if (Lib.IsClicked()) { page = MonitorPage.log; } else if (Lib.IsClicked(2)) { if (UI.window.PanelType == Panel.PanelType.log) { UI.window.Close(); } else { UI.Open((p) => p.Logman(v)); } } } GUILayout.Label(new GUIContent(Lib.Color(page == MonitorPage.config, " " + Local.Monitor_CFG, Lib.Kolor.Green, Lib.Kolor.None, true), Textures.small_config, Local.Monitor_CFG_desc + Local.Monitor_tooltip), config_style); //CFG"Configure the vessel" if (Lib.IsClicked()) { page = MonitorPage.config; } else if (Lib.IsClicked(2)) { if (UI.window.PanelType == Panel.PanelType.config) { UI.window.Close(); } else { UI.Open((p) => p.Config(v)); } } GUILayout.EndHorizontal(); GUILayout.Space(Styles.ScaleFloat(10.0f)); }