Example #1
0
        public void OnDamageTaken(Entity source, DamageInfo damageInfo)
        {
            Vector3 point  = damageInfo.point.HasValue ? damageInfo.point.Value : transform.position;
            Vector3 normal = damageInfo.normal.HasValue ? damageInfo.normal.Value : transform.forward;

            if (referenceCamera)
            {
                if ((point - referenceCamera.transform.position).sqrMagnitude > maxDistanceFromCamera * maxDistanceFromCamera)
                {
                    return;
                }
            }

            // Verify a TextParticle prefab is specified
            if (textParticlePrefab)
            {
                // Instantiate a TextParticle
                TextParticle clone = Instantiate(textParticlePrefab, point, Quaternion.LookRotation(-normal)) as TextParticle;

                // Set TextParticle's text, color, and gravity values
                clone.text    = damageInfo.damage.ToString();
                clone.color   = damageInfo.critical ? criticalDamageColor : standardDamageColor;
                clone.gravity = particleGravity;

                // Calculate and set startVelocity for TextParticle based on impact normal (-clone.transform.forward) and random values
                Vector3 velocity = clone.transform.forward.RandomSpread(normalMaxSpreadAngle) * Random.Range(normalVelocityMin, normalVelocityMax) * (flipNormalVelocity ? 1 : -1);
                velocity.y         += Random.Range(upVelocityMin, upVelocityMax);
                clone.startVelocity = velocity;

                // If scale and transparency AnimationCurves specified, set them for the TextParticle
                if (particleScaleOverLifetime.keys.Length > 0)
                {
                    clone.scaleOverLifetime = particleScaleOverLifetime;
                }
                if (particleTransparencyOverLifetime.keys.Length > 0)
                {
                    clone.transparencyOverLifetime = particleTransparencyOverLifetime;
                }

                // Show a corresponding Critical Message if needed
                if (damageInfo.critical && showCriticalMessage)
                {
                    // Clone a new TextParticle for critical message
                    clone = Instantiate(textParticlePrefab, point, Quaternion.LookRotation(-normal)) as TextParticle;

                    // Set critical message text, color and gravity values
                    clone.text    = criticalMessage;
                    clone.color   = criticalMessageColor;
                    clone.gravity = criticalMessageGravity;

                    // Calculate and set velocity as usual, then multiply by criticalVelocityMultiplier to accentuate this particle
                    velocity            = clone.transform.forward.RandomSpread(normalMaxSpreadAngle) * Random.Range(normalVelocityMin, normalVelocityMax) * (flipNormalVelocity ? 1 : -1);
                    velocity.y         += Random.Range(upVelocityMin, upVelocityMax);
                    velocity           *= criticalVelocityMultiplier;
                    clone.startVelocity = velocity;

                    // Set AnimationCurves if provided
                    if (criticalScaleOverLifetime.keys.Length > 0)
                    {
                        clone.scaleOverLifetime = criticalScaleOverLifetime;
                    }
                    if (criticalTransparencyOverLifetime.keys.Length > 0)
                    {
                        clone.transparencyOverLifetime = criticalTransparencyOverLifetime;
                    }
                }
            }
        }
Example #2
0
 void OnEntityDamaged(Entity source, DamageInfo info)
 {
     // Reset regen enabled timer and disable regeneration for now.
     regenEnableTime = Time.time + damageResetTime;
     regenEnabled    = false;
 }
        // Main method for handling collision and instantiating prefabs.
        protected virtual bool HandleCollision(Collider otherCollider, Vector3 point, Vector3 normal)
        {
            // If specified, unparent any active particles and allow them to continue
            if (unparentParticles)
            {
                ParticleSystem[] particles = GetComponentsInChildren <ParticleSystem>();

                foreach (ParticleSystem particle in particles)
                {
                    if (particle.isPlaying)
                    {
                        // Stop the particle from continuing to add new particles.
                        particle.Stop();

                        particle.transform.parent = null;
                        // Add the DestroyAfterParticlesComplete which will destroy the orphaned object when particles are done.
                        particle.gameObject.AddComponent <DestroyAfterParticlesComplete>();
                    }
                }
            }

            // Instantiate prefabs

            // Obtain layer and tag of collided object.
            int    otherLayer  = 1 << otherCollider.gameObject.layer;
            string otherTag    = otherCollider.gameObject.tag;
            bool   prefabAdded = false;

            // Iterate through each potential impact prefab and check if the collided object is valid for it to be instantiated.
            foreach (ImpactPrefab impactPrefab in impactPrefabs)
            {
                // If the collided objects meets the following criteria
                // Note:  The if statement is setup to short circuit with fastest checks up front and slower checks at the back.
                if (impactPrefab.prefab &&                                                                      // If a prefab specified AND
                    !(prefabAdded & impactPrefab.exclusive) &&                                                  // No prefab already instantiated while this one is exclusive AND
                    ((otherLayer & impactPrefab.validLayers) != 0 ||                                            // (  Valid layer  OR
                     System.Array.IndexOf(impactPrefab.validTags, otherTag) >= 0 ||                             //    Valid tag OR
                     ContainsBehaviour(otherCollider.gameObject, impactPrefab.validTypes)) &&                   //    Valid MonoBehaviour type  )  AND
                    !ContainsBehaviour(otherCollider.gameObject, impactPrefab.excludeTypes))                    // Does not contain excluded MonoBehaviours
                {
                    // Phew!  If we've passed the above, instantiate the prefab.

                    // Calculate prefab rotation based on settings
                    Quaternion prefabRotation = Quaternion.LookRotation(-normal * (impactPrefab.flipFaceDirection ? -1 : 1)) * Quaternion.Euler(0, 0, Random.Range(impactPrefab.prefabRotationMin, impactPrefab.prefabRotationMax));
                    GameObject clone          = Instantiate(impactPrefab.prefab, point + normal * impactPrefab.prefabNormalOffset, prefabRotation) as GameObject;
                    clone.transform.localScale = Vector3.one * impactPrefab.prefabScale;
                    // Attach to collided object if specified
                    if (impactPrefab.attachToCollisionObject)
                    {
                        clone.transform.parent = otherCollider.transform;
                    }

                    prefabAdded = true;
                }
            }

            // If impactForce specified and collision is with a rigidbody, add impact force.
            Rigidbody otherRigidbody = otherCollider.GetComponent <Rigidbody>();

            if (impactForce != 0 && otherRigidbody)
            {
                otherRigidbody.AddForceAtPosition(normal * -impactForce, point, ForceMode.Impulse);
            }

            // If we collided with an Entity, add damage to it.
            Entity entity = otherCollider.gameObject.GetComponentInParent <Entity>();

            if (entity)
            {
                // Add damage details of impact to damageInfo structure.
                damageInfo.critical = Random.Range(0f, 1.0f) <= criticalChance;
                damageInfo.damage   = damageInfo.critical ? Random.Range(criticalDamageMin, criticalDamageMax + 1) : Random.Range(damageMin, damageMax + 1);
                damageInfo.point    = point;
                damageInfo.normal   = normal;
                // Tell Entity to take damage.
                entity.TakeDamage(damageInfo);
            }

            // If explosionForce specified, add explosive force to any rigidbodies within explosionRadius
            if (explosionForce != 0)
            {
                // Save explosionRadius squared for comparison
                float explosionRadiusSquared = explosionRadius * explosionRadius;

                // Get all rigidbodies in scene and iterate through each to see if it is within explosionRadius
                Rigidbody[] allRigidBodies = GameObject.FindObjectsOfType <Rigidbody>();
                foreach (Rigidbody rb in allRigidBodies)
                {
                    Vector3 vectorToRigidbody = rb.position - point;
                    // If the rigidbody is within the explosionRadius, apply explosionForce
                    if (explosionRadius == 0 || vectorToRigidbody.sqrMagnitude <= explosionRadiusSquared)
                    {
                        // Add explosion force.
                        rb.AddExplosionForce(explosionForce, point, explosionRadius);

                        // If the rigidbody is an entity and not the one of the direct hit, apply damage
                        Entity rbEntity = rb.gameObject.GetComponentInParent <Entity>();
                        if (rbEntity != null && rbEntity != entity)
                        {
                            // Calculate explosion damage based on proximity to explosion and radius.
                            float explosionProximityRatio = Mathf.InverseLerp(explosionRadiusSquared, 0, vectorToRigidbody.sqrMagnitude);
                            int   explosiveDamage         = (int)((float)Random.Range(damageMin, damageMax + 1) * explosionProximityRatio);
                            if (explosiveDamage > 0)
                            {
                                // Apply damage to Entity caught in explosion
                                DamageInfo explosionDamageInfo = new DamageInfo(explosiveDamage, false, rb.position, vectorToRigidbody.normalized, damageInfo.source);
                                rbEntity.TakeDamage(explosionDamageInfo);
                            }
                        }
                    }
                }
            }

            // Stop this projectile
            mVelocity *= 0;

            if (mCollider)
            {
                mCollider.isTrigger = true;
            }
            if (mRigidbody)
            {
                mRigidbody.isKinematic = true;
                mRigidbody.position    = point;
                Destroy(mRigidbody);
            }

            // Set position to that of the point of impact
            transform.position = point;
            // Stop raycasting per frame.
            raycastPerFrame = false;

            // Destroy this Projectile either immediately or with specified delay.
            if (postponeDestroyTime == 0)
            {
                Destroy(gameObject);
            }
            else
            {
                Destroy(gameObject, postponeDestroyTime);
            }

            return(true);
        }