예제 #1
0
    void MoveUnitToTileInstant(UnitTB unit, Tile tile)
    {
        List <Tile> path = AStar.SearchToOccupiedTile(unit.occupiedTile, tile);

        //make sure the target tile is not occupied
        if (path.Count > 0)
        {
            if (path[path.Count - 1].unit != null)
            {
                path.RemoveAt(path.Count - 1);
            }
        }

        //make sure the unit doesnt move beyond the allowed range
        while (path.Count > Mathf.Max(1, unit.GetMoveRange() + 1))
        {
            path.RemoveAt(path.Count - 1);
        }

        if (path.Count > 0)
        {
            Tile destinationTile = path[path.Count - 1];

            unit.occupiedTile.unit = null;
            unit.occupiedTile      = destinationTile;
            destinationTile.unit   = unit;
            unit.thisT.position    = destinationTile.pos;
        }

        unitInAction = false;
    }
예제 #2
0
    void DrawSelectedUnit(UnitTB unit)
    {
        GUIStyle style = new GUIStyle();

        style.fontSize = 20;      style.fontStyle = FontStyle.Bold; style.normal.textColor = UI.colorH;       style.alignment = TextAnchor.UpperCenter;

        int winWidth  = 300;
        int winHeight = 550;

        int startX = Screen.width / 2 - 350;
        int startY = Screen.height / 2 - winHeight / 2;

        for (int i = 0; i < 3; i++)
        {
            GUI.Box(new Rect(startX, startY, winWidth, winHeight), "");
        }
        startX += 15;     winWidth -= 30;

        GUI.Label(new Rect(startX, startY + 10, winWidth, winHeight), unit.unitName, style);
        GUI.Label(new Rect(startX, startY + 12, winWidth, winHeight), "_________________________________________________", style);

        startY += 40;

        GUI.DrawTexture(new Rect(startX + 10, startY, 60, 60), texBar);
        GUI.DrawTexture(new Rect(startX + 13, startY + 3, 54, 54), unit.icon);
        style.alignment = TextAnchor.UpperLeft;   style.fontSize = 16;
        GUI.Label(new Rect(startX + 80, startY + 10, winWidth - 80, winHeight), "Hit Point:\nAction Point:", style);
        style.alignment = TextAnchor.UpperRight;
        GUI.Label(new Rect(startX + 80, startY + 10, winWidth - 80, winHeight), unit.fullHP + "\n" + unit.fullAP, style);

        startY += 70;

        if (infoTab == _InfoTab.General)
        {
            style.alignment = TextAnchor.UpperCenter; style.wordWrap = true;    style.normal.textColor = UI.colorN;
            GUI.Label(new Rect(startX, startY, winWidth, 100), unit.desp, style);
        }
        else
        {
            string offText  = "";
            string offVText = "";
            if (unit.attackMode == _AttackMode.Hybrid)
            {
                offText = "Damage (melee/range):\nHit (melee/range):\nCritical (melee/range):\nAttack Range";

                offVText += unit.GetMeleeDamageMin() + "-" + unit.GetMeleeDamageMax() + "/" + unit.GetRangeDamageMin() + "-" + unit.GetRangeDamageMax() + "\n";
                offVText += (unit.GetMeleeAttack() * 100).ToString("f0") + "/" + (unit.GetRangeAttack() * 100).ToString("f0") + "%" + "\n";
                offVText += (unit.GetMeleeCritical() * 100).ToString("f0") + "/" + (unit.GetRangeCritical() * 100).ToString("f0") + "%" + "\n";
                offVText += unit.GetAttackRangeMax().ToString("f0") + "\n";
            }
            else
            {
                offText = "Attack Damage:\nHit Chance:\nCritical Hit Chance:\nAttack Range:";
            }

            if (unit.attackMode == _AttackMode.Melee)
            {
                offVText += unit.GetMeleeDamageMin() + "-" + unit.GetMeleeDamageMax() + "\n";
                offVText += (unit.GetMeleeAttack() * 100).ToString("f0") + "%" + "\n";
                offVText += (unit.GetMeleeCritical() * 100).ToString("f0") + "%" + "\n";

                offVText += unit.GetAttackRangeMax().ToString("f0") + "\n";
            }
            else if (unit.attackMode == _AttackMode.Range)
            {
                offVText += unit.GetRangeDamageMin() + "-" + unit.GetRangeDamageMax() + "\n";
                offVText += (unit.GetRangeAttack() * 100).ToString("f0") + "%" + "\n";
                offVText += (unit.GetRangeCritical() * 100).ToString("f0") + "%" + "\n";

                int dist = unit.GetAttackRangeMin();
                if (dist <= 0)
                {
                    offVText += unit.GetAttackRangeMax().ToString("f0") + "\n";
                }
                else
                {
                    offVText += unit.GetRangeDamageMin() + "-" + unit.GetRangeDamageMax() + "\n";
                }
            }

            string defText  = "Armour:\nDodge Chance:\nCritical Immunity:";
            string miscText = "Mobility:\nSpeed:\nAbilities:";

            string defVText = "";
            defVText += unit.GetDmgReduc().ToString("f0") + "\n";
            defVText += (unit.GetDefend() * 100).ToString("f0") + "%" + "\n";
            defVText += (unit.GetCritDef() * 100).ToString("f0") + "%" + "\n";

            string miscVText = "";
            miscVText += unit.GetMoveRange().ToString("f0") + "\n";
            miscVText += unit.GetTurnPriority().ToString("f0") + "\n";

            style.alignment = TextAnchor.UpperLeft;   style.fontSize = 16;      style.normal.textColor = UI.colorH;
            GUI.Label(new Rect(startX, startY, winWidth, winHeight), "Offense:", style);
            style.fontSize = 12;      style.normal.textColor = UI.colorN;
            GUI.Label(new Rect(startX, startY + 18, winWidth, winHeight), offText, style);
            style.alignment = TextAnchor.UpperRight;
            GUI.Label(new Rect(startX, startY + 18, winWidth, winHeight), offVText, style);

            startY += 90;

            style.alignment = TextAnchor.UpperLeft;   style.fontSize = 16;      style.normal.textColor = UI.colorH;
            GUI.Label(new Rect(startX, startY, winWidth, winHeight), "Defense:", style);
            style.fontSize = 12;      style.normal.textColor = UI.colorN;
            GUI.Label(new Rect(startX, startY + 18, winWidth, winHeight), defText, style);
            style.alignment = TextAnchor.UpperRight;
            GUI.Label(new Rect(startX, startY + 18, winWidth, winHeight), defVText, style);

            startY += 75;

            style.alignment = TextAnchor.UpperLeft;   style.fontSize = 16;      style.normal.textColor = UI.colorH;
            GUI.Label(new Rect(startX, startY, winWidth, winHeight), "Misc:", style);
            style.fontSize = 12;      style.normal.textColor = UI.colorN;
            GUI.Label(new Rect(startX, startY + 18, winWidth, winHeight), miscText, style);
            style.alignment = TextAnchor.UpperRight;
            GUI.Label(new Rect(startX, startY + 18, winWidth, winHeight), miscVText, style);

            startY += 65;

            List <int> abilityIDList = unit.abilityIDList;
            for (int i = 0; i < abilityIDList.Count; i++)
            {
                foreach (UnitAbility uAB in unitAbilityList)
                {
                    if (uAB.ID == abilityIDList[i])
                    {
                        GUI.DrawTexture(new Rect(15 + startX + i * 35, startY, 31, 31), texBar);
                        GUI.DrawTexture(new Rect(15 + startX + i * 35 + 2, startY + 2, 27, 27), uAB.icon);
                        GUIContent cont = new GUIContent("", uAB.ID.ToString());
                        GUI.Label(new Rect(15 + startX + i * 35, startY + 3, 25, 25), cont);
                    }
                }
            }

            startY += 40;

            if (GUI.tooltip != "")
            {
                int ID = int.Parse(GUI.tooltip);
                foreach (UnitAbility uAB in unitAbilityList)
                {
                    if (uAB.ID == ID)
                    {
                        style.alignment = TextAnchor.UpperCenter; style.wordWrap = true;
                        GUI.Label(new Rect(startX + 3, startY + 3, winWidth, 50), uAB.desp.ToString());
                    }
                }
            }
        }

        string buttonText = "Less Details";

        if (infoTab == _InfoTab.General)
        {
            buttonText = "More Details";
        }
        bool switchFlag = GUI.Button(new Rect(startX + winWidth / 2 - 60, Screen.height / 2 + winHeight / 2 - 40, 120, 30), buttonText, UI.buttonStyle);

        if (switchFlag)
        {
            if (infoTab == _InfoTab.General)
            {
                infoTab = _InfoTab.Stats;
            }
            else
            {
                infoTab = _InfoTab.General;
            }
        }
    }
예제 #3
0
    //LOS and fog of war is not considered
    //that has already been built into various function called on UnitControl and GridManager
    public Tile Analyse(UnitTB unit)
    {
        //analyse current tile first
        List<UnitTB> currentHostilesList;
        if(!GameControlTB.EnableFogOfWar()) currentHostilesList=UnitControl.GetHostileInRangeFromTile(unit.occupiedTile, unit);
        else currentHostilesList=UnitControl.GetVisibleHostileInRangeFromTile(unit.occupiedTile, unit);
        unit.occupiedTile.AIHostileList=currentHostilesList;

        if(GameControlTB.EnableCover()){
            if(currentHostilesList.Count!=0){
                int count=0;
                for(int n=0; n<currentHostilesList.Count; n++){
                    if((int)unit.occupiedTile.GetCoverType(currentHostilesList[n].thisT.position)>0){
                        count+=1;
                    }
                }
                if(count==currentHostilesList.Count) return unit.occupiedTile;
            }
        }
        else{
            if(currentHostilesList.Count!=0) return unit.occupiedTile;
        }

        //get all possible target
        List<UnitTB> allHostiles=new List<UnitTB>();
        if(GameControlTB.EnableFogOfWar()) allHostiles=UnitControl.GetAllHostileWithinFactionSight(unit.factionID);
        else allHostiles=UnitControl.GetAllHostile(unit.factionID);

        //if there's no potential target at all
        if(allHostiles.Count==0){
            if(unit.attackerList.Count>0){
                return unit.attackerList[0].unit.occupiedTile;
            }
            else{
                //if stance is set to passive, stay put
                if(aIStance==_AIStance.Passive) return unit.occupiedTile;
            }
        }

        //get all walkable
        List<Tile> walkableTiles=GridManager.GetWalkableTilesWithinRange(unit.occupiedTile, unit.GetMoveRange());

        //get tiles with target in range from the walkables
        List<Tile> offensiveTiles=new List<Tile>();
        for(int i=0; i<walkableTiles.Count; i++){
            walkableTiles[i].AIHostileList=new List<UnitTB>();
            bool visibleOnly=GameControlTB.EnableFogOfWar();
            List<UnitTB> hostilesList=UnitControl.GetHostileInRangeFromTile(walkableTiles[i], unit, visibleOnly);
            walkableTiles[i].AIHostileList=hostilesList;
            if(hostilesList.Count>0){
                offensiveTiles.Add(walkableTiles[i]);
            }
        }

        //cross search any walkables with any tiles with target
        List<Tile> offensiveWalkableTiles=new List<Tile>();
        for(int i=0; i<offensiveTiles.Count; i++){
            if(walkableTiles.Contains(offensiveTiles[i])){
                offensiveWalkableTiles.Add(offensiveTiles[i]);
            }
        }

        //if the game uses cover
        if(GameControlTB.EnableCover()){
            //calculating general direction of enemy, to know which direction to take cover from
            //Vector3 hostileAveragePos=Vector3.zero;
            //for(int i=0; i<allHostiles.Count; i++){
            //	hostileAveragePos+=allHostiles[i].occupiedTile.pos;
            //}
            //hostileAveragePos/=allHostiles.Count;

            //get offensive tile with cover from all hostile
            List<Tile> offensiveTilesWithAllCover=new List<Tile>();
            List<Tile> offensiveTilesWithPartialCover=new List<Tile>();
            for(int i=0; i<offensiveWalkableTiles.Count; i++){
                Tile tile=offensiveWalkableTiles[i];
                int count=0;
                for(int n=0; n<tile.AIHostileList.Count; n++){
                    if((int)tile.GetCoverType(tile.AIHostileList[n].thisT.position)>0){
                        count+=1;
                    }
                }
                if(count==tile.AIHostileList.Count) offensiveTilesWithAllCover.Add(tile);
                else if(count>0) offensiveTilesWithPartialCover.Add(tile);
            }

            if(offensiveTilesWithAllCover.Count>0){
                int rand=UnityEngine.Random.Range(0, offensiveTilesWithAllCover.Count);
                return(offensiveTilesWithAllCover[rand]);
            }
            else if(offensiveTilesWithAllCover.Count>0){
                int rand=UnityEngine.Random.Range(0, offensiveTilesWithPartialCover.Count);
                return(offensiveTilesWithPartialCover[rand]);
            }

            //get any tile with possible cover from the walkables
            List<Tile> walkableTilesWithCover=new List<Tile>();
            for(int i=0; i<walkableTiles.Count; i++){
                if(walkableTiles[i].GotCover()){
                    walkableTilesWithCover.Add(walkableTiles[i]);
                }
            }

            //cross-search offense and walkable tile with cover
            //to get tiles which offer cover and the unit can attack from
            List<Tile> offensiveTilesWithCover=new List<Tile>();
            for(int i=0; i<offensiveTiles.Count; i++){
                if(walkableTilesWithCover.Contains(offensiveTiles[i])){
                    offensiveTilesWithCover.Add(offensiveTiles[i]);
                }
            }

            //if there's any tile that offer cover and target at the same time, use the tile
            if(offensiveTilesWithCover.Count>0){
                int rand=UnityEngine.Random.Range(0, offensiveTilesWithCover.Count);
                return offensiveTilesWithCover[rand];
            }

            //if there's no tile that offer cover and target at the same time
            //just use any walkable tile with cover instead
            if(walkableTilesWithCover.Count>0){
                int rand=UnityEngine.Random.Range(0, walkableTilesWithCover.Count);
                return walkableTilesWithCover[rand];
            }
        }

        //if cover system is not used, or there's no cover in any walkable tiles
        //if there's walkable that the unit can attack from, uses that
        if(offensiveWalkableTiles.Count>0){
            int rand=UnityEngine.Random.Range(0, offensiveWalkableTiles.Count);
            return offensiveWalkableTiles[rand];
        }

        //check if the unit has been attacked, if yes, retaliate
        UnitTB attacker=unit.GetNearestAttacker();
        if(attacker!=null) return attacker.occupiedTile;

        //no hostile unit within range
        if(aIStance==_AIStance.Active || aIStance==_AIStance.Trigger){
            //no hostile detected at all, just move randomly
            if(allHostiles.Count==0){
                if(walkableTiles.Count>0){
                    int rand=UnityEngine.Random.Range(0, walkableTiles.Count);
                    return walkableTiles[rand];
                }
            }
            //get the nearest target and move towards it
            else{
                int nearest=999999999;
                int nearestID=0;
                for(int i=0; i<allHostiles.Count; i++){
                    int dist=GridManager.Distance(unit.occupiedTile, allHostiles[i].occupiedTile);
                    if(dist<nearest){
                        nearest=dist;
                        nearestID=i;
                    }
                }
                return allHostiles[nearestID].occupiedTile;
            }
        }

        return null;
    }
예제 #4
0
    void MoveUnitToTileInstant(UnitTB unit, Tile tile)
    {
        List<Tile> path=AStar.SearchToOccupiedTile(unit.occupiedTile, tile);

        //make sure the target tile is not occupied
        if(path.Count>0){
            if(path[path.Count-1].unit!=null) path.RemoveAt(path.Count-1);
        }

        //make sure the unit doesnt move beyond the allowed range
        while(path.Count>Mathf.Max(1, unit.GetMoveRange()+1)){
            path.RemoveAt(path.Count-1);
        }

        if(path.Count>0){
            Tile destinationTile=path[path.Count-1];

            unit.occupiedTile.unit=null;
            unit.occupiedTile=destinationTile;
            destinationTile.unit=unit;
            unit.thisT.position=destinationTile.pos;
        }

        unitInAction=false;
    }
예제 #5
0
    void DrawSelectedUnit(UnitTB unit)
    {
        GUIStyle style=new GUIStyle();
        style.fontSize=20;	style.fontStyle=FontStyle.Bold;	style.normal.textColor=UI.colorH;	style.alignment=TextAnchor.UpperCenter;

        int winWidth=300;
        int winHeight=550;

        int startX=Screen.width/2-350;
        int startY=Screen.height/2-winHeight/2;

        for(int i=0; i<3; i++) GUI.Box(new Rect(startX, startY, winWidth, winHeight), "");
        startX+=15;	winWidth-=30;

        GUI.Label(new Rect(startX, startY+10, winWidth, winHeight), unit.unitName, style);
        GUI.Label(new Rect(startX, startY+12, winWidth, winHeight), "_________________________________________________", style);

        startY+=40;

        GUI.DrawTexture(new Rect(startX+10, startY, 60, 60), texBar);
        GUI.DrawTexture(new Rect(startX+13, startY+3, 54, 54), unit.icon);
        style.alignment=TextAnchor.UpperLeft;	style.fontSize=16;
        GUI.Label(new Rect(startX+80, startY+10, winWidth-80, winHeight), "Hit Point:\nAction Point:", style);
        style.alignment=TextAnchor.UpperRight;
        GUI.Label(new Rect(startX+80, startY+10, winWidth-80, winHeight), unit.fullHP+"\n"+unit.fullAP, style);

        startY+=70;

        if(infoTab==_InfoTab.General){
            style.alignment=TextAnchor.UpperCenter;	style.wordWrap=true;	style.normal.textColor=UI.colorN;
            GUI.Label(new Rect(startX, startY, winWidth, 100), unit.desp, style);
        }
        else{
            string offText="";
            string offVText="";
            if(unit.attackMode==_AttackMode.Hybrid){
                offText="Damage (melee/range):\nHit (melee/range):\nCritical (melee/range):\nAttack Range";

                offVText+=unit.GetMeleeDamageMin()+"-"+unit.GetMeleeDamageMax()+"/"+unit.GetRangeDamageMin()+"-"+unit.GetRangeDamageMax()+"\n";
                offVText+=(unit.GetMeleeAttack()*100).ToString("f0")+"/"+(unit.GetRangeAttack()*100).ToString("f0")+"%"+"\n";
                offVText+=(unit.GetMeleeCritical()*100).ToString("f0")+"/"+(unit.GetRangeCritical()*100).ToString("f0")+"%"+"\n";
                offVText+=unit.GetAttackRangeMax().ToString("f0")+"\n";
            }
            else{
                offText="Attack Damage:\nHit Chance:\nCritical Hit Chance:\nAttack Range:";
            }

            if(unit.attackMode==_AttackMode.Melee){
                offVText+=unit.GetMeleeDamageMin()+"-"+unit.GetMeleeDamageMax()+"\n";
                offVText+=(unit.GetMeleeAttack()*100).ToString("f0")+"%"+"\n";
                offVText+=(unit.GetMeleeCritical()*100).ToString("f0")+"%"+"\n";

                offVText+=unit.GetAttackRangeMax().ToString("f0")+"\n";
            }
            else if(unit.attackMode==_AttackMode.Range){
                offVText+=unit.GetRangeDamageMin()+"-"+unit.GetRangeDamageMax()+"\n";
                offVText+=(unit.GetRangeAttack()*100).ToString("f0")+"%"+"\n";
                offVText+=(unit.GetRangeCritical()*100).ToString("f0")+"%"+"\n";

                int dist=unit.GetAttackRangeMin();
                if(dist<=0) offVText+=unit.GetAttackRangeMax().ToString("f0")+"\n";
                else offVText+=unit.GetRangeDamageMin()+"-"+unit.GetRangeDamageMax()+"\n";
            }

            string defText="Armour:\nDodge Chance:\nCritical Immunity:";
            string miscText="Mobility:\nSpeed:\nAbilities:";

            string defVText="";
            defVText+=unit.GetDmgReduc().ToString("f0")+"\n";
            defVText+=(unit.GetDefend()*100).ToString("f0")+"%"+"\n";
            defVText+=(unit.GetCritDef()*100).ToString("f0")+"%"+"\n";

            string miscVText="";
            miscVText+=unit.GetMoveRange().ToString("f0")+"\n";
            miscVText+=unit.GetTurnPriority().ToString("f0")+"\n";

            style.alignment=TextAnchor.UpperLeft;	style.fontSize=16;	style.normal.textColor=UI.colorH;
            GUI.Label(new Rect(startX, startY, winWidth, winHeight), "Offense:", style);
            style.fontSize=12;	style.normal.textColor=UI.colorN;
            GUI.Label(new Rect(startX, startY+18, winWidth, winHeight), offText, style);
            style.alignment=TextAnchor.UpperRight;
            GUI.Label(new Rect(startX, startY+18, winWidth, winHeight), offVText, style);

            startY+=90;

            style.alignment=TextAnchor.UpperLeft;	style.fontSize=16;	style.normal.textColor=UI.colorH;
            GUI.Label(new Rect(startX, startY, winWidth, winHeight), "Defense:", style);
            style.fontSize=12;	style.normal.textColor=UI.colorN;
            GUI.Label(new Rect(startX, startY+18, winWidth, winHeight), defText, style);
            style.alignment=TextAnchor.UpperRight;
            GUI.Label(new Rect(startX, startY+18, winWidth, winHeight), defVText, style);

            startY+=75;

            style.alignment=TextAnchor.UpperLeft;	style.fontSize=16;	style.normal.textColor=UI.colorH;
            GUI.Label(new Rect(startX, startY, winWidth, winHeight), "Misc:", style);
            style.fontSize=12;	style.normal.textColor=UI.colorN;
            GUI.Label(new Rect(startX, startY+18, winWidth, winHeight), miscText, style);
            style.alignment=TextAnchor.UpperRight;
            GUI.Label(new Rect(startX, startY+18, winWidth, winHeight), miscVText, style);

            startY+=65;

            List<int> abilityIDList=unit.abilityIDList;
            for(int i=0; i<abilityIDList.Count; i++){
                foreach(UnitAbility uAB in unitAbilityList){
                    if(uAB.ID==abilityIDList[i]){
                        GUI.DrawTexture(new Rect(15+startX+i*35, startY, 31, 31), texBar);
                        GUI.DrawTexture(new Rect(15+startX+i*35+2, startY+2, 27, 27), uAB.icon);
                        GUIContent cont=new GUIContent("", uAB.ID.ToString());
                        GUI.Label(new Rect(15+startX+i*35, startY+3, 25, 25), cont);
                    }
                }
            }

            startY+=40;

            if(GUI.tooltip!=""){
                int ID=int.Parse(GUI.tooltip);
                foreach(UnitAbility uAB in unitAbilityList){
                    if(uAB.ID==ID){
                        style.alignment=TextAnchor.UpperCenter;	style.wordWrap=true;
                        GUI.Label(new Rect(startX+3, startY+3, winWidth, 50), uAB.desp.ToString());
                    }
                }
            }
        }

        string buttonText="Less Details";
        if(infoTab==_InfoTab.General) buttonText="More Details";
        bool switchFlag=GUI.Button(new Rect(startX+winWidth/2-60, Screen.height/2+winHeight/2-40, 120, 30), buttonText, UI.buttonStyle);

        if(switchFlag){
            if(infoTab==_InfoTab.General) infoTab=_InfoTab.Stats;
            else infoTab=_InfoTab.General;
        }
    }
예제 #6
0
    //LOS and fog of war is not considered
    //that has already been built into various function called on UnitControl and GridManager
    public Tile Analyse(UnitTB unit)
    {
        //analyse current tile first
        List <UnitTB> currentHostilesList;

        if (!GameControlTB.EnableFogOfWar())
        {
            currentHostilesList = UnitControl.GetHostileInRangeFromTile(unit.occupiedTile, unit);
        }
        else
        {
            currentHostilesList = UnitControl.GetVisibleHostileInRangeFromTile(unit.occupiedTile, unit);
        }
        unit.occupiedTile.AIHostileList = currentHostilesList;

        if (GameControlTB.EnableCover())
        {
            if (currentHostilesList.Count != 0)
            {
                int count = 0;
                for (int n = 0; n < currentHostilesList.Count; n++)
                {
                    if ((int)unit.occupiedTile.GetCoverType(currentHostilesList[n].thisT.position) > 0)
                    {
                        count += 1;
                    }
                }
                if (count == currentHostilesList.Count)
                {
                    return(unit.occupiedTile);
                }
            }
        }
        else
        {
            if (currentHostilesList.Count != 0)
            {
                return(unit.occupiedTile);
            }
        }


        //get all possible target
        List <UnitTB> allHostiles = new List <UnitTB>();

        if (GameControlTB.EnableFogOfWar())
        {
            allHostiles = UnitControl.GetAllHostileWithinFactionSight(unit.factionID);
        }
        else
        {
            allHostiles = UnitControl.GetAllHostile(unit.factionID);
        }


        //if there's no potential target at all
        if (allHostiles.Count == 0)
        {
            if (unit.attackerList.Count > 0)
            {
                return(unit.attackerList[0].unit.occupiedTile);
            }
            else
            {
                //if stance is set to passive, stay put
                if (aIStance == _AIStance.Passive)
                {
                    return(unit.occupiedTile);
                }
            }
        }

        //get all walkable
        List <Tile> walkableTiles = GridManager.GetWalkableTilesWithinRange(unit.occupiedTile, unit.GetMoveRange());

        //get tiles with target in range from the walkables
        List <Tile> offensiveTiles = new List <Tile>();

        for (int i = 0; i < walkableTiles.Count; i++)
        {
            walkableTiles[i].AIHostileList = new List <UnitTB>();
            bool          visibleOnly  = GameControlTB.EnableFogOfWar();
            List <UnitTB> hostilesList = UnitControl.GetHostileInRangeFromTile(walkableTiles[i], unit, visibleOnly);
            walkableTiles[i].AIHostileList = hostilesList;
            if (hostilesList.Count > 0)
            {
                offensiveTiles.Add(walkableTiles[i]);
            }
        }

        //cross search any walkables with any tiles with target
        List <Tile> offensiveWalkableTiles = new List <Tile>();

        for (int i = 0; i < offensiveTiles.Count; i++)
        {
            if (walkableTiles.Contains(offensiveTiles[i]))
            {
                offensiveWalkableTiles.Add(offensiveTiles[i]);
            }
        }

        //if the game uses cover
        if (GameControlTB.EnableCover())
        {
            //calculating general direction of enemy, to know which direction to take cover from
            //Vector3 hostileAveragePos=Vector3.zero;
            //for(int i=0; i<allHostiles.Count; i++){
            //	hostileAveragePos+=allHostiles[i].occupiedTile.pos;
            //}
            //hostileAveragePos/=allHostiles.Count;


            //get offensive tile with cover from all hostile
            List <Tile> offensiveTilesWithAllCover     = new List <Tile>();
            List <Tile> offensiveTilesWithPartialCover = new List <Tile>();
            for (int i = 0; i < offensiveWalkableTiles.Count; i++)
            {
                Tile tile  = offensiveWalkableTiles[i];
                int  count = 0;
                for (int n = 0; n < tile.AIHostileList.Count; n++)
                {
                    if ((int)tile.GetCoverType(tile.AIHostileList[n].thisT.position) > 0)
                    {
                        count += 1;
                    }
                }
                if (count == tile.AIHostileList.Count)
                {
                    offensiveTilesWithAllCover.Add(tile);
                }
                else if (count > 0)
                {
                    offensiveTilesWithPartialCover.Add(tile);
                }
            }

            if (offensiveTilesWithAllCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, offensiveTilesWithAllCover.Count);
                return(offensiveTilesWithAllCover[rand]);
            }
            else if (offensiveTilesWithAllCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, offensiveTilesWithPartialCover.Count);
                return(offensiveTilesWithPartialCover[rand]);
            }


            //get any tile with possible cover from the walkables
            List <Tile> walkableTilesWithCover = new List <Tile>();
            for (int i = 0; i < walkableTiles.Count; i++)
            {
                if (walkableTiles[i].GotCover())
                {
                    walkableTilesWithCover.Add(walkableTiles[i]);
                }
            }

            //cross-search offense and walkable tile with cover
            //to get tiles which offer cover and the unit can attack from
            List <Tile> offensiveTilesWithCover = new List <Tile>();
            for (int i = 0; i < offensiveTiles.Count; i++)
            {
                if (walkableTilesWithCover.Contains(offensiveTiles[i]))
                {
                    offensiveTilesWithCover.Add(offensiveTiles[i]);
                }
            }

            //if there's any tile that offer cover and target at the same time, use the tile
            if (offensiveTilesWithCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, offensiveTilesWithCover.Count);
                return(offensiveTilesWithCover[rand]);
            }

            //if there's no tile that offer cover and target at the same time
            //just use any walkable tile with cover instead
            if (walkableTilesWithCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, walkableTilesWithCover.Count);
                return(walkableTilesWithCover[rand]);
            }
        }

        //if cover system is not used, or there's no cover in any walkable tiles
        //if there's walkable that the unit can attack from, uses that
        if (offensiveWalkableTiles.Count > 0)
        {
            int rand = UnityEngine.Random.Range(0, offensiveWalkableTiles.Count);
            return(offensiveWalkableTiles[rand]);
        }

        //check if the unit has been attacked, if yes, retaliate
        UnitTB attacker = unit.GetNearestAttacker();

        if (attacker != null)
        {
            return(attacker.occupiedTile);
        }


        //no hostile unit within range
        if (aIStance == _AIStance.Active || aIStance == _AIStance.Trigger)
        {
            //no hostile detected at all, just move randomly
            if (allHostiles.Count == 0)
            {
                if (walkableTiles.Count > 0)
                {
                    int rand = UnityEngine.Random.Range(0, walkableTiles.Count);
                    return(walkableTiles[rand]);
                }
            }
            //get the nearest target and move towards it
            else
            {
                int nearest   = 999999999;
                int nearestID = 0;
                for (int i = 0; i < allHostiles.Count; i++)
                {
                    int dist = GridManager.Distance(unit.occupiedTile, allHostiles[i].occupiedTile);
                    if (dist < nearest)
                    {
                        nearest   = dist;
                        nearestID = i;
                    }
                }
                return(allHostiles[nearestID].occupiedTile);
            }
        }

        return(null);
    }