Exemple #1
0
        private void OnIsAliveChanged(bool alive)
        {
            m_IsActive &= alive;

            if (alive)
            {
                return;
            }

            CombatMessage message = CombatMessage.Allocate();

            if (message != null)
            {
                message.ID         = EnumMessageID.MSG_COMBAT_DEFENDER_KILLED;
                message.StyleIndex = -1; // Random
                message.Defender   = m_MotionController.gameObject;
                m_MotionController.SendMessage(message);
                message.Release();
            }

            if (m_NavMeshAgent != null)
            {
                m_NavMeshAgent.isStopped = true;
            }

            if (message.IsHandled)
            {
                m_DeathMotion = message.Recipient as MotionControllerMotion;
            }
        }
Exemple #2
0
        /// <summary>
        /// Tells the actor when to block
        /// </summary>
        public void DetermineBlock()
        {
            if (_Target == null)
            {
                return;
            }

#if USE_SWORD_SHIELD_MP || OOTII_SSMP
            Vector3 lToTarget         = _Target.transform.position - transform.position;
            float   lToTargetDistance = lToTarget.magnitude;

            BasicMeleeBlock lMeleeBlock = mMotionController.GetMotion <BasicMeleeBlock>();
            if (lMeleeBlock != null)
            {
                if (lMeleeBlock.IsActive)
                {
                    if (lMeleeBlock.Age > 1f)
                    {
                        CombatMessage lMessage = CombatMessage.Allocate();
                        lMessage.ID       = CombatMessage.MSG_COMBATANT_CANCEL;
                        lMessage.Defender = gameObject;
                        lMeleeBlock.OnMessageReceived(lMessage);

                        CombatMessage.Release(lMessage);

                        mActorCore.SetStateValue("State", IDLE);
                    }
                }
                else
                {
                    BasicMeleeAttack lMeleeAttack = mTargetMotionController.GetMotion <BasicMeleeAttack>();
                    if (lMeleeAttack != null && lMeleeAttack.IsActive)
                    {
                        if (lMeleeAttack.Age < 0.1f && !lMeleeBlock.IsActive)
                        {
                            if (mActorCore.GetStateValue("Stance") == EnumControllerStance.COMBAT_MELEE)
                            {
                                mMotionController.ActivateMotion(lMeleeBlock);
                                mActorCore.SetStateValue("State", BLOCKING);
                            }
                        }
                    }

#if USE_ARCHERY_MP || OOTII_AYMP
                    BasicRangedAttack lRangedAttack = mTargetMotionController.GetMotion <BasicRangedAttack>();
                    if (lRangedAttack != null && lRangedAttack.IsActive)
                    {
                    }
#endif
                }
            }
#endif
        }
Exemple #3
0
        private void HandleMeleeAttackMotion(GameObject target)
        {
            CombatMessage message = CombatMessage.Allocate();

            if (message != null)
            {
                message.ID       = CombatMessage.MSG_COMBATANT_ATTACK;
                message.Attacker = m_Owner;
                message.Defender = target;
                m_MotionController.SendMessage(message);
                CombatMessage.Release(message);
            }
        }
Exemple #4
0
        private IEnumerator HandleDamageMotion(float damage)
        {
            CombatMessage message = CombatMessage.Allocate();
            if (message != null)
            {
                message.ID = EnumMessageID.MSG_COMBAT_DEFENDER_DAMAGED;
                message.Damage = damage * m_Multiplier;
                message.Defender = gameObject;
                m_MotionController.SendMessage(message);
                message.Release();
            }

            yield return null;
        }
Exemple #5
0
        /// <summary>
        /// Called when the action is first activated
        /// <param name="rPreviousSpellActionState">State of the action prior to this one activating</param>
        public override void Activate(int rPreviousSpellActionState = -1, object rData = null)
        {
            base.Activate(rPreviousSpellActionState, rData);

            MotionController lMotionController = _Spell.Owner.GetComponent <MotionController>();

            if (lMotionController != null)
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID = MessageID;

                lMotionController.SendMessage(lMessage);

                lMessage.Release();
            }

            base.Deactivate();
        }
Exemple #6
0
        /// <summary>
        /// Called each frame
        /// </summary>
        private void Update()
        {
            if (!IsActive)
            {
                return;
            }
            if (mCombatant == null)
            {
                return;
            }
            if (Target == null)
            {
                return;
            }

            MotionControllerMotion lMotion = mMotionController.ActiveMotion;

            if (lMotion == null)
            {
                return;
            }

            MotionControllerMotion lTargetMotion = mTargetMotionController.ActiveMotion;

            // Determine if we rotate to the target
            bool lRotate = true;

            // Ensure our weapon is equipped
            //if (!mBasicInventory.IsWeaponSetEquipped(2))
            //{
            //    if (mLastEquipTime + AttackDelay < Time.time)
            //    {
            //        mBasicInventory.EquipWeaponSet(2);
            //        mLastEquipTime = Time.time;
            //    }
            //}
            //// The main AI loop
            //else
            //{
            Vector3 lToTarget = Target._Transform.position - transform.position;

            lToTarget.y = 0f;

            Vector3 lToTargetDirection = lToTarget.normalized;
            float   lToTargetDistance  = lToTarget.magnitude;

            bool lIsTargetAimingAtMe = false;

#if USE_ARCHERY_MP || OOTII_AYMP
            //float lTargetToMeHorizontalAngle = NumberHelper.GetHorizontalAngle(Target._Transform.forward, -lToTargetDirection, Target._Transform.up);
            //lIsTargetAimingAtMe = ((lTargetMotion is Bow_WalkRunTarget || lTargetMotion is Bow_BasicAttacks) && Mathf.Abs(lTargetToMeHorizontalAngle) < 10f);
#endif

            // Determine if we should move to the target
            float lRange = Range;

            if (!mFollow && lToTargetDistance > lRange + 1f)
            {
                mFollow = true;
            }
            if (mFollow && lToTargetDistance <= lRange)
            {
                mFollow = false;
            }
            if (mFollow && (lMotion.Category != EnumMotionCategories.IDLE && lMotion.Category != EnumMotionCategories.WALK))
            {
                mFollow = false;
            }
            if (mFollow && lIsTargetAimingAtMe)
            {
                mFollow = false;
            }
            if (!Move)
            {
                mFollow = false;
            }

            // Ensure we're not casting
            if (mMotionController.ActiveMotion is BasicSpellCasting)
            {
            }
            // Cast a healing spell
            else if (Cast &&
                     mLastCastTime + CastDelay < Time.time &&
                     mBasicAttributes != null && mBasicAttributes.GetAttributeValue <float>("Health", 100f) < 40f &&
                     mSpellInventory != null && mSpellInventory.GetSpellIndex("Heal Self") >= 0)
            {
                int lSpellIndex = mSpellInventory.GetSpellIndex("Heal Self");
                if (lSpellIndex >= 0)
                {
                    BasicSpellCasting lCastMotion = mMotionController.GetMotion <BasicSpellCasting>();
                    mMotionController.ActivateMotion(lCastMotion, lSpellIndex);

                    mLastCastTime = Time.time;
                }
            }
            // Move to the target
            else if (mFollow)
            {
                float lSpeed = Mathf.Min(MovementSpeed * Time.deltaTime, lToTargetDistance);
                transform.position = transform.position + (lToTargetDirection * lSpeed);
            }
            // If we're being shot at, block
            else if (Block && lIsTargetAimingAtMe)
            {
                mFollow = false;

                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_BLOCK;
                lMessage.Attacker = null;
                lMessage.Defender = gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);
            }
            // Let the movement finish up
            else if (lMotion.Category == EnumMotionCategories.WALK)
            {
            }
            // Attack with the sword
            else if (Attack && lMotion.Category == EnumMotionCategories.IDLE && (mLastAttackTime + AttackDelay < Time.time))
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_ATTACK;
                lMessage.Attacker = gameObject;
                lMessage.Defender = Target.gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);

                mLastAttackTime = Time.time;
            }
            // Block with the shield
            else if (Block && lMotion.Category == EnumMotionCategories.IDLE && lMotion.Age > 0.5f)
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_BLOCK;
                lMessage.Attacker = null;
                lMessage.Defender = gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);
            }
            // Free the block
            else if (lMotion.Category == EnumMotionCategories.COMBAT_MELEE_BLOCK && (lToTargetDistance > lRange + 1f || lMotion.Age > BlockHold))
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_CANCEL;
                lMessage.Attacker = null;
                lMessage.Defender = gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);
            }

            // Allow rotation only
            if (mMotionController.enabled && lRotate)
            {
                float lAngle = NumberHelper.GetHorizontalAngle(transform.forward, lToTargetDirection, transform.up);
                if (lAngle != 0f)
                {
                    float lRotationSpeed = Mathf.Sign(lAngle) * Mathf.Min(RotationSpeed * Time.deltaTime, Mathf.Abs(lAngle));
                    transform.rotation = transform.rotation * Quaternion.AngleAxis(lRotationSpeed, transform.up);
                }
            }
            //}

            // If we're dead, we can just stop
            if (lMotion.Category == EnumMotionCategories.DEATH)
            {
                IsActive = false;
            }
            // Clear the target if they are dead
            else if (Target != null && !Target.enabled)
            {
                Target = null;
                //StartCoroutine(WaitAndStoreEquipment(2f));
            }
        }
Exemple #7
0
        protected virtual void Update()
        {
            if (!IsActive)
            {
                return;
            }
            MotionControllerMotion lMotion = mMotionController.ActiveMotion;

            if (lMotion == null)
            {
                return;
            }

            // Ensure the weapon is equipped
            if (mCombatant.PrimaryWeapon == null)
            {
                EquipWeapon();
                return;
            }


            Vector3 lToTarget = Target._Transform.position - transform.position;

            lToTarget.y = 0f;

            Vector3 lToTargetDirection = lToTarget.normalized;
            float   lToTargetDistance  = lToTarget.magnitude;
            float   lRange             = mCombatant.MinMeleeReach + mCombatant.PrimaryWeapon.MaxRange;

            if (lToTargetDistance < StopDistance)
            {
                mDoMove = false;
            }
            else
            {
                mDoMove = true;
            }

            if (mDoMove)
            {
                MoveToTarget();
            }
            else
            {
                mNavMeshAgent.isStopped = true;
            }


            // Attack with the sword
            if (Attack && lMotion.Category == EnumMotionCategories.IDLE && (mLastAttackTime + AttackDelay < Time.time))//&& lMotion.Category == EnumMotionCategories.IDLE
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_ATTACK;
                lMessage.Attacker = gameObject;
                lMessage.Defender = Target.gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);

                mLastAttackTime = Time.time;
            }
            // Block with shield
            else if (Block && lMotion.Category == EnumMotionCategories.IDLE && lMotion.Age > 0.5f)
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_BLOCK;
                lMessage.Attacker = null;
                lMessage.Defender = gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);
            }
            // Release the shield block
            else if (lMotion.Category == EnumMotionCategories.COMBAT_MELEE_BLOCK && (lToTargetDistance > lRange + 1f || lMotion.Age > BlockHold))
            {
                CombatMessage lMessage = CombatMessage.Allocate();
                lMessage.ID       = CombatMessage.MSG_COMBATANT_CANCEL;
                lMessage.Attacker = null;
                lMessage.Defender = gameObject;

                mMotionController.SendMessage(lMessage);
                CombatMessage.Release(lMessage);
            }



            // If we're dead, we can just stop
            if (lMotion.Category == EnumMotionCategories.DEATH)
            {
                IsActive = false;
            }
            // Clear the target if they are dead
            else if (Target != null && !Target.enabled)
            {
                Target = null;
                StartCoroutine(WaitAndStoreEquipment(2f));
            }
        }
        /// <summary>
        /// Raised when the impact occurs
        /// </summary>
        /// <param name="rHitInfo">CombatHit structure detailing the hit information.</param>
        /// <param name="rAttackStyle">ICombatStyle that details the combat style being used.</param>
        protected override void OnImpact(CombatHit rHitInfo, ICombatStyle rAttackStyle = null)
        {
            // Test impact is now rolling up to the parent object but this means we are trying to apply the damage to the actorcore rather than the collider actually hit
            // see Test impact below
            IHealthManager lHealthManager = rHitInfo.Collider.gameObject.GetComponentInParent <IHealthManager>();
            GameObject     defender       = ((MonoBehaviour)lHealthManager).gameObject;

            mDefenders.Add(defender);

            mImpactCount++;

            Transform lHitTransform = GetClosestTransform(rHitInfo.Point, rHitInfo.Collider.transform);
            Vector3   lHitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lHitTransform.position).normalized;

            CombatMessage lMessage = CombatMessage.Allocate();

            lMessage.Attacker     = mOwner;
            lMessage.Defender     = rHitInfo.Collider.gameObject;
            lMessage.Weapon       = this;
            lMessage.Damage       = GetAttackDamage(Random.value, (rAttackStyle != null ? rAttackStyle.DamageModifier : 1f));
            lMessage.ImpactPower  = GetAttackImpactPower();
            lMessage.HitPoint     = rHitInfo.Point;
            lMessage.HitDirection = lHitDirection;
            lMessage.HitVector    = rHitInfo.Vector;
            lMessage.HitTransform = lHitTransform;
            lMessage.AttackIndex  = mAttackStyleIndex;
            lMessage.CombatStyle  = rAttackStyle;

            ActorCore lAttackerCore = (mOwner != null ? mOwner.GetComponentInParent <ActorCore>() : null);
            ActorCore lDefenderCore = defender.gameObject.GetComponentInParent <ActorCore>();

            lMessage.ID = CombatMessage.MSG_ATTACKER_ATTACKED;

            if (lAttackerCore != null)
            {
                lAttackerCore.SendMessage(lMessage);
            }

#if USE_MESSAGE_DISPATCHER || OOTII_MD
            MessageDispatcher.SendMessage(lMessage);
#endif

            lMessage.ID = CombatMessage.MSG_DEFENDER_ATTACKED;

            if (lDefenderCore != null)
            {
                lDefenderCore.SendMessage(lMessage);

#if USE_MESSAGE_DISPATCHER || OOTII_MD
                MessageDispatcher.SendMessage(lMessage);
#endif
            }

            if (lAttackerCore != null)
            {
                lAttackerCore.SendMessage(lMessage);

#if USE_MESSAGE_DISPATCHER || OOTII_MD
                MessageDispatcher.SendMessage(lMessage);
#endif
            }

            OnImpactComplete(lMessage);

            CombatMessage.Release(lMessage);
        }
Exemple #9
0
        /// <summary>
        /// Raised when the impact occurs
        /// </summary>
        /// <param name="rHitInfo">CombatHit structure detailing the hit information.</param>
        /// <param name="rAttackStyle">ICombatStyle that details the combat style being used.</param>
        protected virtual void OnImpact(CombatHit rHitInfo, ICombatStyle rAttackStyle = null)
        {
            // If we get here, there's an impact
            mImpactCount++;

            // Extract out information about the hit
            Transform lHitTransform = GetClosestTransform(rHitInfo.Point, rHitInfo.Collider.transform);
            Vector3   lHitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lHitTransform.position).normalized;

            // Put together the combat info. This will will be modified over time
            CombatMessage lMessage = CombatMessage.Allocate();

            lMessage.Attacker     = mOwner;
            lMessage.Defender     = rHitInfo.Collider.gameObject;
            lMessage.Weapon       = this;
            lMessage.Damage       = GetAttackDamage(1f, (rAttackStyle != null ? rAttackStyle.DamageModifier : 1f));
            lMessage.ImpactPower  = GetAttackImpactPower();
            lMessage.HitPoint     = rHitInfo.Point;
            lMessage.HitDirection = lHitDirection;
            lMessage.HitVector    = rHitInfo.Vector;
            lMessage.HitTransform = lHitTransform;

            // Grab cores for processing
            ActorCore lAttackerCore = (mOwner != null ? mOwner.GetComponent <ActorCore>() : null);
            ActorCore lDefenderCore = rHitInfo.Collider.gameObject.GetComponent <ActorCore>();

            // Pre-Attack
            lMessage.ID = CombatMessage.MSG_ATTACKER_ATTACKED;

            if (lAttackerCore != null)
            {
                lAttackerCore.SendMessage(lMessage);
            }

#if USE_MESSAGE_DISPATCHER || OOTII_MD
            MessageDispatcher.SendMessage(lMessage);
#endif

            // Attack Defender
            lMessage.ID = CombatMessage.MSG_DEFENDER_ATTACKED;

            if (lDefenderCore != null)
            {
                ICombatant lDefenderCombatant = rHitInfo.Collider.gameObject.GetComponent <ICombatant>();
                if (lDefenderCombatant != null)
                {
                    lMessage.HitDirection = Quaternion.Inverse(lDefenderCore.Transform.rotation) * (rHitInfo.Point - lDefenderCombatant.CombatOrigin).normalized;
                }

                lDefenderCore.SendMessage(lMessage);

#if USE_MESSAGE_DISPATCHER || OOTII_MD
                MessageDispatcher.SendMessage(lMessage);
#endif
            }
            else
            {
                lMessage.HitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lHitTransform.position).normalized;

                IDamageable lDefenderDamageable = rHitInfo.Collider.gameObject.GetComponent <IDamageable>();
                if (lDefenderDamageable != null)
                {
                    lDefenderDamageable.OnDamaged(lMessage);
                }

                Rigidbody lRigidBody = rHitInfo.Collider.gameObject.GetComponent <Rigidbody>();
                if (lRigidBody != null)
                {
                    lRigidBody.AddForceAtPosition(rHitInfo.Vector * lMessage.ImpactPower, rHitInfo.Point, ForceMode.Impulse);
                }
            }

            // Attacker response
            if (lAttackerCore != null)
            {
                lAttackerCore.SendMessage(lMessage);

#if USE_MESSAGE_DISPATCHER || OOTII_MD
                MessageDispatcher.SendMessage(lMessage);
#endif
            }

            // Finish up any impact processing (like sound)
            OnImpactComplete(lMessage);

            // Release the combatant to the pool
            CombatMessage.Release(lMessage);
        }
Exemple #10
0
        /// <summary>
        /// Activates the action on a single target
        /// </summary>
        /// <param name="rTarget">Target to activate on</param>
        protected void ActivateInstance(GameObject rTarget)
        {
            Vector3 lPoint   = rTarget.transform.position;
            Vector3 lForward = rTarget.transform.forward;

            // Combatant that is attacking
            ICombatant lAttacker = (_Spell.Owner != null ? _Spell.Owner.GetComponent <ICombatant>() : null);

            // Determine who we're colliding with
            IActorCore  lDefenderCore = rTarget.GetComponent <IActorCore>();
            IDamageable lDamageable   = rTarget.GetComponent <IDamageable>();

            if (lDefenderCore == null)
            {
                IWeaponCore lWeaponCore = rTarget.GetComponent <IWeaponCore>();
                if (lWeaponCore != null)
                {
                    lDefenderCore = lWeaponCore.Owner.GetComponent <IActorCore>();
                    if (lDamageable == null)
                    {
                        lDamageable = lWeaponCore.Owner.GetComponent <IDamageable>();
                    }
                }
            }

            // Save the hit information
            Transform lHitTransform = GetClosestTransform(lPoint, rTarget.transform);
            Vector3   lCombatCenter = lHitTransform.position;
            Vector3   lHitDirection = Vector3.zero;

            if (lDefenderCore != null)
            {
                ICombatant lDefenderCombatant = lDefenderCore.gameObject.GetComponent <ICombatant>();
                if (lDefenderCombatant != null)
                {
                    lHitDirection = Quaternion.Inverse(lDefenderCore.Transform.rotation) * (lPoint - lDefenderCombatant.CombatOrigin).normalized;
                }
            }
            else
            {
                lHitDirection = Quaternion.Inverse(lHitTransform.rotation) * (lPoint - lCombatCenter).normalized;
            }

            // Determine the damage
            float lDamage = UnityEngine.Random.Range(_MinDamage, _MaxDamage);

            if (_DamageFloatValueIndex >= 0 && _Spell.Data.FloatValues != null)
            {
                lDamage = _Spell.Data.FloatValues[_DamageFloatValueIndex];
            }

            // Put together the combat round info
            CombatMessage lCombatMessage = CombatMessage.Allocate();

            lCombatMessage.ID               = CombatMessage.MSG_DEFENDER_ATTACKED;
            lCombatMessage.Attacker         = (lAttacker != null ? lAttacker.Transform.gameObject : _Spell.Owner);
            lCombatMessage.Defender         = (lDefenderCore != null ? lDefenderCore.Transform.gameObject : rTarget);
            lCombatMessage.Weapon           = null;
            lCombatMessage.DamageType       = _DamageType;
            lCombatMessage.ImpactType       = _ImpactType;
            lCombatMessage.Damage           = lDamage;
            lCombatMessage.AnimationEnabled = _PlayAnimation;
            lCombatMessage.HitPoint         = lPoint;
            lCombatMessage.HitDirection     = lHitDirection;
            lCombatMessage.HitVector        = lForward;
            lCombatMessage.HitTransform     = lHitTransform;

            // Let the defender react to the damage
            if (lDefenderCore != null)
            {
                lDefenderCore.SendMessage(lCombatMessage);
            }
            // If needed, send the damage directly to the actor core
            else if (lDamageable != null)
            {
                lDamageable.OnDamaged(lCombatMessage);
            }
            // Without an actor core, check if we can set attributes
            else
            {
                IAttributeSource lAttributeSource = rTarget.GetComponent <IAttributeSource>();
                if (lAttributeSource != null)
                {
                    float lHealth = lAttributeSource.GetAttributeValue <float>(EnumAttributeIDs.HEALTH);
                    lAttributeSource.SetAttributeValue(EnumAttributeIDs.HEALTH, Mathf.Max(lHealth - lCombatMessage.Damage, 0f));
                }
            }

            // Release the message
            lCombatMessage.Release();
        }