예제 #1
0
    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.layer == Layer_Wall)
        {
            print("EL colisionador choco con algo... " + other.gameObject.name);

            if (other.gameObject == self)
            {
                return;
            }

            IKilleable killeable = other.gameObject.GetComponent <IKilleable>();
            if (killeable != null)
            {
                if (killeable.IsAlive && !killeable.invulnerable)
                {
#if UNITY_EDITOR
                    if (DebugMessages)
                    {
                        print("EL colisionador choco con algo KILLEABLE: " + other.gameObject.name);
                    }
#endif
                    OnCollide();
                    return;
                }
            }

#if UNITY_EDITOR
            if (DebugMessages)
            {
                print("EL colisionador choco con algo que no es KILLEABLE: " + other.gameObject.name);
            }
#endif
            OnCollide();
        }
    }
예제 #2
0
    //============================= Colisiones ================================================

    private void OnCollisionEnter(Collision collision)
    {
        //Detectamos collisiones con otros cuerpos.
        if (collision.gameObject.tag == "Player")
        {
            if (!charging)
            {
                return;
            }

            IKilleable killeable = collision.gameObject.GetComponent <IKilleable>();
            if (killeable != null && killeable.IsAlive && !killeable.invulnerable)
            {
                print("EL colisionador choco con algo KILLEABLE: " + collision.gameObject.name);
                sm.Feed(BossStates.think);

                var     Target = collision.gameObject.GetComponent <IDamageable <HitData, HitResult> >();
                HitData data   = new HitData()
                {
                    Damage = ChargeDamage, BreakDefence = false
                };
                Target.Hit(data);
                collision.rigidbody.AddForce(_chargeDir * ChargeCollisionForce, ForceMode.Impulse);
                return;
            }
        }

        if (collision.gameObject.layer == Layer_walls)
        {
            if (charging)
            {
                sm.Feed(BossStates.think);
            }
            print("EL colisionador choco con algo que no es KILLEABLE: " + collision.gameObject.name);
        }
    }
예제 #3
0
    //=========================================================================================

    protected override void Awake()
    {
        base.Awake();

        //Vulnerabilidad.
        //Si interrumpo el ataque... voy a stunned.
        FRitmo.OnComboSuccesfullyStart += () => _sm.Feed(ShieldEnemyStates.stunned);
        FRitmo.OnComboCompleted        += () => { Health -= ComboCompleteDamage; };
        FRitmo.TimeEnded     += () => { _sm.Feed(ShieldEnemyStates.think); };
        FRitmo.OnComboFailed += () => { _sm.Feed(ShieldEnemyStates.think); };

        //Primera vulnerabilidad.
        Tuple <int, Inputs>[] data = new Tuple <int, Inputs> [3];
        data[0] = Tuple.Create(1, Inputs.light);
        data[1] = Tuple.Create(3, Inputs.light);
        data[2] = Tuple.Create(7, Inputs.light);

        FRitmo.AddVulnerability(0, data);

        //Segunda vulnerabilidad
        Tuple <int, Inputs>[] data2 = new Tuple <int, Inputs> [3];
        data2[0] = Tuple.Create(2, Inputs.strong);
        data2[1] = Tuple.Create(5, Inputs.light);
        data[2]  = Tuple.Create(9, Inputs.light);

        FRitmo.AddVulnerability(1, data2);

        #region State Machine.

        var idle       = new State <ShieldEnemyStates>("Idle");
        var alerted    = new State <ShieldEnemyStates>("Alerted");
        var pursue     = new State <ShieldEnemyStates>("pursue");
        var blocking   = new State <ShieldEnemyStates>("Bloquing");
        var vulnerable = new State <ShieldEnemyStates>("Vulnerable");
        var reposition = new State <ShieldEnemyStates>("Repositioning");
        var parry      = new State <ShieldEnemyStates>("Parrying");
        var attack     = new State <ShieldEnemyStates>("Attacking");
        var think      = new State <ShieldEnemyStates>("Thinking");
        var dead       = new State <ShieldEnemyStates>("Dead");

        /*
         *  anims.SetBool("Dead", true);
         *  anims.SetTrigger("getDamage");
         *  anims.SetFloat("Moving", 1f);
         *  anims.SetInteger("Attack", 1);
         *  anims.SetBool("Blocking", true);
         *  anims.SetTrigger("BlockBreak");
         *  anims.SetBool("Parrying");
         */
        #region Transitions

        idle.AddTransition(ShieldEnemyStates.alerted, alerted)
        .AddTransition(ShieldEnemyStates.dead, dead);

        alerted.AddTransition(ShieldEnemyStates.think, think)
        .AddTransition(ShieldEnemyStates.dead, dead);

        pursue.AddTransition(ShieldEnemyStates.pursue, pursue)
        .AddTransition(ShieldEnemyStates.think, think)
        .AddTransition(ShieldEnemyStates.dead, dead);

        reposition.AddTransition(ShieldEnemyStates.dead, dead)
        .AddTransition(ShieldEnemyStates.think, think);

        blocking.AddTransition(ShieldEnemyStates.parry, parry)
        .AddTransition(ShieldEnemyStates.attack, attack)
        .AddTransition(ShieldEnemyStates.vulnerable, vulnerable)
        .AddTransition(ShieldEnemyStates.think, think)
        .AddTransition(ShieldEnemyStates.dead, dead);

        vulnerable.AddTransition(ShieldEnemyStates.think, think)
        .AddTransition(ShieldEnemyStates.dead, dead);

        parry.AddTransition(ShieldEnemyStates.think, think)
        .AddTransition(ShieldEnemyStates.dead, dead);

        attack.AddTransition(ShieldEnemyStates.dead, dead)
        .AddTransition(ShieldEnemyStates.think, think);

        think.AddTransition(ShieldEnemyStates.dead, dead)
        .AddTransition(ShieldEnemyStates.block, blocking)
        .AddTransition(ShieldEnemyStates.parry, parry)
        .AddTransition(ShieldEnemyStates.vulnerable, vulnerable)
        .AddTransition(ShieldEnemyStates.reposition, reposition)
        .AddTransition(ShieldEnemyStates.attack, attack)
        .AddTransition(ShieldEnemyStates.pursue, pursue)
        .AddTransition(ShieldEnemyStates.idle, idle);

        #endregion

        #region Estados

        idle.OnEnter += (previousState) =>
        {
            anims.SetFloat("Moving", 0f);
        };
        idle.OnUpdate += () =>
        {
            var toDamage = sight.target.GetComponent <IKilleable>();
            if (!toDamage.IsAlive)
            {
                return;
            }

            if (sight.IsInSight() || sight.distanceToTarget < minDetectionRange)
            {
                _targetDetected = true;
            }

            if (_targetDetected)
            {
                _sm.Feed(ShieldEnemyStates.alerted);
            }
        };

        alerted.OnEnter += (previousState) =>
        {
            _alertedTimeRemaining = AlertedTime;
        };
        alerted.OnUpdate += () =>
        {
            if (_alertedTimeRemaining >= 0)
            {
                _alertedTimeRemaining -= Time.deltaTime;
                transform.forward      = Vector3.Slerp(transform.forward, sight.dirToTarget, _rotationLerpSpeed);
            }
            else
            {
                _sm.Feed(ShieldEnemyStates.think);
            }
        };
        alerted.OnExit += (nextState) => { };


        blocking.OnEnter += (previousState) =>
        {
            anims.SetBool("Blocking", true);
            anims.SetFloat("Moving", 0f);
            LookTowardsPlayer     = true;
            _originalRotLerpSpeed = _rotationLerpSpeed;
            _rotationLerpSpeed    = BlockLerpSpeed;
            _blocking             = true;
            //recievedHits = 0;

            FRitmo.SetCurrentVulnerabilityCombo(1);
            FRitmo.ShowVulnerability();
        };
        blocking.OnUpdate += () =>
        {
            if (sight.distanceToTarget > BlockRange)
            {
                _sm.Feed(ShieldEnemyStates.think);
            }
        };
        blocking.OnExit += (nextState) =>
        {
            if (nextState == ShieldEnemyStates.vulnerable)
            {
                Debug.LogWarning("Voy a vulnerable");
            }

            anims.SetBool("Blocking", false);
            _rotationLerpSpeed = _originalRotLerpSpeed;
            _blocking          = false;
        };

        vulnerable.OnEnter += (previousState) =>
        {
            _blocking            = false;
            Disarmed             = true;
            _currentDisarmedTime = DisarmedTime;
            //SetVulnerabity(true, 1);

            anims.SetBool("Disarmed", true);
        };
        //vulnerable.OnUpdate += () => { };
        vulnerable.OnExit += (nextState) =>
        {
            anims.SetBool("Disarmed", false);
        };


        parry.OnEnter += (previousState) =>
        {
            //_parrying = true;
            //recievedHits = 0;

            anims.SetTrigger("Parrying");
            ShieldSparks.Play();
        };
        //parry.OnExit += (nextState) => { _parrying = false; };

        pursue.OnEnter += (previousState) =>
        {
            anims.SetFloat("Moving", 1f);
            //recievedHits = 0;
        };
        pursue.OnUpdate += () =>
        {
            //Correr como si no hubiera un mañana (?
            transform.forward = Vector3.Slerp(transform.forward, sight.dirToTarget, _rotationLerpSpeed);

            if (sight.distanceToTarget > AttackRange)
            {
                agent.Move(sight.dirToTarget * MovementSpeed * Time.deltaTime);
            }

            if (sight.distanceToTarget <= AttackRange)
            {
                _sm.Feed(ShieldEnemyStates.think);
            }
        };
        //pursue.OnExit += (nextState) => { };

        reposition.OnEnter += (previousState) =>
        {
            LookTowardsPlayer     = true;
            _originalRotLerpSpeed = _rotationLerpSpeed;
            _rotationLerpSpeed    = repositionLerpSpeed;
        };
        reposition.OnUpdate += () =>
        {
            if (sight.angleToTarget < 45)
            {
                _sm.Feed(ShieldEnemyStates.think);
            }
        };
        reposition.OnExit += (nextState) =>
        {
            LookTowardsPlayer  = false;
            _rotationLerpSpeed = _originalRotLerpSpeed;
        };

        attack.OnEnter += (previousState) =>
        {
            //_attacking = true;
            agent.isStopped = true;
            rb.velocity     = Vector3.zero;
            anims.SetInteger("Attack", 1);
            //recievedHits = 0;
        };
        //attack.OnUpdate += () => { };
        attack.OnExit += (nextState) =>
        {
            //_attacking = false;
            agent.isStopped = false;
        };

        think.OnEnter += (previousState) =>
        {
            if (ThinkTime > 0)
            {
                remainingThinkTime = ThinkTime;
            }
        };
        think.OnUpdate += () =>
        {
            if (remainingThinkTime > 0)
            {
                remainingThinkTime -= Time.deltaTime;
            }
            else
            {
                remainingThinkTime = 0;
                IKilleable target = Target.GetComponent <IKilleable>();

                if (sight.angleToTarget > 45f)
                {
                    _sm.Feed(ShieldEnemyStates.reposition);
                    return;
                }

                if (target.IsAlive)
                {
                    //Tomo una desición.
                    float blockImportance  = (1 - (Health / MaxHP)) * 10;
                    float pursueImportance = ((Health / MaxHP) * 10);
                    float AttackImportance = 10f - (blockImportance * 0.8f);

                    //print(string.Format("BlockImp: {0} / PursueImp: {1} / AttackImportance: {2}",
                    //    blockImportance, pursueImportance, AttackImportance));

                    //Desiciones posibles:
                    //Perseguir --> se realiza siempre que el enemigo esté más lejos de cierta distancia.
                    //Atacar --> Su importancia se mantiene.
                    //Bloquear --> Cuando la vida se va reduciendo su imporancia es mayor.

                    if (sight.distanceToTarget > AttackRange)
                    {
                        int decition = RoulleteSelection.Roll(new float[2] {
                            pursueImportance, blockImportance
                        });
                        //print("Distance is bigger than the AttackRange.\nDecition was: " + (decition == 0 ? "pursue" : "block"));

                        if (decition == 0)
                        {
                            _sm.Feed(ShieldEnemyStates.pursue);
                        }
                        if (decition == 1)
                        {
                            _sm.Feed(ShieldEnemyStates.block);
                        }
                    }

                    if (sight.distanceToTarget < AttackRange)
                    {
                        int decition = RoulleteSelection.Roll(new float[2] {
                            AttackImportance, blockImportance
                        });
                        //print("Distance is smaller than the AttackRange.\nDecition was: " + (decition == 0 ? "Attack" : "block"));

                        if (decition == 0)
                        {
                            _sm.Feed(ShieldEnemyStates.attack);
                        }
                        if (decition == 1)
                        {
                            _sm.Feed(ShieldEnemyStates.block);
                        }
                    }
                }
            }
        };
        think.OnExit += (nextState) =>
        {
            //print(string.Format("Exiting from Thinking, next State will be {0}", nextState.ToString()));
        };

        dead.OnEnter += (previousState) =>
        {
            anims.SetBool("Dead", true);
            Die();
        };

        #endregion

        _sm = new GenericFSM <ShieldEnemyStates>(idle);
        #endregion
    }