Ejemplo n.º 1
0
        void UpdateCurve()
        {
            points.Sort();

            curve = new FloatCurve();

            float minY = float.MaxValue;
            float maxY = float.MinValue;

            foreach (FloatString4 v in points)
            {
                curve.Add(v.floats.x, v.floats.y, v.floats.z, v.floats.w);
            }

            textVersion = CurveToString();

            for (int x = 0; x < texWidth; x++)
            {
                for (int y = 0; y < texHeight; y++)
                {
                    graph.SetPixel(x, y, Color.black);
                }
                float fY = curve.Evaluate(curve.minTime + curve.maxTime * (float)x / (float)(texWidth - 1));
                minY = Mathf.Min(minY, fY);
                maxY = Mathf.Max(maxY, fY);
            }
            for (int x = 0; x < texWidth; x++)
            {
                float fY = curve.Evaluate(curve.minTime + curve.maxTime * (float)x / (float)(texWidth - 1));
                graph.SetPixel(x, Mathf.RoundToInt((fY - minY) / (maxY - minY) * (texHeight - 1)), Color.green);
            }
            graph.Apply();
            curveNeedsUpdate = false;
        }
Ejemplo n.º 2
0
        public List <Color> Get(List <float> strengthList)
        {
            List <Color> colorList = new List <Color>();

            if (strengthList.Count > 1)
            {
                for (int i = 0; i < l.Length; i++)
                {
                    colorList.Add(
                        new Color(
                            rCurve.Evaluate(strengthList[i]) + randomValue,
                            gCurve.Evaluate(strengthList[i]) + randomValue,
                            bCurve.Evaluate(strengthList[i]) + randomValue,
                            aCurve.Evaluate(strengthList[i]) + randomValue));
                }
            }
            else
            {
                for (int i = 0; i < l.Length; i++)
                {
                    colorList.Add(
                        new Color(
                            rCurve.Evaluate(strengthList[0]) + randomValue,
                            gCurve.Evaluate(strengthList[0]) + randomValue,
                            bCurve.Evaluate(strengthList[0]) + randomValue,
                            aCurve.Evaluate(strengthList[0]) + randomValue));
                }
            }
            return(colorList);
        }
        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
                    Log(String.Format("TestFlightReliability_EngineCycle: Engine Thrust {0:F4}", engine.finalThrust));
                    float actualThrustModifier = thrustModifier.Evaluate(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);
                    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));
                    float penalty = cycle.Evaluate((float)engineOperatingTime);
                    Log(String.Format("TestFlightReliability_EngineCycle: Applying modifier {0:F4} at cycle time {1:F4}", penalty, engineOperatingTime));
                    core.SetTriggerMomentaryFailureModifier("EngineCycle", penalty, this);
                }
            }
        }
Ejemplo n.º 4
0
        public override void OnStart(StartState state)
        {
            ((UI_ScaleEdit)Fields["SelectedISP"].uiControlEditor).intervals[0]      = atmosphereCurve.Evaluate(0);
            ((UI_ScaleEdit)Fields["SelectedISP"].uiControlEditor).intervals[1]      = MaxVariableISP;
            ((UI_ScaleEdit)Fields["SelectedISP"].uiControlEditor).incrementSlide[0] = VariableIspStep;

            BaseMaxFuelflow     = maxFuelFlow;
            BaseAtmosphereCurve = atmosphereCurve;
            BaseMaxThrust       = maxThrust;

            float fuelMixtureDensity = 0;

            foreach (Propellant p in propellants)
            {
                PartResourceDefinition partResource = PartResourceLibrary.Instance.GetDefinition(p.id);
                fuelMixtureDensity += partResource.density * p.ratio;
            }
            //KSPLog.print("fuelMixtureDensity: " + fuelMixtureDensity);
            fuelRatioMultiplier = maxFuelFlow / fuelMixtureDensity;
            //KSPLog.print("fuelRatioMultiplier: " + fuelRatioMultiplier);

            ThrustIspToFuelFlowConstant = maxThrust / maxFuelFlow / BaseAtmosphereCurve.Evaluate(0);

            baseLfOIsp = BaseAtmosphereCurve.Evaluate(0);

            adjustEngineParams(SelectedISP);

            base.OnStart(state);
        }
Ejemplo n.º 5
0
        public List <Vector3> Get(List <float> strengthList)
        {
            List <Vector3> vectorList = new List <Vector3>();

            if (strengthList.Count > 1)
            {
                for (int i = 0; i < xforms.Count; i++)
                {
                    vectorList.Add(new Vector3(xCurve.Evaluate(strengthList[i]) + randomValue,
                                               yCurve.Evaluate(strengthList[i]) + randomValue,
                                               zCurve.Evaluate(strengthList[i]) + randomValue)

                                   );
                }
            }
            else
            {
                for (int i = 0; i < xforms.Count; i++)
                {
                    vectorList.Add(new Vector3(xCurve.Evaluate(strengthList[0]) + randomValue,
                                               yCurve.Evaluate(strengthList[0]) + randomValue,
                                               zCurve.Evaluate(strengthList[0]) + randomValue)

                                   );
                }
            }
            return(vectorList);
        }
Ejemplo n.º 6
0
        public override string GetModuleInfo(string configuration)
        {
            string infoString = "";

            foreach (var configNode in configs)
            {
                if (!configNode.HasValue("configuration"))
                {
                    continue;
                }

                var nodeConfiguration = configNode.GetValue("configuration");

                if (string.Equals(nodeConfiguration, configuration, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (configNode.HasNode("baseIgnitionChance"))
                    {
                        var nodeIgnitionChance = new FloatCurve();
                        nodeIgnitionChance.Load(configNode.GetNode("baseIgnitionChance"));

                        float pMin = nodeIgnitionChance.Evaluate(nodeIgnitionChance.minTime);
                        float pMax = nodeIgnitionChance.Evaluate(nodeIgnitionChance.maxTime);
                        infoString = $"  Ignition at 0 data: <color=#b1cc00ff>{pMin:P1}</color>\n  Ignition at max data: <color=#b1cc00ff>{pMax:P1}</color>";
                    }
                }
            }

            return(infoString);
        }
        public void Update()
        {
            if (FlightGlobals.ready)
            {
                if (trans != null && ((field != null) || (property != null)))
                {
                    object target = part;

                    if (module != null)
                    {
                        target = module;
                    }

                    float index = trans.gameObject.activeSelf ? 0 : 1;

                    if (field != null)
                    {
                        field.SetValue(target, valueCurve.Evaluate(index));
                    }
                    else
                    {
                        property.SetValue(target, valueCurve.Evaluate(index), null);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// The available torque for a given vessel axis and torque based on the momentum stored in world space.
        /// </summary>

        float CalcAvailableTorque(Vector3 refAxis, float maxAxisTorque)
        {
            var torqueVec = new Vector3(Vector3.Dot(refAxis, Planetarium.forward), Vector3.Dot(refAxis, Planetarium.up), Vector3.Dot(refAxis, Planetarium.right));

            // Smallest ratio is the scaling factor so set them huge as a default.

            float ratiox = 1000000, ratioy = 1000000, ratioz = 1000000;

            if (Math.Abs(torqueVec.x) > double.Epsilon)
            {
                ratiox = Mathf.Abs(torqueCurve.Evaluate(PctSaturation(x_Moment, saturationLimit)) / torqueVec.x);
            }

            if (Math.Abs(torqueVec.y) > double.Epsilon)
            {
                ratioy = Mathf.Abs(torqueCurve.Evaluate(PctSaturation(y_Moment, saturationLimit)) / torqueVec.y);
            }

            if (Math.Abs(torqueVec.z) > double.Epsilon)
            {
                ratioz = Mathf.Abs(torqueCurve.Evaluate(PctSaturation(z_Moment, saturationLimit)) / torqueVec.z);
            }

            return(torqueVec.magnitude * Mathf.Min(ratiox, ratioy, ratioz, 1) * maxAxisTorque);
        }
        protected void SetState(bool newState, bool snapTo)
        {
            if (targetRenderers != null)
            {
                if (newState)
                {
                    animationGoal = 1f;
                    if (snapTo)
                    {
                        animationFraction = 1f;
                    }
                }
                else
                {
                    animationGoal = 0f;
                    if (snapTo)
                    {
                        animationFraction = 0f;
                    }
                }

                Color c = new Color(redCurve.Evaluate(animationFraction) * colorScale, greenCurve.Evaluate(animationFraction) * colorScale, blueCurve.Evaluate(animationFraction) * colorScale, alphaCurve.Evaluate(animationFraction) * colorScale);

                foreach (Renderer r in targetRenderers)
                {
                    r.material.SetColor(shaderProperty, c);
                }
            }
        }
Ejemplo n.º 10
0
        void Trim(List <double[]> list, double topLayer)
        {
            FloatCurve curve = new FloatCurve();

            curve.Load(WriteCurve(list));

            double[] lastKey = { topLayer, curve.Evaluate((float)topLayer) };

            for (int i = list.Count; i > 0; i--)
            {
                if (list[i - 2][0] < topLayer)
                {
                    double dX      = 0.01 * (lastKey[0] - list[i - 2][0]);
                    double dY      = lastKey[1] - curve.Evaluate((float)(lastKey[0] - dX));
                    double tangent = dY / dX;

                    list.RemoveAt(i - 1);

                    list.Add(new double[] { lastKey[0], lastKey[1], tangent, tangent });
                    break;
                }
                else
                {
                    list.RemoveAt(i - 1);
                }
            }

            // Debug
            PrintCurve(list, "Trim");
        }
Ejemplo n.º 11
0
        public void Update()
        {
            if (FlightGlobals.ready)
            {
                if ((anims != null) && (anims.Length > 0) && ((field != null) || (property != null)))
                {
                    object target = part;

                    if (module != null)
                    {
                        target = module;
                    }

                    currentTime = anims[0][animationName].normalizedTime;

                    // Workaround hack for Firespitter FSwheel issue.
                    // Corrects a problem where non-playing animation time is always 0.
                    if (fswHack && (string)fswType.GetField("deploymentState").GetValue(FSwheel) == "Retracted")
                    {
                        // Retracted wheel should always be time index 1
                        currentTime = 1f;
                    }


                    if (field != null)
                    {
                        field.SetValue(target, valueCurve.Evaluate(currentTime));
                    }
                    else
                    {
                        property.SetValue(target, valueCurve.Evaluate(currentTime), null);
                    }
                }
            }
        }
Ejemplo n.º 12
0
        protected override void ApplyReplace(List <float> strengthList)
        {
            float strength = strengthList[0];

            for (int i = 0; i < xforms.Count; i++)
            {
                xforms[i].localPosition = new Vector3(xCurve.Evaluate(strength) + randomValue, yCurve.Evaluate(strength) + randomValue, zCurve.Evaluate(strength) + randomValue);
            }
        }
Ejemplo n.º 13
0
        public override string GetInfo()
        {
            string msg = Localizer.Format("#LOC_FFT_ModuleMultiRatioEngine_PartInfo",
                                          (IspCurve.Evaluate(0f) * IspCurveScale.Evaluate(IspCurve.maxTime * RatioScale)).ToString("F2"),
                                          (IspCurve.Evaluate(0f) * IspCurveScale.Evaluate(IspCurve.minTime * RatioScale)).ToString("F2"),
                                          ThrustCurve.Evaluate(IspCurve.maxTime * RatioScale).ToString("F2"),
                                          ThrustCurve.Evaluate(IspCurve.minTime * RatioScale).ToString("F2"));

            return(msg);
        }
Ejemplo n.º 14
0
 public override string GetInfo()
 {
     try {
         double start = reliabilityCurve.Evaluate(0f) * ratedBurnTime;
         double end   = reliabilityCurve.Evaluate((float)maxData) * ratedBurnTime;
         return(String.Format("{0}: rated {1}s\n{2:P1} at 0du\n{3:P1} at {4}du", configuration, ratedBurnTime, 1d - start, 1d - end, maxData));
     } catch (Exception exc) {
         Logging.LogException(exc);
         return("Erk.");
     }
 }
Ejemplo n.º 15
0
 protected void GenerateHeatEditor()
 {
     if (editorThermalSim)
     {
         heatModule.AddFlux(moduleID, systemOutletTemperature, systemPower.Evaluate(systemOutletTemperature));
     }
     else
     {
         heatModule.AddFlux(moduleID, 0f, 0f);
     }
 }
Ejemplo n.º 16
0
        public override string GetInfo()
        {
            RBlog("RealBattery: INF GetInfo");

            LoadConfig();

            double DischargeRate = part.mass * PowerDensity;

            return("Type: " + RealBatteryConfiguration.getBatteryTypesFriendlyName((BatteryTypes)BatteryType) + "\n"
                   + String.Format("Discharge Rate: {0:F2} EC/s", DischargeRate) + "\n"
                   + String.Format("Charge Rate: {0:F2} EC/s", DischargeRate * ChargeEfficiencyCurve.Evaluate(0f)));
        }
Ejemplo n.º 17
0
        public override string GetInfo()
        {
            string msg = Localizer.Format("#LOC_SystemHeat_ModuleSystemHeatExchanger_UIGroup_Title",
                                          0f.ToString("F0"), temperatureDeltaCostCurve.Evaluate(0f).ToString("F0"),
                                          1000f.ToString("F0"), temperatureDeltaCostCurve.Evaluate(1000f).ToString("F0"),
                                          temperatureDeltaHeatCurve.Evaluate(0).ToString("F0"),
                                          temperatureDeltaHeatCurve.Evaluate(1000f).ToString("F0")

                                          );

            return(msg);
        }
        public static Texture2D GenerateCurveTexture(int texWidth, int texHeight, FloatCurve curve, Color curveColor)
        {
            var   tex  = new Texture2D(texWidth, texHeight, TextureFormat.ARGB32, false, true);
            float minY = Single.MaxValue;
            float maxY = Single.MinValue;

            //textVersion = CurveToString();
            var bgColor      = new Color(.39f, .39f, .39f, 1f);
            var lineColor    = new Color(.33f, .33f, .33f, 1f);
            var outsideColor = new Color(.16f, .16f, .16f, 1f);

            for (int x = 0; x < texWidth; x++)
            {
                for (int y = 0; y < texHeight; y++)
                {
                    tex.SetPixel(x, y, bgColor);
                    if (y == 0 || y == texHeight - 1)
                    {
                        tex.SetPixel(x, y, outsideColor);
                    }
                }

                if (x == 0 || x == texWidth - 1)
                {
                    for (int y = 0; y < texHeight; y++)
                    {
                        tex.SetPixel(x, y, outsideColor);
                    }
                }

                float fY = curve.Evaluate(curve.minTime + curve.maxTime * x / (texWidth - 1));
                minY = Mathf.Min(minY, fY);
                maxY = Mathf.Max(maxY, fY);
            }

            for (int x = 0; x < texWidth; x++)
            {
                float step = texHeight / (float)4;
                for (int y = 0; y < 4; y++)
                {
                    tex.SetPixel(x, Mathf.RoundToInt(y * step), lineColor);
                }
            }

            for (int x = 1; x < texWidth - 1; x++)
            {
                float fY = curve.Evaluate(curve.minTime + curve.maxTime * x / (texWidth - 1));
                tex.SetPixel(x, Mathf.RoundToInt((fY - minY) / (maxY - minY) * (texHeight - 1)), curveColor);
            }

            tex.Apply();
            return(tex);
        }
        public override string GetInfo()
        {
            string msg = Localizer.Format("#LOC_SystemHeat_ModuleSystemHeatTemperatureAdjuster_PartInfo",
                                          0f.ToString("F0"), temperatureDeltaCostCurve.Evaluate(0f).ToString("F0"),
                                          1000f.ToString("F0"), temperatureDeltaCostCurve.Evaluate(1000f).ToString("F0"),
                                          temperatureDeltaHeatCurve.Evaluate(0).ToString("F0"),
                                          temperatureDeltaHeatCurve.Evaluate(1000f).ToString("F0")

                                          );

            return(msg);
        }
Ejemplo n.º 20
0
 public override string GetInfo()
 {
     try {
         double start  = reliabilityCurve.Evaluate(0f) * ratedBurnTime;
         double end    = reliabilityCurve.Evaluate((float)maxData) * ratedBurnTime;
         double istart = ignitionCurve.Evaluate(0f);
         double iend   = ignitionCurve.Evaluate((float)maxData);
         return(String.Format("{0}: rated {1}s\ncycle {2:P1} -> {3:P1}\nignition {4:P1} -> {5:P1}", configuration, ratedBurnTime, 1d - start, 1d - end, istart, iend));
     } catch (Exception exc) {
         Logging.LogException(exc);
         return("Erk.");
     }
 }
Ejemplo n.º 21
0
        // Radiative calculations
        public static float CalculateSolarInput(Vessel vessel)
        {
            // Divide by 1000000 for MW
            float baseIrradiance = solarCurve.Evaluate(GetSolarAltitude(vessel)) / 1000000f;

            if (InAtmosphere(vessel))
            {
                return(baseIrradiance * Mathf.Exp(-AtmosphericPathLength(vessel) * aerosolOpticalDepth));
            }
            else
            {
                return(baseIrradiance);
            }
        }
Ejemplo n.º 22
0
        virtual public Vector3 GetLift(Vector3 velocityVect, float mach)
        {
            float   dot    = Vector3.Dot(velocityVect, liftVector);
            float   absdot = omnidirectional ? Math.Abs(dot) : Mathf.Clamp01(dot);
            Vector3 lift   = Vector3.zero;

            lock (this.liftCurve)
                lift = -liftVector *Math.Sign(dot) * liftCurve.Evaluate(absdot) * liftMachCurve.Evaluate(mach) * deflectionLiftCoeff * PhysicsGlobals.LiftMultiplier;
            if (perpendicularOnly)
            {
                lift = Vector3.ProjectOnPlane(lift, -velocityVect);
            }
            return(lift * 1000);
        }
Ejemplo n.º 23
0
 public void SetConsumptionRates(float throttle, float atmospheres)
 {
     if (isEngine)
     {
         float Isp          = ispCurve.Evaluate(atmospheres);
         float massFlowRate = throttle * maxThrust / (Isp * g);
         if (correctThrust)
         {
             massFlowRate = massFlowRate * Isp / ispCurve.Evaluate(0);                // scale thrust
         }
         //propellant consumption rate = ratio * massFlowRate / sum(ratio * density)
         resourceConsumptions = propellantRatios.Keys.ToDictionary(id => id, id => propellantRatios[id] * massFlowRate / propellantSumRatioTimesDensity);
     }
 }
Ejemplo n.º 24
0
        private void UpdateTurbine()
        {
            float localWindSpeed = (float)(vessel.atmDensity * windSpeedMult) * efficiencyAngle;

            switch (deployState)
            {
            case DeployState.EXTENDED:
                if (isActive)
                {
                    if (localWindSpeed < minWindSpeed)
                    {
                        statusDisplay   = $"Too little wind to generate power!";
                        efficiencyCurve = efficiencyAngle = turbineSpeed = 0.0f;
                        break;
                    }

                    turbineSpeed    = Math.Abs(Mathf.Lerp(turbineSpeed, localWindSpeed, TimeWarp.fixedDeltaTime * spoolUpTime));
                    efficiencyCurve = turbineSpeed / (float)vessel.atmDensity * atmEfficiencyCurve.Evaluate((float)vessel.atmDensity);
                    turbinePivot.Rotate(turbinePivotAxis * (TimeWarp.fixedDeltaTime * SPEEDCONST) * turbineSpeed * turbineSpeedMult, Space.Self);

                    statusDisplay = $"Generating Power...";

                    Debug.Log($"{turbineSpeed}");

                    if (turbineSpeed > maxWindTolerance)
                    {
                        Destroy();
                        ScreenMessage("orange", "Turbine destroyed by excessive wind speed");
                    }
                }
                else
                {
                    turbineSpeed    = Mathf.Lerp(turbineSpeed, 0, TimeWarp.fixedDeltaTime * spoolUpTime);
                    efficiencyCurve = turbineSpeed / (float)vessel.atmDensity * atmEfficiencyCurve.Evaluate((float)vessel.atmDensity);
                    turbinePivot.Rotate(turbinePivotAxis * (TimeWarp.fixedDeltaTime * SPEEDCONST) * turbineSpeed * turbineSpeedMult, Space.Self);

                    if (turbineSpeed < 0.01)
                    {
                        statusDisplay = $"Idling - Not generating power";
                    }
                }
                break;

            case DeployState.RETRACTING:
                turbineSpeed    = Mathf.Lerp(turbineSpeed, 0, (1f - anim[animationName].normalizedTime) * TimeWarp.fixedDeltaTime);
                efficiencyCurve = turbineSpeed / (float)vessel.atmDensity * atmEfficiencyCurve.Evaluate((float)vessel.atmDensity);
                turbinePivot.Rotate(turbinePivotAxis * (TimeWarp.fixedDeltaTime * SPEEDCONST) * turbineSpeed * turbineSpeedMult, Space.Self);
                break;
            }
        }
Ejemplo n.º 25
0
        protected virtual void updateMotor()
        {
            float fI = part.vessel.ctrlState.wheelThrottle + part.vessel.ctrlState.wheelThrottleTrim;

            if (motorLocked)
            {
                fI = 0;
            }
            if (invertMotor)
            {
                fI = -fI;
            }
            if (tankSteering && !steeringLocked && !motorLocked)
            {
                float rI = -(part.vessel.ctrlState.wheelSteer + part.vessel.ctrlState.wheelSteerTrim);
                if (invertSteering)
                {
                    rI = -rI;
                }
                if (halfTrackSteering)
                {
                    bool spinningBackwards = false;
                    if ((fI < 0 && !invertMotor) || (fI > 0 && invertMotor) || spinningBackwards)
                    {
                        rI = -rI;
                    }
                }
                if (Mathf.Sign(wheel.rpm) != Mathf.Sign(rI) && rI != 0)//if rI is commanding the wheel to slow down, also apply brakes, inversely proportional to
                {
                    wheel.brakeTorque += (1 - torqueCurve.Evaluate(Mathf.Abs(wheel.rpm * gearRatio) / scaledMaxRPM)) * scaledMaxTorque * Mathf.Abs(rI);
                }
                fI += rI;
            }
            fI  = Mathf.Clamp(fI, -1, 1);
            fI *= motorOutput * 0.01f;//motor limiting...
            float motorRPM = wheel.rpm * gearRatio;

            //integrateMotorEuler(fI, motorRPM);
            integrateMotorEulerSub(fI, motorRPM, 5);
            //integrateMotorRK4(fI, motorRPM, wheel.mass);

            motorCurRPM = Mathf.Abs(motorRPM);
            float torquePercent   = 1 - (motorCurRPM / scaledMaxRPM);
            float rawTorqueOutput = scaledMaxTorque * torquePercent;

            powerOutKW = motorCurRPM * rawTorqueOutput * rpmToRad;
            //powerInKW = guiResourceUse * powerConversion; // this is the -actual- input power, but we need the pre-integration input power for the given RPM to derive efficiency
            powerInKW = minInputPower + torquePercent * (peakInputPower - minInputPower); //the actual calcualted input power for the output torque
            powerEff  = (powerInKW <= 0 ? 0 : powerOutKW / powerInKW) * 100f;             //finally, the efficiency of the raw output and input power values
        }
Ejemplo n.º 26
0
        public float LensingGain(Vector3d origin, Vector3d destination)
        {
            Vector3d lensPosition = vessel.GetWorldPos3D();
            float    standoff     = Math.Min((float)Vector3d.Distance(origin, lensPosition), (float)Vector3d.Distance(destination, lensPosition));

            if (standoff < minStandoff)
            {
                return(1);
            }
            Vector3 lensToOrigin = (origin - lensPosition).normalized;
            Vector3 lensToDest   = (destination - lensPosition).normalized;
            Vector3 trip         = (destination - origin).normalized;
            float   angle        = (float)Vector3.Angle(lensToDest, lensToOrigin);

            angle = Mathf.Clamp(angle, -180, 180);
            float gainF = gain.Evaluate(angle);
            //float dot = Math.Max(Vector3.Dot(lensToOrigin, trip), Vector3.Dot(lensToDest, trip));
            float dot = Vector3.Dot(lensToDest, trip);

            gainF *= dot;
            if (standoff < standoffBubble)
            {
                gainF = Mathf.Lerp(1, gainF, Mathf.Pow(standoff / standoffBubble, 2));
            }
            return(gainF);
        }
Ejemplo n.º 27
0
        // MULTIPLIERS
        public double Thrust(TechLevel oldTL, bool constantMass = false)
        {
            if (oldTL.thrustMultiplier > 0 && thrustMultiplier > 0)
            {
                return(thrustMultiplier / oldTL.thrustMultiplier);
            }

            if (constantMass)
            {
                return(TWR / oldTL.TWR);
            }
            else
            {
                return(TWR / oldTL.TWR * oldTL.atmosphereCurve.Evaluate(0) / atmosphereCurve.Evaluate(0));
            }
        }
Ejemplo n.º 28
0
        public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, FloatCurve thrustCurve, float thrustCurveRatio, ref float maxMach, float flowMultCap, float flowMultCapSharp)
        {
            float flowModifier = 1.0f;

            if (atmChangeFlow)
            {
                flowModifier = (float)(atmDensity / 1.225);
                if (atmCurve != null)
                {
                    flowModifier = atmCurve.Evaluate(flowModifier);
                }
            }
            if (velCurve != null)
            {
                flowModifier = flowModifier * velCurve.Evaluate(machNumber);
                maxMach      = velCurve.maxTime;
            }
            if (thrustCurve != null)
            {
                flowModifier = flowModifier * thrustCurve.Evaluate(thrustCurveRatio);
            }
            if (flowModifier > flowMultCap)
            {
                flowModifier = flowMultCapSharp / ((flowMultCapSharp - 1) / flowMultCap + 1 / flowModifier);
            }
            if (flowModifier < 1E-05f)
            {
                flowModifier = float.Epsilon;
            }
            return(flowModifier);
        }
Ejemplo n.º 29
0
        public override float GetTargetAnimationState()
        {
            float state;

            if (multiMode == null || !multiMode.isOperational)
            {
                state = shutdownState;
            }
            else if (GetThrottleSetting() <= idleThreshold)
            {
                state = idleState;
            }
            else if (multiMode.runningPrimary)
            {
                state  = throttleCurvePrimary.Evaluate(GetThrottleSetting());
                state += machCurvePrimary.Evaluate(GetMachNumber());
            }
            else
            {
                state  = throttleCurveSecondary.Evaluate(GetThrottleSetting());
                state += machCurveSecondary.Evaluate(GetMachNumber());
            }

            state = Mathf.Clamp(state, 0f, 1f);

            return(state);
        }
Ejemplo n.º 30
0
        private static void updateGraphTexture()
        {
            updateFloatCurve();
            //clear texture to black
            Color[] pixelColors = new Color[graphWidth * graphHeight];
            for (int i = 0; i < pixelColors.Length; i++)
            {
                pixelColors[i] = Color.black;
            }
            texture.SetPixels(0, 0, graphWidth, graphHeight, pixelColors);

            //plot from the current float curve
            float fx, fy;
            int   px, py;

            for (int i = 0; i < graphWidth; i++)
            {
                px = graphWidth - 1 - i;                              //invert x-axis so it goes from 1 -> 0
                fx = ((float)i / (float)graphWidth);
                fy = curve.Evaluate(fx);                              //should be a 0-1 value
                py = Mathf.RoundToInt((float)(graphHeight - 1) * fy); //convert it to a pixel position relative to the size of the texture
                texture.SetPixel(px, py, Color.green);                //update the pixel color
            }
            texture.Apply();
        }
Ejemplo n.º 31
0
 public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach)
 {
     float flowModifier = 1.0f;
     if (atmChangeFlow)
     {
         flowModifier = (float)(atmDensity / 1.225);
         if (atmCurve != null)
         {
             flowModifier = atmCurve.Evaluate(flowModifier);
         }
     }
     if (velCurve != null)
     {
         flowModifier = flowModifier * velCurve.Evaluate(machNumber);
         maxMach = velCurve.maxTime;
     }
     if (flowModifier < float.Epsilon)
     {
         flowModifier = float.Epsilon;
     }
     return flowModifier;
 }
Ejemplo n.º 32
0
        /// <summary>
        /// This will return an image of the specified size with the thrust graph for this nozzle
        /// Totally jacked the image code from the wiki http://wiki.kerbalspaceprogram.com/wiki/Module_code_examples, with some modifications
        /// 
        /// 
        /// </summary>
        /// <param name="imgH">Hight of the desired output, in pixels</param>
        /// <param name="imgW">Width of the desired output, in pixels</param>
        /// <param name="burnTime">Chart for burn time in seconds</param>
        /// <returns></returns>
        public static Texture2D stackThrustPredictPic(int imgH, int imgW, int burnTime, FloatCurve atmoCurve, AdvSRBNozzle nozzle)
        {
            //First we set up the analyzer
            //Step 1: Figure out fuel sources
            nozzle.FuelStackSearcher(nozzle.FuelSourcesList);
            //Step 2: Set up mass variables
            float stackTotalMass = 0f;
            stackTotalMass = nozzle.fullStackFuelMass;

            float remStackFuel = nozzle.fullStackFuelMass;

            //stackTotalMass = CalcStackWetMass(FuelSourcesList, stackTotalMass);

            //float[] segmentFuelArray = new float[nozzle.FuelSourcesList.Count];

            int i = 0;
            //foreach (Part p in nozzle.FuelSourcesList)
            //{
            //    segmentFuelArray[i] = p.GetResourceMass();
            //    i++;
            //}

            //float stackCurrentMass = stackTotalMass;
            //Now we set up the image maker
            Texture2D image = new Texture2D(imgW, imgH);
            int graphXmin = 19;
            int graphXmax = imgW - 20;
            int graphYmin = 19;
            //Step 3: Set Up color variables
            Color brightG = Color.black;
            brightG.r = .3372549f;
            brightG.g = 1;
            Color mediumG = Color.black;
            mediumG.r = 0.16862745f;
            mediumG.g = .5f;
            Color lowG = Color.black;
            lowG.r = 0.042156863f;
            lowG.g = .125f;

            Color MassColor = Color.blue;
            Color ThrustColor = Color.cyan;
            Color ExtraThrustColor = Color.yellow;

            //Step 4: Define text arrays
            KSF_CharArrayUtils.populateCharArrays();
            //Step 5a: Define time markings (every 10 seconds gets a verticle line)
            System.Collections.Generic.List<int> timeLines = new System.Collections.Generic.List<int>();
            double xScale = (imgW - 40) / (double)burnTime;
            //print("xScale: " + xScale);
            calcTimeLines((float)burnTime, 10, timeLines, (float)xScale, 20);
            //Step 5b: Define vertical line markings (9 total to give 10 sections)
            System.Collections.Generic.List<int> horzLines = new System.Collections.Generic.List<int>();
            calcHorizLines(imgH - graphYmin, horzLines, 9, 20);
            //Step 6: Clear the background

            //Set all the pixels to black. If you don't do this the image contains random junk.
            for (int y = 0; y < image.height; y++)
            {
                for (int x = 0; x < image.width; x++)
                {
                    image.SetPixel(x, y, Color.black);
                }
            }

            //Step 7a: Draw Time Lines
            for (int y = 0; y < image.height; y++)
            {
                for (int x = 0; x < image.width; x++)
                {
                    if (timeLines.Contains(x) && y > graphYmin)
                        image.SetPixel(x, y, lowG);
                }
            }

            //Step 7b: Draw Vert Lines
            for (int y = 0; y < image.height; y++)
            {
                for (int x = 0; x < image.width; x++)
                {
                    if (horzLines.Contains(y) && x < graphXmax && x > graphXmin)
                        image.SetPixel(x, y, lowG);
                }
            }

            //Step 7c: Draw Bounding Lines
            for (int y = 0; y < image.height; y++)
            {
                for (int x = 0; x < image.width; x++)
                {
                    if ((x == graphXmin | x == graphXmax) && (y > graphYmin | y == graphYmin))
                        image.SetPixel(x, y, mediumG);

                    if (y == graphYmin && graphXmax > x && graphXmin < x)
                        image.SetPixel(x, y, mediumG);
                }
            }

            //Step 8a: Populate graphArray
            double simStep = .2;
            i = 0;
            //double peakThrustTime = 0;
            double peakThrustAmt = 0;

            //set up the array for the graphs
            int graphArraySize = Convert.ToInt16(Convert.ToDouble(burnTime) / simStep);
            double[,] graphArray = new double[graphArraySize, 4];

            //one time setups
            //graphArray[i, 0] = stackMassFlow(FuelSourcesList, (float)(i * simStep), segmentFuelArray, simStep);

            graphArray[i, 0] = nozzle.MassFlow.Evaluate((float)(i * simStep)) * nozzle.fullStackFuelMass;
            graphArray[i, 1] = stackTotalMass;
            graphArray[i, 2] = 9.80665 * atmoCurve.Evaluate(1) * graphArray[i, 0];
            graphArray[i, 3] = graphArray[i, 2] - (graphArray[i, 1] * 9.80665);

            remStackFuel -= (float)graphArray[i, 0];

            //fForce = 9.81f * fCurrentIsp * fFuelFlowMass / TimeWarp.fixedDeltaTime;
            do
            {
                i++;
                //
                //graphArray[i, 0] = stackMassFlow(FuelSourcesList, (float)(i * simStep), segmentFuelArray, simStep);

                graphArray[i, 0] = nozzle.MassFlow.Evaluate((float)(i * simStep)) * nozzle.fullStackFuelMass;

                graphArray[i, 1] = graphArray[i - 1, 1] - (graphArray[i - 1, 0] * simStep);

                if (remStackFuel > 0)
                    graphArray[i, 2] = 9.80665 * atmoCurve.Evaluate(1) * graphArray[i, 0];
                else
                    graphArray[i, 2] = 0;

                if (graphArray[i, 2] > 0)
                    graphArray[i, 3] = graphArray[i, 2] - (graphArray[i, 1] * 9.80665);
                else
                    graphArray[i, 3] = 0;

                if (graphArray[i, 2] > peakThrustAmt)
                {
                    peakThrustAmt = graphArray[i, 2];
                    //peakThrustTime = i;
                }

                remStackFuel -= (float)graphArray[i, 0] * (float)simStep;

                //print("generating params i=" + i + " peak at " + Convert.ToInt16(Convert.ToDouble(simDuration) / simStep));
            } while (i + 1 < graphArraySize);

            //Step 8b: Make scales for the y axis
            double yScaleMass = 1;
            double yScaleThrust = 1;
            int usableY;
            usableY = imgH - 20;

            yScaleMass = usableY / (Mathf.CeilToInt((float)(graphArray[0, 1] / 10)) * 10);
            float inter;
            inter = (float)peakThrustAmt / 100;
            //print("1: " + inter);
            inter = Mathf.CeilToInt(inter);
            //print("22: " + inter);
            inter = inter * 100;
            //print("3: " + inter);
            inter = usableY / inter;
            //print("4: " + inter);

            yScaleThrust = inter;

            //print(yScaleThrust + ":" + peakThrustAmt + ":" + usableY);

            Debug.Log("graphed scales");

            //Step 8c: Graph the mass
            int lineWidth = 3;
            for (int x = graphXmin; x < graphXmax; x++)
            {
                int fx = fGraph(xScale, x - 20, yScaleMass, graphArray, simStep, graphArraySize, 1, 20);

                for (int y = fx; y < fx + lineWidth; y++)
                {
                    image.SetPixel(x, y, MassColor);
                }
            }

            //Step 8d: Graph the thrust
            lineWidth = 3;
            for (int x = graphXmin; x < graphXmax; x++)
            {
                int fx = fGraph(xScale, x - 20, yScaleThrust, graphArray, simStep, graphArraySize, 2, 20);
                for (int y = fx; y < fx + lineWidth; y++)
                {
                    image.SetPixel(x, y, ThrustColor);
                }
            }

            //Step 8e: Graph the thrust extra
            lineWidth = 2;
            for (int x = graphXmin; x < graphXmax; x++)
            {
                int fx = fGraph(xScale, x - 20, yScaleThrust, graphArray, simStep, graphArraySize, 3, 20);
                for (int y = fx; y < fx + lineWidth; y++)
                {
                    image.SetPixel(x, y, ExtraThrustColor);
                }
            }

            //Step 9: Set up boxes for time

            //int i = 0;
            string s;
            i = 0;
            int length = 0;
            int pos = 0;
            int startpos = 0;
            Texture2D tex;

            do
            {
                s = "";

                pos = timeLines[i];
                i++;
                s = i * 10 + " s";

                //print("composite string: " + s);

                length = calcStringPixLength(KSF_CharArrayUtils.convertStringToCharArray(s));
                //print("length: " + length);

                startpos = Mathf.FloorToInt((float)pos - 0.5f * (float)length);

                Color[] region = image.GetPixels(startpos, 23, length, 11);

                for (int c = 0; c < region.Length; c++)
                {
                    region[c] = brightG;
                }

                image.SetPixels(startpos, 23, length, 11, region);

                tex = convertCharArrayToTex(KSF_CharArrayUtils.convertStringToCharArray(s), length, brightG);

                Color[] region2 = tex.GetPixels();

                image.SetPixels(startpos + 2, 25, length - 4, 7, region2);

                length = 0;

            } while (i < timeLines.Count);

            //set up boxes for horizontal lines, mass first
            startpos = 0;
            length = 0;
            pos = 0;
            i = 0;
            do
            {
                s = "";
                pos = horzLines[i];
                i++;
                s = ((Mathf.CeilToInt((float)(graphArray[0, 1] / 10)) * i)).ToString() + " t";
                length = calcStringPixLength(KSF_CharArrayUtils.convertStringToCharArray(s));
                startpos = Mathf.FloorToInt((float)pos - 5f);
                Color[] region = image.GetPixels(23, startpos, length, 11);
                for (int c = 0; c < region.Length; c++)
                {
                    region[c] = brightG;
                }
                image.SetPixels(23, startpos, length, 11, region);
                tex = convertCharArrayToTex(KSF_CharArrayUtils.convertStringToCharArray(s), length, brightG);
                Color[] region2 = tex.GetPixels();
                image.SetPixels(25, startpos + 2, length - 4, 7, region2);
                length = 0;
            } while (i < horzLines.Count);

            //set up boxes for horizontal lines,  thrust
            startpos = 0;
            length = 0;
            pos = 0;
            i = 0;
            do
            {
                s = "";
                pos = horzLines[i];
                i++;
                s = ((Mathf.CeilToInt((float)(peakThrustAmt / 100)) * (i * 10))).ToString() + " k";
                length = calcStringPixLength(KSF_CharArrayUtils.convertStringToCharArray(s));
                startpos = Mathf.FloorToInt((float)pos - 5f);
                Color[] region = image.GetPixels(imgW - 60, startpos, length, 11);
                for (int c = 0; c < region.Length; c++)
                {
                    region[c] = brightG;
                }
                image.SetPixels(imgW - 60, startpos, length, 11, region);
                tex = convertCharArrayToTex(KSF_CharArrayUtils.convertStringToCharArray(s), length, brightG);
                Color[] region2 = tex.GetPixels();
                image.SetPixels(imgW - 58, startpos + 2, length - 4, 7, region2);
                length = 0;
            } while (i < horzLines.Count);

            image.Apply();
            return image;
        }
Ejemplo n.º 33
0
        void Smooth(List<double[]> list, double smoothRange)
        {
            FloatCurve curve = new FloatCurve();
            curve.Load(WriteCurve(list));
            double topLayer = curve.maxTime;
            double smoothStart = topLayer - smoothRange;

            double[] newKey = { smoothStart, curve.Evaluate((float)smoothStart) };
            double[] lastKey = { topLayer, 0, 0, 0 };

            for (int i = list.Count; i > 0; i--)
            {
                if (list[i - 1][0] >= smoothStart)
                    list.RemoveAt(i - 1);
            }

            list.Add(newKey);
            list.Add(lastKey);

            // Debug
            PrintCurve(list, "Smooth");
        }
        public string GetConfigInfo(ConfigNode config)
        {
            TechLevel cTL = new TechLevel();
            if (!cTL.Load(config, techNodes, engineType, techLevel))
                cTL = null;

            string info = "   " + config.GetValue("name") + "\n";
            if (config.HasValue("description"))
                info += "    " + config.GetValue("description") + "\n";
            if (config.HasValue(thrustRating))
            {
                info += "    " + (scale * ThrustTL(config.GetValue(thrustRating), config)).ToString("G3") + " kN";
                // add throttling info if present
                if (config.HasValue("minThrust"))
                    info += ", min " + (float.Parse(config.GetValue("minThrust")) / float.Parse(config.GetValue(thrustRating)) * 100f).ToString("N0") + "%";
                else if (config.HasValue("throttle"))
                    info += ", min " + (float.Parse(config.GetValue("throttle")) * 100f).ToString("N0") + "%";
            }
            else
                info += "    Unknown Thrust";

            if (origMass > 0f)
            {
                float cMass = scale;
                float ftmp;
                if (config.HasValue("massMult"))
                    if (float.TryParse(config.GetValue("massMult"), out ftmp))
                        cMass *= ftmp;

                cMass = origMass * cMass * RFSettings.Instance.EngineMassMultiplier;

                info += ", " + cMass.ToString("N3") + "t";
            }
            info += "\n";

            FloatCurve isp = new FloatCurve();
            if (config.HasNode("atmosphereCurve"))
            {
                isp.Load(config.GetNode("atmosphereCurve"));
                info += "    Isp: "
                    + isp.Evaluate(isp.maxTime).ToString() + " - "
                      + isp.Evaluate(isp.minTime).ToString() + "s\n";
            }
            else if (config.HasValue("IspSL") && config.HasValue("IspV"))
            {
                float ispSL = 1.0f, ispV = 1.0f;
                float.TryParse(config.GetValue("IspSL"), out ispSL);
                float.TryParse(config.GetValue("IspV"), out ispV);
                if (cTL != null)
                {
                    ispSL *= ispSLMult * cTL.AtmosphereCurve.Evaluate(1);
                    ispV *= ispVMult * cTL.AtmosphereCurve.Evaluate(0);
                    info += "    Isp: " + ispSL.ToString("0") + " - " + ispV.ToString("0") + "s\n";
                }
            }
            float gimbalR = -1f;
            if (config.HasValue("gimbalRange"))
                gimbalR = float.Parse(config.GetValue("gimbalRange"));
            // Don't do per-TL checks here, they're misleading.
            /*else if (!gimbalTransform.Equals("") || useGimbalAnyway)
            {
                if (cTL != null)
                    gimbalR = cTL.GimbalRange;
            }*/
            if (gimbalR != -1f)
                info += "    Gimbal " + gimbalR.ToString("N1") + "d\n";

            if (config.HasValue("ullage") || config.HasValue("ignitions") || config.HasValue("pressureFed"))
            {
                info += "    ";
                bool comma = false;
                if (config.HasValue("ullage"))
                {
                    info += (config.GetValue("ullage").ToLower() == "true" ? "ullage" : "no ullage");
                    comma = true;
                }
                if (config.HasValue("pressureFed") && config.GetValue("pressureFed").ToLower() == "true")
                {
                    if (comma)
                        info += ", ";
                    info += "pfed";
                    comma = true;
                }

                if (config.HasValue("ignitions"))
                {
                    int ignitions;
                    if (int.TryParse(config.GetValue("ignitions"), out ignitions))
                    {
                        if (comma)
                            info += ", ";
                        if (ignitions > 0)
                            info += ignitions + " ignition" + (ignitions > 1 ? "s" : "");
                        else
                            info += "unl. ignitions";
                    }
                }
                info += "\n";
            }
            float cst;
            if (config.HasValue("cost") && float.TryParse(config.GetValue("cost"), out cst))
                info += "    (" + (scale * cst).ToString("N0") + " extra cost)\n"; // FIXME should get cost from TL, but this should be safe

            return info;
        }
Ejemplo n.º 35
0
        public override string GetInfo ()
        {
            if (configs.Count < 2)
                return TLTInfo();

            string info = TLTInfo() + "\nAlternate configurations:\n";

            TechLevel moduleTLInfo = new TechLevel();
            if (techNodes != null)
                moduleTLInfo.Load(techNodes, techLevel);
            else
                moduleTLInfo = null;

            foreach (ConfigNode config in configs) {
                if(!config.GetValue ("name").Equals (configuration)) {
                    info += "   " + config.GetValue ("name") + "\n";
                    if(config.HasValue (thrustRating))
                        info += "    (" + ThrustTL(config.GetValue (thrustRating), config).ToString("0.00") + " Thrust";
                    else
                        info += "    (Unknown Thrust";

                    FloatCurve isp = new FloatCurve();
                    if(config.HasNode ("atmosphereCurve")) {
                        isp.Load (config.GetNode ("atmosphereCurve"));
                        info  += ", "
                            + isp.Evaluate (isp.maxTime).ToString() + "-"
                              + isp.Evaluate (isp.minTime).ToString() + "Isp";
                    }
                    else if (config.HasValue("IspSL") && config.HasValue("IspV"))
                    {
                        float ispSL = 1.0f, ispV = 1.0f;
                        float.TryParse(config.GetValue("IspSL"), out ispSL);
                        float.TryParse(config.GetValue("IspV"), out ispV);
                        TechLevel cTL = new TechLevel();
                        if (cTL.Load(config, techNodes, engineType, techLevel))
                        {
                            ispSL *= ispSLMult * cTL.atmosphereCurve.Evaluate(1);
                            ispV *= ispVMult * cTL.atmosphereCurve.Evaluate(0);
                            info += ", " + ispSL.ToString("0") + "-" + ispV.ToString("0") + "Isp";
                        }
                    }
                    info += ")\n";
                }


            }
            return info;
        }
Ejemplo n.º 36
0
        public static EngineSim New(PartSim theEngine,
                         double atmosphere,
                         float machNumber,
                         float maxFuelFlow,
                         float minFuelFlow,
                         float thrustPercentage,
                         Vector3 vecThrust,
                         FloatCurve atmosphereCurve,
                         bool atmChangeFlow,
                         FloatCurve atmCurve,
                         FloatCurve velCurve,
                         float currentThrottle,
                         float IspG,
                         bool throttleLocked,
                         List<Propellant> propellants,
                         bool active,
                         float resultingThrust,
                         List<Transform> thrustTransforms,
                        LogMsg log)
        {
            EngineSim engineSim = pool.Borrow();

            engineSim.isp = 0.0;
            engineSim.maxMach = 0.0f;
            engineSim.actualThrust = 0.0;
            engineSim.partSim = theEngine;
            engineSim.isActive = active;
            engineSim.thrustVec = vecThrust;
            engineSim.resourceConsumptions.Reset();
            engineSim.resourceFlowModes.Reset();
            engineSim.appliedForces.Clear();

            double flowRate = 0.0;
            if (engineSim.partSim.hasVessel)
            {
                if (log != null) log.buf.AppendLine("hasVessel is true");

                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach);
                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0;
                if (log != null)
                {
                    log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                }

                if (throttleLocked)
                {
                    if (log != null) log.buf.AppendLine("throttleLocked is true, using thrust for flowRate");
                    flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                }
                else
                {
                    if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
                    {
                        if (log != null) log.buf.AppendLine("throttled up and not landed, using actualThrust for flowRate");
                        flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
                    }
                    else
                    {
                        if (log != null) log.buf.AppendLine("throttled down or landed, using thrust for flowRate");
                        flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                    }
                }
            }
            else
            {
                if (log != null) log.buf.AppendLine("hasVessel is false");
                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, ref engineSim.maxMach);
                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = 0d;
                if (log != null)
                {
                    log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
                    log.buf.AppendFormat("isp     = {0:g6}\n", engineSim.isp);
                    log.buf.AppendFormat("thrust  = {0:g6}\n", engineSim.thrust);
                    log.buf.AppendFormat("actual  = {0:g6}\n", engineSim.actualThrust);
                }

                if (log != null) log.buf.AppendLine("no vessel, using thrust for flowRate");
                flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
            }

            if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);

            float flowMass = 0f;
            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];
                if (!propellant.ignoreForIsp)
                    flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
            }

            if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);

            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];

                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                {
                    continue;
                }

                double consumptionRate = propellant.ratio * flowRate / flowMass;
                if (log != null) log.buf.AppendFormat(
                        "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
                        ResourceContainer.GetResourceName(propellant.id),
                        theEngine.name,
                        theEngine.partId,
                        consumptionRate);
                engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
                engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode());
            }

            double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
            for (int i = 0; i < thrustTransforms.Count; i++)
            {
                Transform thrustTransform = thrustTransforms[i];
                Vector3d direction = thrustTransform.forward.normalized;
                Vector3d position = thrustTransform.position;

                AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
                engineSim.appliedForces.Add(appliedForce);
            }

            return engineSim;
        }
Ejemplo n.º 37
0
        public EngineSim(PartSim theEngine,
                            double atmosphere,
                            double velocity,
                            float maxThrust,
                            float minThrust,
                            float thrustPercentage,
                            float requestedThrust,
                            Vector3 vecThrust,
                            float realIsp,
                            FloatCurve atmosphereCurve,
                            FloatCurve velocityCurve,
                            bool throttleLocked,
                            List<Propellant> propellants,
                            bool active,
                            bool correctThrust)
        {
            StringBuilder buffer = null;
            //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
            //MonoBehaviour.print("maxThrust = " + maxThrust);
            //MonoBehaviour.print("minThrust = " + minThrust);
            //MonoBehaviour.print("thrustPercentage = " + thrustPercentage);
            //MonoBehaviour.print("requestedThrust = " + requestedThrust);
            //MonoBehaviour.print("velocity = " + velocity);

            partSim = theEngine;

            isActive = active;
            thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
            //MonoBehaviour.print("thrust = " + thrust);

            thrustVec = vecThrust;

            double flowRate = 0d;
            if (partSim.hasVessel)
            {
                //MonoBehaviour.print("hasVessel is true");
                actualThrust = requestedThrust;
                if (velocityCurve != null)
                {
                    actualThrust *= velocityCurve.Evaluate((float)velocity);
                    //MonoBehaviour.print("actualThrust at velocity = " + actualThrust);
                }

                isp = atmosphereCurve.Evaluate((float)partSim.part.staticPressureAtm);
                if (isp == 0d)
                    MonoBehaviour.print("Isp at " + partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");

                if (correctThrust && realIsp == 0)
                {
                    float ispsl = atmosphereCurve.Evaluate(0);
                    if (ispsl != 0)
                    {
                        thrust = thrust * isp / ispsl;
                    }
                    else
                    {
                        MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
                    }
                    //MonoBehaviour.print("corrected thrust = " + thrust);
                }

                if (velocityCurve != null)
                {
                    thrust *= velocityCurve.Evaluate((float)velocity);
                    //MonoBehaviour.print("thrust at velocity = " + thrust);
                }

                if (throttleLocked)
                {
                    //MonoBehaviour.print("throttleLocked is true");
                    flowRate = thrust / (isp * 9.81d);
                }
                else
                {
                    if (partSim.isLanded)
                    {
                        //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
                        flowRate = Math.Max(0.000001d, thrust * FlightInputHandler.state.mainThrottle) / (isp * 9.81d);
                    }
                    else
                    {
                        if (requestedThrust > 0)
                        {
                            if (velocityCurve != null)
                            {
                                requestedThrust *= velocityCurve.Evaluate((float)velocity);
                                //MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust);
                            }

                            //MonoBehaviour.print("requestedThrust > 0");
                            flowRate = requestedThrust / (isp * 9.81d);
                        }
                        else
                        {
                            //MonoBehaviour.print("requestedThrust <= 0");
                            flowRate = thrust / (isp * 9.81d);
                        }
                    }
                }
            }
            else
            {
                //MonoBehaviour.print("hasVessel is false");
                isp = atmosphereCurve.Evaluate((float)atmosphere);
                if (isp == 0d)
                    MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
                if (correctThrust)
                {
                    float ispsl = atmosphereCurve.Evaluate(0);
                    if (ispsl != 0)
                    {
                        thrust = thrust * isp / ispsl;
                    }
                    else
                    {
                        MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
                    }
                    //MonoBehaviour.print("corrected thrust = " + thrust);
                }

                if (velocityCurve != null)
                {
                    thrust *= velocityCurve.Evaluate((float)velocity);
                    //MonoBehaviour.print("thrust at velocity = " + thrust);
                }

                flowRate = thrust / (isp * 9.81d);
            }

            if (SimManager.logOutput)
            {
                buffer = new StringBuilder(1024);
                buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
            }

            float flowMass = 0f;
            foreach (Propellant propellant in propellants)
                flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);

            if (SimManager.logOutput)
                buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);

            foreach (Propellant propellant in propellants)
            {
                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                    continue;

                double consumptionRate = propellant.ratio * flowRate / flowMass;
                if (SimManager.logOutput)
                    buffer.AppendFormat("Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate);
                resourceConsumptions.Add(propellant.id, consumptionRate);
            }

            if (SimManager.logOutput)
                MonoBehaviour.print(buffer);
        }
Ejemplo n.º 38
0
        public override AnimationCurve computeCurve(FloatCurve Isp, float propellantMass)
        {
            AnimationCurve ac = new AnimationCurve();

            float[] fuelFlow = new float[11];

            float deltaThrust;
            float[] deltaDuration = new float[fuelFlow.Length - 1];
            float[] fuelSlope = new float[fuelFlow.Length - 1];
                        Keyframe[] k = new Keyframe[fuelFlow.Length];

            deltaThrust = propellantMass * g;

            int i = 0;
            do
            {
                float ffA = (UIthrust - (((float)i / deltaDuration.Length) * deltaThrust));

                float ffB = (g * Isp.Evaluate(1 - ((float)i / fuelFlow.Length)));

                fuelFlow[i] = (ffA/ffB)/propellantMass;

                i++;
            } while (i< fuelFlow.Length);

            i = 0;

            do
            {
                deltaThrust = fuelFlow[i] - fuelFlow[i+1];
                deltaDuration[i] = 0.1f / (0.5f * deltaThrust + fuelFlow[i]);
                fuelSlope[i] = -deltaThrust / deltaDuration[i];

                i++;
            } while (i < fuelFlow.Length -1);

            i = 0;

            float cumeDuration = 0;

            do
            {
                //Debug.Log("do C: " + i);
                switch (i)
                {
                    case 0:
                        k[i].time = 0;
                        k[i].value = fuelFlow[i];
                        k[i].outTangent = fuelSlope[i];
                        break;

                    default:
                        cumeDuration += deltaDuration[i - 1];

                        k[i].time = cumeDuration;
                        k[i].value = fuelFlow[i];
                        k[i].inTangent =k[i-1].outTangent;

                        if (i < fuelSlope.Length)
                        {
                            Debug.Log("i = " + i + "  fuelSlope[i] " + fuelSlope[i]);
                            k[i].outTangent = fuelSlope[i];
                        }
                        else
                        {
                            k[i].outTangent = 0;
                        }

                        break;
                }

                i++;
            } while (i < k.Length);

            foreach (Keyframe K in k)
            {

                ac.AddKey(K);
            }

            return ac;
        }
        public static FloatCurve ModifyCurveKeys(FloatCurve initialCurve, float vacMult, float atmMult, bool extendToZero)
        {
            ConfigNode tempNode = new ConfigNode();

            initialCurve.Save(tempNode);

            string[] keyStrings = tempNode.GetValues("key");

            float maxTime, ispAtMaxTime, secondTime, ispAtSecondTime, maxPressure;
            maxTime = ispAtMaxTime = secondTime = ispAtSecondTime = maxPressure = 0;
            FloatCurve newAtmosphereCurve = new FloatCurve();

            maxTime = initialCurve.maxTime;

            for (int i = 0; i < keyStrings.Length; i++)
            {
                string[] splitKey = keyStrings[i].Split(' ');

                float scalar = vacMult + Convert.ToSingle(splitKey[0]) * (atmMult - vacMult);
                if (!extendToZero)
                    scalar = Mathf.Clamp(scalar, Mathf.Min(atmMult, vacMult), Mathf.Max(atmMult, vacMult));

                if (Convert.ToSingle(splitKey[0]) != 0)
                    newAtmosphereCurve.Add(Convert.ToSingle(splitKey[0]), Convert.ToSingle(splitKey[1]) * scalar, Convert.ToSingle(splitKey[2]) * scalar, Convert.ToSingle(splitKey[3]) * scalar);
                else
                    newAtmosphereCurve.Add(Convert.ToSingle(splitKey[0]), Convert.ToSingle(splitKey[1]) * scalar, 0, 0);

                if (i == keyStrings.Length - 2)
                {
                    secondTime = Convert.ToSingle(splitKey[0]);
                    ispAtSecondTime = Convert.ToSingle(splitKey[1]) * scalar;
                }
            }

            ispAtMaxTime = newAtmosphereCurve.Evaluate(maxTime);

            if (extendToZero && (ispAtSecondTime - ispAtMaxTime) >= 0.0001f)
            {
                maxPressure = maxTime + (0.01f - ispAtMaxTime) / (ispAtSecondTime - ispAtMaxTime) * (secondTime - maxTime);
                newAtmosphereCurve.Add(maxPressure, 0.01f, 0, 0);
            }

            return newAtmosphereCurve;
        }
Ejemplo n.º 40
0
        public override AnimationCurve computeCurve(FloatCurve Isp, float propellantMass)
        {
            AnimationCurve ac = new AnimationCurve();

            float fuelFlow;
            fuelFlow = UIthrust / (9.80661f * Isp.Evaluate (UIAtmDen));

            fuelFlow = fuelFlow / propellantMass;

            Keyframe k = new Keyframe();
            k.time = 0;
            k.value = fuelFlow;

            ac.AddKey(k);

            return ac;
        }
Ejemplo n.º 41
0
        public override string GetInfo()
        {
            if (!compatible)
                return "";
            if (configs.Count < 2)
                return TLTInfo();

            string info = TLTInfo() + "\nAlternate configurations:\n";

            //Unused as yet
            /*TechLevel moduleTLInfo = new TechLevel();
            if (techNodes != null)
                moduleTLInfo.Load(techNodes, techLevel);
            else
                moduleTLInfo = null;*/

            foreach (ConfigNode config in configs) {

                TechLevel cTL = new TechLevel();
                if (!cTL.Load(config, techNodes, engineType, techLevel))
                    cTL = null;

                if(!config.GetValue ("name").Equals (configuration)) {
                    info += "   " + config.GetValue ("name") + "\n";
                    if(config.HasValue (thrustRating))
                        info += "    (" + (scale * ThrustTL(config.GetValue (thrustRating), config)).ToString("0.00") + " Thrust";
                    else
                        info += "    (Unknown Thrust";
                    float cst;
                    if(config.HasValue("cost") && float.TryParse(config.GetValue("cost"), out cst))
                        info += "    (" + (scale*cst).ToString("N0") + " extra cost)"; // FIXME should get cost from TL, but this should be safe
                    // because it will always be the cost for the original TL, and thus unmodified.

                    FloatCurve isp = new FloatCurve();
                    if(config.HasNode ("atmosphereCurve")) {
                        isp.Load (config.GetNode ("atmosphereCurve"));
                        info  += ", "
                            + isp.Evaluate (isp.maxTime).ToString() + "-"
                              + isp.Evaluate (isp.minTime).ToString() + "Isp";
                    }
                    else if (config.HasValue("IspSL") && config.HasValue("IspV"))
                    {
                        float ispSL = 1.0f, ispV = 1.0f;
                        float.TryParse(config.GetValue("IspSL"), out ispSL);
                        float.TryParse(config.GetValue("IspV"), out ispV);
                        if (cTL != null)
                        {
                            ispSL *= ispSLMult * cTL.AtmosphereCurve.Evaluate(1);
                            ispV *= ispVMult * cTL.AtmosphereCurve.Evaluate(0);
                            info += ", " + ispSL.ToString("0") + "-" + ispV.ToString("0") + "Isp";
                        }
                    }
                    float gimbalR = -1f;
                    if (config.HasValue("gimbalRange"))
                        gimbalR = float.Parse(config.GetValue("gimbalRange"));
                    // Don't do per-TL checks here, they're misleading.
                    /*else if (!gimbalTransform.Equals("") || useGimbalAnyway)
                    {
                        if (cTL != null)
                            gimbalR = cTL.GimbalRange;
                    }*/
                    if (gimbalR != -1f)
                        info += ", Gimbal " + gimbalR.ToString("N1");

                    if (config.HasValue("ullage"))
                        info += ", " + (config.GetValue("ullage").ToLower() == "true" ? "ullage" : "no ullage");
                    if (config.HasValue("pressureFed") && config.GetValue("pressureFed").ToLower() == "true")
                        info += ", pfed";

                    if (config.HasValue("ignitions"))
                    {
                        int ignitions;
                        if (int.TryParse(config.GetValue("ignitions"), out ignitions))
                        {
                            if (ignitions > 0)
                                info += ", " + ignitions + " ignition" + (ignitions > 1 ? "s" : "");
                            else
                                info += ", unl. ignitions";
                        }
                    }
                    info += ")\n";
                }

            }
            return info;
        }
Ejemplo n.º 42
0
        public static EngineSim New(PartSim theEngine,
                         double atmosphere,
                         float machNumber,
                         float maxFuelFlow,
                         float minFuelFlow,
                         float thrustPercentage,
                         Vector3 vecThrust,
                         FloatCurve atmosphereCurve,
                         bool atmChangeFlow,
                         FloatCurve atmCurve,
                         FloatCurve velCurve,
                         float currentThrottle,
                         float IspG,
                         bool throttleLocked,
                         List<Propellant> propellants,
                         bool active,
                         float resultingThrust,
                         List<Transform> thrustTransforms,
                        LogMsg log)
        {
            EngineSim engineSim = pool.Borrow();

            engineSim.isp = 0.0;
            engineSim.maxMach = 0.0f;
            engineSim.actualThrust = 0.0;
            engineSim.partSim = theEngine;
            engineSim.isActive = active;
            engineSim.thrustVec = vecThrust;
            engineSim.resourceConsumptions.Reset();
            engineSim.appliedForces.Clear();

            double flowRate = 0.0;
            if (engineSim.partSim.hasVessel)
            {
                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach);
                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0;

                if (throttleLocked)
                {
                    flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                }
                else
                {
                    if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
                    {
                        flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
                    }
                    else
                    {
                        flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
                    }
                }
            }
            else
            {
                float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, SimManager.Body.GetDensity(FlightGlobals.getStaticPressure(0, SimManager.Body), FlightGlobals.getExternalTemperature(0, SimManager.Body)), velCurve, machNumber, ref engineSim.maxMach);
                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
                engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
                flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
            }

            if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);

            engineSim.thrust = flowRate * (engineSim.isp * IspG);
            // I did not look into the diff between those 2 so I made them equal...
            engineSim.actualThrust = engineSim.thrust;

            float flowMass = 0f;
            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];
                flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
            }

            if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);

            for (int i = 0; i < propellants.Count; ++i)
            {
                Propellant propellant = propellants[i];

                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
                {
                    continue;
                }

                double consumptionRate = propellant.ratio * flowRate / flowMass;
                if (log != null) log.buf.AppendFormat(
                        "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
                        ResourceContainer.GetResourceName(propellant.id),
                        theEngine.name,
                        theEngine.partId,
                        consumptionRate);
                engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
            }

            double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
            for (int i = 0; i < thrustTransforms.Count; i++)
            {
                Transform thrustTransform = thrustTransforms[i];
                Vector3d direction = thrustTransform.forward.normalized;
                Vector3d position = thrustTransform.position;

                AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
                engineSim.appliedForces.Add(appliedForce);
            }

            return engineSim;
        }
Ejemplo n.º 43
0
 private string convertMassFlowToThrust(float MassFlow, FloatCurve atmosphereCurve, string msgOut)
 {
     msgOut = "";
     msgOut = "Atmosphere thrust at this node is " + (9.80665f * atmosphereCurve.Evaluate(1) * MassFlow * SRB.fullStackFuelMass) + "kN, vacuum thrust is " + (9.80665f * atmosphereCurve.Evaluate(0) * MassFlow * SRB.fullStackFuelMass) + "kN";
     return msgOut;
     ;
 }
        private void SetMode()
        {
            if (multiEngine.runningPrimary)
                EngineModeID = 0;
            else
                EngineModeID = 1;

            Utils.Log("VariableIspEngine: Changing mode to " + engineModes[EngineModeID].name);
            CurrentEngineID = engineModes[EngineModeID].name;
            engine = engines[EngineModeID];
            ThrustCurve = engineModes[EngineModeID].thrustCurve;
            IspCurve = engineModes[EngineModeID].ispCurve;

            for (int i=0; i < engine.propellants.Count; i++)
            {
                if (engine.propellants[i].name != "ElectricCharge")
                {
                    fuelPropellant = engine.propellants[i];
                }
                else
                {
                    ecPropellant = engine.propellants[i];
                }
            }

            //Utils.Log("VariableIspEngine: Changed mode to " + engine.engineID);
            Utils.Log("VariableIspEngine: Fuel: " + fuelPropellant.name);
            Utils.Log("VariableIspEngine: Thrust Curve: " + ThrustCurve.Evaluate(0f) + " to " + ThrustCurve.Evaluate(1f));
            Utils.Log("VariableIspEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f));

            AdjustVariableThrust();
        }
Ejemplo n.º 45
0
        void Trim(List<double[]> list, double topLayer)
        {
            FloatCurve curve = new FloatCurve();
            curve.Load(WriteCurve(list));

            double[] lastKey = { topLayer, curve.Evaluate((float)topLayer) };

            for (int i = list.Count; i > 0; i--)
            {
                if (list[i - 1][0] >= topLayer)
                    list.RemoveAt(i - 1);
            }

            list.Add(lastKey);

            // Debug
            PrintCurve(list, "Trim");
        }
        public void UpdateCurve()
        {
            m_curve = new FloatCurve();
            foreach(Vector4 record in m_values)
            {
                m_curve.Add(record.x, record.y, record.z, record.w);
            }

            // Clear the background to black.
            for (int i = 0; i < canvas.width; ++i)
            {
                for (int j = 0; j < canvas.height; ++j)
                {
                    canvas.SetPixel(i, j, Color.black);
                }
            }

            // Render the border.
            for (int i = 0; i < canvas.width; ++i)
            {
                canvas.SetPixel(i, 0, Color.white);
            }
            for (int j = 0; j < canvas.width; ++j)
            {
                canvas.SetPixel(0, j, Color.white);
            }
            for (int i = 0; i < canvas.width; ++i)
            {
                canvas.SetPixel(i, canvas.height - 1, Color.white);
            }
            for (int j = 0; j < canvas.width; ++j)
            {
                canvas.SetPixel(canvas.width - 1, j, Color.white);
            }

            // Prepare min/max.
            float minX = float.MaxValue;
            float maxX = float.MinValue;
            float minY = float.MaxValue;
            float maxY = float.MinValue;
            foreach(Vector4 record in m_values)
            {
                if (minX > record.x) minX = record.x;
                if (maxX < record.x) maxX = record.x;
                if (minY > record.y) minY = record.y;
                if (maxY < record.y) maxY = record.y;
            }

            float minXLog = Mathf.Sign(minX) * Mathf.Log10(Mathf.Abs(minX) + 1);
            float maxXLog = Mathf.Sign(maxX) * Mathf.Log10(Mathf.Abs(maxX) + 1);

            // Render the curve.
            if(m_values.Count > 0)
            {
                float prevProgressY = float.NaN;

                float selectedActualX = 0.0f;
                float selectedProgressX = 0.0f;
                float selectedActualY = 0.0f;
                float selectedProgressY = 0.0f;
                if (recordIndex != -1)
                {
                    selectedActualX = m_values[recordIndex].x;
                    selectedProgressX = Mathf.InverseLerp(minX, maxX, selectedActualX);
                    selectedActualY = m_values[recordIndex].y;
                    selectedProgressY = (selectedActualY - minY) / (maxY - minY);
                    if (xAxisUseLog)
                    {
                        selectedProgressX = Mathf.Sign(selectedActualX) * Mathf.Log10(Mathf.Abs(selectedActualX) + 1.0f);
                        selectedProgressX = Mathf.InverseLerp(minXLog, maxXLog, selectedProgressX);
                    }
                }

                for (int i = 1; i < canvas.width - 2; ++i)
                {
                    float progressX = (i - 1.0f) / (canvas.width - 2.0f);
                    float actualX = Mathf.Lerp(minX, maxX, progressX);
                    if(xAxisUseLog)
                    {
                        actualX = Mathf.Lerp(minXLog, maxXLog, progressX);
                        actualX = Mathf.Sign(actualX) * (Mathf.Pow(10, Math.Abs(actualX)) - 1.0f);
                    }

                    float actualY = m_curve.Evaluate(actualX);
                    //Debug.Log("TFCE: Eval(" + actualX.ToString("F2") + ") = " + actualY.ToString("F2"));
                    float progressY = (actualY - minY) / (maxY - minY);
                    if (float.IsNaN(prevProgressY))
                    {
                        // This is the first point.
                        prevProgressY = progressY;
                    }
                    else
                    {
                        if (Mathf.Abs(progressY - prevProgressY) >= 1.5f / (canvas.height - 2.0f))
                        {
                            // We need to insert more mid-points to smooth the curve.
                            if(progressY > prevProgressY)
                            {
                                for(float y = prevProgressY; y < progressY; y += 1.0f / (canvas.height - 2.0f))
                                {
                                    if(y - prevProgressY < (progressY - prevProgressY) / 2.0)
                                        canvas.SetPixel(i - 1, (int)(y * (canvas.height - 2.0f) + 1.0f), Color.green);
                                    else
                                        canvas.SetPixel(i, (int)(y * (canvas.height - 2.0f) + 1.0f), Color.green);
                                }
                            }
                            else
                            {
                                for (float y = prevProgressY; y > progressY; y -= 1.0f / (canvas.height - 2.0f))
                                {
                                    if (y - progressY > (prevProgressY - progressY) / 2.0)
                                        canvas.SetPixel(i - 1, (int)(y * (canvas.height - 2.0f) + 1.0f), Color.green);
                                    else
                                        canvas.SetPixel(i, (int)(y * (canvas.height - 2.0f) + 1.0f), Color.green);
                                }
                            }
                        }
                        prevProgressY = progressY;
                    }
                    canvas.SetPixel(i, (int)(progressY * (canvas.height - 2.0f) + 1.0f), Color.green);

                    // Cross line for selected point.
                    if (recordIndex != -1)
                    {
                        if (i == (int)(selectedProgressX * (canvas.width - 2.0f) + 1.0f))
                        {
                            for (int y = 1; y < canvas.height - 2; ++y)
                                canvas.SetPixel(i, y, Color.yellow);
                        }
                        canvas.SetPixel(i, (int)(selectedProgressY * (canvas.height - 2.0f) + 1.0f), Color.yellow);
                    }
                }
            }

            canvas.Apply();
            canvasInvalidated = false;
        }
        public override void OnFixedUpdate()
        {
            if (!HighLogic.LoadedSceneIsFlight)
                return;

            if (!Deployed()) //For variants like the Medusa
                return;

            //Setup
            Transform t = part.FindModelTransform(transformName);
            if (lastCheck < ResourceUtilities.FLOAT_TOLERANCE)
                lastCheck = Planetarium.GetUniversalTime();

            var currentThrust = GetPulseThrust();
            var pulseInterval = GetPulseInterval(lastThrottle);

            //Check Emitters - turn them off if it's time.
            if (Planetarium.GetUniversalTime() > lastParticleCheck + particleLife)
                ToggleEmmitters(false);

            //Check for fuel
            if (!HasFuel())
                return;

            //See if it's time to fire.
            var eng = part.FindModuleImplementing<ModuleEngines>();
            if (Planetarium.GetUniversalTime() > lastCheck + pulseInterval)
            {
                lastThrottle = eng.currentThrottle;
                if (!eng.isActiveAndEnabled || lastThrottle < 0.01)
                {
                    ToggleEmmitters(false);
                    return;
                }
                ConsumeFuel();
                lastCheck = Planetarium.GetUniversalTime();
                lastParticleCheck = lastCheck;
                ToggleEmmitters(true);
                PlayAnimation();
            }

            //Where are we in the curve?
            var pulseCurve = new FloatCurve();
            pulseCurve.Add(0, (1 - powerCurve) / 2);
            pulseCurve.Add(0.5f,  powerCurve);
            pulseCurve.Add(1, (1 - powerCurve) / 2);

            if(Planetarium.GetUniversalTime() - lastCheck < minPulseTime)
            {
                var curveTime = (float) (Planetarium.GetUniversalTime() - lastCheck)/(float) minPulseTime;
                var atmoModifier = 1f;
                if(atmosphereNerf)
                    atmoModifier = (float)Math.Max(0, 1d - vessel.atmDensity);
                var thrustAmount = (float) (currentThrust*pulseCurve.Evaluate(curveTime)) * atmoModifier;

                part.GetComponent<Rigidbody>().AddForceAtPosition(-t.forward * thrustAmount, t.position, ForceMode.Force);
                part.AddThermalFlux(thrustAmount * heatMultiplier);
            }
        }
Ejemplo n.º 48
0
        public virtual void SetConfiguration(string newConfiguration = null)
        {
            if (newConfiguration == null)
                newConfiguration = configuration;
            ConfigNode newConfig = configs.Find (c => c.GetValue ("name").Equals (newConfiguration));
            if (newConfig != null) {

                // for asmi
                if (useConfigAsTitle)
                    part.partInfo.title = configuration;

                configuration = newConfiguration;
                config = new ConfigNode ("MODULE");
                newConfig.CopyTo (config);
                config.name = "MODULE";

                // fix for HotRockets etc.
                if (type.Equals("ModuleEngines") && part.Modules.Contains("ModuleEnginesFX") && !part.Modules.Contains("ModuleEngines"))
                    type = "ModuleEnginesFX";
                if (type.Equals("ModuleEnginesFX") && part.Modules.Contains("ModuleEngines") && !part.Modules.Contains("ModuleEnginesFX"))
                    type = "ModuleEngines";
                // fix for ModuleRCSFX etc
                if (type.Equals("ModuleRCS") && part.Modules.Contains("ModuleRCSFX") && !part.Modules.Contains("ModuleRCS"))
                    type = "ModuleRCSFX";
                if (type.Equals("ModuleRCSFX") && part.Modules.Contains("ModuleRCS") && !part.Modules.Contains("ModuleRCSFX"))
                    type = "ModuleRCS";

                config.SetValue("name", type);

                #if DEBUG
                print ("replacing " + type + " with:");
                print (newConfig.ToString ());
                #endif

                pModule = null;
                if (part.Modules.Contains(type))
                {
                        pModule = part.Modules[type];

                    // clear all FloatCurves
                    Type mType = pModule.GetType();
                    foreach (FieldInfo field in mType.GetFields())
                    {
                        if (field.FieldType == typeof(FloatCurve) && (field.Name.Equals("atmosphereCurve") || field.Name.Equals("velocityCurve")))
                        {
                            //print("*MFS* resetting curve " + field.Name);
                            field.SetValue(pModule, new FloatCurve());
                        }
                    }
                    // clear propellant gauges
                    foreach (FieldInfo field in mType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
                    {
                        if (field.FieldType == typeof(Dictionary<Propellant, VInfoBox>))
                        {
                            Dictionary<Propellant, VInfoBox> boxes = (Dictionary<Propellant, VInfoBox>)(field.GetValue(pModule));
                            if (boxes == null)
                                continue;
                            foreach (VInfoBox v in boxes.Values)
                            {
                                if (v == null) //just in case...
                                    continue;
                                try
                                {
                                    part.stackIcon.RemoveInfo(v);
                                }
                                catch (Exception e)
                                {
                                    print("*MFS* Trying to remove info box: " + e.Message);
                                }
                            }
                            boxes.Clear();
                        }
                    }
                }
                if (type.Equals("ModuleRCS") || type.Equals("ModuleRCSFX"))
                {
                    ModuleRCS rcs = (ModuleRCS)pModule;
                    if (rcs != null)
                    {
                        rcs.G = 9.80665f;
                        /*bool oldRes = config.HasValue("resourceName");
                        string resource = "";
                        if (oldRes)
                        {
                            resource = config.GetValue("resourceName");
                            rcs.resourceName = resource;
                        }*/
                        DoConfig(config);
                        if (config.HasNode("PROPELLANT"))
                        {
                            rcs.propellants.Clear();
                        }
                        pModule.Load(config);
                        /*if (oldRes)
                        {
                            rcs.resourceName = resource;
                            rcs.SetResource(resource);
                        }*/
                        // PROPELLANT handling is automatic.
                        fastRCS = rcs;
                        if(type.Equals("ModuleRCS") && !part.Modules.Contains("ModuleRCSFX"))
                            fastType = ModuleType.MODULERCS;
                        else
                            fastType = ModuleType.MODULERCSFX;
                    }
                }
                else
                { // is an ENGINE
                    if (type.Equals("ModuleEngines"))
                    {
                        ModuleEngines mE = (ModuleEngines)pModule;
                        if (mE != null)
                        {
                            configMaxThrust = mE.maxThrust;
                            configMinThrust = mE.minThrust;
                            fastEngines = mE;
                            fastType = ModuleType.MODULEENGINES;
                            mE.g = 9.80665f;
                            if (config.HasNode("PROPELLANT"))
                            {
                                mE.propellants.Clear();
                            }
                        }
                        if (config.HasValue("maxThrust"))
                        {
                            float thr;
                            if(float.TryParse(config.GetValue("maxThrust"), out thr))
                                configMaxThrust = thr;
                        }
                        if (config.HasValue("minThrust"))
                        {
                            float thr;
                            if(float.TryParse(config.GetValue("minThrust"), out thr))
                                configMinThrust = thr;
                        }
                    }
                    else if (type.Equals("ModuleEnginesFX"))
                    {
                        ModuleEnginesFX mE = (ModuleEnginesFX)pModule;
                        if (mE != null)
                        {
                            configMaxThrust = mE.maxThrust;
                            configMinThrust = mE.minThrust;
                            fastEnginesFX = mE;
                            fastType = ModuleType.MODULEENGINESFX;
                            mE.g = 9.80665f;
                            if (config.HasNode("PROPELLANT"))
                            {
                                mE.propellants.Clear();
                            }
                        }
                        if (config.HasValue("maxThrust"))
                        {
                            float thr;
                            if (float.TryParse(config.GetValue("maxThrust"), out thr))
                                configMaxThrust = thr;
                        }
                        if (config.HasValue("minThrust"))
                        {
                            float thr;
                            if (float.TryParse(config.GetValue("minThrust"), out thr))
                                configMinThrust = thr;
                        }
                    }
                    DoConfig(config);
                    if(pModule != null)
                        pModule.Load (config);
                    if (config.HasNode("ModuleEngineIgnitor") && part.Modules.Contains("ModuleEngineIgnitor"))
                    {
                        ConfigNode eiNode = config.GetNode("ModuleEngineIgnitor");
                        if (eiNode.HasValue("ignitionsAvailable"))
                        {
                            int ignitions;
                            if (int.TryParse(eiNode.GetValue("ignitionsAvailable"), out ignitions))
                            {
                                if (ignitions < 0)
                                {
                                    ignitions = techLevel + ignitions;
                                    if (ignitions < 1)
                                        ignitions = 1;
                                }
                                else if (ignitions == 0)
                                    ignitions = -1;

                                eiNode.SetValue("ignitionsAvailable", ignitions.ToString());
                                if (eiNode.HasValue("ignitionsRemained"))
                                    eiNode.SetValue("ignitionsRemained", ignitions.ToString());
                                else
                                    eiNode.AddValue("ignitionsRemained", ignitions.ToString());
                            }
                        }
                        if (!HighLogic.LoadedSceneIsEditor && !(HighLogic.LoadedSceneIsFlight && vessel != null && vessel.situation == Vessel.Situations.PRELAUNCH)) // fix for prelaunch
                        {
                            int remaining = (int)(part.Modules["ModuleEngineIgnitor"].GetType().GetField("ignitionsRemained").GetValue(part.Modules["ModuleEngineIgnitor"]));
                            if(eiNode.HasValue("ignitionsRemained"))
                                eiNode.SetValue("ignitionsRemained", remaining.ToString());
                            else
                                eiNode.AddValue("ignitionsRemained", remaining.ToString());
                        }
                        ConfigNode tNode = new ConfigNode("MODULE");
                        eiNode.CopyTo(tNode);
                        tNode.SetValue("name", "ModuleEngineIgnitor");
                        part.Modules["ModuleEngineIgnitor"].Load(tNode);
                    }
                }
                if (part.Resources.Contains("ElectricCharge") && part.Resources["ElectricCharge"].maxAmount < 0.1)
                { // hacking around a KSP bug here
                    part.Resources["ElectricCharge"].amount = 0;
                    part.Resources["ElectricCharge"].maxAmount = 0.1;
                }
                UpdateTweakableMenu();
                // Check for and enable the thrust curve
                useThrustCurve = false;
                //Fields["thrustCurveDisplay"].guiActive = true;
                if (config.HasNode("thrustCurve") && config.HasValue("curveResource"))
                {
                    curveResource = config.GetValue("curveResource");
                    if (curveResource != "")
                    {
                        double ratio = 0.0;
                        switch (fastType)
                        {
                            case ModuleType.MODULEENGINES:
                                for (int i = 0; i < fastEngines.propellants.Count; i++ )
                                    if (fastEngines.propellants[i].name.Equals(curveResource))
                                        curveProp = i;
                                if (curveProp >= 0)
                                    ratio = fastEngines.propellants[curveProp].totalResourceAvailable / fastEngines.propellants[curveProp].totalResourceCapacity;
                                break;

                            case ModuleType.MODULEENGINESFX:
                                for (int i = 0; i < fastEnginesFX.propellants.Count; i++)
                                    if (fastEnginesFX.propellants[i].name.Equals(curveResource))
                                        curveProp = i;
                                if (curveProp >= 0)
                                    ratio = fastEnginesFX.propellants[curveProp].totalResourceAvailable / fastEnginesFX.propellants[curveProp].totalResourceCapacity;
                                break;

                            case ModuleType.MODULERCS:
                                for (int i = 0; i < fastRCS.propellants.Count; i++)
                                    if (fastRCS.propellants[i].name.Equals(curveResource))
                                        curveProp = i;
                                if (curveProp >= 0)
                                    ratio = fastRCS.propellants[curveProp].totalResourceAvailable / fastRCS.propellants[curveProp].totalResourceCapacity;
                                break;
                        }
                        if (curveProp != -1)
                        {
                            useThrustCurve = true;
                            configThrustCurve = new FloatCurve();
                            configThrustCurve.Load(config.GetNode("thrustCurve"));
                            print("*RF* Found thrust curve for " + part.name + ", current ratio " + ratio + ", curve: " + configThrustCurve.Evaluate((float)ratio));
                            //Fields["thrustCurveDisplay"].guiActive = true;
                        }

                    }
                }
            }
        }
Ejemplo n.º 49
0
        public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult, Vector3 previousTorque, float maxTorque, float maxAoA, FloatCurve liftCurve, FloatCurve dragCurve)
        {
            Rigidbody rb = ml.part.rb;
            double airDensity = ml.vessel.atmDensity;
            double airSpeed = ml.vessel.srfSpeed;
            Vector3d velocity = ml.vessel.srf_velocity;

            //temp values
            Vector3 CoL = new Vector3(0, 0, -1f);
            float liftMultiplier = BDArmorySettings.GLOBAL_LIFT_MULTIPLIER;
            float dragMultiplier = BDArmorySettings.GLOBAL_DRAG_MULTIPLIER;

            //lift
            float AoA = Mathf.Clamp(Vector3.Angle(ml.transform.forward, velocity.normalized), 0, 90);
            if(AoA > 0)
            {
                double liftForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * liftMultiplier * liftCurve.Evaluate(AoA);
                Vector3 forceDirection = Vector3.ProjectOnPlane(-velocity, ml.transform.forward).normalized;
                rb.AddForceAtPosition((float)liftForce * forceDirection, ml.transform.TransformPoint(CoL));
            }

            //drag
            if(airSpeed > 0)
            {
                double dragForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * dragMultiplier * dragCurve.Evaluate(AoA);
                rb.AddForceAtPosition((float)dragForce * -velocity.normalized, ml.transform.TransformPoint(CoL));
            }

            //guidance
            if(airSpeed > 1)
            {
                Vector3 targetDirection;
                float targetAngle;
                if(AoA < maxAoA)
                {
                    targetDirection = (targetPosition - ml.transform.position);
                    targetAngle = Vector3.Angle(velocity.normalized, targetDirection) * 4;
                }
                else
                {
                    targetDirection = velocity.normalized;
                    targetAngle = AoA;
                }

                Vector3 torqueDirection = -Vector3.Cross(targetDirection, velocity.normalized).normalized;
                torqueDirection = ml.transform.InverseTransformDirection(torqueDirection);

                float torque = Mathf.Clamp(targetAngle * steerMult, 0, maxTorque);
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, torqueDirection*torque, 0.86f), Vector3.forward);

                rb.AddRelativeTorque(finalTorque);

                return finalTorque;

            }
            else
            {
                Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, Vector3.zero, 0.25f), Vector3.forward);
                rb.AddRelativeTorque(finalTorque);
                return finalTorque;
            }
        }