private void SaveUndockTarget(ZACommons commons)
    {
        string value = null;

        if (UndockTarget != null)
        {
            var orientation = QuaternionD.CreateFromForwardUp(UndockForward, UndockUp);
            value = string.Format("{0};{1};{2};{3};{4};{5};{6}",
                                  ((Vector3D)UndockTarget).X,
                                  ((Vector3D)UndockTarget).Y,
                                  ((Vector3D)UndockTarget).Z,
                                  orientation.X,
                                  orientation.Y,
                                  orientation.Z,
                                  orientation.W);
        }
        commons.SetValue(UndockTargetKey, value);

        value = null;
        if (UndockBackward != null)
        {
            value = ((byte)UndockBackward).ToString();
        }
        commons.SetValue(BackwardKey, value);
    }
    public void Run(ZACommons commons, EventDriver eventDriver)
    {
        var shipControl = commons as ShipControlCommons;
        var position    = shipControl.ReferencePoint;
        var orientation = QuaternionD.CreateFromForwardUp(shipControl.ReferenceForward, shipControl.ReferenceUp);

        var msg = string.Format("xponder;{0};{1};{2};{3};{4};{5};{6};{7}",
                                TransponderID,
                                position.X, position.Y, position.Z,
                                orientation.X, orientation.Y, orientation.Z,
                                orientation.W);

        // Transmit on first functional antenna
        var antennas = ZACommons.GetBlocksOfType <IMyRadioAntenna>(commons.Blocks, antenna => antenna.IsFunctional && antenna.Enabled);

        if (antennas.Count > 0)
        {
            var antenna = antennas[0];
            antenna.TransmitMessage(msg, TRANSPONDER_TARGET);
        }

        eventDriver.Schedule(TRANSPONDER_UPDATE_RATE, Run);
    }
            private void UpdateViewRange(MyPlanet planet)
            {
                var pos = MySector.MainCamera.Position;

                double dist = double.MaxValue;

                foreach (var p in MyPlanets.GetPlanets())
                {
                    double dsq = Vector3D.DistanceSquared(pos, p.WorldMatrix.Translation);
                    if (dsq < dist)
                    {
                        planet = p;
                        dist   = dsq;
                    }
                }

                var    radius = planet.MinimumRadius;
                double altitude;

                m_height = planet.MaximumRadius - radius;

                var center = planet.WorldMatrix.Translation;


                m_radius = HyperSphereHelpers.DistanceToTangentProjected(ref center, ref pos, radius, out altitude);

                var up = center - pos;

                up.Normalize();

                m_center = pos + up * altitude;

                var forward = Vector3D.CalculatePerpendicularVector(up);

                m_orientation = QuaternionD.CreateFromForwardUp(forward, up);
            }
        public void Main(string argument, UpdateType updateSource)
        {
            if ((updateSource & UpdateType.Trigger) != 0)
            {
                if (argument == "HDamp")
                {
                    hDamp = !hDamp;
                }
                if (argument == "ManualAlt")
                {
                    manualAlt    = !manualAlt;
                    targAltitude = GetAltitude();
                    targSpd      = 0;
                }
                if (argument == "VDamp")
                {
                    vDamp = !vDamp;
                }
                if (argument == "Spd+")
                {
                    SetSpd(curSpeed + 1);
                }
                if (argument == "Spd-")
                {
                    SetSpd(curSpeed - 1);
                }
            }
            bool     trueHDamp = hDamp;
            Vector3D pos       = sc.CenterOfMass;
            Vector3D spd       = sc.GetShipVelocities().LinearVelocity;
            Vector3D grav      = Vector3D.Normalize(sc.GetTotalGravity());
            double   gravNorm  = sc.GetTotalGravity().Length();
            Vector3D gravin    = Vector3D.TransformNormal(grav, MatrixD.Transpose(sc.WorldMatrix));
            Vector3D spdin     = Vector3D.TransformNormal(spd, MatrixD.Transpose(sc.WorldMatrix));
            Vector3D MoveIndic = sc.MoveIndicator;
            Vector3D COM       = PosToShip(sc.CenterOfMass);

            if (gravin.Y > 0)
            {
                hDamp = false;
            }



            //orientation
            if (MoveIndic.X != 0 || MoveIndic.Z != 0)
            {
                trueHDamp = false;
            }
            double inclCommand   = rotAngles[curSpeed];
            double angleToRotSpd = 1.0;

            // new orientation
            lastHeading -= grav * grav.Dot(lastHeading);
            lastHeading.Normalize();
            Vector3D right = grav.Cross(lastHeading);

            right.Normalize();

            lastHeading += 0.001 * right * sc.RotationIndicator.Y;
            lastHeading.Normalize();

            Vector3D ntarget = grav;
            double   targetX = 0.0, targetZ = 0.0;

            if (trueHDamp)
            {
                targetZ = Clamp(-(spdin.Z) * 0.05, -0.5, 0.5);
                targetX = Clamp(-(spdin.X) * 0.05, -0.5, 0.5);
            }
            else
            {
                targetX = inclCommand * MoveIndic.X;
                targetZ = inclCommand * MoveIndic.Z;
            }
            ntarget -= targetX * right;
            ntarget += targetZ * lastHeading;

            ntarget.Normalize();

            Vector3D headtarget = right.Cross(ntarget);

            headtarget.Normalize();

            Vector3D    ntargetin    = Vector3D.TransformNormal(ntarget, MatrixD.Transpose(sc.WorldMatrix));
            Vector3D    headtargetin = Vector3D.TransformNormal(headtarget, MatrixD.Transpose(sc.WorldMatrix));
            QuaternionD targq        = QuaternionD.CreateFromForwardUp(headtargetin, -ntargetin);
            Vector3D    axis;
            double      angle;

            targq.GetAxisAngle(out axis, out angle);
            axis *= angle;
            axis *= angleToRotSpd;
            SetRotSpd(axis);



            // new altitude
            double curAltitude = GetAltitude();
            double curVSpeed   = (curAltitude - lastAltitude) * 60;
            double targAcc     = 0;

            if (vDamp)
            {
                targAcc = Clamp(-targSpd, -accelerations[curSpeed], accelerations[curSpeed]);
            }
            if (MoveIndic.Y != 0)
            {
                targAcc = MoveIndic.Y * accelerations[curSpeed];
            }
            targSpd      += targAcc / 60;
            targSpd       = Clamp(targSpd, curVSpeed - maxSpdDrift, curVSpeed + maxSpdDrift);
            targAltitude += targSpd / 60;
            targAltitude  = Clamp(targAltitude, curAltitude - maxAltDrift, curAltitude + maxAltDrift);
            double compTargSpd = targSpd + (targAltitude - curAltitude);
            double compTargAcc = targAcc + gravNorm / (-gravin.Y) + (compTargSpd - curVSpeed);

            if (manualAlt)
            {
                ClearThrust();
            }
            else
            {
                SetThrust(compTargAcc * mass);
            }
            if (tick >= 10)
            {
                tick = 0;

                /*lcd.WriteText($@"grav X={gravin.X:F3} Y={gravin.Y:F3} Z={gravin.Z:F3}
                 * Spd X={spdin.X:F3} Y={spdin.Y:F3} Z={spdin.Z:F3}
                 * AA X={axis.X:F3} Y={axis.Y:F3} Z={axis.Z:F3}
                 * NT {ntargetin} {headtargetin}
                 * hDamp {hDamp} vDamp {vDamp} ManualAlt {manualAlt}
                 * Spd: {speedNames[curSpeed]}
                 * Alt cur {curAltitude:F3} targ {targAltitude:F3}
                 * Spd cur {curVSpeed:F10} targ {targSpd:F10} ctarg {compTargSpd:F10}
                 * Acc targ {targAcc:F10} ctarg {compTargAcc:F10}
                 * pos {sc.GetPosition()} scal {Vector3D.Dot(grav, sc.GetPosition())}
                 * cam X {COM.X:F3} Y {COM.Y:F3} Z {COM.Z:F3}
                 * th back {backT:F3} front {frontT:F3}
                 * dist back {distback:F3} front{distfront:F3}
                 * ");*/

                lcd.WriteText($@"Helico control software
Horizontal Dampeners (4) {OnOff(hDamp)}
Vertical Dampeners (5) {OnOff(vDamp)}
Manual Altitude (6) {OnOff(manualAlt)}
Current Altitude {curAltitude:F2}m
Vertical Speed {targSpd:F2}m/s
Speed mode (^8/v9) {speedNames[curSpeed]}
");
            }
            else
            {
                tick++;
            }



            lastAltitude = curAltitude;
        }
 public static QuaternionD ToQuaternionD(this MyPositionAndOrientation positionOrientation)
 {
     return(QuaternionD.CreateFromForwardUp(new Vector3D(positionOrientation.Forward), new Vector3D(positionOrientation.Up)));
 }