Ejemplo n.º 1
0
    /// <summary>
    /// Determines the target for this squad.
    /// </summary>
    /// <returns>AI state the controller should enter after determining the target.</returns>
    public override AIState DetermineMovePoint()
    {
        targetActor = null;

        MovePointBehavior movePoint = Actor.currentMovePoint;

        // Get a list of spaces that are within attack range (movement + range).
        CombatSquadBehavior combatSquad = Actor.GetComponent <CombatSquadBehavior>();

        if (combatSquad == null)
        {
            Debug.LogError(string.Format("AI Squad ({0}) does not have a CombatSquadBehavior!", Actor.transform.name));
            Actor.actorHasMovedThisTurn = true;

            return(AIState.PickingSquad);
        }

        int attackRange  = combatSquad.Squad.Range;
        int moveDistance = combatSquad.Squad.Speed;

        List <MovePointBehavior> pointsInRange = new List <MovePointBehavior>();

        movePoint.BuildGraph(attackRange + moveDistance, 0, grid, ref pointsInRange, true);

        // Find the closest actor in attack range.
        foreach (MovePointBehavior node in pointsInRange)
        {
            ActorBehavior actorOnNode = gameController.GetActorOnNode(node);

            if (actorOnNode == null || (actorOnNode.theSide != GameControllerBehaviour.UnitSide.player))
            {
                continue;
            }

            // If the distance to the target is less than the distance to the selected target, target it instead.
            float distance = Vector3.Distance(Actor.transform.position, actorOnNode.transform.position);
            if (distance < distanceToTarget)
            {
                targetActor      = actorOnNode;
                distanceToTarget = distance;
            }
        }

        // If a target was found, move toward it.
        if (targetActor != null)
        {
            // Build a path to the actor.
            List <MovePointBehavior> pathList = movePoint.FindPath(targetActor.currentMovePoint, (moveDistance + attackRange), grid, true);

            // Remove the target's move point from the grid.
            pathList.RemoveAt(pathList.Count - 1);

            // Determine the excess items in the path list.
            int excess = pathList.Count - moveDistance;

            if (excess > 0)
            {
                pathList.RemoveRange(pathList.Count - excess, excess);
            }

            if (pathList.Count > 0)
            {
                MovePointBehavior targetPoint = pathList[pathList.Count - 1];

                // Determine the fastest path to the target point.
                pathList = movePoint.FindPath(targetPoint, moveDistance, grid);

                if (pathList != null)
                {
                    Actor.pathList = pathList;
                    Actor.canMove  = true;

                    grid.ignoreList.Remove(movePoint);

                    grid.ignoreList.Add(targetPoint);

                    Actor.actorHasMovedThisTurn = true;

                    return(AIState.WaitingForMove);
                }
            }
            else
            {
                Actor.actorHasMovedThisTurn = true;

                return(AIState.WaitingForMove);
            }
        }
        else
        {
            targetActor      = null;
            distanceToTarget = float.PositiveInfinity;

            // No target was found, so determine the closest target to move towards.
            foreach (ActorBehavior playerSquad in gameController.playerTeam)
            {
                float distance = Vector3.Distance(Actor.transform.position, playerSquad.transform.position);
                if (distance < distanceToTarget)
                {
                    targetActor      = playerSquad;
                    distanceToTarget = distance;
                }
            }

            // Retrieve a list of all nodes within movement range.
            List <MovePointBehavior> nodesInRange = new List <MovePointBehavior>();
            movePoint.BuildGraph(moveDistance, 0, grid, ref nodesInRange);

            // Cast a ray to the target and retrieve the farthest one that is in our movement range.
            Ray ray = new Ray(Actor.transform.position, (targetActor.transform.position - Actor.transform.position).normalized);

            // Perform raycasting and store a list of all objects that have been selected.
            List <RaycastHit> hits = new List <RaycastHit>();
            hits.AddRange(Physics.RaycastAll(ray));

            // Iterate over the selection list to determine if the player has clicked on one of her squads.
            foreach (RaycastHit hitInfo in hits.OrderBy(l => l.distance).Reverse())
            {
                MovePointBehavior hitBehavior = hitInfo.transform.GetComponent <MovePointBehavior>();
                if (hitBehavior == null || !nodesInRange.Contains(hitBehavior))
                {
                    continue;
                }

                // Target node has been found! Find a path to it.
                List <MovePointBehavior> pathList = movePoint.FindPath(hitBehavior, moveDistance, grid);

                if (pathList != null)
                {
                    Actor.pathList = pathList;
                    Actor.canMove  = true;

                    grid.ignoreList.Remove(movePoint);
                    grid.ignoreList.Add(hitBehavior);

                    Actor.actorHasMovedThisTurn = true;

                    return(AIState.WaitingForMove);
                }
            }
        }

        Actor.actorHasMovedThisTurn = true;
        return(AIState.PickingSquad);
    }
Ejemplo n.º 2
0
    /// <summary>
    /// Waits for the left mouse button to be clicked, then performs a raycast to determine if the player has clicked
    /// on a valid movement point.
    /// </summary>
    /// <remarks>
    /// Transitions:
    ///     Player presses Escape key -> SelectingUnit
    ///     Player presses Space key -> SelectingTarget
    ///
    ///     Path to movement point cannot be found -> SelectingUnit
    ///     Player selects a valid movement point -> AwaitingMovement
    /// </remarks>
    private void updateSelectingMovement()
    {
        // Allow the player to press the Escape key to deselect their current unit.
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            deselectSquad();
            controlState = GridControlState.SelectingUnit;
            return;
        }

        // Allow the player to press the Space bar to skip the movement step.
        if (Input.GetKeyDown(KeyCode.Space))
        {
            selectedSquad.actorHasMovedThisTurn = true;
            grid.HideMovePoints();
            controlState = GridControlState.SelectingTarget;
            return;
        }

        // Wait for the left mouse button to be pressed.
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            // Perform raycasting and store a list of all objects that have been selected.
            List <RaycastHit> hits = new List <RaycastHit>();
            hits.AddRange(Physics.RaycastAll(ray));

            // Iterate over the selection list to determine if the player has clicked on a valid movementpoint.
            foreach (RaycastHit hitInfo in hits.OrderBy(l => l.distance))
            {
                // Retrieve the movepoint behavior from the hit target.
                MovePointBehavior movePoint = hitInfo.transform.GetComponent <MovePointBehavior>();
                if (movePoint == null || !movePoint.renderer.enabled)
                {
                    continue;
                }

                // Retrieve the combat squad behavior from the currently-selected squad.
                CombatSquadBehavior combatSquad = selectedSquad.GetComponent <CombatSquadBehavior>();
                if (combatSquad == null)
                {
                    Debug.LogError("Selected a unit with no combat squad attached!");
                }

                // Retrieve the maximum movement distance of the selected squad.
                int distance = (combatSquad == null ? 0 : combatSquad.Squad.Speed);

                // Mark the actor as having moved.
                selectedSquad.actorHasMovedThisTurn = true;

                // Retrieve a path from the starting point to the selected node.
                List <MovePointBehavior> pathList = startingPoint.FindPath(movePoint, distance, grid);
                if (pathList != null)
                {
                    selectedSquad.pathList = pathList;
                    selectedSquad.canMove  = true;

                    // Remove the squad's current movement point from the ignore list.
                    grid.ignoreList.Remove(startingPoint);

                    // Add the squad's target movement point to the ignore list.
                    grid.ignoreList.Add(movePoint);

                    // Hide visible nodes on the grid.
                    grid.HideMovePoints();

                    // Transition into the AwaitingMovement state.
                    controlState = GridControlState.AwaitingMovement;
                }
                else
                {
                    Debug.LogError("No path to target!");

                    // Deselect the current squad, but do not allow it to move again!
                    deselectSquad();

                    // Return to the SelectingUnit state.
                    controlState = GridControlState.SelectingUnit;
                }
            }
        }
    }