public bool AtWaypoint(Waypoint w)
        {
            if (w.Position != Vector3.One && w.Position != Vector3.Zero)
            {
                var      speed    = (float)(Controller.GetShipVelocities().LinearVelocity - w.Velocity).Length();
                Vector3D posError = Destination - Reference.WorldMatrix.Translation;
                var      distance = (float)posError.Length();
                if (distance > 0.25f || speed > 0.25f)
                {
                    return(false);
                }
            }
            if (w.Direction != Vector3.One && w.Direction != Vector3.Zero)
            {
                if (VectorHelpers.VectorAngleBetween(Reference.WorldMatrix.Forward, ForwardDir) > 0.03f)
                {
                    return(false);
                }
            }
            if (w.DirectionUp != Vector3.One && w.DirectionUp != Vector3.Zero)
            {
                if (VectorHelpers.VectorAngleBetween(Reference.WorldMatrix.Up, UpDir) > 0.03f)
                {
                    return(false);
                }
            }

            return(true);
        }
        void GetRotationAngles(Vector3D v_target, Vector3D v_front, Vector3D v_left, Vector3D v_up, out double yaw, out double pitch)
        {
            //Dependencies: VectorProjection() | VectorAngleBetween()
            var projectTargetUp     = VectorHelpers.VectorProjection(v_target, v_up);
            var projTargetFrontLeft = v_target - projectTargetUp;

            yaw = VectorHelpers.VectorAngleBetween(v_front, projTargetFrontLeft);

            if (Vector3D.IsZero(projTargetFrontLeft) && !Vector3D.IsZero(projectTargetUp)) //check for straight up case
            {
                pitch = MathHelper.PiOver2;
            }
            else
            {
                pitch = VectorHelpers.VectorAngleBetween(v_target, projTargetFrontLeft); //pitch should not exceed 90 degrees by nature of this definition
            }
            //---Check if yaw angle is left or right
            //multiplied by -1 to convert from right hand rule to left hand rule
            yaw = -1 * Math.Sign(v_left.Dot(v_target)) * yaw;

            //---Check if pitch angle is up or down
            pitch = Math.Sign(v_up.Dot(v_target)) * pitch;

            //---Check if target vector is pointing opposite the front vector
            if (Math.Abs(yaw) <= 1E-6 && v_target.Dot(v_front) < 0)
            {
                yaw = Math.PI;
            }
        }
        private void NeutralControl(Vector3D gravDir)
        {
            Drive.Move(Vector3D.Zero);
            Vector3D turnTarget = Drive.Controller.WorldMatrix.Forward + Drive.Controller.RotationIndicator.Y * Drive.Controller.WorldMatrix.Right * 0.2;

            turnTarget = turnTarget - VectorHelpers.VectorProjection(turnTarget, gravDir);
            Drive.Turn(turnTarget);
            Drive.Drift(Vector3D.Zero);
            Drive.Spin(-gravDir);
        }
        void SetGyroPowers(bool fake = false)
        {
            if (fake)
            {
                return;
            }
            if (reference == null)
            {
                return;
            }
            double yawAngle = 0, pitchAngle = 0, spinAngle = 0;

            if (targetDirection != Vector3.Zero || targetUp != Vector3.Zero)
            {
                if (targetDirection != Vector3.Zero)
                {
                    GetRotationAngles(targetDirection, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle);
                }
                if (targetUp != Vector3.Zero)
                {
                    var projectedTargetUp = targetUp - reference.WorldMatrix.Forward.Dot(targetUp) * reference.WorldMatrix.Forward;
                    spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(targetUp));
                }

                if (DYaw == 0)
                {
                    DYaw = yawAngle;
                }
                if (DPitch == 0)
                {
                    DPitch = pitchAngle;
                }

                IYaw   += yawAngle * kRunEveryXUpdates;
                IPitch += pitchAngle * kRunEveryXUpdates;

                // no point in trying to spin over 180 deg in a direction.
                IYaw   = MathHelper.Clamp(IYaw, -1.0, 1.0);
                IPitch = MathHelper.Clamp(IPitch, -1.0, 1.0);

                ApplyGyroOverride(pitchAngle * RP + (pitchAngle - DPitch) * RD * kInverseTimeStep + IPitch * RI, yawAngle * RP + (yawAngle - DYaw) * RD * kInverseTimeStep + IYaw * RI, spinAngle * RP, gyros, reference);
            }


            if (!Persist && Math.Abs(yawAngle) < 0.01f && Math.Abs(pitchAngle) < 0.01f && Math.Abs(spinAngle) < 0.01f)
            {
                targetDirection = Vector3.Zero;
                targetUp        = Vector3.Zero;
            }

            if (targetDirection == Vector3.Zero && targetUp == Vector3.Zero)
            {
                ClearGyros();
            }
        }
        void Attack(TimeSpan localTime)
        {
            FriendlyShipScratchpad.Clear();

            var intelItems = IntelProvider.GetFleetIntelligences(localTime);

            foreach (var kvp in intelItems)
            {
                if (kvp.Key.Item1 == IntelItemType.Friendly)
                {
                    var friendly = (FriendlyShipIntel)kvp.Value;
                    if (friendly.AgentClass == AgentClass.Fighter && (friendly.AgentStatus & AgentStatus.Docked) != 0 && (friendly.GetPositionFromCanonicalTime(localTime + IntelProvider.CanonicalTimeDiff) - Controller.GetPosition()).Length() < 100)
                    {
                        FriendlyShipScratchpad.Add(friendly);
                    }
                }
            }

            if (FriendlyShipScratchpad.Count == 0)
            {
                return;
            }

            for (int i = 0; i < FriendlyShipScratchpad.Count; i++)
            {
                var targetWaypoint = new Waypoint();

                var gravDir = Controller.GetNaturalGravity();
                targetWaypoint.Position = Controller.GetPosition();
                var angle = 2 * i * Math.PI / FriendlyShipScratchpad.Count;

                if (gravDir != Vector3D.Zero)
                {
                    gravDir.Normalize();
                    var flatForward = Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(Controller.WorldMatrix.Forward, gravDir);
                    flatForward.Normalize();
                    var flatLeftDir = Vector3D.Cross(flatForward, gravDir);
                    targetWaypoint.Position += (flatForward * TrigHelpers.FastCos(angle) + flatLeftDir * TrigHelpers.FastSin(angle)) * 500;
                    targetWaypoint.Position -= gravDir * 200;
                }
                else
                {
                    targetWaypoint.Position += (Controller.WorldMatrix.Forward * TrigHelpers.FastCos(angle) + Controller.WorldMatrix.Left * TrigHelpers.FastSin(angle)) * 500;
                }

                targetWaypoint.Position += Controller.GetShipVelocities().LinearVelocity * 3;
                IntelProvider.ReportFleetIntelligence(targetWaypoint, localTime);
                IntelProvider.ReportCommand(FriendlyShipScratchpad[i], TaskType.Attack, MyTuple.Create(IntelItemType.Waypoint, targetWaypoint.ID), localTime);
            }
        }
示例#6
0
        public void Turn(MatrixD Reference, Vector3D target)
        {
            if (Reference == MatrixD.Zero)
            {
                return;
            }
            MatrixD orientationMatrix = MatrixD.Identity;

            orientationMatrix.Translation = Reference.Translation;
            Vector3D orientationForward = Controller.WorldMatrix.Forward + Controller.WorldMatrix.Down + Controller.WorldMatrix.Left;

            orientationForward.Normalize();
            orientationMatrix.Forward = orientationForward;
            Vector3D orientationUp = Reference.Forward;

            orientationUp -= VectorHelpers.VectorProjection(orientationUp, orientationForward);
            orientationUp.Normalize();
            orientationMatrix.Up = orientationUp;
            Vector3D OrientationRight = orientationForward.Cross(orientationUp);

            orientationMatrix.Right = OrientationRight;
            var gravDir = Controller.GetNaturalGravity();

            gravDir.Normalize();

            double yawAngle, pitchAngle, spinAngle;

            GravAngle = VectorHelpers.VectorAngleBetween(gravDir, orientationMatrix.Forward);

            if (target != Vector3D.Zero && GravAngle < Math.PI * 0.1)
            {
                Vector3D TargetDir = target - orientationMatrix.Translation;
                TargetDir.Normalize();
                var projectedTargetUp = TargetDir - VectorHelpers.VectorProjection(TargetDir, orientationForward);
                spinAngle = -1 * VectorHelpers.VectorAngleBetween(orientationMatrix.Up, projectedTargetUp) * Math.Sign(orientationMatrix.Left.Dot(TargetDir));
            }
            else
            {
                spinAngle = 0;
                SpinPID.Reset();
            }
            TrigHelpers.GetRotationAngles(gravDir, orientationMatrix.Forward, orientationMatrix.Left, orientationMatrix.Up, out yawAngle, out pitchAngle);
            TrigHelpers.ApplyGyroOverride(PitchPID.Control(pitchAngle), YawPID.Control(yawAngle), SpinPID.Control(spinAngle), Gyros, orientationMatrix);
        }
        public bool AtWaypoint(Waypoint w)
        {
            if (Persist)
            {
                return(false);
            }
            if (w.Position != Vector3.One && w.Position != Vector3.Zero)
            {
                var      speed    = (float)(controller.GetShipVelocities().LinearVelocity - w.Velocity).Length();
                Vector3D posError = (targetPosition - reference.WorldMatrix.Translation);
                var      distance = (float)posError.Length();
                if (distance > 0.25f || speed > 0.25f)
                {
                    return(false);
                }
            }
            if (w.Direction != Vector3.One && w.Direction != Vector3.Zero)
            {
                double yawAngle, pitchAngle;
                GetRotationAngles(w.Direction, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle);
                if (Math.Abs(yawAngle) > 0.03f || Math.Abs(pitchAngle) > 0.03f)
                {
                    return(false);
                }
            }
            if (w.DirectionUp != Vector3.One && w.DirectionUp != Vector3.Zero)
            {
                var projectedTargetUp = targetUp - reference.WorldMatrix.Forward.Dot(targetUp) * reference.WorldMatrix.Forward;
                var spinAngle         = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(targetUp));
                if (Math.Abs(spinAngle) > 0.03f)
                {
                    return(false);
                }
            }

            return(true);
        }
        public void Update(TimeSpan timestamp, UpdateFrequency updateFlags)
        {
            runs++;

            if (runs % 5 == 0)
            {
                statusBuilder.Clear();
                indicatorBuilder.Clear();

                bool firing = false;

                var index = Indicator.CustomName.IndexOf('|') + 1;
                if (index <= 0)
                {
                    return;
                }
                string originalName = Indicator.CustomName.Substring(0, index);

                if (Context.WCAPI == null)
                {
                    return;
                }

                var gravDir = IntelProvider.Controller.GetNaturalGravity();
                var gravStr = gravDir.Normalize();

                if (!active)
                {
                    indicatorBuilder.Append("OFF");

                    NeutralControl(gravDir);
                }
                else
                {
                    var target = Context.WCAPI.GetAiFocus(Context.Reference.CubeGrid.EntityId);
                    if (!target.HasValue || target.Value.IsEmpty())
                    {
                        indicatorBuilder.Append("NO TGT");
                        NeutralControl(gravDir);
                    }
                    else
                    {
                        var velocity         = IntelProvider.Controller.GetShipVelocities().LinearVelocity;
                        var relativeVector   = target.Value.Position - IntelProvider.Controller.WorldMatrix.Translation;
                        var relativeVelocity = target.Value.Velocity - velocity;

                        var planarVector = relativeVector - VectorHelpers.VectorProjection(relativeVector, gravDir);
                        planarVector.Normalize();

                        var targetPos = target.Value.Position - gravDir * range + planarVector * 50;

                        statusBuilder.AppendLine((gravDir * range).ToString());

                        Drive.Move(targetPos);
                        if ((targetPos - IntelProvider.Controller.WorldMatrix.Translation).Length() < 100)
                        {
                            Drive.Move(Vector3D.Zero);
                        }
                        Drive.Drift(target.Value.Velocity);

                        var VerticalAngleToTarget = VectorHelpers.VectorAngleBetween(gravDir, relativeVector);

                        planarVector -= gravDir * Math.Tan(VerticalAngleToTarget > 20 * Math.PI / 180 ? 0 : VerticalAngleToTarget);

                        Drive.Turn(planarVector);
                        Drive.Spin(-gravDir);

                        indicatorBuilder.Append("TGT:");
                        indicatorBuilder.Append(target.Value.Name.Length > 4 ? target.Value.Name.Substring(0, 4) : target.Value.Name);
                        indicatorBuilder.Append(" - DIST:");
                        indicatorBuilder.Append(relativeVector.Length().ToString("F"));
                        indicatorBuilder.Append(" - STUS:");

                        // Fire control

                        if (VerticalAngleToTarget > 20 * Math.PI / 180)
                        {
                            indicatorBuilder.Append(" APPROACH");
                        }
                        else
                        {
                            indicatorBuilder.Append(" AIM ");
                            var angleToTargetDegrees = VectorHelpers.VectorAngleBetween(Gun.WorldMatrix.Forward, relativeVector) * 180 / Math.PI;
                            indicatorBuilder.Append(angleToTargetDegrees.ToString("F"));

                            if (angleToTargetDegrees < 0.5 && Context.WCAPI.IsWeaponReadyToFire(Gun))
                            {
                                indicatorBuilder.Clear();
                                indicatorBuilder.Append("FIRING!");
                                firing = true;
                            }
                        }
                    }
                }
                Indicator.CustomName = originalName + " " + indicatorBuilder.ToString();
                Context.WCAPI.ToggleWeaponFire(Gun, firing, true);
            }
        }
示例#9
0
        public void Main(string argument, UpdateType updateSource)
        {
            subsystemManager.UpdateTime();

            if (argument == "descend")
            {
                Mode       = 1;
                lockMatrix = Drive.Controller.WorldMatrix;
            }
            else if (argument == "ascend")
            {
                Mode       = 2;
                lockMatrix = Drive.Controller.WorldMatrix;
            }
            else if (argument == "stop")
            {
                Mode       = 0;
                lockMatrix = MatrixD.Zero;
                Drive.Clear();
            }
            else if (commandLine.TryParse(argument))
            {
                subsystemManager.Command(commandLine.Argument(0), commandLine.Argument(1), commandLine.ArgumentCount > 2 ? commandLine.Argument(2) : null);
            }
            else
            {
                try
                {
                    subsystemManager.Update(updateSource);

                    runs++;
                    if (runs % 5 == 0)
                    {
                        OutputBuilder.Clear();

                        OutputBuilder.Append($"STATUS: ").AppendLine(Mode == 0 ? "STOP" : (Mode == 1 ? "DESC" : "ASCE"));

                        foreach (var screen in Displays)
                        {
                            screen.ContentType = ContentType.TEXT_AND_IMAGE;
                            screen.WriteText(OutputBuilder.ToString());
                        }

                        var destination = new Waypoint();

                        if (Mode == 0)
                        {
                            Drive.Clear();
                        }
                        else if (Mode == 1)
                        {
                            destination.MaxSpeed = DescendSpeed;
                            var gravdir = Cockpit.GetNaturalGravity();
                            if (gravdir == Vector3D.Zero)
                            {
                                gravdir.Normalize();

                                destination.Position = gravdir * 10 + Cockpit.GetPosition();

                                var flatForward = Cockpit.WorldMatrix.Forward - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, gravdir);
                                flatForward.Normalize();
                                var flatLeft = Cockpit.WorldMatrix.Left - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, gravdir);
                                flatLeft.Normalize();

                                destination.Direction = flatForward * TrigHelpers.FastCos(0.02 * RotateSpeed) + flatLeft * TrigHelpers.FastSin(0.02 * RotateSpeed);
                            }
                            else
                            {
                                destination.Position    = lockMatrix.Down * 10 + Cockpit.GetPosition();
                                destination.DirectionUp = lockMatrix.Up;

                                var flatForward = Cockpit.WorldMatrix.Forward - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, lockMatrix.Down);
                                flatForward.Normalize();
                                var flatLeft = Cockpit.WorldMatrix.Left - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, lockMatrix.Down);
                                flatLeft.Normalize();

                                destination.Direction = flatForward * TrigHelpers.FastCos(0.02 * RotateSpeed) + flatLeft * TrigHelpers.FastSin(0.02 * RotateSpeed);
                            }
                        }
                        else if (Mode == 2)
                        {
                            destination.MaxSpeed = AscendSpeed;
                            if (Drive.Controller == Cockpit)
                            {
                                var gravdir = Cockpit.GetNaturalGravity();
                                gravdir.Normalize();

                                destination.Position = -gravdir * 10 + Cockpit.GetPosition();
                            }
                            else
                            {
                                destination.Position  = lockMatrix.Down * 10 + Cockpit.GetPosition();
                                destination.Direction = lockMatrix.Forward;
                            }
                        }

                        Drive.Move(destination.Position);
                        Drive.Turn(destination.Direction);
                        Drive.Spin(destination.DirectionUp);
                        Drive.SetMaxSpeed(destination.MaxSpeed);
                    }
                }
                catch (Exception e)
                {
                    Me.GetSurface(0).WriteText(e.Message);
                    Me.GetSurface(0).WriteText("\n", true);
                    Me.GetSurface(0).WriteText(e.StackTrace);
                    Me.GetSurface(0).WriteText("\n", true);
                    Me.GetSurface(0).WriteText(e.ToString());
                }
                var s = subsystemManager.GetStatus();
                if (!string.IsNullOrEmpty(s))
                {
                    Echo(s);
                }
                else
                {
                    Echo(((int)subsystemManager.OutputMode).ToString());
                }
            }
        }
示例#10
0
        public void Update(TimeSpan timestamp, UpdateFrequency updateFlags)
        {
            runs++;

            if (runs % 10 == 0)
            {
                indicatorBuilder.Clear();

                var index = Indicator.CustomName.IndexOf('|') + 1;
                if (index <= 0)
                {
                    return;
                }
                string originalName = Indicator.CustomName.Substring(0, index);

                if (Context.WCAPI == null)
                {
                    return;
                }
                var rotationIndicator = Vector3.NegativeInfinity;

                var movementIndicator = Vector3.NegativeInfinity;

                if (!active)
                {
                    indicatorBuilder.Append("OFF");
                }
                else
                {
                    var target = Context.WCAPI.GetAiFocus(Context.Reference.CubeGrid.EntityId);
                    if (target == null)
                    {
                        indicatorBuilder.Append("NO TGT");
                    }
                    else
                    {
                        var gravDir  = IntelProvider.Controller.GetNaturalGravity();
                        var gravStr  = gravDir.Normalize();
                        var velocity = IntelProvider.Controller.GetShipVelocities().LinearVelocity;

                        var relativeVector   = target.Value.Position - IntelProvider.Controller.WorldMatrix.Translation;
                        var relativeVelocity = target.Value.Velocity - velocity;

                        var heightSquared          = VectorHelpers.VectorProjection(relativeVector, gravDir).LengthSquared();
                        var relativeplanarDir      = relativeVector - VectorHelpers.VectorProjection(relativeVector, gravDir);
                        var relativeplanarDist     = relativeplanarDir.Normalize();
                        var relativePlanarVelocity = relativeVelocity - VectorHelpers.VectorProjection(relativeVelocity, gravDir);

                        // Attack dir
                        var relativeAttackPoint = AttackHelpers.GetAttackPoint(relativeVelocity, relativeVector, projectileSpeed);
                        var attackPlanarVector  = relativeAttackPoint - VectorHelpers.VectorProjection(relativeAttackPoint, gravDir);

                        var attackPlanarLeft = IntelProvider.Controller.WorldMatrix.Left - VectorHelpers.VectorProjection(IntelProvider.Controller.WorldMatrix.Left, gravDir);
                        attackPlanarLeft.Normalize();

                        var attackPlanarForward = IntelProvider.Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(IntelProvider.Controller.WorldMatrix.Forward, gravDir);
                        attackPlanarForward.Normalize();

                        var spinAngle = VectorHelpers.VectorAngleBetween(attackPlanarForward, attackPlanarVector) * Math.Sign(-attackPlanarLeft.Dot(attackPlanarVector));

                        rotationIndicator.Y = (float)spinAngle;

                        // Movement
                        var myPlanarVelocity        = velocity - VectorHelpers.VectorProjection(relativeAttackPoint, gravDir);
                        var targetPlanarDist        = Math.Sqrt(range * range - heightSquared);
                        var targetPlanarPoint       = relativeplanarDir * (relativeplanarDist - targetPlanarDist);
                        var desiredRelativeVelocity = targetPlanarPoint * 0.5 + relativePlanarVelocity - myPlanarVelocity;
                        desiredRelativeVelocity.Normalize();

                        movementIndicator.X = (float)desiredRelativeVelocity.Dot(IntelProvider.Controller.WorldMatrix.Right);
                        movementIndicator.Z = (float)desiredRelativeVelocity.Dot(IntelProvider.Controller.WorldMatrix.Backward);

                        indicatorBuilder.Append("TGT:");
                        indicatorBuilder.Append(target.Value.Name.Substring(0, 4));
                        indicatorBuilder.Append(" - DIST:");
                        indicatorBuilder.Append(relativeVector.Length().ToString("F"));
                        indicatorBuilder.Append(" - ");
                        indicatorBuilder.Append(movementIndicator.X.ToString("F"));
                        indicatorBuilder.Append(",");
                        indicatorBuilder.Append(movementIndicator.Z.ToString("F"));
                        indicatorBuilder.Append(" -- ");
                        indicatorBuilder.Append(spinAngle.ToString("F"));
                    }
                }
                Indicator.CustomName            = originalName + " " + indicatorBuilder.ToString();
                Drive.RotationIndicatorOverride = rotationIndicator;
                Drive.MoveIndicatorOverride     = movementIndicator;
            }
        }
示例#11
0
        public void Drive(Vector3D Destination)
        {
            if (Destination == Vector3D.Zero)
            {
                return;
            }

            if (GravAngle > Math.PI * 0.1)
            {
                foreach (var engine in HoverEngines)
                {
                    engine.Block.Enabled      = true;
                    engine.OverridePercentage = 0;
                    engine.AltitudeMin        = DesiredAltitude / VertiHoriForceRatio;
                }
                return;
            }

            var gravDir = Controller.GetNaturalGravity();
            var gravStr = gravDir.Length();

            gravDir.Normalize();
            var destDir = Destination - Controller.WorldMatrix.Translation;

            destDir -= VectorHelpers.VectorProjection(destDir, gravDir);
            var dist = destDir.Length();

            Arrived = dist < 20;
            destDir.Normalize();

            var maxSpeed   = SpeedLimit == 0 ? Math.Min(100, GetMaxSpeedFromBrakingDistance((float)dist)) : SpeedLimit;
            var currentVel = Controller.GetShipVelocities().LinearVelocity;
            var horiVel    = currentVel - VectorHelpers.VectorProjection(Controller.GetShipVelocities().LinearVelocity, gravDir);
            var vertiVel   = currentVel.Dot(-gravDir);
            var accelDir   = maxSpeed * destDir - horiVel;

            accelDir.Normalize();
            var mass      = Controller.CalculateShipMass().PhysicalMass;
            var gravForce = gravStr * mass;

            DirForces.Clear();
            Dirs.Clear();

            Dirs.Add(Controller.WorldMatrix.Forward);
            Dirs.Add(Controller.WorldMatrix.Down);
            Dirs.Add(Controller.WorldMatrix.Left);

            float  alpha = 0;
            double altitude;

            Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude);
            DesiredVerticalVel = DesiredAltitude - altitude;
            var altAdjust = DesiredVerticalVel - vertiVel;

            Vector3D PrimaryDriveDir   = Vector3D.Zero;
            Vector3D SecondaryDriveDir = Vector3D.Zero;
            Vector3D OpposDriveDir     = Vector3D.Zero;

            foreach (var dir in Dirs)
            {
                var engineDir = dir;
                engineDir -= VectorHelpers.VectorProjection(engineDir, gravDir);
                engineDir.Normalize();

                var engineAngleDiff = VectorHelpers.VectorAngleBetween(engineDir, accelDir);
                if (engineAngleDiff < 0.3333333333333 * Math.PI)
                {
                    DirForces[dir] = 0;
                    OpposDriveDir  = dir;
                }
                else if (engineAngleDiff > 2 * 0.3333333333333 * Math.PI)
                {
                    DirForces[dir]  = 1f;
                    PrimaryDriveDir = dir;
                }
                else
                {
                    var aPrime = 1 / (TrigHelpers.fastTan(engineAngleDiff - Math.PI * 0.333333333) * sqrt3inv + 1);
                    DirForces[dir]    = (float)(1 - aPrime) * 2;
                    SecondaryDriveDir = dir;
                    alpha             = DirForces[dir];
                }
            }

            var primaryDriveForce   = MaxForce * VerticalForceRatio;
            var secondaryDriveForce = primaryDriveForce * alpha;

            var totalUpForce = primaryDriveForce + secondaryDriveForce;
            var multiplier   = (gravForce + altAdjust * mass) / totalUpForce;

            Status = $"{altAdjust}, {dist}";

            if (PrimaryDriveDir != Vector3D.Zero)
            {
                DirForces[PrimaryDriveDir] = Math.Max(0.01f, (float)multiplier);
            }
            if (SecondaryDriveDir != Vector3D.Zero)
            {
                DirForces[SecondaryDriveDir] = (float)Math.Max(0.01f, alpha * (float)multiplier);
            }

            var altMin = 1;

            if (altitude > 7)
            {
                altMin = 6;
            }
            if (altitude > 40)
            {
                altMin = 10;
            }

            foreach (var engine in HoverEngines)
            {
                engine.AltitudeMin        = altMin;
                engine.Block.Enabled      = OpposDriveDir != engine.Block.WorldMatrix.Forward;
                engine.OverridePercentage = DirForces[engine.Block.WorldMatrix.Forward];
            }
        }
        void GetMovementVectors(Vector3D target, IMyShipController controller, IMyTerminalBlock reference, float maxThrust, float maxSpeed, out Vector3D AutopilotMoveIndicator, ref Vector3D D, ref Vector3D I)
        {
            if (controller == null)
            {
                AutopilotMoveIndicator = Vector3D.Zero;
                return;
            }
            var      speed           = (float)(controller.GetShipVelocities().LinearVelocity - targetDrift).Length();
            Vector3D currentVelocity = controller.GetShipVelocities().LinearVelocity;
            float    aMax            = 0.8f * maxThrust / controller.CalculateShipMass().PhysicalMass;
            Vector3D desiredVelocity = targetDrift;
            Vector3D posError        = target - reference.WorldMatrix.Translation;
            var      distance        = (float)posError.Length();

            posError.Normalize();

            if (target != Vector3D.Zero)
            {
                float desiredSpeed = Math.Min((float)Math.Sqrt(2f * aMax * distance) * 0.01f * (100 - (float)targetDrift.Length()), maxSpeed);
                desiredSpeed     = Math.Min(distance * distance * 2f, desiredSpeed);
                desiredVelocity += posError * desiredSpeed;
            }

            Vector3D adjustVector = currentVelocity - targetDrift - VectorHelpers.VectorProjection(currentVelocity - targetDrift, desiredVelocity - targetDrift);

            if (adjustVector.Length() < (currentVelocity - targetDrift).Length() * 0.1)
            {
                adjustVector = Vector3.Zero;
            }

            Vector3D Error = (desiredVelocity - currentVelocity - adjustVector * 1) * 60 / (aMax * kRunEveryXUpdates);

            float kP = TP;
            float kI = TI;
            float kD = TD;

            if (Error.LengthSquared() > 1)
            {
                Error.Normalize();
            }
            else
            {
                kP = TP2;
                kI = TI2;
                kD = TD2;
            }

            if (D == Vector3.Zero)
            {
                D = Error;
            }

            AutopilotMoveIndicator = kP * Error + kD * (Error - D) * kInverseTimeStep + kI * I;

            // decrease speed when close and slow
            if (distance < 10 && speed < 10)
            {
                AutopilotMoveIndicator *= 0.5f;
            }

            if (AutopilotMoveIndicator.Length() > 1)
            {
                AutopilotMoveIndicator /= AutopilotMoveIndicator.Length();
            }

            I += Error * kRunEveryXUpdates;
            if (I.Length() > 5)
            {
                I *= 5 / I.Length();
            }
            D = Error;

            // if close enough, stop.
            if (targetDrift == Vector3D.Zero && distance < 0.25f && speed < 0.25f)
            {
                targetPosition         = Vector3.Zero;
                AutopilotMoveIndicator = Vector3.Zero;
                I = Vector3.Zero;
                D = Vector3.Zero;
            }
        }
示例#13
0
        // Gets the maximum angle deviation from vertical the drone is allowed to operate in
        double GetMaxAngleConstraint()
        {
            var gravAngle = VectorHelpers.VectorAngleBetween(gravDir, Controller.WorldMatrix.Down);

            return(Math.Max(gravAngle, MaxAngleDegrees * Math.PI / 180));
        }
示例#14
0
        public void Update(TimeSpan timestamp, UpdateFrequency updateFlags)
        {
            runs++;

            if (runs % 30 == 0)
            {
                MaxLiftThrust    = 0;
                MaxLateralThrust = 0;
                MaxDownThrust    = 0;
                foreach (var kvp in Thrusters)
                {
                    if (kvp.Key == Base6Directions.Direction.Down)
                    {
                        foreach (var thruster in kvp.Value)
                        {
                            MaxLiftThrust += thruster.MaxEffectiveThrust;
                        }
                    }
                    else if (kvp.Key == Base6Directions.Direction.Forward)
                    {
                        foreach (var thruster in kvp.Value)
                        {
                            MaxLateralThrust += thruster.MaxEffectiveThrust;
                        }
                    }
                    else if (kvp.Key == Base6Directions.Direction.Up)
                    {
                        foreach (var thruster in kvp.Value)
                        {
                            MaxDownThrust += thruster.MaxEffectiveThrust;
                        }
                    }

                    ThrusterManagers[kvp.Key].RecalculateThrust();
                }
            }

            if (runs % 5 == 0)
            {
                StatusBuilder.Clear();

                shipMass = Controller.CalculateShipMass().PhysicalMass;
                gravDir  = Controller.GetNaturalGravity();

                double yawAngle, pitchAngle, spinAngle;
                yawAngle = pitchAngle = spinAngle = 0;
                MatrixD orientationMatrix = new MatrixD();

                var flatCurrentDir = Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(Controller.WorldMatrix.Forward, gravDir);
                flatCurrentDir.Normalize();

                var flatLeftDir = Vector3D.Cross(flatCurrentDir, gravDir);

                if (gravDir != Vector3D.Zero)
                {
                    gravStr = gravDir.Length();
                    gravDir.Normalize();
                    // Rotational Control
                    var targetDir = Vector3D.Zero;
                    if (ForwardDir != Vector3D.Zero)
                    {
                        targetDir = ForwardDir;
                    }
                    else if (FullAuto)
                    {
                        targetDir = Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(Controller.WorldMatrix.Forward, gravDir);
                    }

                    if (targetDir != Vector3D.Zero)
                    {
                        if (UpDir == Vector3D.Zero)
                        {
                            var angleFromVertical    = VectorHelpers.VectorAngleBetween(targetDir, gravDir) - Math.PI * 0.5;
                            var maxAngleFromVertical = GetMaxAngleConstraint();
                            angleFromVertical = Math.Max(Math.Min(angleFromVertical, maxAngleFromVertical), -maxAngleFromVertical);
                            var flatAimDir = targetDir - VectorHelpers.VectorProjection(targetDir, gravDir);
                            flatAimDir.Normalize();

                            var downDir = TrigHelpers.FastCos(angleFromVertical) * gravDir + TrigHelpers.FastSin(angleFromVertical) * flatAimDir;

                            orientationMatrix.Forward = Controller.WorldMatrix.Down;
                            orientationMatrix.Left    = Controller.WorldMatrix.Left;
                            orientationMatrix.Up      = Controller.WorldMatrix.Forward;

                            spinAngle = -VectorHelpers.VectorAngleBetween(flatAimDir, flatCurrentDir) * Math.Sign(Controller.WorldMatrix.Left.Dot(flatAimDir));
                            TrigHelpers.GetRotationAngles(downDir, orientationMatrix.Forward, orientationMatrix.Left, orientationMatrix.Up, out yawAngle, out pitchAngle);
                        }
                        else
                        {
                            orientationMatrix = reference.WorldMatrix;
                            TrigHelpers.GetRotationAngles(ForwardDir, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle);
                            var projectedTargetUp = UpDir - reference.WorldMatrix.Forward.Dot(UpDir) * reference.WorldMatrix.Forward;
                            spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(UpDir));
                        }
                    }
                }
                else if (ForwardDir != Vector3D.Zero)
                {
                    orientationMatrix = reference.WorldMatrix;
                    TrigHelpers.GetRotationAngles(ForwardDir, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle);

                    if (UpDir != Vector3D.Zero)
                    {
                        var projectedTargetUp = UpDir - reference.WorldMatrix.Forward.Dot(UpDir) * reference.WorldMatrix.Forward;
                        spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(UpDir));
                    }
                }

                if (yawAngle != 0 || pitchAngle != 0 || spinAngle != 0)
                {
                    TrigHelpers.ApplyGyroOverride(PitchPID.Control(pitchAngle), YawPID.Control(yawAngle), gravDir == Vector3D.Zero ? spinAngle : SpinPID.Control(spinAngle), Gyros, orientationMatrix);
                }
                else
                {
                    foreach (var gyro in Gyros)
                    {
                        if (gyro.GyroOverride)
                        {
                            gyro.GyroOverride = false;
                        }
                    }
                }

                // Translational Control

                if (Destination == Vector3D.Zero && TargetDrift == Vector3D.Zero)
                {
                    foreach (var kvp in ThrusterManagers)
                    {
                        kvp.Value.SetThrust(0);
                    }

                    if (FullAuto)
                    {
                        Controller.DampenersOverride = true;
                    }
                }
                else
                {
                    Controller.DampenersOverride = false;

                    // Compute direction of motion
                    var destinationDir  = Destination - Reference.GetPosition();
                    var destinationDist = destinationDir.Length();
                    destinationDir.Normalize();

                    // Compute current motion to find desired acceleration
                    var currentVel = Controller.GetShipVelocities().LinearVelocity;

                    if (destinationDist < 0.25 && currentVel.Length() < 0.25 && TargetDrift == Vector3D.Zero)
                    {
                        foreach (var kvp in ThrusterManagers)
                        {
                            kvp.Value.SetThrust(0);
                        }
                        Controller.DampenersOverride = true;
                        Destination = Vector3D.Zero;
                    }
                    else
                    {
                        Vector3D desiredVel = Vector3D.Zero;
                        if (Destination != Vector3D.Zero)
                        {
                            var maxSpeed = Math.Min(MaxSpeed, GetMaxSpeedFromBrakingDistance(destinationDist, GetMaxAccelFromAngleDeviation((float)GetMaxAngleConstraint() * MaxAngleTolerance)) * 0.9);
                            maxSpeed   = Math.Min(maxSpeed, destinationDist * destinationDist + 0.5);
                            desiredVel = destinationDir * maxSpeed;
                        }
                        desiredVel += TargetDrift;
                        var adjustVector = currentVel - VectorHelpers.VectorProjection(currentVel, desiredVel);
                        var desiredAccel = desiredVel - currentVel - adjustVector * 2;

                        // Transform desired acceleration into remote control frame
                        var gridDesiredAccel = Vector3D.TransformNormal(desiredAccel, MatrixD.Transpose(Controller.WorldMatrix));

                        double accelMagnitude = gridDesiredAccel.Length();
                        if (accelMagnitude < PrecisionThreshold)
                        {
                            gridDesiredAccel *= Math.Max(accelMagnitude / PrecisionThreshold, .1);
                        }

                        gridDesiredAccel.X = XPID.Control(gridDesiredAccel.X);
                        gridDesiredAccel.Y = YPID.Control(gridDesiredAccel.Y);
                        gridDesiredAccel.Z = ZPID.Control(gridDesiredAccel.Z);

                        double MinScale    = 10;
                        var    gridGravDir = Vector3D.TransformNormal(gravDir, MatrixD.Transpose(Controller.WorldMatrix));
                        foreach (var kvp in ThrusterManagers)
                        {
                            var desiredDirectionalThrust = -1 * Base6Directions.GetVector(kvp.Key).Dot(gridDesiredAccel) * shipMass;
                            var gravAssist = Base6Directions.GetVector(kvp.Key).Dot(gridGravDir) * shipMass;
                            if (desiredDirectionalThrust > 0)
                            {
                                MinScale = Math.Min((kvp.Value.MaxThrust - gravAssist) / desiredDirectionalThrust, MinScale);
                            }
                        }

                        gridDesiredAccel *= MinScale;
                        gridDesiredAccel -= gridGravDir * gravStr;

                        foreach (var kvp in ThrusterManagers)
                        {
                            kvp.Value.SetThrust(-1 * Base6Directions.GetVector(kvp.Key).Dot(gridDesiredAccel + gridGravDir) * shipMass);
                        }
                    }
                }
            }
        }
        public void Update(TimeSpan timestamp, UpdateFrequency updateFlags)
        {
            runs++;

            OnRelease = OnRelease || LastFrameMouseDown & !Turret.IsShooting;

            var a            = Turret.Azimuth;
            var b            = Turret.Elevation;
            var TurretAimRay = Math.Sin(a) * Math.Cos(b) * Turret.WorldMatrix.Left + Math.Cos(a) * Math.Cos(b) * Turret.WorldMatrix.Forward + Math.Sin(b) * Turret.WorldMatrix.Up;

            var     WallPlane = new Plane(Panels[Vector2I.Zero].GetPosition() - Panels[Vector2I.Zero].WorldMatrix.Backward, Panels[Vector2I.Zero].WorldMatrix.Backward);
            Vector3 Intersection;

            TrigHelpers.PlaneIntersection(WallPlane, Turret.GetPosition() + Turret.WorldMatrix.Up * 0.579 + Turret.WorldMatrix.Backward * 0.068, TurretAimRay, out Intersection);

            var CursorDirection = Intersection - Panels[Vector2I.Zero].GetPosition() + Panels[Vector2I.Zero].WorldMatrix.Backward * 1.25 + Panels[Vector2I.Zero].WorldMatrix.Right * 1.25;
            var CursorDist      = CursorDirection.Length();

            CursorDirection.Normalize();

            // LCD wall configuration:
            // |  |    |
            // |  |    |
            // |  |    |

            // Cursor position, originating in the middle of the LCD wall, with unit in meters
            CursorPos   = Vector3D.TransformNormal(CursorDirection, MatrixD.Transpose(Panels[Vector2I.Zero].WorldMatrix)) * CursorDist;
            CursorPos2D = new Vector2((float)CursorPos.X, (float)CursorPos.Y);

            if (runs % 10 == 0)
            {
                DebugBuilder.Clear();
                SinViewDegree = Math.Sin(ViewAngleDegrees * Math.PI / 180);
                CosViewDegree = Math.Cos(ViewAngleDegrees * Math.PI / 180);

                SpriteScratchpad.Clear();
                int i;
                AddSprite("CircleHollow", new Vector2(0, 0), new Vector2(5, 5 * (float)CosViewDegree));
                for (i = 10000; i <= MapSize; i += 10000)
                {
                    var CircleSize = MapOnScreenSizeMeters * PixelsPerMeter * i / MapSize;
                    AddSprite("CircleHollow", new Vector2(0, 0), new Vector2(CircleSize, CircleSize * (float)CosViewDegree), new Color(1f, 0.4f, 0f, 0.005f));
                }

                var gravDir = Controller.GetNaturalGravity();

                // Create map matrix
                if (gravDir != Vector3D.Zero)
                {
                    // Within gravity, align with gravity = down
                    // Either use controller's forward direction or north as forward
                    gravDir.Normalize();
                    var flatNorthDir = new Vector3D(0, 1, 0) - VectorHelpers.VectorProjection(new Vector3D(0, 1, 0), gravDir);
                    flatNorthDir.Normalize();
                    var flatForwardDir = AlignWithNorth ? flatNorthDir : (Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(AlignWithNorth ? new Vector3D(0, 1, 0) : Controller.WorldMatrix.Forward, gravDir));
                    flatForwardDir.Normalize();
                    var flatLeftDir = Vector3D.Cross(flatForwardDir, gravDir);

                    MapMatrix.Up      = -gravDir;
                    MapMatrix.Forward = flatForwardDir;
                    MapMatrix.Left    = flatLeftDir;

                    var localNorthDir = Vector3D.TransformNormal(flatNorthDir, MatrixD.Transpose(MapMatrix));
                    var localWestDir  = Vector3D.Cross(localNorthDir, new Vector3D(0, -1, 0));

                    AddTextSprite("N", LocalCoordsToMapPosition(localNorthDir * MapSize * 0.5, true), 4);
                    AddTextSprite("S", LocalCoordsToMapPosition(-localNorthDir * MapSize * 0.5, true), 4);
                    AddTextSprite("W", LocalCoordsToMapPosition(localWestDir * MapSize * 0.5, true), 4);
                    AddTextSprite("E", LocalCoordsToMapPosition(-localWestDir * MapSize * 0.5, true), 4);
                }
                else
                {
                    // Else... idk just align with world axis?
                    MapMatrix = MatrixD.Identity;
                }

                var intelItems = IntelProvider.GetFleetIntelligences(timestamp);
                DebugBuilder.AppendLine(intelItems.Count.ToString());

                SelectionCandidates.Clear();

                ClosestItemKey  = MyTuple.Create(IntelItemType.NONE, (long)0);
                ClosestItemDist = 0.3f;

                LocalCoordsScratchpad.Clear();
                ScreenCoordsScratchpad.Clear();

                if (ActionMode == ActionSelectPosition)
                {
                    AddTextSprite("><", CursorPos2D, 1, "Debug");
                    if (OnRelease)
                    {
                        if (SelectFlatPos == Vector2.PositiveInfinity)
                        {
                            SelectFlatPos = CursorPos2D;
                        }
                        else
                        {
                            SelectedPosition = FlatPosToGlobalPos(SelectFlatPos, CursorPos2D);

                            SelectPositionCallback(timestamp);

                            SelectFlatPos = Vector2.PositiveInfinity;
                            ActionMode    = ActionNone;
                        }
                        OnRelease = false;
                    }

                    if (SelectFlatPos != Vector2.PositiveInfinity)
                    {
                        var selectAltitudePos = SelectFlatPos;
                        selectAltitudePos.Y = CursorPos2D.Y;
                        var midPosition = (selectAltitudePos + SelectFlatPos) * 0.5f;
                        var lineLength  = Math.Abs(selectAltitudePos.Y - SelectFlatPos.Y);
                        AddSprite("CircleHollow", selectAltitudePos, new Vector2(20, 20));

                        AddSprite("CircleHollow", SelectFlatPos, new Vector2(30, 30 * (float)CosViewDegree));
                        AddSprite("SquareSimple", midPosition, new Vector2(2, lineLength * PixelsPerMeter));
                    }
                }

                foreach (var kvp in intelItems)
                {
                    Vector3D localCoords;
                    Vector2  flatPosition, altitudePosition;

                    GetMapCoordsFromIntel(kvp.Value, timestamp, out localCoords, out flatPosition, out altitudePosition);

                    ScreenCoordsScratchpad.Add(flatPosition);
                    ScreenCoordsScratchpad.Add(altitudePosition);
                    LocalCoordsScratchpad.Add(localCoords);

                    DebugBuilder.AppendLine(localCoords.ToString());

                    var distToItem = (altitudePosition - CursorPos2D).Length();
                    if (distToItem < ClosestItemDist)
                    {
                        ClosestItemDist = distToItem;
                        ClosestItemKey  = kvp.Key;
                    }
                }

                DrawContextMenu();

                if (ActionMode == ActionNone)
                {
                    SelectionCandidates.Add(ClosestItemKey);
                    if (OnRelease)
                    {
                        if (ClosestItemKey.Item1 == IntelItemType.NONE)
                        {
                            SelectedItems.Clear();
                        }
                        else if (ClosestItemKey.Item1 != IntelItemType.Waypoint)
                        {
                            if (SelectedItems.Count > 0 && SelectedItems[0].Item2 != ClosestItemKey.Item2)
                            {
                                SelectedItems.Clear();
                            }
                            SelectedItems.Add(ClosestItemKey);
                        }
                    }
                }

                i = 0;
                foreach (var kvp in intelItems)
                {
                    AddFleetIntelToMap(kvp.Value, timestamp, LocalCoordsScratchpad[i], ScreenCoordsScratchpad[2 * i], ScreenCoordsScratchpad[2 * i + 1]);
                    i++;
                }

                // var text = Turret.IsShooting ? "[><]" : "><";
                // AddTextSprite(text, CursorPos2D, 2, "Debug");

                foreach (var kvp in Panels)
                {
                    DrawSpritesForPanel(kvp.Key);
                }

                OnRelease = false;
            }

            LastFrameMouseDown = Turret.IsShooting;
        }
示例#16
0
        public void Do(Dictionary <MyTuple <IntelItemType, long>, IFleetIntelligence> IntelItems, TimeSpan canonicalTime, Profiler profiler)
        {
            if (canonicalTime == TimeSpan.Zero)
            {
                return;
            }

            runs++;

            if (MonitorSubsystem != null &&
                (MonitorSubsystem.GetPercentage(MonitorOptions.Hydrogen) < 0.2 ||
                 MonitorSubsystem.GetPercentage(MonitorOptions.Cargo) < 0.02 ||
                 MonitorSubsystem.GetPercentage(MonitorOptions.Power) < 0.1))
            {
                GoHome(canonicalTime);
                return;
            }

            IMyShipController controller     = Autopilot.Controller;
            Vector3D          linearVelocity = controller.GetShipVelocities().LinearVelocity;
            var currentPosition = controller.WorldMatrix.Translation;

            LeadTask.Destination.MaxSpeed = Autopilot.CruiseSpeed;

            if (!TargetPositionSet)
            {
                if (IntelKey.Item1 == IntelItemType.Waypoint && IntelItems.ContainsKey(IntelKey))
                {
                    TargetPosition = IntelItems[IntelKey].GetPositionFromCanonicalTime(canonicalTime);
                    PatrolMaxSpeed = ((Waypoint)IntelItems[IntelKey]).MaxSpeed;
                }
                TargetPositionSet = true;
            }

            EnemyShipIntel orbitIntel       = null;
            EnemyShipIntel shootIntel       = null;
            double         closestIntelDist = CombatSystem.AlertDist;

            foreach (var intel in IntelItems)
            {
                if (intel.Key.Item1 != IntelItemType.Enemy)
                {
                    continue;
                }

                var enemyIntel = (EnemyShipIntel)intel.Value;
                if (!EnemyShipIntel.PrioritizeTarget(enemyIntel))
                {
                    continue;
                }
                if (IntelProvider.GetPriority(enemyIntel.ID) < 2)
                {
                    continue;
                }

                double dist = (enemyIntel.GetPositionFromCanonicalTime(canonicalTime) - controller.WorldMatrix.Translation).Length();

                if (IntelKey.Item1 == IntelItemType.Enemy && enemyIntel.ID != IntelKey.Item2 && FocusedTarget)
                {
                    continue;
                }

                if (enemyIntel.CubeSize == MyCubeSize.Small)
                {
                    dist -= 300;
                }
                if (IntelProvider.GetPriority(enemyIntel.ID) == 3)
                {
                    dist -= 600;
                }
                if (IntelProvider.GetPriority(enemyIntel.ID) == 4)
                {
                    dist -= 1200;
                }
                if (dist < closestIntelDist)
                {
                    closestIntelDist = dist;
                    shootIntel       = enemyIntel;
                    if (enemyIntel.Radius > 30)
                    {
                        orbitIntel = enemyIntel;
                    }
                }
            }

            if (shootIntel == null && CombatSystem.TargetIntel != null && IntelProvider.GetPriority(CombatSystem.TargetIntel.ID) >= 2)
            {
                shootIntel = CombatSystem.TargetIntel;
            }

            if (orbitIntel == null)
            {
                orbitIntel = shootIntel;
            }

            var gravdir = Autopilot.Controller.GetNaturalGravity();

            if (gravdir != Vector3D.Zero)
            {
                gravdir.Normalize();
            }

            // No Target
            if (orbitIntel == null)
            {
                // Plot Intercept
                if (IntelKey.Item1 == IntelItemType.Enemy && IntelItems.ContainsKey(IntelKey) && EnemyShipIntel.PrioritizeTarget((EnemyShipIntel)IntelItems[IntelKey]) && IntelProvider.GetPriority(IntelKey.Item2) >= 2)
                {
                    var target = IntelItems[IntelKey];
                    LeadTask.Destination.Position = currentPosition + AttackHelpers.GetAttackPoint(target.GetVelocity(), target.GetPositionFromCanonicalTime(canonicalTime) + target.GetVelocity() * 0.08 - currentPosition, Autopilot.CruiseSpeed);
                }
                // Go to Position ( Scramble )
                else if (TargetPosition != Vector3.Zero)
                {
                    LeadTask.Destination.MaxSpeed = PatrolMaxSpeed;
                    LeadTask.Destination.Position = TargetPosition;
                }
                else
                {
                    GoHome(canonicalTime);
                    return;
                }

                Vector3D toTarget = LeadTask.Destination.Position - Program.Me.WorldMatrix.Translation;
                if (toTarget.LengthSquared() > 400)
                {
                    if (gravdir == Vector3D.Zero)
                    {
                        LeadTask.Destination.Direction = toTarget;
                    }
                    else
                    {
                        LeadTask.Destination.Direction = Vector3D.Zero;
                    }
                }
                else
                {
                    LeadTask.Destination.Direction = Vector3D.Zero;
                }

                LastAcceleration        = Vector3D.Zero;
                LastReference           = MatrixD.Zero;
                LastEnemyVelocity       = Vector3D.Zero;
                LastEnemyPosition       = Vector3D.Zero;
                LastRelativeAttackPoint = Vector3D.Zero;
//                targetLastPoweredRun = 0;
            }

            // Orbiting a Target
            else
            {
                CombatSystem.MarkEngaged();
                LeadTask.Destination.MaxSpeed = Autopilot.CombatSpeed;
                Vector3D targetPosition    = orbitIntel.GetPositionFromCanonicalTime(canonicalTime);
                var      periodicFactor    = runs * Math.PI * CombatSystem.EngageTheta / 4;
                Vector3D periodicDirection = Math.Sin(periodicFactor) * controller.WorldMatrix.Left + Math.Cos(periodicFactor) * controller.WorldMatrix.Up;

                var Acceleration = linearVelocity - LastLinearVelocity;
                if (LastAcceleration == Vector3D.Zero)
                {
                    LastAcceleration = Acceleration;
                }
                if (LastReference == MatrixD.Zero)
                {
                    LastReference = controller.WorldMatrix;
                }
                if (LastEnemyVelocity == Vector3D.Zero)
                {
                    LastEnemyVelocity = shootIntel.GetVelocity();
                }
                if (LastEnemyPosition == Vector3D.Zero)
                {
                    LastEnemyPosition = shootIntel.GetPositionFromCanonicalTime(canonicalTime);
                }

                var enemyAcceleration = shootIntel.GetVelocity() - LastEnemyVelocity;

                var enemyVelocityAdjust = shootIntel.GetVelocity() * 2 - LastEnemyVelocity;

                var CurrentAccelerationPreviousFrame = Vector3D.TransformNormal(Acceleration, MatrixD.Transpose(LastReference));

                var accelerationAdjust = Vector3D.TransformNormal(CurrentAccelerationPreviousFrame, controller.WorldMatrix);
                var velocityAdjust     = linearVelocity + accelerationAdjust * 0.4;

                velocityAdjust *= CombatSystem.OwnSpeedMultiplier;

                Vector3D relativeAttackPoint = AttackHelpers.GetAttackPoint(enemyVelocityAdjust - velocityAdjust, shootIntel.GetPositionFromCanonicalTime(canonicalTime) + enemyVelocityAdjust * 0.25 - controller.WorldMatrix.Translation - velocityAdjust * 0.25, CombatSystem.ProjectileSpeed);

                relativeAttackPoint.Normalize();

                if (LastRelativeAttackPoint == Vector3D.Zero)
                {
                    LastRelativeAttackPoint = relativeAttackPoint;
                }

                LastAcceleration = linearVelocity - LastLinearVelocity;
                LeadTask.Destination.Direction = relativeAttackPoint;

                if ((controller.WorldMatrix.Translation - targetPosition).Length() < CombatSystem.FireDist &&
                    VectorHelpers.VectorAngleBetween(LeadTask.Destination.Direction, controller.WorldMatrix.Forward) < CombatSystem.FireTolerance)
                {
                    CombatSystem.Fire();
                }

                Vector3D dirTargetToMe  = controller.WorldMatrix.Translation - targetPosition;
                var      distTargetToMe = dirTargetToMe.Length();
                dirTargetToMe.Normalize();

                if (Mode == 0)
                {
                    Vector3D dirTargetToOrbitTarget = Vector3D.Cross(dirTargetToMe, controller.WorldMatrix.Up);
                    dirTargetToOrbitTarget.Normalize();

                    if (gravdir == Vector3D.Zero)
                    {
                        LeadTask.Destination.DirectionUp = Math.Sin(CombatSystem.EngageTheta) * controller.WorldMatrix.Right + Math.Cos(CombatSystem.EngageTheta) * controller.WorldMatrix.Up;
                        LeadTask.Destination.Position    = targetPosition + orbitIntel.GetVelocity() + dirTargetToMe * CombatSystem.EngageDist + dirTargetToOrbitTarget * 200;
                    }
                    else
                    {
                        var flatDirTargetToMe = dirTargetToMe - VectorHelpers.VectorProjection(dirTargetToMe, gravdir);
                        flatDirTargetToMe.Normalize();
                        LeadTask.Destination.Position = targetPosition + orbitIntel.GetVelocity() + flatDirTargetToMe * CombatSystem.EngageDist * 0.9 - gravdir * 300 + periodicDirection * 100;
                    }
                    LeadTask.Destination.Velocity = orbitIntel.GetVelocity() * 0.5;
                }
                else if (Mode == 2)
                {
                    LeadTask.Destination.Position = targetPosition + dirTargetToMe * (CombatSystem.EngageDist + (CombatSystem.EngageDist - distTargetToMe));
                    LeadTask.Destination.Velocity = orbitIntel.GetVelocity();
                }

                LastReference           = controller.WorldMatrix;
                LastEnemyVelocity       = shootIntel.GetVelocity();
                LastEnemyPosition       = shootIntel.GetPositionFromCanonicalTime(canonicalTime);
                LastRelativeAttackPoint = relativeAttackPoint;

                //var n = VectorHelpers.VectorProjection(enemyAcceleration, gravdir).Length() / enemyAcceleration.Length();
                //
                //if (targetLastPoweredRun == 0 || n < 0.6)
                //    targetLastPoweredRun = runs;
                //
                //if (runs - targetLastPoweredRun > 20)
                //    IntelProvider.SetPriority(shootIntel.ID, 1);
            }

            if (!Attack)
            {
                Vector3D toTarget = TargetPosition - Program.Me.WorldMatrix.Translation;
                if (toTarget.LengthSquared() > 100)
                {
                    LeadTask.Destination.Position = TargetPosition;
                }
                else
                {
                    LeadTask.Destination.Position = Vector3D.Zero;
                }
                LeadTask.Destination.Velocity = Vector3D.Zero;
            }

            if (Mode == 1)
            {
                //TODO: Add support for disabling dampeners in this mode - let pilot have full control aside from aiming
                LeadTask.Destination.Position = controller.GetPosition();
                LeadTask.Destination.Velocity = Vector3D.Zero;

                if (shootIntel == null)
                {
                    LeadTask.Destination.Direction   = Vector3D.Zero;
                    LeadTask.Destination.DirectionUp = Vector3D.Zero;
                }
            }

            LastLinearVelocity = linearVelocity;
            if (LeadTask.Status == TaskStatus.Incomplete)
            {
                LeadTask.Do(IntelItems, canonicalTime, profiler);
            }
        }
示例#17
0
        public void SelectTarget(List <EnemyShipIntel> targets, TimeSpan timestamp)
        {
            // Auto reset
            targetAzimuth   = restAzimuth;
            targetElevation = restElevation;

            if (Elevation == null || Azimuth == null)
            {
                return;
            }

            var reference = WeaponGroup.Reference;

            if (!WeaponGroup.Active)
            {
                return;
            }

            if (!active)
            {
                return;
            }

            var myVel         = Host.IntelProvider.Controller.GetShipVelocities().LinearVelocity;
            var canonicalTime = Host.IntelProvider.CanonicalTimeDiff + timestamp;

            foreach (var target in targets)
            {
                var targetVel = target.GetVelocity();
                var targetPos = target.GetPositionFromCanonicalTime(canonicalTime);

                // Get attack position
                var relativeAttackPoint     = AttackHelpers.GetAttackPoint(targetVel - myVel, targetPos - (reference.WorldMatrix.Translation), projectileSpeed);
                var relativeAttackDirection = Vector3D.Normalize(relativeAttackPoint);

                // Check range
                if (relativeAttackPoint.Length() > range)
                {
                    continue;
                }

                // Calculate azimuth angle
                var azimuthVector = relativeAttackDirection - VectorHelpers.VectorProjection(relativeAttackDirection, Azimuth.WorldMatrix.Up);
                var azimuthAngle  = VectorHelpers.VectorAngleBetween(azimuthVector, Azimuth.WorldMatrix.Backward) * Math.Sign(azimuthVector.Dot(Azimuth.WorldMatrix.Left));

                //statusBuilder.AppendLine("AZM: " + (azimuthAngle * 180 / Math.PI).ToString());

                // Check if azimuth is OK
                if (azimuthAngle > AzimuthMax || azimuthAngle < AzimuthMin)
                {
                    continue;
                }

                // Calculate elevation angle
                var elevationAngle = VectorHelpers.VectorAngleBetween(azimuthVector, relativeAttackDirection) * Math.Sign(relativeAttackDirection.Dot(Azimuth.WorldMatrix.Up));
                if (elevationAngle > ElevationMax || elevationAngle < ElevationMin)
                {
                    continue;
                }

                //statusBuilder.AppendLine("ELV: " + (elevationAngle * 180 / Math.PI).ToString());

                // Found best target, set target az, el, and return
                targetAzimuth   = azimuthAngle;
                targetElevation = elevationAngle;
                return;
            }
        }
        public void Update(TimeSpan timestamp, UpdateFrequency updateFlags)
        {
            if (timestamp == TimeSpan.Zero)
            {
                return;
            }
            foreach (var bird in Hummingbirds)
            {
                if (bird.IsAlive())
                {
                    bird.Update();
                }
                else
                {
                    DeadBirds.Add(bird);
                }
            }

            foreach (var bird in DeadBirds)
            {
                DeregisterBird(bird);
            }

            runs++;
            if (runs % 20 == 0)
            {
                var intelItems = IntelProvider.GetFleetIntelligences(timestamp);

                // Get the top targets
                TopEnemies.Clear();
                EnemyToScore.Clear();

                foreach (var intelItem in intelItems)
                {
                    if (intelItem.Key.Item1 == IntelItemType.Enemy)
                    {
                        var esi  = (EnemyShipIntel)intelItem.Value;
                        var dist = (esi.GetPositionFromCanonicalTime(timestamp + IntelProvider.CanonicalTimeDiff) - Context.Reference.WorldMatrix.Translation).Length();
                        if (dist > MaxEngagementDist)
                        {
                            continue;
                        }

                        var priority = IntelProvider.GetPriority(esi.ID);
                        var size     = esi.Radius;

                        if (size < MinEngagementSize && priority < 3)
                        {
                            continue;
                        }

                        if (priority < 2)
                        {
                            continue;
                        }

                        int score = (int)(priority * 10000 + size);

                        EnemyToScore[esi] = score;

                        for (int i = 0; i <= TopEnemies.Count; i++)
                        {
                            if (i == TopEnemies.Count || score > EnemyToScore[TopEnemies[i]])
                            {
                                TopEnemies.Insert(i, esi);
                                break;
                            }
                        }
                    }
                }

                // Determine how many birds should be assigned to each enemy
                EnemyToNumBirds.Clear();

                int totalNeededBirds = 0;

                for (int i = 0; i < TopEnemies.Count && i < 4; i++)
                {
                    EnemyToNumBirds[TopEnemies[i]]      = EnemyCountToNumBirdsPerEnemy[TopEnemies.Count][i];
                    EnemyToAssignedBirds[TopEnemies[i]] = 0;
                    totalNeededBirds += EnemyToNumBirds[TopEnemies[i]];
                }

                // Remove excess birds from enemies
                foreach (var bird in Hummingbirds)
                {
                    var birdTargetID = BirdToEnemy[bird];
                    if (birdTargetID == 0)
                    {
                        continue;
                    }

                    if (!bird.IsCombatCapable())
                    {
                        BirdToEnemy[bird] = 0;
                        continue;
                    }

                    var birdTargetKey = MyTuple.Create(IntelItemType.Enemy, birdTargetID);
                    if (!intelItems.ContainsKey(birdTargetKey))
                    {
                        BirdToEnemy[bird] = 0;
                        continue;
                    }

                    var birdTarget = (EnemyShipIntel)intelItems[birdTargetKey];
                    if (!EnemyToNumBirds.ContainsKey(birdTarget) || EnemyToNumBirds[birdTarget] == 0)
                    {
                        BirdToEnemy[bird] = 0;
                        continue;
                    }

                    EnemyToNumBirds[birdTarget]--;
                    totalNeededBirds--;
                }

                // Assign birds to enemies
                foreach (var bird in Hummingbirds)
                {
                    if (totalNeededBirds == 0)
                    {
                        break;
                    }

                    // Bird can't fight, keep looking
                    if (!bird.IsCombatCapable())
                    {
                        continue;
                    }

                    // Bird already has target, keep looking
                    if (BirdToEnemy[bird] != 0)
                    {
                        continue;
                    }

                    EnemyShipIntel targetEnemy = null;
                    foreach (var enemy in EnemyToNumBirds.Keys)
                    {
                        if (EnemyToNumBirds[enemy] > 0)
                        {
                            targetEnemy = enemy;
                            break;
                        }
                    }

                    BirdToEnemy[bird] = targetEnemy.ID;
                    EnemyToNumBirds[targetEnemy]--;
                    totalNeededBirds--;
                }

                NeedsMoreBirds = totalNeededBirds > 0;
                int birdIndex;

                // ASSUME birds are not far enough from main controller that gravity direction matters too much
                var gravDir = Controller.GetTotalGravity();
                gravDir.Normalize();

                // For each enemy, assign bird target and destination
                foreach (var enemy in TopEnemies)
                {
                    birdIndex = 0;
                    foreach (var bird in Hummingbirds)
                    {
                        if (BirdToEnemy[bird] != enemy.ID)
                        {
                            continue;
                        }

                        if (bird.Gats.Count == 0)
                        {
                            continue;
                        }
                        var birdAltitudeTheta = Math.PI * ((runs / (BirdSineConstantSeconds * 30) % 2) - 1);
                        var birdSwayTheta     = Math.PI * ((runs / (BirdPendulumConstantSeconds * 30) % 2) - 1);
                        var targetPos         = enemy.GetPositionFromCanonicalTime(timestamp + IntelProvider.CanonicalTimeDiff);

                        bird.SetTarget(targetPos, enemy.GetVelocity() - gravDir * (float)TrigHelpers.FastCos(birdAltitudeTheta) * 2);

                        var targetToBase = bird.Base.WorldMatrix.Translation - targetPos;
                        targetToBase -= VectorHelpers.VectorProjection(targetToBase, gravDir);
                        var targetToBaseDist = targetToBase.Length();
                        targetToBase.Normalize();

                        var engageLocationLocus    = targetToBase * Math.Min(600, targetToBaseDist + 400) + targetPos;
                        var engageLocationSwayDir  = targetToBase.Cross(gravDir);
                        var engageLocationSwayDist = (TrigHelpers.FastCos(birdSwayTheta) - EnemyToAssignedBirds[enemy] * 0.5 + birdIndex + 0.5) * 100;

                        bird.SetDest(engageLocationLocus + engageLocationSwayDist * engageLocationSwayDir);

                        var birdDir = bird.Controller.WorldMatrix.Translation - Controller.WorldMatrix.Translation;
                        birdDir -= VectorHelpers.VectorProjection(birdDir, gravDir);;
                        var birdDist = birdDir.Length();

                        bird.Drive.DesiredAltitude = birdDist < 100 ? Hummingbird.RecommendedServiceCeiling :
                                                     (float)TrigHelpers.FastSin(birdAltitudeTheta + Math.PI * 0.5) *
                                                     (Hummingbird.RecommendedServiceCeiling - Hummingbird.RecommendedServiceFloor) + Hummingbird.RecommendedServiceFloor;

                        birdIndex++;
                    }
                }

                // Assign orbit task for unassigned birds
                int numReserveBirds = 0;
                foreach (var bird in Hummingbirds)
                {
                    if (BirdToEnemy[bird] == 0 && bird.IsCombatCapable())
                    {
                        numReserveBirds++;
                    }
                }
                birdIndex = 0;
                var randomPoint = new Vector3D(190, 2862, 809);
                randomPoint -= VectorHelpers.VectorProjection(randomPoint, gravDir);
                randomPoint.Normalize();

                var randomPointCross = randomPoint.Cross(gravDir);

                foreach (var bird in Hummingbirds)
                {
                    if (BirdToEnemy[bird] != 0)
                    {
                        continue;
                    }
                    bird.SetTarget(Vector3D.Zero, Vector3D.Zero);
                    bird.Drive.DesiredAltitude = 30;

                    if (bird.IsCombatCapable() && !bird.IsRetiring)
                    {
                        var birdOrbitTheta = Math.PI * (((2 * birdIndex / (float)numReserveBirds) + runs / (BirdOrbitSeconds * 30)) % 2 - 1);

                        var birdOrbitDest = Controller.WorldMatrix.Translation +
                                            TrigHelpers.FastCos(birdOrbitTheta) * randomPoint * BirdOrbitDist +
                                            TrigHelpers.FastSin(birdOrbitTheta) * randomPointCross * BirdOrbitDist;

                        bird.SetDest(birdOrbitDest);

                        birdIndex++;
                    }
                    else if (!bird.IsRetiring)
                    {
                        RetireBird(bird);
                    }
                    else if (bird.IsRetiring)
                    {
                        if (!bird.IsLanding)
                        {
                            var birdDir = bird.Controller.WorldMatrix.Translation - bird.Destination;
                            birdDir -= VectorHelpers.VectorProjection(birdDir, gravDir);
                            var birdDist = birdDir.Length();
                            birdDir.Normalize();

                            if (birdDist < 50)
                            {
                                bird.SetDest(Vector3D.Zero);
                                bird.Drive.Flush();
                                foreach (var engine in bird.Drive.HoverEngines)
                                {
                                    engine.AltitudeMin = 0;
                                }
                                bird.IsLanding = true;
                            }
                        }
                        else
                        {
                            double altitude;
                            bird.Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude);
                            if (altitude < 6)
                            {
                                foreach (var engine in bird.Drive.HoverEngines)
                                {
                                    engine.Block.Enabled = false;
                                    DeadBirds.Add(bird);
                                }
                            }
                        }
                    }
                }
            }

            foreach (var cradle in Cradles)
            {
                if (cradle == null)
                {
                    continue;
                }
                cradle.Update();
            }

            if (runs % 60 == 0)
            {
                BirdReleaseTimeout--;
                for (int i = 0; i < Cradles.Count(); i++)
                {
                    if (Cradles[i] == null)
                    {
                        continue;
                    }
                    if (Cradles[i].Hummingbird == null)
                    {
                        Cradles[i].CheckHummingbird();
                    }
                    else if (NeedsMoreBirds && BirdReleaseTimeout <= 0)
                    {
                        Hummingbird bird = Cradles[i].Release();
                        bird.Base = Context.Reference;
                        RegisterBird(bird);
                        BirdReleaseTimeout = 5;
                    }
                }
            }

            DeadBirds.Clear();
        }
示例#19
0
        public void Update()
        {
            LifeTimeTicks++;

            // Startup Subroutine
            if (LifeTimeTicks == 1)
            {
                foreach (var engine in Drive.HoverEngines)
                {
                    engine.AltitudeMin = 1;
                    engine.PushOnly    = true;
                }
            }

            if (LifeTimeTicks == 60)
            {
                foreach (var engine in Drive.HoverEngines)
                {
                    engine.AltitudeMin = 2;
                }
            }

            if (LifeTimeTicks == 120)
            {
                foreach (var engine in Drive.HoverEngines)
                {
                    engine.AltitudeMin = 7;
                }
            }

            if (LifeTimeTicks % kRunEveryXUpdates == 0)
            {
                Vector3D PlanetDir = PlanetPos - Controller.WorldMatrix.Translation;
                PlanetDir.Normalize();

                // Orient Self
                Drive.Turn(Gats.Count > 0 ? Gats[0].WorldMatrix : Controller.WorldMatrix, target);

                // Aim Turret
                if (TurretRotor != null)
                {
                    if (target != Vector3D.Zero && Drive.GravAngle < Math.PI * 0.1)
                    {
                        var TurretAngle = TrigHelpers.FastAsin(Gats[0].WorldMatrix.Forward.Dot(PlanetDir));

                        Vector3D TargetDir  = target - Gats[0].WorldMatrix.Translation;
                        var      targetDist = TargetDir.Length();
                        TargetDir.Normalize();
                        var TargetAngle = TrigHelpers.FastAsin(TargetDir.Dot(PlanetDir));

                        var angleDiff = TargetAngle - TurretAngle;

                        if (VectorHelpers.VectorAngleBetween(Gats[0].WorldMatrix.Forward, TargetDir) < 0.05 && targetDist < 800)
                        {
                            Fire();
                        }

                        TurretRotor.TargetVelocityRPM = (float)TurretPID.Control(angleDiff);
                    }
                    else
                    {
                        TurretPID.Reset();
                        TurretRotor.TargetVelocityRPM = 0;
                    }
                }

                // Check your fire
                fireTicks--;
                if (fireTicks == -1)
                {
                    foreach (var gat in Gats)
                    {
                        TerminalPropertiesHelper.SetValue(gat, "Shoot", false);
                    }
                }

                // Check Movement
                if (Destination != Vector3D.Zero)
                {
                    Drive.Drive(Destination);
                    if (Drive.Arrived)
                    {
                        Destination = Vector3D.Zero;
                        Drive.Flush();
                    }
                }
            }
        }
示例#20
0
        public void Update(TimeSpan timestamp, UpdateFrequency updateFlags)
        {
            if (runs % 240 == 0)
            {
                statusBuilder.Clear();
                foreach (var tube in LandpedoTubes)
                {
                    tube.CheckLandpedo();
                    // statusBuilder.AppendLine(tube.GetStatus());
                }
            }

            if (runs % 10 == 0)
            {
                statusBuilder.Clear();
                var targets       = IntelProvider.GetFleetIntelligences(timestamp);
                var canonicalTime = IntelProvider.CanonicalTimeDiff + timestamp;
                DeadLandpedos.Clear();
                foreach (var landpedo in Landpedos)
                {
                    statusBuilder.AppendLine("LANDPEDO===");

                    if (landpedo.Fired)
                    {
                        landpedo.DeadCount--;
                    }

                    if (!landpedo.IsOK())
                    {
                        DeadLandpedos.Add(landpedo);
                        continue;
                    }
                    landpedo.runs++;
                    var landpedoPosition = landpedo.Controller.WorldMatrix.Translation;
                    var landpedoVelocity = landpedo.Controller.GetShipVelocities().LinearVelocity;
                    var gravDir          = landpedo.Controller.GetNaturalGravity();
                    var gravStr          = gravDir.Normalize();
                    var planarVelocity   = landpedoVelocity - VectorHelpers.VectorProjection(landpedoVelocity, gravDir);

                    if (landpedo.TargetID != -1)
                    {
                        var key = MyTuple.Create(IntelItemType.Enemy, landpedo.TargetID);
                        if (targets.ContainsKey(key))
                        {
                            var target = targets[key];
                            landpedo.TargetPosition = target.GetPositionFromCanonicalTime(canonicalTime);
                            landpedo.TargetVelocity = target.GetVelocity();
                        }
                    }

                    statusBuilder.AppendLine(landpedo.TargetPosition.ToString());

                    if (landpedo.TargetPosition != Vector3D.Zero)
                    {
                        var relativeVector = landpedo.TargetPosition - landpedoPosition;
                        var planarVector   = relativeVector - VectorHelpers.VectorProjection(relativeVector, gravDir);

                        var targetPoint = AttackHelpers.GetAttackPoint(landpedo.TargetVelocity, landpedo.TargetPosition - landpedoPosition, landpedo.lastSpeed);
                        if (targetPoint == Vector3D.Zero)
                        {
                            targetPoint = landpedo.TargetPosition - landpedoPosition;
                        }
                        var targetPointDist = targetPoint.Length();

                        var planarDist = planarVector.Length();
                        var velocity   = landpedo.Controller.GetShipVelocities().LinearVelocity;

                        var verticalVelocity = VectorHelpers.VectorProjection(velocity, gravDir);

                        var planarLeft = landpedo.Controller.WorldMatrix.Left - VectorHelpers.VectorProjection(landpedo.Controller.WorldMatrix.Left, gravDir);
                        planarLeft.Normalize();

                        var planarForward = landpedo.Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(landpedo.Controller.WorldMatrix.Forward, gravDir);
                        planarForward.Normalize();

                        double altitude;
                        landpedo.Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude);

                        if (targetPointDist > 350 || landpedo.Launchers.Count == 0)
                        {
                            landpedo.desiredAltitude = planarVector.Length() > 200 ? 10 : 50;
                            planarVector.Normalize();

                            MatrixD orientationMatrix = MatrixD.Identity;
                            orientationMatrix.Translation = landpedo.Controller.WorldMatrix.Translation;

                            orientationMatrix.Up      = -gravDir;
                            orientationMatrix.Left    = planarLeft;
                            orientationMatrix.Forward = planarForward;

                            var spinAngle = VectorHelpers.VectorAngleBetween(planarForward, planarVector) * Math.Sign(-planarLeft.Dot(planarVector));

                            // var planarVelocity = velocity - verticalVelocity;
                            // var velocityAdjust = planarVelocity - VectorHelpers.VectorProjection(velocity, planarVector);
                            // velocityAdjust.Normalize();
                            // planarVector -= velocityAdjust;
                            // var MoveIndicator = Vector3D.TransformNormal(planarVector, MatrixD.Transpose(orientationMatrix));

                            var rangeVector    = planarVector;
                            var waypointVector = rangeVector;
                            var distTargetSq   = rangeVector.LengthSquared();

                            var targetPlanarVelocity = landpedo.TargetVelocity - VectorHelpers.VectorProjection(landpedo.TargetVelocity, gravDir);


                            Vector3D velocityVector = targetPlanarVelocity - planarVelocity;
                            var      speed          = planarVelocity.Length();

                            Vector3D AccelerationVector;

                            double alignment = planarVelocity.Dot(ref waypointVector);
                            if (alignment > 0)
                            {
                                Vector3D rangeDivSqVector = waypointVector / waypointVector.LengthSquared();
                                Vector3D compensateVector = velocityVector - (velocityVector.Dot(ref waypointVector) * rangeDivSqVector);

                                Vector3D targetANVector;
                                var      targetAccel = (landpedo.lastTargetVelocity - targetPlanarVelocity) * 0.16667;

                                targetANVector = targetAccel - (targetAccel.Dot(ref waypointVector) * rangeDivSqVector);

                                bool accelerating = speed > landpedo.lastSpeed + 1;
                                if (accelerating)
                                {
                                    AccelerationVector = planarVelocity + (10 * 1.5 * (compensateVector + (0.5 * targetANVector)));
                                }
                                else
                                {
                                    AccelerationVector = planarVelocity + (10 * (compensateVector + (0.5 * targetANVector)));
                                }
                            }
                            // going backwards or perpendicular
                            else
                            {
                                AccelerationVector = (waypointVector * 0.1) + velocityVector;
                            }

                            landpedo.lastTargetVelocity = landpedo.TargetVelocity;
                            landpedo.lastSpeed          = speed;

                            var MoveIndicator = Vector3D.TransformNormal(AccelerationVector, MatrixD.Transpose(orientationMatrix));

                            MoveIndicator.Y = 0;
                            MoveIndicator.Normalize();

                            statusBuilder.AppendLine(MoveIndicator.ToString());

                            landpedo.Drive.MoveIndicators     = MoveIndicator;
                            landpedo.Drive.RotationIndicators = new Vector3(0, spinAngle, 0);

                            landpedo.Drive.Drive();

                            if (verticalVelocity.Length() > 10 && verticalVelocity.Dot(gravDir) > 0)
                            {
                                landpedo.Drive.maxFlightPitch = 20;
                                landpedo.Drive.maxFlightRoll  = 20;
                            }
                            else
                            {
                                landpedo.Drive.maxFlightPitch = 60;
                                landpedo.Drive.maxFlightRoll  = 60;
                            }

                            if (targetPointDist < 1000)
                            {
                                landpedo.Drive.maxFlightPitch = 20;
                            }
                        }
                        else if (landpedo.TargetID != -1)
                        {
                            var key = MyTuple.Create(IntelItemType.Enemy, landpedo.TargetID);
                            if (!targets.ContainsKey(key))
                            {
                                return;
                            }
                            var target = targets[key];

                            var posDiff = target.GetPositionFromCanonicalTime(canonicalTime) - landpedoPosition;

                            var avgVel = 400 * Math.Sqrt(posDiff.Length() / 400);

                            var relativeAttackPoint = AttackHelpers.GetAttackPoint(landpedo.TargetVelocity - velocity, posDiff, avgVel);
                            targetPointDist = relativeAttackPoint.Length();

                            double yawAngle, pitchAngle;

                            TrigHelpers.GetRotationAngles(relativeAttackPoint, landpedo.Controller.WorldMatrix.Forward, landpedo.Controller.WorldMatrix.Left, landpedo.Controller.WorldMatrix.Up, out yawAngle, out pitchAngle);
                            TrigHelpers.ApplyGyroOverride(landpedo.PitchPID.Control(pitchAngle), landpedo.YawPID.Control(yawAngle), 0, landpedo.Gyros, landpedo.Controller.WorldMatrix);

                            if ((targetPointDist < 125 || landpedo.minDist < planarDist))
                            {
                                foreach (var weapon in landpedo.Launchers)
                                {
                                    weapon.Enabled = true;
                                }
                                landpedo.Fired = true;
                            }

                            landpedo.minDist = Math.Min(landpedo.minDist, planarDist);
                        }

                        var verticalThrustRatio = TrigHelpers.FastCos(VectorHelpers.VectorAngleBetween(landpedo.Controller.WorldMatrix.Down, gravDir));
                        var desiredThrust       = ((landpedo.desiredAltitude - altitude) + verticalVelocity.LengthSquared() * 0.1 + gravStr) * landpedo.Controller.CalculateShipMass().PhysicalMass / verticalThrustRatio;
                        var individualThrust    = desiredThrust / landpedo.Thrusters.Count();
                        if (individualThrust <= 0)
                        {
                            individualThrust = 0.001;
                        }

                        foreach (var thruster in landpedo.Thrusters)
                        {
                            thruster.Enabled        = ((verticalVelocity.Length() > 20 && verticalVelocity.Dot(gravDir) < 0) || ((verticalVelocity.Length() > 2 && verticalVelocity.Dot(gravDir) < 0) && targetPointDist < 1000)) ? false : true;
                            thruster.ThrustOverride = (float)individualThrust;
                        }

                        statusBuilder.AppendLine($"{landpedo.Drive.thrustController.CalculateThrustToHover()}");
                        statusBuilder.AppendLine($"{landpedo.Drive.thrustController.upThrusters.Count} : {landpedo.Drive.thrustController.downThrusters.Count}");
                    }
                }

                foreach (var landpedo in DeadLandpedos)
                {
                    Landpedos.Remove(landpedo);
                }
            }
            runs++;
        }