using System.Collections; using System.Collections.Generic; using UnityEngine; namespace TBTK{ public enum _GridType{ SquareGrid, HexGrid, } public enum _GridColliderType{ Master, Individual, } [RequireComponent(typeof(GridGenerator))] [ExecuteInEditMode] public class GridManager : MonoBehaviour { #if UNITY_EDITOR public static bool inspector=false; #endif public bool generateGridOnStart=false; public bool generateUnitOnStart=false; public bool generateCollectibleOnStart=false; [Space(8)] public _GridType gridType; public static _GridType GetGridType(){ return instance.cacheGridType; } public static bool IsSquareGrid(){ return GetGridType()==_GridType.SquareGrid; } public static bool IsHexGrid(){ return GetGridType()==_GridType.HexGrid; } public _GridColliderType colliderType; public static bool UseMasterCollider(){ return instance.cacheColliderType==_GridColliderType.Master; } public static bool UseIndividualCollider(){ return instance.cacheColliderType==_GridColliderType.Individual; } public enum _RangeCalculation{ ByNode, ByDistance } public _RangeCalculation rangeCalculation; public bool enableDiagonalNeighbour=false; public static bool EnableDiagonalNeighbour(){ return instance.cacheDiagonalNeighbour; } public float nodeSize=1; //public static float GetBaseNodeSize(){ return instance.cacheNodeSize; } public float nodeSpacing=0.1f; public static float GetNodeSpacing(){ return instance.cacheNodeSpacing; } public static float GetNodeSize(bool addSpacing=true){ return instance._GetNodeSize(addSpacing); } public float _GetNodeSize(bool addSpacing=true){ return cacheNodeSize * (IsHexGrid() ? 1.15f : 1) + (addSpacing ? cacheNodeSpacing : 0); } public static void ResetGrid(){ for(int x=0; x gridT =new List(); public List> grid=new List>(); [HideInInspector] public float offsetX; [HideInInspector] public float offsetZ; public float GetOffsetX(){ if(IsSquareGrid()) offsetX=DimensionX()*GetNodeSize()*.5f-GetNodeSize()*.5f; if(IsHexGrid()) offsetX=DimensionX()*GetNodeSize()*GridGenerator.spaceXHex/2f-0.5f*GetNodeSize()*GridGenerator.spaceXHex; return offsetX; } public float GetOffsetZ(){ if(IsSquareGrid()) offsetZ=DimensionZ()*GetNodeSize()*.5f-nodeSize*.5f; if(IsHexGrid()) offsetZ=DimensionZ()*GetNodeSize()*GridGenerator.spaceZHex/2f-0.5f*GetNodeSize()*GridGenerator.spaceZHex; return offsetZ; } [HideInInspector] public _GridType cacheGridType; [HideInInspector] public _GridColliderType cacheColliderType; [HideInInspector] public bool cacheDiagonalNeighbour; [HideInInspector] public float cacheNodeSize; [HideInInspector] public float cacheNodeSpacing; [HideInInspector] public int cacheDimensionX; [HideInInspector] public int cacheDimensionZ; public void CacheGridSetting(){ cacheGridType=gridType; cacheColliderType=colliderType; cacheDiagonalNeighbour=enableDiagonalNeighbour; cacheNodeSize=nodeSize; cacheNodeSpacing=nodeSpacing; cacheDimensionX=dimensionX; cacheDimensionZ=dimensionZ; } [Space(8)] public GameObject masterColliderObj; public void SetupMasterCollider(){ if(!UseMasterCollider()){ if(masterColliderObj!=null) masterColliderObj.SetActive(false); return; } if(masterColliderObj==null){ masterColliderObj=GameObject.CreatePrimitive(PrimitiveType.Quad); masterColliderObj.transform.parent=transform; masterColliderObj.transform.position=Vector3.zero; masterColliderObj.transform.rotation=Quaternion.Euler(90, 0, 0); masterColliderObj.name="Collider"; masterColliderObj.layer=30; masterColliderObj.GetComponent().enabled=false; } masterColliderObj.transform.localScale=new Vector3(DimensionX()*GetNodeSize(), DimensionZ()*GetNodeSize(), 1); masterColliderObj.SetActive(true); } public static List nodeDirList=new List(); public static void InitNodeDirList(){ nodeDirList=new List(); if(GridManager.IsHexGrid()){ nodeDirList.Add(new Vector3(.866f, 0, .5f)); nodeDirList.Add(new Vector3(0, 0, 1)); nodeDirList.Add(new Vector3(-.866f, 0, .5f)); nodeDirList.Add(new Vector3(-.866f, 0, -.5f)); nodeDirList.Add(new Vector3(0, 0, -1)); nodeDirList.Add(new Vector3(.866f, 0, -.5f)); } else if(GridManager.IsSquareGrid()){ nodeDirList.Add(new Vector3(1, 0, 0)); nodeDirList.Add(new Vector3(0, 0, 1)); nodeDirList.Add(new Vector3(-1, 0, 0)); nodeDirList.Add(new Vector3(0, 0, -1)); } } public static void SetupFogOfWar(){ instance._SetupFogOfWar(); } public void _SetupFogOfWar(){ if(!GameControl.EnableFogOfWar()) return; List unitList=new List( UnitManager.GetAllUnits() ); for(int i=0; isight) return false; if(debugging) Debug.Log(" ___ CheckLOS "); List nList1=new List{ node1 }; List nList2=new List{ node2 }; if(GameControl.EnableSideStepping()){ if(GridManager.IsSquareGrid()){ nList1.AddRange(GetSideStepNeighbours(node1, node2)); nList2.AddRange(GetSideStepNeighbours(node2, node1)); } else{ nList1.AddRange(node1.GetNeighbourList(true)); //n1 is the origin node, //nList2.AddRange(node2.GetNeighbourList(true)); } } if(debugging) Debug.Log(" ___ CheckLOS "+nList1.Count+" "+nList2.Count); for(int i=0; isight) continue; bool visible=!LOSCast(nList1[i].GetPos(), nList2[n].GetPos()); if(debugging) Debug.DrawLine(nList1[i].GetPos(), nList2[n].GetPos(), visible ? Color.white : Color.red, 1); if(visible) return true; } } if(debugging) Debug.Log(" ___ CheckLOS pass all false"); return false; } public static bool LOSCast(Vector3 pos1, Vector3 pos2, bool debugging=false){ InitMask(); return Physics.Linecast(pos1+new Vector3(0, .1f, 0), pos2+new Vector3(0, .1f, 0), losMask); } private static LayerMask losMask; public static bool initMask; public static void InitMask(){ if(initMask) return; initMask=true; losMask=1< GetSideStepNeighbours(Node srcNode, Node tgtNode){ List list=new List(); Node n1=GetSideStepNeighbour(srcNode, tgtNode, 1); if(n1!=null) list.Add(n1); Node n2=GetSideStepNeighbour(srcNode, tgtNode, -1); if(n2!=null) list.Add(n2); return list; } public static Node GetSideStepNeighbour(Node srcNode, Node tgtNode, float mul){ Vector3 dir=(tgtNode.GetPos()-srcNode.GetPos()).normalized; Vector3 dirP=new Vector3(dir.z, 0, -dir.x); Node neighbour=srcNode.GetNeighbourFromPos(srcNode.GetPos()+(mul*dirP)*GridManager.GetNodeSize()); if(neighbour!=null && !neighbour.IsBlocked(srcNode)) return neighbour; return null; } public static void SetupFogOfWarForDeployment(List dNodeList, int factionID){ if(!GameControl.EnableFogOfWar()) return; //Faction fac=UnitManager.GetFaction(UnitManager.GetDeployingFacIdx()); //List dNodeList=GetDeploymentNode(deployFacID); List visibleList=new List(); for(int x=0; x neighbours=node.GetNeighbourList(); for(int n=0; n scannedNodeList=new List(); //list of node under the effect of scan-fog-of-war ability public static void AddScannedNode(Node node){ instance.scannedNodeList.Add(node); } public static void EndTurn(){ for(int i=0; i(); instance.gridGenerator.Init(); instance.InitGrid(); if(Application.isPlaying){// && instance.combineGridMesh){ CombineMeshes cm=instance.gridGenerator.gridParent.GetComponent(); if(cm!=null) cm.Combine(); } GridIndicator indicator=(GridIndicator)FindObjectOfType(typeof(GridIndicator)); indicator.Awake(); } void InitGrid(){ InitNodeDirList(); for(int i=0; i().GenerateUnit(); if(generateCollectibleOnStart) gameObject.GetComponent().GenerateCollectible(); } if(Application.isPlaying && GameControl.EnableCoverSystem()) instance.StartCoroutine(InitGrid_Delayed()); } private IEnumerator InitGrid_Delayed(){ yield return null; for(int x=0; x> GetGrid(){ return instance.grid; } public static int GetNodeCount(){ return instance.dimensionX * instance.dimensionZ ; } public static Node GetNode(int x, int z){ if(x<0 || x>=instance.grid.Count) return null; if(z<0 || z>=instance.grid[x].Count) return null; return instance.grid[x][z]; } public static Node GetNode(Vector3 point, GameObject obj){ if(UseIndividualCollider()){ for(int x=0; x GetDeploymentNode(int facID){ return instance._GetDeploymentNode(facID); } public List _GetDeploymentNode(int facID){ List list=new List(); for(int x=0; x walkableList=new List(); public List attackableList=new List(); public static List GetWalkableList(){ return instance.walkableList; } public static List GetAttackableList(){ return instance.attackableList; } public static void SelectUnit(Unit unit){ SetupWalkableList(unit); SetupAttackableList(unit); } public static List SetupWalkableList(Unit unit){ instance.walkableList.Clear(); if(!unit.CanMove()) return null; //instance.walkableList=GetNodesWithinDistance(unit.node, unit.GetMoveRange(), true, unit.canMovePastUnit, unit.canMovePastObs); instance.walkableList=GetNodesWithinDistance(unit.node, unit.GetMoveRange(), true, AStar.BypassUnitCode(unit), unit.canMovePastObs); for(int i=0; i SetupAttackableList(Unit unit){ instance.attackableList=GetAttackableList(unit, unit.node); return instance.attackableList; //instance.attackableList.Clear(); //List list=GetNodesWithinDistance(unit.node, unit.GetAttackRange(), false); //for(int i=0; i(); instance.attackableList=new List(); } public static List GetAttackableList(Unit unit, Node tgtNode){ if(!unit.CanAttack()) return new List(); List list=GetNodesWithinDistance(tgtNode, unit.GetAttackRange(), false); List tgtList=new List(); float minAttackRange=unit.GetAttackRangeMin(); float meleeAttackRange=unit.hasMeleeAttack ? unit.GetAttackRangeMelee() : 0; for(int i=0; i0){ int dist=GridManager.GetDistance(list[i].unit.node, unit.node); if(meleeAttackRange<=0){ if(minAttackRange>0 && distmeleeAttackRange && dist abilityTargetList=new List(); public static bool InAbilityTargetList(Node node){ return instance.abilityTargetList.Contains(node); } public static void SetupAbilityTargetList(Faction fac, Ability ability){ List list=new List(); for(int x=0; x list=GetNodesInALine(unit.node, angle, ability.GetRange()); for(int n=0; n nodeList=GetNodesWithinDistance(unit.node, ability.GetRange()); SetupAbilityTargetList(ability, nodeList, unit.GetFacID(), unit.node); } public static void SetupAbilityTargetList(Ability ability, List list, int facID, Node origin){ instance.abilityTargetList.Clear(); int rangeMin=ability.GetRangeMin(); if(ability.isUnitAbility && rangeMin>0){ for(int i=0; i()); } else GridIndicator.ShowAbility(instance.abilityTargetList); } public static void ClearAbilityTargetList(bool resetIndicator){ GridIndicator.HideAbility(); instance.abilityTargetList.Clear(); if(resetIndicator){ GridIndicator.ShowMovable(GetWalkableList()); GridIndicator.ShowHostile(GetAttackableList()); } } public static List GetTargetNodeForNonTargetingFAbility(Ability ability){ List list=new List(); List uList=UnitManager.GetAllUnitList(); //if(ability.targetType==Ability._TargetType.AllNode){ // for(int x=0; x testNodeList=new List(); void OnDrawGizmos22(){ Gizmos.color=Color.grey; for(int i=0; i GetSurroundingNodes(Node srcNode, int range, bool walkableOnly=true){ List tgtList=GetNodesWithinDistance(srcNode, range, walkableOnly); List exemptList=GetNodesWithinDistance(srcNode, range-1, walkableOnly); for(int i=0; i GetNodesInACircle(Node srcNode, int range, bool walkableOnly=true){ //int range=(int)Mathf.Ceil(dist/GetNodeSize()); float dist=range*GetNodeSize(); List tgtList=GetNodesWithinDistance(srcNode, range, walkableOnly); //instance.testNodeList=new List( tgtList ); for(int i=0; idist){ tgtList.RemoveAt(i); i-=1; } } return tgtList; } public static List GetNodesInACone(Node srcNode, Node tgtNode, int range, int fov, bool walkableOnly=false){ List tgtList=new List(); Vector3 v=( tgtNode.GetPos() - srcNode.GetPos() ).normalized; float baseAngle=Utility.Vector2ToAngle(new Vector2(v.x, v.z)); //~ int range=(int)Mathf.Ceil(dist/GetNodeSize()); List nodeList=GetNodesWithinDistance(srcNode, range, true, true, true); //~ List nodeList=GetNodesInACircle(srcNode, range, walkableOnly); //instance.testNodeList=nodeList; for(int i=0; idist) continue; if(!nodeList[i].walkable) continue; if(nodeList[i].obstacleT!=null) continue; if(walkableOnly && nodeList[i].unit!=null) continue; float angle=GetAngle(srcNode, nodeList[i], false);//Utility.Vector2ToAngle(new Vector2(vv.x, vv.z)); float angleDiff=Mathf.Abs(angle-baseAngle); if(angleDiff>180) angleDiff=Mathf.Abs(angleDiff-360); if(angleDiff<=fov*0.5f){ tgtList.Add(nodeList[i]); //Debug.DrawLine(srcNode.GetPos(), nodeList[i].GetPos(), Color.green, 0.2f); } //else Debug.DrawLine(srcNode.GetPos(), nodeList[i].GetPos(), Color.red, 0.2f); } return tgtList; } public static List GetNodesInALine(Node srcNode, float angle, int dist, bool walkableOnly=false){ List list=new List(); Node curNode=srcNode; for(int i=0; i neighbourList=curNode.GetNeighbourList(walkableOnly); for(int n=0; n1) continue; curNode=neighbourList[n]; list.Add(curNode); break; } } //Debug.Log("GetNodesInALine "+list.Count); //if(list.Count>3) Debug.Log(list[0].objT+" "+list[1].objT+" "+list[2].objT+" "+list[3].objT+" "); return list; } public static List GetNodesWithinDistance(Node srcNode, int dist, bool walkableOnly=false, bool allowUnit=false, bool allowObs=false){ return GetNodesWithinDistance(srcNode, dist, walkableOnly, AStar.BypassUnitCode(allowUnit), allowObs); } public static List GetNodesWithinDistance(Node srcNode, int dist, bool walkableOnly, int allowUnit, bool allowObs){ List neighbourList=srcNode.GetNeighbourList(walkableOnly, allowUnit, allowObs); List closeList=new List(); List openList=new List(); List newOpenList=new List(); for(int m=0; m(); for(int n=0; n=convertedDist){ closeList.RemoveAt(i); i-=1; } } } return closeList; } public static List GetSpawnGroup(int facID, int areaID){ List list=new List(); for(int x=0; x=0){ Gizmos.color=UnitManager.GetFacColor(grid[x][z].deployFacID); Gizmos.DrawSphere(grid[x][z].GetPos(), nodeSize*0.175f); } if(grid[x][z].spawnGroupFacID>=0){ //Gizmos.DrawSphere(grid[x][z].GetPos(), nodeSize*0.25f); //Utility.GizmosDrawCross(grid[x][z].GetPos(), nodeSize*0.25f, UnitManager.GetFacColor(grid[x][z].spawnGroupFacID)); Gizmos.color=UnitManager.GetFacColor(grid[x][z].spawnGroupFacID); float size=nodeSize*0.25f; Vector3 pos=grid[x][z].GetPos()+new Vector3(0, .1f, 0); Gizmos.DrawLine(pos+new Vector3(1, 0, 1).normalized*size, pos-new Vector3(1, 0, 1).normalized*size); Gizmos.DrawLine(pos+new Vector3(-1, 0, 1).normalized*size, pos-new Vector3(-1, 0, 1).normalized*size); } } } if(abilityTargetList.Count>0){ Gizmos.color=Color.yellow; for(int i=0; i