public override IEnumerator FindPath(Vector2 start, Vector2 target, bool debug) { Node startNode = grid.GetNodeFromWorldPostion(start); Node targetNode = grid.GetNodeFromWorldPostion(target); path = ReconstructPath(startNode, debug); List <Node> openSet = new List <Node>(); List <Node> closedSet = new List <Node>(); startNode.gCost = 0; startNode.fCost = grid.GetDistance(startNode, targetNode); openSet.Add(startNode); if (debug) { tiles[startNode.x, startNode.y].SetDebugColor(Color.cyan); } yield return(new WaitForSeconds(thinkTimeStep)); while (openSet.Count > 0) { Node currentNode = openSet[0]; for (int i = 1; i < openSet.Count; i++) { if (currentNode.fCost > openSet[i].fCost) { currentNode = openSet[i]; } } if (currentNode == targetNode) { path = ReconstructPath(currentNode, debug); break; } openSet.Remove(currentNode); closedSet.Add(currentNode); if (debug) { tiles[currentNode.x, currentNode.y].SetDebugColor(Color.yellow); } yield return(new WaitForSeconds(thinkTimeStep)); foreach (Node neighbor in grid.GetNodeNeighbors4(currentNode)) { if (closedSet.Contains(neighbor)) { continue; } float newNeighborGCost = currentNode.gCost + (grid.GetDistance(currentNode, neighbor) * (currentNode.travelCost + neighbor.travelCost) / 2); if (newNeighborGCost < neighbor.gCost || !openSet.Contains(neighbor)) { neighbor.previousNode = currentNode; neighbor.gCost = newNeighborGCost; neighbor.fCost = newNeighborGCost + grid.GetDistance(neighbor, targetNode); if (!openSet.Contains(neighbor)) { openSet.Add(neighbor); if (debug) { tiles[neighbor.x, neighbor.y].SetDebugColor(Color.cyan); } yield return(new WaitForSeconds(thinkTimeStep)); } } } } yield return(null); }
//this formation makes a number of attacks against the tagret formation, possibly damaging it public void MeleeAttack(Formation target) { if (!(pathGrid.GetDistance(transform.position, target.transform.position) <= meleeWeapon.GetRange())) { Debug.Log("Target out of range"); return; } else if (hasAttacked) { Debug.Log("This Formation has already attacked"); return; } //the number of attacks this formation will make int numAttackers; int targetRemainingFrontage = Mathf.Min(target.frontage, target.currentTroops); //if the target is wider or equal width, make attacks equal to frontage if (targetRemainingFrontage >= frontage) { numAttackers = frontage; } //if this formation is wider by more than 1, make attacks equal to frontage + 4 else if (frontage > targetRemainingFrontage + 1) { numAttackers = (targetRemainingFrontage + 2); } //if this formation is wider by 1, make attacks equal to frontage + 2 else { numAttackers = targetRemainingFrontage + 1; } //multiply the number of melee attackers by the number of ranks that can reach numAttackers *= meleeWeapon.GetReach(); //if there are more attacks than troops remaining, reduce number of attacks to troops remaining if (numAttackers > currentTroops) { numAttackers = currentTroops; } //calculate what kind of facing is being attacked, front, front-flank, rear, or rear-flank int facingType = Mathf.Min(Mathf.Abs(target.facing - facing), 6 - Mathf.Abs(target.facing - facing)); //if facingType = 0, their facing is the same, so it's a rear attack //if facingType = 1, it's a rear-flank //if facingType = 2, it's a front flank //if facingType = 3, they are directly opposite each other so it's a frontal attack int bonusAttack = 0; //apply bonuses based on facing //flanking attacks on a hex grid result in less troops being able to attack, but gaining a bonus to hit if (facingType == 2) //front-flank { numAttackers = (int)Mathf.Round(0.75f * numAttackers); bonusAttack = 2; Debug.Log("Front-Flank Attack"); } else if (facingType == 1) //rear-flank { numAttackers = (int)Mathf.Round(0.75f * numAttackers); bonusAttack = 4; Debug.Log("Rear-Flank Attack"); } else if (facingType == 0) //rear { bonusAttack = 6; Debug.Log("Rear Attack"); } //for each attack, attack, check if a character has died and apply the resulting effects for (int attacks = 0; attacks < numAttackers; attacks++) { troop.Attack(target.troop, meleeWeapon, bonusAttack); //if the target troop dies, reset their health and increment the casualties if (!target.troop.IsAlive()) { target.troop.ResetHealth(); target.casualties++; } } SetHasAttacked(true); }