Пример #1
0
        public static void BackgroundUpdate(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, Reliability reliability)
        {
            // if it has not malfunctioned
            if (!Lib.Proto.GetBool(m, "broken"))
            {
                // get time of next failure
                double next = Lib.Proto.GetDouble(m, "next");

                // get quality
                bool quality = Lib.Proto.GetBool(m, "quality");

                // calculate epoch of failure if necessary
                if (next <= double.Epsilon)
                {
                    double last = Planetarium.GetUniversalTime();
                    next = last + reliability.mtbf * (quality ? Settings.QualityScale : 1.0) * 2.0 * Lib.RandomDouble();
                    Lib.Proto.Set(m, "last", last);
                    Lib.Proto.Set(m, "next", next);
                }

                // if it has failed, trigger malfunction
                if (Planetarium.GetUniversalTime() > next)
                {
                    ProtoBreak(v, p, m);
                }
            }
        }
Пример #2
0
        // render the fields of the interesting body
        public static void Render()
        {
            // get interesting body
            CelestialBody body = Interesting_body();

            // maintain visualization modes
            if (body == null)
            {
                show_inner = false;
                show_outer = false;
                show_pause = false;
            }
            else
            {
                if (Input.GetKeyDown(KeyCode.Keypad0))
                {
                    if (show_inner || show_outer || show_pause)
                    {
                        show_inner = false;
                        show_outer = false;
                        show_pause = false;
                    }
                    else
                    {
                        show_inner = true;
                        show_outer = true;
                        show_pause = true;
                    }
                }
                if (Input.GetKeyDown(KeyCode.Keypad1))
                {
                    show_inner = true;
                    show_outer = false;
                    show_pause = false;
                }
                if (Input.GetKeyDown(KeyCode.Keypad2))
                {
                    show_inner = false;
                    show_outer = true;
                    show_pause = false;
                }
                if (Input.GetKeyDown(KeyCode.Keypad3))
                {
                    show_inner = false;
                    show_outer = false;
                    show_pause = true;
                }
            }


            // if there is an active body, and at least one of the modes is active
            if (body != null && (show_inner || show_outer || show_pause))
            {
                // if we don't know if preprocessing is completed
                if (preprocess_thread != null)
                {
                    // if the preprocess thread has not done yet
                    if (preprocess_thread.IsAlive)
                    {
                        // disable all modes
                        show_inner = false;
                        show_outer = false;
                        show_pause = false;

                        // tell the user and do nothing
                        Message.Post("<color=#00ffff><b>Fitting particles to signed distance fields</b></color>", "Come back in a minute");
                        return;
                    }

                    // wait for particle-fitting thread to cleanup
                    preprocess_thread.Join();

                    // preprocessing is complete
                    preprocess_thread = null;
                }


                // load and configure shader
                if (mat == null)
                {
                    if (!Settings.LowQualityRendering)
                    {
                        // load shader
                        mat = Lib.GetShader("MiniParticle");

                        // configure shader
                        mat.SetColor("POINT_COLOR", new Color(0.33f, 0.33f, 0.33f, 0.1f));
                    }
                    else
                    {
                        // load shader
                        mat = Lib.GetShader("PointParticle");

                        // configure shader
                        mat.SetColor("POINT_COLOR", new Color(0.33f, 0.33f, 0.33f, 0.1f));
                        mat.SetFloat("POINT_SIZE", 4.0f);
                    }
                }

                // generate radii-normalized GMS space
                RadiationBody rb  = Info(body);
                Space         gsm = Gsm_space(rb.body, FlightGlobals.Bodies[rb.reference]);

                // [debug] show axis
                //LineRenderer.commit(gsm.origin, gsm.origin + gsm.x_axis * gsm.scale * 5.0f, Color.red);
                //LineRenderer.commit(gsm.origin, gsm.origin + gsm.y_axis * gsm.scale * 5.0f, Color.green);
                //LineRenderer.commit(gsm.origin, gsm.origin + gsm.z_axis * gsm.scale * 5.0f, Color.blue);

                // get magnetic field data
                RadiationModel mf = Info(body).model;

                // enable material
                mat.SetPass(0);

                // render active body fields
                Matrix4x4 m = gsm.Look_at();
                if (show_inner && mf.has_inner)
                {
                    mf.inner_pmesh.Render(m);
                }
                if (show_outer && mf.has_outer)
                {
                    mf.outer_pmesh.Render(m);
                }
                if (show_pause && mf.has_pause)
                {
                    mf.pause_pmesh.Render(m);
                }
            }
        }
Пример #3
0
        static void Render_ConnectionDetail(Panel p, double range, double rate, short freq)
        {
            // render frequency
            string detail = Lib.BuildString("<size=10>", Lib.HumanReadableRange(range), "</size>");

            p.SetContent(Lib.BuildString("Frequency: <b>", freq.ToString(), "</b>"), detail, Lib.BuildString("<b>", Lib.HumanReadableDataRate(rate), "</b>"));
        }
Пример #4
0
 public static void StartScan(PartModule scanner)
 {
     Lib.ReflectionCall(scanner, "startScan");
 }
Пример #5
0
        // pseudo-ctor
        public static void Init()
        {
            // if radiation is disabled
            if (!Features.Radiation)
            {
                // create default environments for all planets
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    bodies.Add(body.bodyName, new RadiationBody(body));
                }

                // and do nothing else
                return;
            }

            // parse RadiationModel
            var rad_nodes = Lib.ParseConfigs("RadiationModel");

            foreach (var rad_node in rad_nodes)
            {
                string name = Lib.ConfigValue(rad_node, "name", "");
                if (!models.ContainsKey(name))
                {
                    models.Add(name, new RadiationModel(rad_node));
                }
            }

            // parse RadiationBody
            var body_nodes = Lib.ParseConfigs("RadiationBody");

            foreach (var body_node in body_nodes)
            {
                string name = Lib.ConfigValue(body_node, "name", "");
                if (!bodies.ContainsKey(name))
                {
                    CelestialBody body = FlightGlobals.Bodies.Find(k => k.bodyName == name);
                    if (body == null)
                    {
                        continue;                                   // skip non-existing bodies
                    }
                    bodies.Add(name, new RadiationBody(body_node, models, body));
                }
            }

            // create body environments for all the other planets
            foreach (CelestialBody body in FlightGlobals.Bodies)
            {
                if (!bodies.ContainsKey(body.bodyName))
                {
                    bodies.Add(body.bodyName, new RadiationBody(body));
                }
            }

            // remove unused models
            List <string> to_remove = new List <string>();

            foreach (var rad_pair in models)
            {
                bool used = false;
                foreach (var body_pair in bodies)
                {
                    if (body_pair.Value.model == rad_pair.Value)
                    {
                        used = true; break;
                    }
                }
                if (!used)
                {
                    to_remove.Add(rad_pair.Key);
                }
            }
            foreach (string s in to_remove)
            {
                models.Remove(s);
            }

            // start particle-fitting thread
            preprocess_thread = new Thread(Preprocess)
            {
                Name         = "particle-fitting",
                IsBackground = true
            };
            preprocess_thread.Start();
        }
Пример #6
0
 public static double Volume_per_crew(Vessel v)
 {
     // living space is the volume per-capita normalized against an 'ideal living space' and clamped in an acceptable range
     return(Tot_volume(v) / Math.Max(1, Lib.CrewCount(v)));
 }
Пример #7
0
 [KSPEvent(guiActive = false, guiActiveEditor = true, guiName = "[Debug] log volume/surface", active = false, groupName = "Habitat", groupDisplayName = "#KERBALISM_Group_Habitat")]        //Habitat
 public void LogVolumeAndSurface()
 {
     Lib.GetPartVolumeAndSurface(part, true);
 }
Пример #8
0
        // specifics support
        public Specifics Specs()
        {
            Specifics specs = new Specifics();

            specs.Add("Volume", Lib.HumanReadableVolume(volume > double.Epsilon ? volume : Lib.PartVolume(part)));
            specs.Add("Surface", Lib.HumanReadableSurface(surface > double.Epsilon ? surface : Lib.PartSurface(part)));
            specs.Add("Pressurized", max_pressure >= Settings.PressureThreshold ? "yes" : "no");
            if (inflate.Length > 0)
            {
                specs.Add("Inflatable", "yes");
            }
            if (PhysicsGlobals.KerbalCrewMass > 0)
            {
                specs.Add("Added mass per crew", Lib.HumanReadableMass(PhysicsGlobals.KerbalCrewMass));
            }

            return(specs);
        }
Пример #9
0
 // return a verbose description of shielding capability
 public static string Shielding_to_string(double v)
 {
     return(v <= double.Epsilon ? "none" : Lib.BuildString((20.0 * v / PreferencesStorm.Instance.shieldingEfficiency).ToString("F2"), " mm Pb"));
 }
Пример #10
0
		public SupplyData(ConfigNode node)
		{
			message = Lib.ConfigValue(node, "message", 0u);
		}
Пример #11
0
        public AntennaInfoRT(Vessel v, bool powered, bool storm)
        {
            RemoteTech.SetPoweredDown(v.id, !powered);
            RemoteTech.SetCommsBlackout(v.id, storm);

            // if vessel is loaded, don't calculate ec, RT already handle it.
            if (v.loaded)
            {
                // find transmitters
                foreach (Part p in v.parts)
                {
                    foreach (PartModule m in p.Modules)
                    {
                        // calculate internal (passive) transmitter ec usage @ 0.5W each
                        if (m.moduleName == "ModuleRTAntennaPassive")
                        {
                            ec += 0.0005;
                        }
                        // calculate external transmitters
                        else if (m.moduleName == "ModuleRTAntenna")
                        {
                            // only include data rate and ec cost if transmitter is active
                            if (Lib.ReflectionValue <bool>(m, "IsRTActive"))
                            {
                                rate += (Lib.ReflectionValue <float>(m, "RTPacketSize") / Lib.ReflectionValue <float>(m, "RTPacketInterval"));
                            }
                        }
                    }
                }
            }
            // if vessel is not loaded
            else
            {
                // find proto transmitters
                foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots)
                {
                    // get part prefab (required for module properties)
                    Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab;
                    foreach (ProtoPartModuleSnapshot m in p.modules)
                    {
                        // calculate internal (passive) transmitter ec usage @ 0.5W each
                        if (m.moduleName == "ModuleRTAntennaPassive")
                        {
                            ec += 0.0005;
                        }
                        // calculate external transmitters
                        else if (m.moduleName == "ModuleRTAntenna")
                        {
                            // only include data rate and ec cost if transmitter is active
                            if (Lib.Proto.GetBool(m, "IsRTActive"))
                            {
                                bool mFound = false;
                                // get all modules in prefab
                                foreach (PartModule pm in part_prefab.Modules)
                                {
                                    if (pm.moduleName == m.moduleName)
                                    {
                                        mFound = true;
                                        ModuleResource mResource       = pm.resHandler.inputResources.Find(r => r.name == "ElectricCharge");
                                        float?         packet_size     = Lib.SafeReflectionValue <float>(pm, "RTPacketSize");
                                        float?         packet_Interval = Lib.SafeReflectionValue <float>(pm, "RTPacketInterval");

                                        // workaround for old savegames
                                        if (mResource == null || packet_size == null || packet_Interval == null)
                                        {
                                            Lib.DebugLog("Old SaveGame PartModule ModuleRTAntenna for part '{0}' on unloaded vessel '{1}', using default values as a workaround", p.partName, v.vesselName);
                                            Lib.DebugLog("ElectricCharge isNull: '{0}', RTPacketSize isNull: '{1}', RTPacketInterval isNull: '{2}'", mResource == null, packet_size == null, packet_Interval == null);
                                            rate += 6.6666;                                                      // 6.67 Mb/s in 100% factor
                                            ec   += 0.025;                                                       // 25 W/s
                                        }
                                        else
                                        {
                                            rate += (float)packet_size / (float)packet_Interval;
                                            ec   += mResource.rate;
                                        }
                                    }
                                }
                                if (!mFound)
                                {
                                    Lib.DebugLog("Could not find PartModule ModuleRTAntenna for part {0} on unloaded vessel {1}, using default values as a workaround", p.partName, v.vesselName);
                                    rate += 6.6666;                                              // 6.67 Mb/s in 100% factor
                                    ec   += 0.025;                                               // 25 W/s
                                }
                            }
                        }
                    }
                }
            }

            Init(v, powered, storm);
        }
Пример #12
0
 // module info support
 public string GetModuleTitle()
 {
     return(Lib.BuildString(title, " Reliability"));
 }
Пример #13
0
        public static void ProtoBreak(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m)
        {
            // get reliability module prefab
            string      type        = Lib.Proto.GetString(m, "type", string.Empty);
            Reliability reliability = p.partPrefab.FindModulesImplementing <Reliability>().Find(k => k.type == type);

            if (reliability == null)
            {
                return;
            }

            // if manned, or if safemode didn't trigger
            if (Cache.VesselInfo(v).crew_capacity > 0 || Lib.RandomDouble() > Settings.SafeModeChance)
            {
                // flag as broken
                Lib.Proto.Set(m, "broken", true);

                // determine if this is a critical failure
                bool critical = Lib.RandomDouble() < Settings.CriticalChance;
                Lib.Proto.Set(m, "critical", critical);

                // for each associated module
                foreach (var proto_module in p.modules.FindAll(k => k.moduleName == reliability.type))
                {
                    // disable the module
                    Lib.Proto.Set(proto_module, "isEnabled", false);
                }

                // type-specific hacks
                switch (reliability.type)
                {
                case "ProcessController":
                    foreach (ProcessController pc in p.partPrefab.FindModulesImplementing <ProcessController>())
                    {
                        ProtoPartResourceSnapshot res = p.resources.Find(k => k.resourceName == pc.resource);
                        if (res != null)
                        {
                            res.flowState = false;
                        }
                    }
                    break;
                }

                // show message
                broken_msg(v, reliability.title, critical);
            }
            // safe mode
            else
            {
                // reset age
                Lib.Proto.Set(m, "last", 0.0);
                Lib.Proto.Set(m, "next", 0.0);

                // notify user
                safemode_msg(v, reliability.title);
            }

            // in any case, incentive redundancy
            if (Settings.IncentiveRedundancy)
            {
                incentive_redundancy(v, reliability.redundancy);
            }
        }
Пример #14
0
        public void Repair()
        {
            // disable for dead eva kerbals
            Vessel v = FlightGlobals.ActiveVessel;

            if (v == null || EVA.IsDead(v))
            {
                return;
            }

            // check trait
            if (!repair_cs.check(v))
            {
                Message.Post
                (
                    Lib.TextVariant
                    (
                        "I'm not qualified for this",
                        "I will not even know where to start",
                        "I'm afraid I can't do that"
                    ),
                    repair_cs.warning()
                );
                return;
            }

            // flag as not broken
            broken = false;

            // reset times
            last = 0.0;
            next = 0.0;

            // re-enable module
            foreach (PartModule m in modules)
            {
                m.isEnabled = true;
                m.enabled   = true;
            }

            // we need to reconfigure the module here, because if all modules of a type
            // share the broken state, and these modules are part of a configure setup,
            // then repairing will enable all of them, messing up with the configuration
            part.FindModulesImplementing <Configure>().ForEach(k => k.configure());

            // type-specific hacks
            apply(false);

            // notify user
            Message.Post
            (
                Lib.BuildString("<b>", title, "</b> repaired"),
                Lib.TextVariant
                (
                    "A powerkick did the trick",
                    "Duct tape, is there something it can't fix?",
                    "Fully operational again",
                    "We are back in business"
                )
            );
        }
Пример #15
0
        // specifics support
        public Specifics Specs()
        {
            Specifics specs = new Specifics();

            specs.Add(Local.Habitat_info1, Lib.HumanReadableVolume(volume > 0.0 ? volume : Lib.PartBoundsVolume(part)) + (volume > 0.0 ? "" : " (bounds)"));      //"Volume"
            specs.Add(Local.Habitat_info2, Lib.HumanReadableSurface(surface > 0.0 ? surface : Lib.PartBoundsSurface(part)) + (surface > 0.0 ? "" : " (bounds)")); //"Surface"
            specs.Add(Local.Habitat_info3, max_pressure >= Settings.PressureThreshold ? Local.Habitat_yes : Local.Habitat_no);                                    //"Pressurized""yes""no"
            if (inflate.Length > 0)
            {
                specs.Add(Local.Habitat_info4, Local.Habitat_yes);                    //"Inflatable""yes"
            }
            if (PhysicsGlobals.KerbalCrewMass > 0)
            {
                specs.Add(Local.Habitat_info5, Lib.HumanReadableMass(PhysicsGlobals.KerbalCrewMass));//"Added mass per crew"
            }
            return(specs);
        }
Пример #16
0
        static Styles()
        {
            blackBackground = Lib.GetTexture("black-background");

            // window container
            win = new GUIStyle(HighLogic.Skin.window)
            {
                padding =
                {
                    left   = ScaleInteger(6),
                    right  = ScaleInteger(6),
                    top    =               0,
                    bottom = 0
                }
            };

            // window title container
            title_container = new GUIStyle
            {
                stretchWidth = true,
                fixedHeight  = ScaleFloat(16.0f),
                margin       =
                {
                    bottom = ScaleInteger(2),
                    top    = ScaleInteger(2)
                }
            };

            // window title text
            title_text = new GUIStyle
            {
                fontStyle   = FontStyle.Bold,
                fontSize    = ScaleInteger(10),
                fixedHeight = ScaleFloat(16.0f),
                alignment   = TextAnchor.MiddleCenter
            };

            // subsection title container
            section_container = new GUIStyle
            {
                stretchWidth = true,
                fixedHeight  = ScaleFloat(16.0f),
                normal       = { background = blackBackground },
                margin       =
                {
                    bottom = ScaleInteger(4),
                    top    = ScaleInteger(4)
                }
            };

            // subsection title text
            section_text = new GUIStyle(HighLogic.Skin.label)
            {
                stretchWidth  = true,
                stretchHeight = true,
                fontSize      = ScaleInteger(12),
                alignment     = TextAnchor.MiddleCenter,
                normal        = { textColor = Color.white }
            };

            // entry row container
            entry_container = new GUIStyle
            {
                stretchWidth = true,
                fixedHeight  = ScaleFloat(16.0f)
            };

            // entry label text
            entry_label = new GUIStyle(HighLogic.Skin.label)
            {
                richText      = true,
                stretchWidth  = true,
                stretchHeight = true,
                fontSize      = ScaleInteger(12),
                alignment     = TextAnchor.MiddleLeft,
                normal        = { textColor = Color.white }
            };

            entry_label_nowrap = new GUIStyle(HighLogic.Skin.label)
            {
                richText      = true,
                wordWrap      = false,
                stretchWidth  = true,
                stretchHeight = true,
                fontSize      = ScaleInteger(12),
                alignment     = TextAnchor.MiddleLeft,
                normal        = { textColor = Color.white }
            };

            // entry value text
            entry_value = new GUIStyle(HighLogic.Skin.label)
            {
                richText      = true,
                stretchWidth  = true,
                stretchHeight = true,
                fontStyle     = FontStyle.Bold,
                fontSize      = ScaleInteger(12),
                alignment     = TextAnchor.MiddleRight,
                normal        = { textColor = Color.white }
            };

            // desc row container
            desc_container = new GUIStyle
            {
                stretchWidth  = true,
                stretchHeight = true
            };

            // entry multi-line description
            desc = new GUIStyle(entry_label)
            {
                fontStyle = FontStyle.Italic,
                alignment = TextAnchor.UpperLeft,
                margin    =
                {
                    top    = 0,
                    bottom = 0
                },
                padding =
                {
                    top    = 0,
                    bottom = ScaleInteger(10)
                }
            };

            // left icon
            left_icon = new GUIStyle
            {
                stretchWidth  = true,
                stretchHeight = true,
                fixedWidth    = ScaleFloat(16.0f),
                alignment     = TextAnchor.MiddleLeft
            };

            // right icon
            right_icon = new GUIStyle
            {
                stretchWidth  = true,
                stretchHeight = true,
                margin        = { left = ScaleInteger(8) },
                fixedWidth    = ScaleFloat(16.0f),
                alignment     = TextAnchor.MiddleRight
            };

            // tooltip label style
            tooltip = new GUIStyle(HighLogic.Skin.label)
            {
                stretchWidth  = true,
                stretchHeight = true,
                fontSize      = ScaleInteger(12),
                alignment     = TextAnchor.MiddleCenter,
                border        = new RectOffset(0, 0, 0, 0),
                normal        =
                {
                    textColor  = Color.white,
                    background = blackBackground
                },
                margin  = new RectOffset(0, 0, 0, 0),
                padding = new RectOffset(ScaleInteger(6), ScaleInteger(6), ScaleInteger(3), ScaleInteger(3))
            };

            tooltip.normal.background.wrapMode = TextureWrapMode.Repeat;

            // tooltip container style
            tooltip_container = new GUIStyle
            {
                stretchWidth  = true,
                stretchHeight = true
            };

            smallStationHead = new GUIStyle(HighLogic.Skin.label)
            {
                fontSize = ScaleInteger(12)
            };

            smallStationText = new GUIStyle(HighLogic.Skin.label)
            {
                fontSize = ScaleInteger(12),
                normal   = { textColor = Color.white }
            };

            message = new GUIStyle()
            {
                normal =
                {
                    background = blackBackground,
                    textColor  = new Color(0.66f, 0.66f, 0.66f, 1.0f)
                },
                richText      = true,
                stretchWidth  = true,
                stretchHeight = true,
                fixedWidth    = 0,
                fixedHeight   = 0,
                fontSize      = Styles.ScaleInteger(12),
                alignment     = TextAnchor.MiddleCenter,
                border        = new RectOffset(0, 0, 0, 0),
                padding       = new RectOffset(Styles.ScaleInteger(2), Styles.ScaleInteger(2), Styles.ScaleInteger(2), Styles.ScaleInteger(2))
            };
        }
Пример #17
0
 // return living space factor in a vessel
 public static double Living_space(Vessel v)
 {
     // living space is the volume per-capita normalized against an 'ideal living space' and clamped in an acceptable range
     return(Lib.Clamp(Volume_per_crew(v) / PreferencesComfort.Instance.livingSpace, 0.1, 1.0));
 }
Пример #18
0
  // add a message related to vessel resources
  public static void Post(Severity severity, VesselEvent e, Vessel v)
  {
    bool is_eva = v.isEVA;
    bool is_probe = Lib.CrewCapacity(v) == 0;
    string text = "";
    string subtext = "";

    // vessel
    if (!v.isEVA)
    {
      switch(e)
      {
        // electric charge
        case VesselEvent.ec:

          // manned vessel
          if (Lib.CrewCapacity(v) > 0)
          {
            switch(severity)
            {
              case Severity.relax:    text = "$VESSEL batteries recharged"; subtext = "The crew is allowed music again"; break;
              case Severity.warning:  text = "On $VESSEL, batteries are almost empty"; subtext = "We are squeezing the last bit of juice"; break;
              case Severity.danger:   text = "There is no more electric charge on $VESSEL"; subtext = "Life support systems are off"; break;
            }
          }
          // probe
          else
          {
            switch(severity)
            {
              case Severity.relax:    text = "$VESSEL batteries recharged";  subtext = "Systems are back online"; break;
              case Severity.warning:  text = "On $VESSEL, batteries are almost empty"; subtext = "Shutting down non-essential systems"; break;
              case Severity.danger:   text = "There is no more electric charge on $VESSEL"; subtext = "We lost control"; break;
            }
          }
          break;

        // food
        case VesselEvent.food:

          switch(severity)
          {
            case Severity.relax:      text = "$VESSEL food reserves restored"; subtext = "Double snack rations for everybody"; break;
            case Severity.warning:    text = "On $VESSEL, food reserves are getting low"; subtext = "Anything edible is being scrutinized"; break;
            case Severity.danger:     text = "There is no more food on $VESSEL"; subtext = "The crew prepare to the inevitable"; break;
          }
          break;

        // oxygen
        case VesselEvent.oxygen:

          switch(severity)
          {
            case Severity.relax:      text = "$VESSEL oxygen reserves restored"; subtext = "The crew is taking a breather"; break;
            case Severity.warning:    text = "On $VESSEL, oxygen reserves are dangerously low"; subtext = "There is mildly panic among the crew"; break;
            case Severity.danger:     text = "There is no more oxygen on $VESSEL"; subtext = "Everybody stop breathing"; break;
          }
          break;
      }
    }
    // eva
    else
    {
      switch(e)
      {
        // electric charge
        case VesselEvent.ec:

          switch(severity)
          {
            case Severity.relax:      text = "$VESSEL recharged the battery"; break;
            case Severity.warning:    text = "$VESSEL is running out of power"; break;
            case Severity.danger:     text = "$VESSEL is out of power"; break;
          }
          break;

        // oxygen
        case VesselEvent.oxygen:

          switch(severity)
          {
            case Severity.relax:      text = "$VESSEL oxygen tank has been refilled"; break;
            case Severity.warning:    text = "$VESSEL is running out of oxygen"; break;
            case Severity.danger:     text = "$VESSEL is out of oxygen"; break;
          }
          break;
      }
    }

    text = text.Replace("$VESSEL", "<color=ffffff>" + v.vesselName + "</color>");

    Post(severity, text, subtext);
  }
Пример #19
0
 // return a verbose description of shielding capability
 public static string Shielding_to_string(double v)
 {
     return(v <= double.Epsilon ? Local.Habitat_none : Lib.BuildString((20.0 * v / PreferencesRadiation.Instance.shieldingEfficiency).ToString("F2"), " mm"));//"none"
 }
Пример #20
0
        // pseudo-ctor
        public override void OnStart(StartState state)
        {
            // don't break tutorial scenarios
            if (Lib.DisableScenario(this))
            {
                return;
            }

            // check if has Connected Living Space mod
            hasCLS = Lib.HasAssembly("ConnectedLivingSpace");

            // if part has Gravity Ring, find it.
            gravityRing    = part.FindModuleImplementing <GravityRing>();
            hasGravityRing = gravityRing != null;

            if (volume <= 0.0 || surface <= 0.0)
            {
                Habitat prefab = part.partInfo.partPrefab.FindModuleImplementing <Habitat>();
                if (volume <= 0.0)
                {
                    volume = prefab.volume;
                }
                if (surface <= 0.0)
                {
                    surface = prefab.surface;
                }
            }

            // set RMB UI status strings
            Volume  = Lib.HumanReadableVolume(volume);
            Surface = Lib.HumanReadableSurface(surface);

            // hide toggle if specified
            Events["Toggle"].active = toggle;
            //Actions["Action"].active = toggle;

#if DEBUG
            Events["LogVolumeAndSurface"].active = true;
#else
            Events["LogVolumeAndSurface"].active = Settings.VolumeAndSurfaceLogging;
#endif
            // create animators
            if (!hasGravityRing)
            {
                inflate_anim = new Animator(part, inflate);
            }

            // configure on start
            Configure();

            perctDeployed = Lib.Level(part, "Atmosphere", true);

            switch (this.state)
            {
            case State.enabled: Set_flow(true); break;

            case State.disabled: Set_flow(false); break;

            case State.pressurizing: Set_flow(true); break;

            case State.depressurizing: Set_flow(false); break;
            }

            if (Get_inflate_string().Length == 0) // not inflatable
            {
                SetPassable(true);
                UpdateIVA(true);
            }
            else
            {
                SetPassable(Math.Truncate(Math.Abs((perctDeployed + ResourceBalance.precision) - 1.0) * 100000) / 100000 <= ResourceBalance.precision);
                UpdateIVA(Math.Truncate(Math.Abs((perctDeployed + ResourceBalance.precision) - 1.0) * 100000) / 100000 <= ResourceBalance.precision);
            }

            if (Lib.IsFlight())
            {
                // For fix IVA when crewTransfered occur, add event to define flag for FixedUpdate
                GameEvents.onCrewTransferred.Add(UpdateCrew);
            }
        }
Пример #21
0
 public static bool IsScanning(PartModule scanner)
 {
     return(Lib.ReflectionValue <bool>(scanner, "scanning"));
 }
Пример #22
0
 void Set_flow(bool b)
 {
     Lib.SetResourceFlow(part, "Atmosphere", b);
     Lib.SetResourceFlow(part, "WasteAtmosphere", b);
     Lib.SetResourceFlow(part, "Shielding", b);
 }
Пример #23
0
        public void Render()
        {
            // headers
            foreach (Header h in headers)
            {
                GUILayout.BeginHorizontal(Styles.entry_container);
                if (h.leftIcon != null)
                {
                    GUILayout.Label(new GUIContent(h.leftIcon.texture, h.leftIcon.tooltip), Styles.left_icon);
                    if (h.leftIcon.click != null && Lib.IsClicked())
                    {
                        callbacks.Add(h.leftIcon.click);
                    }
                }
                GUILayout.Label(new GUIContent(h.label, h.tooltip), Styles.entry_label_nowrap);
                if (h.click != null && Lib.IsClicked())
                {
                    callbacks.Add(h.click);
                }
                foreach (Icon i in h.icons)
                {
                    GUILayout.Label(new GUIContent(i.texture, i.tooltip), Styles.right_icon);
                    if (i.click != null && Lib.IsClicked())
                    {
                        callbacks.Add(i.click);
                    }
                }
                GUILayout.EndHorizontal();
                GUILayout.Space(Styles.ScaleFloat(10.0f));
            }

            // sections
            foreach (Section p in sections)
            {
                // section title
                GUILayout.BeginHorizontal(Styles.section_container);
                if (p.left != null)
                {
                    GUILayout.Label(Textures.left_arrow, Styles.left_icon);
                    if (Lib.IsClicked())
                    {
                        callbacks.Add(p.left);
                    }
                }
                GUILayout.Label(p.title, Styles.section_text);
                if (p.right != null)
                {
                    GUILayout.Label(Textures.right_arrow, Styles.right_icon);
                    if (Lib.IsClicked())
                    {
                        callbacks.Add(p.right);
                    }
                }
                GUILayout.EndHorizontal();

                // description
                if (p.desc.Length > 0)
                {
                    GUILayout.BeginHorizontal(Styles.desc_container);
                    GUILayout.Label(p.desc, Styles.desc);
                    GUILayout.EndHorizontal();
                }

                // entries
                if (p.needsSort)
                {
                    p.needsSort = false;
                    p.entries.Sort((a, b) => string.Compare(a.label, b.label, StringComparison.Ordinal));
                }
                foreach (Entry e in p.entries)
                {
                    GUILayout.BeginHorizontal(Styles.entry_container);
                    if (e.leftIcon != null)
                    {
                        GUILayout.Label(new GUIContent(e.leftIcon.texture, e.leftIcon.tooltip), Styles.left_icon);
                        if (e.leftIcon.click != null && Lib.IsClicked())
                        {
                            callbacks.Add(e.leftIcon.click);
                        }
                    }
                    GUILayout.Label(new GUIContent(e.label, e.tooltip), Styles.entry_label, GUILayout.Height(Styles.entry_label.fontSize));
                    if (e.hover != null && Lib.IsHover())
                    {
                        callbacks.Add(e.hover);
                    }
                    GUILayout.Label(new GUIContent(e.value, e.tooltip), Styles.entry_value, GUILayout.Height(Styles.entry_value.fontSize));
                    if (e.click != null && Lib.IsClicked())
                    {
                        callbacks.Add(e.click);
                    }
                    if (e.hover != null && Lib.IsHover())
                    {
                        callbacks.Add(e.hover);
                    }
                    foreach (Icon i in e.icons)
                    {
                        GUILayout.Label(new GUIContent(i.texture, i.tooltip), Styles.right_icon);
                        if (i.click != null && Lib.IsClicked())
                        {
                            callbacks.Add(i.click);
                        }
                    }
                    GUILayout.EndHorizontal();
                }

                // spacing
                GUILayout.Space(Styles.ScaleFloat(10.0f));
            }

            // call callbacks
            if (Event.current.type == EventType.Repaint)
            {
                foreach (Action func in callbacks)
                {
                    func();
                }
                callbacks.Clear();
            }
        }
Пример #24
0
        public void Update()
        {
            // The first time an existing save game is loaded with Kerbalism installed,
            // MM will to any existing vessels add Nitrogen with the correct capacities as set in default.cfg but they will have zero amounts,
            // this is not the case for any newly created vessels in the editor.
            if (configured)
            {
                if (state == State.enabled && Features.Pressure)
                {
                    Lib.FillResource(part, "Nitrogen");
                }
                else
                {
                    Lib.EmptyResource(part, "Nitrogen");
                }
                configured = false;
            }

            // update ui
            string status_str = string.Empty;

            switch (state)
            {
            case State.enabled:
                if (Math.Truncate(Math.Abs((perctDeployed + ResourceBalance.precision) - 1.0) * 100000) / 100000 > ResourceBalance.precision)
                {
                    // No inflatable can be enabled been pressurizing
                    status_str = Local.Habitat_pressurizing;
                }
                else
                {
                    status_str = Local.Generic_ENABLED;
                }
                Set_pressurized(true);

                // GOT 12-2020 : Disabling ability to disable habs due to pressurization bugs that I'm not willing to investigate
                Events["Toggle"].guiActive = false;
                break;

            case State.disabled:
                status_str = Local.Generic_DISABLED;
                Set_pressurized(false);
                break;

            case State.pressurizing:
                status_str  = Get_inflate_string().Length == 0 ? Local.Habitat_pressurizing : Local.Habitat_inflating;
                status_str += string.Format("{0:p2}", perctDeployed);
                Set_pressurized(false);
                break;

            case State.depressurizing:
                status_str  = Get_inflate_string().Length == 0 ? Local.Habitat_depressurizing : Local.Habitat_deflating;
                status_str += string.Format("{0:p2}", perctDeployed);
                Set_pressurized(false);
                break;
            }

            Events["Toggle"].guiName = Lib.StatusToggle(Local.StatuToggle_Habitat, status_str);//"Habitat"

            // Changing this animation when we expect rotation will not work because
            // Unity disables other animations when playing the inflation animation.
            if (prev_state != State.enabled)
            {
                Set_inflation();
            }
            prev_state = state;
        }
Пример #25
0
        // do the particle-fitting in another thread
        public static void Preprocess()
        {
            // deduce number of particles
            int inner_count = 150000;
            int outer_count = 600000;
            int pause_count = 250000;

            if (Settings.LowQualityRendering)
            {
                inner_count /= 5;
                outer_count /= 5;
                pause_count /= 5;
            }

            // start time
            UInt64 time = Lib.Clocks();

            // create all magnetic fields and do particle-fitting
            List <string> done = new List <string>();

            foreach (var pair in models)
            {
                // get radiation data
                RadiationModel mf = pair.Value;

                // skip if model is already done
                if (done.Contains(mf.name))
                {
                    continue;
                }

                // add to the skip list
                done.Add(mf.name);

                // if it has a field
                if (mf.Has_field())
                {
                    // some feedback in the log
                    // note: can't use BuildString here, as it is not thread-safe
                    Lib.Log("particle-fitting '" + mf.name + "'...");
                }

                // particle-fitting for the inner radiation belt
                if (mf.has_inner)
                {
                    mf.inner_pmesh = new ParticleMesh(mf.Inner_func, mf.Inner_domain(), mf.Inner_offset(), inner_count, mf.inner_quality);
                }

                // particle-fitting for the outer radiation belt
                if (mf.has_outer)
                {
                    mf.outer_pmesh = new ParticleMesh(mf.Outer_func, mf.Outer_domain(), mf.Outer_offset(), outer_count, mf.outer_quality);
                }

                // particle-fitting for the magnetopause
                if (mf.has_pause)
                {
                    mf.pause_pmesh = new ParticleMesh(mf.Pause_func, mf.Pause_domain(), mf.Pause_offset(), pause_count, mf.pause_quality);
                }
            }

            // measure time required
            // note: can't use BuildString here, as it is not thread-safe
            Lib.Log("particle-fitting completed in " + Lib.Seconds(Lib.Clocks() - time).ToString("F3") + " seconds");
        }
Пример #26
0
        public void FixedUpdate()
        {
            // if part is manned (even in the editor), force enabled
            if (Lib.IsCrewed(part) && state != State.enabled)
            {
                Set_flow(true);
                state = State.pressurizing;

                // Equalize run only in Flight mode
                needEqualize = Lib.IsFlight();
            }

            perctDeployed = Lib.Level(part, "Atmosphere", true);

            // Only handle crewTransferred & Toggle, this way has less calls in FixedUpdate
            // CrewTransferred Event occur after FixedUpdate, this must be check in crewtransferred
            if (FixIVA)
            {
                if (Get_inflate_string().Length == 0) // it is not inflatable (We always going to show and cross those habitats)
                {
                    SetPassable(true);
                    UpdateIVA(true);
                }
                else
                {
                    // Inflatable modules shows IVA and are passable only in 99.9999% deployed
                    SetPassable(Lib.IsCrewed(part) || Math.Truncate(Math.Abs((perctDeployed + ResourceBalance.precision) - 1.0) * 100000) / 100000 <= ResourceBalance.precision);
                    UpdateIVA(Math.Truncate(Math.Abs((perctDeployed + ResourceBalance.precision) - 1.0) * 100000) / 100000 <= ResourceBalance.precision);
                }
                FixIVA = false;
            }

            // state machine
            switch (state)
            {
            case State.enabled:
                // In case it is losting pressure
                if (perctDeployed < Settings.PressureThreshold)
                {
                    if (Get_inflate_string().Length != 0)             // it is inflatable
                    {
                        SetPassable(false || Lib.IsCrewed(part));     // Prevent to not lock a Kerbal into a the part
                        UpdateIVA(false);
                    }
                    needEqualize = true;
                    state        = State.pressurizing;
                }
                break;

            case State.disabled:
                break;

            case State.pressurizing:
                state = Pressurizing();
                break;

            case State.depressurizing:
                // Just do Venting when has no gravityRing or when the gravity ring is not spinning.
                if (hasGravityRing && !gravityRing.Is_rotating())
                {
                    state = Depressurizing();
                }
                else if (!hasGravityRing)
                {
                    state = Depressurizing();
                }
                break;
            }
        }
Пример #27
0
        // return the total environent radiation at position specified
        public static double Compute(Vessel v, Vector3d position, double gamma_transparency, double sunlight, out bool blackout,
                                     out bool magnetosphere, out bool inner_belt, out bool outer_belt, out bool interstellar)
        {
            // prepare out parameters
            blackout      = false;
            magnetosphere = false;
            inner_belt    = false;
            outer_belt    = false;
            interstellar  = false;

            // no-op when Radiation is disabled
            if (!Features.Radiation)
            {
                return(0.0);
            }

            // store stuff
            Space   gsm;
            Vector3 p;
            float   D;

            // transform to local space once
            position = ScaledSpace.LocalToScaledSpace(position);

            // accumulate radiation
            double        radiation = 0.0;
            CelestialBody body      = v.mainBody;

            while (body != null)
            {
                RadiationBody  rb = Info(body);
                RadiationModel mf = rb.model;
                if (mf.Has_field())
                {
                    // generate radii-normalized GSM space
                    gsm = Gsm_space(rb.body, FlightGlobals.Bodies[rb.reference]);

                    // move the poing in GSM space
                    p = gsm.Transform_in(position);

                    // accumulate radiation and determine pause/belt flags
                    if (mf.has_inner)
                    {
                        D           = mf.Inner_func(p);
                        radiation  += Lib.Clamp(D / -0.0666f, 0.0f, 1.0f) * rb.radiation_inner;
                        inner_belt |= D < 0.0f;
                    }
                    if (mf.has_outer)
                    {
                        D           = mf.Outer_func(p);
                        radiation  += Lib.Clamp(D / -0.0333f, 0.0f, 1.0f) * rb.radiation_outer;
                        outer_belt |= D < 0.0f;
                    }
                    if (mf.has_pause)
                    {
                        D              = mf.Pause_func(p);
                        radiation     += Lib.Clamp(D / -0.1332f, 0.0f, 1.0f) * rb.radiation_pause;
                        magnetosphere |= D < 0.0f && rb.body.flightGlobalsIndex != 0;                        //< ignore heliopause
                        interstellar  |= D > 0.0f && rb.body.flightGlobalsIndex == 0;                        //< outside heliopause
                    }
                }

                // avoid loops in the chain
                body = (body.referenceBody != null && body.referenceBody.referenceBody == body) ? null : body.referenceBody;
            }

            // add extern radiation
            radiation += Settings.ExternRadiation;

            // add emitter radiation
            radiation += Emitter.Total(v);

            // if there is a storm in progress
            if (Storm.InProgress(v))
            {
                // inside a magnetopause (except heliosphere), blackout the signal
                // outside, add storm radiations modulated by sun visibility
                if (magnetosphere)
                {
                    blackout = true;
                }
                else
                {
                    radiation += Settings.StormRadiation * sunlight;
                }
            }

            // clamp radiation to positive range
            // note: we avoid radiation going to zero by using a small positive value
            radiation = Math.Max(radiation, Nominal);

            // return radiation, scaled by gamma transparency if inside atmosphere
            return(radiation * gamma_transparency);
        }
Пример #28
0
        // volume / surface evaluation at prefab compilation
        public override void OnLoad(ConfigNode node)
        {
            // volume/surface calcs are quite slow and memory intensive, so we do them only once on the prefab
            // then get the prefab values from OnStart. Moreover, we cache the results in the
            // Kerbalism\HabitatData.cache file and reuse those cached results on next game launch.
            if (HighLogic.LoadedScene == GameScenes.LOADING)
            {
                if (volume <= 0.0 || surface <= 0.0)
                {
                    if (habitatDatabase == null)
                    {
                        ConfigNode   dbRootNode   = ConfigNode.Load(HabitatDataCachePath);
                        ConfigNode[] habInfoNodes = dbRootNode?.GetNodes(habitatDataCacheNodeName);
                        habitatDatabase = new Dictionary <string, Lib.PartVolumeAndSurfaceInfo>();

                        if (habInfoNodes != null)
                        {
                            for (int i = 0; i < habInfoNodes.Length; i++)
                            {
                                string partName = habInfoNodes[i].GetValue("partName") ?? string.Empty;
                                if (!string.IsNullOrEmpty(partName) && !habitatDatabase.ContainsKey(partName))
                                {
                                    habitatDatabase.Add(partName, new Lib.PartVolumeAndSurfaceInfo(habInfoNodes[i]));
                                }
                            }
                        }
                    }

                    // SSTU specific support copypasted from the old system, not sure how well this works
                    foreach (PartModule pm in part.Modules)
                    {
                        if (pm.moduleName == "SSTUModularPart")
                        {
                            Bounds bb = Lib.ReflectionCall <Bounds>(pm, "getModuleBounds", new Type[] { typeof(string) }, new string[] { "CORE" });
                            if (bb != null)
                            {
                                if (volume <= 0.0)
                                {
                                    volume = Lib.BoundsVolume(bb) * 0.785398;                                                // assume it's a cylinder
                                }
                                if (surface <= 0.0)
                                {
                                    surface = Lib.BoundsSurface(bb) * 0.95493;                                                 // assume it's a cylinder
                                }
                            }
                            return;
                        }
                    }

                    string configPartName = part.name.Replace('.', '_');
                    Lib.PartVolumeAndSurfaceInfo partInfo;
                    if (!habitatDatabase.TryGetValue(configPartName, out partInfo))
                    {
                        // Find deploy/retract animations, either here on in the gravityring module
                        // then set the part to the deployed state before doing the volume/surface calcs
                        // if part has Gravity Ring, find it.
                        gravityRing    = part.FindModuleImplementing <GravityRing>();
                        hasGravityRing = gravityRing != null;

                        // create animators and set the model to the deployed state
                        if (hasGravityRing)
                        {
                            gravityRing.deploy_anim          = new Animator(part, gravityRing.deploy);
                            gravityRing.deploy_anim.reversed = gravityRing.animBackwards;

                            if (gravityRing.deploy_anim.IsDefined)
                            {
                                gravityRing.deploy_anim.Still(1.0);
                            }
                        }
                        else
                        {
                            inflate_anim          = new Animator(part, inflate);
                            inflate_anim.reversed = animBackwards;

                            if (inflate_anim.IsDefined)
                            {
                                inflate_anim.Still(1.0);
                            }
                        }

                        // get surface and volume
                        partInfo = Lib.GetPartVolumeAndSurface(part, Settings.VolumeAndSurfaceLogging);

                        habitatDatabase.Add(configPartName, partInfo);
                    }

                    partInfo.GetUsingMethod(
                        volumeAndSurfaceMethod != Lib.VolumeAndSurfaceMethod.Best ? volumeAndSurfaceMethod : partInfo.bestMethod,
                        out double infoVolume, out double infoSurface, substractAttachementNodesSurface);

                    if (volume <= 0.0)
                    {
                        volume = infoVolume;
                    }
                    if (surface <= 0.0)
                    {
                        surface = infoSurface;
                    }
                }
            }
        }
Пример #29
0
        public static void NetMan(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 info from the cache
            Vessel_Info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 20), " <color=#cccccc>NETWORK INFO</color>"));

            // time-out simulation
#if !DEBUG
            if (p.Timeout(vi))
            {
                return;
            }
#endif

            p.SetSection("ADAPTORS");
            p.Set_IsFreqSelector(true);

            // store all devices
            var devices = new Dictionary <uint, NetDevice>();

            // store device being added
            NetDevice adap;

            // loaded vessel
            if (v.loaded)
            {
                foreach (NetworkAdaptor m in Lib.FindModules <NetworkAdaptor>(v))
                {
                    adap = new NetAdaptorDevice(m);

                    // add the device
                    // - multiple same-type components in the same part will have the same id, and are ignored
                    if (!devices.ContainsKey(adap.Id()))
                    {
                        devices.Add(adap.Id(), adap);
                    }
                }
            }
            else
            {
                // store data required to support multiple modules of same type in a part
                var PD = new Dictionary <string, Lib.module_prefab_data>();

                // for each part
                foreach (ProtoPartSnapshot proto in v.protoVessel.protoPartSnapshots)
                {
                    // get part prefab (required for module properties)
                    Part part_prefab = PartLoader.getPartInfoByName(proto.partName).partPrefab;

                    // get all module prefabs
                    var module_prefabs = part_prefab.FindModulesImplementing <PartModule>();

                    // clear module indexes
                    PD.Clear();

                    // for each module
                    foreach (ProtoPartModuleSnapshot m in proto.modules)
                    {
                        // get the module prefab
                        // if the prefab doesn't contain this module, skip it
                        PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD);
                        if (!module_prefab)
                        {
                            continue;
                        }

                        // if the module is disabled, skip it
                        // note: this must be done after ModulePrefab is called, so that indexes are right
                        if (!Lib.Proto.GetBool(m, "isEnabled"))
                        {
                            continue;
                        }

                        if (m.moduleName == "NetworkAdaptor")
                        {
                            adap = new ProtoNetAdaptorDevice(m, proto.flightID, v);

                            // add the device
                            // - multiple same-type components in the same part will have the same id, and are ignored
                            if (!devices.ContainsKey(adap.Id()))
                            {
                                devices.Add(adap.Id(), adap);
                            }
                        }
                    }
                }
            }

            // dict order by device name
            // for each device
            foreach (var pair in devices.OrderBy(x => x.Value.Name()))
            {
                // render device entry
                NetDevice dev = pair.Value;
                // Get how many antennas share the same freq
                AntennasByFrequency x = null;
                if (vi.antenna.antennasByFreq.ContainsKey(dev.InfoFreq()))
                {
                    x = vi.antenna.antennasByFreq[dev.InfoFreq()];
                }

                p.SetContent(dev.Name(), dev.InfoRate(), string.Empty, null, () => Highlighter.Set(dev.Part(), Color.cyan), dev.InfoFreq());
                p.SetIcon(Icons.left_freq, "Decrease", () =>
                {
                    if (dev.InfoFreq() > 0) // && x != null
                    {
                        //if (x.antCount == 1 && x.countConnections > 0)
                        //{
                        //  Lib.Popup(
                        //    "Warning!",
                        //    Lib.BuildString("This is the last antenna on '", dev.InfoFreq().ToString(),
                        //                    "' frequency.\nYou will lost connection in this frequency.\nDo you really want to remove this frequency from this vessel?"),
                        //    new DialogGUIButton("Remove", () => dev.ChangeFreq(-1)),
                        //    new DialogGUIButton("Keep it", () => { }));
                        //}
                        //else
                        dev.ChangeFreq(-1);
                    }
                });
                p.SetIcon(Icons.right_freq, "Increase", () =>
                {
                    if (dev.InfoFreq() < 99) // && x != null
                    {
                        //if (x.antCount == 1 && x.countConnections > 0)
                        //{
                        //  Lib.Popup(
                        //    "Warning!",
                        //    Lib.BuildString("This is the last antenna on '", dev.InfoFreq().ToString(),
                        //                    "' frequency.\nYou will lost connection in this frequency.\nDo you really want to remove this frequency from this vessel?"),
                        //    new DialogGUIButton("Remove", () => dev.ChangeFreq(+1)),
                        //    new DialogGUIButton("Keep it", () => { }));
                        //}
                        //else
                        dev.ChangeFreq(+1);
                    }
                });
            }

            p.SetSection("FREQUENCY(S) DETAIL");
            foreach (short key in vi.antenna.antennasByFreq.Keys)
            {
                double range = vi.antenna.antennasByFreq[key].antennaPower;
                double rate  = vi.antenna.antennasByFreq[key].antennaRate;

                Render_ConnectionDetail(p, range, rate, key);
            }
        }
Пример #30
0
        public void FixedUpdate()
        {
            // do nothing in the editor
            if (Lib.IsEditor())
            {
                return;
            }

            // if it has not malfunctioned
            if (!broken)
            {
                // calculate time of next failure if necessary
                if (next <= double.Epsilon)
                {
                    last = Planetarium.GetUniversalTime();
                    next = last + mtbf * (quality ? Settings.QualityScale : 1.0) * 2.0 * Lib.RandomDouble();
                }

                // if it has failed, trigger malfunction
                if (Planetarium.GetUniversalTime() > next)
                {
                    Break();
                }
            }
        }