예제 #1
0
    public override void Execute()
    {
        ExecuteMethod.OnceInUpdate("SquadChildFSM.UpdateLandmineList", null, null);

        m_scFSM.Strafing();

        // if: There is more landmine than the production child count
        if (SquadChildFSM.ListLandmine.Count >= SquadChildFSM.StateCount(SCState.Produce))
        {
            for (int i = 0; i < SquadChildFSM.ListLandmine.Count; i++)
            {
                if (Vector3.Distance(SquadChildFSM.ListLandmine[i].transform.position, m_scFSM.transform.position) < 2f)
                {
                    m_scFSM.Advance(SCState.Avoid);
                    return;
                }
            }
        }
        // else if: There is lesser landmine state BUT not 0
        else if (SquadChildFSM.ListLandmine.Count != 0)
        {
            for (int i = 0; i < SquadChildFSM.ListLandmine.Count; i++)
            {
                if (Vector3.Distance(SquadChildFSM.ListLandmine[i].transform.position, m_scFSM.transform.position) < 2f)
                {
                    m_scFSM.Advance(SCState.Attack);
                    return;
                }
            }
        }
    }
예제 #2
0
    // Co-Routines
    IEnumerator SpawnRoutine()
    {
        bIsProduce = true;
        this.CalculateCooldown();
        while (bIsProduce)
        {
            yield return(new WaitForSeconds(fNextCooldown));

            if (SquadChildFSM.StateCount(SCState.Produce) != 0)
            {
                if (!this.CalculateCooldown())
                {
                    bIsProduce = false;
                }
                else
                {
                    SquadChildFSM.Spawn(transform.position);
                    mAnimate.ExpandContract(0.5f, 1, 1.3f);
                }
            }
            else
            {
                bIsProduce = false;
            }
        }
    }
예제 #3
0
    /// <summary>
    /// Advance _chance amount of alive cells to _nextsState
    /// </summary>
    /// <returns><c>true</c> There was transition happening <c>false</c> There wasn't any transition happening </returns>
    /// <param name="_nextState"> The state in which the squad child advances to </param>
    /// <param name="_chance"> The chance in which the squad child cell will advance </param>
    public static bool AdvanceSquadPercentage(SCState _nextState, float _chance)
    {
        // if: All the alive child is the _nextstate state
        if (SquadChildFSM.AliveCount() == SquadChildFSM.StateCount(_nextState))
        {
            return(false);
        }

        // for: Checksthrough all the child in the array
        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            if (s_array_SquadChildFSM[i].EnumState != SCState.Dead)
            {
                // if: the current cell type is NOT the targeted cell type, as transition would be useless
                if (s_array_SquadChildFSM[i].EnumState != _nextState)
                {
                    // if: The it is within the chance range
                    if (UnityEngine.Random.value <= _chance)
                    {
                        s_array_SquadChildFSM[i].Advance(_nextState);
                    }
                }
            }
        }
        return(true);
    }
예제 #4
0
    /// <summary>
    /// Advance all squad in the state _currentState to _nextState by a certain amount of _chance
    /// </summary>
    /// <param name="_currentState"> the state of squad child which would be advancing </param>
    /// <param name="_nextState"> The state that the squad child cell will advance towards </param>
    /// <param name="_chance"> The chance of which the squad child cell will advance </param>
    public static bool AdvanceSquadPercentage(SCState _currentState, SCState _nextState, float _chance)
    {
        if (_currentState == _nextState)
        {
            return(false);
        }
        else if (SquadChildFSM.StateCount(_currentState) == 0)
        {
            return(false);
        }

        // for: Checks through all the child in the array
        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            // if: The current cell type is the trageted cell type
            if (s_array_SquadChildFSM[i].EnumState == _currentState)
            {
                // if: The it is within the chance range
                if (UnityEngine.Random.value <= _chance)
                {
                    s_array_SquadChildFSM[i].Advance(_nextState);
                }
            }
        }
        return(true);
    }
예제 #5
0
    // Public Functions
    // Think(): The think process of the Squad Captain. Call this method to return the desire state that the SquadCaptain should be in
    public void Think()
    {
        // if: Restricts the brain from think too much
        if (fCurrentThinkCooldown >= fThinkCooldown)
        {
            fCurrentThinkCooldown = 0f;
        }
        else
        {
            fCurrentThinkCooldown += Time.deltaTime;
            return;
        }

        // Squad Child Cells Count Check
        // if: The number of alive squad child is less than fMininumChildCount <--------------------------------------------- DEPERATE TIMES
        if (PlayerSquadFSM.Instance.AliveChildCount() < nMinimumChildProducing)
        {
            SquadChildFSM.AdvanceSquadPercentage(SCState.Produce, 1f);
            m_PlayerSquadFSM.Advance(PSState.Produce);
        }
        // else if: There is more than enough child cells producing, moves to idle <----------------------------------------- RECOVERY
        else if (SquadChildFSM.StateCount(SCState.Produce) > nMaximumChildProducing)
        {
            SquadChildFSM.AdvanceSquadPercentage(SCState.Produce, SCState.Idle, 0.75f);
        }

        // if: There is child idling, assign them to defence <-------------------------------------------------------------- ASSIGN JOB
        if (SquadChildFSM.StateCount(SCState.Idle) > 0)
        {
            // if: Aggressive is triggered
            if (UnityEngine.Random.value > fAggressiveToDefensive)
            {
                SquadChildFSM.AdvanceSquadPercentage(SCState.Idle, SCState.Attack, 1f);
            }
            else if (SquadChildFSM.StateCount(SCState.Defend) < nMaximumChildDefence)
            {
                // nPredictedCount: The predicted number of defence cells it would have
                int nPredictedCount = (int)((float)SquadChildFSM.StateCount(SCState.Idle) * (1f - fAggressiveToDefensive)) + SquadChildFSM.StateCount(SCState.Defend);

                // if: The current predicted count is more that its requirement AND there is room to spawn more defence
                if (nPredictedCount > nMinimumIdleToDefence && SquadChildFSM.StateCount(SCState.Defend) < nMaximumChildDefence)
                {
                    SquadChildFSM.AdvanceSquadPercentage(SCState.Idle, SCState.Defend, 1f - fAggressiveToDefensive);
                }
            }
        }

        // if: There is no child cells producing but it is still important to do it <-------------------------------------- ASSIGN JOB
        if (SquadChildFSM.StateCount(SCState.Produce) == 0 && SquadChildFSM.AliveCount() < nOptionalToProduceAt)
        {
            SquadChildFSM.AdvanceSquadPercentage(SCState.Produce, 0.2f);
        }

        // if: There is extra child in Idle and the player have relatively low amount of resource
        if (SquadChildFSM.StateCount(SCState.Idle) >= nAmountIdleBeforeConsider && player_control.Instance.s_nResources <= nNeedNutrients)
        {
            SquadChildFSM.AdvanceSquadPercentage(SCState.Idle, SCState.FindResource, 0.75f);
        }
    }
예제 #6
0
    // GetNearestTargetPosition(): Assign a target to aggressive squad child cells.
    public static bool GetNearestTargetPosition()
    {
        // if: There are no attacking squad children
        if (SquadChildFSM.StateCount(SCState.Attack) == 0)
        {
            return(false);
        }

        s_list_enemyChild = EnemyMainFSM.Instance().ECList;

        // if: There is no enemy child cells to attack
        if (s_list_enemyChild.Count == 0)
        {
            for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
            {
                if (s_array_SquadChildFSM[i].EnumState == SCState.Attack)
                {
                    s_array_SquadChildFSM[i].Advance(SCState.Idle);
                }
            }
            return(false);
        }

        // for: Resets all the attackTarget of all squad children
        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            s_array_SquadChildFSM[i].attackTarget = null;
        }

        // for: Every enemy child in the list...
        for (int i = 0; i < s_list_enemyChild.Count; i++)
        {
            // for: Finds a squad children in the list...
            for (int j = 0; j < s_array_SquadChildFSM.Length; j++)
            {
                // if: The current squad children is attacking and it has no target
                if (s_array_SquadChildFSM[j].EnumState == SCState.Attack && s_array_SquadChildFSM[j].attackTarget == null)
                {
                    s_array_SquadChildFSM[j].attackTarget = s_list_enemyChild[i];
                }
            }
        }

        // for: This for loops returns all attacking squad children to idle when they have no target
        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            if (s_array_SquadChildFSM[i].EnumState == SCState.Attack && s_array_SquadChildFSM[i].attackTarget == null)
            {
                s_array_SquadChildFSM[i].Advance(SCState.Idle);
            }
        }
        return(true);
    }
예제 #7
0
    // CalculateDefenceSheildOffset(): Calling this method will recalculates all defence offsets for all defence cells
    public static bool CalculateDefenceSheildOffset()
    {
        // Resets all the strafing offset to 0
        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            s_array_SquadChildFSM[i].fDefenceOffsetAngle = 0f;
        }

        // if: There is no squad cells in defence state
        if (StateCount(SCState.Defend) == 0)
        {
            return(false);
        }

        int defenceCount = SquadChildFSM.StateCount(SCState.Defend);

        // if: there is only 1 defence cell
        if (defenceCount == 1)
        {
            for (int i = 0; i < defenceCount; i++)
            {
                if (s_array_SquadChildFSM[i].EnumState == SCState.Defend)
                {
                    s_array_SquadChildFSM[i].fDefenceOffsetAngle = 0.5f * fDefenceAngle;
                    return(true);
                }
            }
            return(false);
        }
        else
        {
            // for: Calculates the distribution of the angle offset from the main vector
            int j = 0;
            for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
            {
                if (s_array_SquadChildFSM[i].EnumState == SCState.Defend)
                {
                    s_array_SquadChildFSM[i].fDefenceOffsetAngle = j / (defenceCount - 1f) * fDefenceAngle;
                    j++;
                }
                // if: The loop have checked through all defence state cells, then it would break the loop
                if (j == defenceCount)
                {
                    break;
                }
            }
            return(true);
        }
    }
예제 #8
0
    // Update(): is called once every frame
    void Update()
    {
        // Pre-Execution
        if (SquadChildFSM.StateCount(SCState.Produce) > 0)
        {
            if (!bIsProduce)
            {
                StartCoroutine("SpawnRoutine");
            }
        }

        // Execution
        m_CurrentState.Execute();

        // Post-Execution
    }
예제 #9
0
    // CalculateStrafingOffset(): Calling this method will recalculate all strafing offsets for all production cells
    public static bool CalculateStrafingOffset()
    {
        // Resets all the strafing offset to 0
        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            s_array_SquadChildFSM[i].fStrafingOffsetAngle = 0f;
        }

        // if: There is no squad child cells in produce state
        if (StateCount(SCState.Produce) == 0)
        {
            return(false);
        }

        int produceCount = SquadChildFSM.StateCount(SCState.Produce);
        // for: Calculates strafing angle for squad child cells that are in production state
        // Calculation: Angles are split equally among each cells, which is also based on the number of production cells
        //              1 cell = 360 deg apart, 2 cells = 180 deg apart, 3 cells = 120 deg apart, 4 cells = 90 deg apart...
        int j = 0;

        for (int i = 0; i < s_array_SquadChildFSM.Length; i++)
        {
            if (s_array_SquadChildFSM[i].EnumState == SCState.Produce)
            {
                s_array_SquadChildFSM[i].fStrafingOffsetAngle = 360f / produceCount * j;
                j++;
            }
            // if: The loop have checked through all production state cells, then it would break the loop
            if (j == produceCount)
            {
                break;
            }
        }

        return(true);
    }
예제 #10
0
    // DefenceSheild(): Handles the movement when the cells in defence state
    public bool DefenceSheild()
    {
        if (m_currentEnumState != SCState.Defend)
        {
            Debug.LogWarning(gameObject.name + ".SquadChildFSM.DefenceSheild(): Current state is not SCState.Defend! Ignore Defence!");
            return(false);
        }

        // if: There is lesser defence child than it have
        if (SquadChildFSM.StateCount(SCState.Defend) < nDefenceMinimumCount)
        {
            SquadChildFSM.AdvanceSquadPercentage(SCState.Defend, SCState.Idle, 1f);
        }

        Vector3 toTargetPosition = Quaternion.Euler(0f, 0f, -fDefenceOffsetAngle) * mainDefenceVector + playerPosition - transform.position;

        if (toTargetPosition.magnitude > fDefenceRigidity)
        {
            m_RigidBody.AddForce(toTargetPosition * Time.deltaTime * fDefenceSpeed);
        }
        m_RigidBody.velocity = Vector3.ClampMagnitude(m_RigidBody.velocity, Mathf.Max(fDefenceRigidity, toTargetPosition.magnitude));

        return(true);
    }
예제 #11
0
    // CalculateCooldown(): Call this function to re-calculate the cooldown of production
    public bool CalculateCooldown()
    {
        fNextCooldown = (fMaximumCooldown - fMinimumCooldown) * ((float)(nMaximumChildCount - SquadChildFSM.StateCount(SCState.Idle)) / (float)nMaximumChildCount) + fMinimumCooldown;

        if (fNextCooldown <= 0f)
        {
            Debug.LogWarning(this.name + ".CalculateCooldown: fNextCooldown is less than or equal to 0! fNextCooldown = " + fNextCooldown);

            fNextCooldown = 0.0f;
            return(false);
        }
        else
        {
            return(true);
        }
    }