internal static bool TargetAligned(Weapon weapon, Target target, out Vector3D targetPos) { Vector3 targetLinVel = Vector3.Zero; Vector3 targetAccel = Vector3.Zero; var targetCenter = weapon.Comp.TrackReticle ? weapon.Comp.Ai.DummyTarget.Position : target.Projectile?.Position ?? target.Entity.PositionComp.WorldAABB.Center; 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; } var targetDir = targetPos - weapon.MyPivotPos; double rangeToTarget; Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTarget); var inRange = rangeToTarget <= weapon.MaxTargetDistanceSqr; var isAligned = (inRange || weapon.Comp.TrackReticle) && MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotDir, ref targetDir, weapon.AimingTolerance); weapon.Target.TargetPos = targetPos; weapon.Target.IsAligned = isAligned; return(isAligned); }
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 void RunSmart() { Vector3D newVel; if (DeltaVelocityPerTick <= 0 || Vector3D.DistanceSquared(Info.Origin, Position) >= Info.ConsumableDef.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.ConsumableDef.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; if (fake) { targetPos = Info.DummyTarget.Position; } 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.ConsumableDef.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) { tVel = Info.DummyTarget.LinearVelocity; } else if (Info.Target.IsProjectile) { tVel = Info.Target.Projectile.Velocity; } else if (physics != null) { tVel = physics.LinearVelocity; } if (Info.ConsumableDef.Const.TargetLossDegree > 0 && Vector3D.DistanceSquared(Info.Origin, Position) >= Info.ConsumableDef.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.ConsumableDef.Const.TargetLossDegree)) { if (WasTracking) { PickTarget = true; } } else if (!WasTracking) { WasTracking = true; } } } PrevTargetVel = tVel; } else { var roam = Info.ConsumableDef.Trajectory.Smarts.Roam; PrevTargetPos = roam ? PredictedTargetPos : Position + (Info.Direction * Info.MaxTrajectory); if (ZombieLifeTime++ > Info.ConsumableDef.Const.TargetLossTime && !Info.ConsumableDef.Trajectory.Smarts.KeepAliveAfterTargetLoss && (Info.ConsumableDef.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; } } } var missileToTarget = Vector3D.Normalize(PrevTargetPos - Position); var relativeVelocity = PrevTargetVel - Velocity; var normalMissileAcceleration = (relativeVelocity - (relativeVelocity.Dot(missileToTarget) * missileToTarget)) * Info.ConsumableDef.Trajectory.Smarts.Aggressiveness; Vector3D commandedAccel; if (Vector3D.IsZero(normalMissileAcceleration)) { commandedAccel = (missileToTarget * AccelInMetersPerSec); } else { var maxLateralThrust = AccelInMetersPerSec * Math.Min(1, Math.Max(0, Info.ConsumableDef.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; } newVel = Velocity + (commandedAccel * StepConst); AccelDir = commandedAccel / AccelInMetersPerSec; 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; }
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); }
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); }
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); }
internal bool GetTargetState(Session s) { var ai = s.TrackingAi; var validFocus = false; var maxNameLength = 18; if (s.Tick - MasterUpdateTick > 300 || MasterUpdateTick < 300 && _masterTargets.Count == 0) { BuildMasterCollections(ai); } for (int i = 0; i < ai.Construct.Data.Repo.FocusData.Target.Length; i++) { var targetId = ai.Construct.Data.Repo.FocusData.Target[i]; float offenseRating; MyEntity target; if (targetId <= 0 || !MyEntities.TryGetEntityById(targetId, out target) || !_masterTargets.TryGetValue(target, out offenseRating)) { continue; } validFocus = true; if (!s.Tick20) { continue; } var grid = target as MyCubeGrid; var partCount = 1; var largeGrid = false; GridAi targetAi = null; if (grid != null) { largeGrid = grid.GridSizeEnum == MyCubeSize.Large; GridMap gridMap; if (s.GridToMasterAi.TryGetValue(grid, out targetAi)) { partCount = targetAi.Construct.BlockCount; } else if (s.GridToInfoMap.TryGetValue(grid, out gridMap)) { partCount = gridMap.MostBlocks; } } var state = ai.TargetState[i]; state.Aware = targetAi != null?AggressionState(ai, targetAi) : TargetStatus.Awareness.WONDERING; var displayName = target.DisplayName; var name = string.IsNullOrEmpty(displayName) ? string.Empty : displayName.Length <= maxNameLength ? displayName : displayName.Substring(0, maxNameLength); var targetVel = target.Physics?.LinearVelocity ?? Vector3.Zero; if (MyUtils.IsZero(targetVel, 1E-01F)) { targetVel = Vector3.Zero; } var targetDir = Vector3D.Normalize(targetVel); var targetRevDir = -targetDir; var targetPos = target.PositionComp.WorldAABB.Center; var myPos = ai.MyGrid.PositionComp.WorldAABB.Center; var myHeading = Vector3D.Normalize(myPos - targetPos); var intercept = MathFuncs.IsDotProductWithinTolerance(ref targetDir, ref myHeading, s.ApproachDegrees); var retreat = MathFuncs.IsDotProductWithinTolerance(ref targetRevDir, ref myHeading, s.ApproachDegrees); var distanceFromCenters = Vector3D.Distance(ai.MyGrid.PositionComp.WorldAABB.Center, target.PositionComp.WorldAABB.Center); distanceFromCenters -= ai.MyGrid.PositionComp.LocalVolume.Radius; distanceFromCenters -= target.PositionComp.LocalVolume.Radius; distanceFromCenters = distanceFromCenters <= 0 ? 0 : distanceFromCenters; var speed = (float)Math.Round(target.Physics?.Speed ?? 0, 1); state.Name = name; state.RealDistance = distanceFromCenters; state.SizeExtended = (float)Math.Round(partCount / (largeGrid ? 100f : 500f), 1); state.Speed = speed; if (intercept) { state.Engagement = 0; } else if (retreat) { state.Engagement = 1; } else { state.Engagement = 2; } MyTuple <bool, bool, float, float, float, int> shieldInfo = new MyTuple <bool, bool, float, float, float, int>(); if (s.ShieldApiLoaded) { shieldInfo = s.SApi.GetShieldInfo(target); } if (shieldInfo.Item1) { var modInfo = s.SApi.GetModulationInfo(target); var modValue = MyUtils.IsEqual(modInfo.Item3, modInfo.Item4) ? 0 : modInfo.Item3 > modInfo.Item4 ? modInfo.Item3 : -modInfo.Item4; var faceInfo = s.SApi.GetFacesFast(target); state.ShieldFaces = faceInfo.Item1 ? faceInfo.Item2 : Vector3I.Zero; state.ShieldHeat = shieldInfo.Item6 / 10; state.ShieldMod = modValue; state.ShieldHealth = (float)Math.Round(shieldInfo.Item5); } else { state.ShieldHeat = 0; state.ShieldMod = 0; state.ShieldHealth = -1; state.ShieldFaces = Vector3I.Zero; } var friend = false; if (grid != null && grid.BigOwners.Count != 0) { var relation = MyIDModule.GetRelationPlayerBlock(ai.AiOwner, grid.BigOwners[0], MyOwnershipShareModeEnum.Faction); if (relation == MyRelationsBetweenPlayerAndBlock.FactionShare || relation == MyRelationsBetweenPlayerAndBlock.Owner || relation == MyRelationsBetweenPlayerAndBlock.Friends) { friend = true; } } if (friend) { state.ThreatLvl = -1; } else { int shieldBonus = 0; if (s.ShieldApiLoaded) { var myShieldInfo = s.SApi.GetShieldInfo(ai.MyGrid); if (shieldInfo.Item1 && myShieldInfo.Item1) { shieldBonus = shieldInfo.Item5 > myShieldInfo.Item5 ? 1 : -1; } else if (shieldInfo.Item1) { shieldBonus = 1; } else if (myShieldInfo.Item1) { shieldBonus = -1; } } if (offenseRating > 5) { state.ThreatLvl = shieldBonus < 0 ? 8 : 9; } else if (offenseRating > 4) { state.ThreatLvl = 8 + shieldBonus; } else if (offenseRating > 3) { state.ThreatLvl = 7 + shieldBonus; } else if (offenseRating > 2) { state.ThreatLvl = 6 + shieldBonus; } else if (offenseRating > 1) { state.ThreatLvl = 5 + shieldBonus; } else if (offenseRating > 0.5) { state.ThreatLvl = 4 + shieldBonus; } else if (offenseRating > 0.25) { state.ThreatLvl = 3 + shieldBonus; } else if (offenseRating > 0.125) { state.ThreatLvl = 2 + shieldBonus; } else if (offenseRating > 0.0625) { state.ThreatLvl = 1 + shieldBonus; } else if (offenseRating > 0) { state.ThreatLvl = shieldBonus > 0 ? 1 : 0; } else { state.ThreatLvl = -1; } } } return(validFocus); }
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 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); }
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); }
internal bool GetTargetState(Session s) { var ai = s.TrackingAi; var validFocus = false; var size0 = s.Settings.Enforcement.ShipSizes[0]; var size1 = s.Settings.Enforcement.ShipSizes[1]; var size2 = s.Settings.Enforcement.ShipSizes[2]; var size3 = s.Settings.Enforcement.ShipSizes[3]; var size4 = s.Settings.Enforcement.ShipSizes[4]; var size5 = s.Settings.Enforcement.ShipSizes[5]; var size6 = s.Settings.Enforcement.ShipSizes[6]; if (s.Tick - MasterUpdateTick > 300 || MasterUpdateTick < 300 && _masterTargets.Count == 0) { BuildMasterCollections(ai); } for (int i = 0; i < ai.Construct.Data.Repo.FocusData.Target.Length; i++) { var targetId = ai.Construct.Data.Repo.FocusData.Target[i]; float offenseRating; MyEntity target; if (targetId <= 0 || !MyEntities.TryGetEntityById(targetId, out target) || !_masterTargets.TryGetValue(target, out offenseRating)) { continue; } validFocus = true; if (!s.Tick20) { continue; } var grid = target as MyCubeGrid; var partCount = 1; var largeGrid = false; var smallGrid = false; if (grid != null) { largeGrid = grid.GridSizeEnum == MyCubeSize.Large; smallGrid = !largeGrid; GridAi targetAi; GridMap gridMap; if (s.GridToMasterAi.TryGetValue(grid, out targetAi)) { partCount = targetAi.Construct.BlockCount; } else if (s.GridToInfoMap.TryGetValue(grid, out gridMap)) { partCount = gridMap.MostBlocks; } } var targetVel = target.Physics?.LinearVelocity ?? Vector3.Zero; if (MyUtils.IsZero(targetVel, 1E-01F)) { targetVel = Vector3.Zero; } var targetDir = Vector3D.Normalize(targetVel); var targetRevDir = -targetDir; var targetPos = target.PositionComp.WorldAABB.Center; var myPos = ai.MyGrid.PositionComp.WorldAABB.Center; var myHeading = Vector3D.Normalize(myPos - targetPos); if ((size6.LargeGrid && largeGrid || !size6.LargeGrid && smallGrid) && partCount > size6.BlockCount) { ai.TargetState[i].Size = 6; } else if ((size5.LargeGrid && largeGrid || !size5.LargeGrid && smallGrid) && partCount > size5.BlockCount) { ai.TargetState[i].Size = 5; } else if ((size4.LargeGrid && largeGrid || !size4.LargeGrid && smallGrid) && partCount > size4.BlockCount) { ai.TargetState[i].Size = 4; } else if ((size3.LargeGrid && largeGrid || !size3.LargeGrid && smallGrid) && partCount > size3.BlockCount) { ai.TargetState[i].Size = 3; } else if ((size2.LargeGrid && largeGrid || !size2.LargeGrid && smallGrid) && partCount > size2.BlockCount) { ai.TargetState[i].Size = 2; } else if ((size1.LargeGrid && largeGrid || !size1.LargeGrid && smallGrid) && partCount > size1.BlockCount) { ai.TargetState[i].Size = 1; } else { ai.TargetState[i].Size = 0; } ai.TargetState[i].SizeExtended = partCount / (largeGrid ? 100f : 500f); var intercept = MathFuncs.IsDotProductWithinTolerance(ref targetDir, ref myHeading, s.ApproachDegrees); var retreat = MathFuncs.IsDotProductWithinTolerance(ref targetRevDir, ref myHeading, s.ApproachDegrees); if (intercept) { ai.TargetState[i].Engagement = 0; } else if (retreat) { ai.TargetState[i].Engagement = 1; } else { ai.TargetState[i].Engagement = 2; } var distanceFromCenters = Vector3D.Distance(ai.MyGrid.PositionComp.WorldAABB.Center, target.PositionComp.WorldAABB.Center); distanceFromCenters -= ai.MyGrid.PositionComp.LocalVolume.Radius; distanceFromCenters -= target.PositionComp.LocalVolume.Radius; distanceFromCenters = distanceFromCenters <= 0 ? 0 : distanceFromCenters; ai.TargetState[i].RealDistance = distanceFromCenters; var distPercent = (distanceFromCenters / ai.MaxTargetingRange) * 100; if (distPercent > 95) { ai.TargetState[i].Distance = 9; } else if (distPercent > 90) { ai.TargetState[i].Distance = 8; } else if (distPercent > 80) { ai.TargetState[i].Distance = 7; } else if (distPercent > 70) { ai.TargetState[i].Distance = 6; } else if (distPercent > 60) { ai.TargetState[i].Distance = 5; } else if (distPercent > 50) { ai.TargetState[i].Distance = 4; } else if (distPercent > 40) { ai.TargetState[i].Distance = 3; } else if (distPercent > 30) { ai.TargetState[i].Distance = 2; } else if (distPercent > 20) { ai.TargetState[i].Distance = 1; } else if (distPercent > 0) { ai.TargetState[i].Distance = 0; } else { ai.TargetState[i].Distance = -1; } var speed = Math.Round(target.Physics?.Speed ?? 0, 1); if (speed <= 0) { ai.TargetState[i].Speed = -1; } else { var speedPercent = (speed / s.MaxEntitySpeed) * 100; if (speedPercent > 95) { ai.TargetState[i].Speed = 9; } else if (speedPercent > 90) { ai.TargetState[i].Speed = 8; } else if (speedPercent > 80) { ai.TargetState[i].Speed = 7; } else if (speedPercent > 70) { ai.TargetState[i].Speed = 6; } else if (speedPercent > 60) { ai.TargetState[i].Speed = 5; } else if (speedPercent > 50) { ai.TargetState[i].Speed = 4; } else if (speedPercent > 40) { ai.TargetState[i].Speed = 3; } else if (speedPercent > 30) { ai.TargetState[i].Speed = 2; } else if (speedPercent > 20) { ai.TargetState[i].Speed = 1; } else if (speedPercent > 0.3) { ai.TargetState[i].Speed = 0; } else { ai.TargetState[i].Speed = -1; } } MyTuple <bool, bool, float, float, float, int> shieldInfo = new MyTuple <bool, bool, float, float, float, int>(); if (s.ShieldApiLoaded) { shieldInfo = s.SApi.GetShieldInfo(target); } if (shieldInfo.Item1) { var shieldPercent = shieldInfo.Item5; if (shieldPercent > 95) { ai.TargetState[i].ShieldHealth = 9; } else if (shieldPercent > 90) { ai.TargetState[i].ShieldHealth = 8; } else if (shieldPercent > 80) { ai.TargetState[i].ShieldHealth = 7; } else if (shieldPercent > 70) { ai.TargetState[i].ShieldHealth = 6; } else if (shieldPercent > 60) { ai.TargetState[i].ShieldHealth = 5; } else if (shieldPercent > 50) { ai.TargetState[i].ShieldHealth = 4; } else if (shieldPercent > 40) { ai.TargetState[i].ShieldHealth = 3; } else if (shieldPercent > 30) { ai.TargetState[i].ShieldHealth = 2; } else if (shieldPercent > 20) { ai.TargetState[i].ShieldHealth = 1; } else if (shieldPercent > 0) { ai.TargetState[i].ShieldHealth = 0; } else { ai.TargetState[i].ShieldHealth = -1; } } else { ai.TargetState[i].ShieldHealth = -1; } var friend = false; if (grid != null && grid.BigOwners.Count != 0) { var relation = MyIDModule.GetRelationPlayerBlock(ai.AiOwner, grid.BigOwners[0], MyOwnershipShareModeEnum.Faction); if (relation == MyRelationsBetweenPlayerAndBlock.FactionShare || relation == MyRelationsBetweenPlayerAndBlock.Owner || relation == MyRelationsBetweenPlayerAndBlock.Friends) { friend = true; } } if (friend) { ai.TargetState[i].ThreatLvl = -1; } else { int shieldBonus = 0; if (s.ShieldApiLoaded) { var myShieldInfo = s.SApi.GetShieldInfo(ai.MyGrid); if (shieldInfo.Item1 && myShieldInfo.Item1) { shieldBonus = shieldInfo.Item5 > myShieldInfo.Item5 ? 1 : -1; } else if (shieldInfo.Item1) { shieldBonus = 1; } else if (myShieldInfo.Item1) { shieldBonus = -1; } } if (offenseRating > 5) { ai.TargetState[i].ThreatLvl = shieldBonus < 0 ? 8 : 9; } else if (offenseRating > 4) { ai.TargetState[i].ThreatLvl = 8 + shieldBonus; } else if (offenseRating > 3) { ai.TargetState[i].ThreatLvl = 7 + shieldBonus; } else if (offenseRating > 2) { ai.TargetState[i].ThreatLvl = 6 + shieldBonus; } else if (offenseRating > 1) { ai.TargetState[i].ThreatLvl = 5 + shieldBonus; } else if (offenseRating > 0.5) { ai.TargetState[i].ThreatLvl = 4 + shieldBonus; } else if (offenseRating > 0.25) { ai.TargetState[i].ThreatLvl = 3 + shieldBonus; } else if (offenseRating > 0.125) { ai.TargetState[i].ThreatLvl = 2 + shieldBonus; } else if (offenseRating > 0.0625) { ai.TargetState[i].ThreatLvl = 1 + shieldBonus; } else if (offenseRating > 0) { ai.TargetState[i].ThreatLvl = shieldBonus > 0 ? 1 : 0; } else { ai.TargetState[i].ThreatLvl = -1; } } } return(validFocus); }
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; }