internal static bool GetClosestHitableBlockOfType(ConcurrentCachingList <MyCubeBlock> cubes, GridAi ai, Target target, Vector3D currentPos, Vector3D targetLinVel, Vector3D targetAccel, WeaponSystem system, Weapon w = null, bool checkPower = true) { var minValue = double.MaxValue; var minValue0 = double.MaxValue; var minValue1 = double.MaxValue; var minValue2 = double.MaxValue; var minValue3 = double.MaxValue; MyCubeBlock newEntity = null; MyCubeBlock newEntity0 = null; MyCubeBlock newEntity1 = null; MyCubeBlock newEntity2 = null; MyCubeBlock newEntity3 = null; var bestCubePos = Vector3D.Zero; var top5Count = target.Top5.Count; var testPos = currentPos; var top5 = target.Top5; IHitInfo hitInfo = null; var notSelfHit = false; for (int i = 0; i < cubes.Count + top5Count; i++) { ai.Session.BlockChecks++; var index = i < top5Count ? i : i - top5Count; var cube = i < top5Count ? top5[index] : cubes[index]; var grid = cube.CubeGrid; if (grid?.Physics == null || !grid.Physics.Enabled || grid.PositionComp == null) { continue; } if (cube.MarkedForClose || checkPower && !cube.IsWorking || !(cube is IMyTerminalBlock) || cube == newEntity || cube == newEntity0 || cube == newEntity1 || cube == newEntity2 || cube == newEntity3) { continue; } var cubePos = grid.GridIntegerToWorld(cube.Position); var range = cubePos - testPos; var test = (range.X * range.X) + (range.Y * range.Y) + (range.Z * range.Z); if (test < minValue3) { IHitInfo hit = null; var best = test < minValue; var bestTest = false; if (best) { if (w != null && !(!w.IsTurret && w.ActiveAmmoDef.AmmoDef.Trajectory.Smarts.OverideTarget)) { ai.Session.CanShoot++; var castRay = false; Vector3D predictedPos; Vector3D?hitPos; if (Weapon.CanShootTarget(w, cubePos, targetLinVel, targetAccel, out predictedPos)) { castRay = !w.HitOther || !GridIntersection.BresenhamGridIntersection(ai.MyGrid, ref testPos, ref cubePos, out hitPos, w.Comp.MyCube, w.Comp.Ai); } if (castRay) { ai.Session.ClosestRayCasts++; bestTest = MyAPIGateway.Physics.CastRay(testPos, cubePos, out hit, 15, true) && hit?.HitEntity == cube.CubeGrid; if (hit == null && (!w.System.Values.HardPoint.Other.MuzzleCheck || !w.MuzzleHitSelf()) || (hit.HitEntity != ai.MyGrid)) { notSelfHit = true; } } } else { bestTest = true; } } if (best && bestTest) { minValue3 = minValue2; newEntity3 = newEntity2; minValue2 = minValue1; newEntity2 = newEntity1; minValue1 = minValue0; newEntity1 = newEntity0; minValue0 = minValue; newEntity0 = newEntity; minValue = test; newEntity = cube; bestCubePos = cubePos; hitInfo = hit; } else if (test < minValue0) { minValue3 = minValue2; newEntity3 = newEntity2; minValue2 = minValue1; newEntity2 = newEntity1; minValue1 = minValue0; newEntity1 = newEntity0; minValue0 = test; newEntity0 = cube; } else if (test < minValue1) { minValue3 = minValue2; newEntity3 = newEntity2; minValue2 = minValue1; newEntity2 = newEntity1; minValue1 = test; newEntity1 = cube; } else if (test < minValue2) { minValue3 = minValue2; newEntity3 = newEntity2; minValue2 = test; newEntity2 = cube; } else { minValue3 = test; newEntity3 = cube; } } } top5.Clear(); if (newEntity != null && hitInfo != null) { double rayDist; Vector3D.Distance(ref testPos, ref bestCubePos, out rayDist); var shortDist = rayDist * (1 - hitInfo.Fraction); var origDist = rayDist * hitInfo.Fraction; var topEntId = newEntity.GetTopMostParent().EntityId; target.Set(newEntity, hitInfo.Position, shortDist, origDist, topEntId); top5.Add(newEntity); } else if (newEntity != null) { double rayDist; Vector3D.Distance(ref testPos, ref bestCubePos, out rayDist); var shortDist = rayDist; var origDist = rayDist; var topEntId = newEntity.GetTopMostParent().EntityId; target.Set(newEntity, bestCubePos, shortDist, origDist, topEntId); top5.Add(newEntity); } else { target.Reset(ai.Session.Tick, Target.States.NoTargetsSeen, w == null); } if (newEntity0 != null) { top5.Add(newEntity0); } if (newEntity1 != null) { top5.Add(newEntity1); } if (newEntity2 != null) { top5.Add(newEntity2); } if (newEntity3 != null) { top5.Add(newEntity3); } if (!notSelfHit && w != null) { w.HitOther = true; } return(hitInfo != null); }
internal static void AcquireProjectile(Weapon w, out TargetType targetType) { var ai = w.Comp.Ai; var s = w.System; var physics = s.Session.Physics; var target = w.NewTarget; var weaponPos = w.MyPivotPos; var collection = ai.GetProCache(); var numOfTargets = collection.Count; var lockedOnly = w.System.Values.Targeting.LockedSmartOnly; var smartOnly = w.System.Values.Targeting.IgnoreDumbProjectiles; if (s.ClosestFirst) { int length = collection.Count; for (int h = length / 2; h > 0; h /= 2) { for (int i = h; i < length; i += 1) { var tempValue = collection[i]; double temp; Vector3D.DistanceSquared(ref collection[i].Position, ref weaponPos, out temp); int j; for (j = i; j >= h && Vector3D.DistanceSquared(collection[j - h].Position, weaponPos) > temp; j -= h) { collection[j] = collection[j - h]; } collection[j] = tempValue; } } } var numToRandomize = s.ClosestFirst ? w.System.Values.Targeting.TopTargets : numOfTargets; var deck = GetDeck(ref target.TargetDeck, ref target.TargetPrevDeckLen, 0, numOfTargets, numToRandomize, w.TargetData.WeaponRandom, Acquire); for (int x = 0; x < numOfTargets; x++) { var card = deck[x]; var lp = collection[card]; var cube = lp.Info.Target.Entity as MyCubeBlock; if (smartOnly && !lp.SmartsOn || lockedOnly && (!lp.SmartsOn || cube != null && cube.CubeGrid.IsSameConstructAs(w.Comp.Ai.MyGrid)) || lp.MaxSpeed > s.MaxTargetSpeed || lp.MaxSpeed <= 0 || lp.State != Projectile.ProjectileState.Alive || Vector3D.DistanceSquared(lp.Position, w.MyPivotPos) > w.MaxTargetDistanceSqr || Vector3D.DistanceSquared(lp.Position, w.MyPivotPos) < w.MinTargetDistanceSqr) { continue; } Vector3D predictedPos; if (Weapon.CanShootTarget(w, ref lp.Position, lp.Velocity, lp.AccelVelocity, out predictedPos)) { var needsCast = false; for (int i = 0; i < ai.Obstructions.Count; i++) { var ent = ai.Obstructions[i]; var obsSphere = ent.PositionComp.WorldVolume; var dir = lp.Position - weaponPos; var beam = new RayD(ref weaponPos, ref dir); if (beam.Intersects(obsSphere) != null) { var transform = ent.PositionComp.WorldMatrixRef; var box = ent.PositionComp.LocalAABB; var obb = new MyOrientedBoundingBoxD(box, transform); if (obb.Intersects(ref beam) != null) { needsCast = true; break; } } } if (needsCast) { IHitInfo hitInfo; physics.CastRay(weaponPos, lp.Position, out hitInfo, 15); if (hitInfo?.HitEntity == null && (!w.System.Values.HardPoint.Other.MuzzleCheck || !w.MuzzleHitSelf())) { double hitDist; Vector3D.Distance(ref weaponPos, ref lp.Position, out hitDist); var shortDist = hitDist; var origDist = hitDist; const long topEntId = long.MaxValue; target.Set(null, lp.Position, shortDist, origDist, topEntId, lp); targetType = TargetType.Projectile; target.TransferTo(w.Target, w.Comp.Session.Tick); return; } } else { Vector3D?hitInfo; if (GridIntersection.BresenhamGridIntersection(ai.MyGrid, ref weaponPos, ref lp.Position, out hitInfo, w.Comp.MyCube, w.Comp.Ai)) { continue; } double hitDist; Vector3D.Distance(ref weaponPos, ref lp.Position, out hitDist); var shortDist = hitDist; var origDist = hitDist; const long topEntId = long.MaxValue; target.Set(null, lp.Position, shortDist, origDist, topEntId, lp); targetType = TargetType.Projectile; target.TransferTo(w.Target, w.Comp.Session.Tick); return; } } } targetType = TargetType.None; }
private static bool FindRandomBlock(WeaponSystem system, GridAi ai, Target target, Vector3D weaponPos, TargetInfo info, ConcurrentCachingList <MyCubeBlock> subSystemList, Weapon w, int seed, bool checkPower = true) { var totalBlocks = subSystemList.Count; var topEnt = info.Target.GetTopMostParent(); var entSphere = topEnt.PositionComp.WorldVolume; var distToEnt = MyUtils.GetSmallestDistanceToSphere(ref weaponPos, ref entSphere); var turretCheck = w != null; var topBlocks = system.Values.Targeting.TopBlocks; var lastBlocks = topBlocks > 10 && distToEnt < 1000 ? topBlocks : 10; var isPriroity = false; if (lastBlocks < 250) { TargetInfo priorityInfo; if (ai.Focus.Target[0] != null && ai.Targets.TryGetValue(ai.Focus.Target[0], out priorityInfo) && priorityInfo.Target?.GetTopMostParent() == topEnt) { isPriroity = true; lastBlocks = totalBlocks < 250 ? totalBlocks : 250; } else if (ai.Focus.Target[1] != null && ai.Targets.TryGetValue(ai.Focus.Target[1], out priorityInfo) && priorityInfo.Target?.GetTopMostParent() == topEnt) { isPriroity = true; lastBlocks = totalBlocks < 250 ? totalBlocks : 250; } } if (totalBlocks < lastBlocks) { lastBlocks = totalBlocks; } var deck = GetDeck(ref target.BlockDeck, ref target.BlockPrevDeckLen, 0, totalBlocks, topBlocks, seed); var physics = ai.Session.Physics; var iGrid = topEnt as IMyCubeGrid; var gridPhysics = iGrid?.Physics; Vector3D targetLinVel = gridPhysics?.LinearVelocity ?? Vector3D.Zero; Vector3D targetAccel = (int)system.Values.HardPoint.AimLeadingPrediction > 1 ? info.Target.Physics?.LinearAcceleration ?? Vector3D.Zero : Vector3.Zero; var notSelfHit = false; var foundBlock = false; var blocksChecked = 0; var blocksSighted = 0; var weaponRangeSqr = turretCheck ? w.MaxTargetDistanceSqr : 0; for (int i = 0; i < totalBlocks; i++) { if (turretCheck && (blocksChecked > lastBlocks || isPriroity && (blocksSighted > 100 || blocksChecked > 50 && ai.Session.RandomRayCasts > 500 || blocksChecked > 25 && ai.Session.RandomRayCasts > 1000))) { break; } var card = deck[i]; var block = subSystemList[card]; if (!(block is IMyTerminalBlock) || block.MarkedForClose || checkPower && !block.IsWorking) { continue; } ai.Session.BlockChecks++; var blockPos = block.CubeGrid.GridIntegerToWorld(block.Position); double rayDist; if (turretCheck) { double distSqr; Vector3D.DistanceSquared(ref blockPos, ref weaponPos, out distSqr); if (distSqr > weaponRangeSqr) { continue; } blocksChecked++; ai.Session.CanShoot++; Vector3D predictedPos; if (!Weapon.CanShootTarget(w, blockPos, targetLinVel, targetAccel, out predictedPos)) { continue; } blocksSighted++; Vector3D?hitPos; if (!w.HitOther && GridIntersection.BresenhamGridIntersection(ai.MyGrid, ref weaponPos, ref blockPos, out hitPos, w.Comp.MyCube, w.Comp.Ai)) { continue; } ai.Session.RandomRayCasts++; IHitInfo hitInfo; physics.CastRay(weaponPos, blockPos, out hitInfo, 15, true); if (hitInfo == null || hitInfo.HitEntity != ai.MyGrid && (!w.System.Values.HardPoint.Other.MuzzleCheck || !w.MuzzleHitSelf())) { notSelfHit = true; } if (hitInfo?.HitEntity == null || hitInfo.HitEntity is MyVoxelBase || hitInfo.HitEntity == ai.MyGrid) { continue; } var hitGrid = hitInfo.HitEntity as MyCubeGrid; if (hitGrid != null) { if (hitGrid.MarkedForClose) { continue; } bool enemy; var bigOwners = hitGrid.BigOwners; if (bigOwners.Count == 0) { enemy = true; } else { var relationship = target.FiringCube.GetUserRelationToOwner(hitGrid.BigOwners[0]); enemy = relationship != MyRelationsBetweenPlayerAndBlock.Owner && relationship != MyRelationsBetweenPlayerAndBlock.FactionShare; } if (!enemy) { continue; } } Vector3D.Distance(ref weaponPos, ref blockPos, out rayDist); var shortDist = rayDist * (1 - hitInfo.Fraction); var origDist = rayDist * hitInfo.Fraction; var topEntId = block.GetTopMostParent().EntityId; target.Set(block, hitInfo.Position, shortDist, origDist, topEntId); foundBlock = true; break; } Vector3D.Distance(ref weaponPos, ref blockPos, out rayDist); target.Set(block, block.PositionComp.WorldAABB.Center, rayDist, rayDist, block.GetTopMostParent().EntityId); foundBlock = true; break; } if (turretCheck && !notSelfHit) { w.HitOther = true; } return(foundBlock); }