Пример #1
0
        /// <summary>
        /// Gets the best block to target from a grid.
        /// </summary>
        /// <param name="grid">The grid to search</param>
        /// <param name="tType">Checked for destroy</param>
        /// <param name="target">The best block fromt the grid</param>
        /// <param name="distanceValue">The value assigned based on distance and position in blocksToTarget.</param>
        /// <remarks>
        /// <para>Decoy blocks will be given a distanceValue of the distance squared to weapon.</para>
        /// <para>Blocks from blocksToTarget will be given a distanceValue of the distance squared * (index + 1)^3.</para>
        /// <para>Other blocks will be given a distanceValue of the distance squared * (1e12).</para>
        /// </remarks>
        public bool GetTargetBlock(IMyCubeGrid grid, TargetType tType, out IMyCubeBlock target, out double distanceValue, bool doRangeTest = true)
        {
            Vector3D      myPosition = ProjectilePosition();
            CubeGridCache cache      = CubeGridCache.GetFor(grid);

            target        = null;
            distanceValue = double.MaxValue;

            if (cache == null)
            {
                return(false);
            }

            if (cache.TerminalBlocks == 0)
            {
                Log.TraceLog("no terminal blocks on grid: " + grid.DisplayName);
                return(false);
            }

            // get decoy block
            {
                foreach (IMyCubeBlock block in cache.BlocksOfType(typeof(MyObjectBuilder_Decoy)))
                {
                    if (!TargetableBlock(block, true))
                    {
                        continue;
                    }

                    double distanceSq = Vector3D.DistanceSquared(myPosition, block.GetPosition());
                    if (doRangeTest && distanceSq > Options.TargetingRangeSquared)
                    {
                        continue;
                    }

                    if (distanceSq < distanceValue && CanConsiderHostile(block))
                    {
                        target        = block;
                        distanceValue = distanceSq;
                    }
                }
                if (target != null)
                {
                    Log.TraceLog("for type = " + tType + " and grid = " + grid.DisplayName + ", found a decoy block: " + target.DisplayNameText + ", distanceValue: " + distanceValue);
                    return(true);
                }
            }

            // get block from blocksToTarget
            if (!Options.blocksToTarget.IsNullOrEmpty())
            {
                int          index        = 0;
                IMyCubeBlock in_target    = target;
                double       in_distValue = distanceValue;

                foreach (MyDefinitionId[] ids in Options.listOfBlocks.IdGroups())
                {
                    index++;
                    foreach (MyDefinitionId id in ids)
                    {
                        //Log.TraceLog("searching for blocks of type: " + id + ", count: " + cache.BlocksOfType(id).Count());
                        foreach (IMyCubeBlock block in cache.BlocksOfType(id))
                        {
                            if (!TargetableBlock(block, true))
                            {
                                continue;
                            }

                            double distSq = Vector3D.DistanceSquared(myPosition, block.GetPosition());
                            if (doRangeTest && distSq > Options.TargetingRangeSquared)
                            {
                                Log.TraceLog("out of range: " + block.nameWithId());
                                continue;
                            }

                            distSq *= index * index * index;

                            if (distSq < in_distValue && CanConsiderHostile(block))
                            {
                                in_target    = block;
                                in_distValue = distSq;
                            }
                        }
                    }
                }

                target        = in_target;
                distanceValue = in_distValue;

                if (target != null)                 // found a block from blocksToTarget
                {
                    Log.TraceLog("for type = " + tType + " and grid = " + grid.DisplayName + ", target = " + target.DisplayNameText +
                                 ", distance = " + Vector3D.Distance(myPosition, target.GetPosition()) + ", distanceValue = " + distanceValue);
                    return(true);
                }
            }

            // get any IMyTerminalBlock
            bool destroy = (tType & TargetType.Moving) != 0 || (tType & TargetType.Destroy) != 0;

            if (destroy || Options.blocksToTarget.IsNullOrEmpty())
            {
                double closest = double.MaxValue;
                foreach (MyCubeBlock block in cache.AllCubeBlocks())
                {
                    if (block is IMyTerminalBlock && TargetableBlock(block, !destroy))
                    {
                        double distanceSq = Vector3D.DistanceSquared(myPosition, block.PositionComp.GetPosition());
                        if (doRangeTest && distanceSq > Options.TargetingRangeSquared)
                        {
                            continue;
                        }
                        distanceSq *= 1e12;

                        if (distanceSq < closest && CanConsiderHostile(block))
                        {
                            target        = block;
                            distanceValue = distanceSq;
                        }
                    }
                }

                if (target != null)
                {
                    Log.TraceLog("for type = " + tType + " and grid = " + grid.DisplayName + ", found a block: " + target.DisplayNameText + ", distanceValue = " + distanceValue);
                    return(true);
                }
            }

            return(false);
        }