Пример #1
0
        internal static bool TargetAligned(Weapon weapon, Target target, out Vector3D targetPos)
        {
            Vector3  targetLinVel = Vector3.Zero;
            Vector3  targetAccel  = Vector3.Zero;
            Vector3D targetCenter;

            FakeWorldTargetInfo fakeTargetInfo = null;

            if (weapon.Comp.Data.Repo.Base.Set.Overrides.Control != GroupOverrides.ControlModes.Auto && weapon.ValidFakeTargetInfo(weapon.Comp.Data.Repo.Base.State.PlayerId, out fakeTargetInfo))
            {
                targetCenter = fakeTargetInfo.WorldPosition;
            }
            else if (target.IsProjectile)
            {
                targetCenter = target.Projectile?.Position ?? Vector3D.Zero;
            }
            else if (!target.IsFakeTarget)
            {
                targetCenter = target.Entity?.PositionComp.WorldAABB.Center ?? Vector3D.Zero;
            }
            else
            {
                targetCenter = Vector3D.Zero;
            }

            var validEstimate = true;

            if (weapon.System.Prediction != Prediction.Off && (!weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0))
            {
                if (fakeTargetInfo != null)
                {
                    targetLinVel = fakeTargetInfo.LinearVelocity;
                    targetAccel  = fakeTargetInfo.Acceleration;
                }
                else
                {
                    var cube       = target.Entity as MyCubeBlock;
                    var topMostEnt = cube != null ? cube.CubeGrid : target.Entity;

                    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 = TrajectoryEstimation(weapon, targetCenter, targetLinVel, targetAccel, out validEstimate);
            }
            else
            {
                targetPos = targetCenter;
            }

            var targetDir = targetPos - weapon.MyPivotPos;

            double rangeToTarget;

            Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTarget);
            var inRange = rangeToTarget <= weapon.MaxTargetDistanceSqr && rangeToTarget >= weapon.MinTargetDistanceSqr;

            var isAligned = validEstimate && (inRange || weapon.Comp.Data.Repo.Base.State.TrackingReticle) && MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotFwd, ref targetDir, weapon.AimingTolerance);

            weapon.Target.TargetPos = targetPos;
            weapon.Target.IsAligned = isAligned;
            return(isAligned);
        }
Пример #2
0
        internal static bool TrackingTarget(Weapon w, Target target, out bool targetLock)
        {
            Vector3D targetPos;
            Vector3  targetLinVel = Vector3.Zero;
            Vector3  targetAccel  = Vector3.Zero;
            Vector3D targetCenter;

            targetLock = false;

            var baseData = w.Comp.Data.Repo.Base;
            var session  = w.System.Session;
            var ai       = w.Comp.Ai;

            FakeWorldTargetInfo fakeTargetInfo = null;

            if (baseData.Set.Overrides.Control != GroupOverrides.ControlModes.Auto && w.ValidFakeTargetInfo(baseData.State.PlayerId, out fakeTargetInfo))
            {
                targetCenter = fakeTargetInfo.WorldPosition;
            }
            else if (target.IsProjectile)
            {
                targetCenter = target.Projectile?.Position ?? Vector3D.Zero;
            }
            else if (!target.IsFakeTarget)
            {
                targetCenter = target.Entity?.PositionComp.WorldAABB.Center ?? Vector3D.Zero;
            }
            else
            {
                targetCenter = Vector3D.Zero;
            }

            var validEstimate = true;

            if (w.System.Prediction != Prediction.Off && !w.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && w.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0)
            {
                if (fakeTargetInfo != null)
                {
                    targetLinVel = fakeTargetInfo.LinearVelocity;
                    targetAccel  = fakeTargetInfo.Acceleration;
                }
                else
                {
                    var cube       = target.Entity as MyCubeBlock;
                    var topMostEnt = cube != null ? cube.CubeGrid : target.Entity;

                    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 = TrajectoryEstimation(w, targetCenter, targetLinVel, targetAccel, out validEstimate);
            }
            else
            {
                targetPos = targetCenter;
            }

            w.Target.TargetPos = targetPos;

            double rangeToTargetSqr;

            Vector3D.DistanceSquared(ref targetPos, ref w.MyPivotPos, out rangeToTargetSqr);

            var targetDir    = targetPos - w.MyPivotPos;
            var readyToTrack = validEstimate && !w.Comp.ResettingSubparts && (baseData.State.TrackingReticle || rangeToTargetSqr <= w.MaxTargetDistanceSqr && rangeToTargetSqr >= w.MinTargetDistanceSqr);

            var locked     = true;
            var isTracking = false;

            if (readyToTrack && baseData.State.Control != CompStateValues.ControlMode.Camera)
            {
                if (MathFuncs.WeaponLookAt(w, ref targetDir, rangeToTargetSqr, true, false, out isTracking))
                {
                    w.ReturingHome = false;
                    locked         = false;
                    w.AimBarrel();
                }
            }

            w.Rotating = !locked;

            if (baseData.State.Control == CompStateValues.ControlMode.Camera)
            {
                return(isTracking);
            }

            var isAligned = false;

            if (isTracking)
            {
                isAligned = locked || MathFuncs.IsDotProductWithinTolerance(ref w.MyPivotFwd, ref targetDir, w.AimingTolerance);
            }

            var wasAligned = w.Target.IsAligned;

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

            if (w.System.DesignatorWeapon && session.IsServer && alignedChange)
            {
                for (int i = 0; i < w.Comp.Platform.Weapons.Length; i++)
                {
                    var weapon = w.Comp.Platform.Weapons[i];
                    if (isAligned && !weapon.System.DesignatorWeapon)
                    {
                        weapon.Target.Reset(session.Tick, Target.States.Designator);
                    }
                    else if (!isAligned && weapon.System.DesignatorWeapon)
                    {
                        weapon.Target.Reset(session.Tick, Target.States.Designator);
                    }
                }
            }

            targetLock = isTracking && w.Target.IsAligned;

            if (session.IsServer && baseData.Set.Overrides.Repel && ai.TargetingInfo.DroneInRange && !target.IsDrone && (session.AwakeCount == w.Acquire.SlotId || ai.Construct.RootAi.Construct.LastDroneTick == session.Tick) && GridAi.SwitchToDrone(w))
            {
                return(true);
            }

            var rayCheckTest = !w.Comp.Session.IsClient && targetLock && (baseData.State.Control == CompStateValues.ControlMode.None || baseData.State.Control == CompStateValues.ControlMode.Ui) && w.ActiveAmmoDef.AmmoDef.Trajectory.Guidance != GuidanceType.Smart && (!w.Casting && session.Tick - w.Comp.LastRayCastTick > 29 || w.System.Values.HardPoint.Other.MuzzleCheck && session.Tick - w.LastMuzzleCheck > 29);

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

            return(isTracking);
        }
Пример #3
0
        internal void RunSmart()
        {
            Vector3D newVel;

            if (DeltaVelocityPerTick <= 0 || Vector3D.DistanceSquared(Info.Origin, Position) >= Info.AmmoDef.Const.SmartsDelayDistSqr)
            {
                var fake            = Info.Target.IsFakeTarget;
                var gaveUpChase     = !fake && Info.Age - ChaseAge > MaxChaseTime && HadTarget;
                var validTarget     = fake || Info.Target.IsProjectile || Info.Target.Entity != null && !Info.Target.Entity.MarkedForClose;
                var isZombie        = Info.AmmoDef.Const.CanZombie && HadTarget && !fake && !validTarget && ZombieLifeTime > 0 && (ZombieLifeTime + SmartSlot) % 30 == 0;
                var seekFirstTarget = !HadTarget && !validTarget && Info.Age > 120 && (Info.Age + SmartSlot) % 30 == 0;

                if ((PickTarget && (Info.Age + SmartSlot) % 30 == 0 || gaveUpChase && validTarget || isZombie || seekFirstTarget) && NewTarget() || validTarget)
                {
                    HadTarget = true;
                    if (ZombieLifeTime > 0)
                    {
                        ZombieLifeTime = 0;
                        OffSetTarget();
                    }
                    var targetPos = Vector3D.Zero;

                    FakeWorldTargetInfo fakeTargetInfo = null;
                    if (fake)
                    {
                        var fakeTarget = Info.DummyTargets.PaintedTarget.EntityId != 0 && !Info.DummyTargets.PaintedTarget.Dirty ? Info.DummyTargets.PaintedTarget : Info.DummyTargets.ManualTarget;
                        fakeTargetInfo = fakeTarget.LastInfoTick != Info.System.Session.Tick ? fakeTarget.GetFakeTargetInfo(Info.Ai) : fakeTarget.FakeInfo;
                        targetPos      = fakeTargetInfo.WorldPosition;
                    }
                    else if (Info.Target.IsProjectile)
                    {
                        targetPos = Info.Target.Projectile.Position;
                    }
                    else if (Info.Target.Entity != null)
                    {
                        targetPos = Info.Target.Entity.PositionComp.WorldAABB.Center;
                    }

                    if (Info.AmmoDef.Const.TargetOffSet && WasTracking)
                    {
                        if (Info.Age - LastOffsetTime > 300)
                        {
                            double dist;
                            Vector3D.DistanceSquared(ref Position, ref targetPos, out dist);
                            if (dist < OffsetSqr + VelocityLengthSqr && Vector3.Dot(Info.Direction, Position - targetPos) > 0)
                            {
                                OffSetTarget();
                            }
                        }
                        targetPos += TargetOffSet;
                    }

                    PredictedTargetPos = targetPos;

                    var physics = Info.Target.Entity?.Physics ?? Info.Target.Entity?.Parent?.Physics;
                    if (!(Info.Target.IsProjectile || fake) && (physics == null || Vector3D.IsZero(targetPos)))
                    {
                        PrevTargetPos = PredictedTargetPos;
                    }
                    else
                    {
                        PrevTargetPos = targetPos;
                    }

                    var tVel = Vector3.Zero;
                    if (fake && fakeTargetInfo != null)
                    {
                        tVel = fakeTargetInfo.LinearVelocity;
                    }
                    else if (Info.Target.IsProjectile)
                    {
                        tVel = Info.Target.Projectile.Velocity;
                    }
                    else if (physics != null)
                    {
                        tVel = physics.LinearVelocity;
                    }
                    if (Info.AmmoDef.Const.TargetLossDegree > 0 && Vector3D.DistanceSquared(Info.Origin, Position) >= Info.AmmoDef.Const.SmartsDelayDistSqr)
                    {
                        if (WasTracking && (Info.System.Session.Tick20 || Vector3.Dot(Info.Direction, Position - targetPos) > 0) || !WasTracking)
                        {
                            var targetDir = -Info.Direction;
                            var refDir    = Vector3D.Normalize(Position - targetPos);
                            if (!MathFuncs.IsDotProductWithinTolerance(ref targetDir, ref refDir, Info.AmmoDef.Const.TargetLossDegree))
                            {
                                if (WasTracking)
                                {
                                    PickTarget = true;
                                }
                            }
                            else if (!WasTracking)
                            {
                                WasTracking = true;
                            }
                        }
                    }

                    PrevTargetVel = tVel;
                }
                else
                {
                    var roam = Info.AmmoDef.Trajectory.Smarts.Roam;
                    PrevTargetPos = roam ? PredictedTargetPos : Position + (Info.Direction * Info.MaxTrajectory);

                    if (ZombieLifeTime++ > Info.AmmoDef.Const.TargetLossTime && !Info.AmmoDef.Trajectory.Smarts.KeepAliveAfterTargetLoss && (Info.AmmoDef.Trajectory.Smarts.NoTargetExpire || HadTarget))
                    {
                        DistanceToTravelSqr = Info.DistanceTraveled * Info.DistanceTraveled;
                        EarlyEnd            = true;
                    }

                    if (roam && Info.Age - LastOffsetTime > 300 && HadTarget)
                    {
                        double dist;
                        Vector3D.DistanceSquared(ref Position, ref PrevTargetPos, out dist);
                        if (dist < OffsetSqr + VelocityLengthSqr && Vector3.Dot(Info.Direction, Position - PrevTargetPos) > 0)
                        {
                            OffSetTarget(true);
                            PrevTargetPos     += TargetOffSet;
                            PredictedTargetPos = PrevTargetPos;
                        }
                    }
                    else if (MineSeeking)
                    {
                        ResetMine();
                        return;
                    }
                }

                var missileToTarget           = Vector3D.Normalize(PrevTargetPos - Position);
                var relativeVelocity          = PrevTargetVel - Velocity;
                var normalMissileAcceleration = (relativeVelocity - (relativeVelocity.Dot(missileToTarget) * missileToTarget)) * Info.AmmoDef.Trajectory.Smarts.Aggressiveness;

                Vector3D commandedAccel;
                if (Vector3D.IsZero(normalMissileAcceleration))
                {
                    commandedAccel = (missileToTarget * AccelInMetersPerSec);
                }
                else
                {
                    var maxLateralThrust = AccelInMetersPerSec * Math.Min(1, Math.Max(0, Info.AmmoDef.Const.MaxLateralThrust));
                    if (normalMissileAcceleration.LengthSquared() > maxLateralThrust * maxLateralThrust)
                    {
                        Vector3D.Normalize(ref normalMissileAcceleration, out normalMissileAcceleration);
                        normalMissileAcceleration *= maxLateralThrust;
                    }
                    commandedAccel = Math.Sqrt(Math.Max(0, AccelInMetersPerSec * AccelInMetersPerSec - normalMissileAcceleration.LengthSquared())) * missileToTarget + normalMissileAcceleration;
                }

                var offsetTime = Info.AmmoDef.Trajectory.Smarts.OffsetTime;
                if (offsetTime > 0)
                {
                    if ((Info.Age % offsetTime == 0))
                    {
                        double angle = Info.WeaponRng.ClientProjectileRandom.NextDouble() * MathHelper.TwoPi;
                        Info.WeaponRng.ClientProjectileCurrentCounter += 1;
                        var up    = Vector3D.Normalize(Vector3D.CalculatePerpendicularVector(Info.Direction));
                        var right = Vector3D.Cross(Info.Direction, up);
                        OffsetDir  = Math.Sin(angle) * up + Math.Cos(angle) * right;
                        OffsetDir *= Info.AmmoDef.Trajectory.Smarts.OffsetRatio;
                    }

                    commandedAccel += AccelInMetersPerSec * OffsetDir;
                    commandedAccel  = Vector3D.Normalize(commandedAccel) * AccelInMetersPerSec;
                }

                newVel = Velocity + (commandedAccel * StepConst);
                var accelDir = commandedAccel / AccelInMetersPerSec;

                AccelDir = accelDir;

                Vector3D.Normalize(ref newVel, out Info.Direction);
            }
            else
            {
                newVel = Velocity += (Info.Direction * DeltaVelocityPerTick);
            }
            VelocityLengthSqr = newVel.LengthSquared();

            if (VelocityLengthSqr > MaxSpeedSqr)
            {
                newVel = Info.Direction * MaxSpeed;
            }
            Velocity = newVel;
        }