コード例 #1
0
        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);
        }
コード例 #2
0
        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;
            }
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
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);
        }
コード例 #5
0
        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);
        }
コード例 #6
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();
                    }
                }
            }
        }
コード例 #7
0
        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);
            }
        }
コード例 #8
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;
            }
        }
コード例 #9
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++;
        }
コード例 #10
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));
        }
コード例 #11
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);
                        }
                    }
                }
            }
        }
コード例 #12
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);
            }
        }
コード例 #13
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;
            }
        }
コード例 #14
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];
            }
        }