private static void AcquireOther(Weapon w, out TargetType targetType, bool attemptReset = false, MyEntity targetGrid = null) { var comp = w.Comp; var overRides = comp.Data.Repo.Base.Set.Overrides; var attackNeutrals = overRides.Neutrals; var attackFriends = overRides.Friendly; var attackNoOwner = overRides.Unowned; var forceFoci = overRides.FocusTargets; var session = w.Comp.Session; var ai = comp.Ai; session.TargetRequests++; var physics = session.Physics; var weaponPos = w.MyPivotPos; var target = w.NewTarget; var s = w.System; var accelPrediction = (int)s.Values.HardPoint.AimLeadingPrediction > 1; var minRadius = overRides.MinSize * 0.5f; var maxRadius = overRides.MaxSize * 0.5f; var minTargetRadius = minRadius > 0 ? minRadius : s.MinTargetRadius; var maxTargetRadius = maxRadius < s.MaxTargetRadius ? maxRadius : s.MaxTargetRadius; var moveMode = overRides.MoveMode; var movingMode = moveMode == GroupOverrides.MoveModes.Moving; var fireOnStation = moveMode == GroupOverrides.MoveModes.Any || moveMode == GroupOverrides.MoveModes.Moored; var stationOnly = moveMode == GroupOverrides.MoveModes.Moored; Water water = null; BoundingSphereD waterSphere = new BoundingSphereD(Vector3D.Zero, 1f); if (session.WaterApiLoaded && !w.ActiveAmmoDef.AmmoDef.IgnoreWater && ai.InPlanetGravity && ai.MyPlanet != null && session.WaterMap.TryGetValue(ai.MyPlanet, out water)) { waterSphere = new BoundingSphereD(ai.MyPlanet.PositionComp.WorldAABB.Center, water.radius); } TargetInfo alphaInfo = null; TargetInfo betaInfo = null; int offset = 0; MyEntity fTarget; if (ai.Construct.Data.Repo.FocusData.Target[0] > 0 && MyEntities.TryGetEntityById(ai.Construct.Data.Repo.FocusData.Target[0], out fTarget) && ai.Targets.TryGetValue(fTarget, out alphaInfo)) { offset++; } if (ai.Construct.Data.Repo.FocusData.Target[1] > 0 && MyEntities.TryGetEntityById(ai.Construct.Data.Repo.FocusData.Target[1], out fTarget) && ai.Targets.TryGetValue(fTarget, out betaInfo)) { offset++; } TargetInfo gridInfo = null; var forceTarget = false; if (targetGrid != null) { if (ai.Targets.TryGetValue(targetGrid, out gridInfo)) { forceTarget = true; } } var hasOffset = offset > 0; var numOfTargets = ai.SortedTargets.Count; var adjTargetCount = forceFoci && hasOffset ? offset : numOfTargets + offset; var deck = GetDeck(ref target.TargetDeck, ref target.TargetPrevDeckLen, 0, numOfTargets, w.System.Values.Targeting.TopTargets, w.TargetData.WeaponRandom, Acquire); try { for (int x = 0; x < adjTargetCount; x++) { var focusTarget = hasOffset && x < offset; var lastOffset = offset - 1; if (attemptReset && !focusTarget) { break; } TargetInfo info = null; if (forceTarget && !focusTarget) { info = gridInfo; } else { if (focusTarget) { if (x == 0 && alphaInfo != null) { info = alphaInfo; } else if (x == 0 && betaInfo != null) { info = betaInfo; } else if (x == 1) { info = betaInfo; } if (!attackFriends && info.EntInfo.Relationship == MyRelationsBetweenPlayerAndBlock.Friends) { continue; } } else { info = ai.SortedTargets[deck[x - offset]]; } } if (info?.Target == null || info.Target.MarkedForClose || hasOffset && x > lastOffset && (info.Target == alphaInfo?.Target || info.Target == betaInfo?.Target) || !attackNeutrals && info.EntInfo.Relationship == MyRelationsBetweenPlayerAndBlock.Neutral || !attackNoOwner && info.EntInfo.Relationship == MyRelationsBetweenPlayerAndBlock.NoOwnership) { continue; } if (movingMode && info.VelLenSqr < 1 || !fireOnStation && info.IsStatic || stationOnly && !info.IsStatic) { continue; } var character = info.Target as IMyCharacter; var targetRadius = character != null ? info.TargetRadius * 5 : info.TargetRadius; if (targetRadius < minTargetRadius || info.TargetRadius > maxTargetRadius && maxTargetRadius < 8192 || !focusTarget && info.OffenseRating <= 0) { continue; } var targetCenter = info.Target.PositionComp.WorldAABB.Center; var targetDistSqr = Vector3D.DistanceSquared(targetCenter, w.MyPivotPos); if (targetDistSqr > (w.MaxTargetDistance + info.TargetRadius) * (w.MaxTargetDistance + info.TargetRadius) || targetDistSqr < w.MinTargetDistanceSqr) { continue; } if (water != null) { if (new BoundingSphereD(ai.MyPlanet.PositionComp.WorldAABB.Center, water.radius).Contains(new BoundingSphereD(targetCenter, targetRadius)) == ContainmentType.Contains) { continue; } } session.TargetChecks++; Vector3D targetLinVel = info.Target.Physics?.LinearVelocity ?? Vector3D.Zero; Vector3D targetAccel = accelPrediction ? info.Target.Physics?.LinearAcceleration ?? Vector3D.Zero : Vector3.Zero; if (info.IsGrid) { if (!s.TrackGrids || !focusTarget && info.FatCount < 2) { continue; } session.CanShoot++; Vector3D newCenter; if (!w.AiEnabled) { var validEstimate = true; newCenter = w.System.Prediction != HardPointDef.Prediction.Off && (!w.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && w.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0) ? Weapon.TrajectoryEstimation(w, targetCenter, targetLinVel, targetAccel, out validEstimate) : targetCenter; var targetSphere = info.Target.PositionComp.WorldVolume; targetSphere.Center = newCenter; if (!validEstimate || !MathFuncs.TargetSphereInCone(ref targetSphere, ref w.AimCone)) { continue; } } else if (!Weapon.CanShootTargetObb(w, info.Target, targetLinVel, targetAccel, out newCenter)) { continue; } if (w.Comp.Ai.FriendlyShieldNear) { var targetDir = newCenter - weaponPos; if (w.HitFriendlyShield(newCenter, targetDir)) { continue; } } if (!AcquireBlock(s, w.Comp.Ai, target, info, weaponPos, w.TargetData.WeaponRandom, Acquire, ref waterSphere, w, !focusTarget)) { continue; } targetType = TargetType.Other; target.TransferTo(w.Target, w.Comp.Session.Tick); return; } var meteor = info.Target as MyMeteor; if (meteor != null && !s.TrackMeteors || !overRides.Meteors) { continue; } if (character != null && (!s.TrackCharacters || !overRides.Biologicals || character.IsDead || character.Integrity <= 0 || session.AdminMap.ContainsKey(character))) { continue; } Vector3D predictedPos; if (!Weapon.CanShootTarget(w, ref targetCenter, targetLinVel, targetAccel, out predictedPos)) { continue; } if (w.Comp.Ai.FriendlyShieldNear) { var targetDir = predictedPos - weaponPos; if (w.HitFriendlyShield(predictedPos, targetDir)) { continue; } } session.TopRayCasts++; var targetPos = info.Target.PositionComp.WorldAABB.Center; IHitInfo hitInfo; physics.CastRay(weaponPos, targetPos, out hitInfo, CollisionLayers.DefaultCollisionLayer); if (hitInfo != null && hitInfo.HitEntity == info.Target && (!w.System.Values.HardPoint.Other.MuzzleCheck || !w.MuzzleHitSelf())) { double rayDist; Vector3D.Distance(ref weaponPos, ref targetPos, out rayDist); var shortDist = rayDist * (1 - hitInfo.Fraction); var origDist = rayDist * hitInfo.Fraction; var topEntId = info.Target.GetTopMostParent().EntityId; target.Set(info.Target, hitInfo.Position, shortDist, origDist, topEntId); targetType = TargetType.Other; target.TransferTo(w.Target, w.Comp.Session.Tick); return; } if (forceTarget) { break; } } if (!attemptReset || !w.Target.HasTarget) { targetType = TargetType.None; } else { targetType = w.Target.IsProjectile ? TargetType.Projectile : TargetType.Other; } } catch (Exception ex) { Log.Line($"Exception in AcquireOther: {ex}"); targetType = TargetType.None; } }
private static void AcquireOther(Weapon w, out TargetType targetType, bool attemptReset = false, MyEntity targetGrid = null) { var comp = w.Comp; var overRides = comp.Set.Value.Overrides; var overActive = overRides.Activate; var attackNeutrals = overActive && overRides.Neutrals; var attackFriends = overActive && overRides.Friendly; var attackNoOwner = overActive && overRides.Unowned; var forceFoci = overActive && overRides.FocusTargets; var session = w.Comp.Session; var ai = comp.Ai; session.TargetRequests++; var physics = session.Physics; var weaponPos = w.MyPivotPos; var weaponRange = w.MaxTargetDistance; var target = w.NewTarget; var s = w.System; var accelPrediction = (int)s.Values.HardPoint.AimLeadingPrediction > 1; TargetInfo alphaInfo = null; TargetInfo betaInfo = null; int offset = 0; if (ai.Focus.Target[0] != null) { if (ai.Targets.TryGetValue(ai.Focus.Target[0], out alphaInfo)) { offset++; } } if (ai.Focus.Target[1] != null) { if (ai.Targets.TryGetValue(ai.Focus.Target[1], out betaInfo)) { offset++; } } TargetInfo gridInfo = null; var forceTarget = false; if (targetGrid != null) { if (ai.Targets.TryGetValue(targetGrid, out gridInfo)) { forceTarget = true; } } var hasOffset = offset > 0; var numOfTargets = ai.SortedTargets.Count; var adjTargetCount = forceFoci && hasOffset ? offset : numOfTargets + offset; var deck = GetDeck(ref target.TargetDeck, ref target.TargetPrevDeckLen, 0, numOfTargets, w.System.Values.Targeting.TopTargets, w.Comp.Seed); try { for (int x = 0; x < adjTargetCount; x++) { var focusTarget = hasOffset && x < offset; var lastOffset = offset - 1; if (attemptReset && !focusTarget) { break; } TargetInfo info = null; if (forceTarget && !focusTarget) { info = gridInfo; } else { if (focusTarget) { if (x == 0 && alphaInfo != null) { info = alphaInfo; } else if (x == 0 && betaInfo != null) { info = betaInfo; } else if (x == 1) { info = betaInfo; } if (!attackFriends && info.EntInfo.Relationship == MyRelationsBetweenPlayerAndBlock.Friends) { continue; } } else { info = ai.SortedTargets[deck[x - offset]]; } } if (info?.Target == null || info.Target.MarkedForClose || hasOffset && x > lastOffset && (info.Target == alphaInfo?.Target || info.Target == betaInfo?.Target) || !attackNeutrals && info.EntInfo.Relationship == MyRelationsBetweenPlayerAndBlock.Neutral || !attackNoOwner && info.EntInfo.Relationship == MyRelationsBetweenPlayerAndBlock.NoOwnership) { continue; } if (info.TargetRadius < s.MinTargetRadius || info.TargetRadius > s.MaxTargetRadius || !focusTarget && info.OffenseRating <= 0) { continue; } var targetCenter = info.Target.PositionComp.WorldAABB.Center; if (Vector3D.DistanceSquared(targetCenter, w.MyPivotPos) > ((weaponRange + info.TargetRadius) * (weaponRange + info.TargetRadius))) { continue; } session.TargetChecks++; Vector3D targetLinVel = info.Target.Physics?.LinearVelocity ?? Vector3D.Zero; Vector3D targetAccel = accelPrediction ? info.Target.Physics?.LinearAcceleration ?? Vector3D.Zero : Vector3.Zero; if (info.IsGrid) { if (!s.TrackGrids || !focusTarget && info.FatCount < 2) { continue; } session.CanShoot++; if (!w.AiEnabled) { var newCenter = w.System.Prediction != HardPointDef.Prediction.Off && (!w.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && w.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0) ? w.GetPredictedTargetPosition(targetCenter, targetLinVel, targetAccel) : targetCenter; var targetSphere = info.Target.PositionComp.WorldVolume; targetSphere.Center = newCenter; if (!MathFuncs.TargetSphereInCone(ref targetSphere, ref w.AimCone)) { continue; } } else if (!Weapon.CanShootTargetObb(w, info.Target, targetLinVel, targetAccel)) { continue; } if (!AcquireBlock(s, w.Comp.Ai, target, info, weaponPos, w, true, w.Comp.Seed)) { continue; } targetType = TargetType.Other; target.TransferTo(w.Target, w.Comp.Session.Tick); return; } var meteor = info.Target as MyMeteor; if (meteor != null && !s.TrackMeteors) { continue; } var character = info.Target as IMyCharacter; if (character != null && !s.TrackCharacters || character.IsDead || session.AdminMap.ContainsKey(character)) { continue; } Vector3D predictedPos; if (!Weapon.CanShootTarget(w, targetCenter, targetLinVel, targetAccel, out predictedPos)) { continue; } var targetPos = info.Target.PositionComp.WorldAABB.Center; session.TopRayCasts++; IHitInfo hitInfo; physics.CastRay(weaponPos, targetPos, out hitInfo, 15, true); if (hitInfo != null && hitInfo.HitEntity == info.Target && (!w.System.Values.HardPoint.Other.MuzzleCheck || !w.MuzzleHitSelf())) { double rayDist; Vector3D.Distance(ref weaponPos, ref targetPos, out rayDist); var shortDist = rayDist * (1 - hitInfo.Fraction); var origDist = rayDist * hitInfo.Fraction; var topEntId = info.Target.GetTopMostParent().EntityId; target.Set(info.Target, hitInfo.Position, shortDist, origDist, topEntId); targetType = TargetType.Other; target.TransferTo(w.Target, w.Comp.Session.Tick); return; } if (forceTarget) { break; } } if (!attemptReset || !w.Target.HasTarget) { targetType = TargetType.None; } else { targetType = w.Target.IsProjectile ? TargetType.Projectile : TargetType.Other; } } catch (Exception ex) { Log.Line($"Exception in AcquireOther: {ex}"); targetType = TargetType.None; } }