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 Action OnInitialized; public static Action OnAnyTileCaptured; public static List tileMaterialsStatic; public static float tileOffset; public static Vector3[] basicDirections; [SerializeField] private List _tileMaterials; [SerializeField] private Transform _tileParent; private void Awake() { //OnInitialized = null; //OnAnyTileCaptured = null; InitTileManager(); Debug.Log("tile offset is " + tileOffset + " points"); } private void InitTileManager() { levelTiles.Clear(); SetStaticTileMaterials(); InitCharacterTiles(); for (int i = 0; i < _tileParent.childCount; i++) { var tile = _tileParent.GetChild(i).GetComponent(); if (tile) { levelTiles.Add(tile); SetTileStartParams(tile); charTiles[(int)tile.tileOwnerIndex].Add(tile); } } basicDirections = GetBasicDirections(BASIC_DIRECTIONS); tileOffset = GetTileOffset(levelTiles); //Debug.Log("tile offset is "+ tileOffset); OnInitialized?.Invoke(); } private float GetTileOffset(List tiles) { TileInfo firstTile = tiles[0]; TileInfo secondTile = tiles[1]; return Vector3.Distance(firstTile.tilePosition, secondTile.tilePosition); } private void SetStaticTileMaterials() { tileMaterialsStatic = new List(); foreach (var mat in _tileMaterials) { tileMaterialsStatic.Add(mat); } } private void InitCharacterTiles() { if (charTiles.Count > 0) { charTiles.Clear(); } for (int i = 0; i < tileMaterialsStatic.Count; i++) { List charTileList = new List(); charTiles.Add(charTileList); //init empty lists for character tiles } } private void SetTileStartParams(TileInfo tile) { tile.tilePosition = tile.transform.position; tile.GetComponent().material = tileMaterialsStatic[(int)tile.tileOwnerIndex]; } public static void ChangeTileOwner(TileInfo tile, PlayerState newPlayer) { tile.easyCaptureForAll = false; TileOwner newOwner = newPlayer.ownerIndex; TileOwner oldOwner = tile.tileOwnerIndex; tile.tileOwnerIndex = newOwner; tile.GetComponent().material = tileMaterialsStatic[(int)tile.tileOwnerIndex]; charTiles[(int)newOwner].Add(tile); charTiles[(int)oldOwner].Remove(tile); OnAnyTileCaptured?.Invoke(newPlayer); CheckSurroundedTiles(levelTiles, newOwner, oldOwner); SetAllPLayersTilesCapState(GameManager.activePlayers); } public static void AssignBuildingToTile(TileInfo tile, GameObject building) { tile.buildingOnTile = building; tile.canMove = false; tile.canBuildHere = false; } public static void ReleaseTile(TileInfo tile) { tile.buildingOnTile = null; tile.canMove = true; tile.canBuildHere = true; } public static void SetTileAvailable(TileInfo tile) { tile.canMove = true; tile.canBuildHere = true; } 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 TileInfo GetRandomOtherTile(TileOwner owner) { int randomTargetOwner = UnityEngine.Random.Range(0, charTiles.Count); var searchingTiles = charTiles[randomTargetOwner]; while (searchingTiles.Count == 0 || randomTargetOwner == (int)owner) { randomTargetOwner = UnityEngine.Random.Range(0, charTiles.Count); searchingTiles = charTiles[randomTargetOwner]; } int randomTileIndex = UnityEngine.Random.Range(0, searchingTiles.Count); TileInfo otherTile = searchingTiles[randomTileIndex]; if (!otherTile.canMove) { return GetRandomOtherTile(owner); } else { return otherTile; } } 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); } } } return otherTiles; } 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 GetOwnerAdjacentTiles(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 List GetCharacterTiles(PlayerState character) { TileOwner owner = character.ownerIndex; List playerTiles = new List(); foreach (TileInfo tile in charTiles[(int)owner]) { playerTiles.Add(tile); } return playerTiles; } public static void SetEasyCapState(List tiles, bool capState) { foreach (TileInfo tile in tiles) { tile.easyCaptureForAll = capState; } } /*public static void RemoveEasyCaptureForTiles(List tiles) { foreach (TileInfo tile in tiles) { tile.easyCaptureFor.Clear(); tile.isLocked = false; } }*/ /*public static TileInfo GetClosestOwnerTile(TileInfo startTile, TileOwner owner, float searchRadius) { var ownerTiles = charTiles[(int)owner]; TileInfo closestTile = ownerTiles[0]; foreach (TileInfo tile in ownerTiles) { //if () } return closestTile; }*/ public static TileInfo GetClosestOtherTile(TileInfo currentTile, TileOwner owner,/* float capRadius,*/ Vector3 startPoint) { var neutralTiles = charTiles[(int)TileOwner.Neutral]; //Debug.Log("neutral tiles " + neutralTiles.Count); TileInfo closestTile = neutralTiles[0]; 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 playerDistOld = Vector3.Distance(currentTile.tilePosition, closestTile.tilePosition); float playerDistNew = Vector3.Distance(currentTile.tilePosition, tile.tilePosition); //Debug.Log("new distance " + distNew); if ((distNew <= distOld) /*&& (distNew < capRadius)*/) { if ((playerDistNew < playerDistOld)) { closestTile = tile; } } } } return closestTile; } public static void CheckSurroundedTiles(List tiles, TileOwner newOwner, TileOwner oldOwner) { List checkPlayers = new List(); if (oldOwner != TileOwner.Neutral) { checkPlayers.Add(oldOwner); } checkPlayers.Add(newOwner); foreach (TileInfo tile in levelTiles) { tile.checkedFor.Clear(); foreach (var owner in checkPlayers) { tile.easyCaptureFor.Remove(owner); } } 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 SetPlayerTilesCapState(PlayerState player) { List playerTiles = charTiles[(int)player.ownerIndex]; foreach (TileInfo tile in playerTiles) { tile.easyCaptureForAll = true; } List playerConnectedTiles = GetConnectedTiles(levelTiles, player.ownerIndex, player.currentTile); foreach (TileInfo tile in playerConnectedTiles) { tile.easyCaptureForAll = false; } } public static void SetAllPLayersTilesCapState(List activePlayers) { foreach (PlayerState player in activePlayers) { SetPlayerTilesCapState(player); } } public static List GetConnectedTiles(List allTiles, TileOwner ownerIndex, TileInfo startTile) { List connectedTiles = new List(); var q = new Queue(allTiles.Count); q.Enqueue(startTile); int iterations = 0; while (q.Count > 0) { var tile = q.Dequeue(); if (q.Count > allTiles.Count) { throw new Exception("The algorithm is probably looping. Queue size: " + q.Count); } if (connectedTiles.Contains(tile)) { continue; } connectedTiles.Add(tile); var myAdjacentTiles = GetOwnerAdjacentTiles(tile, ownerIndex); foreach (TileInfo newTile in myAdjacentTiles) { q.Enqueue(newTile); } iterations++; } return connectedTiles; } 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) { tile.easyCaptureFor.Add(ownerIndex); } } private 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; } }