示例#1
0
 void decelerate(bool collision_detected)
 {
     VSL.Controls.StopWarp();
     DecelerationTimer.Reset();
     landing_stage = LandingStage.Decelerate;
     Working       = collision_detected;
 }
示例#2
0
 public override void Init()
 {
     base.Init();
     Dtol = LTRJ.Dtol;
     CorrectionTimer.Period = LTRJ.CorrectionTimer;
     StageTimer.action      = () =>
     {
         VSL.ActivateNextStage();
         Message("Have to drop ballast to decelerate...");
     };
     dP_up_timer.action = () =>
     {
         dP_threshold = Utils.ClampL(dP_threshold * 0.9, LTRJ.MinDPressure);
         last_dP      = VSL.vessel.dynamicPressurekPa;
     };
     dP_down_timer.action = () =>
     {
         dP_threshold = Utils.ClampH(dP_threshold * 1.1, LTRJ.MaxDPressure);
         last_dP      = VSL.vessel.dynamicPressurekPa;
     };
     NoEnginesTimer.action = () =>
     {
         landing_stage = LandingStage.HardLanding;
     };
     sim                  = new AtmoSim(VSL);
     Executor             = new ManeuverExecutor(TCA);
     scanner              = new PQS_Scanner(VSL);
     scanner.MaxUnevennes = GLB.LND.MaxUnevenness / 3;
     dP_threshold         = LTRJ.MaxDPressure;
     last_Err             = 0;
     last_dP              = 0;
     Working              = false;
 }
示例#3
0
        void decelerate(bool collision_detected)
        {
            VSL.Controls.StopWarp();
            DecelerationTimer.Reset();
            landing_stage = LandingStage.Decelerate;
            Working       = collision_detected;
//			Log("Current Trajectory:\n{}", trajectory);//debug
        }
示例#4
0
 void land()
 {
     if (CFG.Target != null && !CFG.Target.IsVessel)
     {
         LND.StartFromTarget();
     }
     CFG.AP1.On(Autopilot1.Land);
     landing_stage = LandingStage.Land;
 }
示例#5
0
 protected void start_landing()
 {
     Working = false;
     clear_nodes();
     update_trajectory();
     VSL.Controls.StopWarp();
     VSL.Controls.Aligned     = false;
     CFG.AltitudeAboveTerrain = false;
     landing_stage            = LandingStage.Wait;
     PressureASL = Body.GetPressure(0);
 }
示例#6
0
 protected override void reset()
 {
     base.reset();
     landing_stage = LandingStage.None;
     DecelerationTimer.Reset();
     dP_up_timer.Reset();
     dP_down_timer.Reset();
     dP_threshold = LTRJ.MaxDPressure;
     last_Err     = 0;
     last_dP      = 0;
     Working      = false;
 }
示例#7
0
 void approach()
 {
     CFG.BR.Off();
     CFG.BlockThrottle        = true;
     CFG.AltitudeAboveTerrain = true;
     CFG.VF.On(VFlight.AltitudeControl);
     CFG.DesiredAltitude = LTRJ.ApproachAlt < VSL.Altitude.Relative / 2?
                           LTRJ.ApproachAlt : Utils.ClampL(VSL.Altitude.Relative / 2, VSL.Geometry.H * 2);
     SetTarget(CFG.Target);
     CFG.Nav.On(Navigation.GoToTarget);
     if (CFG.Target.IsVessel)
     {
         CFG.Target.Radius = 7;
     }
     landing_stage = LandingStage.Approach;
 }
示例#8
0
    void BlastOff()
    {
        _landingStage = LandingStage.CantLand;
        _sr.sprite = RegularSprite;

        float radius = 0.0f;
        if (_landingObj == _Earth)
            radius = 10.0f;
        else if (IsAsteroid(_landingObj)) {
            radius = 13.0f;
        }

        Vector2 random = (new Vector2 (Random.Range (-1.0f, 1.0f), Random.Range (-1.0f, 1.0f))).normalized;
        Vector3 delta = radius * random;
        transform.position = transform.position + delta;

        _landingObj = null;
        HideText ();
    }
示例#9
0
 void CancelLandingPreparations(GameObject _Earth)
 {
     _landingStage = LandingStage.CantLand;
     _landingObj = null;
     HideText ();
 }
示例#10
0
 void PrepareToLandOn(GameObject target)
 {
     _landingStage = LandingStage.CanLand;
     _landingObj = target;
     ShowText ("Y to land on " + _landingObj.name);
 }
示例#11
0
 void InitiateLandingSequence()
 {
     _landingStage = LandingStage.Landing;
     _sr.sprite = LandingSprite;
     _landingStartTime = Time.time;
 }
示例#12
0
    /// <summary>
    /// Finalizes the landing. Extracts resources, adds to inventory.
    /// </summary>
    void FinalizeLanding()
    {
        _landingStage = LandingStage.Landed;
        _sr.sprite = LandedSprite;

        if (IsAsteroid (_landingObj)) {
            // Extract resources from this asteroid and add them to inventory
            this.GetComponent<Inventory> ().MineralXAmt += _landingObj.GetComponent<AsteroidValue> ().Extract ();
            ShowText ("Y to blast off");
        } else {
            Inventory i = this.GetComponent<Inventory>();
            i.returnedAmt += i.MineralXAmt;
            i.MineralXAmt = 0;
            ShowText ("A to upgrade; Y to blast off");
        }
    }
示例#13
0
        protected bool do_land()
        {
            if (VSL.LandedOrSplashed)
            {
                THR.Throttle = 0;
                SetTarget();
                ClearStatus();
                CFG.AP2.Off();
                return(true);
            }
            VSL.Engines.ActivateEngines();
            if (VSL.Engines.MaxThrustM.Equals(0) && !VSL.Engines.HaveNextStageEngines)
            {
                landing_stage = LandingStage.HardLanding;
            }
            landing_deadzone = VSL.Geometry.D + CFG.Target.AbsRadius;
            if (VSL.vessel.dynamicPressurekPa > 0)
            {
                if (!dP_up_timer.RunIf(VSL.Controls.AttitudeError > last_Err ||
                                       Mathf.Abs(VSL.Controls.AttitudeError - last_Err) < 0.01f))
                {
                    dP_down_timer.RunIf(VSL.Controls.AttitudeError < last_Err &&
                                        VSL.vessel.dynamicPressurekPa < last_dP);
                }
            }
            else
            {
                dP_threshold = LTRJ.MaxDPressure;
            }
            rel_dP   = VSL.vessel.dynamicPressurekPa / dP_threshold;
            last_Err = VSL.Controls.AttitudeError;
            float    rel_Ve;
            double   terminal_velocity;
            Vector3d brake_pos, brake_vel, obt_vel;

            switch (landing_stage)
            {
            case LandingStage.Wait:
                Status("Preparing for deceleration...");
                THR.Throttle = 0;
                update_trajectory();
                nose_to_target();
                rel_altitude_if_needed();
                obt_vel   = VesselOrbit.getOrbitalVelocityAtUT(trajectory.BrakeStartUT);
                brake_pos = VesselOrbit.getRelativePositionAtUT(trajectory.BrakeStartUT);
                brake_vel = corrected_brake_velocity(obt_vel, brake_pos);
                brake_vel = corrected_brake_direction(brake_vel, brake_pos.xzy);
                CFG.AT.OnIfNot(Attitude.Custom);
                ATC.SetThrustDirW(brake_vel);
                VSL.Info.Countdown = trajectory.BrakeEndUT - VSL.Physics.UT - 1
                                     - Math.Max(MatchVelocityAutopilot.BrakingOffset((float)obt_vel.magnitude, VSL, out VSL.Info.TTB),
                                                LTRJ.MinBrakeOffset * (1 - Utils.ClampH(Body.atmDensityASL, 1)));
                correct_attitude_with_thrusters(VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError));
                if (obstacle_ahead(trajectory) > 0)
                {
                    decelerate(true); break;
                }
                if (VSL.Info.Countdown <= rel_dP)
                {
                    decelerate(false); break;
                }
                if (VSL.Controls.CanWarp)
                {
                    VSL.Controls.WarpToTime = VSL.Physics.UT + VSL.Info.Countdown;
                }
                else
                {
                    VSL.Controls.StopWarp();
                }
                break;

            case LandingStage.Decelerate:
                rel_altitude_if_needed();
                update_trajectory();
                nose_to_target();
                if (Working)
                {
                    Status("red", "Possible collision detected.");
                    correct_attitude_with_thrusters(VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError));
                    Executor.Execute(VSL.Physics.Up * 10);
                    if (obstacle_ahead(trajectory) > 0)
                    {
                        CollisionTimer.Reset(); break;
                    }
                    if (!CollisionTimer.TimePassed)
                    {
                        break;
                    }
                    start_landing();
                    break;
                }
                else
                {
                    Status("white", "Decelerating. Landing site error: {0}",
                           Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                    compute_terminal_velocity();
                    if (VSL.Controls.HaveControlAuthority)
                    {
                        DecelerationTimer.Reset();
                    }
                    if (Vector3d.Dot(VSL.HorizontalSpeed.Vector, CFG.Target.WorldPos(Body) - VSL.Physics.wCoM) < 0)
                    {
                        if (Executor.Execute(-VSL.vessel.srf_velocity, LTRJ.BrakeEndSpeed))
                        {
                            break;
                        }
                    }
                    else if (!DecelerationTimer.TimePassed &&
                             trajectory.DistanceToTarget > landing_deadzone &&
                             Vector3d.Dot(CFG.Target.VectorTo(trajectory.SurfacePoint, Body), VSL.HorizontalSpeed.Vector) > 0)
                    {
                        brake_vel = corrected_brake_velocity(VesselOrbit.vel, VesselOrbit.pos);
                        brake_vel = corrected_brake_direction(brake_vel, VesselOrbit.pos.xzy);
                        //this is nice smoothing, but is dangerous on a low decending trajectory
                        VSL.Info.TTB = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                        if (VSL.Info.Countdown - VSL.Torque.MaxCurrent.TurnTime - VSL.vessel.dynamicPressurekPa > VSL.Info.TTB)
                        {
                            brake_vel = brake_vel.normalized * VSL.HorizontalSpeed.Absolute * Utils.ClampH(trajectory.DistanceToTarget / CFG.Target.DistanceTo(VSL.vessel), 1);
                        }
                        if (Executor.Execute(-brake_vel, (float)Utils.ClampL(LTRJ.BrakeEndSpeed * Body.GeeASL, GLB.THR.MinDeltaV)))
                        {
                            break;
                        }
                    }
                }
                landing_stage = LandingStage.Coast;
                break;

            case LandingStage.Coast:
                Status("white", "Coasting. Landing site error: {0}", Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                THR.Throttle = 0;
                update_trajectory();
                nose_to_target();
                setup_for_deceleration();
                terminal_velocity = compute_terminal_velocity();
                correct_attitude_with_thrusters(VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError));
                correct_landing_site();
                VSL.Info.TTB        = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                VSL.Info.Countdown -= Math.Max(VSL.Info.TTB + VSL.Torque.NoEngines.TurnTime + VSL.vessel.dynamicPressurekPa, TRJ.ManeuverOffset);
                if (VSL.Info.Countdown <= 0)
                {
                    Working = false;
                    rel_Ve  = VSL.Engines.RelVeASL;
                    if (rel_Ve <= 0)
                    {
                        Message(10, "Not enough thrust to land properly.\nPerforming emergency landing...");
                        landing_stage = LandingStage.HardLanding;
                        break;
                    }
                    if (!(VSL.Controls.HaveControlAuthority || VSL.Torque.HavePotentialControlAuthority))
                    {
                        Message(10, "Lacking control authority to land properly.\nPerforming emergency landing...");
                        landing_stage = LandingStage.HardLanding;
                        break;
                    }
                    var fuel_left   = VSL.Engines.GetAvailableFuelMass();
                    var fuel_needed = VSL.Engines.FuelNeeded((float)terminal_velocity, rel_Ve);
                    if (!CheatOptions.InfinitePropellant &&
                        (fuel_needed >= fuel_left ||
                         VSL.Engines.MaxHoverTimeASL(fuel_left - fuel_needed) < LTRJ.HoverTimeThreshold))
                    {
                        Message(10, "Not enough fuel to land properly.\nPerforming emergency landing...");
                        landing_stage = LandingStage.HardLanding;
                        break;
                    }
                    landing_stage = LandingStage.SoftLanding;
                }
                break;

            case LandingStage.HardLanding:
                Status("yellow", "Emergency Landing...");
                set_destination_vector();
                update_trajectory();
                VSL.BrakesOn();
                CFG.BR.Off();
                setup_for_deceleration();
                terminal_velocity = compute_terminal_velocity();
                if (VSL.Engines.MaxThrustM > 0 &&
                    (VSL.Controls.HaveControlAuthority || VSL.Torque.HavePotentialControlAuthority))
                {
                    rel_Ve = VSL.Engines.RelVeASL;
                    var fuel_left   = VSL.Engines.GetAvailableFuelMass();
                    var fuel_needed = rel_Ve > 0? VSL.Engines.FuelNeeded((float)terminal_velocity, rel_Ve) : fuel_left * 2;
                    VSL.Info.Countdown -= fuel_left > fuel_needed?
                                          VSL.Engines.TTB((float)terminal_velocity) :
                                              VSL.Engines.TTB(VSL.Engines.DeltaV(fuel_left));

                    if ((VSL.Info.Countdown < 0 &&
                         (!VSL.OnPlanetParams.HaveParachutes ||
                          VSL.OnPlanetParams.ParachutesActive && VSL.OnPlanetParams.ParachutesDeployed)))
                    {
                        THR.Throttle = VSL.VerticalSpeed.Absolute < -5? 1 : VSL.OnPlanetParams.GeeVSF;
                    }
                    else
                    {
                        THR.Throttle = 0;
                    }
                    Status("yellow", "Not enough fuel to land properly.\nWill deceletate as much as possible before impact...");
                }
                if (Body.atmosphere && VSL.OnPlanetParams.HaveUsableParachutes)
                {
                    VSL.OnPlanetParams.ActivateParachutes();
                    if (!VSL.OnPlanetParams.ParachutesActive)
                    {
                        ATC.SetCustomRotationW(VSL.Geometry.MaxAreaDirection, VSL.Physics.Up);
                        StageTimer.RunIf(Body.atmosphere &&                         //!VSL.Controls.HaveControlAuthority &&
                                         VSL.vessel.currentStage - 1 > VSL.OnPlanetParams.NearestParachuteStage &&
                                         VSL.vessel.dynamicPressurekPa > LTRJ.DropBallastThreshold * PressureASL &&
                                         VSL.vessel.mach > LTRJ.MachThreshold);
                        if (CFG.AutoParachutes)
                        {
                            Status("yellow", "Waiting for safe speed to deploy parachutes.\n" +
                                   "Trying to decelerate using drag...");
                        }
                        else
                        {
                            Status("red", "Automatic parachute deployment is disabled.\nActivate parachutes manually when needed.");
                        }
                    }
                }
                if (!VSL.OnPlanetParams.HaveParachutes &&
                    !VSL.Engines.HaveNextStageEngines &&
                    (VSL.Engines.MaxThrustM.Equals(0) || !VSL.Controls.HaveControlAuthority))
                {
                    if (Body.atmosphere)
                    {
                        ATC.SetCustomRotationW(VSL.Geometry.MaxAreaDirection, VSL.Physics.Up);
                    }
                    Status("red", "Crash is imminent.\nImpact speed: {0}", Utils.formatBigValue((float)terminal_velocity, "m/s"));
                }
                break;

            case LandingStage.SoftLanding:
                THR.Throttle = 0;
                set_destination_vector();
                update_trajectory();
                setup_for_deceleration();
                compute_terminal_velocity();
                nose_to_target();
                if (Working)
                {
                    Status("white", "Final deceleration. Landing site error: {0}",
                           Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                    ATC.SetThrustDirW(correction_direction());
                    if (VSL.Altitude.Relative > GLB.LND.WideCheckAltitude)
                    {
                        var brake_spd  = Mathf.Max(VSL.HorizontalSpeed.Absolute, -VSL.VerticalSpeed.Absolute);
                        var min_thrust = Utils.Clamp(brake_spd / (VSL.Engines.MaxAccel - VSL.Physics.G) /
                                                     Utils.ClampL((float)VSL.Info.Countdown, 0.01f),
                                                     VSL.OnPlanetParams.GeeVSF, 1);
                        THR.Throttle = Utils.Clamp(brake_spd / LTRJ.BrakeThrustThreshod, min_thrust, 1);
                    }
                    else
                    {
                        THR.Throttle = 1;
                    }
                    if (VSL.vessel.srfSpeed > LTRJ.BrakeEndSpeed)
                    {
                        Working = THR.Throttle.Equals(1) || VSL.Info.Countdown < 10;
                        break;
                    }
                }
                else
                {
                    var turn_time = VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError);
                    correct_attitude_with_thrusters(turn_time);
                    correct_landing_site();
                    VSL.Info.TTB        = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                    VSL.Info.Countdown -= VSL.Info.TTB + turn_time + LTRJ.FinalBrakeOffset;
                    if (VSL.Controls.InvAlignmentFactor > 0.5)
                    {
                        Status("white", "Final deceleration: correcting attitude.\nLanding site error: {0}",
                               Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                    }
                    else
                    {
                        Status("white", "Final deceleration: waiting for the burn.\nLanding site error: {0}",
                               Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                    }
                    Working = VSL.Info.Countdown <= 0 || VSL.vessel.srfSpeed < LTRJ.BrakeEndSpeed;
                    break;
                }
                THR.Throttle = 0;
                if (CFG.Target.DistanceTo(VSL.vessel) - VSL.Geometry.R > LTRJ.Dtol)
                {
                    approach();
                }
                else
                {
                    land();
                }
                break;

            case LandingStage.Approach:
                Status("Approaching the target...");
                set_destination_vector();
                if (!CFG.Nav[Navigation.GoToTarget])
                {
                    land();
                }
                break;

            case LandingStage.Land:
                set_destination_vector();
                break;
            }
            return(false);
        }
示例#14
0
 void land()
 {
     CFG.AP1.On(Autopilot1.Land);
     landing_stage = LandingStage.Land;
 }
示例#15
0
        protected bool do_land()
        {
            if (VSL.LandedOrSplashed)
            {
                stop_aerobraking();
                THR.Throttle = 0;
                SetTarget();
                ClearStatus();
                CFG.AP2.Off();
                return(true);
            }
            update_trajectory();
            VSL.Engines.ActivateEngines();
            NoEnginesTimer.RunIf(VSL.Engines.MaxThrustM.Equals(0) && !VSL.Engines.HaveNextStageEngines);
            landing_deadzone = VSL.Geometry.D + CFG.Target.AbsRadius;
            if (VSL.vessel.dynamicPressurekPa > 0)
            {
                if (!dP_up_timer.RunIf(VSL.Controls.AttitudeError > last_Err ||
                                       Mathf.Abs(VSL.Controls.AttitudeError - last_Err) < 0.01f))
                {
                    dP_down_timer.RunIf(VSL.Controls.AttitudeError < last_Err &&
                                        VSL.vessel.dynamicPressurekPa < last_dP);
                }
            }
            else
            {
                dP_threshold = LTRJ.MaxDPressure;
            }
            rel_dP   = VSL.vessel.dynamicPressurekPa / dP_threshold;
            last_Err = VSL.Controls.AttitudeError;
            float    rel_Ve;
            Vector3d brake_pos, brake_vel, obt_vel;
            var      vessel_within_range   = CFG.Target.DistanceTo(VSL.vessel) < LTRJ.Dtol;
            var      vessel_after_target   = Vector3.Dot(VSL.HorizontalSpeed.Vector, CFG.Target.VectorTo(VSL.vessel)) >= 0;
            var      target_within_range   = trajectory.DistanceToTarget < LTRJ.Dtol;
            var      landing_before_target = trajectory.DeltaR > 0;
            var      terminal_velocity     = compute_terminal_velocity();;

            switch (landing_stage)
            {
            case LandingStage.Wait:
                Status("Preparing for deceleration...");
                THR.Throttle = 0;
                nose_to_target();
                rel_altitude_if_needed();
                obt_vel   = VesselOrbit.getOrbitalVelocityAtUT(trajectory.BrakeStartUT);
                brake_pos = VesselOrbit.getRelativePositionAtUT(trajectory.BrakeStartUT);
                brake_vel = corrected_brake_velocity(obt_vel, brake_pos);
                brake_vel = corrected_brake_direction(brake_vel, brake_pos.xzy);
                CFG.AT.OnIfNot(Attitude.Custom);
                ATC.SetThrustDirW(brake_vel);
                var offset = MatchVelocityAutopilot.BrakingOffset((float)obt_vel.magnitude, VSL, out VSL.Info.TTB);
                offset             = Mathf.Lerp(VSL.Info.TTB, offset, Utils.Clamp(VSL.Engines.TMR - 0.1f, 0, 1));
                VSL.Info.Countdown = trajectory.BrakeEndUT - VSL.Physics.UT - 1
                                     - Math.Max(offset, LTRJ.MinBrakeOffset * (1 - Utils.ClampH(Body.atmDensityASL, 1)));
                correct_attitude_with_thrusters(VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError));
                if (obstacle_ahead(trajectory) > 0)
                {
                    decelerate(true); break;
                }
                if (VSL.Info.Countdown <= rel_dP ||
                    will_overheat(trajectory.GetAtmosphericCurve(5, VSL.Physics.UT + TRJ.ManeuverOffset)))
                {
                    decelerate(false); break;
                }
                if (VSL.Controls.CanWarp)
                {
                    VSL.Controls.WarpToTime = VSL.Physics.UT + VSL.Info.Countdown;
                }
                else
                {
                    VSL.Controls.StopWarp();
                }
                if (CorrectTarget && VSL.Info.Countdown < CorrectionOffset)
                {
                    scan_for_landing_site();
                }
                break;

            case LandingStage.Decelerate:
                rel_altitude_if_needed();
                CFG.BR.Off();
                if (Working)
                {
                    Status("red", "Possible collision detected.");
                    correct_attitude_with_thrusters(VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError));
                    Executor.Execute(VSL.Physics.Up * 10);
                    if (obstacle_ahead(trajectory) > 0)
                    {
                        CollisionTimer.Reset(); break;
                    }
                    if (!CollisionTimer.TimePassed)
                    {
                        break;
                    }
                    start_landing();
                    break;
                }
                else
                {
                    Status("white", "Decelerating. Landing site error: {0}",
                           Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                    if (CorrectTarget)
                    {
                        scan_for_landing_site();
                    }
                    do_aerobraking_if_requested();
                    if (VSL.Controls.HaveControlAuthority)
                    {
                        DecelerationTimer.Reset();
                    }
                    if (Vector3d.Dot(VSL.HorizontalSpeed.Vector, CFG.Target.WorldPos(Body) - VSL.Physics.wCoM) < 0)
                    {
                        if (Executor.Execute(-VSL.vessel.srf_velocity, LTRJ.BrakeEndSpeed))
                        {
                            break;
                        }
                    }
                    else if (!DecelerationTimer.TimePassed &&
                             trajectory.DistanceToTarget > landing_deadzone &&
                             Vector3d.Dot(CFG.Target.VectorTo(trajectory.SurfacePoint, Body), VSL.HorizontalSpeed.Vector) > 0)
                    {
                        THR.Throttle = 0;
                        brake_vel    = corrected_brake_velocity(VesselOrbit.vel, VesselOrbit.pos);
                        brake_vel    = corrected_brake_direction(brake_vel, VesselOrbit.pos.xzy);
                        VSL.Info.TTB = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                        var aerobraking = rel_dP > 0 && VSL.OnPlanetParams.ParachutesActive;
                        if (!vessel_after_target)
                        {
                            var overheating = rel_dP > 0 &&
                                              VSL.vessel.Parts.Any(p =>
                                                                   p.temperature / p.maxTemp > PhysicsGlobals.TemperatureGaugeThreshold ||
                                                                   p.skinTemperature / p.skinMaxTemp > PhysicsGlobals.TemperatureGaugeThreshold);
                            if (!overheating)
                            {
                                ATC.SetThrustDirW(brake_vel);
                                THR.Throttle = CFG.Target.DistanceTo(VSL.vessel) > trajectory.DistanceToTarget?
                                               (float)Utils.ClampH(trajectory.DistanceToTarget / LTRJ.Dtol / 2, 1) : 1;
                            }
                            else
                            {
                                THR.Throttle = 1;
                            }
                        }
                        if (THR.Throttle > 0 || aerobraking)
                        {
                            break;
                        }
                    }
                }
                if (landing_before_target ||
                    target_within_range && !vessel_within_range)
                {
                    stop_aerobraking();
                }
                landing_stage = LandingStage.Coast;
                break;

            case LandingStage.Coast:
                Status("white", "Coasting. Landing site error: {0}", Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                THR.Throttle = 0;
                nose_to_target();
                setup_for_deceleration();
                if (correct_landing_site())
                {
                    correct_attitude_with_thrusters(VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError));
                }
                if (landing_before_target ||
                    target_within_range && !vessel_within_range)
                {
                    stop_aerobraking();
                }
                VSL.Info.TTB        = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                VSL.Info.Countdown -= Math.Max(VSL.Info.TTB + VSL.Torque.NoEngines.TurnTime + VSL.vessel.dynamicPressurekPa, ManeuverOffset);
                if (VSL.Info.Countdown > 0)
                {
                    if (THR.Throttle.Equals(0))
                    {
                        warp_to_coundown();
                    }
                }
                else
                {
                    Working = false;
                    rel_Ve  = VSL.Engines.RelVeASL;
                    if (rel_Ve <= 0)
                    {
                        Message(10, "Not enough thrust for powered landing.\nPerforming emergency landing...");
                        landing_stage = LandingStage.HardLanding;
                        break;
                    }
                    if (!(VSL.Controls.HaveControlAuthority || VSL.Torque.HavePotentialControlAuthority))
                    {
                        Message(10, "Lacking control authority to land properly.\nPerforming emergency landing...");
                        landing_stage = LandingStage.HardLanding;
                        break;
                    }
                    var fuel_left         = VSL.Engines.GetAvailableFuelMass();
                    var fuel_needed       = VSL.Engines.FuelNeeded((float)terminal_velocity, rel_Ve);
                    var needed_hover_time = LandASAP? LTRJ.HoverTimeThreshold / 5 : LTRJ.HoverTimeThreshold;
                    if (!CheatOptions.InfinitePropellant &&
                        (fuel_needed >= fuel_left ||
                         VSL.Engines.MaxHoverTimeASL(fuel_left - fuel_needed) < needed_hover_time))
                    {
                        Message(10, "Not enough fuel for powered landing.\nPerforming emergency landing...");
                        landing_stage = LandingStage.HardLanding;
//						Log("Hard Landing. Trajectory:\n{}", trajectory);//debug
                        break;
                    }
                    landing_stage = LandingStage.SoftLanding;
//					Log("Soft Landing. Trajectory:\n{}", trajectory);//debug
                }
                break;

            case LandingStage.HardLanding:
                Status("yellow", VSL.OnPlanetParams.ParachutesActive?
                       "Landing on parachutes..." : "Emergency Landing...");
                set_destination_vector();
                CFG.BR.Off();
                var not_too_hot = VSL.vessel.externalTemperature < VSL.Physics.MinMaxTemperature;
                if (not_too_hot)
                {
                    setup_for_deceleration();
                }

                if (VSL.Engines.MaxThrustM > 0 &&
                    (VSL.Controls.HaveControlAuthority || VSL.Torque.HavePotentialControlAuthority))
                {
                    rel_Ve = VSL.Engines.RelVeASL;
                    var fuel_left   = VSL.Engines.GetAvailableFuelMass();
                    var fuel_needed = rel_Ve > 0? VSL.Engines.FuelNeeded((float)terminal_velocity, rel_Ve) : fuel_left * 2;
                    VSL.Info.Countdown -= fuel_left > fuel_needed?
                                          VSL.Engines.TTB((float)terminal_velocity) :
                                              VSL.Engines.TTB(VSL.Engines.DeltaV(fuel_left));

                    if ((VSL.Info.Countdown < 0 &&
                         (!VSL.OnPlanetParams.HaveParachutes ||
                          VSL.OnPlanetParams.ParachutesActive && VSL.OnPlanetParams.ParachutesDeployed)))
                    {
                        THR.Throttle = VSL.VerticalSpeed.Absolute < -5? 1 : VSL.OnPlanetParams.GeeVSF;
                    }
                    else if (VSL.Info.Countdown > 0.5f)
                    {
                        THR.Throttle = 0;
                    }
                    Status("yellow", "Not enough fuel for powered landing.\nWill deceletate as much as possible before impact.");
                }
                if (Body.atmosphere && VSL.OnPlanetParams.HaveUsableParachutes)
                {
                    if (vessel_within_range || vessel_after_target ||
                        trajectory.BrakeEndUT - VSL.Physics.UT < LTRJ.ParachutesDeployOffset)
                    {
                        VSL.OnPlanetParams.ActivateParachutesASAP();
                    }
                    else
                    {
                        VSL.OnPlanetParams.ActivateParachutesBeforeUnsafe();
                    }
                    if (!VSL.OnPlanetParams.ParachutesActive)
                    {
                        //don't push our luck when it's too hot outside
                        if (not_too_hot)
                        {
                            brake_with_drag();
                        }
                        else
                        {
                            CFG.AT.Off();
                            CFG.StabilizeFlight = false;
                            VSL.vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, false);
                        }
                        StageTimer.RunIf(Body.atmosphere &&                         //!VSL.Controls.HaveControlAuthority &&
                                         VSL.vessel.currentStage - 1 > VSL.OnPlanetParams.NearestParachuteStage &&
                                         VSL.vessel.dynamicPressurekPa > LTRJ.DropBallastThreshold * PressureASL &&
                                         VSL.vessel.mach > LTRJ.MachThreshold);
                        if (CFG.AutoParachutes)
                        {
                            Status("yellow", "Waiting for the right moment to deploy parachutes...");
                        }
                        else
                        {
                            Status("red", "Automatic parachute deployment is disabled.\nActivate parachutes manually when needed.");
                        }
                    }
                }
                if (Body.atmosphere)
                {
                    VSL.BrakesOn();
                }
                if (!VSL.OnPlanetParams.HaveParachutes &&
                    !VSL.Engines.HaveNextStageEngines &&
                    (VSL.Engines.MaxThrustM.Equals(0) || !VSL.Controls.HaveControlAuthority))
                {
                    if (Body.atmosphere && not_too_hot)
                    {
                        brake_with_drag();
                    }
                    Status("red", "Crash is imminent.\nVertical impact speed: {0}", Utils.formatBigValue((float)terminal_velocity, "m/s"));
                }
                break;

            case LandingStage.SoftLanding:
                CFG.BR.Off();
                THR.Throttle = 0;
                set_destination_vector();
                setup_for_deceleration();
                if (vessel_within_range || vessel_after_target ||
                    trajectory.BrakeEndUT - VSL.Physics.UT < LTRJ.ParachutesDeployOffset)
                {
                    do_aerobraking_if_requested(true);
                }
                var turn_time = VSL.Torque.MaxPossible.MinRotationTime(VSL.Controls.AttitudeError);
                if (!Working)
                {
                    correct_landing_site();
                    correct_attitude_with_thrusters(turn_time);
                    VSL.Info.TTB = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                    //VSL.Engines.OnPlanetTTB(VSL.vessel.srf_velocity, VSL.Physics.Up);
                    VSL.Info.Countdown -= VSL.Info.TTB + turn_time;
                    Working             = VSL.Info.Countdown <= 0 || VSL.vessel.srfSpeed < LTRJ.BrakeEndSpeed;        //TODO: is this correct?
                    if (!Working)
                    {
                        if (VSL.Controls.InvAlignmentFactor > 0.5)
                        {
                            Status("white", "Final deceleration: correcting attitude.\nLanding site error: {0}",
                                   Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                        }
                        else
                        {
                            Status("white", "Final deceleration: waiting for the burn.\nLanding site error: {0}",
                                   Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                        }
                        break;
                    }
                }
                if (Working)
                {
                    ATC.SetThrustDirW(correction_direction());
                    if (!VSL.Controls.HaveControlAuthority)
                    {
                        correct_attitude_with_thrusters(turn_time);
                        if (!VSL.Torque.HavePotentialControlAuthority)
                        {
                            landing_stage = LandingStage.HardLanding;
                        }
                        break;
                    }
                    if (vessel_within_range || VSL.Altitude.Relative > GLB.LND.WideCheckAltitude)
                    {
                        var brake_spd  = -VSL.VerticalSpeed.Absolute;
                        var min_thrust = Utils.Clamp(brake_spd / (VSL.Engines.MaxAccel - VSL.Physics.G) /
                                                     Utils.ClampL((float)VSL.Info.Countdown, 0.01f),
                                                     VSL.OnPlanetParams.GeeVSF, 1);
                        THR.Throttle = Utils.Clamp(brake_spd / LTRJ.BrakeThrustThreshod, min_thrust, 1);
                    }
                    else
                    {
                        THR.Throttle = 1;
                    }
                    if (vessel_within_range && VSL.Altitude.Relative > GLB.LND.StopAtH * VSL.Geometry.D ||
                        VSL.Altitude.Relative > GLB.LND.WideCheckAltitude)
                    {
                        VSL.Info.TTB        = VSL.Engines.TTB((float)VSL.vessel.srfSpeed);
                        VSL.Info.Countdown -= VSL.Info.TTB + turn_time;
                        Working             = THR.Throttle > 0.7 || VSL.Info.Countdown < 10;
                        Status("white", "Final deceleration. Landing site error: {0}",
                               Utils.formatBigValue((float)trajectory.DistanceToTarget, "m"));
                        break;
                    }
                }
                THR.Throttle = 0;
                if (LandASAP)
                {
                    landing_stage = LandingStage.LandHere;
                }
                else
                {
                    stop_aerobraking();
                    if (CFG.Target.DistanceTo(VSL.vessel) - VSL.Geometry.R > LTRJ.Dtol)
                    {
                        approach();
                    }
                    else
                    {
                        land();
                    }
                }
                break;

            case LandingStage.LandHere:
                Status("lime", "Landing...");
                CFG.BR.Off();
                CFG.BlockThrottle        = true;
                CFG.AltitudeAboveTerrain = true;
                CFG.VF.On(VFlight.AltitudeControl);
                CFG.HF.OnIfNot(HFlight.Stop);
                if (CFG.DesiredAltitude >= 0 && !VSL.HorizontalSpeed.MoovingFast)
                {
                    CFG.DesiredAltitude = 0;
                }
                else
                {
                    CFG.DesiredAltitude = Utils.ClampL(VSL.Altitude.Relative / 2, VSL.Geometry.H * 2);
                }
                break;

            case LandingStage.Approach:
                Status("Approaching the target...");
                set_destination_vector();
                if (!CFG.Nav[Navigation.GoToTarget])
                {
                    land();
                }
                break;

            case LandingStage.Land:
                set_destination_vector();
                break;
            }
            return(false);
        }