/// <summary>
        /// Reduces the health by the damage amount.
        /// </summary>
        private void ReduceHealth()
        {
            m_Health.Damage(m_DamageAmount.RandomValue);
            if (m_Health.IsAlive())
            {
                // Keep reducing the object's health until is is no longer alive.
                SchedulerBase.Schedule(m_HealthReductionInterval.RandomValue, ReduceHealth);
            }
            else
            {
                // After the object is no longer alive spawn some wood shreds. These shreds should be cleaned up after a random
                // amount of time.
                var crateTransform = transform;
                m_SpawnedCrate = ObjectPoolBase.Instantiate(m_DestroyedCrate, crateTransform.position, crateTransform.rotation);
                var maxDestroyTime = 0f;
                for (int i = 0; i < m_SpawnedCrate.transform.childCount; ++i)
                {
                    var destroyTime = m_WoodShreadRemovalTime.RandomValue;
                    if (destroyTime > maxDestroyTime)
                    {
                        maxDestroyTime = destroyTime;
                    }
                    Destroy(m_SpawnedCrate.transform.GetChild(i).gameObject, destroyTime);
                }

                m_StopEvent = SchedulerBase.Schedule(maxDestroyTime, StopParticles);
            }
        }
Exemple #2
0
        /// <summary>
        /// Does the actual fire.
        /// </summary>
        public void Fire()
        {
            m_LastFireTime = Time.time;

            // Spawn a projectile which will move in the direction that the turret is facing
            var projectile = ObjectPoolBase.Instantiate(m_Projectile, m_FireLocation.position, m_Transform.rotation).GetCachedComponent <Projectile>();

            projectile.Initialize(m_FireLocation.forward * m_VelocityMagnitude, Vector3.zero, null, m_DamageAmount, m_ImpactForce, m_ImpactForceFrames,
                                  m_ImpactLayers, string.Empty, 0, m_SurfaceImpact, m_GameObject);
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_NetworkInfo != null)
            {
                NetworkObjectPool.NetworkSpawn(m_Projectile, projectile.gameObject, true);
            }
#endif

            // Spawn a muzzle flash.
            if (m_MuzzleFlash)
            {
                var muzzleFlash = ObjectPoolBase.Instantiate(m_MuzzleFlash, m_MuzzleFlashLocation.position, m_MuzzleFlashLocation.rotation, m_Transform).GetCachedComponent <MuzzleFlash>();
                muzzleFlash.Show(null, 0, true, null);
            }

            // Play a firing sound.
            if (m_FireAudioClip != null)
            {
                m_AudioSource.clip = m_FireAudioClip;
                m_AudioSource.Play();
            }
        }
Exemple #3
0
        /// <summary>
        /// Instantiate the object.
        /// </summary>
        /// <param name="position">The position to instantiate the object at.</param>
        /// <param name="normal">The normal of the instantiated object.</param>
        /// <param name="gravityDirection">The normalized direction of the character's gravity.</param>
        /// <returns>The instantiated object (can be null). </returns>
        public GameObject Instantiate(Vector3 position, Vector3 normal, Vector3 gravityDirection)
        {
            if (m_Object == null)
            {
                return(null);
            }

            // There is a random chance that the object cannot be spawned.
            if (UnityEngine.Random.value < m_Probability)
            {
                var rotation = Quaternion.LookRotation(normal);
                // A random spin can be applied so the rotation isn't the same every hit.
                if (m_RandomSpin)
                {
                    rotation *= Quaternion.AngleAxis(UnityEngine.Random.Range(0, 360), normal);
                }
                var instantiatedObject = ObjectPoolBase.Instantiate(m_Object, position, rotation);
                // If the DirectionalConstantForce component exists then the gravity direction should be set so the object will move in the correct direction.
                var directionalConstantForce = instantiatedObject.GetCachedComponent <Traits.DirectionalConstantForce>();
                if (directionalConstantForce != null)
                {
                    directionalConstantForce.Direction = gravityDirection;
                }
                return(instantiatedObject);
            }
            return(null);
        }
        /// <summary>
        /// Perform the impact action.
        /// </summary>
        /// <param name="castID">The ID of the cast.</param>
        /// <param name="source">The object that caused the cast.</param>
        /// <param name="target">The object that was hit by the cast.</param>
        /// <param name="hit">The raycast that caused the impact.</param>
        protected override void ImpactInternal(uint castID, GameObject source, GameObject target, RaycastHit hit)
        {
            if (m_ParticlePrefab == null)
            {
                Debug.LogError("Error: A Particle Prefab must be specified.", m_MagicItem);
                return;
            }

            var rotation = Quaternion.LookRotation(hit.normal) * Quaternion.Euler(m_RotationOffset);
            var position = MathUtility.TransformPoint(hit.point, rotation, m_PositionOffset);

            if (m_CastIDParticleMap.TryGetValue(castID, out var existingParticleSystem))
            {
                existingParticleSystem.transform.SetPositionAndRotation(position, rotation);
                return;
            }

            var obj            = ObjectPoolBase.Instantiate(m_ParticlePrefab, position, rotation, m_ParentToImpactedObject ? target.transform : null);
            var particleSystem = obj.GetCachedComponent <ParticleSystem>();

            if (particleSystem == null)
            {
                Debug.LogError($"Error: A Particle System must be specified on the particle {m_ParticlePrefab}.", m_MagicItem);
                return;
            }
            particleSystem.Clear(true);
            m_CastIDParticleMap.Add(castID, particleSystem);
        }
Exemple #5
0
        /// <summary>
        /// Initialize the default values.
        /// </summary>
        protected override void Awake()
        {
            base.Awake();

            m_TrajectoryObject    = GetComponent <TrajectoryObject>();
            m_CharacterLocomotion = m_Character.GetCachedComponent <UltimateCharacterLocomotion>();
            m_CharacterTransform  = m_CharacterLocomotion.transform;
#if ULTIMATE_CHARACTER_CONTROLLER_VR
            m_VRThrowableItem = GetComponent <IVRThrowableItem>();
#endif

            if (m_ThrownObject != null && m_TrajectoryObject != null)
            {
                // The object has to be instantiated for GetComponent to work.
                var instantiatedThrownObject = ObjectPoolBase.Instantiate(m_ThrownObject);
                var trajectoryCollider       = instantiatedThrownObject.GetComponent <Collider>();
                if (trajectoryCollider != null)
                {
                    // Only sphere and capsules are supported.
                    if (trajectoryCollider is SphereCollider)
                    {
                        var trajectorySphereCollider = trajectoryCollider as SphereCollider;
                        var sphereCollider           = m_GameObject.AddComponent <SphereCollider>();
                        sphereCollider.center  = trajectorySphereCollider.center;
                        sphereCollider.radius  = trajectorySphereCollider.radius;
                        sphereCollider.enabled = false;
                    }
                    else if (trajectoryCollider is CapsuleCollider)
                    {
                        var trajectoryCapsuleCollider = trajectoryCollider as CapsuleCollider;
                        var capsuleCollider           = m_GameObject.AddComponent <CapsuleCollider>();
                        capsuleCollider.center    = trajectoryCapsuleCollider.center;
                        capsuleCollider.radius    = trajectoryCapsuleCollider.radius;
                        capsuleCollider.height    = trajectoryCapsuleCollider.height;
                        capsuleCollider.direction = trajectoryCapsuleCollider.direction;
                        capsuleCollider.enabled   = false;
                    }
                    else
                    {
                        Debug.LogError($"Error: The collider of type {trajectoryCollider.GetType()} is not supported on the trajectory object " + m_ThrownObject.name);
                    }
                    m_GameObject.layer = LayerManager.SubCharacter;
                }
                ObjectPoolBase.Destroy(instantiatedThrownObject);
            }
            m_ThrowableItemPerpectiveProperties = m_ActivePerspectiveProperties as IThrowableItemPerspectiveProperties;

            if (m_ShowTrajectoryOnAim && m_TrajectoryObject == null)
            {
                Debug.LogError($"Error: A TrajectoryObject must be added to the {m_GameObject.name} GameObject in order for the trajectory to be shown.");
            }

            if (m_ThrownObject == null)
            {
                Debug.LogError($"Error: A ThrownObject must be assigned to the {m_GameObject.name} GameObject.");
            }

            EventHandler.RegisterEvent <bool, bool>(m_Character, "OnAimAbilityStart", OnAim);
            EventHandler.RegisterEvent(m_Character, "OnAnimatorReequipThrowableItem", ReequipThrowableItem);
        }
Exemple #6
0
        /// <summary>
        /// Starts the item use.
        /// </summary>
        /// <param name="itemAbility">The item ability that is using the item.</param>
        public override void StartItemUse(ItemAbility itemAbility)
        {
            base.StartItemUse(itemAbility);

            // An Animator Audio State Set may prevent the item from being used.
            if (!IsItemInUse())
            {
                return;
            }

            if (!m_ThrowOnStopUse)
            {
                StartThrow();
            }

            // Instantiate the object that will actually be thrown.
            var location = m_ThrowableItemPerpectiveProperties.ThrowLocation;

            m_InstantiatedThrownObject = ObjectPoolBase.Instantiate(m_ThrownObject, location.position, location.rotation, m_ObjectTransform.parent);
            m_InstantiatedThrownObject.transform.localScale = location.localScale;
            m_InstantiatedThrownObject.transform.SetLayerRecursively(m_StartLayer);
            m_InstantiatedTrajectoryObject = m_InstantiatedThrownObject.GetCachedComponent <TrajectoryObject>();
            if (m_InstantiatedTrajectoryObject == null)
            {
                Debug.LogError($"Error: {m_TrajectoryObject.name} must contain the TrajectoryObject component.");
                return;
            }
            if (m_InstantiatedTrajectoryObject is Destructible)
            {
                (m_InstantiatedTrajectoryObject as Destructible).InitializeDestructibleProperties(m_DamageProcessor, m_DamageAmount, m_ImpactForce, m_ImpactForceFrames,
                                                                                                  m_ImpactLayers, m_ImpactStateName, m_ImpactStateDisableTimer, m_SurfaceImpact);
            }
            // The trajectory object will be enabled when the object is thrown.
            m_InstantiatedTrajectoryObject.enabled = false;

            // Hide the object that isn't thrown.
            EnableObjectMeshRenderers(false);

            // The instantiated object may not immediately be visible.
            if (m_DisableVisibleObject)
            {
                m_InstantiatedThrownObject.SetActive(false);
                m_ActivateVisibleObject = false;
                m_Item.SetVisibleObjectActive(false, true);

                if (m_ActivateThrowableObjectEvent.WaitForAnimationEvent)
                {
                    EventHandler.RegisterEvent(m_Character, "OnAnimatorActivateThrowableObject", ActivateThrowableObject);
                }
                else
                {
                    SchedulerBase.ScheduleFixed(m_ActivateThrowableObjectEvent.Duration, ActivateThrowableObject);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Performs the cast.
        /// </summary>
        /// <param name="origin">The location that the cast should spawn from.</param>
        /// <param name="direction">The direction of the cast.</param>
        /// <param name="targetPosition">The target position of the cast.</param>
        public override void Cast(Transform origin, Vector3 direction, Vector3 targetPosition)
        {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            // The server will spawn the projectile.
            if (m_MagicItem.NetworkInfo != null)
            {
                if (m_MagicItem.NetworkInfo.IsLocalPlayer())
                {
                    m_MagicItem.NetworkCharacter.MagicCast(m_MagicItem, m_Index, m_CastID, direction, targetPosition);
                }
                if (!m_MagicItem.NetworkInfo.IsServer())
                {
                    return;
                }
            }
#endif

            if (m_ProjectilePrefab == null)
            {
                Debug.LogError("Error: A Projectile Prefab must be specified", m_MagicItem);
                return;
            }

            var position = Utility.MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset);
            var obj      = ObjectPoolBase.Instantiate(m_ProjectilePrefab, position,
                                                      Quaternion.LookRotation(direction, m_CharacterLocomotion.Up) * Quaternion.Euler(m_RotationOffset), m_ParentToOrigin ? origin : null);
            var projectile = obj.GetComponent <MagicProjectile>();
            if (projectile != null)
            {
                projectile.Initialize(direction * m_Speed, Vector3.zero, m_GameObject, m_MagicItem, m_CastID);
            }
            else
            {
                Debug.LogWarning($"Warning: The projectile {m_ProjectilePrefab.name} does not have the MagicProjectile component attached.");
            }
            var magicParticle = obj.GetComponent <MagicParticle>();
            if (magicParticle != null)
            {
                magicParticle.Initialize(m_MagicItem, m_CastID);
            }

#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_MagicItem.NetworkInfo != null)
            {
                NetworkObjectPool.NetworkSpawn(m_ProjectilePrefab, obj, true);
            }
#endif
        }
        /// <summary>
        /// The magic cast has collided with another object.
        /// </summary>
        /// <param name="hit">The raycast that caused the impact.</param>
        /// <param name="surfaceImpact">The type of particle that collided with the object.</param>
        private void MagicCastCollision(RaycastHit hit, SurfaceImpact surfaceImpact)
        {
            if (m_FlameParticle != null || (m_FlameImpact != null && m_FlameImpact != surfaceImpact))
            {
                return;
            }

            // A fireball has collided with the crate. Start the flame.
            var crateTransform = transform;
            var flamePrefab    = ObjectPoolBase.Instantiate(m_FlamePrefab, crateTransform.position, crateTransform.rotation);

            m_FlameParticle                   = flamePrefab.GetComponent <ParticleSystem>();
            m_FlameParticleAudioSource        = flamePrefab.GetCachedComponent <AudioSource>();
            m_FlameParticleAudioSource.volume = 1;
            m_DamageTrigger.enabled           = true;

            // The crate should be destroyed by the flame.
            ReduceHealth();
        }
Exemple #9
0
        /// <summary>
        /// Performs the cast.
        /// </summary>
        /// <param name="origin">The location that the cast should spawn from.</param>
        /// <param name="direction">The direction of the cast.</param>
        /// <param name="targetPosition">The target position of the cast.</param>
        public override void Cast(Transform origin, Vector3 direction, Vector3 targetPosition)
        {
            if (m_Object == null)
            {
                Debug.LogError("Error: An Object must be specified.", m_MagicItem);
                return;
            }

#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            // The local player will spawn the object if the object is a networked magic object.
            if (m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer())
            {
                if (m_Object.GetComponent <INetworkMagicObject>() != null)
                {
                    return;
                }
            }
#endif

            var position = MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset);
            if (targetPosition != position)
            {
                direction = (targetPosition - position).normalized;
            }
            m_SpawnedObject = ObjectPoolBase.Instantiate(m_Object, position,
                                                         Quaternion.LookRotation(direction, m_CharacterLocomotion.Up) * Quaternion.Euler(m_RotationOffset), m_ParentToOrigin ? origin : null);

#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_MagicItem.NetworkInfo != null && m_MagicItem.NetworkInfo.IsLocalPlayer())
            {
                var networkMagicObject = m_SpawnedObject.GetComponent <INetworkMagicObject>();
                if (networkMagicObject != null)
                {
                    networkMagicObject.Instantiate(m_GameObject, m_MagicItem, m_Index, m_CastID);
                }

                NetworkObjectPool.NetworkSpawn(m_Object, m_SpawnedObject, false);
            }
#endif
        }
Exemple #10
0
        /// <summary>
        /// Spawns the particle.
        /// </summary>
        /// <param name="origin">The location that the cast originates from.</param>
        private void Spawn(Transform origin)
        {
            if (m_ParticlePrefab == null)
            {
                Debug.LogError("Error: A Particle Prefab must be specified.", m_MagicItem);
                return;
            }

            var obj = ObjectPoolBase.Instantiate(m_ParticlePrefab, MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset),
                                                 origin.rotation * Quaternion.Euler(m_RotationOffset), m_ParentToOrigin ? origin : null);

            m_SpawnedTransform = obj.transform;
            var particleSystem = obj.GetCachedComponent <ParticleSystem>();

            if (particleSystem == null)
            {
                Debug.LogError($"Error: A Particle System must be specified on the particle {m_ParticlePrefab}.", m_MagicItem);
                return;
            }

            particleSystem.Clear(true);
        }
Exemple #11
0
        /// <summary>
        /// Instantiates a new decal.
        /// </summary>
        /// <param name="original">The original prefab to spawn an instance of.</param>
        /// <param name="hit">The RaycastHit which caused the footprint to spawn.</param>
        /// <param name="rotation">The rotation of the decal which should be spawned.</param>
        /// <param name="scale">The scale of the decal to spawn.</param>
        /// <param name="allowedEdgeOverlap">How close to the edge the footprint is allowed to spawn.</param>
        /// <returns>The spawned decal. Can be null.</returns>
        private GameObject SpawnDecal(GameObject original, RaycastHit hit, Quaternion rotation, float scale, float allowedEdgeOverlap)
        {
            // Prevent z fighting by slightly raising the decal off of the surface.
            var decal = ObjectPoolBase.Instantiate(original, hit.point + (hit.normal * 0.001f), rotation);

            // Only set the decal parent to the hit transform on uniform objects to prevent stretching.
            if (MathUtility.IsUniform(hit.transform.localScale))
            {
                decal.transform.parent = hit.transform;
            }
            if (scale != 1)
            {
                var vectorScale = Vector3.one;
                vectorScale.x = vectorScale.y = scale;
                decal.transform.localScale = vectorScale;
            }

            // Destroy the object if it cannot be cached. The object won't be able to be cached if it doesn't have all of the required components.
            if (!CacheMeshAndRenderer(decal))
            {
                ObjectPoolBase.Destroy(decal);
                return(null);
            }

            // Do a test on the decal's quad to ensure all four corners are flush against a surface. This will prevent the decal from sticking out on an edge.
            if (allowedEdgeOverlap < 0.5f)
            {
                if (!DoQuadTest(decal, allowedEdgeOverlap))
                {
                    ObjectPoolBase.Destroy(decal);
                    return(null);
                }
            }

            // The decal can be added.
            Add(decal);

            return(decal);
        }
Exemple #12
0
        /// <summary>
        /// Performs the cast.
        /// </summary>
        /// <param name="origin">The location that the cast should spawn from.</param>
        /// <param name="direction">The direction of the cast.</param>
        /// <param name="targetPosition">The target position of the cast.</param>
        public override void Cast(Transform origin, Vector3 direction, Vector3 targetPosition)
        {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_MagicItem.NetworkInfo != null && m_MagicItem.NetworkInfo.IsLocalPlayer())
            {
                m_MagicItem.NetworkCharacter.MagicCast(m_MagicItem, m_Index, m_CastID, direction, targetPosition);
            }
#endif

            var position = MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset);
            if (targetPosition != position)
            {
                direction = (targetPosition - position).normalized;
            }
            if (m_ProjectDirectionOnPlane)
            {
                direction = Vector3.ProjectOnPlane(direction, m_CharacterLocomotion.Up);
            }
            // The direction can't be 0.
            if (direction.sqrMagnitude == 0)
            {
                direction = m_CharacterLocomotion.transform.forward;
            }
            var rotation = Quaternion.LookRotation(direction, m_CharacterLocomotion.Up) * Quaternion.Euler(m_RotationOffset);

            // If the cast is currently active then the particle should be reused.
            if (m_Active)
            {
                if (m_SetRendererLengthScale)
                {
                    SetRendererLength(origin.position, targetPosition);
                }
                if (!m_ParentToOrigin)
                {
                    m_ParticleTransform.position = position;
                }
                m_ParticleTransform.rotation = rotation;
                return;
            }

            if (m_ParticlePrefab == null)
            {
                Debug.LogError("Error: A Particle Prefab must be specified.", m_MagicItem);
                return;
            }

#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            // The local player will spawn the particle if the object is a networked magic object.
            if (m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer())
            {
                if (m_ParticlePrefab.GetComponent <INetworkMagicObject>() != null)
                {
                    return;
                }
            }
#endif

            if (m_FadeEvent != null)
            {
                SchedulerBase.Cancel(m_FadeEvent);
                m_FadeEvent = null;
                SetRendererAlpha(0);
            }
            var obj = ObjectPoolBase.Instantiate(m_ParticlePrefab, position, rotation, m_ParentToOrigin ? origin : null);
            m_ParticleTransform = obj.transform;
            m_ParticleTransform.SetLayerRecursively(m_ParticleLayer);
            m_ParticleSystem = obj.GetCachedComponent <ParticleSystem>();

            if (m_ParticleSystem == null)
            {
                Debug.LogError($"Error: A Particle System must be specified on the particle {m_ParticlePrefab}.", m_MagicItem);
                return;
            }

            m_ParticleSystem.Clear(true);
            m_Renderers = null;
            if (m_SetRendererLengthScale)
            {
                SetRendererLength(origin.position, targetPosition);
            }
            StartMaterialFade(obj);

            // The MagicParticle can determine the impacts.
            var magicParticle = obj.GetComponent <MagicParticle>();
            if (magicParticle != null)
            {
                magicParticle.Initialize(m_MagicItem, m_CastID);
            }
            m_Active = true;

#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_MagicItem.NetworkInfo != null && m_MagicItem.NetworkInfo.IsLocalPlayer())
            {
                var networkMagicObject = obj.GetComponent <INetworkMagicObject>();
                if (networkMagicObject != null)
                {
                    networkMagicObject.Instantiate(m_GameObject, m_MagicItem, m_Index, m_CastID);
                }

                NetworkObjectPool.NetworkSpawn(m_ParticlePrefab, obj, false);
            }
#endif
        }
Exemple #13
0
        /// <summary>
        /// Drop an Item from the character.
        /// </summary>
        /// <param name="item">The item to drop.</param>
        /// <param name="forceDrop">Should the item be dropped even if the inventory doesn't contain any count for the item?</param>
        /// <param name="amount">The amount of ItemIdentifier that should be dropped.</param>
        /// <param name="remove">Should the item be removed after it is dropped?</param>
        /// <returns>The instance of the dropped item (can be null).</returns>
        public virtual GameObject DropItem(Item item, int amount, bool forceDrop, bool remove)
        {
            // The item needs to first be unequipped before it can be dropped.
            if (item.VisibleObjectActive && item.CharacterLocomotion.FirstPersonPerspective && remove)
            {
                item.UnequipDropAmount = amount;
                var itemObject = item.GetVisibleObject().transform;
                item.UnequpDropPosition  = itemObject.position;
                item.UnequipDropRotation = itemObject.rotation;
                return(null);
            }

            GameObject     spawnedObject = null;
            ItemPickupBase itemPickup    = null;

            // If a drop prefab exists then the character should drop a prefab of the item so it can later be picked up.
            if (item.DropPrefab != null)
            {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
                if (m_NetworkInfo == null || m_NetworkInfo.IsServer())
                {
#endif
                var existingAmount = GetItemIdentifierAmount(item.ItemIdentifier);
                if (existingAmount > 0)
                {
                    // If the usable item prevents the item from being equipped when empty, and the usable item is empty, then the item
                    // should not be dropped.
                    for (int i = 0; i < item.ItemActions.Length; ++i)
                    {
                        var usableItem = (item.ItemActions[i] as UsableItem);
                        if (usableItem != null && usableItem.GetConsumableItemIdentifier() != null &&
                            !usableItem.CanEquipEmptyItem && GetItemIdentifierAmount(usableItem.GetConsumableItemIdentifier()) == 0)
                        {
                            existingAmount = 0;
                            break;
                        }
                    }
                }
                // The prefab can be dropped if the inventory contains the item or is force dropped.
                if (existingAmount > 0 || forceDrop)
                {
                    Vector3    dropPosition;
                    Quaternion dropRotation;
                    // If the item is unequipped before it is dropped then it could be holstered so the current transform should not be used.
                    if (item.UnequipDropAmount > 0)
                    {
                        dropPosition = item.UnequpDropPosition;
                        dropRotation = item.UnequipDropRotation;
                    }
                    else
                    {
                        var itemObject = item.GetVisibleObject().transform;
                        dropPosition = itemObject.position;
                        dropRotation = itemObject.rotation;
                    }
                    spawnedObject = ObjectPoolBase.Instantiate(item.DropPrefab, dropPosition, dropRotation);
                    // The ItemPickup component is responsible for allowing characters to pick up the item. Save the ItemIdentifier count
                    // to the ItemIdentifierAmount array so that same amount can be picked up again.
                    itemPickup = spawnedObject.GetCachedComponent <ItemPickupBase>();
                    if (itemPickup != null)
                    {
                        // Return the old.
                        var itemDefinitionAmounts = itemPickup.GetItemDefinitionAmounts();
                        var itemDefinitionAmount  = new ItemDefinitionAmount(item.ItemIdentifier.GetItemDefinition(), Mathf.Min(existingAmount, amount));

                        // If the dropped Item is a usable item then the array should be larger to be able to pick up the usable ItemIdentifier.
                        var        consumableItemIdentifiers = 0;
                        UsableItem usableItem;
                        if (item.DropConsumableItems)
                        {
                            for (int i = 0; i < item.ItemActions.Length; ++i)
                            {
                                if ((usableItem = (item.ItemActions[i] as UsableItem)) != null &&
                                    usableItem.GetConsumableItemIdentifier() != null && usableItem.GetConsumableItemIdentifierAmount() != -1)
                                {
                                    consumableItemIdentifiers++;
                                }
                            }
                        }

                        // Save the main ItemIdentifier.
                        var length = consumableItemIdentifiers + 1;
                        if (itemDefinitionAmounts.Length != length)
                        {
                            itemDefinitionAmounts = new ItemDefinitionAmount[length];
                        }
                        itemDefinitionAmounts[0] = itemDefinitionAmount;

                        // Save the usable ItemIdentifier if any exist.
                        if (item.DropConsumableItems)
                        {
                            IItemIdentifier consumableItemIdentifier;
                            consumableItemIdentifiers = 1;
                            for (int i = 0; i < item.ItemActions.Length; ++i)
                            {
                                if ((usableItem = (item.ItemActions[i] as UsableItem)) != null && (consumableItemIdentifier = usableItem.GetConsumableItemIdentifier()) != null &&
                                    usableItem.GetConsumableItemIdentifierAmount() != -1)
                                {
                                    var consumableDropCount = 0;
                                    // Only remove the remaining inventory if there is just one ItemIdentifier remaining. This will allow the character to keep the consumable ammo
                                    // if only one item is dropped and the character has multiple of the same item.
                                    if (existingAmount == 1)
                                    {
                                        consumableDropCount = GetItemIdentifierAmount(consumableItemIdentifier);
                                    }
                                    var remainingConsumableAmount  = usableItem.GetConsumableItemIdentifierAmount();    // The count may be negative (for use by the UI).
                                    var consumableDefinitionAmount = new ItemDefinitionAmount(consumableItemIdentifier.GetItemDefinition(), consumableDropCount + (remainingConsumableAmount > 0 ? remainingConsumableAmount : 0));
                                    itemDefinitionAmounts[consumableItemIdentifiers] = consumableDefinitionAmount;
                                    consumableItemIdentifiers++;
                                }
                            }
                        }

                        // Enable the ItemPickup.
                        itemPickup.SetItemDefinitionAmounts(itemDefinitionAmounts);
                        itemPickup.Initialize(true);
                    }

                    // The ItemPickup may have a TrajectoryObject attached instead of a Rigidbody.
                    var trajectoryObject = spawnedObject.GetCachedComponent <Objects.TrajectoryObject>();
                    if (trajectoryObject != null)
                    {
                        var velocity = item.CharacterLocomotion.Velocity;
    #if ULTIMATE_CHARACTER_CONTROLLER_VR
                        if (item.HandHandler != null)
                        {
                            velocity += item.HandHandler.GetVelocity(item.SlotID) * item.DropVelocityMultiplier;
                        }
    #endif
                        trajectoryObject.Initialize(velocity, item.CharacterLocomotion.Torque.eulerAngles, item.Character);
                    }
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
                    if (m_NetworkInfo != null)
                    {
                        Networking.Game.NetworkObjectPool.NetworkSpawn(item.DropPrefab, spawnedObject, true);
                    }
#endif
                }
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            }
#endif
            }
            if (remove)
            {
                item.UnequipDropAmount = 0;
                RemoveItem(item.ItemIdentifier, item.SlotID, GetItemIdentifierAmount(item.ItemIdentifier), false);
            }

            if (item.DropItemEvent != null)
            {
                item.DropItemEvent.Invoke();
            }
            return(spawnedObject);
        }
Exemple #14
0
        /// <summary>
        /// The object is no longer alive.
        /// </summary>
        /// <param name="position">The position of the damage.</param>
        /// <param name="force">The amount of force applied to the object while taking the damage.</param>
        /// <param name="attacker">The GameObject that killed the character.</param>
        public virtual void Die(Vector3 position, Vector3 force, GameObject attacker)
        {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer())
            {
                m_NetworkHealthMonitor.Die(position, force, attacker);
            }
#endif

            // Spawn any objects on death, such as an explosion if the object is an explosive barrel.
            if (m_SpawnedObjectsOnDeath != null)
            {
                for (int i = 0; i < m_SpawnedObjectsOnDeath.Length; ++i)
                {
                    var       spawnedObject = ObjectPoolBase.Instantiate(m_SpawnedObjectsOnDeath[i], m_Transform.position, m_Transform.rotation);
                    Explosion explosion;
                    if ((explosion = spawnedObject.GetCachedComponent <Explosion>()) != null)
                    {
                        explosion.Explode(gameObject);
                    }
                    var rigidbodies = spawnedObject.GetComponentsInChildren <Rigidbody>();
                    for (int j = 0; j < rigidbodies.Length; ++j)
                    {
                        rigidbodies[j].AddForceAtPosition(force, position);
                    }
                }
            }

            // Destroy any objects on death. The objects will be placed back in the object pool if they were created within it otherwise the object will be destroyed.
            if (m_DestroyedObjectsOnDeath != null)
            {
                for (int i = 0; i < m_DestroyedObjectsOnDeath.Length; ++i)
                {
                    if (ObjectPoolBase.InstantiatedWithPool(m_DestroyedObjectsOnDeath[i]))
                    {
                        ObjectPoolBase.Destroy(m_DestroyedObjectsOnDeath[i]);
                    }
                    else
                    {
                        Object.Destroy(m_DestroyedObjectsOnDeath[i]);
                    }
                }
            }

            // Change the layer to a death layer.
            if (m_DeathLayer.value != 0)
            {
                m_AliveLayer       = m_GameObject.layer;
                m_GameObject.layer = m_DeathLayer;
            }

            // Play any take death audio. Use PlayAtPosition because the audio won't play if the GameObject is inactive.
            m_DeathAudioClipSet.PlayAtPosition(m_Transform.position);

            // Deactivate the object if requested.
            if (m_DeactivateOnDeath)
            {
                SchedulerBase.Schedule(m_DeactivateOnDeathDelay, Deactivate);
            }

            // The attributes shouldn't regenerate.
            if (m_ShieldAttribute != null)
            {
                m_ShieldAttribute.CancelAutoUpdate();
            }
            if (m_HealthAttribute != null)
            {
                m_HealthAttribute.CancelAutoUpdate();
            }

            // Notify those interested.
            EventHandler.ExecuteEvent <Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", position, force, attacker);
            if (m_OnDeathEvent != null)
            {
                m_OnDeathEvent.Invoke(position, force, attacker);
            }
        }