protected override void OnUpdate() { foreach(Vessel v in FlightGlobals.Vessels) { vessel_info vi = Cache.VesselInfo(v); if (!vi.is_valid) continue; bool manned = v.loaded ? v.GetCrewCount() > 0 : v.protoVessel.GetVesselCrew().Count > 0; bool in_orbit = Sim.Apoapsis(v) > v.mainBody.atmosphereDepth && Sim.Periapsis(v) > v.mainBody.atmosphereDepth; bool for_30days = v.missionTime > 60.0 * 60.0 * Lib.HoursInDay() * 30.0; if (manned && in_orbit && for_30days && DB.Ready()) { base.SetComplete(); DB.Landmarks().manned_orbit = 1; //< remember that contract was completed break; } } }
void render_signal(signal_data signal, environment_data env, crew_data crew) { // approximate min/max distance between home and target body CelestialBody home = FlightGlobals.GetHomeBody(); double home_dist_min = 0.0; double home_dist_max = 0.0; if (env.body == home) { home_dist_min = env.altitude; home_dist_max = env.altitude; } else if (env.body.referenceBody == home) { home_dist_min = Sim.Periapsis(env.body); home_dist_max = Sim.Apoapsis(env.body); } else { double home_p = Sim.Periapsis(Lib.PlanetarySystem(home)); double home_a = Sim.Apoapsis(Lib.PlanetarySystem(home)); double body_p = Sim.Periapsis(Lib.PlanetarySystem(env.body)); double body_a = Sim.Apoapsis(Lib.PlanetarySystem(env.body)); home_dist_min = Math.Min(Math.Abs(home_a - body_p), Math.Abs(home_p - body_a)); home_dist_max = home_a + body_a; } // calculate if antenna is out of range from target body string range_tooltip = ""; if (signal.range > double.Epsilon) { if (signal.range < home_dist_min) range_tooltip = "<color=#ff0000>out of range</color>"; else if (signal.range < home_dist_max) range_tooltip = "<color=#ffff00>partially out of range</color>"; else range_tooltip = "<color=#00ff00>in range</color>"; if (home_dist_max > double.Epsilon) //< if not landed at home { range_tooltip += "\nbody distance (min): <b>" + Lib.HumanReadableRange(home_dist_min) + "</b>" + "\nbody distance (max): <b>" + Lib.HumanReadableRange(home_dist_max) + "</b>"; } } else if (crew.capacity == 0) range_tooltip = "<color=#ff0000>no antenna on unmanned vessel</color>"; // calculate transmission cost double cost = signal.range > double.Epsilon ? signal.transmission_cost_min + (signal.transmission_cost_max - signal.transmission_cost_min) * Math.Min(home_dist_max, signal.range) / signal.range : 0.0; string cost_str = signal.range > double.Epsilon ? cost.ToString("F1") + " EC/Mbit" : "none"; // generate ecc table Func<double, double, double, string> deduce_color = (double range, double dist_min, double dist_max) => { if (range < dist_min) return "<color=#ff0000>"; else if (range < dist_max) return "<color=#ffff00>"; else return "<color=#ffffff>"; }; double signal_100 = signal.range / signal.ecc; double signal_15 = signal_100 * 0.15; double signal_33 = signal_100 * 0.33; double signal_66 = signal_100 * 0.66; string ecc_tooltip = signal.range > double.Epsilon ? "<align=left /><b>ecc</b>\t<b>range</b>" + "\n15%\t" + deduce_color(signal_15, home_dist_min, home_dist_max) + Lib.HumanReadableRange(signal_15) + "</color>" + "\n33%\t" + deduce_color(signal_33, home_dist_min, home_dist_max) + Lib.HumanReadableRange(signal_33) + "</color>" + "\n66%\t" + deduce_color(signal_66, home_dist_min, home_dist_max) + Lib.HumanReadableRange(signal_66) + "</color>" + "\n100%\t" + deduce_color(signal_100,home_dist_min, home_dist_max) + Lib.HumanReadableRange(signal_100) + "</color>" : ""; render_title("SIGNAL"); render_content("range", Lib.HumanReadableRange(signal.range), range_tooltip); render_content("relay", signal.relay_range <= double.Epsilon ? "none" : signal.relay_range < signal.range ? Lib.HumanReadableRange(signal.relay_range) : "yes"); render_content("transmission", cost_str, "worst case data transmission cost\nfrom destination body"); render_content("error correction", (signal.ecc * 100.0).ToString("F0") + "%", ecc_tooltip); render_space(); }