Beispiel #1
0
        public override List <string> GetTestFlightInfo()
        {
            List <string> infoStrings = new List <string>();

            infoStrings.Add("<b>Engine Cycle</b>");
            infoStrings.Add(String.Format("<b>Rated Burn Time</b>: {0}", TestFlightUtil.FormatTime(ratedBurnTime, TestFlightUtil.TIMEFORMAT.SHORT_IDENTIFIER, true)));
            if (idleDecayRate > 0)
            {
                infoStrings.Add(String.Format("Cooling. Burn time decays {0:F2} per sec second engine is off", idleDecayRate));
            }
            float minThrust, maxThrust;

            thrustModifier.FindMinMaxValue(out minThrust, out maxThrust);
            if (minThrust != maxThrust)
            {
                infoStrings.Add(String.Format("Engine thrust affects burn time"));
                infoStrings.Add(String.Format("<b>Min Thrust/b> {0:F2}kn, {1:F2}x", thrustModifier.minTime, minThrust));
                infoStrings.Add(String.Format("<b>Max Thrust/b> {0:F2}kn, {1:F2}x", thrustModifier.maxTime, maxThrust));
            }
            return(infoStrings);
        }
Beispiel #2
0
        protected void UpdateCycle()
        {
            double currentTime = Planetarium.GetUniversalTime();
            double deltaTime   = (currentTime - previousOperatingTime) / 1d;

//            Log(String.Format("TestFlightReliability_EngineCycle: previous time: {0:F4}, current time: {1:F4}, delta time: {2:F4}", previousOperatingTime, currentTime, deltaTime));
            if (deltaTime >= 1d)
            {
                previousOperatingTime = currentTime;
                // Is our engine running?
                if (!core.IsPartOperating())
                {
                    // If not then we optionally cool down the engine, which decresses the burn time used
                    engineOperatingTime = Math.Max(engineOperatingTime - (idleDecayRate * deltaTime), 0d);
                }
                else
                {
                    // If so then we add burn time based on time passed, optionally modified by the thrust
                    float actualThrustModifier = thrustModifier.Evaluate(engine.finalThrust);
                    if (verboseDebugging)
                    {
                        Log(String.Format("TestFlightReliability_EngineCycle: Engine Thrust {0:F4}", engine.finalThrust));
                        Log(String.Format("TestFlightReliability_EngineCycle: delta time: {0:F4}, operating time :{1:F4}, thrustModifier: {2:F4}", deltaTime, engineOperatingTime, actualThrustModifier));
                    }
                    engineOperatingTime = engineOperatingTime + (deltaTime * actualThrustModifier);

                    // Check for failure
                    float minValue, maxValue = -1f;
                    cycle.FindMinMaxValue(out minValue, out maxValue);
                    float penalty = cycle.Evaluate((float)engineOperatingTime);
                    if (verboseDebugging)
                    {
                        Log(String.Format("TestFlightReliability_EngineCycle: Cycle Curve, Min Value {0:F2}:{1:F6}, Max Value {2:F2}:{3:F6}", cycle.minTime, minValue, cycle.maxTime, maxValue));
                        Log(String.Format("TestFlightReliability_EngineCycle: Applying modifier {0:F4} at cycle time {1:F4}", penalty, engineOperatingTime));
                    }
                    core.SetTriggerMomentaryFailureModifier("EngineCycle", penalty, this);
                }
            }
        }
Beispiel #3
0
        public override string GetInfo()
        {
            if (wheelRef == null)
            {
                return("");
            }

            if (HighLogic.LoadedSceneIsEditor && string.IsNullOrEmpty(info))
            {
                saturationLimit = (wheelRef.PitchTorque + wheelRef.YawTorque + wheelRef.RollTorque) * saturationScale / 3;

                // Base info
                info = string.Format("<b>Pitch Torque:</b> {0:F1} kNm\r\n<b>Yaw Torque:</b> {1:F1} kNm\r\n<b>Roll Torque:</b> {2:F1} kNm\r\n\r\n<b>Capacity:</b> {3:F1} kNms",
                                     wheelRef.PitchTorque, wheelRef.YawTorque, wheelRef.RollTorque, saturationLimit);

                // display min/max bleed rate if there is a difference, otherwise just one value
                float min, max;
                bleedRate.FindMinMaxValue(out min, out max);
                if (min == max)
                {
                    info += string.Format("\r\n<b>Bleed Rate:</b> {0:F1}%", max * 100);
                }
                else
                {
                    info += string.Format("\r\n<b>Bleed Rate:\r\n\tMin:</b> {0:0.#%}\r\n\t<b>Max:</b> {1:0.#%}", min, max);
                }

                // resource consumption
                info += "\r\n\r\n<b><color=#99ff00ff>Requires:</color></b>";
                //foreach (ModuleResource res in wheelRef.GetConsumedResources())
                //{
                //    if (res.rate <= 1)
                //        info += string.Format("\r\n - <b>{0}:</b> {1:F1} /min", res.name, res.rate * 60);
                //    else
                //        info += string.Format("\r\n - <b>{0}:</b> {1:F1} /s", res.name, res.rate);
                //}
            }
            return(info);
        }
Beispiel #4
0
        public override void OnUpdate()
        {
            if (!TestFlightEnabled)
            {
                return;
            }

            // For each engine we are tracking, compare its current ignition state to our last known ignition state
            for (int i = 0; i < engines.Count; i++)
            {
                EngineHandler engine = engines[i];
                EngineModuleWrapper.EngineIgnitionState currentIgnitionState = engine.engine.IgnitionState;
                // If we are transitioning from not ignited to ignited, we do our check
                // The ignitionFailureRate defines the failure rate per flight data

                if (currentIgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED)
                {
                    if (engine.ignitionState == EngineModuleWrapper.EngineIgnitionState.NOT_IGNITED || engine.ignitionState == EngineModuleWrapper.EngineIgnitionState.UNKNOWN)
                    {
                        double failureRoll = 0d;
                        if (verboseDebugging)
                        {
                            Log(String.Format("IgnitionFail: Engine {0} transitioning to INGITED state", engine.engine.Module.GetInstanceID()));
                            Log(String.Format("IgnitionFail: Checking curves..."));
                        }
                        numIgnitions++;

                        double initialFlightData = core.GetInitialFlightData();
                        float  ignitionChance    = 1f;
                        float  multiplier        = 1f;

                        // Check to see if the vessel has not launched and if the player disabled pad failures
                        if (this.vessel.situation == Vessel.Situations.PRELAUNCH && !preLaunchFailures)
                        {
                            ignitionChance = 1.0f;
                        }
                        else
                        {
                            ignitionChance = baseIgnitionChance.Evaluate((float)initialFlightData);
                            if (ignitionChance <= 0)
                            {
                                ignitionChance = 1f;
                            }
                        }

                        if (dynPressurePenalties)
                        {
                            multiplier = pressureCurve.Evaluate((float)(part.dynamicPressurekPa * 1000d));
                            if (multiplier <= 0f)
                            {
                                multiplier = 1f;
                            }
                        }

                        float minValue, maxValue = -1f;
                        baseIgnitionChance.FindMinMaxValue(out minValue, out maxValue);
                        if (verboseDebugging)
                        {
                            Log(String.Format("TestFlightFailure_IgnitionFail: IgnitionChance Curve, Min Value {0:F2}:{1:F6}, Max Value {2:F2}:{3:F6}", baseIgnitionChance.minTime, minValue, baseIgnitionChance.maxTime, maxValue));
                        }

                        if (this.vessel.situation != Vessel.Situations.PRELAUNCH)
                        {
                            ignitionChance = ignitionChance * multiplier * ignitionUseMultiplier.Evaluate(numIgnitions);
                        }

                        failureRoll = core.RandomGenerator.NextDouble();
                        if (verboseDebugging)
                        {
                            Log(String.Format("IgnitionFail: Engine {0} ignition chance {1:F4}, roll {2:F4}", engine.engine.Module.GetInstanceID(), ignitionChance, failureRoll));
                        }
                        if (failureRoll > ignitionChance)
                        {
                            engine.failEngine = true;
                            core.TriggerNamedFailure("TestFlightFailure_IgnitionFail");
                            failureRoll = core.RandomGenerator.NextDouble();
                            if (failureRoll < additionalFailureChance)
                            {
                                core.TriggerFailure();
                            }
                        }
                    }
                }
                engine.ignitionState = currentIgnitionState;
            }
        }
        /// <summary>
        /// Load the engine config
        /// </summary>
        /// <param name="node">The config node to load from</param>
        public void Load(ConfigNode node)
        {
            if (node.name.Equals("MODE"))
            {
                ConfigNode.LoadObjectFromConfig(this, node);

                //load the propellants
                ConfigNode[] propellantNodes = node.GetNodes("PROPELLANT");
                propellants = new List <Propellant>();
                for (int i = 0; i < propellantNodes.Length; i++)
                {
                    Propellant p = new Propellant();
                    p.Load(propellantNodes[i]);
                    propellants.Add(p);
                }

                //load the name of the mode
                if (node.HasValue("name"))
                {
                    name = node.GetValue("name");
                }

                //load the curve for atmosphere ISP or Thrust
                if (node.HasNode("atmosphereISPCurve"))
                {
                    atmosphereISPCurve = new FloatCurve();
                    atmosphereISPCurve.Load(node.GetNode("atmosphereISPCurve"));

                    float tmpMin;
                    atmosphereISPCurve.FindMinMaxValue(out tmpMin, out maxISP);
                }
                else if (node.HasNode("atmosphereThrustCurve"))
                {
                    atmosphereThrustCurve = new FloatCurve();
                    atmosphereThrustCurve.Load(node.GetNode("atmosphereThrustCurve"));
                }
                else
                {
                    atmosphereISPCurve = new FloatCurve();
                    atmosphereISPCurve.Add(0, 0);
                    atmosphereISPCurve.Add(1, 100);
                    maxISP = 100;
                }

                //load the consumption curve
                if (node.HasNode("consumptionCurve"))
                {
                    consumptionCurve = new FloatCurve();
                    consumptionCurve.Load(node.GetNode("consumptionCurve"));
                }

                //load the velocity curve
                if (node.HasNode("velocityCurve"))
                {
                    velocityCurve = new FloatCurve();
                    velocityCurve.Load(node.GetNode("velocityCurve"));
                }

                //wheter the engine needs an atmosphere to work
                if (node.HasValue("needsAtmosphere"))
                {
                    needsAtmosphere = bool.Parse(node.GetValue("needsAtmosphere"));
                }

                //wheter the engine needs oxygen to operate
                if (node.HasValue("needsOxygen"))
                {
                    needsOxygen = bool.Parse(node.GetValue("needsOxygen"));
                }

                //wheter the engine needs to be in water to operate
                if (node.HasValue("needsWater"))
                {
                    needsWater = bool.Parse(node.GetValue("needsWater"));
                }

                //wheter the engine needs to be in water to operate
                if (node.HasValue("maxThrust"))
                {
                    try
                    {
                        maxThrust = float.Parse(node.GetValue("maxThrust"));
                    }
                    catch (Exception e)
                    {
                        maxThrust = 0;
                        Debug.LogError("[LYNX] Cannot load maxThrust for engine: " + e.Message);
                    }
                }

                //wheter the engine needs to be in water to operate
                if (node.HasValue("flameoutThreshold"))
                {
                    try
                    {
                        flameoutThreshold = float.Parse(node.GetValue("flameoutThreshold"));
                    }
                    catch (Exception e)
                    {
                        flameoutThreshold = 0.1f;
                        Debug.LogError("[LYNX] Cannot load flameoutThreshold for engine: " + e.Message);
                    }
                }

                //calculate the fuel flow modifier
                if (atmosphereISPCurve != null)
                {
                    float fuelDensity = 0.0f;
                    for (int i = 0; i < propellants.Count; i++)
                    {
                        fuelDensity += PartResourceLibrary.Instance.resourceDefinitions[propellants[i].name].density;
                    }

                    fuelFlow = (fuelDensity > 0.0f) ? maxThrust / (9.80665f * maxISP * fuelDensity) : 1;
                }
                else
                {
                    fuelFlow = 1.0f;
                }
            }
        }