/// <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; }
/// <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; }
/// <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); }
/// <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; }
/// <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; }
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); }
/// <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; } }
/// <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; }
/// <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; }
/// <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; }
/// <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; } } } } }
/// <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; } } } }