예제 #1
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);
    }