private static bool AcquireBlock(WeaponSystem system, GridAi ai, Target target, TargetInfo info, Vector3D weaponPos, WeaponRandomGenerator wRng, RandomType type, ref BoundingSphereD waterSphere, Weapon w = null, bool checkPower = true) { if (system.TargetSubSystems) { var subSystems = system.Values.Targeting.SubSystems; var targetLinVel = info.Target.Physics?.LinearVelocity ?? Vector3D.Zero; var targetAccel = (int)system.Values.HardPoint.AimLeadingPrediction > 1 ? info.Target.Physics?.LinearAcceleration ?? Vector3D.Zero : Vector3.Zero; var focusSubSystem = w != null && w.Comp.Data.Repo.Base.Set.Overrides.FocusSubSystem; foreach (var blockType in subSystems) { var bt = focusSubSystem ? w.Comp.Data.Repo.Base.Set.Overrides.SubSystem : blockType; ConcurrentDictionary <BlockTypes, ConcurrentCachingList <MyCubeBlock> > blockTypeMap; system.Session.GridToBlockTypeMap.TryGetValue((MyCubeGrid)info.Target, out blockTypeMap); if (bt != Any && blockTypeMap != null && blockTypeMap[bt].Count > 0) { var subSystemList = blockTypeMap[bt]; if (system.ClosestFirst) { if (target.Top5.Count > 0 && (bt != target.LastBlockType || target.Top5[0].CubeGrid != subSystemList[0].CubeGrid)) { target.Top5.Clear(); } target.LastBlockType = bt; if (GetClosestHitableBlockOfType(subSystemList, ai, target, weaponPos, targetLinVel, targetAccel, ref waterSphere, w, checkPower)) { return(true); } } else if (FindRandomBlock(system, ai, target, weaponPos, info, subSystemList, w, wRng, type, ref waterSphere, checkPower)) { return(true); } } if (focusSubSystem) { break; } } if (system.OnlySubSystems || focusSubSystem && w.Comp.Data.Repo.Base.Set.Overrides.SubSystem != Any) { return(false); } } FatMap fatMap; return(system.Session.GridToFatMap.TryGetValue((MyCubeGrid)info.Target, out fatMap) && fatMap.MyCubeBocks != null && FindRandomBlock(system, ai, target, weaponPos, info, fatMap.MyCubeBocks, w, wRng, type, ref waterSphere, checkPower)); }
private static bool FindRandomBlock(WeaponSystem system, GridAi ai, Target target, Vector3D weaponPos, TargetInfo info, ConcurrentCachingList <MyCubeBlock> subSystemList, Weapon w, WeaponRandomGenerator wRng, RandomType type, ref BoundingSphereD waterSphere, 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; 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 priorityInfo) && priorityInfo.Target?.GetTopMostParent() == topEnt) { isPriroity = true; lastBlocks = totalBlocks < 250 ? totalBlocks : 250; } else 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 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, wRng, type); var physics = system.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 foundBlock = false; var blocksChecked = 0; var blocksSighted = 0; for (int i = 0; i < totalBlocks; i++) { if (turretCheck && (blocksChecked > lastBlocks || isPriroity && (blocksSighted > 100 || blocksChecked > 50 && system.Session.RandomRayCasts > 500 || blocksChecked > 25 && system.Session.RandomRayCasts > 1000))) { break; } var card = deck[i]; var block = subSystemList[card]; if (!(block is IMyTerminalBlock) || block.MarkedForClose || checkPower && !block.IsWorking) { continue; } system.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 > w.MaxTargetDistanceSqr || distSqr < w.MinTargetDistanceSqr) { continue; } blocksChecked++; ai.Session.CanShoot++; Vector3D predictedPos; if (!Weapon.CanShootTarget(w, ref blockPos, targetLinVel, targetAccel, out predictedPos)) { continue; } if (system.Session.WaterApiLoaded && waterSphere.Radius > 2 && waterSphere.Contains(predictedPos) != ContainmentType.Disjoint) { continue; } blocksSighted++; system.Session.RandomRayCasts++; IHitInfo hitInfo; physics.CastRay(weaponPos, blockPos, out hitInfo, 15); if (hitInfo?.HitEntity == null || hitInfo.HitEntity is MyVoxelBase) { continue; } var hitGrid = hitInfo.HitEntity as MyCubeGrid; if (hitGrid != null) { if (hitGrid.MarkedForClose || hitGrid != block.CubeGrid && hitGrid.IsSameConstructAs(ai.MyGrid)) { 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; } return(foundBlock); }
private static int[] GetDeck(ref int[] deck, ref int prevDeckLen, int firstCard, int cardsToSort, int cardsToShuffle, WeaponRandomGenerator rng, RandomType type) { var count = cardsToSort - firstCard; if (prevDeckLen < count) { deck = new int[count]; prevDeckLen = count; } Random rnd; if (type == RandomType.Acquire) { rnd = rng.AcquireRandom; rng.AcquireCurrentCounter += count; } else { rnd = rng.ClientProjectileRandom; rng.ClientProjectileCurrentCounter += count; } for (int i = 0; i < count; i++) { var j = i < cardsToShuffle?rnd.Next(i + 1) : i; deck[i] = deck[j]; deck[j] = firstCard + i; } return(deck); }