/// <summary>
    /// Initializes the combat system.
    /// </summary>
    /// <param name="offensiveSquad">GameObject for the squad performing the attack.</param>
    /// <param name="defensiveSquad">GameObject for the squad on defense.</param>
    public void BeginCombat(CombatSquadBehavior offensiveSquad, CombatSquadBehavior defensiveSquad)
    {
        if (offensiveSquad.Squad == null || defensiveSquad.Squad == null)
        {
            Debug.LogError("Combat was started with either the offensive or defense squad being null!");
            return;
        }

        GridBehavior.inCombat = true;
        InCombat = true;

        this.offensiveSquad = offensiveSquad;
        this.defensiveSquad = defensiveSquad;

        Debug.Log("Combat between " + offensiveSquad.ToString() + " and " + defensiveSquad.ToString() + " begin.");

        Debug.Log("Offensive size: " + offensiveSquad.Squad.Units.Count);
        Debug.Log("Defensive size: " + defensiveSquad.Squad.Units.Count);

        int unitCount = offensiveSquad.Squad.Units.Count + defensiveSquad.Squad.Units.Count;
        unitPrefabs = new List<NodeSkeletonBehavior>(unitCount);

        createUnits(offensiveSquad.Squad.Units, true, 0.0f);
        createUnits (defensiveSquad.Squad.Units, false, 1.0f);

        currentAttacker = CurrentAttacker.OffensiveFront;
    }
Esempio n. 2
0
    /// <summary>
    /// Initializes the combat system.
    /// </summary>
    /// <param name="offensiveSquad">GameObject for the squad performing the attack.</param>
    /// <param name="defensiveSquad">GameObject for the squad on defense.</param>
    /// <param name="grid">Grid behavior on which the combat is taking place.</param>
    public void BeginCombat(CombatSquadBehavior offensiveSquad, CombatSquadBehavior defensiveSquad, GridBehavior grid)
    {
        if (offensiveSquad.Squad == null || defensiveSquad.Squad == null)
        {
            Debug.LogError("Combat was started with either the offensive or defense squad being null!");
            return;
        }

        combatRange = (int)Mathf.Ceil(Vector3.Distance(offensiveSquad.transform.position, defensiveSquad.transform.position));

        this.grid = grid;

        GridBehavior.inCombat  = true;
        AudioBehavior.inCombat = true;

        this.offensiveSquad = offensiveSquad;
        this.defensiveSquad = defensiveSquad;

        int unitCount = offensiveSquad.Squad.Units.Count + defensiveSquad.Squad.Units.Count;

        unitPrefabs = new List <NodeSkeletonBehavior>(unitCount);

        createUnits(offensiveSquad.Squad.Units, true, 0.0f);
        createUnits(defensiveSquad.Squad.Units, false, 1.0f);

        currentAttacker = CurrentAttacker.OffensiveFront;
    }
Esempio n. 3
0
    /// <summary>
    /// Initiates combat between this squad and the target.
    /// </summary>
    /// <param name="target">Target.</param>
    protected void beginCombatWithTarget(ActorBehavior target)
    {
        // Capture the combat camera.
        CombatSystemBehavior combatSystem = GameObject.Find("Combat Camera").GetComponent <CombatSystemBehavior>();

        if (combatSystem == null)
        {
            Debug.LogError("Unable to find a valid combat system in scene!");
            return;
        }

        // Capture the offensive and defensive combat squads
        CombatSquadBehavior offensiveSquad = actor.GetComponent <CombatSquadBehavior>();

        if (!offensiveSquad)
        {
            Debug.LogError("Attempted to enter combat with an invalid offensive squad!");
            return;
        }

        CombatSquadBehavior defensiveSquad = target.GetComponent <CombatSquadBehavior>();

        if (!defensiveSquad)
        {
            Debug.LogError("Attempted to enter combat with an invalid defensive squad!");
            return;
        }

        // Hide the target movement points.
        grid.HideMovePoints();

        // Begin combat!
        combatSystem.BeginCombat(offensiveSquad, defensiveSquad, grid);
    }
Esempio n. 4
0
    /// <summary>
    /// Initializes the combat system.
    /// </summary>
    /// <param name="offensiveSquad">GameObject for the squad performing the attack.</param>
    /// <param name="defensiveSquad">GameObject for the squad on defense.</param>
    public void BeginCombat(CombatSquadBehavior offensiveSquad, CombatSquadBehavior defensiveSquad)
    {
        if (offensiveSquad.Squad == null || defensiveSquad.Squad == null)
        {
            Debug.LogError("Combat was started with either the offensive or defense squad being null!");
            return;
        }

        GridBehavior.inCombat = true;
        InCombat = true;

        this.offensiveSquad = offensiveSquad;
        this.defensiveSquad = defensiveSquad;

        Debug.Log("Combat between " + offensiveSquad.ToString() + " and " + defensiveSquad.ToString() + " begin.");

        Debug.Log("Offensive size: " + offensiveSquad.Squad.Units.Count);
        Debug.Log("Defensive size: " + defensiveSquad.Squad.Units.Count);

        int unitCount = offensiveSquad.Squad.Units.Count + defensiveSquad.Squad.Units.Count;
        unitPrefabs = new List<NodeSkeletonBehavior>(unitCount);

        foreach(UnitData data in offensiveSquad.Squad.Units)
        {
            float x = -1.0f + (0.33f * data.Position.Row);
            float y = 0.7f - (0.33f * data.Position.Column);
            float z = 0.9f - (0.05f * data.Position.Column);

            NodeSkeletonBehavior skele = (NodeSkeletonBehavior)Instantiate(unitSkeleton);

            skele.transform.parent = transform;
            skele.transform.localScale = (Vector3.one / 2.0f);
            skele.transform.localPosition = Vector3.zero;

            skele.transform.Translate(x, y, z);
        }

        foreach (UnitData data in defensiveSquad.Squad.Units)
        {
            float x = 1.0f - (0.33f * data.Position.Row);
            float y = 0.7f - (0.33f * data.Position.Column);
            float z = 0.9f - (0.05f * data.Position.Column);

            NodeSkeletonBehavior skele = (NodeSkeletonBehavior)Instantiate(unitSkeleton);

            skele.transform.parent = transform;
            skele.transform.localScale = new Vector3(-0.5f, 0.5f, 0.5f);
            skele.transform.localPosition = Vector3.zero;

            skele.transform.Translate(x, y, z);
        }

        currentAttacker = CurrentAttacker.OffensiveFront;
    }
Esempio n. 5
0
    /// <summary>
    /// Completes the combat,
    /// </summary>
    /// <param name="losingSquad">
    /// Reference to the squad that lost the combat.
    /// </param>
    private void endCombat(CombatSquadBehavior losingSquad)
    {
        MonoBehaviour[] objects = GetComponentsInChildren <MonoBehaviour>();
        for (int _i = (objects.Count() - 1); _i >= 0; _i--)
        {
            if (objects[_i].name == "__UNITBASE__")
            {
                DestroyImmediate(objects[_i].gameObject);
            }
        }

        if (losingSquad != null)
        {
            ActorBehavior actor = losingSquad.GetComponent <ActorBehavior>();
            if (actor != null && grid.ignoreList.Contains(actor.currentMovePoint))
            {
                grid.ignoreList.Remove(actor.currentMovePoint);
            }

            // Retrieve the game controller to determine which side the losing team was on.
            GameControllerBehaviour gameController = grid.GetComponent <GameControllerBehaviour>();
            if (actor.theSide == GameControllerBehaviour.UnitSide.player)
            {
                gameController.playerTeamTotal--;
            }
            else
            {
                gameController.enemyTeamTotal--;
            }

            Destroy(losingSquad.gameObject);
        }

        foreach (NodeSkeletonBehavior node in unitPrefabs)
        {
            DestroyImmediate(node.gameObject);
        }

        this.offensiveSquad = null;
        this.defensiveSquad = null;

        GridBehavior.preCombat       = false;
        HonorSystemBehavior.inCombat = true;
        GridBehavior.inCombat        = false;
        AudioBehavior.inCombat       = false;
    }
Esempio n. 6
0
    public override AIState DetermineCombatTarget()
    {
        targetActor      = null;
        distanceToTarget = float.PositiveInfinity;

        MovePointBehavior movePoint = Actor.currentMovePoint;

        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;

        // Retrieve a list of nodes in range.
        List <MovePointBehavior> graph = new List <MovePointBehavior>();

        movePoint.BuildGraph(attackRange, 0, grid, ref graph, true);

        // Iterate over the nodes to determine if any node has an enemy.
        foreach (MovePointBehavior node in graph)
        {
            ActorBehavior actorOnNode = gameController.GetActorOnNode(node);

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

            beginCombatWithTarget(actorOnNode);

            return(AIState.WaitingForCombat);
        }

        return(AIState.PickingSquad);
    }
Esempio n. 7
0
    /// <summary>
    /// Enables the renderer on any nodes the unit can move to.
    /// </summary>
    /// <param name="actor">Actor associated with this movement attempt.</param>
    /// <param name="grid">Grid associated with the movement.</param>
    /// <param name="range">Maximum distance (in grid squares) to highlight.</param>
    public void HighlightValidNodes(ActorBehavior actor, GridBehavior grid, int range = -1)
    {
        int depth = 0;

        if (actor.currentMovePoint == null)
        {
            Debug.LogError("Current move point is null!");
            return;
        }

        //int maxDistance = 0;
        CombatSquadBehavior csb = actor.GetComponent <CombatSquadBehavior>();

        if (csb == null)
        {
            Debug.LogWarning("Attempting to move a unit that does not have a squad associated!");
        }

        bool skipIgnoreList = false;

        if (range == -1)
        {
            range = (csb == null ? 1 : csb.Squad.Speed);
        }
        else
        {
            skipIgnoreList = true;
        }

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

        actor.currentMovePoint.BuildGraph(range, depth, grid, ref moveGraph, skipIgnoreList);
        moveGraph.RemoveAt(0);

        foreach (MovePointBehavior node in moveGraph)
        {
            node.renderer.enabled = true;
        }
    }
Esempio n. 8
0
    /// <summary>
    /// Completes the combat, 
    /// </summary>
    /// <param name="losingSquad">
    /// Reference to the squad that lost the combat.
    /// </param>
    private void endCombat(CombatSquadBehavior losingSquad)
    {
        Debug.Log("Combat between " + offensiveSquad.ToString() + " and " + defensiveSquad.ToString() + " end.");

        if(losingSquad != null)
            Destroy(losingSquad.gameObject);

        foreach (NodeSkeletonBehavior node in unitPrefabs)
            DestroyImmediate(node.gameObject);

        this.offensiveSquad = null;
        this.defensiveSquad = null;

        GridBehavior.preCombat = false;
        GridBehavior.inCombat = false;
        InCombat = false;
    }
Esempio n. 9
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);
    }
	/// <summary>
	/// Completes the combat, 
	/// </summary>
	/// <param name="losingSquad">
	/// Reference to the squad that lost the combat.
	/// </param>
	private void endCombat(CombatSquadBehavior losingSquad)
	{
		MonoBehaviour[] objects = GetComponentsInChildren<MonoBehaviour>();
		for(int _i = (objects.Count() - 1); _i >= 0; _i--)
		{
			if(objects[_i].name == "__UNITBASE__")
				DestroyImmediate(objects[_i].gameObject);
		}
		
		if(losingSquad != null)
		{
			ActorBehavior actor = losingSquad.GetComponent<ActorBehavior>();
			if (actor != null && grid.ignoreList.Contains(actor.currentMovePoint))
				grid.ignoreList.Remove(actor.currentMovePoint);

			// Retrieve the game controller to determine which side the losing team was on.
			GameControllerBehaviour gameController = grid.GetComponent<GameControllerBehaviour>();
			if(actor.theSide == GameControllerBehaviour.UnitSide.player)
				gameController.playerTeamTotal--;
			else
				gameController.enemyTeamTotal--;

			Destroy(losingSquad.gameObject);
		}

		foreach (NodeSkeletonBehavior node in unitPrefabs)
			DestroyImmediate(node.gameObject);

		this.offensiveSquad = null;
		this.defensiveSquad = null;

		GridBehavior.preCombat = false;
        HonorSystemBehavior.inCombat = true;
		GridBehavior.inCombat = false;
        AudioBehavior.inCombat = false;
	}
	/// <summary>
	/// Initializes the combat system.
	/// </summary>
	/// <param name="offensiveSquad">GameObject for the squad performing the attack.</param>
	/// <param name="defensiveSquad">GameObject for the squad on defense.</param>
	/// <param name="grid">Grid behavior on which the combat is taking place.</param>
	public void BeginCombat(CombatSquadBehavior offensiveSquad, CombatSquadBehavior defensiveSquad, GridBehavior grid)
	{
		if (offensiveSquad.Squad == null || defensiveSquad.Squad == null)
		{
			Debug.LogError("Combat was started with either the offensive or defense squad being null!");
			return;
		}

		combatRange = (int)Mathf.Ceil(Vector3.Distance(offensiveSquad.transform.position, defensiveSquad.transform.position));

		this.grid = grid;

		GridBehavior.inCombat = true;
        AudioBehavior.inCombat = true;

		this.offensiveSquad = offensiveSquad;
		this.defensiveSquad = defensiveSquad;

		int unitCount = offensiveSquad.Squad.Units.Count + defensiveSquad.Squad.Units.Count;
		unitPrefabs = new List<NodeSkeletonBehavior>(unitCount);

		createUnits (offensiveSquad.Squad.Units, true, 0.0f);
		createUnits (defensiveSquad.Squad.Units, false, 1.0f);

		currentAttacker = CurrentAttacker.OffensiveFront;
	}
Esempio n. 12
0
    /// <summary>
    /// Completes the combat, 
    /// </summary>
    /// <param name="losingSquad">
    /// Reference to the squad that lost the combat.
    /// </param>
    private void endCombat(CombatSquadBehavior losingSquad)
    {
        Debug.Log("Combat between " + offensiveSquad.ToString() + " and " + defensiveSquad.ToString() + " end.");

        //foreach(GameObject obj in transform.GetComponentsInChildren<MonoBehaviour>())
        MonoBehaviour[] objects = GetComponentsInChildren<MonoBehaviour>();
        for(int _i = (objects.Count() - 1); _i >= 0; _i--)
        {
            if(objects[_i].name == "__UNITBASE__")
                DestroyImmediate(objects[_i].gameObject);
        }

        if(losingSquad != null)
            Destroy(losingSquad.gameObject);

        foreach (NodeSkeletonBehavior node in unitPrefabs)
            DestroyImmediate(node.gameObject);

        this.offensiveSquad = null;
        this.defensiveSquad = null;

        GridBehavior.preCombat = false;
        GridBehavior.inCombat = false;
        InCombat = false;
    }
Esempio n. 13
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 enemy unit.
    /// </summary>
    /// <remarks>
    /// Transitions:
    ///     Player presses Escape key -> SelectingMovement
    ///     Player presses Space key -> SelectingUnit or AwaitingEnemy
    /// </remarks>
    private void updateSelectingTarget()
    {
        // Allow the player to press the escape key to undo their movement.
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            // Unflag the actor as having moved.
            selectedSquad.actorHasMovedThisTurn = false;

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

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

            // Forcibly move the actor to the starting point.
            selectedSquad.currentMovePoint   = startingPoint;
            selectedSquad.transform.position = startingPoint.transform.position;

            // Hide currently-visible movement nodes.
            grid.HideMovePoints();

            // Re-highlight valid movement nodes.
            startingPoint.HighlightValidNodes(selectedSquad, grid);

            // Release the current list of valid targets.
            validTargets = null;

            // Return to the SelectingMovement state.
            controlState = GridControlState.SelectingMovement;

            return;
        }

        // Allow the player to press the space bar to skip attacking.
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Hide the target movement points.
            grid.HideMovePoints();

            // Decrement the number of moves left for this turn.
            controller.leftToMoveThis--;

            // Switch to the SelectingUnits state if the player still has moves left, otherwise end the turn.
            controlState = (controller.leftToMoveThis > 0 ?
                            GridControlState.SelectingUnit :
                            GridControlState.AwaitingEnemy);

            // Deselect the current squad.
            deselectSquad();

            return;
        }

        if (validTargets == null)
        {
            // Highlight grid points in attack range.
            CombatSquadBehavior combatSquad = selectedSquad.GetComponent <CombatSquadBehavior>();
            if (combatSquad != null)
            {
                int depth = 0;
                int range = combatSquad.Squad.Range;

                selectedSquad.currentMovePoint.HighlightValidNodes(selectedSquad, grid, range);

                // Store a list of valid targets.
                validTargets = new List <MovePointBehavior>();
                selectedSquad.currentMovePoint.BuildGraph(range, depth, grid, ref validTargets, true);
            }
        }

        // 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))
            {
                // Capture the actor behavior on the hit object.
                ActorBehavior actor = hitInfo.transform.GetComponent <ActorBehavior>();
                if (actor == null)
                {
                    continue;
                }

                // Ensure that the unit has not moved and does not belong to the player.
                if (actor.theSide == enemySide)
                {
                    // Ensure the the enemy's move point is in the list of valid target move points.
                    if (validTargets.Contains(actor.currentMovePoint))
                    {
                        // Capture the combat camera.
                        CombatSystemBehavior combatSystem = GameObject.Find("Combat Camera").GetComponent <CombatSystemBehavior>();
                        if (combatSystem == null)
                        {
                            Debug.LogError("Unable to find a valid combat system in scene!");
                            return;
                        }

                        // Capture the offensive and defensive combat squads
                        CombatSquadBehavior offensiveSquad = selectedSquad.GetComponent <CombatSquadBehavior>();

                        if (!offensiveSquad)
                        {
                            Debug.LogError("Attempted to enter combat with an invalid offensive squad!");
                            return;
                        }

                        CombatSquadBehavior defensiveSquad = actor.GetComponent <CombatSquadBehavior>();

                        if (!defensiveSquad)
                        {
                            Debug.LogError("Attempted to enter combat with an invalid defensive squad!");
                            return;
                        }

                        // Hide the target movement points.
                        grid.HideMovePoints();

                        // Begin combat!
                        combatSystem.BeginCombat(offensiveSquad, defensiveSquad, grid);

                        // Transition to Awaiting Combat state.
                        controlState = GridControlState.AwaitingCombat;
                    }
                }
            }
        }
    }
Esempio n. 14
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;
                }
            }
        }
    }