示例#1
0
 protected virtual void DoAttack(Actor self, AttackFrontal attack, IEnumerable <Armament> armaments)
 {
     if (!attack.IsTraitPaused)
     {
         foreach (var a in armaments)
         {
             a.CheckFire(self, facing, target);
         }
     }
 }
示例#2
0
 protected override void DoAttack(Actor self, AttackFrontal attack, IEnumerable <Armament> armaments)
 {
     attack.DoAttack(self, target);
 }
示例#3
0
        protected virtual AttackStatus TickAttack(Actor self, AttackFrontal attack)
        {
            if (!target.IsValidFor(self))
            {
                return(AttackStatus.UnableToAttack);
            }

            if (attack.Info.AttackRequiresEnteringCell && !positionable.CanEnterCell(target.Actor.Location, null, false))
            {
                return(AttackStatus.UnableToAttack);
            }

            if (!attack.Info.TargetFrozenActors && !forceAttack && target.Type == TargetType.FrozenActor)
            {
                // Try to move within range, drop the target otherwise
                if (move == null)
                {
                    return(AttackStatus.UnableToAttack);
                }

                var rs = revealsShroud
                         .Where(Exts.IsTraitEnabled)
                         .MaxByOrDefault(s => s.Range);

                // Default to 2 cells if there are no active traits
                var sightRange = rs != null ? rs.Range : WDist.FromCells(2);

                attackStatus |= AttackStatus.NeedsToMove;
                QueueChild(self, move.MoveWithinRange(target, sightRange, target.CenterPosition, Color.Red), true);
                return(AttackStatus.NeedsToMove);
            }

            // Drop the target once none of the weapons are effective against it
            var armaments = attack.ChooseArmamentsForTarget(target, forceAttack).ToList();

            if (armaments.Count == 0)
            {
                return(AttackStatus.UnableToAttack);
            }

            // Update ranges
            minRange = armaments.Max(a => a.Weapon.MinRange);
            maxRange = armaments.Min(a => a.MaxRange());

            var pos    = self.CenterPosition;
            var mobile = move as Mobile;

            if (!target.IsInRange(pos, maxRange) ||
                (minRange.Length != 0 && target.IsInRange(pos, minRange)) ||
                (mobile != null && !mobile.CanInteractWithGroundLayer(self)))
            {
                // Try to move within range, drop the target otherwise
                if (move == null)
                {
                    return(AttackStatus.UnableToAttack);
                }

                attackStatus |= AttackStatus.NeedsToMove;
                var checkTarget = useLastVisibleTarget ? lastVisibleTarget : target;
                QueueChild(self, move.MoveWithinRange(target, minRange, maxRange, checkTarget.CenterPosition, Color.Red), true);
                return(AttackStatus.NeedsToMove);
            }

            if (!attack.TargetInFiringArc(self, target, attack.Info.FacingTolerance))
            {
                var desiredFacing = (attack.GetTargetPosition(pos, target) - pos).Yaw.Facing;
                attackStatus |= AttackStatus.NeedsToTurn;
                QueueChild(self, new Turn(self, desiredFacing), true);
                return(AttackStatus.NeedsToTurn);
            }

            attackStatus |= AttackStatus.Attacking;
            DoAttack(self, attack, armaments);

            return(AttackStatus.Attacking);
        }