using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class TileManagment : MonoBehaviour { public const int BASIC_DIRECTIONS = 6; public static List levelTiles = new List(); public static List> charTiles = new List>(); public static List players = new List(); public static Action OnAnyTileCaptured; public List tileMaterials; public static float tileOffset; public static Vector3[] basicDirections; private void Awake() { InitCharTiles(); for (int i = 0; i < transform.childCount; i++) { var tile = transform.GetChild(i).GetComponent(); if (tile) { levelTiles.Add(tile); SetTileStartParams(tile); charTiles[(int)tile.tileOwnerIndex].Add(tile); } } tileOffset = Vector3.Distance(levelTiles[0].tilePosition, levelTiles[3].tilePosition); basicDirections = GetBasicDirections(BASIC_DIRECTIONS); //Debug.Log(players.Count); } private void InitCharTiles() { for (int i = 0; i < tileMaterials.Count; i++) { List charTileList = new List(); charTiles.Add(charTileList); //init empty lists for character tiles } } private void Start() { if (tileMaterials.Count == 0) { Debug.LogError("You need to set tile materials to TileManagment"); } } private void SetTileStartParams(TileInfo tile) { tile.tilePosition = tile.transform.position; tile.GetComponent().material = tileMaterials[(int)tile.tileOwnerIndex]; } public void ChangeTileOwner(TileInfo tile, TileOwner newOwner) { TileOwner oldOwner = tile.tileOwnerIndex; tile.tileOwnerIndex = newOwner; tile.GetComponent().material = tileMaterials[(int)tile.tileOwnerIndex]; charTiles[(int)newOwner].Add(tile); charTiles[(int)oldOwner].Remove(tile); CheckSurroundedTiles(levelTiles, newOwner, oldOwner); OnAnyTileCaptured?.Invoke(); } public static void AssignBuildingToTile(TileInfo tile, GameObject building) { tile.buildingOnTile = building; tile.canMove = false; tile.canBuildHere = false; } public static TileInfo GetTile(Vector3 position) { TileInfo resultTile = levelTiles[0]; foreach (TileInfo tile in levelTiles) { if (Vector3.Distance(position, tile.tilePosition) < Vector3.Distance(position, resultTile.tilePosition)) { resultTile = tile; } } if (Vector3.Distance(position, resultTile.tilePosition) > tileOffset / 2) { return null; } else { return resultTile; } } public static TileInfo GetTile(Vector3 currentTilePosition, Vector3 direction, float distance) { direction = direction.normalized; distance = distance - 0.1f; Vector3 tilePos = currentTilePosition + (direction * distance * tileOffset); return GetTile(tilePos); } public static TileInfo GetTile(TileOwner owner) { var ownerTiles = charTiles[(int)owner]; int randomTileIndex = UnityEngine.Random.Range(0, ownerTiles.Count - 1); TileInfo resultTile = ownerTiles[randomTileIndex]; while (!resultTile.canMove) { randomTileIndex = UnityEngine.Random.Range(0, ownerTiles.Count - 1); resultTile = ownerTiles[randomTileIndex]; } return resultTile; } public static List GetOtherTiles(TileInfo currentTile, TileOwner ownerIndex) { List otherTiles = new List(); //int notMyTiles = 0; foreach (Vector3 dir in basicDirections) { var tile = GetTile(currentTile.tilePosition + dir * tileOffset); if (tile) { if (tile.tileOwnerIndex != ownerIndex) { //notMyTiles++; otherTiles.Add(tile); } } } //Debug.Log("We have " + notMyTiles + " not my tiles around " + currentTile.name); return otherTiles; } public static Vector2 GetDirection(TileInfo currentTile, TileInfo adjacentTile) { if (!currentTile || !adjacentTile) return Vector2.zero; Vector3 dir3 = adjacentTile.tilePosition - currentTile.tilePosition; Vector2 dir2 = new Vector2(dir3.x, dir3.z); return dir2.normalized; } public static List GetAllAdjacentTiles(TileInfo currentTile) { List allTiles = new List(); foreach (Vector3 dir in basicDirections) { var tile = GetTile(currentTile.tilePosition + dir * tileOffset); if (tile) { allTiles.Add(tile); } } return allTiles; } public static List GetAllAdjacentTiles(TileInfo currentTile, TileOwner ownerIndex) { List allTiles = new List(); foreach (Vector3 dir in basicDirections) { var tile = GetTile(currentTile.tilePosition + dir * tileOffset); if (tile && ownerIndex == tile.tileOwnerIndex) { allTiles.Add(tile); } } return allTiles; } public static TileInfo GetRandomOtherTile(TileOwner owner) { int randomIndex = UnityEngine.Random.Range(0, levelTiles.Count - 1); while ((levelTiles[randomIndex].tileOwnerIndex == owner) && (levelTiles[randomIndex].canMove == false)) { randomIndex = UnityEngine.Random.Range(0, levelTiles.Count - 1); } TileInfo otherTile = levelTiles[randomIndex]; return otherTile; } public static TileInfo GetNearestOtherTile(TileInfo currentTile, TileOwner owner, float capRadius, Vector3 startPoint) { var neutralTiles = charTiles[(int)TileOwner.Neutral]; //Debug.Log("neutral tiles " + neutralTiles.Count); TileInfo closestTile = GetRandomOtherTile(owner); foreach (TileInfo tile in levelTiles) { if (tile.canMove && tile!=currentTile && tile.tileOwnerIndex!=owner) { float distOld = Vector3.Distance(startPoint, closestTile.tilePosition); float distNew = Vector3.Distance(startPoint, tile.tilePosition); float distToTileOld = Vector3.Distance(currentTile.tilePosition, closestTile.tilePosition); float distToTileNew = Vector3.Distance(currentTile.tilePosition, tile.tilePosition); //Debug.Log("new distance " + distNew); if ((distNew <= distOld) && (distNew < capRadius)) { if ((distToTileNew < distToTileOld)) { closestTile = tile; } } } } //float dist = Vector3.Distance(startPoint, closestTile.tilePosition); //Debug.Log(startPoint); //Debug.Log(closestTile); //Debug.Log("start point " + startPoint); return closestTile; } public static Vector3[] GetBasicDirections(int directionsAmount) { Vector3[] tempArr = new Vector3[directionsAmount]; float deltaAngle = 360 / directionsAmount; for (int i = 0; i < directionsAmount; i++) { tempArr[i] = Quaternion.AngleAxis(i * deltaAngle, Vector3.up) * Vector3.right; } //Debug.Log(tempArr); return tempArr; } public static void CheckSurroundedTiles(List tiles, TileOwner newOwner, TileOwner oldOwner) { List checkPlayers = new List(); checkPlayers.Add(oldOwner); checkPlayers.Add(newOwner); foreach (var player in checkPlayers) { foreach (TileInfo tile in levelTiles) { tile.checkedFor.Remove(newOwner); if (!tile.isLocked) { tile.easyCaptureFor.Remove(newOwner); } } } foreach (var player in checkPlayers) { foreach (TileInfo tile in levelTiles) { if (!tile.isBorderTile) { if ((!tile.checkedFor.Contains(player)) && (tile.tileOwnerIndex != player)) { CheckIfSurroundedByOwner(tiles, player, tile); } } } } } public static void CheckIfSurroundedByOwner(List tiles, TileOwner ownerIndex, TileInfo startTile) { List connectedTiles = new List(); var q = new Queue(tiles.Count); q.Enqueue(startTile); int iterations = 0; while (q.Count > 0) { var tile = q.Dequeue(); if (q.Count > tiles.Count) { throw new Exception("The algorithm is probably looping. Queue size: " + q.Count); } if (tile.isBorderTile) //we are in a wrong area { connectedTiles.Clear(); return; } if (connectedTiles.Contains(tile)) { continue; } connectedTiles.Add(tile); tile.checkedFor.Add(ownerIndex); //Debug.Log("Checked"); var adjacentTiles = GetOtherTiles(tile, ownerIndex); foreach (TileInfo newTile in adjacentTiles) { q.Enqueue(newTile); } iterations++; } foreach (TileInfo tile in connectedTiles) { if(!tile.isLocked) { tile.easyCaptureFor.Add(ownerIndex); } } } }