示例#1
0
            bool CanTargetActor(Actor self, Target target, ref TargetModifiers modifiers, ref string cursor)
            {
                IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);

                if (modifiers.HasModifier(TargetModifiers.ForceMove))
                {
                    return(false);
                }

                if (target.Type == TargetT.Actor && target.Actor.EffectiveOwner != null &&
                    target.Actor.EffectiveOwner.Disguised && self.Owner.Stances[target.Actor.Owner] == Stance.Enemy)
                {
                    modifiers |= TargetModifiers.ForceAttack;
                }

                var forceAttack = modifiers.HasModifier(TargetModifiers.ForceAttack);
                var armaments   = ab.ChooseArmamentsForTarget(target, forceAttack);

                if (!armaments.Any())
                {
                    return(false);
                }

                armaments = armaments.OrderByDescending(x => x.MaxRange());
                var a = armaments.FirstOrDefault(x => !x.IsTraitPaused);

                if (a == null)
                {
                    a = armaments.First();
                }

                cursor = !target.IsInRange(self.CenterPosition, a.MaxRange())
                    ? ab.Info.OutsideRangeCursor ?? a.Info.OutsideRangeCursor
                    : ab.Info.Cursor ?? a.Info.Cursor;

                if (!forceAttack)
                {
                    return(true);
                }

                OrderID = ab.forceAttackOrderName;
                return(true);
            }
示例#2
0
        /// <summary>
        /// 选择攻击目标
        /// </summary>
        /// <param name="self"></param>
        /// <param name="ab"></param>
        /// <param name="attackStances"></param>
        /// <param name="scanRange"></param>
        /// <param name="allowMove"></param>
        /// <returns></returns>
        Actor ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove)
        {
            Actor chosenTarget         = null;
            var   chosenTargetPriority = int.MinValue;
            int   chosenTargetRange    = 0;

            var activePriorities = targetPriorities.Where(Exts.IsTraitEnabled)
                                   .Select(at => at.Info)
                                   .OrderByDescending(ati => ati.Priority)
                                   .ToList();

            if (!activePriorities.Any())
            {
                return(null);
            }

            var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, scanRange);

            foreach (var actor in actorsInRange)
            {
                //PERF:Most units can only attack enemy units.If this is the case but the target is not an enemy,
                //We can bail early and avoid the more expensive targeting checks and armaments selection.
                //For groups of allied units.this helps significantly reduce the cost of auto target scans.
                //This is important as these groups will continuously rescan their allies until an enemy finally comes into range.
                //
                if (attackStances == EW.Traits.Stance.Enemy && !actor.AppearsHostileTo(self))
                {
                    continue;
                }

                var targetTypes = actor.TraitsImplementing <ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).ToHashSet();

                var target          = Target.FromActor(actor);
                var validPriorities = activePriorities.Where(ati =>
                {
                    //Already have a higher priority target.
                    if (ati.Priority < chosenTargetPriority)
                    {
                        return(false);
                    }

                    //Incompatible target types.
                    if (!targetTypes.Overlaps(ati.ValidTargets) || targetTypes.Overlaps(ati.InvalidTargets))
                    {
                        return(false);
                    }
                    return(true);
                }).ToList();

                if (!validPriorities.Any() || PreventsAutoTarget(self, actor) || !actor.CanBeViewedByPlayer(self.Owner))
                {
                    continue;
                }

                //Make sure that we can actually fire on the actor.
                var armaments = ab.ChooseArmamentsForTarget(target, false);

                if (!allowMove)
                {
                    armaments = armaments.Where(arm => target.IsInRange(self.CenterPosition, arm.MaxRange()) && !target.IsInRange(self.CenterPosition, arm.Weapon.MinRange));
                }

                if (!armaments.Any())
                {
                    continue;
                }

                //Evaluate whether we want to target this actor.
                var targetRange = (target.CenterPosition - self.CenterPosition).Length;
                foreach (var ati in validPriorities)
                {
                    if (chosenTarget == null || chosenTargetPriority < ati.Priority || (chosenTargetPriority == ati.Priority && targetRange < chosenTargetRange))
                    {
                        chosenTarget         = actor;
                        chosenTargetPriority = ati.Priority;
                        chosenTargetRange    = targetRange;
                    }
                }
            }

            return(chosenTarget);
        }