コード例 #1
0
        //move a single unit only
        IEnumerator SingleUnitRoutine(Unit unit)
        {
            GameControl.DisplayMessage("AI's Turn");

            yield return(new WaitForSeconds(0.1f));

            if (!unit.IsStunned())
            {
                Faction faction      = FactionManager.GetFaction(unit.factionID);
                _AIMode activeAIMode = !faction.useDefaultAIMode ? faction.aiMode : mode;

                while (unit.moveRemain > 0 || unit.CanAttack())
                {
                    StartCoroutine(MoveUnitRoutine(unit, activeAIMode));
                    while (movingUnit)
                    {
                        yield return(null);
                    }
                    if (unit == null)
                    {
                        break;
                    }
                    if (unit.attackRemain > 0 || unit.CanAttack())
                    {
                        yield return(new WaitForSeconds(.1f));
                    }
                }

                //~ StartCoroutine(MoveUnitRoutine(unit, activeAIMode));
                //~ while(movingUnit) yield return null;
                //~ yield return new WaitForSeconds(0.25f);
            }

            GameControl.EndTurn();
        }
コード例 #2
0
        //move the whole faction, unit by unit
        IEnumerator FactionRoutine(Faction faction)
        {
            GameControl.DisplayMessage("AI's Turn");
            yield return(new WaitForSeconds(0.3f));

            //create a new list so no unit will be skipped is one of them is somehow destroyed (by counter attack);
            List <Unit> unitList = new List <Unit>(faction.allUnitList);

            for (int i = 0; i < unitList.Count; i++)
            {
                AIDebug("Start moving unit " + unitList[i].gameObject.name);

                yield return(new WaitForSeconds(unitInterval));

                if (unitList[i].IsStunned())
                {
                    continue;
                }

                _AIMode activeAIMode = !faction.useDefaultAIMode ? faction.aiMode : mode;

                while (unitList[i].moveRemain > 0 || unitList[i].CanAttack())
                {
                    AIDebug("Moving unit " + unitList[i].gameObject.name + "     (move remain:" + (unitList[i].moveRemain > 0) + ", can attack:" + unitList[i].CanAttack() + ")");
                    StartCoroutine(MoveUnitRoutine(unitList[i], activeAIMode));
                    while (movingUnit)
                    {
                        yield return(null);
                    }
                    if (unitList[i] == null)
                    {
                        break;
                    }
                    if (unitList[i].moveRemain > 0 || unitList[i].CanAttack())
                    {
                        yield return(new WaitForSeconds(.1f));
                    }
                }

                //~ StartCoroutine(MoveUnitRoutine(unitList[i], activeAIMode));
                //~ while(movingUnit) yield return null;
                //~ yield return new WaitForSeconds(0.25f);

                if (GameControl.GetGamePhase() == _GamePhase.Over)
                {
                    yield break;
                }
            }

            GameControl.EndTurn();
        }
コード例 #3
0
        //analyse the grid to know where the unit should move to
        private Tile Analyse(Unit unit, _AIMode activeMode)
        {
            //get all wakable tiles in range first
            List <Tile> walkableTilesInRange = GridManager.GetTilesWithinDistance(unit.tile, unit.GetEffectiveMoveRange(), true);

            walkableTilesInRange.Add(unit.tile);

            //get all visible hostile
            List <Unit> allHostileInSight = FactionManager.GetAllHostileUnit(unit.factionID);

            if (GameControl.EnableFogOfWar())
            {
                for (int i = 0; i < allHostileInSight.Count; i++)
                {
                    if (!FogOfWar.IsTileVisibleToFaction(allHostileInSight[i].tile, unit.factionID))
                    {
                        allHostileInSight.RemoveAt(i);  i -= 1;
                    }
                }
            }

            //if cover system is in used
            if (GameControl.EnableCover())
            {
                Tile tile = AnalyseCoverSystem(unit, walkableTilesInRange, allHostileInSight);
                if (tile != null)
                {
                    return(tile);
                }
            }


            //if there are hostile
            if (allHostileInSight.Count > 0)
            {
                //fill up the walkableTilesInRange hostile list
                //then filter thru walkableTilesInRange, those that have a hostile in range will be add to a tilesWithHostileInRange
                List <Tile> tilesWithHostileInRange = new List <Tile>();
                GridManager.SetupHostileInRangeforTile(unit, walkableTilesInRange);
                for (int i = 0; i < walkableTilesInRange.Count; i++)
                {
                    if (walkableTilesInRange[i].GetHostileInRange().Count > 0)
                    {
                        tilesWithHostileInRange.Add(walkableTilesInRange[i]);
                    }
                }

                //if the tilesWithHostileInRange is not empty after the process, means there's tiles which the unit can move into and attack
                //return one of those in the tilesWithHostileInRange so the unit can attack
                if (tilesWithHostileInRange.Count > 0)
                {
                    //if the unit current tile is one of those tiles with hostile, just stay put and attack
                    if (tilesWithHostileInRange.Contains(unit.tile))
                    {
                        //randomize it a bit so the unit do move around but not stay in place all the time
                        if (Random.Range(0f, 1f) > 0.25f)
                        {
                            return(unit.tile);
                        }
                    }
                    return(tilesWithHostileInRange[Random.Range(0, tilesWithHostileInRange.Count)]);
                }
            }


            //if there's not potential target at all, check if the unit has any previous attacker
            //if there are, go after the last attacker
            if (unit.lastAttacker != null)
            {
                return(unit.lastAttacker.tile);
            }


            //for aggresive mode with FogOfWar disabled, try move towards the nearest unit
            if (activeMode == _AIMode.Aggressive && Random.Range(0f, 1f) > 0.25f)
            {
                List <Unit> allHostile = FactionManager.GetAllHostileUnit(unit.factionID);
                float       nearest = Mathf.Infinity;   int nearestIndex = 0;
                for (int i = 0; i < allHostile.Count; i++)
                {
                    float dist = GridManager.GetDistance(allHostile[i].tile, unit.tile);
                    if (dist < nearest)
                    {
                        nearest      = dist;
                        nearestIndex = i;
                    }
                }
                return(allHostile[nearestIndex].tile);
            }


            //if there's really no hostile to go after, then just move randomly in one of the walkable
            int rand = Random.Range(0, walkableTilesInRange.Count);

            //clear in hostileInRange list for all moveable tile so, just in case the list is not empty (hostileInRange dont clear after each move)
            //so the unit dont try to attack anything when it moves into the targetTile
            walkableTilesInRange[rand].SetHostileInRange(new List <Tile>());

            return(walkableTilesInRange[rand]);
        }
コード例 #4
0
        private bool movingUnit = false;                //set to true when a unit is being moved
        IEnumerator MoveUnitRoutine(Unit unit, _AIMode activeMode)
        {
            TBTK.OnUnitSelected(unit);

            movingUnit = true;
            //Debug.Log("moving unit");
            if (activeMode != _AIMode.Aggressive && !unit.trigger)
            {
                AIDebug("unit " + unit.gameObject.name + " is not triggered");
                if (!untriggeredUnitMove)
                {
                    StartCoroutine(EndMoveUnitRoutine());
                    unit.moveRemain = 0;      unit.attackRemain = 0;
                }
                else
                {
                    if (Random.value < 0.5f)
                    {
                        StartCoroutine(EndMoveUnitRoutine());
                        unit.moveRemain = 0;      unit.attackRemain = 0;
                    }
                    else
                    {
                        AIDebug("Randomly move unit " + unit.gameObject.name + " anyway");
                        List <Tile> walkableTilesInRange = GridManager.GetTilesWithinDistance(unit.tile, Mathf.Min(1, unit.GetEffectiveMoveRange() / 2), true);
                        if (walkableTilesInRange.Count > 0)
                        {
                            unit.Move(walkableTilesInRange[Random.Range(0, walkableTilesInRange.Count)]);
                        }
                    }
                }
                AIDebug("End unit " + unit.gameObject.name + " turn");
                StartCoroutine(EndMoveUnitRoutine());
                yield break;
            }

            Tile targetTile = Analyse(unit, activeMode);


            if (CameraControl.CenterOnSelectedUnit())
            {
                bool visible = false;
                if (unit.tile.IsVisible())
                {
                    visible = true;
                }
                else if (targetTile != unit.tile)
                {
                    List <Tile> path = unit.GetPathForAI(targetTile);
                    for (int i = 0; i < path.Count; i++)
                    {
                        if (path[i].IsVisible())
                        {
                            visible = true;
                            break;
                        }
                    }
                    targetTile = path[path.Count - 1];
                    Debug.DrawLine(unit.tile.GetPos(), targetTile.GetPos(), Color.red, 2);
                }

                if (visible)
                {
                    CameraControl.OnUnitSelected(unit, false);
                    while (CameraControl.IsLerping())
                    {
                        yield return(null);
                    }
                }
            }


            //first move to the targetTile
            if (targetTile != unit.tile)
            {
                unit.Move(targetTile);
                yield return(new WaitForSeconds(.1f));                  //wait until the unit has moved into the targetTile

                while (!TurnControl.ClearToProceed())
                {
                    //AIDebug("waiting, unit "+unit.gameObject.name+" is moving");
                    AIDebug("waiting while unit is moving");
                    yield return(null);
                }
            }

            if (unit == null || unit.HP <= 0)           //in case unit is destroyed by overwatch
            {
                StartCoroutine(EndMoveUnitRoutine());
                yield break;
            }

            for (int i = 0; i < targetTile.hostileInRangeList.Count; i++)
            {
                if (targetTile.hostileInRangeList[i].unit == null || targetTile.hostileInRangeList[i].unit.factionID == unit.factionID)
                {
                    targetTile.hostileInRangeList.RemoveAt(i);              i -= 1;
                }
            }

            //if there's hostile within range, attack it
            if (targetTile.hostileInRangeList.Count > 0)
            {
                if (unit.CanAttack())
                {
                    AIDebug("waiting, unit " + unit.gameObject.name + " is attacking");

                    //~ if(targetTile!=unit.tile){	//wait until the unit has moved into the targetTile
                    //~ yield return new WaitForSeconds(.25f);
                    //~ while(!TurnControl.ClearToProceed()) yield return null;
                    //~ }

                    int rand = Random.Range(0, targetTile.hostileInRangeList.Count);
                    unit.Attack(targetTile.hostileInRangeList[rand].unit);
                }
                else
                {
                    if (unit.moveRemain > 0)
                    {
                        unit.moveRemain -= 1;
                    }
                }
            }
            else
            {
                if (unit.moveRemain <= 0)
                {
                    unit.attackRemain = 0;
                }
            }

            AIDebug("End unit " + unit.gameObject.name + " turn");
            StartCoroutine(EndMoveUnitRoutine());

            yield return(null);
        }