예제 #1
1
        public void Update()
        {
            if (afx == null)
            {
                GameObject fx = GameObject.Find("FXLogic");
                if (fx != null)
                {
                    afx = fx.GetComponent<AerodynamicsFX>();
                }
            }
            Animation flapsAnim = part.FindModelAnimators("Flap_Top_Right")[0];
            if (vessel != null && vessel.mainBody.atmosphere && vessel.altitude < vessel.mainBody.RealMaxAtmosphereAltitude())
            {
                float direction = ((vessel.GetSrfVelocity().magnitude > 25) && (Vector3.Angle(vessel.transform.up, vessel.GetSrfVelocity()) > 90)) ? -1 : 1;

                lastFlaps[0] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Right", Mathf.Clamp01(direction * (vessel.ctrlState.pitch - vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[0]);
                lastFlaps[1] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Left", Mathf.Clamp01(direction * (vessel.ctrlState.pitch + vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[1]);
                lastFlaps[2] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Right", Mathf.Clamp01(direction * (-vessel.ctrlState.pitch - vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[2]);
                lastFlaps[3] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Left", Mathf.Clamp01(direction * (-vessel.ctrlState.pitch + vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[3]);
            }
            else
            {
                lastFlaps[0] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Right", 0, TimeWarp.deltaTime, lastFlaps[0]);
                lastFlaps[1] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Left", 0, TimeWarp.deltaTime, lastFlaps[1]);
                lastFlaps[2] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Right", 0, TimeWarp.deltaTime, lastFlaps[2]);
                lastFlaps[3] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Left", 0, TimeWarp.deltaTime, lastFlaps[3]);
            }
            switch (state)
            {
                case State.OFF:
                    if (HighLogic.LoadedSceneIsEditor || (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel != null && core.attitude.enabled))
                    {
                        state = State.AWAKENING;
                        part.FindModelAnimators("Waking")[0].Play("Waking");
                    }
                    break;
                case State.AWAKENING:
                    if (!part.FindModelAnimators("Waking")[0].isPlaying)
                    {
                        AdvanceAnimationTo(part.FindModelAnimators("Waking")[0], "Waking", 1, 100);

                        state = State.AWAKE;
                        lastBlink = lastAction = Time.time;
                    }
                    break;
                case State.AWAKE:
                    if (!part.FindModelAnimators("Blink")[0].isPlaying)
                    {
                        if ((UnityEngine.Random.Range(0, 10.0F / (HighLogic.LoadedSceneIsEditor ? Time.deltaTime : TimeWarp.deltaTime)) < (Time.time - lastBlink)))
                        {
                            part.FindModelAnimators("Blink")[0].Play("Blink");
                            lastBlink = Time.time;
                        }
                        GameObject cam = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.editorCamera.gameObject : FlightCamera.fetch.gameObject;
                        Vector3 target = (cam.transform.position - part.transform.position).normalized;
                        if (core.attitude.enabled)
                        {
                            target = core.attitude.attitudeGetReferenceRotation(core.attitude.attitudeReference) * core.attitude.attitudeTarget * Quaternion.Euler(90, 0, 0) * Vector3.up;
                            lastAction = Time.time;
                        }
                        Vector3 localTarget = part.transform.InverseTransformDirection(target);
                        Vector2 polarTarget = CartesianToPolar(localTarget);
                        if (Mathfx.Approx(polarTarget.x, -90, 1) || Mathfx.Approx(polarTarget.x, 90, 1))
                        {
                            polarTarget.y = eye_base.localEulerAngles.z + 90;
                        }
                        if ((!HighLogic.LoadedSceneIsEditor && (Time.time - lastAction > 30)))
                        {
                            if (Mathfx.Approx(eye_base.localEulerAngles.z, 0, 1) && Mathfx.Approx(eye_ball.localEulerAngles.x, 0, 1))
                            {
                                state = State.SLEEPING;
                                part.FindModelAnimators("Sleeping")[0].Play("Sleeping");
                            }
                            else
                            {
                                polarTarget = new Vector2(-90, 90);
                            }
                        }
                        if (afx != null && afx.FxScalar > 0)
                        {
                            polarTarget = new Vector2(90, 90);
                        }
                        eye_base.localEulerAngles = new Vector3(0, 0, Mathf.MoveTowardsAngle(eye_base.localEulerAngles.z, polarTarget.y - 90, 360 * Time.deltaTime));
                        eye_ball.localRotation = Quaternion.RotateTowards(eye_ball.localRotation, Quaternion.Euler(polarTarget.x + 90, 0, 0), 360 * Time.deltaTime);
                    }
                    break;
                case State.SLEEPING:
                    if (!part.FindModelAnimators("Sleeping")[0].isPlaying)
                    {
                        AdvanceAnimationTo(part.FindModelAnimators("Sleeping")[0], "Sleeping", 1, 100);

                        state = State.OFF;
                    }
                    break;
                default:
                    break;
            }
        }
        private void GetAeroFX()
        {
            GameObject fxLogicObject = GameObject.Find("FXLogic");

            if (fxLogicObject != null)
            {
                AeroFX = fxLogicObject.GetComponent <AerodynamicsFX>();
            }
        }
예제 #3
0
 private void FixAeroFX(AerodynamicsFX aeroFX)
 {
     if (afx.velocity.magnitude < startThermal)             // approximate speed where shockwaves begin visibly glowing
     {
         afx.state = 0;
     }
     else if (afx.velocity.magnitude >= fullThermal)
     {
         afx.state = 1;
     }
     else
     {
         afx.state = (afx.velocity.magnitude - startThermal) / (fullThermal - startThermal);
     }
 }
예제 #4
0
            void Awake()
            {
                aeroFX = Resources.FindObjectsOfTypeAll <AerodynamicsFX>()[0];
                GameEvents.onDominantBodyChange.Add(OnDominantBodyChange);

                // Check if we already stored the default values
                if (ReentryHeat == null)
                {
                    ReentryHeat = aeroFX.ReentryHeat;
                }
                if (Condensation == null)
                {
                    Condensation = aeroFX.Condensation;
                }
            }
        void Awake()
        {
            if (!NewKerbolConfig.ModEnabled)
            {
                DestroyImmediate(this);
                return;
            }

            aeroFX = aeroFX = Resources.FindObjectsOfTypeAll <AerodynamicsFX> ()[0];

            if (defaultReentryState == null)
            {
                defaultReentryState = aeroFX.ReentryHeat;
            }
            if (defaultMachState == null)
            {
                defaultMachState = aeroFX.Condensation;
            }

            //DumpAeroFXState (defaultReentryState, "Reentry");
            //DumpAeroFXState (defaultMachState, "Mach");

            GameEvents.onDominantBodyChange.Add(OnDominantBodyChange);
        }
예제 #6
0
 public void Start()
 {
     _afx = null; // clear it for this start
 }
예제 #7
0
 private void FixAeroFX(AerodynamicsFX aeroFX)
 {
     if (afx.velocity.magnitude < startThermal) // approximate speed where shockwaves begin visibly glowing
         afx.state = 0;
     else if (afx.velocity.magnitude >= fullThermal)
         afx.state = 1;
     else
         afx.state = (afx.velocity.magnitude - startThermal) / (fullThermal - startThermal);
 }
예제 #8
0
        public void Update()
        {
            if (Input.GetKeyDown(KeyCode.R) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.D))
            {
                debugging = !debugging;
            }

            if (FlightGlobals.ready && (FlightGlobals.ActiveVessel != null))
            {
                if (afx == null)
                {
                    GameObject fx = GameObject.Find("FXLogic");
                    if (fx != null)
                    {
                        afx = fx.GetComponent<AerodynamicsFX>();
                    }
                }

                if ((afx != null) && (afx.FxScalar > 0))
                {
                    Ray ray = new Ray();

                    foreach (Part p in FlightGlobals.ActiveVessel.Parts)
                    {
                        ray.direction = (p.Rigidbody.GetPointVelocity(p.transform.position) + Krakensbane.GetFrameVelocityV3f() - Krakensbane.GetLastCorrection() * TimeWarp.fixedDeltaTime).normalized;
                        ray.origin = p.transform.position;

                        if (!Physics.Raycast(ray, 10))
                        {
                            p.temperature += Mathf.Pow(afx.FxScalar, Exponent) * Multiplier * TimeWarp.deltaTime;
                        }
                    }
                }
            }
        }
예제 #9
0
        private void FixAeroFX(AerodynamicsFX aeroFX)
        {
            aeroFX.airDensity = (float)(Math.Pow(frameDensity, afxDensityExponent));
            /*aeroFX.state = Mathf.InverseLerp(0.15f, 0.1f, aeroFX.airDensity);
            aeroFX.heatFlux = 0.5f * aeroFX.airDensity * Mathf.Pow(aeroFX.airspeed, aeroFX.fudge1);
            aeroFX.FxScalar = Mathf.Min(1f, (aeroFX.heatFlux - aeroFX.) / (5f * aeroFX.));
            aeroFX.transitionFade = 1f - Mathf.Sin(aeroFX.state * 3.14159274f);
            aeroFX.FxScalar *= aeroFX.transitionFade;*/

            afx.state = Mathf.InverseLerp(startThermal, fullThermal, afx.airspeed);
        }
예제 #10
0
        public void Update()
        {
            if (afx == null)
            {
                GameObject fx = GameObject.Find("FXLogic");
                if (fx != null)
                {
                    afx = fx.GetComponent <AerodynamicsFX>();
                }
            }
            Animation flapsAnim = part.FindModelAnimators("Flap_Top_Right")[0];

            if (vessel != null && vessel.mainBody.atmosphere && vessel.altitude < vessel.mainBody.RealMaxAtmosphereAltitude())
            {
                float direction = ((vessel.GetSrfVelocity().magnitude > 25) && (Vector3.Angle(vessel.transform.up, vessel.GetSrfVelocity()) > 90)) ? -1 : 1;

                lastFlaps[0] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Right", Mathf.Clamp01(direction * (vessel.ctrlState.pitch - vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[0]);
                lastFlaps[1] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Left", Mathf.Clamp01(direction * (vessel.ctrlState.pitch + vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[1]);
                lastFlaps[2] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Right", Mathf.Clamp01(direction * (-vessel.ctrlState.pitch - vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[2]);
                lastFlaps[3] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Left", Mathf.Clamp01(direction * (-vessel.ctrlState.pitch + vessel.ctrlState.yaw) / 2), TimeWarp.deltaTime, lastFlaps[3]);
            }
            else
            {
                lastFlaps[0] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Right", 0, TimeWarp.deltaTime, lastFlaps[0]);
                lastFlaps[1] = AdvanceAnimationTo(flapsAnim, "Flap_Top_Left", 0, TimeWarp.deltaTime, lastFlaps[1]);
                lastFlaps[2] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Right", 0, TimeWarp.deltaTime, lastFlaps[2]);
                lastFlaps[3] = AdvanceAnimationTo(flapsAnim, "Flap_Bottom_Left", 0, TimeWarp.deltaTime, lastFlaps[3]);
            }
            switch (state)
            {
            case State.OFF:
                if (HighLogic.LoadedSceneIsEditor || (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && vessel != null && core.attitude.enabled))
                {
                    state = State.AWAKENING;
                    part.FindModelAnimators("Waking")[0].Play("Waking");
                }
                break;

            case State.AWAKENING:
                if (!part.FindModelAnimators("Waking")[0].isPlaying)
                {
                    AdvanceAnimationTo(part.FindModelAnimators("Waking")[0], "Waking", 1, 100);

                    state     = State.AWAKE;
                    lastBlink = lastAction = Time.time;
                }
                break;

            case State.AWAKE:
                if (!part.FindModelAnimators("Blink")[0].isPlaying)
                {
                    if ((UnityEngine.Random.Range(0, 10.0F / (HighLogic.LoadedSceneIsEditor ? Time.deltaTime : TimeWarp.deltaTime)) < (Time.time - lastBlink)))
                    {
                        part.FindModelAnimators("Blink")[0].Play("Blink");
                        lastBlink = Time.time;
                    }
                    GameObject cam    = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.editorCamera.gameObject : FlightCamera.fetch.gameObject;
                    Vector3    target = (cam.transform.position - part.transform.position).normalized;
                    if (core.attitude.enabled)
                    {
                        target     = core.attitude.attitudeGetReferenceRotation(core.attitude.attitudeReference) * core.attitude.attitudeTarget * Quaternion.Euler(90, 0, 0) * Vector3.up;
                        lastAction = Time.time;
                    }
                    Vector3 localTarget = part.transform.InverseTransformDirection(target);
                    Vector2 polarTarget = CartesianToPolar(localTarget);
                    if (Mathfx.Approx(polarTarget.x, -90, 1) || Mathfx.Approx(polarTarget.x, 90, 1))
                    {
                        polarTarget.y = eye_base.localEulerAngles.z + 90;
                    }
                    if ((!HighLogic.LoadedSceneIsEditor && (Time.time - lastAction > 30)))
                    {
                        if (Mathfx.Approx(eye_base.localEulerAngles.z, 0, 1) && Mathfx.Approx(eye_ball.localEulerAngles.x, 0, 1))
                        {
                            state = State.SLEEPING;
                            part.FindModelAnimators("Sleeping")[0].Play("Sleeping");
                        }
                        else
                        {
                            polarTarget = new Vector2(-90, 90);
                        }
                    }
                    if (afx != null && afx.FxScalar > 0)
                    {
                        polarTarget = new Vector2(90, 90);
                    }
                    eye_base.localEulerAngles = new Vector3(0, 0, Mathf.MoveTowardsAngle(eye_base.localEulerAngles.z, polarTarget.y - 90, 360 * Time.deltaTime));
                    eye_ball.localRotation    = Quaternion.RotateTowards(eye_ball.localRotation, Quaternion.Euler(polarTarget.x + 90, 0, 0), 360 * Time.deltaTime);
                }
                break;

            case State.SLEEPING:
                if (!part.FindModelAnimators("Sleeping")[0].isPlaying)
                {
                    AdvanceAnimationTo(part.FindModelAnimators("Sleeping")[0], "Sleeping", 1, 100);

                    state = State.OFF;
                }
                break;

            default:
                break;
            }
        }
        void Update()
        {
            vessel = FlightGlobals.ActiveVessel;

            if (vessel == null || vessel.isEVA || !HighLogic.LoadedSceneIsFlight)
            {
                return;
            }

            //grab the data we need
            surfSpeed          = (float)vessel.srfSpeed;
            atmDensity         = (float)vessel.atmDensity;
            vesselMass         = vessel.GetTotalMass();
            vesselRot          = (float)Math.Sqrt(Math.Pow(vessel.angularVelocity.x, 2) + Math.Pow(vessel.angularVelocity.y, 2) + Math.Pow(vessel.angularVelocity.z, 2));
            vesselAcceleration = (float)Math.Sqrt(Math.Pow(vessel.acceleration.x, 2) + Math.Pow(vessel.acceleration.y, 2) + Math.Pow(vessel.acceleration.z, 2)) * 0.1f;
            vResist            = (atmDensity * surfSpeed * 0.01f) * vesselAcceleration;



            if (aeroFx == null)
            {
                GameObject fx = GameObject.Find("FXLogic");
                if (fx != null)
                {
                    aeroFx = fx.GetComponent <AerodynamicsFX>();
                }
            }

            if ((aeroFx != null) && (aeroFx.FxScalar > 0.01))
            {
                if (aeroFx.fxLight.color.b < 0.12f)
                {
                    burnDownTime = atmBurnDowntimes[0];
                }

                if (aeroFx.fxLight.color.b > 0.20f)
                {
                    if (aeroFx.FxScalar > 0.1)
                    {
                        vResist += (aeroFx.FxScalar * 2);
                    }
                }
            }

            if (burnDownTime > 0)
            {
                vResist += (aeroFx.FxScalar * burnDownTime * reEntryMultiplier);

                burnDownTime -= Time.deltaTime;
            }

            //thickeratmosphericsound in thicker atmospheres
            if (atmDensity > 0)
            {
                float airPressure = 1f / atmDensity;
                atmosphereGroup.audio.pitch = Mathf.Clamp(airPressure, 0, 1.5f);
            }

            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleEnginesFX"))
                    {
                        ModuleEnginesFX e = module as ModuleEnginesFX;
                        if (e != null && e.isOperational)
                        {
                            engineThrust += (e.finalThrust);
                        }
                        if (engineThrust > 0)
                        {
                            doEngineThrust = true;
                        }
                    }
                    else if (module.moduleName.Contains("ModuleEngine"))
                    {
                        ModuleEngines e = module as ModuleEngines;
                        if (e != null && e.isOperational)
                        {
                            engineThrust += (e.finalThrust);
                        }

                        if (engineThrust > 0)
                        {
                            doEngineThrust = true;
                        }
                    }
                }
            }

            if (engineThrust > 0 && doEngineThrust == true)
            {
                engineMicro = engineThrust / 1000f;
                engineAccel = Mathf.Abs(((engineThrust / vesselMass) * 0.1f) - vesselAcceleration) + engineMicro;
            }
            else if (engineThrust <= 0)
            {
                doEngineThrust = false;
            }

            vResist += engineAccel;

            vResist *= resistMultiplier;

            bool isCrewed = false;

            foreach (Part part in vessel.parts)
            {
                if (part.protoModuleCrew.Count >= 1)
                {
                    isCrewed = true;
                }
            }

            if (!gamePaused)
            {
                if (isCrewed && !MapView.MapIsEnabled && (onlyIVA == false || InternalCamera.Instance.isActive))
                {
                    //wind and pressure?
                    if (surfSpeed > 10 || vesselRot > 1.5f)
                    {
                        SoundFX(atmosphereGroup, ((atmDensity * surfSpeed - 10f) / 80f) + ((vesselRot - 1.5f) / 7.0f * atmDensity), aVolCtrl, 90f, true);
                    }
                    else
                    {
                        SoundFX(atmosphereGroup, false);
                    }

                    //dynamics
                    if (vResist > 0.5)
                    {
                        SoundFX(smallRattlesGroup, (vResist - 0.5f) / 4f, rVolCtrl, 90f, true);
                    }
                    else
                    {
                        SoundFX(smallRattlesGroup, false);
                    }
                    if (vResist > 0.8 || vesselRot > 1.5f)
                    {
                        SoundFX(vibrationsGroup, ((vResist - 0.8f) / 2f) + ((vesselRot - 1.5f) / 6f), vVolCtrl, 35f, true);
                    }
                    else
                    {
                        SoundFX(vibrationsGroup, false);
                    }
                    if (vResist > 1 || vesselRot > 2.0f)
                    {
                        SoundFX(rumbleGroup, ((vResist - 1f) / 2f) + ((vesselRot - 2.0f) / 6f), rmVolCtrl, 180f, true);
                    }
                    else
                    {
                        SoundFX(rumbleGroup, false);
                    }
                    if (vResist > 4.0)
                    {
                        SoundFX(bigRattlesGroup, (vResist - 5f) / 4f, rVolCtrl, 90f, true);
                    }
                    else
                    {
                        SoundFX(bigRattlesGroup, false);
                    }
                    if (vResist > 8.0)
                    {
                        SoundFX(stressBigGroup, (vResist - 6f) / 6f, sVolCtrl, 90f, true);
                    }
                    else
                    {
                        SoundFX(stressBigGroup, false);
                    }

                    if (dockTime > 0)
                    {
                        if (ifUndocking)
                        {
                            SoundFX(undockedGroup, 1f, 1f, 45f, true);
                        }
                        if (!ifUndocking)
                        {
                            SoundFX(dockedGroup, 1f, 1f, 45f, true);
                        }

                        dockTime -= Time.deltaTime;
                    }

                    if (vResist > 1.8)
                    {
                        counter += Time.deltaTime;
                        if (counter > 0.26f)
                        {
                            counter = 1;
                        }
                        if (counter < 0.25f)
                        {
                            if (vResist > 2.0f && vResist < 5.0)
                            {
                                SoundFX(thumpLowGroup, (vResist - 2.0f) / 3f, tVolCtrl, 180f, true);
                            }
                            if (vResist > 4.0f && vResist < 8.0)
                            {
                                SoundFX(thumpHeavyGroup, (vResist - 4.0f) / 4f, tVolCtrl, 180f, true);
                            }
                        }
                    }
                    else
                    {
                        counter = 0;
                    }
                }
                else
                {
                    SoundFX(atmosphereGroup, false);
                    SoundFX(smallRattlesGroup, false);
                    SoundFX(vibrationsGroup, false);
                    SoundFX(bigRattlesGroup, false);
                    SoundFX(rumbleGroup, false);
                    SoundFX(stressBigGroup, false);
                }
            }
            else
            {
                SoundFX(atmosphereGroup, false);
                SoundFX(smallRattlesGroup, false);
                SoundFX(vibrationsGroup, false);
                SoundFX(bigRattlesGroup, false);
                SoundFX(rumbleGroup, false);
                SoundFX(stressBigGroup, false);
            }

            engineMicro  = 0;
            engineThrust = 0;
            engineAccel  = 0;
        }
예제 #12
0
        public void Update()
        {
            Vessel vessel = FlightGlobals.ActiveVessel;             // easier to use vessel

            // safety check
            if (vessel == null || !HighLogic.LoadedSceneIsFlight)
            {
                return;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // atmospheric shake
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // up the shake based on atmopshereic density and surface speed
            float spdDensity = (float)(vessel.atmDensity) * (float)FlightGlobals.ship_srfSpeed;

            // limit here, mainly for space planes
            spdDensity = Mathf.Clamp(spdDensity, 0, maxSpdDensityEarly);

            // exagerate shake if semideployed, dampen if deployed
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleParachute"))
                    {
                        ModuleParachute p = module as ModuleParachute;

                        if (p.deploymentState == ModuleParachute.deploymentStates.SEMIDEPLOYED && !vessel.LandedOrSplashed)
                        {
                            spdDensity *= 1.25f;
                        }

                        if (p.deploymentState == ModuleParachute.deploymentStates.DEPLOYED && !vessel.LandedOrSplashed)
                        {
                            spdDensity *= 0.75f;
                        }
                    }
                    // RealChute Support, reworked to be compatible with RealChute v1.2
                    if (module.moduleName.Contains("RealChuteModule"))
                    {
                        PartModule p          = part.Modules["RealChuteModule"];
                        Type       pType      = p.GetType();
                        object     parachutes = pType.GetField("parachutes").GetValue(p);
                        foreach (object parachute in (parachutes as IEnumerable))
                        {
                            Type cType = parachute.GetType();
                            if (cType.GetField("depState").GetValue(parachute) == "PREDEPLOYED")
                            {
                                spdDensity *= 1.25f;
                            }
                            if ((cType.GetField("depState").GetValue(parachute) == "DEPLOYED") || (cType.GetField("depState").GetValue(parachute) == "LOWDEPLOYED"))
                            {
                                spdDensity *= 0.75f;
                            }
                        }
                    }
                }
            }

            // lifted from DRE (thanks r4m0n), gets the mach / reentry fx
            if (afx == null)
            {
                GameObject fx = GameObject.Find("FXLogic");
                if (fx != null)
                {
                    afx = fx.GetComponent <AerodynamicsFX>();
                }
            }

            // sirhaxington special: use weird values I found to determine if mach or reentry, there has to be a better way...
            if ((afx != null) && (afx.FxScalar > 0.01))
            {
                // hack, whatever the .b color value is, always is this for re-entry, .11 something
                if (afx.fxLight.color.b < 0.12f)
                {
                    burnDownTime = atmoBurnDownTimes[0];
                }

                // hack, whatever the .b color value is, always is this for mach fx, .21 something
                if (afx.fxLight.color.b > 0.20f)
                {
                    // since we * 10, only do this if it's going to increase...
                    if (afx.FxScalar > 0.1)
                    {
                        spdDensity *= (afx.FxScalar * 10);
                    }
                }
            }

            // ease back into normal atmophere from re-entry
            if (burnDownTime > 0)
            {
                spdDensity   *= (afx.FxScalar * burnDownTime * 1000);
                burnDownTime -= Time.deltaTime;
            }

            // dont go too crazy...
            spdDensity = Mathf.Clamp(spdDensity, 0, maxSpdDensity);

            if (!vessel.isEVA)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * spdDensity) / 500000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, (UnityEngine.Random.Range(-0.1f, 0.1f) * spdDensity) / 5000), shakeRot);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // parachute open shake
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int chuteCheck = 0;                                 // re-do this every frame, check against previous frame to see if chute opened

            // a chute has popped...
            // Note: Don't need to do this with realChutes as they tend to open slow anyway
            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleParachute"))
                    {
                        ModuleParachute p = module as ModuleParachute;

                        if (p.deploymentState != ModuleParachute.deploymentStates.DEPLOYED)
                        {
                            chuteCheck++;
                        }
                    }
                }
            }

            // check against previous frames' chutes, then prep shake event
            if (chuteCheck < totalUndeployedChutes)
            {
                doParaFull    = true;
                paraShakeTime = paraShakeTimes[0];
            }

            // set this at end of check for next frame
            totalUndeployedChutes = chuteCheck;

            // do the parachute pop shake
            if (paraShakeTime > 0 && doParaFull)
            {
                shakeAmt       = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 500, shakeAmt);
                shakeRot       = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.5f, 0.5f)), shakeRot);
                paraShakeTime -= Time.deltaTime;
            }
            else if (paraShakeTime <= 0)
            {
                doParaFull = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // decoupler shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // total is grabbed from event handler
            if (ejectionForceTotal > 0)
            {
                // playing around with set shake timers, not sure if I like this way but it works for now
                if (ejectionForceTotal <= 15)
                {
                    decoupleShakeTime = decoupleShakeTimes[0];
                }
                else if (ejectionForceTotal <= 250)
                {
                    decoupleShakeTime = decoupleShakeTimes[1];
                }
                else if (ejectionForceTotal <= 500)
                {
                    decoupleShakeTime = decoupleShakeTimes[2];
                }
                else if (ejectionForceTotal <= 1000)
                {
                    decoupleShakeTime = decoupleShakeTimes[3];
                }
                else
                {
                    decoupleShakeTime = decoupleShakeTimes[4];
                }

                decoupleShakeForce = ejectionForceTotal;

                doDecoupleShake    = true;
                ejectionForceTotal = 0;
            }

            // do the decoupler shake
            if (decoupleShakeTime > 0 && doDecoupleShake)
            {
                shakeAmt           = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere * decoupleShakeForce / 500000, shakeAmt);
                shakeRot           = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.5f, 0.5f)), shakeRot);
                decoupleShakeTime -= Time.deltaTime;
            }
            else if (decoupleShakeTime <= 0)
            {
                doDecoupleShake = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // docking shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // do the dock shake...we set the time from the handler, no need for other checks
            if (dockShakeTime > 0)
            {
                shakeAmt       = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 1000, shakeAmt);
                shakeRot       = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.07f, 0.07f)), shakeRot);
                dockShakeTime -= Time.deltaTime;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // launch clamp shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int clampCheck = 0;

            // a clamp has detached...
            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("LaunchClamp"))
                    {
                        LaunchClamp lc = module as LaunchClamp;

                        if (lc.enabled)
                        {
                            clampCheck++;
                        }
                    }
                }
            }

            // check against previous frames' chutes, then prep shake event
            if (clampCheck < totalClampedClamps)
            {
                doClamp        = true;
                clampShakeTime = clampShakeTimes[0];
            }

            // set this at end of check for next frame
            totalClampedClamps = clampCheck;

            // do the parachute pop shake
            if (clampShakeTime > 0 && doClamp)
            {
                shakeAmt        = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 500, shakeAmt);
                shakeRot        = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.7f, 0.7f)), shakeRot);
                clampShakeTime -= Time.deltaTime;
            }
            else if (clampShakeTime <= 0)
            {
                doClamp = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // engine shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // check both engine types (rapier uses ModuleEnginesFX, most use ModuleEngines) then base shake on thrust amount
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleEnginesFX"))
                    {
                        ModuleEnginesFX e = module as ModuleEnginesFX;

                        if (e.isOperational)
                        {
                            float solidScalar = 1.0f;            // scale up SRBs

                            if (e.propellants.Count > 0)
                            {
                                foreach (Propellant p in e.propellants)
                                {
                                    if (p.name == "SolidFuel")
                                    {
                                        solidScalar = 2.5f;
                                    }
                                }
                            }
                            engineThrustTotal += (e.finalThrust * solidScalar);
                        }

                        if (engineThrustTotal > 0)
                        {
                            doEngineShake = true;
                        }
                    }
                    else if (module.moduleName.Contains("ModuleEngines"))
                    {
                        ModuleEngines e = module as ModuleEngines;

                        if (e.isOperational)
                        {
                            float typeScalar = 1.0f;            // scale up SRBs, down jets

                            if (e.propellants.Count > 0)
                            {
                                foreach (Propellant p in e.propellants)
                                {
                                    if (p.name == "SolidFuel")
                                    {
                                        typeScalar = 2.5f;
                                    }
                                    else if (p.name == "IntakeAir")
                                    {
                                        typeScalar = 0.01f;
                                    }
                                }
                            }
                            engineThrustTotal += (e.finalThrust * typeScalar);
                        }

                        if (engineThrustTotal > 0)
                        {
                            doEngineShake = true;
                        }
                    }

                    // don't go too crazy...
                    engineThrustTotal = Mathf.Clamp(engineThrustTotal, 0, maxEngineForce);
                }
            }

            // do engine shake...
            if (engineThrustTotal > 0 && doEngineShake)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * (engineThrustTotal / 1000)) / 800, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.8f, 0.8f) * (engineThrustTotal / 1000)), shakeRot);
            }
            else if (engineThrustTotal <= 0)
            {
                doEngineShake = false;
            }

            // reset every frame
            engineThrustTotal = 0;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // nearby collision shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // do the collision shake...we set the time from the handler, no need for other checks
            if (collisionShakeTime > 0)
            {
                shakeAmt            = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 50, shakeAmt);
                shakeRot            = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-1.5f, 1.5f)), shakeRot);
                collisionShakeTime -= Time.deltaTime;
            }

            // reset for next frame, use negative since we're looking for distance now
            collisionClosest = -1;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // rover ground shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            float spdRover = (float)FlightGlobals.ship_srfSpeed;

            doRover = false;
            float roverScalar = 1.0f;

            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleWheel"))
                    {
                        if (part.GroundContact)
                        {
                            if (vessel.landedAt.Length == 0 || vessel.landedAt.ToString() == "KSC")
                            {
                                roverScalar = 2.0f;
                            }
                            // maybe later, do biome specific shakes
                            //CBAttributeMap currentBiome = vessel.mainBody.BiomeMap;
                            //print(currentBiome.GetAtt(vessel.latitude * Mathf.Deg2Rad, vessel.longitude * Mathf.Deg2Rad).name);
                            //print(currentBiome.ToString());

                            doRover = true;
                        }
                    }
                    if (module.moduleName.Contains("ModuleLandingGear"))
                    {
                        if (part.Landed)
                        {
                            if (vessel.landedAt.Length == 0 || vessel.landedAt.ToString() == "KSC")         // basically, in and around KSC
                            {
                                roverScalar = 2.0f;
                            }

                            doRover = true;
                        }
                    }
                }
            }

            spdRover *= roverScalar;

            // dont go too crazy...
            spdRover = Mathf.Clamp(spdRover, 0, maxSpdRover);

            if (doRover && !vessel.isEVA)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * spdRover) / 50000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, (UnityEngine.Random.Range(-0.1f, 0.1f) * spdRover) / 500), shakeRot);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // landing shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // note, parts that break off may throw this off
            int landedCurParts = 0;

            foreach (Part part in vessel.Parts)
            {
                if (part.GroundContact || part.WaterContact)
                {
                    landedCurParts++;
                }
            }

            // if more parts are touching the ground this frame...
            if (landedCurParts > landedPrevParts)
            {
                doLanded = true;

                // do I need horizontal surface speed as well? hmmm...
                landedShakeForce = landedPrevSrfSpd;

                if (landedShakeForce <= 0.5)
                {
                    landedShakeTime = landedShakeTimes[0];
                }
                else if (landedShakeForce <= 1.5)
                {
                    landedShakeTime = landedShakeTimes[1];
                }
                else if (landedShakeForce <= 3.0)
                {
                    landedShakeTime = landedShakeTimes[2];
                }
                else if (landedShakeForce <= 5.0)
                {
                    landedShakeTime = landedShakeTimes[3];
                }
                else
                {
                    landedShakeTime = landedShakeTimes[4];
                }

                if (doRover)
                {
                    landedShakeForce /= 2;
                }

                landedShakeForce = Mathf.Clamp(landedShakeForce, 0, maxLandedForce);
            }

            // set the current parts for the next frame
            landedPrevParts = landedCurParts;

            // do the landing / touching ground / water shake
            if (doLanded && !vessel.isEVA)
            {
                if (landedShakeTime > 0)
                {
                    shakeAmt         = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * landedShakeForce) / 3600, shakeAmt);
                    shakeRot         = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.1f, 0.1f) * landedShakeForce), shakeRot);
                    landedShakeTime -= Time.deltaTime;
                }
                else
                {
                    doLanded = false;
                }
            }

            // set the speed for the next frame
            landedPrevSrfSpd = (float)FlightGlobals.ActiveVessel.srfSpeed;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // EVA Shakes (under construction)
            //
            // to do: polish shakes (check on a few planets), rotation add back in
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            if (vessel.isEVA)
            {
                KerbalEVA eva = (KerbalEVA)vessel.rootPart.Modules["KerbalEVA"];

                // if an anim has changed
                if (eva.fsm.currentStateName != evaAnimState)
                {
                    //print(evaSrfSpedPrev);
                    if (eva.fsm.currentStateName == "Landing")                              // standard landing from a jump / RCS
                    {
                        evaShakeTime       = evaShakeTimes[2];
                        evaAnimShakeAmount = (int)(45000 / evaSrfSpedPrev);
                    }
                    else if (eva.fsm.currentStateName == "Ragdoll")                         // we landed too hard / jumped and landed at an odd angle
                    {
                        evaShakeTime       = evaShakeTimes[5];
                        evaAnimShakeAmount = (int)(8000 / evaSrfSpedPrev);
                    }
                    else if (eva.fsm.currentStateName == "Low G Bound (Grounded - FPS)")    // each step on a low g world should be felt
                    {
                        evaShakeTime       = evaShakeTimes[2];
                        evaAnimShakeAmount = (int)(50000);
                    }
                    else if (eva.fsm.currentStateName == "Ladder (Acquire)")                 // feel the grab a bit more
                    {
                        evaShakeTime       = evaShakeTimes[5];
                        evaAnimShakeAmount = (int)(1000000);
                    }
                    evaAnimState = eva.fsm.currentStateName;
                    //print(evaAnimState);
                }
                else if (evaAnimState == "Ragdoll" && vessel.Landed && evaShakeTime <= 0)    // when ragging and sliding along the surface, keep shaking
                {
                    evaShakeTime       = evaShakeTimes[5];
                    evaAnimShakeAmount = (int)(8000 / evaSrfSpedPrev);
                }
                else if (evaAnimState == "Ladder (Acquire)" && evaShakeTime >= 0)           // when ragging and sliding along the surface or falling, update shaking
                {
                    if (evaShakeTime < 0.3)
                    {
                        evaAnimShakeAmount = (int)(4000);
                    }
                }

                // update shake based on timers
                if (evaShakeTime > 0)
                {
                    shakeAmt      = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / evaAnimShakeAmount, shakeAmt);
                    evaShakeTime -= Time.deltaTime;
                }

                // RCS Cam Shake
                if (Math.Round(eva.Fuel, 3) != Math.Round(evaFuel, 3))
                {
                    evaFuel  = eva.Fuel;
                    shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / evaRCSShakeAmount, shakeAmt);
                    Math.Round(eva.Fuel, 3);
                }

                // grab frame two behind to test against
                evaSrfSpedPrev = evaSrfSped;
                evaSrfSped     = (float)vessel.srfSpeed;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // DO THE HARLEMSHAKE! o/\o
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Set isCrewed to true if not unmanned, used to remove shake in control room when using ProbeControlRoom mod
            bool isCrewed = false;

            foreach (Part part in vessel.Parts)
            {
                if (part.protoModuleCrew.Count >= 1)
                {
                    isCrewed = true;
                }
            }

            // hopefully we've picked the largest values... also, don't shake while paused, looks dumb
            if (InternalCamera.Instance != null)
            {
                if (!gamePaused && InternalCamera.Instance.isActive && isCrewed) // isCrewed for shake only if not in control room
                {
                    InternalCamera.Instance.camera.transform.localPosition  = shakeAmt;
                    InternalCamera.Instance.camera.transform.localRotation *= shakeRot;
                }
            }


            // for a different first person EVA mod...
            bool FPEVAMod = false;

            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("EVACamera"))
                    {
                        FPEVAMod = true;
                    }
                }
            }

            // rotation is wonky in EVA, skip
            if (vessel.isEVA && FlightCamera.fetch.minDistance == 0.01f && FlightCamera.fetch.maxDistance == 0.01f)
            {
                if (shakeAmt.x != 0 && shakeAmt.y != 0 && shakeAmt.z != 0)
                {
                    FlightCamera.fetch.transform.localPosition += shakeAmt;
                }
            }
            else if (vessel.isEVA && FPEVAMod)
            {
                FlightCamera.fetch.transform.localPosition += (shakeAmt * 1000);
            }

            // reset the shake vals every frame and start over...
            shakeAmt = new Vector3(0.0f, 0.0f, 0.0f);
            shakeRot = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f);
        }
예제 #13
0
        public void Update()
        {
            if (Input.GetKeyDown(KeyCode.R) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.D))
            {
                debugging = !debugging;
            }

            if (FlightGlobals.ready && (FlightGlobals.ActiveVessel != null))
            {
                Ray ray = new Ray();

                if (afx == null)
                {
                    GameObject fx = GameObject.Find("FXLogic");
                    if (fx != null)
                    {
                        afx = fx.GetComponent <AerodynamicsFX>();
                    }
                }

                foreach (var vessel in FlightGlobals.Vessels)
                {
                    if (vessel.packed)
                    {
                        continue;
                    }

                    float atmDensity = (float)FlightGlobals.getAtmDensity(
                        FlightGlobals.getStaticPressure(vessel.findWorldCenterOfMass()));

                    if (atmDensity < 0.0001f)
                    {
                        continue;
                    }

                    float airspeed = (float)vessel.srf_velocity.magnitude;

                    reentryTemperature = ReentryTemperature(airspeed, atmDensity);

                    if (heatEnabled && (afx != null) && afx.FxScalar > 0)
                    {
                        foreach (Part p in vessel.Parts)
                        {
                            ray.direction = (p.Rigidbody.GetPointVelocity(p.transform.position) + Krakensbane.GetFrameVelocityV3f() - Krakensbane.GetLastCorrection() * TimeWarp.fixedDeltaTime).normalized;
                            ray.origin    = p.transform.position;

                            var forwardFacing = !Physics.Raycast(ray, 10);
                            p.temperature = Heating(p, forwardFacing);
                        }
                    }
                }

                if (debugging)
                {
                    maxheat = (from p in FlightGlobals.ActiveVessel.Parts
                               select p.temperature).Max();
                    maxheatfail = (from p in FlightGlobals.ActiveVessel.Parts
                                   select p.temperature / p.maxTemp).Max();
                }
            }
        }
예제 #14
0
 public void Start()
 {
     _afx = null; // clear it for this start
 }
예제 #15
0
        public void Update()
        {
            Vessel vessel = FlightGlobals.ActiveVessel;             // easier to use vessel

            // safety check
            if (vessel == null || !HighLogic.LoadedSceneIsFlight)
                return;
            
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // atmospheric shake
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // up the shake based on atmopshereic density and surface speed
            float spdDensity = (float)(vessel.atmDensity) * (float)FlightGlobals.ship_srfSpeed;

            // limit here, mainly for space planes
            spdDensity = Mathf.Clamp(spdDensity, 0, maxSpdDensityEarly);

            // exagerate shake if semideployed, dampen if deployed
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleParachute"))
                    {
                        ModuleParachute p = module as ModuleParachute;

                        if (p.deploymentState == ModuleParachute.deploymentStates.SEMIDEPLOYED && !vessel.LandedOrSplashed)
                            spdDensity *= 1.25f;

                        if (p.deploymentState == ModuleParachute.deploymentStates.DEPLOYED && !vessel.LandedOrSplashed)
                            spdDensity *= 0.75f;
                    }
                    // RealChute Support, reworked to be compatible with RealChute v1.2
                    if (module.moduleName.Contains("RealChuteModule"))
                    {
                        PartModule p = part.Modules["RealChuteModule"];
                        Type pType = p.GetType();
                        object parachutes = pType.GetField("parachutes").GetValue(p);
                        foreach (object parachute in (parachutes as IEnumerable))
                        {
                            Type cType = parachute.GetType();							
                            if (cType.GetField("depState").GetValue(parachute) == "PREDEPLOYED")
                                spdDensity *= 1.25f;
                            if ((cType.GetField("depState").GetValue(parachute) == "DEPLOYED") || (cType.GetField("depState").GetValue(parachute) == "LOWDEPLOYED"))
                                spdDensity *= 0.75f;
                        }
                    }
                }
            }

            // lifted from DRE (thanks r4m0n), gets the mach / reentry fx
            if (afx == null)
            {
                GameObject fx = GameObject.Find("FXLogic");
                if (fx != null)
                {
                    afx = fx.GetComponent<AerodynamicsFX>();
                }
            }

            // sirhaxington special: use weird values I found to determine if mach or reentry, there has to be a better way...
            if ((afx != null) && (afx.FxScalar > 0.01))
            {
                // hack, whatever the .b color value is, always is this for re-entry, .11 something
                if (afx.fxLight.color.b < 0.12f)
                {
                    burnDownTime = atmoBurnDownTimes[0];
                }

                // hack, whatever the .b color value is, always is this for mach fx, .21 something
                if (afx.fxLight.color.b > 0.20f)
                {
                    // since we * 10, only do this if it's going to increase...
                    if (afx.FxScalar > 0.1)
                        spdDensity *= (afx.FxScalar * 10);
                }
            }

            // ease back into normal atmophere from re-entry
            if (burnDownTime > 0)
            {
                spdDensity *= (afx.FxScalar * burnDownTime * 1000);
                burnDownTime -= Time.deltaTime;
            }

            // dont go too crazy...
            spdDensity = Mathf.Clamp(spdDensity, 0, maxSpdDensity);

            if (!vessel.isEVA)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * spdDensity) / 500000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, (UnityEngine.Random.Range(-0.1f, 0.1f) * spdDensity) / 5000), shakeRot);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // parachute open shake
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int chuteCheck = 0;                                 // re-do this every frame, check against previous frame to see if chute opened

            // a chute has popped...
            // Note: Don't need to do this with realChutes as they tend to open slow anyway
            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleParachute"))
                    {
                        ModuleParachute p = module as ModuleParachute;

                        if (p.deploymentState != ModuleParachute.deploymentStates.DEPLOYED)
                            chuteCheck++;
                    }
                }
            }

            // check against previous frames' chutes, then prep shake event
            if (chuteCheck < totalUndeployedChutes)
            {
                doParaFull = true;
                paraShakeTime = paraShakeTimes[0];
            }

            // set this at end of check for next frame
            totalUndeployedChutes = chuteCheck;

            // do the parachute pop shake
            if (paraShakeTime > 0 && doParaFull)
            {
                shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 500, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.5f, 0.5f)), shakeRot);
                paraShakeTime -= Time.deltaTime;
            }
            else if (paraShakeTime <= 0)
                doParaFull = false;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // decoupler shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
             
            // total is grabbed from event handler
            if (ejectionForceTotal > 0)
            {
                // playing around with set shake timers, not sure if I like this way but it works for now
                if (ejectionForceTotal <= 15)
                    decoupleShakeTime = decoupleShakeTimes[0];
                else if (ejectionForceTotal <= 250)
                    decoupleShakeTime = decoupleShakeTimes[1];
                else if (ejectionForceTotal <= 500)
                    decoupleShakeTime = decoupleShakeTimes[2];
                else if (ejectionForceTotal <= 1000)
                    decoupleShakeTime = decoupleShakeTimes[3];
                else
                    decoupleShakeTime = decoupleShakeTimes[4];

                decoupleShakeForce = ejectionForceTotal;

                doDecoupleShake = true;
                ejectionForceTotal = 0;
            }

            // do the decoupler shake
            if (decoupleShakeTime > 0 && doDecoupleShake)
            {
                shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere * decoupleShakeForce / 500000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.5f, 0.5f)), shakeRot);
                decoupleShakeTime -= Time.deltaTime;
            }
            else if (decoupleShakeTime <= 0)
            {
                doDecoupleShake = false;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // docking shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // do the dock shake...we set the time from the handler, no need for other checks
            if (dockShakeTime > 0)
            {
                shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 1000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.07f, 0.07f)), shakeRot);
                dockShakeTime -= Time.deltaTime;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // launch clamp shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            int clampCheck = 0;                                 

            // a clamp has detached...
            foreach (Part part in vessel.parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("LaunchClamp"))
                    {
                        LaunchClamp lc = module as LaunchClamp;

                        if (lc.enabled)
                            clampCheck++;
                    }
                }
            }

            // check against previous frames' chutes, then prep shake event
            if (clampCheck < totalClampedClamps)
            {
                doClamp = true;
                clampShakeTime = clampShakeTimes[0];
            }

            // set this at end of check for next frame
            totalClampedClamps = clampCheck;

            // do the parachute pop shake
            if (clampShakeTime > 0 && doClamp)
            {
                shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 500, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.7f, 0.7f)), shakeRot);
                clampShakeTime -= Time.deltaTime;
            }
            else if (clampShakeTime <= 0)
                doClamp = false;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // engine shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // check both engine types (rapier uses ModuleEnginesFX, most use ModuleEngines) then base shake on thrust amount
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleEnginesFX"))
                    {
                        ModuleEnginesFX e = module as ModuleEnginesFX;

                        if (e.isOperational)
                        {
                            float solidScalar = 1.0f;            // scale up SRBs

                            if (e.propellants.Count > 0)
                            {
                                foreach (Propellant p in e.propellants)
                                {
                                    if (p.name == "SolidFuel")
                                    {
                                        solidScalar = 2.5f;
                                    }
                                }
                            }
                            engineThrustTotal += (e.finalThrust * solidScalar);
                        }
                         
                        if (engineThrustTotal > 0)
                            doEngineShake = true;
                    }
                    else if (module.moduleName.Contains("ModuleEngines"))
                    {
                        ModuleEngines e = module as ModuleEngines;

                        if (e.isOperational)
                        {
                            float typeScalar = 1.0f;            // scale up SRBs, down jets

                            if (e.propellants.Count > 0)
                            {
                                foreach (Propellant p in e.propellants)
                                {
                                    if (p.name == "SolidFuel")
                                    {
                                        typeScalar = 2.5f;
                                    }
                                    else if (p.name == "IntakeAir")
                                    {
                                        typeScalar = 0.01f;
                                    }
                                }
                            }
                            engineThrustTotal += (e.finalThrust * typeScalar);
                        }

                        if (engineThrustTotal > 0)
                            doEngineShake = true;
                    }

                    // don't go too crazy...
                    engineThrustTotal = Mathf.Clamp(engineThrustTotal, 0, maxEngineForce);
                }
            }

            // do engine shake...
            if (engineThrustTotal > 0 && doEngineShake)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * (engineThrustTotal / 1000)) / 800, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.8f, 0.8f) * (engineThrustTotal / 1000)), shakeRot);
            }
            else if (engineThrustTotal <= 0)
            {
                doEngineShake = false;            
            }

            // reset every frame
            engineThrustTotal = 0;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // nearby collision shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // do the collision shake...we set the time from the handler, no need for other checks
            if (collisionShakeTime > 0)
            {
                shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / 50, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-1.5f, 1.5f)), shakeRot);
                collisionShakeTime -= Time.deltaTime;
            }

            // reset for next frame, use negative since we're looking for distance now
            collisionClosest = -1;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // rover ground shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            float spdRover = (float)FlightGlobals.ship_srfSpeed;

            doRover = false;
            float roverScalar = 1.0f;
            foreach (Part part in vessel.Parts)
            {
                foreach (PartModule module in part.Modules)
                {
                    if (module.moduleName.Contains("ModuleWheel"))
                    {
                        if (part.GroundContact)
                        {
                            if (vessel.landedAt.Length == 0 || vessel.landedAt.ToString() == "KSC")
                            {
                                roverScalar = 2.0f;
                            }
                            // maybe later, do biome specific shakes
                            //CBAttributeMap currentBiome = vessel.mainBody.BiomeMap;
                            //print(currentBiome.GetAtt(vessel.latitude * Mathf.Deg2Rad, vessel.longitude * Mathf.Deg2Rad).name);
                            //print(currentBiome.ToString());
                            
                            doRover = true;
                        }
                    }
                    if (module.moduleName.Contains("ModuleLandingGear"))
                    {
                        if (part.Landed)
                        {
                            if (vessel.landedAt.Length == 0 || vessel.landedAt.ToString() == "KSC")         // basically, in and around KSC
                            {
                                roverScalar = 2.0f;
                            }
                        
                            doRover = true;
                        }
                    }
                }
            }

            spdRover *= roverScalar;

            // dont go too crazy...
            spdRover = Mathf.Clamp(spdRover, 0, maxSpdRover);

            if (doRover && !vessel.isEVA)
            {
                shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * spdRover) / 50000, shakeAmt);
                shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, (UnityEngine.Random.Range(-0.1f, 0.1f) * spdRover) / 500), shakeRot);
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // landing shakes
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // note, parts that break off may throw this off
            int landedCurParts = 0;
            foreach (Part part in vessel.Parts)
            {
                if (part.GroundContact || part.WaterContact)
                    landedCurParts++;
            }

            // if more parts are touching the ground this frame...
            if (landedCurParts > landedPrevParts)
            {
                doLanded = true;

                // do I need horizontal surface speed as well? hmmm...
                landedShakeForce = landedPrevSrfSpd;

                if (landedShakeForce <= 0.5)
                    landedShakeTime = landedShakeTimes[0];
                else if (landedShakeForce <= 1.5)
                    landedShakeTime = landedShakeTimes[1];
                else if (landedShakeForce <= 3.0)
                    landedShakeTime = landedShakeTimes[2];
                else if (landedShakeForce <= 5.0)
                    landedShakeTime = landedShakeTimes[3];
                else
                    landedShakeTime = landedShakeTimes[4];

                if (doRover)
                    landedShakeForce /= 2;

                landedShakeForce = Mathf.Clamp(landedShakeForce, 0, maxLandedForce);
            }

            // set the current parts for the next frame
            landedPrevParts = landedCurParts;

            // do the landing / touching ground / water shake
            if (doLanded && !vessel.isEVA)
            {
                if (landedShakeTime > 0)
                {
                    shakeAmt = ReturnLargerAmt((UnityEngine.Random.insideUnitSphere * landedShakeForce) / 3600, shakeAmt);
                    shakeRot = ReturnLargerRot(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-0.1f, 0.1f) * landedShakeForce), shakeRot);
                    landedShakeTime -= Time.deltaTime;
                }
                else
                {
                    doLanded = false;
                }
            }

            // set the speed for the next frame
            landedPrevSrfSpd = (float)FlightGlobals.ActiveVessel.srfSpeed;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // EVA Shakes (under construction)
            //
            // to do: polish shakes (check on a few planets), rotation add back in
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            if (vessel.isEVA)
            {
                KerbalEVA eva = (KerbalEVA)vessel.rootPart.Modules["KerbalEVA"];

                // if an anim has changed
                if (eva.fsm.currentStateName != evaAnimState)
                {
                    //print(evaSrfSpedPrev);
                    if (eva.fsm.currentStateName == "Landing")                              // standard landing from a jump / RCS
                    {
                        evaShakeTime = evaShakeTimes[2];
                        evaAnimShakeAmount = (int)(45000 / evaSrfSpedPrev);

                    }
                    else if (eva.fsm.currentStateName == "Ragdoll")                         // we landed too hard / jumped and landed at an odd angle
                    {
                        evaShakeTime = evaShakeTimes[5];
                        evaAnimShakeAmount = (int)(8000 / evaSrfSpedPrev);
                    }
                    else if (eva.fsm.currentStateName == "Low G Bound (Grounded - FPS)")    // each step on a low g world should be felt
                    {
                        evaShakeTime = evaShakeTimes[2];
                        evaAnimShakeAmount = (int)(50000);
                    }
                    else if (eva.fsm.currentStateName == "Ladder (Acquire)")                 // feel the grab a bit more
                    {
                        evaShakeTime = evaShakeTimes[5];
                        evaAnimShakeAmount = (int)(1000000);
                    }
                    evaAnimState = eva.fsm.currentStateName;
                    //print(evaAnimState);
                }
                else if (evaAnimState == "Ragdoll" && vessel.Landed && evaShakeTime <= 0)    // when ragging and sliding along the surface, keep shaking
                {
                    evaShakeTime = evaShakeTimes[5];
                    evaAnimShakeAmount = (int)(8000 / evaSrfSpedPrev);
                }
                else if (evaAnimState == "Ladder (Acquire)" && evaShakeTime >= 0)           // when ragging and sliding along the surface or falling, update shaking
                {
                    if (evaShakeTime < 0.3)
                        evaAnimShakeAmount = (int)(4000);
                }

                // update shake based on timers
                if (evaShakeTime > 0)
                {
                    shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / evaAnimShakeAmount, shakeAmt);
                    evaShakeTime -= Time.deltaTime;
                }

                // RCS Cam Shake
                if (Math.Round(eva.Fuel, 3) != Math.Round(evaFuel, 3))
                {
                    evaFuel = eva.Fuel;
                    shakeAmt = ReturnLargerAmt(UnityEngine.Random.insideUnitSphere / evaRCSShakeAmount, shakeAmt);
                    Math.Round(eva.Fuel, 3);
                }

                // grab frame two behind to test against
                evaSrfSpedPrev = evaSrfSped;
                evaSrfSped     = (float)vessel.srfSpeed;                
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // DO THE HARLEMSHAKE! o/\o
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Set isCrewed to true if not unmanned, used to remove shake in control room when using ProbeControlRoom mod
            bool isCrewed = false;
            foreach (Part part in vessel.Parts)
                if (part.protoModuleCrew.Count >= 1)
                    isCrewed = true;
			
            // hopefully we've picked the largest values... also, don't shake while paused, looks dumb
            if (InternalCamera.Instance != null)
            {
                if (!gamePaused && InternalCamera.Instance.isActive && isCrewed) // isCrewed for shake only if not in control room
                {
                   InternalCamera.Instance.camera.transform.localPosition = shakeAmt;
                   InternalCamera.Instance.camera.transform.localRotation *= shakeRot;
                }
            }


            // for a different first person EVA mod...
            bool FPEVAMod = false;
            foreach (Part part in vessel.Parts)
                foreach (PartModule module in part.Modules)
                    if (module.moduleName.Contains("EVACamera"))
                        FPEVAMod = true;

            // rotation is wonky in EVA, skip
            if (vessel.isEVA && FlightCamera.fetch.minDistance == 0.01f && FlightCamera.fetch.maxDistance == 0.01f)
            {
                if (shakeAmt.x != 0 && shakeAmt.y != 0 && shakeAmt.z != 0)
                    FlightCamera.fetch.transform.localPosition += shakeAmt;
            }
            else if (vessel.isEVA && FPEVAMod)
            {
                FlightCamera.fetch.transform.localPosition += (shakeAmt * 1000);
            }

            // reset the shake vals every frame and start over...
            shakeAmt = new Vector3(0.0f, 0.0f, 0.0f);
            shakeRot = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f);
        }
 private void GetAeroFX()
 {
     GameObject fxLogicObject = GameObject.Find("FXLogic");
     if (fxLogicObject != null)
         AeroFX = fxLogicObject.GetComponent<AerodynamicsFX>();
 }