// Checks for each unit to see if it could potentially be reached, and if so adds to the lists. private void ScanForUnits() { //@todo Unit scan doesn't consider "faction" yet, in case you want to use it for player-friendly units as well Unit currentUnit = unitManager.currentTurnUnit; int maxDistance = currentUnit.unitStats.movementDistance + 6; //@todo Replace the +6 with the longest-range ability the unit has // Getting Friendly units //@todo only do so if the current AI unit has beneficial spells that can be cast on allies; do so during the foreach (Unit attemptUnit in unitManager.tempEnemyUnitList) { if (currentUnit.Equals(attemptUnit)) // If the unit is itself { self = new OtherUnit(attemptUnit, 0, null, true); friendlyUnits.Add(self); continue; } int unitDistance = LandTileMap.instance.GetTileDistance(currentUnit.currentTile, attemptUnit.currentTile); if (maxDistance >= unitDistance) { OtherUnit otherUnit; LandTile [] pathTowards = LandTileMap.instance.RequestPath(currentUnit.currentTile, attemptUnit.currentTile, currentUnit.unitStats.canMoveDiagonally, false); if (pathTowards.Length != 0 && pathTowards.Length <= currentUnit.unitStats.movementDistance) { otherUnit = new OtherUnit(attemptUnit, unitDistance, pathTowards, true); } else // No path or out of our movement range means there's no walkable path { otherUnit = new OtherUnit(attemptUnit, unitDistance, pathTowards); } friendlyUnits.Add(otherUnit); } } // Getting Hostile units foreach (Unit attemptUnit in unitManager.tempFriendlyUnitList) { int unitDistance = LandTileMap.instance.GetTileDistance(currentUnit.currentTile, attemptUnit.currentTile); if (maxDistance >= unitDistance) { OtherUnit otherUnit; LandTile [] pathTowards = LandTileMap.instance.RequestPath(currentUnit.currentTile, attemptUnit.currentTile, currentUnit.unitStats.canMoveDiagonally, false); if (pathTowards.Length != 0 && pathTowards.Length <= currentUnit.unitStats.movementDistance) { otherUnit = new OtherUnit(attemptUnit, unitDistance, pathTowards, true); } else // No path or out of our movement range means there's no walkable path { otherUnit = new OtherUnit(attemptUnit, unitDistance, pathTowards); } enemyUnits.Add(otherUnit); } } }
public AIAttackAction(OtherUnit targetUnit, int score, LandTile tileToMoveTo = null) { this.targetUnit = targetUnit; this.score = score; if (tileToMoveTo == null) { return; } this.tileToMoveTo = tileToMoveTo; requiresMovement = true; }
public AIAbilityAction(OtherUnit targetUnit, Ability abilityToUse, int score, LandTile tileToMoveTo = null) { this.targetUnit = targetUnit; this.abilityToUse = abilityToUse; this.score = score; if (tileToMoveTo == null) { return; } this.tileToMoveTo = tileToMoveTo; requiresMovement = true; }
private LandTile FindPointToMoveTo() { //@todo Does adding a "is being threatened" tag to tiles improve this performance-wise? //@todo Has the option of returning its current position Unit currentUnit = unitManager.currentTurnUnit; LandTile [] possibleTiles = LandTileMap.instance.RequestRange(currentUnit.transform.position, currentUnit.unitStats.movementDistance, currentUnit.unitStats.canMoveDiagonally, true, false, false); if (possibleTiles.Length == 0) { return(null); } LandTile tileToMoveTo = null; if (enemyUnits.Count != 0) { // Am I ranged/wizard? Move away from closest target //@todo Find way of recognizing spellcasters/healers etc. Could be class-based, but not preferable. If Intelligence>Attack? if (currentUnit.unitStats.attackRange > 1 || currentUnit.unitStats.intelligence > currentUnit.unitStats.attackPower) { int [] tileScores = new int [possibleTiles.Length]; int lowestValue = 9999; int lowestIndex = 0; for (int i = 0; i < possibleTiles.Length; i++) // Calculates the 'safest' spot by adding up the tile's distance to each enemy and picking the lowest { foreach (OtherUnit enemy in enemyUnits) //@todo Better ways to do this? { tileScores [i] += LandTileMap.instance.GetTileDistance(currentUnit.currentTile, enemy.unit.currentTile); if (tileScores [i] < lowestValue) { lowestValue = tileScores [i]; lowestIndex = i; } } } return(tileToMoveTo = possibleTiles [lowestIndex]); } int lowestHealth = 9999; OtherUnit lowestHealthEnemy = null; // Scan for lowest health enemy, move towards that one foreach (OtherUnit enemy in enemyUnits) { if (enemy.canReach && enemy.unit.unitStats.currentHealth < lowestHealth) { LandTile testingTile = enemy.pathToTarget [Mathf.Clamp(enemy.pathToTarget.Length - 2, 0, enemy.pathToTarget.Length - 1)]; if ((possibleTiles.Contains <LandTile> (testingTile) || currentUnit.currentTile == testingTile) && testingTile.unitOnTile == null) { lowestHealthEnemy = enemy; lowestHealth = enemy.unit.unitStats.currentHealth; } } } if (lowestHealthEnemy != null) { if (LandTileMap.instance.GetTileDistance(currentUnit.currentTile, lowestHealthEnemy.unit.currentTile) < currentUnit.unitStats.attackRange) { return(null); // if we're already in range of the lowest health unit; we don't have to move. } else { return(tileToMoveTo = lowestHealthEnemy.pathToTarget [Mathf.Clamp(lowestHealthEnemy.pathToTarget.Length - 2, 0, lowestHealthEnemy.pathToTarget.Length)]); } } // If there were no possible enemies to path to, move in the general direction of one //@todo doesn't consider movement costs yet if (tileToMoveTo == null) { for (int i = 0; i < enemyUnits.Count - 1; i++) { int random = Random.Range(i, enemyUnits.Count); if (enemyUnits [random].pathToTarget != null && enemyUnits[random].pathToTarget.Length != 0) { tileToMoveTo = enemyUnits [random].pathToTarget [Mathf.Clamp(currentUnit.unitStats.movementDistance, 0, enemyUnits [random].pathToTarget.Length - 1)]; break; } } } } // If all else fails, pick a random tile within movement range if (tileToMoveTo == null) { tileToMoveTo = possibleTiles [Random.Range(0, possibleTiles.Length - 1)]; } return(tileToMoveTo); }