示例#1
0
        internal static bool CanShootTargetObb(Weapon weapon, MyEntity entity, Vector3D targetLinVel, Vector3D targetAccel)
        {
            var      prediction     = weapon.System.Values.HardPoint.AimLeadingPrediction;
            var      trackingWeapon = weapon.TurretMode ? weapon : weapon.Comp.TrackingWeapon;
            Vector3D targetPos;

            if (Vector3D.IsZero(targetLinVel, 5E-03))
            {
                targetLinVel = Vector3.Zero;
            }
            if (Vector3D.IsZero(targetAccel, 5E-03))
            {
                targetAccel = Vector3.Zero;
            }

            var rotMatrix = Quaternion.CreateFromRotationMatrix(entity.PositionComp.WorldMatrix);
            var obb       = new MyOrientedBoundingBoxD(entity.PositionComp.WorldAABB.Center, entity.PositionComp.LocalAABB.HalfExtents, rotMatrix);

            if (prediction != Prediction.Off && !weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0)
            {
                targetPos = weapon.GetPredictedTargetPosition(obb.Center, targetLinVel, targetAccel);
            }
            else
            {
                targetPos = obb.Center;
            }

            obb.Center       = targetPos;
            weapon.TargetBox = obb;

            var maxRangeSqr = obb.HalfExtent.AbsMax() + weapon.MaxTargetDistance;

            maxRangeSqr *= maxRangeSqr;
            double rangeToTarget;

            Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTarget);

            bool canTrack = false;

            if (rangeToTarget <= maxRangeSqr)
            {
                var targetDir = targetPos - weapon.MyPivotPos;
                if (weapon == trackingWeapon)
                {
                    double checkAzimuth;
                    double checkElevation;

                    MathFuncs.GetRotationAngles(ref targetDir, ref weapon.WeaponConstMatrix, out checkAzimuth, out checkElevation);

                    var azConstraint = Math.Min(weapon.MaxAzimuthRadians, Math.Max(weapon.MinAzimuthRadians, checkAzimuth));
                    var elConstraint = Math.Min(weapon.MaxElevationRadians, Math.Max(weapon.MinElevationRadians, checkElevation));

                    Vector3D constraintVector;
                    Vector3D.CreateFromAzimuthAndElevation(azConstraint, elConstraint, out constraintVector);
                    constraintVector = Vector3D.Rotate(constraintVector, weapon.WeaponConstMatrix);

                    var testRay = new RayD(weapon.MyPivotPos, constraintVector);
                    if (obb.Intersects(ref testRay) != null)
                    {
                        canTrack = true;
                    }

                    if (weapon.Comp.Debug)
                    {
                        weapon.LimitLine = new LineD(weapon.MyPivotPos, weapon.MyPivotPos + (constraintVector * weapon.ActiveAmmoDef.AmmoDef.Const.MaxTrajectory));
                    }
                }
                else
                {
                    canTrack = MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotDir, ref targetDir, weapon.AimingTolerance);
                }
            }
            return(canTrack);
        }
示例#2
0
        internal static bool CanShootTarget(Weapon weapon, Vector3D targetCenter, Vector3D targetLinVel, Vector3D targetAccel, out Vector3D targetPos)
        {
            var prediction     = weapon.System.Values.HardPoint.AimLeadingPrediction;
            var trackingWeapon = weapon.TurretMode ? weapon : weapon.Comp.TrackingWeapon;

            if (Vector3D.IsZero(targetLinVel, 5E-03))
            {
                targetLinVel = Vector3.Zero;
            }
            if (Vector3D.IsZero(targetAccel, 5E-03))
            {
                targetAccel = Vector3.Zero;
            }

            if (prediction != Prediction.Off && !weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0)
            {
                targetPos = weapon.GetPredictedTargetPosition(targetCenter, targetLinVel, targetAccel);
            }
            else
            {
                targetPos = targetCenter;
            }
            var targetDir = targetPos - weapon.MyPivotPos;

            double rangeToTarget;

            Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTarget);

            var inRange = rangeToTarget <= weapon.MaxTargetDistanceSqr;

            bool canTrack;

            if (weapon == trackingWeapon)
            {
                Vector3D currentVector;
                Vector3D.CreateFromAzimuthAndElevation(weapon.Azimuth, weapon.Elevation, out currentVector);
                currentVector = Vector3D.Rotate(currentVector, weapon.WeaponConstMatrix);

                var up   = weapon.MyPivotUp;
                var left = Vector3D.Cross(up, currentVector);
                if (!Vector3D.IsUnit(ref left) && !Vector3D.IsZero(left))
                {
                    left.Normalize();
                }
                var forward = Vector3D.Cross(left, up);

                var matrix = new MatrixD {
                    Forward = forward, Left = left, Up = up,
                };

                double desiredAzimuth;
                double desiredElevation;
                MathFuncs.GetRotationAngles(ref targetDir, ref matrix, out desiredAzimuth, out desiredElevation);

                var azConstraint  = Math.Min(weapon.MaxAzimuthRadians, Math.Max(weapon.MinAzimuthRadians, desiredAzimuth));
                var elConstraint  = Math.Min(weapon.MaxElevationRadians, Math.Max(weapon.MinElevationRadians, desiredElevation));
                var azConstrained = Math.Abs(elConstraint - desiredElevation) > 0.0000001;
                var elConstrained = Math.Abs(azConstraint - desiredAzimuth) > 0.0000001;
                canTrack = !azConstrained && !elConstrained;
            }
            else
            {
                canTrack = MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotDir, ref targetDir, weapon.AimingTolerance);
            }

            return((inRange && canTrack) || weapon.Comp.TrackReticle);
        }
示例#3
0
        internal static bool TrackingTarget(Weapon weapon, Target target)
        {
            Vector3D targetPos;
            Vector3  targetLinVel = Vector3.Zero;
            Vector3  targetAccel  = Vector3.Zero;
            var      system       = weapon.System;
            Vector3D targetCenter;

            var rayCheckTest = !weapon.Comp.Session.IsClient && weapon.Comp.State.Value.CurrentPlayerControl.ControlType == ControlType.None && weapon.ActiveAmmoDef.AmmoDef.Trajectory.Guidance == GuidanceType.None && (!weapon.Casting && weapon.Comp.Session.Tick - weapon.Comp.LastRayCastTick > 29 || weapon.System.Values.HardPoint.Other.MuzzleCheck && weapon.Comp.Session.Tick - weapon.LastMuzzleCheck > 29);

            if (rayCheckTest && !weapon.RayCheckTest())
            {
                return(false);
            }

            if (weapon.Comp.TrackReticle)
            {
                targetCenter = weapon.Comp.Ai.DummyTarget.Position;
            }
            else if (target.IsProjectile)
            {
                if (target.Projectile == null)
                {
                    Log.Line($"TrackingTarget: is projectile and it is null");
                    targetCenter = Vector3D.Zero;
                }
                else
                {
                    targetCenter = target.Projectile.Position;
                }
            }
            else if (!target.IsFakeTarget)
            {
                if (target.Entity == null)
                {
                    Log.Line($"TrackingTarget: is entity and it is null");
                    targetCenter = Vector3D.Zero;
                }
                else
                {
                    targetCenter = target.Entity.PositionComp.WorldAABB.Center;
                }
            }
            else
            {
                targetCenter = Vector3D.Zero;
            }

            var needsPrediction = weapon.System.Prediction != Prediction.Off && (!weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0);

            if (needsPrediction)
            {
                if (weapon.Comp.TrackReticle)
                {
                    targetLinVel = weapon.Comp.Ai.DummyTarget.LinearVelocity;
                    targetAccel  = weapon.Comp.Ai.DummyTarget.Acceleration;
                }
                else
                {
                    var topMostEnt = target.Entity?.GetTopMostParent();
                    if (target.Projectile != null)
                    {
                        targetLinVel = target.Projectile.Velocity;
                        targetAccel  = target.Projectile.AccelVelocity;
                    }
                    else if (topMostEnt?.Physics != null)
                    {
                        targetLinVel = topMostEnt.Physics.LinearVelocity;
                        targetAccel  = topMostEnt.Physics.LinearAcceleration;
                    }
                }
                if (Vector3D.IsZero(targetLinVel, 5E-03))
                {
                    targetLinVel = Vector3.Zero;
                }
                if (Vector3D.IsZero(targetAccel, 5E-03))
                {
                    targetAccel = Vector3.Zero;
                }
                targetPos = weapon.GetPredictedTargetPosition(targetCenter, targetLinVel, targetAccel);
            }
            else
            {
                targetPos = targetCenter;
            }

            weapon.Target.TargetPos = targetPos;

            double rangeToTargetSqr;

            Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTargetSqr);
            var targetDir = targetPos - weapon.MyPivotPos;
            var locked    = true;

            if (weapon.Comp.TrackReticle || rangeToTargetSqr <= weapon.MaxTargetDistanceSqr)
            {
                var maxAzimuthStep   = system.AzStep;
                var maxElevationStep = system.ElStep;

                Vector3D currentVector;
                Vector3D.CreateFromAzimuthAndElevation(weapon.Azimuth, weapon.Elevation, out currentVector);
                currentVector = Vector3D.Rotate(currentVector, weapon.WeaponConstMatrix);

                var up   = weapon.MyPivotUp;
                var left = Vector3D.Cross(up, currentVector);
                if (!Vector3D.IsUnit(ref left) && !Vector3D.IsZero(left))
                {
                    left.Normalize();
                }
                var forward          = Vector3D.Cross(left, up);
                var constraintMatrix = new MatrixD {
                    Forward = forward, Left = left, Up = up,
                };

                double desiredAzimuth;
                double desiredElevation;
                MathFuncs.GetRotationAngles(ref targetDir, ref constraintMatrix, out desiredAzimuth, out desiredElevation);

                var azConstraint  = Math.Min(weapon.MaxAzimuthRadians, Math.Max(weapon.MinAzimuthRadians, desiredAzimuth));
                var elConstraint  = Math.Min(weapon.MaxElevationRadians, Math.Max(weapon.MinElevationRadians, desiredElevation));
                var elConstrained = Math.Abs(elConstraint - desiredElevation) > 0.0000001;
                var azConstrained = Math.Abs(azConstraint - desiredAzimuth) > 0.0000001;
                weapon.Target.IsTracking = !azConstrained && !elConstrained;

                if (weapon.Target.IsTracking && weapon.Comp.State.Value.CurrentPlayerControl.ControlType != ControlType.Camera && !weapon.Comp.ResettingSubparts)
                {
                    var oldAz   = weapon.Azimuth;
                    var oldEl   = weapon.Elevation;
                    var epsilon = target.IsProjectile ? 1E-06d : rangeToTargetSqr <= 640000 ? 1E-03d : rangeToTargetSqr <= 3240000 ? 1E-04d : 1E-05d;
                    var az      = weapon.Azimuth + MathHelperD.Clamp(desiredAzimuth, -maxAzimuthStep, maxAzimuthStep);
                    var el      = weapon.Elevation + MathHelperD.Clamp(desiredElevation - weapon.Elevation, -maxElevationStep, maxElevationStep);

                    var azDiff   = oldAz - az;
                    var elDiff   = oldEl - el;
                    var azLocked = MyUtils.IsZero(azDiff, (float)epsilon);
                    var elLocked = MyUtils.IsZero(elDiff, (float)epsilon);

                    locked = azLocked && elLocked;
                    var aim = !azLocked || !elLocked;
                    if (aim)
                    {
                        if (!azLocked)
                        {
                            weapon.Azimuth = az;
                        }
                        if (!elLocked)
                        {
                            weapon.Elevation = el;
                        }
                        weapon.IsHome = false;
                        weapon.AimBarrel(azDiff, elDiff, !azLocked, !elLocked);
                    }
                }
            }
            else
            {
                weapon.Target.IsTracking = false;
            }

            if (weapon.Comp.State.Value.CurrentPlayerControl.ControlType == ControlType.Camera)
            {
                return(weapon.Target.IsTracking);
            }

            var isAligned = false;

            if (weapon.Target.IsTracking)
            {
                isAligned = locked || MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotDir, ref targetDir, weapon.AimingTolerance);
            }

            var wasAligned = weapon.Target.IsAligned;

            weapon.Target.IsAligned = isAligned;
            var alignedChange = wasAligned != isAligned;

            if (alignedChange && isAligned)
            {
                if (weapon.System.DesignatorWeapon)
                {
                    for (int i = 0; i < weapon.Comp.Platform.Weapons.Length; i++)
                    {
                        var w = weapon.Comp.Platform.Weapons[i];
                        w.Target.StateChange(false, Target.States.Expired);
                        w.Target.CheckTick -= 240;
                    }
                }
            }
            else if (alignedChange && !weapon.System.DelayCeaseFire)
            {
                weapon.StopShooting();
            }

            weapon.Target.TargetLock = weapon.Target.IsTracking && weapon.Target.IsAligned;
            return(weapon.Target.IsTracking);
        }
示例#4
0
        internal static void LeadTarget(Weapon weapon, MyEntity target, out Vector3D targetPos, out bool couldHit, out bool willHit)
        {
            var vel            = target.Physics.LinearVelocity;
            var accel          = target.Physics.LinearAcceleration;
            var trackingWeapon = weapon.TurretMode || weapon.Comp.TrackingWeapon == null ? weapon : weapon.Comp.TrackingWeapon;

            var box = target.PositionComp.LocalAABB;
            var obb = new MyOrientedBoundingBoxD(box, target.PositionComp.WorldMatrixRef);

            var validEstimate = true;
            var advancedMode  = weapon.ActiveAmmoDef.AmmoDef.Trajectory.AccelPerSec > 0 || weapon.Comp.Ai.InPlanetGravity && weapon.ActiveAmmoDef.AmmoDef.Const.FeelsGravity;

            if (!weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0)
            {
                targetPos = TrajectoryEstimation(weapon, obb.Center, vel, accel, out validEstimate, true, advancedMode);
            }
            else
            {
                targetPos = obb.Center;
            }

            obb.Center       = targetPos;
            weapon.TargetBox = obb;

            var obbAbsMax   = obb.HalfExtent.AbsMax();
            var maxRangeSqr = obbAbsMax + weapon.MaxTargetDistance;
            var minRangeSqr = obbAbsMax + weapon.MinTargetDistance;

            maxRangeSqr *= maxRangeSqr;
            minRangeSqr *= minRangeSqr;
            double rangeToTarget;

            Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTarget);
            couldHit = validEstimate && rangeToTarget <= maxRangeSqr && rangeToTarget >= minRangeSqr;

            bool canTrack = false;

            if (validEstimate && rangeToTarget <= maxRangeSqr && rangeToTarget >= minRangeSqr)
            {
                var targetDir = targetPos - weapon.MyPivotPos;
                if (weapon == trackingWeapon)
                {
                    double checkAzimuth;
                    double checkElevation;

                    MathFuncs.GetRotationAngles(ref targetDir, ref weapon.WeaponConstMatrix, out checkAzimuth, out checkElevation);

                    var azConstraint = Math.Min(weapon.MaxAzToleranceRadians, Math.Max(weapon.MinAzToleranceRadians, checkAzimuth));
                    var elConstraint = Math.Min(weapon.MaxElToleranceRadians, Math.Max(weapon.MinElToleranceRadians, checkElevation));

                    Vector3D constraintVector;
                    Vector3D.CreateFromAzimuthAndElevation(azConstraint, elConstraint, out constraintVector);
                    Vector3D.Rotate(ref constraintVector, ref weapon.WeaponConstMatrix, out constraintVector);

                    var testRay = new RayD(ref weapon.MyPivotPos, ref constraintVector);
                    if (obb.Intersects(ref testRay) != null)
                    {
                        canTrack = true;
                    }

                    if (weapon.Comp.Debug)
                    {
                        weapon.LimitLine = new LineD(weapon.MyPivotPos, weapon.MyPivotPos + (constraintVector * weapon.ActiveAmmoDef.AmmoDef.Const.MaxTrajectory));
                    }
                }
                else
                {
                    canTrack = MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotFwd, ref targetDir, weapon.AimingTolerance);
                }
            }
            willHit = canTrack;
        }