Esempio n. 1
0
    private Vector2Int?MovementTowards(AITarget target)
    {
        movementCalculator.CalculateMovementUnrestricted(AttachedUnit.GetCoordinates());
        List <Vector2Int> path = movementCalculator.GetPath(movementCalculator.GetNearestAvailableNeighbor(target.coordinates));

        if (path != null)
        {
            return(path[AttachedUnit.movementRange]);
        }

        return(null);
    }
Esempio n. 2
0
    // Parses all possible targets and tracks the most optimal target
    // Use FoundTarget to get the AI's target, and FoundMovePos to get the position the AI should move to
    // Both of these may be null
    public void FindTarget()
    {
        movementCalculator.CalculateMovement(AttachedUnit.GetCoordinates(), AttachedUnit.movementRange);
        List <AITarget> targets = GetPossibleTargets();

        FoundTarget  = null;
        FoundMovePos = null;

        // No targets, no action
        if (targets.Count == 0)
        {
            return;
        }

        // Check all possible targets from the most valuable to the least valuable
        // Take the first target in range
        foreach (var target in targets)
        {
            Vector2Int?movePos = null;
            if (IsTargetReachable(target, ref movePos))
            {
                FoundTarget  = target.coordinates;
                FoundMovePos = movePos;
                return;
            }
        }

        // If no targets were in range, find nearest target and start moving towards it
        AITarget closest = new AITarget();

        closest.distance = float.MaxValue;
        foreach (var target in targets)
        {
            if (target.distance < closest.distance)
            {
                closest = target;
            }
        }

        // Find the tile to move to
        FoundMovePos = MovementTowards(closest);
    }
Esempio n. 3
0
    // Returns true if this target is within attack range
    // If this target requires movement before it can be in range, movePos will assume the destination coordinates.
    // If no movement is required, movePos will not be altered.
    private bool IsTargetReachable(AITarget target, ref Vector2Int?movePos)
    {
        float distToTarget = Vector2Int.Distance(target.coordinates, AttachedUnit.GetCoordinates());

        // Check if target is in range without moving
        if (distToTarget <= AttachedUnit.AttackRange)
        {
            return(true);
        }

        // Check if target can be in range after moving
        if (distToTarget > AttachedUnit.AttackRange + AttachedUnit.movementRange)
        {
            return(false);
        }

        // Find tile within movement range that is also in attack range of the desired target
        // Prioritize the least amount of movement
        int        distance    = int.MaxValue;
        Vector2Int?coordinates = null;

        List <Vector2Int> reachableTiles = movementCalculator.GetReachableTiles();

        foreach (var tile in reachableTiles)
        {
            if (Vector2Int.Distance(target.coordinates, tile) <= AttachedUnit.AttackRange)
            {
                int thisDist = movementCalculator.GetDistance(tile);
                if (thisDist < distance)
                {
                    distance    = thisDist;
                    coordinates = tile;
                }
            }
        }

        movePos = coordinates;
        return(coordinates != null);
    }
Esempio n. 4
0
    // Returns a list of possible target points for the Unit, sorted by value (descending order) and distance (ascending order)
    private List <AITarget> GetPossibleTargets()
    {
        List <AITarget> targets = new List <AITarget>();

        switch (AttachedSkill.targetType)
        {
        // Only units can be targeted, thus check the value of targeting all valid Units
        case Skill.TargetType.Unit:
        {
            List <Unit> allUnits = Grid.ActiveGrid.GetAllUnits();
            foreach (var unit in allUnits)
            {
                // Filter out only valid targets
                if (AttachedSkill.IsAffected(AttachedUnit, unit))
                {
                    // Check all units that will be affected from targeting this unit
                    AITarget target;
                    target.coordinates = unit.GetCoordinates();
                    target.value       = GetValueFor(AttachedSkill.GetAffectedUnits(AttachedUnit, target.coordinates, true));
                    target.distance    = Vector2Int.Distance(AttachedUnit.GetCoordinates(), target.coordinates);

                    // If there is value to this target, add it to the list
                    if (target.value > 0)
                    {
                        targets.Add(target);
                    }
                }
            }
        }
        break;

        // Any tile can be targeted, thus check the values of all tiles
        case Skill.TargetType.Tile:
        {
            for (int x = 0; x < Grid.ActiveGrid.gridSize.x; x++)
            {
                for (int y = 0; y < Grid.ActiveGrid.gridSize.y; y++)
                {
                    // Check all units that will be affected from targeting this tile
                    AITarget target;
                    target.coordinates = new Vector2Int(x, y);
                    target.value       = GetValueFor(AttachedSkill.GetAffectedUnits(AttachedUnit, target.coordinates, true));
                    target.distance    = Vector2Int.Distance(AttachedUnit.GetCoordinates(), target.coordinates);

                    // If there is value to this target, add it to the list
                    if (target.value > 0)
                    {
                        targets.Add(target);
                    }
                }
            }
        }
        break;
        }

        targets.Sort((x, y) =>
        {
            int i = y.value.CompareTo(x.value);
            if (i == 0)
            {
                return(x.distance.CompareTo(y.distance));
            }
            return(i);
        });
        return(targets);
    }