コード例 #1
0
ファイル: EnemyAiAggressive.cs プロジェクト: maxxyh/Elsewhere
    public override IEnumerator Execute()
    {
        map.FindSelectableTiles(currUnit.currentTile, currUnit.stats[StatString.MOVEMENT_RANGE].Value);

        yield return(new WaitForSecondsRealtime(0.75f));

        List <Tile> targets      = turnScheduler.players.ConvertAll(x => x.currentTile);
        Tile        targetTile   = AStarSearch.GeneratePathToNearestTarget(map, currUnit.currentTile, targets, false, true);
        Unit        targetPlayer = turnScheduler.players.Find(x => x.currentTile == targetTile);

        // check if target tile is selectable, and also go as far from movement range as possible
        int distanceFromTarget = 0, attackRange = (int)currUnit.stats[StatString.ATTACK_RANGE].Value;

        while ((!targetTile.selectable || distanceFromTarget < attackRange) && targetTile != currUnit.currentTile)
        {
            distanceFromTarget++;
            targetTile = targetTile.parent;
        }

        // A star movement towards the target
        currUnit.GetPathToTile(targetTile);

        yield return(new WaitUntil(() => currUnit.CurrState == UnitState.IDLING));

        // check if there are players in range
        if (map.PlayerTargetInAttackRange(currUnit.currentTile, currUnit.stats[StatString.ATTACK_RANGE].Value, targetPlayer))
        {
            currUnit.attackingTargetUnit = targetPlayer;
            turnScheduler.SetState(new EnemyAttack(turnScheduler));
        }
        else
        {
            turnScheduler.SetState(new EnemyEndTurn(turnScheduler));
        }
    }
コード例 #2
0
    public override IEnumerator Execute()
    {
        map.FindSelectableTiles(currUnit.currentTile, currUnit.stats[StatString.MOVEMENT_RANGE].Value);

        yield return(new WaitForSecondsRealtime(0.25f));

        List <Tile> targets      = turnScheduler.players.ConvertAll(x => x.currentTile);
        Tile        targetTile   = AStarSearch.GeneratePathToNearestTarget(map, currUnit.currentTile, targets, false, true);
        Unit        targetPlayer = turnScheduler.players.Find(x => x.currentTile == targetTile);

        // check if target tile is selectable, and also go as far from movement range as possible
        int cautiousRange = 2;

        while (!targetTile.selectable || targetTile.distance > cautiousRange)
        {
            targetTile = targetTile.parent;
        }

        // A star movement towards the target, 70% of the time, 10% of time will choose a random target and go
        int chance = new Random().Next(1, 100);

        if (chance <= 70)
        {
            currUnit.GetPathToTile(targetTile);
        }
        else if (chance >= 90)
        {
            List <Tile> closeTiles = map.GetSelectableTiles().ToList().FindAll(tile => tile.distance <= 2);
            targetTile = closeTiles[new Random().Next(0, closeTiles.Count - 1)];
            currUnit.GetPathToTile(targetTile);
        }

        yield return(new WaitUntil(() => currUnit.CurrState == UnitState.IDLING));

        turnScheduler.SetState(new EnemyEndTurn(turnScheduler));
    }
コード例 #3
0
ファイル: EnemyAiManager.cs プロジェクト: maxxyh/Elsewhere
    // decide order of movement
    // decide who is in recovery mode
    // decide who is going to heal those in recovery mode
    public LinkedList <Unit> StartTurn(List <PlayerUnit> players, List <EnemyUnit> enemies, Map map, LinkedList <Unit> currTeamQueue)
    {
        UpdateGameState(players, enemies, map);

        List <EnemyUnit> unitsInRecoveryMode = new List <EnemyUnit>();

        // Assign recovery mode
        foreach (EnemyUnit enemyUnit in enemies)
        {
            if (enemyUnit.IsRecoveryMode() && enemyUnit.selfHealingAbilities.Count == 0)
            {
                unitsInRecoveryMode.Add(enemyUnit);
            }
        }

        Queue <EnemyUnit> unassignedMedics   = new Queue <EnemyUnit>(medics);
        List <EnemyUnit>  remainingHurtUnits = new List <EnemyUnit>(unitsInRecoveryMode);

        medics.ForEach(unit => unit.ResetMedicStatus());

        // Assign targets to medics = will keep running as long as there are there are both unassignedHurtUnits and unassignedMedics
        while (unitsInRecoveryMode.Count > 0 && unassignedMedics.Count > 0)
        {
            EnemyUnit        currMedic   = unassignedMedics.Dequeue();
            bool             foundTarget = false;
            List <EnemyUnit> remainingHurtUnitsToSearch = new List <EnemyUnit>(unitsInRecoveryMode);

            while (!foundTarget && remainingHurtUnitsToSearch.Count > 0)
            {
                // Find closest target
                Tile targetTile = AStarSearch.GeneratePathToNearestTarget(map, currMedic.currentTile,
                                                                          remainingHurtUnitsToSearch.ConvertAll(input => input.currentTile), false, true);
                EnemyUnit medicTarget = unitsInRecoveryMode.Find(unit => unit.currentTile == targetTile);

                // if already assigned to another medic, compare relative distance
                if (!remainingHurtUnits.Contains(medicTarget))
                {
                    EnemyUnit oldMedic = medics.Find(unit => unit.medicTarget == medicTarget);
                    if (targetTile.distance < oldMedic.distanceToMedicTarget)
                    {
                        currMedic.medicTarget           = medicTarget;
                        currMedic.distanceToMedicTarget = targetTile.distance;
                        oldMedic.ResetMedicStatus();
                        unassignedMedics.Enqueue(oldMedic);
                        foundTarget = true;
                    }
                    else
                    {
                        remainingHurtUnitsToSearch.Remove(medicTarget);
                    }
                }

                // new target, has not been assigned a medic
                else
                {
                    currMedic.medicTarget           = medicTarget;
                    currMedic.distanceToMedicTarget = targetTile.distance;
                    foundTarget = true;
                    remainingHurtUnits.Remove(medicTarget);
                }
            }
        }

        LinkedList <Unit> updatedCurrTeamQueue = new LinkedList <Unit>(currTeamQueue);

        // Reorder the queue: hurt people first, then medics
        foreach (Unit hurtUnit in unitsInRecoveryMode.FindAll(unit => !remainingHurtUnits.Contains(unit)))
        {
            updatedCurrTeamQueue.Remove(hurtUnit);
            updatedCurrTeamQueue.AddFirst(hurtUnit);
        }

        return(updatedCurrTeamQueue);
    }