internal static bool CanShootTarget(Weapon weapon, ref 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; } var validEstimate = true; if (prediction != Prediction.Off && !weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0) { 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; bool canTrack; bool isTracking; if (weapon == trackingWeapon) { canTrack = validEstimate && MathFuncs.WeaponLookAt(weapon, ref targetDir, rangeToTarget, false, true, out isTracking); } else { canTrack = validEstimate && MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotDir, ref targetDir, weapon.AimingTolerance); } return((inRange && canTrack) || weapon.Comp.Data.Repo.Base.State.TrackingReticle); }
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); }
internal static bool CanShootTarget(Weapon weapon, ref Vector3D targetCenter, Vector3D targetLinVel, Vector3D targetAccel, out Vector3D targetPos, bool checkSelfHit = false, MyEntity target = null) { 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; } var validEstimate = true; if (prediction != Prediction.Off && !weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0) { 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; bool canTrack; bool isTracking; if (weapon == trackingWeapon) { canTrack = validEstimate && MathFuncs.WeaponLookAt(weapon, ref targetDir, rangeToTarget, false, true, out isTracking); } else { canTrack = validEstimate && MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotFwd, ref targetDir, weapon.AimingTolerance); } bool selfHit = false; weapon.LastHitInfo = null; if (checkSelfHit && target != null) { var testLine = new LineD(targetCenter, weapon.BarrelOrigin); var predictedMuzzlePos = testLine.To + (-testLine.Direction * weapon.MuzzleDistToBarrelCenter); var ai = weapon.Comp.Ai; var localPredictedPos = Vector3I.Round(Vector3D.Transform(predictedMuzzlePos, ai.MyGrid.PositionComp.WorldMatrixNormalizedInv) * ai.MyGrid.GridSizeR); MyCube cube; var noCubeAtPosition = !ai.MyGrid.TryGetCube(localPredictedPos, out cube); if (noCubeAtPosition || cube.CubeBlock == weapon.Comp.MyCube.SlimBlock) { var noCubeInLine = !ai.MyGrid.GetIntersectionWithLine(ref testLine, ref ai.GridHitInfo); var noCubesInLineOrHitSelf = noCubeInLine || ai.GridHitInfo.Position == weapon.Comp.MyCube.Position; if (noCubesInLineOrHitSelf) { weapon.System.Session.Physics.CastRay(predictedMuzzlePos, testLine.From, out weapon.LastHitInfo, CollisionLayers.DefaultCollisionLayer); if (weapon.LastHitInfo != null && weapon.LastHitInfo.HitEntity == ai.MyGrid) { selfHit = true; } } } else { selfHit = true; } } return(!selfHit && (inRange && canTrack || weapon.Comp.Data.Repo.Base.State.TrackingReticle)); }
internal static bool TrackingTarget(Weapon weapon, Target target, out bool targetLock) { Vector3D targetPos; Vector3 targetLinVel = Vector3.Zero; Vector3 targetAccel = Vector3.Zero; Vector3D targetCenter; targetLock = false; var rayCheckTest = !weapon.Comp.Session.IsClient && (weapon.Comp.Data.Repo.Base.State.Control == CompStateValues.ControlMode.None || weapon.Comp.Data.Repo.Base.State.Control == CompStateValues.ControlMode.Ui) && 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.Data.Repo.Base.State.TrackingReticle) { targetCenter = weapon.Comp.Session.PlayerDummyTargets[weapon.Comp.Data.Repo.Base.State.PlayerId].Position; } 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 (weapon.Comp.Data.Repo.Base.State.TrackingReticle) { targetLinVel = weapon.Comp.Session.PlayerDummyTargets[weapon.Comp.Data.Repo.Base.State.PlayerId].LinearVelocity; targetAccel = weapon.Comp.Session.PlayerDummyTargets[weapon.Comp.Data.Repo.Base.State.PlayerId].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; } weapon.Target.TargetPos = targetPos; double rangeToTargetSqr; Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTargetSqr); var targetDir = targetPos - weapon.MyPivotPos; var readyToTrack = validEstimate && !weapon.Comp.ResettingSubparts && (weapon.Comp.Data.Repo.Base.State.TrackingReticle || rangeToTargetSqr <= weapon.MaxTargetDistanceSqr && rangeToTargetSqr >= weapon.MinTargetDistanceSqr); var locked = true; var isTracking = false; if (readyToTrack && weapon.Comp.Data.Repo.Base.State.Control != CompStateValues.ControlMode.Camera) { if (MathFuncs.WeaponLookAt(weapon, ref targetDir, rangeToTargetSqr, true, false, out isTracking)) { weapon.ReturingHome = false; locked = false; weapon.AimBarrel(); /* * weapon.LastRotateTick = weapon.System.Session.Tick; * if (!weapon.Rotating) * weapon.System.Session.RotateWeapons.Add(weapon); */ } } weapon.Rotating = !locked; if (weapon.Comp.Data.Repo.Base.State.Control == CompStateValues.ControlMode.Camera) { return(isTracking); } var isAligned = false; if (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 (weapon.System.DesignatorWeapon && weapon.System.Session.IsServer && alignedChange) { for (int i = 0; i < weapon.Comp.Platform.Weapons.Length; i++) { var w = weapon.Comp.Platform.Weapons[i]; if (isAligned && !w.System.DesignatorWeapon) { w.Target.Reset(weapon.System.Session.Tick, Target.States.Designator); } else if (!isAligned && w.System.DesignatorWeapon) { w.Target.Reset(weapon.System.Session.Tick, Target.States.Designator); } } } targetLock = isTracking && weapon.Target.IsAligned; return(isTracking); }