Ejemplo n.º 1
0
        void UpdatePosition()
        {
            Vector3d oceanNormal = _vessel.mainBody.GetSurfaceNVector(_vessel.latitude, _vessel.longitude);
            Vector3  newPosition = (_vessel.ReferenceTransform.position - oceanNormal * (FlightGlobals.getAltitudeAtPos(_vessel.ReferenceTransform.position) - fColliderHeight));

            _collider.rigidbody.position = newPosition;
            _collider.rigidbody.rotation = Quaternion.LookRotation(oceanNormal) * Quaternion.AngleAxis(90f, Vector3.right);
        }
Ejemplo n.º 2
0
        private void UpdateMove()
        {
            if (!MovingVessel)
            {
                EndMove();
                return;
            }
            MovingVessel.IgnoreGForces(240);

            // Lerp is animating move
            if (!_hoverChanged)
            {
                MoveHeight = Mathf.Lerp(MoveHeight, _vBounds.BottomLength + HoverHeight, 10 * Time.fixedDeltaTime);
            }
            else
            {
                double alt = MovingVessel.radarAltitude;
                // sINCE Lerp is animating move from 0 to hoverheight, we do not want this going below current altitude
                if (MoveHeight < alt)
                {
                    MoveHeight = Convert.ToSingle(alt);
                }

                MoveHeight = MovingVessel.Splashed
                  ? Mathf.Lerp(MoveHeight, _vBounds.BottomLength + _hoverAdjust, 10 * Time.fixedDeltaTime)
                  : Mathf.Lerp(MoveHeight, _vBounds.BottomLength + (MoveHeight + _hoverAdjust < 0 ? -MoveHeight : _hoverAdjust), 10 * Time.fixedDeltaTime);
            }
            MovingVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, false);

            _up = (MovingVessel.transform.position - FlightGlobals.currentMainBody.transform.position).normalized;

            Vector3 forward;

            if (MapView.MapIsEnabled)
            {
                forward = North();
            }
            else
            {
                forward = Vector3.ProjectOnPlane(MovingVessel.CoM - FlightCamera.fetch.mainCamera.transform.position, _up).normalized;
                if (Vector3.Dot(-_up, FlightCamera.fetch.mainCamera.transform.up) > 0)
                {
                    forward = Vector3.ProjectOnPlane(FlightCamera.fetch.mainCamera.transform.up, _up).normalized;
                }
            }

            Vector3 right = Vector3.Cross(_up, forward);

            Vector3 offsetDirection = Vector3.zero;
            bool    inputting       = false;

            //Altitude Adjustment
            if (GameSettings.THROTTLE_CUTOFF.GetKey())
            {
                _hoverAdjust  = 0f;
                _hoverChanged = false;
            }

            if (GameSettings.THROTTLE_UP.GetKey())
            {
                _hoverAdjust += MoveSpeed * Time.fixedDeltaTime;
                inputting     = true;
                _hoverChanged = true;
            }

            if (GameSettings.THROTTLE_DOWN.GetKey())
            {
                _hoverAdjust += -(MoveSpeed * Time.fixedDeltaTime);
                inputting     = true;
                _hoverChanged = true;
            }

            if (GameSettings.PITCH_DOWN.GetKey())
            {
                offsetDirection += (forward * MoveSpeed * Time.fixedDeltaTime);
                inputting        = true;
            }
            if (GameSettings.PITCH_UP.GetKey())
            {
                offsetDirection += (-forward * MoveSpeed * Time.fixedDeltaTime);
                inputting        = true;
            }

            if (GameSettings.YAW_RIGHT.GetKey())
            {
                offsetDirection += (right * MoveSpeed * Time.fixedDeltaTime);
                inputting        = true;
            }
            if (GameSettings.YAW_LEFT.GetKey())
            {
                offsetDirection += (-right * MoveSpeed * Time.fixedDeltaTime);
                inputting        = true;
            }

            if (GameSettings.TRANSLATE_RIGHT.GetKey())
            {
                _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.forward) * _startRotation;
                _hasRotated    = true;
            }
            else if (GameSettings.TRANSLATE_LEFT.GetKey())
            {
                _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.forward) * _startRotation;
                _hasRotated    = true;
            }

            if (GameSettings.TRANSLATE_DOWN.GetKey())
            {
                _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.right) * _startRotation;
                _hasRotated    = true;
            }
            else if (GameSettings.TRANSLATE_UP.GetKey())
            {
                _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.right) * _startRotation;
                _hasRotated    = true;
            }

            if (GameSettings.ROLL_LEFT.GetKey())
            {
                _startRotation = Quaternion.AngleAxis(RotationSpeed, MovingVessel.ReferenceTransform.up) * _startRotation;
                _hasRotated    = true;
            }
            else if (GameSettings.ROLL_RIGHT.GetKey())
            {
                _startRotation = Quaternion.AngleAxis(-RotationSpeed, MovingVessel.ReferenceTransform.up) * _startRotation;
                _hasRotated    = true;
            }

            //auto level plane
            if (GameSettings.TRANSLATE_FWD.GetKey())
            {
                Quaternion targetRot = Quaternion.LookRotation(-_up, forward);
                _startRotation = Quaternion.RotateTowards(_startRotation, targetRot, RotationSpeed * 2);
                _hasRotated    = true;
            }
            else if (GameSettings.TRANSLATE_BACK.GetKey())//auto level rocket
            {
                Quaternion targetRot = Quaternion.LookRotation(forward, _up);
                _startRotation = Quaternion.RotateTowards(_startRotation, targetRot, RotationSpeed * 2);
                _hasRotated    = true;
            }

            if (inputting)
            {
                _currMoveSpeed = Mathf.Clamp(Mathf.MoveTowards(_currMoveSpeed, MoveSpeed, MoveAccel * Time.fixedDeltaTime), 0, MoveSpeed);
            }
            else
            {
                _currMoveSpeed = 0;
            }

            Vector3 offset = offsetDirection.normalized * _currMoveSpeed;

            _currMoveVelocity = offset / Time.fixedDeltaTime;
            Vector3    vSrfPt        = MovingVessel.CoM - (MoveHeight * _up);
            bool       srfBelowWater = false;
            RaycastHit ringHit;

            bool    surfaceDetected = CapsuleCast(out ringHit);
            Vector3 finalOffset     = Vector3.zero;

            if (surfaceDetected)
            {
                if (FlightGlobals.getAltitudeAtPos(ringHit.point) < 0)
                {
                    srfBelowWater = true;
                }

                Vector3 rOffset = Vector3.Project(ringHit.point - vSrfPt, _up);
                Vector3 mOffset = (vSrfPt + offset) - MovingVessel.CoM;
                finalOffset = rOffset + mOffset + (MoveHeight * _up);
                MovingVessel.Translate(finalOffset);
            }

            PQS bodyPQS = MovingVessel.mainBody.pqsController;

            Vector3d geoCoords = WorldPositionToGeoCoords(MovingVessel.GetWorldPos3D() + (_currMoveVelocity * Time.fixedDeltaTime), MovingVessel.mainBody);
            double   lat       = geoCoords.x;
            double   lng       = geoCoords.y;

            Vector3d bodyUpVector = new Vector3d(1, 0, 0);

            bodyUpVector = QuaternionD.AngleAxis(lat, Vector3d.forward /*around Z axis*/) * bodyUpVector;
            bodyUpVector = QuaternionD.AngleAxis(lng, Vector3d.down /*around -Y axis*/) * bodyUpVector;

            double srfHeight = bodyPQS.GetSurfaceHeight(bodyUpVector);

            //double alt = srfHeight - bodyPQS.radius;
            //double rAlt = movingVessel.radarAltitude;
            //double tAlt = TrueAlt(movingVessel);
            //double pAlt = movingVessel.pqsAltitude;
            //double teralt = movingVessel.mainBody.TerrainAltitude(movingVessel.mainBody.GetLatitude(geoCoords), movingVessel.mainBody.GetLongitude(geoCoords));
            //Debug.Log ("Surface height: "+movingVessel.mainBody.pqsController.GetSurfaceHeight(up));

            if (!surfaceDetected || srfBelowWater)
            {
                Vector3 terrainPos    = MovingVessel.mainBody.position + (float)srfHeight * _up;
                Vector3 waterSrfPoint = FlightGlobals.currentMainBody.position + ((float)FlightGlobals.currentMainBody.Radius * _up);

                if (!surfaceDetected)
                {
                    MovingVessel.SetPosition(terrainPos + (MoveHeight * _up) + offset);
                }
                else
                {
                    MovingVessel.SetPosition(waterSrfPoint + (MoveHeight * _up) + offset);
                }

                //update vessel situation to splashed down:
                MovingVessel.UpdateLandedSplashed();
            }

            //fix surface rotation
            Quaternion srfRotFix = Quaternion.FromToRotation(_startingUp, _up);

            _currRotation = srfRotFix * _startRotation;
            MovingVessel.SetRotation(_currRotation);

            if (Vector3.Angle(_startingUp, _up) > 5)
            {
                _startRotation = _currRotation;
                _startingUp    = _up;
            }

            MovingVessel.SetWorldVelocity(Vector3d.zero);
            MovingVessel.angularVelocity = Vector3.zero;
            MovingVessel.angularMomentum = Vector3.zero;
        }
Ejemplo n.º 3
0
 protected bool CheckUnderwater()
 {
     return(FlightGlobals.getAltitudeAtPos(intakeTransform.position) < 0.0f && vessel.mainBody.ocean);
 }
Ejemplo n.º 4
0
 public double AtmosphericPressure()
 {
     return(FlightGlobals.getStaticPressure(vesselState.CoM));
 }
Ejemplo n.º 5
0
 public void FixedUpdate()
 {
     if (IsActivate == true)
     {
         //Landing Burn
         if (burn != null)
         {
             if (alreadyFired == false)
             {
                 if (BurnRay())
                 {
                     alreadyFired = true;
                 }
             }
             else
             {
                 if (this.vessel.situation != Vessel.Situations.LANDED || this.vessel.situation != Vessel.Situations.SPLASHED && burn.triggered)
                 {
                     foreach (Part p in this.vessel.parts)
                     {
                         if ((p.physicalSignificance == Part.PhysicalSignificance.FULL) && (p.rb != null))
                         {
                             Vector3 gee = FlightGlobals.getGeeForceAtPosition(this.vessel.transform.position);
                             p.AddForce(-gee.normalized * p.rb.mass * ((float)Math.Min(Math.Abs(this.vessel.verticalSpeed), gee.magnitude) + gee.magnitude));
                         }
                     }
                     Debug.Log(this.vessel.srf_velocity.magnitude);
                 }
             }
         }
         //Inflate Buoy
         if (buoy != null)
         {
             if (alreadyInflated == false)
             {
                 if (vessel.Splashed)
                 {
                     buoy.Inflate();
                     alreadyInflated = true;
                 }
             }
         }
         //Airbag
         if (airbag != null)
         {
             //Inflate Airbag
             if (alreadyInflatedAirBag == false)
             {
                 if (vessel.radarAltitude <= airbag.inflateAltitude)
                 {
                     airbag.Inflate();
                     alreadyInflatedAirBag = true;
                 }
             }
             //Deflate Airbag
             if (alreadyInflatedAirBag == true && alreadyDeflatedAirBag == false)
             {
                 if (vessel.Landed)
                 {
                     //Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>Landed!");
                     airbag.Deflate();
                     alreadyDeflatedAirBag = true;
                 }
                 else if (vessel.Splashed && airbag.damageAfterSplashed == true)
                 {
                     //Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>Splashed with damage");
                     airbag.Deflate();
                     alreadyDeflatedAirBag = true;
                 }
                 else if (vessel.Splashed && airbag.damageAfterSplashed == false)
                 {
                     //Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>Splashed with out damage");
                     airbag.Touchdown();
                     alreadyDeflatedAirBag = true;
                 }
             }
         }
         //Check
         if (vessel.Landed || vessel.Splashed)
         {
             Events["Deactivate"].guiActive = false;
             Events["Activate"].guiActive   = false;
             IsActivate = false;
             Debug.Log("<color=#FF8C00ff>[Comfortable Landing]</color>The vessel has landed or splashed, deactivate pre-landing mode.");
         }
     }
 }
Ejemplo n.º 6
0
        public void FixedUpdate() // FixedUpdate is also called when not activated
        {
            try
            {
                UpdateWasteheatBuffer();

                if (!HighLogic.LoadedSceneIsFlight)
                {
                    return;
                }

                if (!active)
                {
                    base.OnFixedUpdate();
                }

                effectiveRadiatorArea = EffectiveRadiatorArea;

                var external_temperature = FlightGlobals.getExternalTemperature(part.transform.position);

                wasteheatManager = getManagerForVessel(ResourceManager.FNRESOURCE_WASTEHEAT);

                // get resource bar ratio at start of frame
                wasteheatRatio = wasteheatManager.ResourceBarRatioBegin;

                if (Double.IsNaN(wasteheatRatio))
                {
                    Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in wasteheatRatio");
                    return;
                }

                var normalized_atmosphere = Math.Min(vessel.atmDensity, 1);

                maxCurrentTemperature = maxAtmosphereTemperature * Math.Max(normalized_atmosphere, 0) + maxVacuumTemperature * Math.Max(Math.Min(1 - vessel.atmDensity, 1), 0);

                radiator_temperature_temp_val = external_temperature + Math.Min((maxRadiatorTemperature - external_temperature) * Math.Sqrt(wasteheatRatio), maxCurrentTemperature - external_temperature);

                var efficiency = 1 - Math.Pow(1 - wasteheatRatio, 400);
                var delta_temp = Math.Max(radiator_temperature_temp_val - Math.Max(external_temperature * normalized_atmosphere, 2.7), 0);

                if (radiatorIsEnabled)
                {
                    if (!CheatOptions.IgnoreMaxTemperature && wasteheatRatio >= 1 && CurrentRadiatorTemperature >= maxRadiatorTemperature)
                    {
                        explode_counter++;
                        if (explode_counter > 25)
                        {
                            part.explode();
                        }
                    }
                    else
                    {
                        explode_counter = 0;
                    }

                    var thermal_power_dissip_per_second = efficiency * Math.Pow(delta_temp, 4) * GameConstants.stefan_const * effectiveRadiatorArea / 1e6;

                    if (Double.IsNaN(thermal_power_dissip_per_second))
                    {
                        Debug.LogWarning("FNRadiator: FixedUpdate Single.IsNaN detected in fixed_thermal_power_dissip");
                    }

                    radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermal_power_dissip_per_second) : 0;

                    if (Double.IsNaN(radiatedThermalPower))
                    {
                        Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in radiatedThermalPower after call consumeWasteHeat (" + thermal_power_dissip_per_second + ")");
                    }

                    instantaneous_rad_temp = Math.Max(radiator_temperature_temp_val, Math.Max(FlightGlobals.getExternalTemperature(vessel.altitude, vessel.mainBody), 2.7));

                    if (Double.IsNaN(instantaneous_rad_temp))
                    {
                        Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in instantaneous_rad_temp after reading external temperature");
                    }

                    CurrentRadiatorTemperature = instantaneous_rad_temp;

                    if (_moduleDeployableRadiator)
                    {
                        _moduleDeployableRadiator.hasPivot = pivotEnabled;
                    }
                }
                else
                {
                    double thermal_power_dissip_per_second = efficiency * Math.Pow(Math.Max(delta_temp - external_temperature, 0), 4) * GameConstants.stefan_const * effectiveRadiatorArea / 0.5e7;

                    radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermal_power_dissip_per_second) : 0;

                    instantaneous_rad_temp = Math.Max(radiator_temperature_temp_val, Math.Max(FlightGlobals.getExternalTemperature(vessel.altitude, vessel.mainBody), 2.7));

                    CurrentRadiatorTemperature = instantaneous_rad_temp;
                }

                if (vessel.atmDensity > 0)
                {
                    var pressure = vessel.atmDensity;
                    dynamic_pressure = 0.60205 * pressure * vessel.srf_velocity.sqrMagnitude / 101325;
                    pressure        += dynamic_pressure;

                    var splashBonus           = Math.Max(part.submergedPortion * 10, 1);
                    var convection_delta_temp = Math.Max(0, CurrentRadiatorTemperature - external_temperature);
                    var conv_power_dissip     = efficiency * pressure * convection_delta_temp * effectiveRadiatorArea * 0.001 * convectiveBonus * splashBonus;

                    if (!radiatorIsEnabled)
                    {
                        conv_power_dissip = conv_power_dissip / 2;
                    }

                    convectedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(conv_power_dissip) : 0;

                    if (update_count == 6)
                    {
                        DeployMentControl(dynamic_pressure);
                    }
                }
                else
                {
                    convectedThermalPower = 0;

                    if (!radiatorIsEnabled && isAutomated && canRadiateHeat && showControls && update_count == 6)
                    {
                        Debug.Log("[KSPI] - FixedUpdate Automated Deplotment ");
                        Deploy();
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSPI] - FNRadiator.FixedUpdate" + e.Message);
            }
        }
        public override void Drive(FlightCtrlState s) // TODO put the brake in when running out of power to prevent nighttime solar failures on hills, or atleast try to
        {                                             // TODO make distance calculation for 'reached' determination consider the rover and waypoint on sealevel to prevent height differences from messing it up -- should be done now?
            if (orbit.referenceBody != lastBody)
            {
                WaypointIndex = -1; Waypoints.Clear();
            }
            MechJebWaypoint wp = (WaypointIndex > -1 && WaypointIndex < Waypoints.Count ? Waypoints[WaypointIndex] : null);

            var brake = vessel.ActionGroups[KSPActionGroup.Brakes];             // keep brakes locked if they are

            curSpeed = Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward);

            CalculateTraction();
            speedIntAcc = speedPID.intAccum;

            if (wp != null && wp.Body == orbit.referenceBody)
            {
                if (ControlHeading)
                {
                    heading.val = Math.Round(HeadingToPos(vessel.CoM, wp.Position), 1);
                }
                if (ControlSpeed)
                {
                    var nextWP   = (WaypointIndex < Waypoints.Count - 1 ? Waypoints[WaypointIndex + 1] : (LoopWaypoints ? Waypoints[0] : null));
                    var distance = Vector3.Distance(vessel.CoM, wp.Position);
                    if (wp.Target != null)
                    {
                        distance += (float)(wp.Target.srfSpeed * curSpeed) / 2;
                    }
                    // var maxSpeed = (wp.MaxSpeed > 0 ? Math.Min((float)speed, wp.MaxSpeed) : speed); // use waypoints maxSpeed if set and smaller than set the speed or just stick with the set speed
                    var maxSpeed = (wp.MaxSpeed > 0 ? wp.MaxSpeed : speed);                     // speed used to go towards the waypoint, using the waypoints maxSpeed if set or just stick with the set speed
                    var minSpeed = (wp.MinSpeed > 0 ? wp.MinSpeed :
                                    (nextWP != null ? TurningSpeed((nextWP.MaxSpeed > 0 ? nextWP.MaxSpeed : speed), heading - HeadingToPos(wp.Position, nextWP.Position)) :
                                     (distance - wp.Radius > 50 ? turnSpeed.val : 1)));
                    minSpeed = (wp.Quicksave ? 1 : minSpeed);
                    // ^ speed used to go through the waypoint, using half the set speed or maxSpeed as minSpeed for routing waypoints (all except the last)
                    var newSpeed = Math.Min(maxSpeed, Math.Max((distance - wp.Radius) / curSpeed, minSpeed));              // brake when getting closer
                    newSpeed = (newSpeed > turnSpeed ? TurningSpeed(newSpeed, headingErr) : newSpeed);                     // reduce speed when turning a lot
//					if (LimitAcceleration) { newSpeed = curSpeed + Mathf.Clamp((float)(newSpeed - curSpeed), -1.5f, 0.5f); }
//					newSpeed = tgtSpeed + Mathf.Clamp((float)(newSpeed - tgtSpeed), -Time.deltaTime * 8f, Time.deltaTime * 2f);
                    var radius = Math.Max(wp.Radius, 10);
                    if (distance < radius)
                    {
                        if (WaypointIndex + 1 >= Waypoints.Count)                         // last waypoint
                        {
                            newSpeed = new [] { newSpeed, (distance < radius * 0.8 ? 0 : 1) }.Min();
                            // ^ limit speed so it'll only go from 1m/s to full stop when braking to prevent accidents on moons
                            if (LoopWaypoints)
                            {
                                WaypointIndex = 0;
                            }
                            else
                            {
                                newSpeed = 0;
                                brake    = true;
//								tgtSpeed.force(newSpeed);
                                if (curSpeed < brakeSpeedLimit)
                                {
                                    if (wp.Quicksave)
                                    {
                                        //if (s.mainThrottle > 0) { s.mainThrottle = 0; }
                                        if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR)
                                        {
                                            WaypointIndex  = -1;
                                            ControlHeading = ControlSpeed = false;
                                            QuickSaveLoad.QuickSave();
                                        }
                                    }
                                    else
                                    {
                                        WaypointIndex  = -1;
                                        ControlHeading = ControlSpeed = false;
                                    }
                                }
//								else {
//									Debug.Log("Is this even getting called?");
//									WaypointIndex++;
//								}
                            }
                        }
                        else
                        {
                            if (wp.Quicksave)
                            {
                                //if (s.mainThrottle > 0) { s.mainThrottle = 0; }
                                newSpeed = 0;
//								tgtSpeed.force(newSpeed);
                                if (curSpeed < brakeSpeedLimit)
                                {
                                    if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR)
                                    {
                                        WaypointIndex++;
                                        QuickSaveLoad.QuickSave();
                                    }
                                }
                            }
                            else
                            {
                                WaypointIndex++;
                            }
                        }
                    }
                    brake = brake || ((s.wheelThrottle == 0 || !vessel.isActiveVessel) && curSpeed < brakeSpeedLimit && newSpeed < brakeSpeedLimit);
                    // ^ brake if needed to prevent rolling, hopefully
                    tgtSpeed = (newSpeed >= 0 ? newSpeed : 0);
                }
            }

            if (ControlHeading)
            {
                headingPID.intAccum = Mathf.Clamp((float)headingPID.intAccum, -1, 1);

                double instantaneousHeading = vesselState.rotationVesselSurface.eulerAngles.y;
                headingErr = MuUtils.ClampDegrees180(instantaneousHeading - heading);
                if (s.wheelSteer == s.wheelSteerTrim || FlightGlobals.ActiveVessel != vessel)
                {
                    float limit = (Math.Abs(curSpeed) > turnSpeed ? Mathf.Clamp((float)((turnSpeed + 6) / Square(curSpeed)), 0.1f, 1f) : 1f);
                    // turnSpeed needs to be higher than curSpeed or it will never steer as much as it could even at 0.2m/s above it
                    // double act = headingPID.Compute(headingErr * headingErr / 10 * Math.Sign(headingErr));
                    double act = headingPID.Compute(headingErr);
                    if (traction >= tractionLimit)
                    {
                        s.wheelSteer = Mathf.Clamp((float)act, -limit, limit);
                        // prevents it from flying above a waypoint and landing with steering at max while still going fast
                    }
                }
            }

            // Brake if there is no controler (Pilot eject from seat)
            if (BrakeOnEject && vessel.GetReferenceTransformPart() == null)
            {
                s.wheelThrottle = 0;
//				vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true);
                brake = true;
            }
            else if (ControlSpeed)
            {
                speedPID.intAccum = Mathf.Clamp((float)speedPID.intAccum, -5, 5);

                speedErr = (WaypointIndex == -1 ? speed.val : tgtSpeed) - Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward);
                if (s.wheelThrottle == s.wheelThrottleTrim || FlightGlobals.ActiveVessel != vessel)
                {
                    float act = (float)speedPID.Compute(speedErr);
                    s.wheelThrottle = Mathf.Clamp(act, -1f, 1f);
                    // s.wheelThrottle = (!LimitAcceleration ? Mathf.Clamp(act, -1, 1) : // I think I'm using these ( ? : ) a bit too much
                    // (traction == 0 ? 0 : (act < 0 ? Mathf.Clamp(act, -1f, 1f) : (lastThrottle + Mathf.Clamp(act - lastThrottle, -0.01f, 0.01f)) * (traction < tractionLimit ? -1 : 1))));
//						(lastThrottle + Mathf.Clamp(act, -0.01f, 0.01f)));
//					Debug.Log(s.wheelThrottle + Mathf.Clamp(act, -0.01f, 0.01f));
                    if (curSpeed < 0 & s.wheelThrottle < 0)
                    {
                        s.wheelThrottle = 0;
                    }                                                                                    // don't go backwards
                    if (Mathf.Sign(act) + Mathf.Sign(s.wheelThrottle) == 0)
                    {
                        s.wheelThrottle = Mathf.Clamp(act, -1f, 1f);
                    }
                    if (speedErr < -1 && StabilityControl && Mathf.Sign(s.wheelThrottle) + Math.Sign(curSpeed) == 0)                       // StabilityControl && traction > 50 &&
////						vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true);
                    {
                        brake = true;
//						foreach (Part p in wheels) {
//							if (p.GetModule<ModuleWheels.ModuleWheelDamage>().stressPercent >= 0.01) { // #TODO needs adaptive braking
//								brake = false;
//								break;
//							}
//						}
                    }
////					else if (!StabilityControl || traction <= 50 || speedErr > -0.2 || Mathf.Sign(s.wheelThrottle) + Mathf.Sign((float)curSpeed) != 0) {
////						vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, (GameSettings.BRAKES.GetKey() && vessel.isActiveVessel));
////					}
                    lastThrottle = Mathf.Clamp(s.wheelThrottle, -1, 1);
                }
            }

            if (StabilityControl)
            {
                if (!core.attitude.users.Contains(this))
                {
                    core.attitude.users.Add(this);
//					line.enabled = true;
                }
//				float scale = Vector3.Distance(FlightCamera.fetch.mainCamera.transform.position, vessel.CoM) / 900f;
//				line.SetPosition(0, vessel.CoM);
//				line.SetPosition(1, vessel.CoM + hit.normal * 5);
//				line.SetWidth(0, scale + 0.1f);
                var fSpeed = (float)curSpeed;
//				if (Mathf.Abs(fSpeed) >= turnSpeed * 0.75) {
                Vector3 fwd = (Vector3)(traction > 0 ?                 // V when the speed is low go for the vessels forward, else with a bit of velocity
//				                        ((Mathf.Abs(fSpeed) <= turnSpeed ? vesselState.forward : vesselState.surfaceVelocity / 4) - vessel.transform.right * s.wheelSteer) * Mathf.Sign(fSpeed) :
//				                        // ^ and then add the steering
                                        vesselState.forward * 4 - vessel.transform.right * s.wheelSteer * Mathf.Sign(fSpeed) : // and then add the steering
                                        vesselState.surfaceVelocity);                                                          // in the air so follow velocity
                Vector3.OrthoNormalize(ref norm, ref fwd);
                var quat = Quaternion.LookRotation(fwd, norm);

//				if (traction > 0 || speed <= turnSpeed) {
//					var u = new Vector3(0, 1, 0);
//
//					var q = FlightGlobals.ship_rotation;
//					var q_s = quat;
//
//					var q_u = new Quaternion(u.x, u.y, u.z, 0);
//					var a = Quaternion.Dot(q, q_s * q_u);
//					var q_qs = Quaternion.Dot(q, q_s);
//					var b = (a == 0) ? Math.Sign(q_qs) : (q_qs / a);
//					var g = b / Mathf.Sqrt((b * b) + 1);
//					var gu = Mathf.Sqrt(1 - (g * g)) * u;
//					var q_d = new Quaternion() { w = g, x = gu.x, y = gu.y, z = gu.z };
//					var n = q_s * q_d;
//
//					quat = n;
//				}
                if (vesselState.torqueAvailable.sqrMagnitude > 0)
                {
                    core.attitude.attitudeTo(quat, AttitudeReference.INERTIAL, this);
                }
//				}
            }

            if (BrakeOnEnergyDepletion)
            {
                var batteries  = vessel.Parts.FindAll(p => p.Resources.Contains(PartResourceLibrary.ElectricityHashcode) && p.Resources.Get(PartResourceLibrary.ElectricityHashcode).flowState);
                var energyLeft = batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).amount) / batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).maxAmount);
                var openSolars = vessel.mainBody.atmosphere &&                 // true if in atmosphere and there are breakable solarpanels that aren't broken nor retracted
                                 vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable && p.deployState != ModuleDeployablePart.DeployState.BROKEN &&
                                                                                                           p.deployState != ModuleDeployablePart.DeployState.RETRACTED).Count > 0;

                if (openSolars && energyLeft > 0.99)
                {
                    vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable &&
                                                                                              p.deployState == ModuleDeployablePart.DeployState.EXTENDED).ForEach(p => p.Retract());
                }

                if (energyLeft < 0.05 && Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0)
                {
                    s.wheelThrottle = 0;
                }                                                                                                                        // save remaining energy by not using it for acceleration
                if (openSolars || energyLeft < 0.03)
                {
                    tgtSpeed = 0;
                }

                if (curSpeed < brakeSpeedLimit && (energyLeft < 0.05 || openSolars))
                {
                    brake = true;
                }

                if (curSpeed < 0.1 && energyLeft < 0.05 && !waitingForDaylight &&
                    vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.deployState == ModuleDeployablePart.DeployState.EXTENDED).Count > 0)
                {
                    waitingForDaylight = true;
                }
            }

//			brake = brake && (s.wheelThrottle == 0); // release brake if the user or AP want to drive
            if (s.wheelThrottle != 0 && (Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0 || curSpeed < 1))
            {
                brake = false;                 // the AP or user want to drive into the direction of momentum so release the brake
            }

            if (vessel.isActiveVessel)
            {
                if (GameSettings.BRAKES.GetKeyUp())
                {
                    brake = false;                     // release the brakes if the user lets go of them
                }
                if (GameSettings.BRAKES.GetKey())
                {
                    brake = true;                     // brake if the user brakes and we aren't about to flip
                }
            }

            tractionLimit = (double)Mathf.Clamp((float)tractionLimit, 0, 100);
            vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, brake && (StabilityControl && (ControlHeading || ControlSpeed) ? traction >= tractionLimit : true));
            // only let go of the brake when losing traction if the AP is driving, otherwise assume the player knows when to let go of it
            // also to not constantly turn off the parking brake from going over a small bump
            if (brake && curSpeed < 0.1)
            {
                s.wheelThrottle = 0;
            }
        }
Ejemplo n.º 8
0
 public static Vector3d computeTotalAccel(Vector3d pos, Vector3d orbitVel, double dragCoeffOverMass, CelestialBody body)
 {
     return(FlightGlobals.getGeeForceAtPosition(pos) + computeDragAccel(pos, orbitVel, dragCoeffOverMass, body));
 }
        public void FixedUpdate()
        {
            if (initializationCountdown > 0)
            {
                initializationCountdown--;
            }

            if (!HighLogic.LoadedSceneIsFlight)
            {
                return;
            }

            if (_attached_engine == null)
            {
                return;
            }

            if (_attached_engine is ModuleEnginesFX)
            {
                ElectricEngineControllerFX.getAllPropellants().ForEach(prop => part.Effect(prop.ParticleFXName, 0, -1)); // set all FX to zero
            }
            if (Current_propellant == null)
            {
                return;
            }

            if (!this.vessel.packed && !warpToReal)
            {
                storedThrotle = vessel.ctrlState.mainThrottle;
            }

            // retrieve power
            maxEffectivePower = MaxEffectivePower;
            var sumOfAllEffectivePower = vessel.FindPartModulesImplementing <ElectricEngineControllerFX>().Where(ee => ee.IsOperational).Sum(ee => ee.MaxEffectivePower);

            _electrical_share_f = sumOfAllEffectivePower > 0 ? maxEffectivePower / sumOfAllEffectivePower : 1;

            maxThrottlePower = maxEffectivePower * ModifiedThrotte;
            var currentPropellantEfficiency = CurrentPropellantEfficiency;

            if (CheatOptions.InfiniteElectricity)
            {
                power_request = maxThrottlePower;
            }
            else
            {
                var availablePower     = Math.Max(getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES) - getCurrentHighPriorityResourceDemand(FNResourceManager.FNRESOURCE_MEGAJOULES), 0);
                var megaJoulesBarRatio = getResourceBarRatio(FNResourceManager.FNRESOURCE_MEGAJOULES);

                var effectiveResourceThrotling = megaJoulesBarRatio > oneThird ? 1 : megaJoulesBarRatio * 3;

                var power_per_engine = effectiveResourceThrotling * ModifiedThrotte * EvaluateMaxThrust(availablePower * _electrical_share_f) * CurrentIspMultiplier * _modifiedEngineBaseISP / GetPowerThrustModifier() * _g0;
                power_request = currentPropellantEfficiency <= 0 ? 0 : Math.Min(power_per_engine / currentPropellantEfficiency, maxThrottlePower);
            }

            var power_received = CheatOptions.InfiniteElectricity
                ? power_request
                : consumeFNResource(power_request * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES) / TimeWarp.fixedDeltaTime;

            // produce waste heat
            var heat_to_produce = power_received * (1 - currentPropellantEfficiency) * Current_propellant.WasteHeatMultiplier;

            var heat_production = CheatOptions.IgnoreMaxTemperature
                ? heat_to_produce
                : supplyFNResourceFixed(heat_to_produce * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime;

            // update GUI Values
            _electrical_consumption_f = power_received;
            _heat_production_f        = heat_production;

            var effectiveIsp = _modifiedCurrentPropellantIspMultiplier * _modifiedEngineBaseISP * ThrottleModifiedIsp();

            var max_thrust_in_space = currentPropellantEfficiency * CurrentPropellantThrustMultiplier * ModifiedThrotte * GetPowerThrustModifier() * power_received / (effectiveIsp * _g0);

            _maxISP             = _modifiedEngineBaseISP * _modifiedCurrentPropellantIspMultiplier * CurrentPropellantThrustMultiplier * ThrottleModifiedIsp();
            _max_fuel_flow_rate = _maxISP <= 0 ? 0 : max_thrust_in_space / _maxISP / PluginHelper.GravityConstant;

            var max_thrust_with_current_throttle = max_thrust_in_space * ModifiedThrotte;

            throtle_max_thrust = Current_propellant.SupportedEngines == 8
                ? max_thrust_with_current_throttle
                : Math.Max(max_thrust_with_current_throttle - (exitArea * FlightGlobals.getStaticPressure(vessel.transform.position)), 0);

            float throttle = _attached_engine.currentThrottle > 0 ? Mathf.Max(_attached_engine.currentThrottle, 0.01f) : 0;

            //if (ModifiedThrotte > 0)
            if (throttle > 0 && !this.vessel.packed)
            {
                if (IsValidPositiveNumber(throtle_max_thrust) && IsValidPositiveNumber(max_thrust_with_current_throttle))
                {
                    updateISP(throtle_max_thrust / max_thrust_with_current_throttle);
                    _attached_engine.maxFuelFlow = (float)Math.Max(_max_fuel_flow_rate * (ModifiedThrotte / _attached_engine.currentThrottle), 0.0000000001);
                }
                else
                {
                    updateISP(0.000001);
                    _attached_engine.maxFuelFlow = 0.0000000001f;
                }

                if (_attached_engine is ModuleEnginesFX)
                {
                    this.part.Effect(Current_propellant.ParticleFXName, Mathf.Min((float)Math.Pow(_electrical_consumption_f / maxEffectivePower, 0.5), _attached_engine.finalThrust / _attached_engine.maxThrust), -1);
                }
            }
            else if (this.vessel.packed && _attached_engine.enabled && FlightGlobals.ActiveVessel == vessel && throttle > 0 && initializationCountdown == 0)
            {
                warpToReal = true; // Set to true for transition to realtime

                PersistantThrust(TimeWarp.fixedDeltaTime, Planetarium.GetUniversalTime(), this.part.transform.up, this.vessel.GetTotalMass());
            }
            else
            {
                throtle_max_thrust = 0;
                var projected_max_thrust = Math.Max(max_thrust_in_space - (exitArea * FlightGlobals.getStaticPressure(vessel.transform.position)), 0);

                if (IsValidPositiveNumber(projected_max_thrust) && IsValidPositiveNumber(max_thrust_in_space))
                {
                    updateISP(projected_max_thrust / max_thrust_in_space);
                    _attached_engine.maxFuelFlow = (float)Math.Max(_max_fuel_flow_rate, 0.0000000001);
                }
                else
                {
                    updateISP(1);
                    _attached_engine.maxFuelFlow = 0.0000000001f;
                }

                if (_attached_engine is ModuleEnginesFX)
                {
                    this.part.Effect(Current_propellant.ParticleFXName, 0, -1);
                }
            }

            if (isupgraded && vacuumPlasmaResource != null)
            {
                //vacuumPlasmaResource.maxAmount = maxPower * 0.00001 * TimeWarp.fixedDeltaTime;
                this.part.RequestResource(InterstellarResourcesConfiguration.Instance.VacuumPlasma, -vacuumPlasmaResource.maxAmount);
            }
        }
Ejemplo n.º 10
0
        internal void BuildAndLaunchCraft()
        {
            // build craft
            ShipConstruct nship = new ShipConstruct();

            nship.LoadShip(craftConfig);

            string             landedAt = "";
            string             flag     = flagname;
            Game               game     = FlightDriver.FlightStateCache;
            VesselCrewManifest crew     = new VesselCrewManifest();

            Box vessel_bounds = GetVesselBox(nship);

            launchTransform = builder.PlaceShip(nship, vessel_bounds);

            EnableExtendingLaunchClamps(nship);
            ShipConstruction.AssembleForLaunch(nship, landedAt, landedAt,
                                               flag, game, crew);
            var FlightVessels = FlightGlobals.Vessels;

            craftVessel = FlightVessels[FlightVessels.Count - 1];
            craftVessel.launchedFrom = builder.LaunchedFrom;

            FlightGlobals.ForceSetActiveVessel(craftVessel);
            if (builder.capture)
            {
                craftVessel.Splashed = craftVessel.Landed = false;
            }
            else
            {
                bool loaded = craftVessel.loaded;
                bool packed = craftVessel.packed;
                craftVessel.loaded = true;
                craftVessel.packed = false;
                // The default situation for new vessels is PRELAUNCH, but
                // that is not so good for bases because contracts check for
                // LANDED. XXX should this be selectable?
                craftVessel.situation = Vessel.Situations.LANDED;
                craftVessel.GetHeightFromTerrain();
                Debug.Log($"[ELBuildControl] height from terrain {craftVessel.heightFromTerrain}");
                craftVessel.loaded = loaded;
                craftVessel.packed = packed;
            }

            Vector3 offset = craftVessel.transform.position - launchTransform.position;

            craftOffset = launchTransform.InverseTransformDirection(offset);
            SetupCraftResources(craftVessel);

            KSP.UI.Screens.StageManager.BeginFlight();

            builtStuff = null;                  // ensure pad mass gets reset
            SetPadMass();
            if (builder.capture)
            {
                FlightGlobals.overrideOrbit = true;
                (builder as PartModule).StartCoroutine(CaptureCraft());
            }
            else
            {
                CleaupAfterRelease();
            }
        }
Ejemplo n.º 11
0
        public override void Drive(FlightCtrlState s) // TODO put the brake in when running out of power to prevent nighttime solar failures on hills, or atleast try to
        {                                             // TODO make distance calculation for 'reached' determination consider the rover and waypoint on sealevel to prevent height differences from messing it up
            if (orbit.referenceBody != lastBody)
            {
                WaypointIndex = -1; Waypoints.Clear();
            }
            MechJebRoverWaypoint wp = (WaypointIndex > -1 && WaypointIndex < Waypoints.Count ? Waypoints[WaypointIndex] : null);

            var curSpeed = vesselState.speedSurface;

            etaSpeed.value = curSpeed;

            if (wp != null && wp.Body == orbit.referenceBody)
            {
                if (controlHeading)
                {
                    heading = Math.Round(HeadingToPos(vessel.CoM, wp.Position), 1);
                }
                if (controlSpeed)
                {
                    var nextWP   = (WaypointIndex < Waypoints.Count - 1 ? Waypoints[WaypointIndex + 1] : (LoopWaypoints ? Waypoints[0] : null));
                    var distance = Vector3.Distance(vessel.CoM, wp.Position);
                    //var maxSpeed = (wp.MaxSpeed > 0 ? Math.Min((float)speed, wp.MaxSpeed) : speed); // use waypoints maxSpeed if set and smaller than set the speed or just stick with the set speed
                    var maxSpeed = (wp.MaxSpeed > 0 ? wp.MaxSpeed : speed);                     // speed used to go towards the waypoint, using the waypoints maxSpeed if set or just stick with the set speed
                    var minSpeed = (wp.MinSpeed > 0 ? wp.MinSpeed :
                                    (nextWP != null ? TurningSpeed((nextWP.MaxSpeed > 0 ? nextWP.MaxSpeed : speed), heading - HeadingToPos(wp.Position, nextWP.Position)) :
                                     (distance - wp.Radius > 50 ? turnSpeed.val : 1)));
                    minSpeed = (wp.Quicksave ? 0 : minSpeed);
                    // ^ speed used to go through the waypoint, using half the set speed or maxSpeed as minSpeed for routing waypoints (all except the last)
                    var brakeFactor = Math.Max((curSpeed - minSpeed) * 1, 3);
                    var newSpeed    = Math.Min(maxSpeed, Math.Max((distance - wp.Radius) / brakeFactor, minSpeed)); // brake when getting closer
                    newSpeed = (newSpeed > turnSpeed ? TurningSpeed(newSpeed, headingErr) : newSpeed);              // reduce speed when turning a lot
                    var radius = Math.Max(wp.Radius, 10 / 0.8);                                                     // alternative radius so negative radii can still make it go full speed through waypoints for navigation reasons
                    if (distance < radius)
                    {
                        if (WaypointIndex + 1 >= Waypoints.Count)                           // last waypoint
                        {
                            newSpeed = new [] { newSpeed, (distance < radius * 0.8 ? 0 : 1) }.Min();
                            // ^ limit speed so it'll only go from 1m/s to full stop when braking to prevent accidents on moons
                            if (LoopWaypoints)
                            {
                                WaypointIndex = 0;
                            }
                            else
                            {
                                newSpeed = -0.25;
                                tgtSpeed.force(newSpeed);
                                if (curSpeed < 0.85)
                                {
                                    if (wp.Quicksave)
                                    {
                                        if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR)
                                        {
                                            WaypointIndex  = -1;
                                            controlHeading = controlSpeed = false;
                                            QuickSaveLoad.QuickSave();
                                        }
                                    }
                                    else
                                    {
                                        WaypointIndex  = -1;
                                        controlHeading = controlSpeed = false;
                                    }
                                }
//								else {
//									Debug.Log("Is this even getting called?");
//									WaypointIndex++;
//								}
                            }
                        }
                        else
                        {
                            if (wp.Quicksave)
                            {
                                newSpeed = -0.25;
                                tgtSpeed.force(newSpeed);
                                if (curSpeed < 0.85)
                                {
                                    if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR)
                                    {
                                        WaypointIndex++;
                                        QuickSaveLoad.QuickSave();
                                    }
                                }
                            }
                            else
                            {
                                WaypointIndex++;
                            }
                        }
                    }
                    vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, (GameSettings.BRAKES.GetKey() && vessel.isActiveVessel) || ((s.wheelThrottle == 0 || !vessel.isActiveVessel) && curSpeed < 0.85 && newSpeed < 0.85));
                    // ^ brake if needed to prevent rolling, hopefully
                    tgtSpeed.value = Math.Round(newSpeed, 1);
                }
            }

            if (controlHeading)
            {
                if (heading != headingLast)
                {
                    headingPID.Reset();
                    headingLast = heading;
                }

                double instantaneousHeading = vesselState.rotationVesselSurface.eulerAngles.y;
                headingErr = MuUtils.ClampDegrees180(instantaneousHeading - heading);
                if (s.wheelSteer == s.wheelSteerTrim || FlightGlobals.ActiveVessel != vessel)
                {
                    float  spd   = Mathf.Min((float)speed, (float)turnSpeed);                  // if a slower speed than the turnspeed is used also be more careful with the steering
                    float  limit = (curSpeed <= turnSpeed ? 1 : Mathf.Clamp((float)((spd * spd) / (curSpeed * curSpeed)), 0.2f, 1f));
                    double act   = headingPID.Compute(headingErr);
                    s.wheelSteer = Mathf.Clamp((float)act, -limit, limit);
                }
            }
            // Brake if there is no controler (Pilot eject from seat)
            if (brakeOnEject && vessel.GetReferenceTransformPart() == null)
            {
                s.wheelThrottle = 0;
                vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true);
            }
            else if (controlSpeed)
            {
                if (speed != speedLast)
                {
                    speedPID.Reset();
                    speedLast = speed;
                }

                speedErr = (WaypointIndex == -1 ? speed.val : tgtSpeed.value) - Vector3d.Dot(vesselState.velocityVesselSurface, vesselState.forward);
                if (s.wheelThrottle == s.wheelThrottleTrim || FlightGlobals.ActiveVessel != vessel)
                {
                    double act = speedPID.Compute(speedErr);
                    s.wheelThrottle = Mathf.Clamp((float)act, -1, 1);
                }
            }
        }
        public override void Drive(FlightCtrlState s) // TODO put the brake in when running out of power to prevent nighttime solar failures on hills, or atleast try to
        {                                             // TODO make distance calculation for 'reached' determination consider the rover and waypoint on sealevel to prevent height differences from messing it up -- should be done now?
            if (orbit.referenceBody != lastBody)
            {
                WaypointIndex = -1; Waypoints.Clear();
            }
            MechJebWaypoint wp = (WaypointIndex > -1 && WaypointIndex < Waypoints.Count ? Waypoints[WaypointIndex] : null);

            bool brake = vessel.ActionGroups[KSPActionGroup.Brakes];             // keep brakes locked if they are

            curSpeed = Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward);

            CalculateTraction();
            speedIntAcc = speedPID.intAccum;

            if (wp != null && wp.Body == orbit.referenceBody)
            {
                if (ControlHeading)
                {
                    double newHeading = Math.Round(HeadingToPos(vessel.CoM, wp.Position), 1);

                    // update GUI text only if the value changed
                    if (newHeading != heading)
                    {
                        heading.val = newHeading;
                    }
                }
                if (ControlSpeed)
                {
                    MechJebWaypoint nextWP   = (WaypointIndex < Waypoints.Count - 1 ? Waypoints[WaypointIndex + 1] : (LoopWaypoints ? Waypoints[0] : null));
                    float           distance = Vector3.Distance(vessel.CoM, wp.Position);
                    if (wp.Target != null)
                    {
                        distance += (float)(wp.Target.srfSpeed * curSpeed) / 2;
                    }
                    // var maxSpeed = (wp.MaxSpeed > 0 ? Math.Min((float)speed, wp.MaxSpeed) : speed); // use waypoints maxSpeed if set and smaller than set the speed or just stick with the set speed
                    double maxSpeed = (wp.MaxSpeed > 0 ? wp.MaxSpeed : speed);                     // speed used to go towards the waypoint, using the waypoints maxSpeed if set or just stick with the set speed
                    double minSpeed = (wp.MinSpeed > 0 ? wp.MinSpeed :
                                       (nextWP != null ? TurningSpeed((nextWP.MaxSpeed > 0 ? nextWP.MaxSpeed : speed), MuUtils.ClampDegrees180(heading - HeadingToPos(wp.Position, nextWP.Position))) :
                                        (distance - wp.Radius > 50 ? turnSpeed.val : 1)));
                    minSpeed = (wp.Quicksave ? 1 : minSpeed);
                    // ^ speed used to go through the waypoint, using half the set speed or maxSpeed as minSpeed for routing waypoints (all except the last)
                    double newSpeed = Math.Min(maxSpeed, Math.Max((distance - wp.Radius) / curSpeed, minSpeed));           // brake when getting closer
                    newSpeed = (newSpeed > turnSpeed ? TurningSpeed(newSpeed, headingErr) : newSpeed);                     // reduce speed when turning a lot
                    float radius = Math.Max(wp.Radius, 10);
                    if (distance < radius)
                    {
                        if (WaypointIndex + 1 >= Waypoints.Count)                         // last waypoint
                        {
                            newSpeed = new [] { newSpeed, (distance < radius * 0.8 ? 0 : 1) }.Min();
                            // ^ limit speed so it'll only go from 1m/s to full stop when braking to prevent accidents on moons
                            if (LoopWaypoints)
                            {
                                WaypointIndex = 0;
                            }
                            else
                            {
                                newSpeed = 0;
                                brake    = true;
                                if (curSpeed < brakeSpeedLimit)
                                {
                                    if (wp.Quicksave)
                                    {
                                        if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR)
                                        {
                                            WaypointIndex  = -1;
                                            ControlHeading = ControlSpeed = false;
                                            QuickSaveLoad.QuickSave();
                                        }
                                    }
                                    else
                                    {
                                        WaypointIndex  = -1;
                                        ControlHeading = ControlSpeed = false;
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (wp.Quicksave)
                            {
                                newSpeed = 0;
                                if (curSpeed < brakeSpeedLimit)
                                {
                                    if (FlightGlobals.ClearToSave() == ClearToSaveStatus.CLEAR)
                                    {
                                        WaypointIndex++;
                                        QuickSaveLoad.QuickSave();
                                    }
                                }
                            }
                            else
                            {
                                WaypointIndex++;
                            }
                        }
                    }
                    brake = brake || ((s.wheelThrottle == 0 || !vessel.isActiveVessel) && curSpeed < brakeSpeedLimit && newSpeed < brakeSpeedLimit);
                    // ^ brake if needed to prevent rolling, hopefully
                    tgtSpeed = (newSpeed >= 0 ? newSpeed : 0);
                }
            }

            if (ControlHeading)
            {
                headingPID.intAccum = Mathf.Clamp((float)headingPID.intAccum, -1, 1);

                double instantaneousHeading = vesselState.rotationVesselSurface.eulerAngles.y;
                headingErr = MuUtils.ClampDegrees180(instantaneousHeading - heading);
                if (s.wheelSteer == s.wheelSteerTrim || FlightGlobals.ActiveVessel != vessel)
                {
                    float limit = (Math.Abs(curSpeed) > turnSpeed ? Mathf.Clamp((float)((turnSpeed + 6) / Square(curSpeed)), 0.1f, 1f) : 1f);
                    // turnSpeed needs to be higher than curSpeed or it will never steer as much as it could even at 0.2m/s above it
                    double act = headingPID.Compute(headingErr);
                    if (traction >= tractionLimit)
                    {
                        s.wheelSteer = Mathf.Clamp((float)act, -limit, limit);
                        // prevents it from flying above a waypoint and landing with steering at max while still going fast
                    }
                }
            }

            // Brake if there is no controler (Pilot eject from seat)
            if (BrakeOnEject && vessel.GetReferenceTransformPart() == null)
            {
                s.wheelThrottle = 0;
                brake           = true;
            }
            else if (ControlSpeed)
            {
                speedPID.intAccum = Mathf.Clamp((float)speedPID.intAccum, -5, 5);

                speedErr = (WaypointIndex == -1 ? speed.val : tgtSpeed) - Vector3d.Dot(vesselState.surfaceVelocity, vesselState.forward);
                if (s.wheelThrottle == s.wheelThrottleTrim || FlightGlobals.ActiveVessel != vessel)
                {
                    float act = (float)speedPID.Compute(speedErr);
                    s.wheelThrottle = Mathf.Clamp(act, -1f, 1f);
                    if (curSpeed < 0 & s.wheelThrottle < 0)
                    {
                        s.wheelThrottle = 0;
                    }                                                                                    // don't go backwards
                    if (Mathf.Sign(act) + Mathf.Sign(s.wheelThrottle) == 0)
                    {
                        s.wheelThrottle = Mathf.Clamp(act, -1f, 1f);
                    }
                    if (speedErr < -1 && StabilityControl && Mathf.Sign(s.wheelThrottle) + Math.Sign(curSpeed) == 0)
                    {
                        brake = true;
                    }
                    lastThrottle = Mathf.Clamp(s.wheelThrottle, -1, 1);
                }
            }

            if (StabilityControl)
            {
                RaycastHit hit;
                Physics.Raycast(vessel.CoM + vesselState.surfaceVelocity * terrainLookAhead + vesselState.up * 100, -vesselState.up, out hit, 500, 1 << 15, QueryTriggerInteraction.Ignore);
                Vector3 norm = hit.normal;

                if (!core.attitude.users.Contains(this))
                {
                    core.attitude.users.Add(this);
                }
                float   fSpeed = (float)curSpeed;
                Vector3 fwd    = (Vector3)(traction > 0 ?                                                                         // V when the speed is low go for the vessels forward, else with a bit of velocity
                                           vesselState.forward * 4 - vessel.transform.right * s.wheelSteer * Mathf.Sign(fSpeed) : // and then add the steering
                                           vesselState.surfaceVelocity);                                                          // in the air so follow velocity
                Vector3.OrthoNormalize(ref norm, ref fwd);
                Quaternion quat = Quaternion.LookRotation(fwd, norm);

                if (vesselState.torqueAvailable.sqrMagnitude > 0)
                {
                    core.attitude.attitudeTo(quat, AttitudeReference.INERTIAL, this);
                }
            }

            if (BrakeOnEnergyDepletion)
            {
                var batteries  = vessel.Parts.FindAll(p => p.Resources.Contains(PartResourceLibrary.ElectricityHashcode) && p.Resources.Get(PartResourceLibrary.ElectricityHashcode).flowState);
                var energyLeft = batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).amount) / batteries.Sum(p => p.Resources.Get(PartResourceLibrary.ElectricityHashcode).maxAmount);
                var openSolars = vessel.mainBody.atmosphere &&                 // true if in atmosphere and there are breakable solarpanels that aren't broken nor retracted
                                 vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable && p.deployState != ModuleDeployablePart.DeployState.BROKEN &&
                                                                                                           p.deployState != ModuleDeployablePart.DeployState.RETRACTED).Count > 0;

                if (openSolars && energyLeft > 0.99)
                {
                    vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.isBreakable &&
                                                                                              p.deployState == ModuleDeployablePart.DeployState.EXTENDED).ForEach(p => p.Retract());
                }

                if (energyLeft < 0.05 && Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0)
                {
                    s.wheelThrottle = 0;
                }                                                                                                                        // save remaining energy by not using it for acceleration
                if (openSolars || energyLeft < 0.03)
                {
                    tgtSpeed = 0;
                }

                if (curSpeed < brakeSpeedLimit && (energyLeft < 0.05 || openSolars))
                {
                    brake = true;
                }

                if (curSpeed < 0.1 && energyLeft < 0.05 && !waitingForDaylight &&
                    vessel.FindPartModulesImplementing <ModuleDeployableSolarPanel>().FindAll(p => p.deployState == ModuleDeployablePart.DeployState.EXTENDED).Count > 0)
                {
                    waitingForDaylight = true;
                }
            }

            if (s.wheelThrottle != 0 && (Math.Sign(s.wheelThrottle) + Math.Sign(curSpeed) != 0 || curSpeed < 1))
            {
                brake = false;                 // the AP or user want to drive into the direction of momentum so release the brake
            }

            if (vessel.isActiveVessel)
            {
                if (GameSettings.BRAKES.GetKeyUp())
                {
                    brake = false;                     // release the brakes if the user lets go of them
                }
                if (GameSettings.BRAKES.GetKey())
                {
                    brake = true;                     // brake if the user brakes and we aren't about to flip
                }
            }

            tractionLimit = (double)Mathf.Clamp((float)tractionLimit, 0, 100);
            vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, brake && (StabilityControl && (ControlHeading || ControlSpeed) ? traction >= tractionLimit : true));
            // only let go of the brake when losing traction if the AP is driving, otherwise assume the player knows when to let go of it
            // also to not constantly turn off the parking brake from going over a small bump
            if (brake && curSpeed < 0.1)
            {
                s.wheelThrottle = 0;
            }
        }
Ejemplo n.º 13
0
        private void UpdateKolonizationStats()
        {
            //No kolonization on Kerbin!
            if (vessel.mainBody == FlightGlobals.GetHomeBody())
            {
                return;
            }

            var k = KolonizationManager.Instance.FetchLogEntry(vessel.id.ToString(), vessel.mainBody.flightGlobalsIndex);

            if (Planetarium.GetUniversalTime() - k.LastUpdate < checkTime)
            {
                return;
            }

            var numPilots     = GetVesselCrewByTrait("Pilot");
            var numEngineers  = GetVesselCrewByTrait("Engineer");
            var numScientists = GetVesselCrewByTrait("Scientist");

            var elapsedTime = Planetarium.GetUniversalTime() - k.LastUpdate;
            var orbitMod    = 1d;

            if (!vessel.LandedOrSplashed)
            {
                orbitMod = KolonizationSetup.Instance.Config.OrbitMultiplier;
            }

            var scienceBase = numScientists * elapsedTime * orbitMod;
            var repBase     = numPilots * elapsedTime * orbitMod;
            var fundsBase   = numEngineers * elapsedTime * orbitMod;

            k.LastUpdate            = Planetarium.GetUniversalTime();
            k.BotanyResearch       += scienceBase;
            k.KolonizationResearch += repBase;
            k.GeologyResearch      += fundsBase;


            var mult    = vessel.mainBody.scienceValues.RecoveryValue;
            var science = scienceBase * KolonizationSetup.Instance.Config.ScienceMultiplier * mult;
            var rep     = repBase * KolonizationSetup.Instance.Config.RepMultiplier * mult;
            var funds   = fundsBase * KolonizationSetup.Instance.Config.FundsMultiplier * mult;

            k.Science += science;
            k.Funds   += funds;
            k.Rep     += rep;
            KolonizationManager.Instance.TrackLogEntry(k);

            //Update the hab bonus
            var thisBodyInfo = KolonizationManager.Instance.KolonizationInfo.Where(b => b.BodyIndex == vessel.mainBody.flightGlobalsIndex);
            var habBonus     = thisBodyInfo.Sum(b => b.KolonizationResearch);

            habBonus  = Math.Sqrt(habBonus);
            habBonus /= KolonizationSetup.Instance.Config.EfficiencyMultiplier;
            USI_GlobalBonuses.Instance.SaveHabBonus(vessel.mainBody.flightGlobalsIndex, habBonus);

            //Update the drill bonus
            foreach (var d in vessel.FindPartModulesImplementing <BaseDrill>())
            {
                var geoBonus = thisBodyInfo.Sum(b => b.GeologyResearch);
                geoBonus  = Math.Sqrt(habBonus);
                geoBonus /= KolonizationSetup.Instance.Config.EfficiencyMultiplier;

                geoBonus         += KolonizationSetup.Instance.Config.StartingBaseBonus;
                d.EfficiencyBonus = (float)Math.Max(KolonizationSetup.Instance.Config.MinBaseBonus, geoBonus);
            }
        }
Ejemplo n.º 14
0
        void Update()
        {
            CastSpell();
            if (loading)
            {
                //Debug.Log($"reset: {reset}, stage: {stage}, grav: {PhysicsGlobals.GraviticForceMultiplier}, pos: {FlightGlobals.currentMainBody.pqsController.target.position}");
                if (!FlightGlobals.currentMainBody.pqsController.isBuildingMaps)
                {
                    --reset;
                }
                if (reset <= 0)
                {
                    reset = vesLoad;
                    switch (stage)
                    {
                    case 0:
                        vesEnume = FlightGlobals.VesselsLoaded.ToList().GetEnumerator();
                        tvel     = FlightGlobals.ActiveVessel;
                        ++stage;
                        break;

                    case 1:
                        if (vesEnume.Current != null)
                        {
                            vesEnume.Current.OnFlyByWire -= thratlarasat;
                        }
                        if (vesEnume.MoveNext())
                        {
                            if (sortaLanded(vesEnume.Current))
                            {
                                FlightGlobals.ForceSetActiveVessel(vesEnume.Current);
                            }
                            vesEnume.Current.OnFlyByWire += thratlarasat;
                        }
                        else
                        {
                            vesEnume.Dispose();
                            ++stage;
                            FlightGlobals.ForceSetActiveVessel(tvel);
                        }
                        Debug.LogError($"Black Spell entangling {vesEnume.Current?.vesselName}");
                        break;

                    case 2:
                        Debug.LogError("Black Spell condensing");
                        ++stage;
                        break;

                    case 3:
                        Debug.LogError("Black Spell releasing energies");
                        reset = 100;
                        ++stage;
                        break;

                    case 4:
                        CheatOptions.NoCrashDamage     = crashDamage;
                        CheatOptions.UnbreakableJoints = joints;
                        loading = false;
                        Debug.LogError("Black Spell complete");
                        break;
                    }
                }
            }
        }
Ejemplo n.º 15
0
        public void FixedUpdate()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                UpdateBalloonType();
            }
            if (HighLogic.LoadedSceneIsFlight)
            {
                //print("hasInflated: " + hasInflated + " | isInflated: " + isInflated + " | isInflating: " + isInflating + " | isDeflating: " + isDeflating + " | hasBurst: " + hasBurst + " | isRepacked: " + isRepacked);
                float currentPressure = (float)FlightGlobals.getStaticPressure(this.part.transform.position);
                if (hasInflated && !hasBurst)
                {
                    if (isInflated)
                    {
                        float lift = BalloonProperties.getLift(this);
                        this.part.AddForceAtPosition(vessel.upAxis * lift, liftPointObject.transform.position);
                        Vector3 scale = new Vector3(BalloonProperties.getScale(this), BalloonProperties.getScale(this), BalloonProperties.getScale(this));
                        balloonObject.transform.localScale = scale;

                        ropeObject.transform.rotation    = Quaternion.Slerp(ropeObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 10);
                        balloonObject.transform.rotation = Quaternion.Slerp(balloonObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 8);

                        balloonObject.transform.position = balloonPointObject.transform.position;

                        if (currentPressure < minAtmoPressure || currentPressure > maxAtmoPressure)
                        {
                            hasBurst = true;
                        }
                    }
                    else if (isDeflating)
                    {
                        if (scaleInc > 0)
                        {
                            scaleInc -= BalloonProperties.getScale(this) / 100;
                            balloonObject.transform.localScale = new Vector3(scaleInc, scaleInc, scaleInc);

                            float progress = scaleInc / BalloonProperties.getScale(this);

                            float lift = BalloonProperties.getLift(this) * progress;
                            this.part.AddForceAtPosition(vessel.upAxis * lift, liftPointObject.transform.position);

                            ropeObject.transform.localScale  = new Vector3(1, 1, progress);
                            balloonObject.transform.position = balloonPointObject.transform.position;
                        }
                        else
                        {
                            balloonObject.SetActive(false);
                            ropeObject.SetActive(false);

                            isInflated  = false;
                            isDeflating = false;
                            isRepacked  = false;
                        }
                    }
                    else if (!isInflated && !isInflating && !isDeflating && !isRepacked)
                    {
                        Events["repackBalloon"].active = true;
                    }
                }
                else if (isInflating && !hasBurst)
                {
                    if (scaleInc < BalloonProperties.getScale(this))
                    {
                        scaleInc += BalloonProperties.getScale(this) / 200;
                        balloonObject.transform.localScale = new Vector3(scaleInc, scaleInc, scaleInc);

                        float progress = scaleInc / BalloonProperties.getScale(this);

                        float lift = BalloonProperties.getLift(this) * progress;
                        this.part.AddForceAtPosition(vessel.upAxis * lift, liftPointObject.transform.position);


                        ropeObject.transform.rotation    = Quaternion.Slerp(ropeObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 10);
                        balloonObject.transform.rotation = Quaternion.Slerp(balloonObject.transform.rotation, Quaternion.LookRotation(vessel.upAxis, vessel.upAxis), BalloonProperties.getLift(this) / 8);

                        ropeObject.transform.localScale  = new Vector3(1, 1, progress);
                        balloonObject.transform.position = balloonPointObject.transform.position;
                    }
                    else
                    {
                        hasInflated = true;
                        isInflated  = true;
                        isInflating = false;
                    }
                }
                else if (hasBurst && (isInflated || isInflating || isDeflating))
                {
                    this.part.Effect("burst");
                    isInflated  = false;
                    isInflating = false;
                    isDeflating = false;
                    balloonObject.SetActive(false);
                    ropeObject.SetActive(false);
                    Events["inflateBalloon"].active = false;
                    Events["deflateBalloon"].active = false;
                    Actions["inflateAction"].active = false;
                    Actions["deflateAction"].active = false;
                }
            }
        }
Ejemplo n.º 16
0
        // Awake() - flag this class as don't destroy on load and register delegates
        void Awake()
        {
            // Don't run if Kopernicus isn't compatible
            if (!CompatibilityChecker.IsCompatible())
            {
                Destroy(this);
                return;
            }

            // Make sure the runtime utility isn't killed
            DontDestroyOnLoad(this);

            // Init the runtime logging
            new Logger("Kopernicus.Runtime").SetAsActive();

            // Add handlers
            GameEvents.onPartUnpack.Add(OnPartUnpack);
            GameEvents.onLevelWasLoaded.Add(FixCameras);
            GameEvents.onLevelWasLoaded.Add(delegate(GameScenes scene)
            {
                //if (MapView.fetch != null)
                //    MapView.fetch.max3DlineDrawDist = Single.MaxValue;
                if (scene == GameScenes.SPACECENTER)
                {
                    PatchFI();
                }
                foreach (CelestialBody body in PSystemManager.Instance.localBodies)
                {
                    GameObject star = KopernicusStar.GetNearest(body).gameObject;
                    if (body.afg != null)
                    {
                        body.afg.sunLight = star;
                    }
                    if (body.scaledBody.GetComponent <MaterialSetDirection>() != null)
                    {
                        body.scaledBody.GetComponent <MaterialSetDirection>().target = star.transform;
                    }

                    foreach (PQSMod_MaterialSetDirection msd in body.GetComponentsInChildren <PQSMod_MaterialSetDirection>(true))
                    {
                        msd.target = star.transform;
                    }

                    // Contract Weight
                    if (ContractSystem.ContractWeights != null)
                    {
                        if (body.Has("contractWeight"))
                        {
                            if (ContractSystem.ContractWeights.ContainsKey(body.name))
                            {
                                ContractSystem.ContractWeights[body.name] = body.Get <Int32>("contractWeight");
                            }
                            else
                            {
                                ContractSystem.ContractWeights.Add(body.name, body.Get <Int32>("contractWeight"));
                            }
                        }
                    }
                }

                foreach (TimeOfDayAnimation anim in Resources.FindObjectsOfTypeAll <TimeOfDayAnimation>())
                {
                    anim.target = KopernicusStar.GetNearest(FlightGlobals.GetHomeBody()).gameObject.transform;
                }
#if FALSE
                foreach (TimeOfDayAnimation anim in Resources.FindObjectsOfTypeAll <TimeOfDayAnimation>())
                {
                    anim.gameObject.AddOrGetComponent <KopernicusStarTimeOfDay>();
                }

                foreach (GalaxyCubeControl control in Resources.FindObjectsOfTypeAll <GalaxyCubeControl>())
                {
                    control.gameObject.AddOrGetComponent <KopernicusStarGalaxyCubeControl>();
                }

                foreach (SkySphereControl control in Resources.FindObjectsOfTypeAll <SkySphereControl>())
                {
                    control.gameObject.AddOrGetComponent <KopernicusStarSkySphereControl>();
                }
#endif
            });
            GameEvents.onProtoVesselLoad.Add(TransformBodyReferencesOnLoad);
            GameEvents.onProtoVesselSave.Add(TransformBodyReferencesOnSave);

            // Update Music Logic
            if (MusicLogic.fetch != null && FlightGlobals.fetch != null && FlightGlobals.GetHomeBody() != null)
            {
                MusicLogic.fetch.flightMusicSpaceAltitude = FlightGlobals.GetHomeBody().atmosphereDepth;
            }

            // Log
            Logger.Default.Log("[Kopernicus] RuntimeUtility Started");
            Logger.Default.Flush();
        }
Ejemplo n.º 17
0
        void StationaryCamera()
        {
            Debug.Log("flightCamera position init: " + flightCamera.transform.position);
            if (FlightGlobals.ActiveVessel != null)
            {
                hasDied  = false;
                vessel   = FlightGlobals.ActiveVessel;
                cameraUp = -FlightGlobals.getGeeForceAtPosition(vessel.GetWorldPos3D()).normalized;
                if (FlightCamera.fetch.mode == FlightCamera.Modes.ORBITAL || (FlightCamera.fetch.mode == FlightCamera.Modes.AUTO && FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL))
                {
                    cameraUp = Vector3.up;
                }

                flightCamera.transform.parent = cameraParent.transform;
                flightCamera.setTarget(null);
                cameraParent.transform.position = vessel.transform.position + vessel.rigidbody.velocity * Time.fixedDeltaTime;
                manualPosition = Vector3.zero;


                hasTarget = (camTarget != null) ? true : false;


                Vector3 rightAxis;
                if (referenceMode == ReferenceModes.Surface && vessel.horizontalSrfSpeed > 2)
                {
                    rightAxis = Quaternion.AngleAxis(-90, vessel.srf_velocity) * cameraUp;
                }
                else
                {
                    rightAxis = Quaternion.AngleAxis(-90, vessel.obt_velocity) * cameraUp;
                }

                if (flightCamera.autoMode == FlightCamera.Modes.FREE)
                {
                    Vector3 cameraUpRef = cameraUp;
                    Vector3.OrthoNormalize(ref rightAxis, ref cameraUpRef);
                }


                if (autoFlybyPosition)
                {
                    setPresetOffset = false;
                    Vector3 velocity = vessel.srf_velocity;
                    if (referenceMode == ReferenceModes.Orbit)
                    {
                        velocity = vessel.obt_velocity;
                    }

                    Vector3 clampedVelocity = Mathf.Clamp((float)vessel.srfSpeed, 0, maxRelV) * velocity.normalized;
                    float   clampedSpeed    = clampedVelocity.magnitude;
                    float   sideDistance    = Mathf.Clamp(20 + (clampedSpeed / 10), 20, 150);
                    float   distanceAhead   = Mathf.Clamp(4 * clampedSpeed, 30, 3500);

                    flightCamera.transform.rotation = Quaternion.LookRotation(vessel.transform.position - flightCamera.transform.position, cameraUp);


                    if (referenceMode == ReferenceModes.Surface && vessel.srfSpeed > 4)
                    {
                        flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.srf_velocity.normalized);
                    }
                    else if (referenceMode == ReferenceModes.Orbit && vessel.obt_speed > 4)
                    {
                        flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.obt_velocity.normalized);
                    }
                    else
                    {
                        flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.vesselTransform.up);
                    }


                    if (flightCamera.mode == FlightCamera.Modes.FREE || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.FREE)
                    {
                        flightCamera.transform.position += (sideDistance * rightAxis) + (15 * cameraUp);
                    }
                    else if (flightCamera.mode == FlightCamera.Modes.ORBITAL || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL)
                    {
                        flightCamera.transform.position += (sideDistance * FlightGlobals.getUpAxis()) + (15 * Vector3.up);
                    }
                }
                else if (manualOffset)
                {
                    setPresetOffset = false;
                    float sideDistance  = manualOffsetRight;
                    float distanceAhead = manualOffsetForward;


                    flightCamera.transform.rotation = Quaternion.LookRotation(vessel.transform.position - flightCamera.transform.position, cameraUp);

                    if (referenceMode == ReferenceModes.Surface && vessel.srfSpeed > 4)
                    {
                        flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.srf_velocity.normalized);
                    }
                    else if (referenceMode == ReferenceModes.Orbit && vessel.obt_speed > 4)
                    {
                        flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.obt_velocity.normalized);
                    }
                    else
                    {
                        flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.vesselTransform.up);
                    }

                    if (flightCamera.mode == FlightCamera.Modes.FREE || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.FREE)
                    {
                        flightCamera.transform.position += (sideDistance * rightAxis) + (manualOffsetUp * cameraUp);
                    }
                    else if (flightCamera.mode == FlightCamera.Modes.ORBITAL || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL)
                    {
                        flightCamera.transform.position += (sideDistance * FlightGlobals.getUpAxis()) + (manualOffsetUp * Vector3.up);
                    }
                }
                else if (setPresetOffset)
                {
                    flightCamera.transform.position = presetOffset;
                    //setPresetOffset = false;
                }

                initialVelocity = vessel.srf_velocity;
                initialOrbit    = new Orbit();
                initialOrbit.UpdateFromStateVectors(vessel.orbit.pos, vessel.orbit.vel, FlightGlobals.currentMainBody, Planetarium.GetUniversalTime());
                initialUT = Planetarium.GetUniversalTime();

                isStationaryCamera = true;
                isDefault          = false;

                SetDoppler();
                AddAtmoAudioControllers();
            }
            else
            {
                Debug.Log("CameraTools: Stationary Camera failed. Active Vessel is null.");
            }
            resetPositionFix = flightCamera.transform.position;
            Debug.Log("flightCamera position post init: " + flightCamera.transform.position);
        }
Ejemplo n.º 18
0
 public static void RemovePhysicObject(Part p, Transform transf) {
   FlightGlobals.removePhysicalObject(transf.gameObject);
   UnityEngine.Object.Destroy(transf.GetComponent<Rigidbody>());
   transf.parent = p.transform;
 }
 protected override void on_vessel_launched(Vessel vsl)
 {
     base.on_vessel_launched(vsl);
     if (recipient_node != null)
     {
         var     construction_node_pos = part.partTransform.TransformPoint(construction_node.position);
         var     construction_node_fwd = part.partTransform.TransformDirection(construction_node.orientation).normalized;
         var     construction_part     = recipient_node.owner;
         var     spawn_transform       = get_deploy_transform();
         Vector3 docking_offset        = spawn_transform.position
                                         + spawn_transform.TransformDirection(get_deployed_offset())
                                         - construction_node_pos;
         var docking_node = kit.GetDockingNode(vsl, ConstructDockingNode);
         if (docking_node == null)
         {
             Utils.Message("No suitable attachment node found in \"{0}\" to dock it to the {1}",
                           vsl.GetDisplayName(), construction_part.Title());
             return;
         }
         FXMonger.Explode(part, construction_node_pos, 0);
         var docking_part = docking_node.owner;
         this.Log("Docking {} to {}", docking_part.GetID(), construction_part.GetID());
         var old_vessel = construction_part.vessel;
         // vessels' position and rotation
         construction_part.vessel.SetPosition(construction_part.vessel.transform.position, true);
         construction_part.vessel.SetRotation(construction_part.vessel.transform.rotation);
         docking_part.vessel.SetPosition(docking_part.vessel.transform.position - docking_offset, true);
         docking_part.vessel.SetRotation(docking_part.vessel.transform.rotation);
         construction_part.vessel.IgnoreGForces(10);
         docking_part.vessel.IgnoreGForces(10);
         if (construction_part == part.parent)
         {
             part.decouple();
         }
         else
         {
             construction_part.decouple();
         }
         recipient_node.attachedPart   = docking_part;
         recipient_node.attachedPartId = docking_part.flightID;
         docking_node.attachedPart     = construction_part;
         docking_node.attachedPartId   = construction_part.flightID;
         docking_part.Couple(construction_part);
         // manage docking ports, if any
         foreach (var port in construction_part.FindModulesImplementing <ModuleDockingNode>())
         {
             if (port.referenceNode == recipient_node)
             {
                 port.dockedPartUId = docking_part.persistentId;
                 port.fsm.StartFSM(port.st_preattached);
                 break;
             }
         }
         foreach (var port in docking_part.FindModulesImplementing <ModuleDockingNode>())
         {
             if (port.referenceNode == docking_node)
             {
                 port.dockedPartUId = construction_part.persistentId;
                 port.fsm.StartFSM(port.st_preattached);
                 break;
             }
         }
         // add fuel lookups
         construction_part.fuelLookupTargets.Add(docking_part);
         docking_part.fuelLookupTargets.Add(construction_part);
         GameEvents.onPartFuelLookupStateChange.Fire(new GameEvents.HostedFromToAction <bool, Part>(true, docking_part, construction_part));
         FlightGlobals.ForceSetActiveVessel(construction_part.vessel);
         FlightInputHandler.SetNeutralControls();
         GameEvents.onVesselWasModified.Fire(construction_part.vessel);
         recipient_node = null;
         this.Log("Docked {} to {}, new vessel {}",
                  docking_part, construction_part, construction_part.vessel.GetID());
     }
 }
Ejemplo n.º 20
0
        private void PerformScan()
        {
            var    numLodes = 0;
            string msg;

            if (_ani != null && !_ani.isDeployed)
            {
                msg = string.Format("Must deploy first!");
                ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            var minAlt = vessel.mainBody.Radius * altModifier;

            if (altModifier > ResourceUtilities.FLOAT_TOLERANCE &&
                (vessel.altitude < minAlt || vessel.altitude > minAlt * 2d))
            {
                msg = string.Format("Must perform scan at an altitude between {0:0}km and {1:0}km.", minAlt / 1000, minAlt * 2 / 1000);
                ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            if (FlightGlobals.currentMainBody == FlightGlobals.GetHomeBody() && !allowHomeBody)
            {
                msg = string.Format("There are no resource lodes available on " + FlightGlobals.GetHomeBody().bodyName + "!");
                ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            foreach (var v in FlightGlobals.Vessels)
            {
                if (v.mainBody != vessel.mainBody)
                {
                    continue;
                }
                if (v.packed && !v.loaded)
                {
                    if (v.protoVessel.protoPartSnapshots.Count > 1)
                    {
                        continue;
                    }

                    if (v.protoVessel.protoPartSnapshots[0].partName == lodePart)
                    {
                        numLodes++;
                    }
                }
                else
                {
                    if (v.Parts.Count > 1)
                    {
                        continue;
                    }

                    if (v.FindPartModuleImplementing <ModuleResourceLode>() != null)
                    {
                        numLodes++;
                    }
                }
            }

            if (numLodes >= maxLodes)
            {
                msg = string.Format("Too many resource lodes active - Harvest some first!");
                ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            var lode = new LodeData();

            lode.name       = "Resource Lode";
            lode.craftPart  = PartLoader.getPartInfoByName(lodePart);
            lode.vesselType = VesselType.Unknown;
            lode.body       = FlightGlobals.currentMainBody;
            lode.orbit      = null;
            lode.latitude   = RandomizePosition(part.vessel.latitude, lodeRange);
            lode.longitude  = RandomizePosition(part.vessel.longitude, lodeRange);
            lode.altitude   = null;
            CreateLode(lode);
            msg = string.Format("A new resource lode has been discovered and added to your map!");
            ScreenMessages.PostScreenMessage(msg, 5f, ScreenMessageStyle.UPPER_CENTER);
        }
Ejemplo n.º 21
0
        public void FixedUpdate()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }
            if (engine.type == EngineWrapper.EngineType.NONE || !engine.EngineIgnited)
            {
                return;
            }
            if (vessel.mainBody.atmosphereContainsOxygen == false || part.vessel.altitude > vessel.mainBody.maxAtmosphereAltitude)
            {
                engine.SetThrust(0);
                return;
            }

            #region Inlet

            float     Arearatio, OverallTPR = 0, EngineArea = 0, InletArea = 0;
            AJEModule e;
            AJEInlet  i;
            foreach (Part p in vessel.parts)
            {
                if (p.Modules.Contains("AJEModule"))
                {
                    e           = (AJEModule)p.Modules["AJEModule"];
                    EngineArea += (float)(e.aje.areaCore * (1 + e.aje.byprat));
                }
                if (p.Modules.Contains("AJEInlet"))
                {
                    i = (AJEInlet)p.Modules["AJEInlet"];
                    if (true)
                    {
                        InletArea  += i.Area;
                        OverallTPR += i.Area * i.cosine * i.cosine * i.GetTPR((float)aje.fsmach);
                    }
                }
            }
            if (InletArea > 0)
            {
                OverallTPR /= InletArea;
            }
            Arearatio  = Mathf.Min(InletArea / EngineArea, 1f);
            aje.eta[2] = Mathf.Clamp(Mathf.Sqrt(Arearatio) * OverallTPR, 0.001f, 1f);

            Inlet = "Area:" + ((int)(Arearatio * 100f)).ToString() + "%  TPR:" + ((int)(OverallTPR * 100f)).ToString() + "%";

            #endregion

            aje.FARps0 = FlightGlobals.getStaticPressure(vessel.altitude, vessel.mainBody);
            aje.FARts0 = FlightGlobals.getExternalTemperature((float)vessel.altitude, vessel.mainBody) + 273.15f;

            Environment = (((int)(aje.FARps0 * 100f)) / 100f).ToString() + "atm;" + (((int)(aje.FARts0 * 100f)) / 100f) + "K";

            if (usePrat3Curve)
            {
                aje.prat[3] = aje.p3p2d = (double)(prat3Curve.Evaluate((float)aje.fsmach));
            }
            aje.u0d         = part.vessel.srfSpeed * 3.6d;
            OverallThrottle = vessel.ctrlState.mainThrottle * engine.thrustPercentage / 100f;
            if (!useAB)
            {
                aje.comPute();
                engine.SetThrust(((float)aje.forceNetlb) * 0.004448f);
                engine.SetIsp((float)aje.isp);
                Mode = "Cruise " + System.Convert.ToString((int)(OverallThrottle * 100f)) + "%";
            }
            else
            {
                if (OverallThrottle <= ABthreshold)
                {
                    engine.useEngineResponseTime = true;
                    aje.abflag = 0;
                    aje.comPute();
                    engine.SetThrust(((float)aje.forceNetlb) * 0.004448f / ABthreshold);
                    engine.SetIsp((float)aje.isp);
                    Mode = "Cruise " + System.Convert.ToString((int)(OverallThrottle / ABthreshold * 100f)) + "%";
                }
                else
                {
                    // only allow instance response when already at max RPM; if the compressor is still spooling up, it's still spooling up.
                    if (engine.currentThrottle > ABthreshold)
                    {
                        engine.useEngineResponseTime = false;
                    }
                    else
                    {
                        engine.useEngineResponseTime = true;
                    }

                    aje.abflag = 1;
                    aje.tt7    = (OverallThrottle - ABthreshold) * (ABmax - ABmin) / (1 - ABthreshold) + ABmin;

                    aje.comPute();
                    engine.SetThrust(((float)aje.forceNetlb) * 0.004448f / OverallThrottle);
                    engine.SetIsp((float)aje.isp * ABIspMult);
                    Mode = "Afterburner " + System.Convert.ToString((int)((OverallThrottle - ABthreshold) / (1 - ABthreshold) * 100f)) + "%";
                }
            }
            Mode += " (" + (aje.forceGrosslb * 0.004448f).ToString("N2") + "kN gr)";



            if (aje.fireflag > 0.9f && useOverheat)
            {
                part.temperature = (aje.fireflag * 2f - 1.2f) * part.maxTemp;
            }

            fireflag = aje.fireflag;
            parttemp = part.temperature;
            maxtemp  = part.maxTemp;


            //           mach = (float)aje.fsmach;
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Update for every other tic
        /// </summary>
        public override void OnUpdate()
        {
            base.OnUpdate();

            if (HighLogic.LoadedSceneIsFlight)
            {
                bool valid = true;

                //check for atmosphere
                if (needsAtmosphere)
                {
                    valid &= vessel.mainBody.atmosphere;
                }

                if (needsOxygen)
                {
                    valid &= vessel.mainBody.atmosphere && vessel.mainBody.atmosphereContainsOxygen;
                }

                //check for water
                if (needsSubmerged)
                {
                    valid &= (vessel.mainBody.ocean) && (thrustTransform != null) && (FlightGlobals.getAltitudeAtPos(thrustTransform.position) < 0.0f);
                }

                //when all conditions are fulfilled, produce the resource
                if (valid)
                {
                    produce(resourceName, amount);
                }
            }
        }
        private Vector3 AddGroundEffectForce(Part part, Vector3 originalLift)
        {
            Vector3 normal = oceanNormal;

            // groundPlane.distance and groundDistance are different btw.
            // groundDistance is measured from an individual part
            float groundDistance = Single.MaxValue;

            // say that wings must be within 45 degrees flat towards the ground to have any effect
            //if (dot > 0.707f) {

            // Check distance from ocean (if planet has one), sea level is 0 (i think)
            if (FlightGlobals.currentMainBody.ocean)
            {
                groundDistance = Math.Max(FlightGlobals.getAltitudeAtPos(part.transform.position), 0.0f);
            }

            // groundPlane.distance is zero if ground is too far away
            if (NearlyEqual(groundPlane.distance, 0.0f) == false)
            {
                // Set ground distance to approximated terrain proximity
                // If the ocean is closer, then the ocean distance will be used
                groundDistance = Math.Min(groundDistance, groundPlane.GetDistanceToPoint(part.transform.position));
                normal         = groundPlane.normal;
            }

            if (Vector3.Dot(originalLift, normal) < 0)
            {
                // ignore downwards facing wings
                return(originalLift);
            }

            // By now, ground distance has been determined

            // Convert ground distance to wing spans between 0.0 .. 1.0
            groundDistance = Math.Min(1.0f, groundDistance / wingSpan);

            if (NearlyEqual(groundDistance, 1.0f))
            {
                // not close enough to the ground, return lift unchanged
                return(originalLift);
            }

            // Confirmed wing is in ground effect

            inGroundEffect = true;


            // Dot product with surface normal is how aligned the wing is to the ground.
            // Vertical stabilizers would have a dot product of zero
            // Horizontal wings will have 1
            float horizontalness = Math.Abs(Vector3.Dot(groundDir, part.transform.forward));


            // at groundDistance = 1.0, groundEffectMul is 1.0
            // as it gets closer to the ground...
            // at groundDistance = 0.0, groundEffectMul = LiftMultiplier
            // y = m(x - 1)^2 + 1
            //float groundEffectMul = (DefaultLiftMultiplier - 1)
            //                      * (float)(Math.Pow(groundDistance - 1.0f, 2.0f))
            //                      + 1;

            // Induced drag:
            // get horizontal velocity = velocity - normal * velocity.dot(normal)
            // normalize horizontal velocity
            // induced drag = horzVelocity * lift.dot(horzVelocity)

            Vector3 velocity         = part.Rigidbody.velocity;
            Vector3 horzVelocity     = (velocity - normal * Vector3.Dot(velocity, normal)).normalized;
            Vector3 protoInducedDrag = horzVelocity * Vector3.Dot(originalLift, horzVelocity);
            Vector3 inducedDrag;

            float dotInducedDrag = Vector3.Dot(velocity, protoInducedDrag);

            if (dotInducedDrag < 0)         // If drag is pulling us the same way as our velocity, something is wrong!
            {
                inducedDrag = Vector3.zero; // dirty, but works I think
            }
            else
            {
                inducedDrag = protoInducedDrag;
            }

            float groundness = horizontalness * (1.0f - groundDistance);

            groundness *= groundness;

            // force = -inducedDrag * groundness + (originalLift - inducedDrag) * DefaultLiftMultiplier * groundness;
            // force = ((originalLift - inducedDrag) * DefaultLiftMultiplier - inducedDrag) * groundness;

            // The problem with this is that it can lead to negative drag for some reason in certain contexts (often
            // involving Tweakscale). Simple dirty fix: ignore the inducedDrag vector if it's gonna cause negative drag.
            // Simple in theory, but there's no good built in way to compare Vector3 objects how I want, so gotta make one.
            //    (See dotInducedDrag and the comparison stuff above.)

            Vector3 force = -inducedDrag * groundness + (originalLift - inducedDrag) * DefaultLiftMultiplier * groundness;

            part.Rigidbody.AddForce(force, ForceMode.Force);

            return(force + originalLift);

            //Vector3 extraLift = (originalLift - inducedDrag) * DefaultLiftMultiplier * (groundDistance - horizontalness + 1.0f);

            //Vector3 extraLift = normal * horizontalness * equation;

            //float totalMag = originalLift.magnitude * DefaultLiftMultiplier;
            //Vector3 newLift = Vector3.Lerp(normal * totalMag, originalLift,
            //                               groundDistance - horizontalness + 1.0f);

            //part.Rigidbody.AddForce(newLift - originalLift, ForceMode.Force);

            //part.Rigidbody.AddForce(newLift - originalLift, ForceMode.Force);

            // return new lift force
            //return newLift;
        }
Ejemplo n.º 24
0
        public float StageTimeLeftFullThrottle()
        {
            MechJebModuleStageStats stats = core.GetComputerModule <MechJebModuleStageStats>();

            stats.RequestUpdate(this);

            if (stats.vacStats.Length == 0 || stats.atmoStats.Length == 0)
            {
                return(0);
            }

            float vacTimeLeft  = stats.vacStats[stats.vacStats.Length - 1].deltaTime;
            float atmoTimeLeft = stats.atmoStats[stats.atmoStats.Length - 1].deltaTime;
            float timeLeft     = Mathf.Lerp(vacTimeLeft, atmoTimeLeft, Mathf.Clamp01((float)FlightGlobals.getStaticPressure()));

            return(timeLeft);
        }
Ejemplo n.º 25
0
 private float CalculateExposure(Vector3d cameraWorldPos)
 {
     staticPressure = (float)(FlightGlobals.getStaticPressure(cameraWorldPos) * KPtoAtms);
     return(Mathf.Lerp(SkyboxExposure, 0f, staticPressure));
 }
Ejemplo n.º 26
0
 public Vessel GetVessel()
 {
     return(FlightGlobals.FindVessel(vesselID));
 }
Ejemplo n.º 27
0
        void FixedUpdate()
        {
            float distanceFromStart = Vector3.Distance(transform.position, startPosition);

            if (!gameObject.activeInHierarchy)
            {
                return;
            }
            flightTimeElapsed += TimeWarp.fixedDeltaTime;       //calculate flight time for drag purposes

            if (bulletDrop && FlightGlobals.RefFrameIsRotating)
            {
                currentVelocity += FlightGlobals.getGeeForceAtPosition(transform.position) * TimeWarp.fixedDeltaTime;
            }
            if (dragType == BulletDragTypes.NumericalIntegration)
            {
                Vector3 dragAcc = currentVelocity * currentVelocity.magnitude * (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position), FlightGlobals.getExternalTemperature(transform.position));
                dragAcc *= 0.5f;
                dragAcc /= ballisticCoefficient;

                currentVelocity -= dragAcc * TimeWarp.fixedDeltaTime;       //numerical integration; using Euler is silly, but let's go with it anyway
            }


            if (tracerLength == 0)
            {
                bulletTrail.SetPosition(0, transform.position + (currentVelocity * tracerDeltaFactor * TimeWarp.fixedDeltaTime / TimeWarp.CurrentRate) - (FlightGlobals.ActiveVessel.rb_velocity * TimeWarp.fixedDeltaTime));
            }
            else
            {
                bulletTrail.SetPosition(0, transform.position + ((currentVelocity - sourceOriginalV).normalized * tracerLength));
            }
            if (fadeColor)
            {
                FadeColor();
                bulletTrail.material.SetColor("_TintColor", currentColor * tracerLuminance);
            }



            bulletTrail.SetPosition(1, transform.position);



            currPosition = gameObject.transform.position;

            if (distanceFromStart > maxDistance)
            {
                //GameObject.Destroy(gameObject);
                KillBullet();
                return;
            }

            if (collisionEnabled)
            {
                float dist = initialSpeed * TimeWarp.fixedDeltaTime;

                Ray        ray = new Ray(prevPosition, currPosition - prevPosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, dist, 557057))
                {
                    bool penetrated = true;

                    float impactVelocity = currentVelocity.magnitude;
                    if (dragType == BulletDragTypes.AnalyticEstimate)
                    {
                        float analyticDragVelAdjustment = (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(currPosition), FlightGlobals.getExternalTemperature(currPosition));
                        analyticDragVelAdjustment *= flightTimeElapsed * initialSpeed;
                        analyticDragVelAdjustment += 2 * ballisticCoefficient;

                        analyticDragVelAdjustment = 2 * ballisticCoefficient * initialSpeed / analyticDragVelAdjustment; //velocity as a function of time under the assumption of a projectile only acted upon by drag with a constant drag area

                        analyticDragVelAdjustment = analyticDragVelAdjustment - initialSpeed;                            //since the above was velocity as a function of time, but we need a difference in drag, subtract the initial velocity
                        //the above number should be negative...
                        impactVelocity += analyticDragVelAdjustment;                                                     //so add it to the impact velocity

                        if (impactVelocity < 0)
                        {
                            impactVelocity = 0;     //clamp the velocity to > 0, since it could drop below 0 if the bullet is fired upwards
                        }
                        //Debug.Log("flight time: " + flightTimeElapsed + " BC: " + ballisticCoefficient + "\ninit speed: " + initialSpeed + " vel diff: " + analyticDragVelAdjustment);
                    }

                    //hitting a vessel Part

                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE START//////////////////////////////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                    Part hitPart = null;                        //determine when bullet collides with a target
                    try{
                        hitPart = Part.FromGO(hit.rigidbody.gameObject);
                    }catch (NullReferenceException) {}

                    float hitAngle = Vector3.Angle(currentVelocity, -hit.normal);
                    if (hitPart != null)                  //see if it will ricochet of the part
                    {
                        penetrated = !RicochetOnPart(hitPart, hitAngle, impactVelocity);
                    }
                    else                     //see if it will ricochet off scenery
                    {
                        float reflectRandom = UnityEngine.Random.Range(-150f, 90f);
                        if (reflectRandom > 90 - hitAngle)
                        {
                            penetrated = false;
                        }
                    }


                    if (hitPart != null && !hitPart.partInfo.name.Contains("Strut"))                                                                             //when a part is hit, execute damage code (ignores struts to keep those from being abused as armor)(no, because they caused weird bugs :) -BahamutoD)
                    {
                        float heatDamage = (mass / (hitPart.crashTolerance * hitPart.mass)) * impactVelocity * impactVelocity * BDArmorySettings.DMG_MULTIPLIER; //how much heat damage will be applied based on bullet mass, velocity, and part's impact tolerance and mass
                        if (!penetrated)
                        {
                            heatDamage = heatDamage / 8;
                        }
                        if (BDArmorySettings.INSTAKILL)                         //instakill support, will be removed once mod becomes officially MP
                        {
                            heatDamage = (float)hitPart.maxTemp + 100;          //make heat damage equal to the part's max temperture, effectively instakilling any part it hits
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LINES)
                        {
                            Debug.Log("Hit! damage applied: " + heatDamage);                                                            //debugging stuff
                        }
                        if (hitPart.vessel != sourceVessel)
                        {
                            hitPart.temperature += heatDamage;                                                      //apply heat damage to the hit part.
                        }
                        float overKillHeatDamage = (float)(hitPart.temperature - hitPart.maxTemp);

                        if (overKillHeatDamage > 0)                       //if the part is destroyed by overheating, we want to add the remaining heat to attached parts.  This prevents using tiny parts as armor
                        {
                            overKillHeatDamage *= hitPart.crashTolerance; //reset to raw damage
                            float numConnectedParts = hitPart.children.Count;
                            if (hitPart.parent != null)
                            {
                                numConnectedParts++;
                                overKillHeatDamage         /= numConnectedParts;
                                hitPart.parent.temperature += overKillHeatDamage / (hitPart.parent.crashTolerance * hitPart.parent.mass);

                                for (int i = 0; i < hitPart.children.Count; i++)
                                {
                                    hitPart.children[i].temperature += overKillHeatDamage / hitPart.children[i].crashTolerance;
                                }
                            }
                            else
                            {
                                overKillHeatDamage /= numConnectedParts;
                                for (int i = 0; i < hitPart.children.Count; i++)
                                {
                                    hitPart.children[i].temperature += overKillHeatDamage / hitPart.children[i].crashTolerance;
                                }
                            }
                        }
                    }

                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    /////////////////////////////////////////////////[panzer1b] HEAT BASED DAMAGE CODE END////////////////////////////////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


                    //hitting a Building
                    DestructibleBuilding hitBuilding = null;
                    try{
                        hitBuilding = hit.collider.gameObject.GetComponentUpwards <DestructibleBuilding>();
                    }
                    catch (NullReferenceException) {}
                    if (hitBuilding != null && hitBuilding.IsIntact)
                    {
                        float damageToBuilding = mass * initialSpeed * initialSpeed * BDArmorySettings.DMG_MULTIPLIER / 12000;
                        if (!penetrated)
                        {
                            damageToBuilding = damageToBuilding / 8;
                        }
                        hitBuilding.AddDamage(damageToBuilding);
                        if (hitBuilding.Damage > hitBuilding.impactMomentumThreshold)
                        {
                            hitBuilding.Demolish();
                        }
                        if (BDArmorySettings.DRAW_DEBUG_LINES)
                        {
                            Debug.Log("bullet hit destructible building! Damage: " + (damageToBuilding).ToString("0.00") + ", total Damage: " + hitBuilding.Damage);
                        }
                    }

                    if (hitPart == null || (hitPart != null && hitPart.vessel != sourceVessel))
                    {
                        if (!penetrated && !hasBounced)
                        {
                            //ricochet
                            hasBounced = true;
                            if (BDArmorySettings.BULLET_HITS)
                            {
                                BulletHitFX.CreateBulletHit(hit.point, hit.normal, true);
                            }

                            tracerStartWidth /= 2;
                            tracerEndWidth   /= 2;

                            transform.position = hit.point;
                            currentVelocity    = Vector3.Reflect(currentVelocity, hit.normal);
                            currentVelocity    = (hitAngle / 150) * currentVelocity * 0.65f;

                            Vector3 randomDirection = UnityEngine.Random.rotation * Vector3.one;

                            currentVelocity = Vector3.RotateTowards(currentVelocity, randomDirection, UnityEngine.Random.Range(0f, 5f) * Mathf.Deg2Rad, 0);
                        }
                        else
                        {
                            if (BDArmorySettings.BULLET_HITS)
                            {
                                BulletHitFX.CreateBulletHit(hit.point, hit.normal, false);
                            }

                            if (bulletType == PooledBulletTypes.Explosive)
                            {
                                ExplosionFX.CreateExplosion(hit.point, radius, blastPower, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                            }

                            //GameObject.Destroy(gameObject); //destroy bullet on collision
                            KillBullet();
                            return;
                        }
                    }
                }

                /*
                 * if(isUnderwater)
                 * {
                 *      if(FlightGlobals.getAltitudeAtPos(transform.position) > 0)
                 *      {
                 *              isUnderwater = false;
                 *      }
                 *      else
                 *      {
                 *              rigidbody.AddForce(-rigidbody.velocity * 0.15f);
                 *      }
                 * }
                 * else
                 * {
                 *      if(FlightGlobals.getAltitudeAtPos(transform.position) < 0)
                 *      {
                 *              isUnderwater = true;
                 *              //FXMonger.Splash(transform.position, 1);
                 *              //make a custom splash here
                 *      }
                 * }
                 */
            }

            if (bulletType == PooledBulletTypes.Explosive && airDetonation && distanceFromStart > detonationRange)
            {
                //detonate
                ExplosionFX.CreateExplosion(transform.position, radius, blastPower, sourceVessel, currentVelocity.normalized, explModelPath, explSoundPath);
                //GameObject.Destroy(gameObject); //destroy bullet on collision
                KillBullet();
                return;
            }


            prevPosition = currPosition;

            //move bullet
            transform.position += currentVelocity * Time.fixedDeltaTime;
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Send new control data to the active vessel.
        /// Checks the vesselSync value to prevent using old ControlPackets after vessel change.
        /// </summary>
        /// <param name="CPacket">Control data</param>
        /// <param name="sync">Current VesselData sync value</param>
        public void ControlsReceived(ControlPacket CPacket, byte sync)
        {
            if (CPacket.vesselSync == sync)
            {
                //Detect vessel change
                _vControls.vesselSync = CPacket.vesselSync;
                bool vesselChanged = _vControls.vesselSync != _vControlsOld.vesselSync;
                _vControlsOld.vesselSync = _vControls.vesselSync;


                _vControls.SAS           = BitMathByte(CPacket.MainControls, 7);
                _vControls.RCS           = BitMathByte(CPacket.MainControls, 6);
                _vControls.Lights        = BitMathByte(CPacket.MainControls, 5);
                _vControls.Gear          = BitMathByte(CPacket.MainControls, 4);
                _vControls.Brakes        = BitMathByte(CPacket.MainControls, 3);
                _vControls.Precision     = BitMathByte(CPacket.MainControls, 2);
                _vControls.Abort         = BitMathByte(CPacket.MainControls, 1);
                _vControls.Stage         = BitMathByte(CPacket.MainControls, 0);
                _vControls.Pitch         = (float)CPacket.Pitch / 1000.0F;
                _vControls.Roll          = (float)CPacket.Roll / 1000.0F;
                _vControls.Yaw           = (float)CPacket.Yaw / 1000.0F;
                _vControls.TX            = (float)CPacket.TX / 1000.0F;
                _vControls.TY            = (float)CPacket.TY / 1000.0F;
                _vControls.TZ            = (float)CPacket.TZ / 1000.0F;
                _vControls.WheelSteer    = (float)CPacket.WheelSteer / 1000.0F;
                _vControls.Throttle      = (float)CPacket.Throttle / 1000.0F;
                _vControls.WheelThrottle = (float)CPacket.WheelThrottle / 1000.0F;
                _vControls.SASMode       = (int)CPacket.NavballSASMode & 0x0F;
                _vControls.SpeedMode     = (int)(CPacket.NavballSASMode >> 4);
                _vControls.UiMode        = (int)CPacket.Mode & 0x0F;
                _vControls.CameraMode    = (int)(CPacket.Mode >> 4);
                _vControls.OpenMenu      = BitMathByte(CPacket.AdditionalControlByte1, 0);
                _vControls.OpenMap       = BitMathByte(CPacket.AdditionalControlByte1, 1);

                for (int j = 1; j <= 10; j++)
                {
                    _vControls.ControlGroup[j] = BitMathUshort(CPacket.ControlGroup, j);
                }


                //if (FlightInputHandler.RCSLock != VControls.RCS)
                if (_vControls.RCS != _vControlsOld.RCS || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, _vControls.RCS);
                    _vControlsOld.RCS = _vControls.RCS;
                    //ScreenMessages.PostScreenMessage("RCS: " + VControls.RCS.ToString(), 10f, KSPIOScreenStyle);
                }

                //if (ActiveVessel.ctrlState.killRot != VControls.SAS)
                if (_vControls.SAS != _vControlsOld.SAS || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, _vControls.SAS);
                    _vControlsOld.SAS = _vControls.SAS;
                    //ScreenMessages.PostScreenMessage("SAS: " + VControls.SAS.ToString(), 10f, KSPIOScreenStyle);
                }

                if (_vControls.Lights != _vControlsOld.Lights || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Light, _vControls.Lights);
                    _vControlsOld.Lights = _vControls.Lights;
                }

                if (_vControls.Gear != _vControlsOld.Gear || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, _vControls.Gear);
                    _vControlsOld.Gear = _vControls.Gear;
                }

                if (_vControls.Brakes != _vControlsOld.Brakes || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, _vControls.Brakes);
                    _vControlsOld.Brakes = _vControls.Brakes;
                }

                if (_vControls.Abort != _vControlsOld.Abort || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Abort, _vControls.Abort);
                    _vControlsOld.Abort = _vControls.Abort;
                }

                if (_vControls.Stage != _vControlsOld.Stage || vesselChanged)
                {
                    if (_vControls.Stage)
                    {
                        StageManager.ActivateNextStage();
                    }

                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Stage, _vControls.Stage);
                    _vControlsOld.Stage = _vControls.Stage;
                }

                //================ control groups

                if (_vControls.ControlGroup[1] != _vControlsOld.ControlGroup[1] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom01, _vControls.ControlGroup[1]);
                    _vControlsOld.ControlGroup[1] = _vControls.ControlGroup[1];
                }

                if (_vControls.ControlGroup[2] != _vControlsOld.ControlGroup[2] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom02, _vControls.ControlGroup[2]);
                    _vControlsOld.ControlGroup[2] = _vControls.ControlGroup[2];
                }

                if (_vControls.ControlGroup[3] != _vControlsOld.ControlGroup[3] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom03, _vControls.ControlGroup[3]);
                    _vControlsOld.ControlGroup[3] = _vControls.ControlGroup[3];
                }

                if (_vControls.ControlGroup[4] != _vControlsOld.ControlGroup[4] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom04, _vControls.ControlGroup[4]);
                    _vControlsOld.ControlGroup[4] = _vControls.ControlGroup[4];
                }

                if (_vControls.ControlGroup[5] != _vControlsOld.ControlGroup[5] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom05, _vControls.ControlGroup[5]);
                    _vControlsOld.ControlGroup[5] = _vControls.ControlGroup[5];
                }

                if (_vControls.ControlGroup[6] != _vControlsOld.ControlGroup[6] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom06, _vControls.ControlGroup[6]);
                    _vControlsOld.ControlGroup[6] = _vControls.ControlGroup[6];
                }

                if (_vControls.ControlGroup[7] != _vControlsOld.ControlGroup[7] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom07, _vControls.ControlGroup[7]);
                    _vControlsOld.ControlGroup[7] = _vControls.ControlGroup[7];
                }

                if (_vControls.ControlGroup[8] != _vControlsOld.ControlGroup[8] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom08, _vControls.ControlGroup[8]);
                    _vControlsOld.ControlGroup[8] = _vControls.ControlGroup[8];
                }

                if (_vControls.ControlGroup[9] != _vControlsOld.ControlGroup[9] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom09, _vControls.ControlGroup[9]);
                    _vControlsOld.ControlGroup[9] = _vControls.ControlGroup[9];
                }

                if (_vControls.ControlGroup[10] != _vControlsOld.ControlGroup[10] || vesselChanged)
                {
                    _activeVessel.ActionGroups.SetGroup(KSPActionGroup.Custom10, _vControls.ControlGroup[10]);
                    _vControlsOld.ControlGroup[10] = _vControls.ControlGroup[10];
                }

                //Set sas mode
                if (_vControls.SASMode != _vControlsOld.SASMode || vesselChanged)
                {
                    if (_vControls.SASMode != 0 && _vControls.SASMode < 11)
                    {
                        if (!_activeVessel.Autopilot.CanSetMode((VesselAutopilot.AutopilotMode)(_vControls.SASMode - 1)))
                        {
                            ScreenMessages.PostScreenMessage("[KSPEthernetIO]: SAS mode " + _vControls.SASMode.ToString() + " not avalible");
                        }
                        else
                        {
                            _activeVessel.Autopilot.SetMode((VesselAutopilot.AutopilotMode)_vControls.SASMode - 1);
                        }
                    }
                    _vControlsOld.SASMode = _vControls.SASMode;
                }

                //set navball mode
                if (_vControls.SpeedMode != _vControlsOld.SpeedMode || vesselChanged)
                {
                    if (!((_vControls.SpeedMode == 0) || ((_vControls.SpeedMode == 3) && !TargetExists())))
                    {
                        FlightGlobals.SetSpeedMode((FlightGlobals.SpeedDisplayModes)(_vControls.SpeedMode - 1));
                    }
                    _vControlsOld.SpeedMode = _vControls.SpeedMode;
                }


                if (Math.Abs(_vControls.Pitch) > Settings.SASTol ||
                    Math.Abs(_vControls.Roll) > Settings.SASTol ||
                    Math.Abs(_vControls.Yaw) > Settings.SASTol)
                {
                    if ((_activeVessel.ActionGroups[KSPActionGroup.SAS]) && (_wasSASOn == false))
                    {
                        _wasSASOn = true;
                        _activeVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false);
                    }
                }
                else
                {
                    if (_wasSASOn == true)
                    {
                        _wasSASOn = false;
                        _activeVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true);
                    }
                }

                if (_vControlsOld.UiMode != _vControls.UiMode || vesselChanged)
                {
                    if (FlightUIModeController.Instance != null)
                    {
                        switch (_vControls.UiMode)
                        {
                        case 0:
                            FlightUIModeController.Instance.SetMode(FlightUIMode.STAGING);
                            break;

                        case 1:
                            FlightUIModeController.Instance.SetMode(FlightUIMode.DOCKING);
                            break;

                        case 2:
                            FlightUIModeController.Instance.SetMode(FlightUIMode.MAPMODE);
                            break;

                        default:
                            break;
                        }
                        _vControlsOld.UiMode = _vControls.UiMode;
                    }
                }

                if (_vControlsOld.CameraMode != _vControls.CameraMode || vesselChanged)
                {
                    if (FlightCamera.fetch != null)
                    {
                        switch (_vControls.CameraMode)
                        {
                        case 0:
                            FlightCamera.fetch.setMode(FlightCamera.Modes.AUTO);
                            break;

                        case 1:
                            FlightCamera.fetch.setMode(FlightCamera.Modes.FREE);
                            break;

                        case 2:
                            FlightCamera.fetch.setMode(FlightCamera.Modes.ORBITAL);
                            break;

                        case 3:
                            FlightCamera.fetch.setMode(FlightCamera.Modes.CHASE);
                            break;

                        case 4:
                            FlightCamera.fetch.setMode(FlightCamera.Modes.LOCKED);
                            break;

                        default:
                            break;
                        }
                        _vControlsOld.CameraMode = _vControls.CameraMode;
                    }
                }

                if (_vControlsOld.OpenMenu != _vControls.OpenMenu || vesselChanged)
                {
                    if (_vControls.OpenMenu)
                    {
                        PauseMenu.Display();
                    }
                    else
                    {
                        PauseMenu.Close();
                    }
                    _vControlsOld.OpenMenu = _vControls.OpenMenu;
                }

                if (_vControlsOld.OpenMap != _vControls.OpenMap || vesselChanged)
                {
                    if (_vControls.OpenMap)
                    {
                        MapView.EnterMapView();
                    }
                    else
                    {
                        MapView.ExitMapView();
                    }
                    _vControlsOld.OpenMap = _vControls.OpenMap;
                }
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Updates this instance
        /// </summary>
        void LateUpdate()
        {
            // Set precision
            sunRotationPrecision = MapView.MapIsEnabled ? sunRotationPrecisionMapView : sunRotationPrecisionDefault;

            // Apply light settings
            Vector3d localSpace = ScaledSpace.ScaledToLocalSpace(target.position);

            if (light)
            {
                light.color     = shifter.sunlightColor;
                light.intensity =
                    shifter.intensityCurve.Evaluate((Single)Vector3d.Distance(sun.position, localSpace));
                light.shadowStrength = shifter.sunlightShadowStrength;
            }

            // Patch the ScaledSpace light
            if (scaledSunLight)
            {
                scaledSunLight.color     = shifter.scaledSunlightColor;
                scaledSunLight.intensity = shifter.scaledIntensityCurve.Evaluate((Single)Vector3d.Distance(ScaledSpace.LocalToScaledSpace(sun.position), target.position));
            }

            if (HighLogic.LoadedSceneIsFlight && iva?.GetComponent <Light>())
            {
                iva.GetComponent <Light>().color     = shifter.IVASunColor;
                iva.GetComponent <Light>().intensity = shifter.ivaIntensityCurve.Evaluate((Single)Vector3d.Distance(sun.position, localSpace));
            }

            // Set SunFlare color
            lensFlare.sunFlare.color = shifter.sunLensFlareColor;

            // Set other stuff
            lensFlare.AU = shifter.AU;
            lensFlare.brightnessCurve = shifter.brightnessCurve.Curve;
            lensFlare.sun             = sun;
            lensFlare.target          = target;

            // States
            Boolean lightsOn = (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneHasPlanetarium || HighLogic.LoadedScene == GameScenes.SPACECENTER);

            light.enabled = shifter.givesOffLight && lightsOn;
            lensFlare.sunFlare.enabled = shifter.givesOffLight && lightsOn;
            sunFlare.enabled           = false;
            if (useLocalSpaceSunLight && Sun.Instance.useLocalSpaceSunLight)
            {
                scaledSunLight.enabled = shifter.givesOffLight && lightsOn;
            }
            if (Current != null && Current.lensFlare != null)
            {
                SunFlare.Instance = Current.lensFlare;
            }

            // Update Scaled Space Light
            if (!useLocalSpaceSunLight)
            {
                return;
            }
            if (FlightGlobals.currentMainBody == null || FlightGlobals.currentMainBody == sun)
            {
                localTime = 1f;
            }
            else
            {
                Double targetAltitude = FlightGlobals.getAltitudeAtPos(localSpace, FlightGlobals.currentMainBody);
                if (targetAltitude < 0)
                {
                    targetAltitude = 0;
                }
                Double horizonAngle   = Math.Acos(FlightGlobals.currentMainBody.Radius / (FlightGlobals.currentMainBody.Radius + targetAltitude));
                Single horizonScalar  = -Mathf.Sin((Single)horizonAngle);
                Single dayNightRatio  = 1f - Mathf.Abs(horizonScalar);
                Single fadeStartAtAlt = horizonScalar + fadeStart * dayNightRatio;
                Single fadeEndAtAlt   = horizonScalar - fadeEnd * dayNightRatio;
                localTime       = Vector3.Dot(-FlightGlobals.getUpAxis(localSpace), transform.forward);
                light.intensity = Mathf.Lerp(0f, light.intensity, Mathf.InverseLerp(fadeEndAtAlt, fadeStartAtAlt, localTime));
            }
        }
Ejemplo n.º 30
0
 public void SetNavMode(FlightGlobals.SpeedDisplayModes navMode)
 {
     FlightGlobals.SetSpeedMode(navMode);
 }
Ejemplo n.º 31
0
        /// <summary>
        /// The flight integrator doesn't seem to update the EVA kerbal's position or velocity for about 0.95s of real-time for some unknown reason (this seems fairly constant regardless of time-control or FPS).
        /// </summary>
        /// <param name="kerbal">The kerbal on EVA.</param>
        /// <param name="realTime">The amount of real-time to manually update for.</param>
        IEnumerator ManuallyMoveKerbalEVACoroutine(KerbalEVA kerbal, Vector3 velocity, float realTime = 1f)
        {
            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                Debug.Log("[BDArmory.KerbalSafety]: Manually setting position of " + kerbal.vessel.vesselName + " for " + realTime + "s of real-time.");
            }
            if (!evaKerbalsToMonitor.Contains(kerbal))
            {
                evaKerbalsToMonitor.Add(kerbal);
            }
            var   gee                     = (Vector3)FlightGlobals.getGeeForceAtPosition(kerbal.transform.position);
            var   verticalSpeed           = Vector3.Dot(-gee.normalized, velocity);
            float verticalSpeedAdjustment = 0f;
            var   position                = kerbal.vessel.GetWorldPos3D();

            if (kerbal.vessel.radarAltitude + verticalSpeed * Time.fixedDeltaTime < 2f) // Crashed into terrain, explode upwards.
            {
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    verticalSpeedAdjustment = 3f * (float)gee.magnitude - verticalSpeed;
                }
                velocity  = Vector3.ProjectOnPlane(velocity, -gee.normalized) - 3f * (gee + UnityEngine.Random.onUnitSphere * 0.3f * gee.magnitude);
                position += (2f - (float)kerbal.vessel.radarAltitude) * -gee.normalized;
                kerbal.vessel.SetPosition(position); // Put the kerbal back at just above gound level.
                kerbal.vessel.Landed = false;
            }
            else
            {
                velocity += 1.5f * -(gee + UnityEngine.Random.onUnitSphere * 0.3f * gee.magnitude);
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    verticalSpeedAdjustment = 1.5f * (float)gee.magnitude;
                }
            }
            verticalSpeed = Vector3.Dot(-gee.normalized, velocity);
            kerbal.vessel.SetRotation(UnityEngine.Random.rotation);
            kerbal.vessel.rootPart.AddTorque(UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(1, 2));
            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                Debug.Log("[BDArmory.KerbalSafety]: Setting " + kerbal.vessel.vesselName + "'s position to " + position.ToString("0.00") + " (" + kerbal.vessel.GetWorldPos3D().ToString("0.00") + ", altitude: " + kerbal.vessel.radarAltitude.ToString("0.00") + ") and velocity to " + velocity.magnitude.ToString("0.00") + " (" + verticalSpeed.ToString("0.00") + "m/s vertically, adjusted by " + verticalSpeedAdjustment.ToString("0.00") + "m/s)");
            }
            var startTime = Time.realtimeSinceStartup;

            kerbal.vessel.rootPart.SetDetectCollisions(false);
            while (kerbal != null && kerbal.isActiveAndEnabled && kerbal.vessel != null && kerbal.vessel.isActiveAndEnabled && Time.realtimeSinceStartup - startTime < realTime)
            {
                // Note: 0.968f gives a reduction in speed to ~20% over 1s.
                if (verticalSpeed < 0f && kerbal.vessel.radarAltitude + verticalSpeed * (realTime - (Time.realtimeSinceStartup - startTime)) < 100f)
                {
                    velocity = velocity * 0.968f + gee * verticalSpeed / 10f * Time.fixedDeltaTime;
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        verticalSpeedAdjustment = Vector3.Dot(-gee.normalized, gee * verticalSpeed / 10f * Time.fixedDeltaTime);
                    }
                }
                else
                {
                    velocity = velocity * 0.968f + gee * Time.fixedDeltaTime;
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        verticalSpeedAdjustment = Vector3.Dot(-gee.normalized, gee * Time.fixedDeltaTime);
                    }
                }
                verticalSpeed = Vector3.Dot(-gee.normalized, velocity);
                position     += velocity * Time.fixedDeltaTime - FloatingOrigin.Offset;
                kerbal.vessel.IgnoreGForces(1);
                kerbal.vessel.IgnoreSpeed(1);
                kerbal.vessel.SetPosition(position);
                kerbal.vessel.SetWorldVelocity(velocity + Krakensbane.GetLastCorrection());
                yield return(new WaitForFixedUpdate());

                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BDArmory.KerbalSafety]: Setting " + kerbal.vessel.vesselName + "'s position to " + position.ToString("0.00") + " (" + kerbal.vessel.GetWorldPos3D().ToString("0.00") + ", altitude: " + kerbal.vessel.radarAltitude.ToString("0.00") + ") and velocity to " + velocity.magnitude.ToString("0.00") + " (" + kerbal.vessel.Velocity().magnitude.ToString("0.00") + ", " + verticalSpeed.ToString("0.00") + "m/s vertically, adjusted by " + verticalSpeedAdjustment.ToString("0.00") + "m/s)." + " (offset: " + !FloatingOrigin.Offset.IsZero() + ", frameVel: " + !Krakensbane.GetFrameVelocity().IsZero() + ")" + " " + Krakensbane.GetFrameVelocityV3f().ToString("0.0") + ", corr: " + Krakensbane.GetLastCorrection().ToString("0.0"));
                }
            }
            if (kerbal != null && kerbal.vessel != null)
            {
                kerbal.vessel.rootPart.SetDetectCollisions(true);
            }
            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                for (int count = 0; kerbal != null && kerbal.isActiveAndEnabled && kerbal.vessel != null && kerbal.vessel.isActiveAndEnabled && count < 10; ++count)
                {
                    yield return(new WaitForFixedUpdate());

                    Debug.Log("[BDArmory.KerbalSafety]: Tracking " + kerbal.vessel.vesselName + "'s position to " + kerbal.vessel.GetWorldPos3D().ToString("0.00") + " (altitude: " + kerbal.vessel.radarAltitude.ToString("0.00") + ") and velocity to " + kerbal.vessel.Velocity().magnitude.ToString("0.00") + " (" + kerbal.vessel.verticalSpeed.ToString("0.00") + "m/s vertically." + " (offset: " + !FloatingOrigin.Offset.IsZero() + ", frameVel: " + !Krakensbane.GetFrameVelocity().IsZero() + ")" + " " + Krakensbane.GetFrameVelocityV3f().ToString("0.0") + ", corr: " + Krakensbane.GetLastCorrection().ToString("0.0"));
                }
            }
        }