コード例 #1
0
    /// <summary>
    /// Called by the OnEnemyTurnEnd event from EnemyMoveAttackAI after all enemies have moved.
    /// Starts Players Turn, Enables player to control characters
    /// </summary>
    private void StartPlayerTurn()
    {
        //Debug.Log("StartPlayerTurn");
        _endTurnButt.interactable = true;
        _state = TurnState.PLAYERTURN;
        // We reset the turns of all characters
        // Allies
        foreach (Transform allyTrans in _allyParent)
        {
            MoveAttack allyMA = allyTrans.GetComponent <MoveAttack>();
            if (allyMA != null)
            {
                allyMA.ResetMyTurn();
            }
            else
            {
                Debug.LogError("There is no MoveAttack script attached to " + allyTrans.name);
            }
        }
        // Enemies
        foreach (Transform enemyTrans in _enemyParent)
        {
            MoveAttack enemyMA = enemyTrans.GetComponent <MoveAttack>();
            if (enemyMA != null)
            {
                enemyMA.ResetMyTurn();
            }
            else
            {
                Debug.LogError("There is no MoveAttack script attached to " + enemyTrans.name);
            }
        }

        // Call the event that the player's turn has begun
        if (OnBeginPlayerTurn != null)
        {
            //Debug.Log("OnBeginPlayerTurn");
            OnBeginPlayerTurn();
        }
    }
コード例 #2
0
    /// <summary>
    /// Takes the turn of the enemy
    /// </summary>
    public void TakeTurn()
    {
        // Reset my turn
        _mARef.ResetMyTurn();

        // Get the node this enemy is standing on
        _standingNode = _mAContRef.GetNodeByWorldPosition(this.transform.position);
        // We are going to use the enemy's move tiles, so we need to recalculate those,
        // since other characters have probably moved on their turn
        _mARef.CalculateAllTiles();
        // Find the tile the enemy should move to
        Node nodeToMoveTo = FindTileToMoveTo();

        // Make sure we have a place to move
        if (nodeToMoveTo != null)
        {
            // After the enemy finishes moving, it will call the CharacterFinishedMovingEvent.
            // So we add the BeginAttemptAction function to be called when that event is called.
            // It will remove itself from the event once it is called.
            // The idea is that only one function will be attached to that event at a time (will belong to current character)
            MoveAttack.OnCharacterFinishedMoving += BeginAttemptAction;
            // Start moving the enemy
            MoveToTile(nodeToMoveTo);

            /// We want the enemy's turn to look like Move, Action, End.
            /// But we only call MoveToTile above.
            /// This is because we need the enemy to finish moving before it does its action.
            /// Action is called when the character finishes moving.
            /// Similarly, End is called when the character finishes its action.
        }
        // If we have no where to move, just finish this enemy's turn
        else
        {
            // Call the finish enemy turn event
            if (OnSingleEnemyFinish != null)
            {
                OnSingleEnemyFinish();
            }
        }
    }
コード例 #3
0
    /// <summary>
    /// Finds and returns the tile this enemy should move to.
    /// Find the closest tile they can heal an enemy from
    /// </summary>
    /// <returns>Node that this enemy should move to</returns>
    override protected Node FindTileToMoveTo()
    {
        //Debug.Log("------------------------------------------");
        //Debug.Log("Start Node " + StandingNode.Position);
        // 1) Get closest enemy node that can be healed
        Node closestEnemyNode = null;
        int  closestEnemyF    = int.MaxValue;
        Node closestHealNode  = null;
        int  closestHealF     = int.MaxValue;

        // Iterate over each enemy to find the closest
        foreach (Transform charTrans in GetEnemyParent())
        {
            // Only if the enemy is active and not this character
            if (charTrans.gameObject.activeInHierarchy && charTrans != this.transform)
            {
                // We only want to try moving there is the enemy is damaged
                Health charHealth = charTrans.GetComponent <Health>();
                if (charHealth.CurHP < charHealth.MaxHP)
                {
                    Node charNode = MAContRef.GetNodeByWorldPosition(charTrans.position);
                    // Path to that enemy
                    MAContRef.Pathing(StandingNode, charNode, CharacterType.Enemy, false);

                    // FOR TESTING
                    //Vector2Int printPos = new Vector2Int(int.MaxValue, int.MaxValue);
                    //if (closestAllyNode != null)
                    //    printPos = closestAllyNode.Position;
                    //Debug.Log(charNode.Position + " with " + charNode.F + " is being compared with " + printPos + " with " + closestAllyF);

                    // If it is closer than the currently closest enemy
                    if (closestEnemyF > charNode.F)
                    {
                        int charFVal = charNode.F;
                        //Debug.Log("It was closer in distance");

                        // 2) Get the closest node this enemy could heal that enemy from
                        // We know that is enemy is closer in walking distance, but we don't know if they have any openings to heal
                        // So we test to see if we can find any openings to heal
                        // Get the potential nodes to heal from
                        List <Node> potHealNodes = MAContRef.GetNodesDistFromNode(charNode, MARef.AttackRange);
                        // Figure out which is closest to the standing positions
                        //Debug.Log("The attack nodes are at ");
                        foreach (Node curAdjNode in potHealNodes)
                        {
                            //Debug.Log(curAdjNode.Position);
                            // If the node is not occupied by someone other than this enemy
                            // since if this enemy is standing next to an ally, obvious that ally is the closest
                            MoveAttack curAdjEnemyMARef = MAContRef.GetCharacterMAByNode(curAdjNode);
                            if (curAdjNode.Occupying == CharacterType.None || curAdjEnemyMARef == MARef)
                            {
                                // Path there, if succesful, then see if it is closer than the current attackfrom node
                                // We say we don't care if we can get there (shouldCare=false) because we have already
                                // checked if someone was there and if there is someone there, it would be this enemy
                                if (MAContRef.Pathing(StandingNode, curAdjNode, CharacterType.Enemy, false))
                                {
                                    // If it is closer than the closest attack from node
                                    if (closestHealF > curAdjNode.F)
                                    {
                                        //Debug.Log("It was closer and could be attacked");
                                        // It is the new closest enemy node
                                        closestEnemyNode = charNode;
                                        closestEnemyF    = charFVal;

                                        // It is the new closest heal node
                                        closestHealNode = curAdjNode;
                                        closestHealF    = curAdjNode.F;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // If there is no closest heal from node, make the enemy run away
        if (closestHealNode == null)
        {
            // Get the allies nodes before (we only want the allies who are close enough
            // that they could attack us on their next turn)
            List <Node> allyNodes = new List <Node>();
            foreach (Transform allyTrans in GetAllyParent())
            {
                Node curAllyNode = MAContRef.GetNodeByWorldPosition(allyTrans.position);
                // Calculate the distance between the ally's node and this enemy's node
                Vector2Int distVect = curAllyNode.Position - StandingNode.Position;
                int        dist     = Mathf.Abs(distVect.x + distVect.y);
                // Only add the ally if the enemy is within their attack range
                MoveAttack curAllyMA = MAContRef.GetCharacterMAByNode(curAllyNode);
                curAllyMA.ResetMyTurn();
                //Debug.Log("Dist from " + curAllyMA.name + ": " + dist + ". " + curAllyNode.Position + "->" + StandingNode.Position);
                if (dist <= curAllyMA.AttackRange + curAllyMA.MoveRange)
                {
                    //Debug.Log(curAllyMA.name + " is close enough to " + this.name);
                    allyNodes.Add(curAllyNode);
                }
            }
            // Set a reference to the node that is the farthest from all allies
            Node furthestNode = StandingNode;
            int  furthestF    = 0;
            // Get the move tiles of this enemy plus the node they are standing on
            List <Node> testNodes = new List <Node>(MARef.MoveTiles);
            testNodes.Add(StandingNode);
            // Iterate over this enemy's move tiles
            foreach (Node moveTile in testNodes)
            {
                int curAddedF = 0;
                // Path from each ally to the current tile
                foreach (Node curAllyNode in allyNodes)
                {
                    MAContRef.Pathing(curAllyNode, moveTile, CharacterType.Enemy, false);
                    curAddedF += moveTile.F;
                }
                // If the distance from each ally is greater than the last distance, it is the new furthest
                if (curAddedF > furthestF)
                {
                    furthestNode = moveTile;
                    furthestF    = curAddedF;
                }
            }

            // Return the furthest node
            return(furthestNode);
        }
        //Debug.Log("The closest ally is at " + closestAllyNode.Position);


        // Short cut. If the closest attack node is one of the moveTiles, just return it
        // Iterate over the possible tiles to move to
        if (MARef.MoveTiles != null)
        {
            foreach (Node moveTile in MARef.MoveTiles)
            {
                // If its a part of the movetiles
                if (moveTile == closestHealNode)
                {
                    return(closestHealNode);
                }
            }
        }
        else
        {
            Debug.LogError("MoveTiles is null");
        }


        // If the shortcut didn't work do it the long way
        Node closestNode = StandingNode;
        int  closestF    = int.MaxValue;

        if (MARef.MoveTiles != null)
        {
            // Iterate over the possible tiles to move to
            foreach (Node moveTile in MARef.MoveTiles)
            {
                // Path from that move tile to the closest attack node
                // If successful, check if its closer than the closestNode
                if (MAContRef.Pathing(moveTile, closestHealNode, CharacterType.Enemy))
                {
                    // It its closer, its the new closestNode
                    if (closestF > closestHealNode.F)
                    {
                        closestNode = moveTile;
                        closestF    = closestHealNode.F;
                    }
                }
            }
        }
        else
        {
            Debug.LogError("MoveTiles is null");
        }
        // Its the endtile
        return(closestNode);
    }