// Use this for initialization
 void Start()
 {
     sp        = gameObject.GetComponent <SpriteRenderer>();
     anm       = gameObject.GetComponent <Animator>();
     patrolA   = transform.position;
     eCurState = BossActions.Patrolling;
 }
 //Moves from left to right, can do whatever when it reaches a point of its patrol.
 void Patrol()
 {
     anm.SetBool("isMoving", true);
     if (patrolA.x == transform.position.x)
     {
         moveUp = true;
         if (Flips)
         {
             direction = -direction;
             Flip();
             eCurState = BossActions.Idle;
         }
     }
     if (patrolB.x == transform.position.x)
     {
         moveUp = false;
         if (Flips)
         {
             direction = -direction;
             Flip();
             eCurState = BossActions.Idle;
         }
     }
     if (moveUp)
     {
         transform.position = Vector2.MoveTowards(transform.position, patrolB, speed);
     }
     else
     {
         transform.position = Vector2.MoveTowards(transform.position, patrolA, speed);
     }
 }
    //And drops on them, dealing damage.
    void Fall()
    {
        anm.Play("Fall");
        Vector3 fallPos = new Vector3(transform.position.x, -2);

        transform.position = Vector2.MoveTowards(transform.position, fallPos, jumpSpeed * 0.5f);
        if (transform.position.y <= -2)
        {
            anm.Play("FallRecover");
            eCurState = BossActions.Idle;
        }
    }
Beispiel #4
0
    // 행동이 종료될 때까지 기다림
    private IEnumerator WaitForNextAction(BossActions _waitingAction, BossActions _nextAction, bool _conditionOfNextAction)
    {
        if (_waitingAction != BossActions.Finish)
        {
            while (action[_waitingAction].enabled)
            {
                yield return(new WaitForFixedUpdate());
            }
        }

        if (!_nextAction.Equals(BossActions.Finish))
        {
            ActionControl(_nextAction, true);
            action[_nextAction].Action(_conditionOfNextAction);
            StartCoroutine(WaitForNextAction(_nextAction, BossActions.Finish, false));
        }
        else
        {
            // 모든 행동이 끝나면 최초 조건으로 돌아감
            Action();
        }
    }
Beispiel #5
0
    // Used with action que.
    //private bool Aggresive(Vector3 a_directionToMove)
    //{
    //    // Am I in range to launch attack or am I already
    //    // attacking?
    //    if (CalculateDistance(a_directionToMove) || m_continue)
    //    {
    //        // So you're at the correct distance
    //        // Stop your movement.
    //        m_animator.SetFloat("Movement/Z", 0);
    //        m_animator.SetFloat("Movement/X", 0);


    //        // So launch attack if facing correct direction
    //        if (!m_continue && CorrectFacing(a_directionToMove))
    //        {
    //            m_animator.SetInteger("Ai/Action", m_actionQue[0].GetAnimNum);
    //            m_continue = true;
    //            return false;
    //        }
    //        else
    //        {
    //            // If attack variants would need to check what ones to go down somewhere
    //            // Or do internal logic on state machine.
    //            if (!m_animator.GetBool("Ai/PlayingAction") && m_continue)
    //            {
    //                ResetState();
    //                return true;
    //            }
    //            else
    //            {
    //                return false;
    //            }
    //        }
    //    }
    //    else
    //    {
    //        AddSeek(a_directionToMove);
    //        return false;
    //    }
    //}

    // Move towards target by default.
    // Needs to evaluate an animation if special
    // ability time limit is triggered.

    private bool Seek(Vector3 a_directionToMove)
    {
        // Check if within range or currently playing action
        if (CalculateDistance(a_directionToMove) && !m_animator.GetBool("Ai/PlayingAction"))
        {
            return(true);
        }

        // Needs to check if it's time to do an action like dodge forward ect
        if (m_timeOutSeek < Time.time)
        {
            // Set time for next evaluation
            m_timeOutSeek = Time.time + m_bossPhaseList[m_currentPhase].m_timeBetweenMovementAction;
            // Evaluate action
            BossActions t = m_bossPhaseList[m_currentPhase].EvaluateSeek(GetDistanceToPlayer(a_directionToMove), m_desiredRange);
            // If action is returned instantly do action
            if (t != null)
            {
                // Do the action straight away
                m_animator.SetInteger("Ai/Action", t.GetAnimNum);
                // Should set plaing action to true.
                return(false);
            }
            // Else seek towards player still.
        }

        // If not time boss will walk towards target.
        a_directionToMove = this.transform.worldToLocalMatrix * a_directionToMove.normalized;
        m_animator.SetFloat("Movement/Z", a_directionToMove.z);
        m_animator.SetFloat("Movement/X", a_directionToMove.x);
        m_animator.SetInteger("Ai/Action", 0);
        // Should always get the animation speed multiplyer
        //m_animator.SetFloat("AnimationSpeedMultiplyer", 2);

        // Has not reached target.
        return(false);
    }
Beispiel #6
0
    // Seeks to desired range. Since seeks don't require a range this probably works.
    //public BossActions EvaluateSeek(float a_distanceToTarget, float m_desiredRange)
    //{
    //    BossActions output = null;
    //    foreach (BossActions t in m_bossActions)
    //    {
    //        if(t.GetBehaviourType == SteeringBehaviours.SEEK_BEHAVIOUR)
    //        {
    //            // from 10 to 0       Range from 020    0 or neg * 5
    //            // optimal distance, coolness factor, timeused
    //            // Weighing happens here
    //            // If desirability is greater than previous replace.
    //            // bossaction
    //            // Only here to test
    //            output = t;
    //            break;
    //        }
    //        // Adjust the weighing values of the list
    //    }
    //    return output;
    //}

    // Seek to desired target.
    // Think point to point movement with animations
    public BossActions EvaluateSeek(float a_distanceToTarget, float m_desiredRange)
    {
        // Chosen action
        BossActions output = null;
        // If it's good it goes here to be chosen later.
        List <BossActions> desired = new List <BossActions>();
        // If the move does not benefit but can be done.
        List <BossActions> neutral = new List <BossActions>();

        foreach (BossActions t in m_bossActions)
        {
            // List to be populated.
            // Behaviors are seeks therefore we should be checking
            // if they put the boss in a good position.
            if (t.GetBehaviourType == SteeringBehaviours.SEEK)
            {
                // If the distance covered is beneficial or negligalble
                // does the movement get the boss closer or further?
                float distanceCovered = t.GetDestinationDistance;
                // Need to check if the distance covered is beneficial

                float resultingDistanceWhenMoveUsed = a_distanceToTarget - distanceCovered;

                // Should be passed in by action.

                float rangeThreshold = 2;

                // Check if the moves result is neutral.
                if (resultingDistanceWhenMoveUsed == a_distanceToTarget)
                {
                    if (m_lastSeekAction != null)
                    {
                        if (m_lastSeekAction == t)
                        {
                            continue;
                        }
                    }
                    // No benefit but do able.
                    //Debug.Log(t.GetAnimNum + " is neutral");
                    neutral.Add(t);
                }

                // Check if the move gets boss closer to optimal position without passing
                // through player.
                // If 0 or neg

                // Need to check if the resulting distance when used is closer to the target.
                // If not it is not good and should be skipped.
                else if ((resultingDistanceWhenMoveUsed > 0 && resultingDistanceWhenMoveUsed > m_desiredRange))
                {
                    if (m_lastSeekAction != null)
                    {
                        if (m_lastSeekAction == t)
                        {
                            continue;
                        }
                    }
                    // A good choice
                    //Debug.Log(t.GetAnimNum + " is desired");
                    desired.Add(t);
                }
                // Otherwise move is skipped.
            }
        }

        int reroll = 0;

        if (desired.Count > 0)
        {
            while (reroll < 1)
            {
                BossActions t = ChooseSeekAction(desired);

                // Reset the last actions used
                if (m_lastSeekAction != null)
                {
                    if (t == m_lastSeekAction)
                    {
                        t = ChooseSeekAction(desired);
                    }
                }
                else
                {
                    output = t;
                    m_lastNeutralAction = m_timeBetweenNeutral + Time.time;
                    reroll = 2;
                }
                reroll++;
            }
        }
        // Same loop as above but with neutral evalations
        else if (neutral.Count > 0 && m_lastNeutralAction < Time.time)
        {
            while (reroll < 1)
            {
                BossActions t = ChooseSeekAction(neutral);

                // Reset the last actions used
                if (m_lastSeekAction != null)
                {
                    if (t == m_lastSeekAction)
                    {
                        t = ChooseSeekAction(neutral);
                    }
                }
                else
                {
                    output = t;
                    m_lastNeutralAction = m_timeBetweenNeutral + Time.time;
                    reroll = 2;
                }
                reroll++;
            }
        }
        else
        {
            output = null;
        }

        // Used to stop moves occuring twice in a row.
        if (output != null)
        {
            m_lastSeekAction = output;
        }
        else
        {
            m_lastSeekAction = null;
        }
        return(output);
    }
Beispiel #7
0
    // Boss checks to see what it's stamina is at.
    // DEFUNCT
    //public BossActions EvaluateSelf(float a_distanceToTarget, Vector3 m_targetDirection)
    //{
    //   // Might need to be removed
    //   // Boss should only need to act agressivly

    //    // Did i do a dodge last action?
    //    // if yes choose attack and seek towards player
    //    // if no choose either an attack or dodge.


    //    //float currentStam = EntityStats.Instance.GetStaminaOfEntity("Boss");
    //    //if (currentStam > m_aggresiveStaminaThreshold)
    //    //{
    //        return EvaluateAggresiveAction(a_distanceToTarget);
    //    //}
    //    //else if(currentStam > m_defensiveStaminaThreshold)
    //    //{
    //    //    return EvaluateDefensiveAction(m_targetDirection);
    //    //}
    //    //else
    //    //{
    //    //    return EvaluatePassiveAction();
    //    //}

    //}

    // Before attack needs to evaluate if it should evaluate
    // whether it should do an action that would result in no change
    // and launch the attack straight after.

    // Needs to know if the attack is launchable.
    // Attacks that need to be launched from a larger
    // distance will be weighted
    public BossActions EvaluateAggresiveAction(float a_distanceToTarget)
    {
        //sets multiplyWeight
        multiplyWeight = multiplyWeightWeight / m_bossActions.Count;

        BossActions            output  = null;
        List <EvaluatedAction> actions = new List <EvaluatedAction>();

        foreach (BossActions t in m_bossActions)
        {
            if (t.GetBehaviourType == SteeringBehaviours.AGGRESSIVE)
            {
                EvaluatedAction z = new EvaluatedAction();
                // Need to give values for evaluations
                z.m_action = t;

                float range = t.AttackRange;      // Higher value closter to the target range
                //float distanceCovered = t.GetDestinationDistance; // How far the move travels.
                float weight = t.AttackWeight;    // Flat value
                if (weight < 10f)
                {
                    weight = 10f;
                }                                     //sets weight to 10 if input as less than 10
                float timesUnused    = t.TimesUnused; // Subtraction based on times used
                float rangeThreshold = 2;             // needs to be passed in by attack
                                                      // Did we want a random number added?

                // Weight
                z.m_score = weight;
                // Time used
                z.m_score += timesUnused * multiplyWeight;

                z.m_score *= RangeMultiply(a_distanceToTarget, 0.3f, range, rangeThreshold);

                actions.Add(z);

                // Distance to player, damage, coolness factor(set by designer) timeused

                // more ways to be effect weighing.

                // Weighing happens here
                // If desirability is greater than previous replace.
                // bossaction
                // Only here to test
                //output = t;
                //break;
            }
            // Add all the evaluated values together
        }
        // Add up all scores
        float total = 0;

        foreach (EvaluatedAction t in actions)
        {
            total += t.m_score;
        }
        float norm           = 1 / total;
        float assaignedSoFar = 0;

        // Apply normal value to every attack
        // and set min and max roll
        foreach (EvaluatedAction t in actions)
        {
            float normalizedScore = norm * t.m_score;
            t.m_rollMin = assaignedSoFar;
            t.m_rollMax = assaignedSoFar + normalizedScore + 0.01f;
            // Will this be okay? I dunno lol
            assaignedSoFar = t.m_rollMax - 0.01f;
        }


        // roll and convert to 0 - 1.
        // pass out action within range.
        float number = UnityEngine.Random.Range(0, assaignedSoFar);

        //1 to 100

        //number = number / assaignedSoFar;
        foreach (EvaluatedAction t in actions)
        {
            if (number >= t.m_rollMin && number <= t.m_rollMax)
            {
                output = t.m_action;
                t.m_action.TimesUnused = 0;
            }
            else
            {
                t.m_action.TimesUnused++;
            }
        }

        //Debug.Log(number);

        // Adjust the weighing values of the list

        // Needs an output other than null otherwise breakage.
        if (output == null)
        {
            Debug.Log("F**k ai is busted.");
            Debug.Log("Random number was: " + number + " and " +
                      assaignedSoFar + " was the total assaigned values.");
        }

        return(output);
    }
Beispiel #8
0
 // 행동 관련
 public void ActionControl(BossActions _action, bool _enable)
 {
     action[_action].enabled = _enable;
 }
Beispiel #9
0
    //************************************************************
    //Action moves
    //************************************************************
    //************************************************************
    // Evaluation of moves on the action list.
    //************************************************************



    // Evaluate best attack
    // Try to launch attack
    // If can't add a seek above this action
    // If can decide if another action should occur
    // before and/or after the attack action.
    // Once complete or player is dead or knockeddown
    // remove from list.


    // Used with base actions.
    // Currently bugged and ai will forget his action sometimes
    // while curretnly doing it.
    private bool Aggresive(Vector3 a_target)
    {
        if (!m_continue)
        {
            // If aggresive but no action get action and time out
            // Or launching attack (in case time breaks it.
            if (m_currentAttack != null && m_timeOutAttack > Time.time)
            {
                // If in action skip entirely
                if (!m_animator.GetBool("Ai/PlayingAction"))
                {
                    // Check if you're at the correct distance or should continue
                    if (m_launchAttack || CalculateDistance(a_target) && CorrectFacing(a_target))
                    {
                        // Stop your movement. Mostly a safety.
                        m_animator.SetFloat("Movement/Z", 0);
                        m_animator.SetFloat("Movement/X", 0);
                        int random = Random.Range(0, 100);
                        //Debug.Log(random);
                        // Should I do an action before I attack or currenlty not in action
                        if (random < m_chanceOfPreMove && !m_launchAttack)
                        {
                            BossActions t = m_bossPhaseList[m_currentPhase].EvaluateSeek(GetDistanceToPlayer(a_target), m_desiredRange);
                            if (t != null)
                            {
                                m_chanceOfPreMove = m_PreMoveFloor;
                                m_animator.SetInteger("Ai/Action", t.GetAnimNum);
                                m_launchAttack = true;
                                return(false);
                            }
                        }
                        else
                        {
                            // Increase chance boss will do something before
                            // a move.
                            m_chanceOfPreMove += m_increasePerPremove;
                            if (m_chanceOfPreMove > 100)
                            {
                                m_chanceOfPreMove = 100;
                            }
                        }
                        // if it is not launching an extra animation it should get here.
                        m_animator.SetInteger("Ai/Action", m_currentAttack.GetAnimNum);
                        m_continue = true;
                    }
                    else
                    {
                        // If null or not within distance launch attack launch attack
                        AddSeek();
                    }
                }
            }
            else
            {
                // A safety in case no action chosen.
                BossActions t = m_bossPhaseList[m_currentPhase].EvaluateAggresiveAction(GetDistanceToPlayer(a_target));
                if (t != null)
                {
                    m_currentAttack = t;
                    m_desiredRange  = t.AttackRange;
                    m_launchAttack  = false;
                    m_continue      = false;
                    //Debug.Log("New attack");
                    // Will try to launch attack for x time
                    m_timeOutAttack = Time.time + 10;
                    // Sometimes enters here unintentionally
                }
            }
            return(false);
        }
        // logic is wrong. Enters here when it shouldn't
        else if (!m_animator.GetBool("Ai/PlayingAction") && m_animator.GetInteger("Ai/Action") == 0)
        {
            Debug.Log("I am forget");
            // Should be hitting this whenever attacks are finished.
            m_continue     = false;
            m_launchAttack = false;
            // Null so new attack needed. V dangerous.
            m_currentAttack = null;
            //Debug.Log("Attack Complete");
            return(true);
        }
        else
        {
            return(false);
        }
    }
 //If it has finished whatever it was doing, it rerolls and does something else.
 void Idle()
 {
     eCurState = (BossActions)Random.Range(0, 3);
 }
    IEnumerator wait(float secs)
    {
        yield return(new WaitForSeconds(secs));

        eCurState = BossActions.Idle;
    }
 //Gets close to the x value of the player
 void MoveAround()
 {
     transform.position = new Vector2(player.position.x + Random.Range(0, 2f), transform.position.y);
     eCurState          = BossActions.Falling;
 }
Beispiel #13
0
 public void changeState(BossActions action)
 {
     currentAction = action;
 }