Пример #1
0
        public IEnumerable <ICombatAction> ComputeActions(IBattle battle)
        {
            var map = battle.Map;

            if (_target != null)
            {
                // If the target has died since we last acted, give up on it and
                // try to find a new thing to do.
                if (!_target.IsAlive)
                {
                    _target = null;
                    return(ComputeActions(battle));
                }

                // If the target is in range of one of our weapons, use it
                var weapon = ChooseWeapon();
                if (IsInAttackRange(_self.Position, _target, weapon, map))
                {
                    var skill     = weapon.Range > 1 ? SkillType.Ranged : SkillType.Melee;
                    var forecast  = battle.ForecastFight(_self, _target, skill);
                    var finalized = battle.FinalizeFight(forecast);
                    return(new List <ICombatAction> {
                        new FightAction(finalized)
                    });
                }

                // If there's actually a path to the target, move there
                var path = map.FindPathToAdjacentTile(_self.Position, _target.Position, PathfindingUtils.GetCombatantTileFilter(_self));
                if (path != null)
                {
                    // Remove the first node because it's exactly where we're standing
                    path.RemoveAt(0);

                    // Move as far as we can toward the target, limited by our move range.
                    var moveRange     = _self.GetAttribute(Attribute.AttributeType.Move).Value;
                    var maxPathLength = Math.Min(moveRange, path.Count);
                    path = path.GetRange(0, maxPathLength);

                    var destination = path[path.Count - 1];
                    var moveAction  = new MoveAction(map, _self, destination, path);
                    if (!IsInAttackRange(destination, _target, weapon, map))
                    {
                        return(new List <ICombatAction> {
                            moveAction
                        });
                    }

                    var skill     = weapon.Range > 1 ? SkillType.Ranged : SkillType.Melee;
                    var forecast  = battle.ForecastFight(_self, _target, skill);
                    var finalized = battle.FinalizeFight(forecast);
                    return(new List <ICombatAction> {
                        moveAction,
                        new FightAction(finalized)
                    });
                }

                // There's no path to the target, so do nothing for now.
                return(new List <ICombatAction>());
            }

            // Find a new target and restart
            var potentials = map.FindSurroundingPoints(_self.Position, _aggroRadius)
                             .Select(pos => map.GetAtPosition(pos))
                             .Where(combatant => combatant != null && combatant.Army != _self.Army)
                             .ToList();

            // If there's nothing on the field to attack do nothing.
            if (!potentials.Any())
            {
                return(new List <ICombatAction>());
            }

            _target = potentials.OrderBy(target => {
                var path = map.FindPathToAdjacentTile(_self.Position, target.Position, PathfindingUtils.GetCombatantTileFilter(_self));
                return(path == null ? int.MaxValue : path.Count);
            })
                      .First();

            return(ComputeActions(battle));
        }