private static void ParseDamageTypeDefinition(string gameConstantsFilePath)
        {
            Debug.Assert(gameConstantsFilePath != null, nameof(gameConstantsFilePath) + " != null");
            Debug.Assert(File.Exists(gameConstantsFilePath), nameof(gameConstantsFilePath) + " must exist");
            XDocument gameConstantsFile = XDocument.Load(gameConstantsFilePath);

            Debug.Assert(gameConstantsFile.Root != null, "gameConstantsFile.Root != null");
            foreach (XElement xElement in gameConstantsFile.Root.Elements())
            {
                if (!xElement.Name.ToString().Equals(Tags.DAMAGE_TYPES, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                List <Damage> damages = DamageUtility.ParseFromString(xElement.Value);
                foreach (Damage damage in damages)
                {
                    if (GlobalStore.DAMAGE_REGISTRY.Contains(damage))
                    {
                        Debug.Assert(damage != null, nameof(commons.damage) + " != null");
                        Log.Warning(
                            $"Found duplicated damage type definition \"{damage.Name}\" was previously defined.");
                        continue;
                    }

                    GlobalStore.DAMAGE_REGISTRY.Add(damage);
                }

                break;
            }
        }
Esempio n. 2
0
    public void Damage(float damageAmount)
    {
        //subtract damage amount when Damage function is called
        currentHealth -= damageAmount;

        //Check if health has fallen below zero
        if (currentHealth <= 0)
        {
            currentHealth = 0;
            if (gameObject.tag != "Player")
            {
                //if health has fallen below zero, deactivate it
                gameObject.SetActive(false);
                if (explosionParticle)
                {
                    Instantiate(explosionParticle, this.transform.position, Quaternion.identity);
                    // var obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    // obj.name = "tester";
                    // obj.transform.localScale = new Vector3(10, 10, 10);
                    // obj.transform.position = gameObject.transform.position;
                    // print("radius is " + obj.GetComponent<SphereCollider>().radius.ToString());
                    DamageUtility.AreaDamageThings(gameObject.transform.position, 20, 70.0f);
                }
            }
            else
            {
                UnityEngine.SceneManagement.SceneManager.LoadScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
            }
        }

        if (TookDamage != null)
        {
            TookDamage(damageAmount, currentHealth);
        }
    }
Esempio n. 3
0
    public IEnumerator AttackVFX(Transform _start, IDestructible _end, float _time, bool _miss = false)
    {
        var T = 0.0f;

        line.SetPosition(0, _start.position);
        line.SetPosition(1, _start.position);

        var endPos = _miss ? DamageUtility.GetMissPosition(_start, _end.GetTransform(), _end.SizeType) : _start.position;

        while (T < _time)
        {
            if (!_miss)
            {
                endPos = Vector3.MoveTowards(line.GetPosition(1), _end.GetPointToAttack(_start.position), speed * Time.deltaTime);
            }

            line.SetPosition(0, _start.position);
            line.SetPosition(1, endPos);

            yield return(null);

            T += Time.deltaTime;
        }

        HideLaser();
    }
Esempio n. 4
0
    protected virtual IEnumerator Attack()
    {
        //Подготовка к выстрелу
        yield return(Preparation());

        GetTarget();

        if (target == null)
        {
            yield break;
        }

        var destructible = target.destructible;

        if (destructible == null)
        {
            yield break;
        }

        //Попадание
        if (DamageUtility.CheckHit(data, target, Vector3.Distance(transform.position, target.transform.position)))
        {
            yield return(effects.AttackVFX(startPos, destructible, rate * timeLerpRateToAttack));

            var damage = new Damage(armorDamage, shieldDamage, critical, accuracy);
            destructible.ApplyDamage(damage, startPos.position);
        }
        else
        {
            yield return(effects.AttackVFX(startPos, destructible, rate * timeLerpRateToAttack, true));

            destructible.ApplyMiss(startPos.position);
        }
    }
Esempio n. 5
0
        public void ParseFromString_Test()
        {
            List <Damage> l = DamageUtility.ParseFromString(DAMAGE_STRING);

            Assert.IsNotNull(l);
            Assert.IsTrue(l.Any());
            Assert.AreEqual(99, l.Count);
        }
Esempio n. 6
0
    //отрицательное значение - урон, положительное - ремонт
    private float CalculateDamageArmor(Damage _damage)
    {
        //var result = -_damage.ArmorDmg;
        var result = -DamageUtility.GetDamageValue(_damage, true);

        //var armor = GetArmor();
        //TODO:

        return(result);
    }
Esempio n. 7
0
    //отрицательное значение - урон, положительное - ремонт
    private float CalculateDamageShield(Damage _damage)
    {
        //var result = -_damage.ShieldDmg;
        var result = -DamageUtility.GetDamageValue(_damage, false);

        //var shield = GetShield();
        //TODO:

        return(result);
    }
Esempio n. 8
0
        public void ParseFromString_TestNullEmptyOrWhitespace()
        {
            List <Damage> l0 = DamageUtility.ParseFromString(null);

            Assert.IsNotNull(l0);
            Assert.IsFalse(l0.Any());
            List <Damage> l1 = DamageUtility.ParseFromString(string.Empty);

            Assert.IsNotNull(l1);
            Assert.IsFalse(l1.Any());
            List <Damage> l2 = DamageUtility.ParseFromString("\n \t\r\n");

            Assert.IsNotNull(l2);
            Assert.IsFalse(l2.Any());
        }
Esempio n. 9
0
        public static IEnumerable <XElement> ParseDamageToArmourMatrixAsXElement()
        {
            List <XElement> elements = new List <XElement>();

            foreach (Damage damage in DamageUtility.GetAll())
            {
                if (damage.IsBuiltInType)
                {
                    elements.AddRange(from damageToArmour in GetDamageToArmourMatrixByDamage(damage) where Math.Abs(damageToArmour.DamageToArmourFactor - 1.0f) > 0.000001f select damageToArmour.ToXElement());
                }
                else
                {
                    elements.AddRange(GetDamageToArmourMatrixByDamage(damage).Select(damageToArmour => damageToArmour.ToXElement()));
                }
            }

            return(elements);
        }
Esempio n. 10
0
        /// <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)
        {
            var damageTarget = DamageUtility.GetDamageTarget(target);

            if (damageTarget == null || !damageTarget.IsAlive())
            {
                if (m_InterruptImpactOnNullHealth)
                {
                    m_MagicItem.InterruptImpact();
                }
                return;
            }
            var pooledDamageData = GenericObjectPool.Get <DamageData>();

            pooledDamageData.SetDamage(m_Amount, source.transform.position, (source.transform.position - target.transform.position), m_ForceMagnitude, m_ForceFrames, 0, source, this, null);
            if (m_DamageProcessor == null)
            {
                m_DamageProcessor = DamageProcessor.Default;
            }
            m_DamageProcessor.Process(damageTarget, pooledDamageData);
            GenericObjectPool.Return(pooledDamageData);
        }
Esempio n. 11
0
        /// <summary>
        /// The object has collided with another object.
        /// </summary>
        /// <param name="hit">The RaycastHit of the object. Can be null.</param>
        protected override void OnCollision(RaycastHit?hit)
        {
            base.OnCollision(hit);

            var forceDestruct = false;

            if (m_CollisionMode == CollisionMode.Collide)
            {
                // When there is a collision the object should move to the position that was hit so if it's not destroyed then it looks like it
                // is penetrating the hit object.
                if (hit != null && hit.HasValue && m_Collider != null)
                {
                    var closestPoint = m_Collider.ClosestPoint(hit.Value.point);
                    m_Transform.position += (hit.Value.point - closestPoint);
                    // Only set the parent to the hit transform on uniform objects to prevent stretching.
                    if (MathUtility.IsUniform(hit.Value.transform.localScale))
                    {
                        // The parent layer must be within the sticky layer mask.
                        if (MathUtility.InLayerMask(hit.Value.transform.gameObject.layer, m_StickyLayers))
                        {
                            m_Transform.parent = hit.Value.transform;

                            // If the destructible sticks to a character then the object should be added as a sub collider so collisions will be ignored.
                            m_StickyCharacterLocomotion = hit.Value.transform.gameObject.GetCachedComponent <UltimateCharacterLocomotion>();
                            if (m_StickyCharacterLocomotion != null)
                            {
                                m_StickyCharacterLocomotion.AddIgnoredCollider(m_Collider);
                            }
                        }
                        else
                        {
                            forceDestruct = true;
                        }
                    }
                }
                if (m_TrailRenderer != null)
                {
                    m_TrailRenderer.enabled = false;
                }
            }

            var destructionDelay = m_DestructionDelay;

            if (m_ParticleSystem != null && m_WaitForParticleStop)
            {
                destructionDelay = m_ParticleSystem.main.duration;
                m_ParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmitting);
                Stop();
            }

            // The object may not have been initialized before it collides.
            if (m_GameObject == null)
            {
                InitializeComponentReferences();
            }

            if (hit != null && hit.HasValue)
            {
                var hitValue      = hit.Value;
                var hitGameObject = hitValue.collider.gameObject;
                // The shield can absorb some (or none) of the damage from the destructible.
                var damageAmount = m_DamageAmount;
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
                ShieldCollider shieldCollider;
                if ((shieldCollider = hitGameObject.GetCachedComponent <ShieldCollider>()) != null)
                {
                    damageAmount = shieldCollider.Shield.Damage(this, damageAmount);
                }
#endif

                // Allow a custom event to be received.
                EventHandler.ExecuteEvent <float, Vector3, Vector3, GameObject, object, Collider>(hitGameObject, "OnObjectImpact", damageAmount, hitValue.point, m_Velocity.normalized * m_ImpactForce, m_Originator, this, hitValue.collider);
                if (m_OnImpactEvent != null)
                {
                    m_OnImpactEvent.Invoke(damageAmount, hitValue.point, m_Velocity.normalized * m_ImpactForce, m_Originator);
                }

                // If the shield didn't absorb all of the damage then it should be applied to the character.
                if (damageAmount > 0)
                {
                    var damageTarget = DamageUtility.GetDamageTarget(hitGameObject);
                    if (damageTarget != null)
                    {
                        var pooledDamageData = GenericObjectPool.Get <DamageData>();
                        pooledDamageData.SetDamage(this, damageAmount, hitValue.point, -hitValue.normal, m_ImpactForce, m_ImpactForceFrames, 0, hitValue.collider);
                        var damageProcessorModule = hitGameObject.GetCachedComponent <DamageProcessorModule>();
                        if (damageProcessorModule != null)
                        {
                            damageProcessorModule.ProcessDamage(m_DamageProcessor, damageTarget, pooledDamageData);
                        }
                        else
                        {
                            if (m_DamageProcessor == null)
                            {
                                m_DamageProcessor = DamageProcessor.Default;
                            }
                            m_DamageProcessor.Process(damageTarget, pooledDamageData);
                        }
                        GenericObjectPool.Return(pooledDamageData);
                    }
                    else if (m_ImpactForce > 0)
                    {
                        // If the damage target exists it will apply a force to the rigidbody in addition to procesing the damage. Otherwise just apply the force to the rigidbody.
                        var collisionRigidbody = hitGameObject.GetCachedParentComponent <Rigidbody>();
                        if (collisionRigidbody != null && !collisionRigidbody.isKinematic)
                        {
                            collisionRigidbody.AddForceAtPosition(m_ImpactForce * MathUtility.RigidbodyForceMultiplier * -hitValue.normal, hitValue.point);
                        }
                        else
                        {
                            var forceObject = hitGameObject.GetCachedParentComponent <IForceObject>();
                            if (forceObject != null)
                            {
                                forceObject.AddForce(m_Transform.forward * m_ImpactForce);
                            }
                        }
                    }
                }

                // An optional state can be activated on the hit object.
                if (!string.IsNullOrEmpty(m_ImpactStateName))
                {
                    StateManager.SetState(hitGameObject, m_ImpactStateName, true);
                    // If the timer isn't -1 then the state should be disabled after a specified amount of time. If it is -1 then the state
                    // will have to be disabled manually.
                    if (m_ImpactStateDisableTimer != -1)
                    {
                        StateManager.DeactivateStateTimer(hitGameObject, m_ImpactStateName, m_ImpactStateDisableTimer);
                    }
                }
            }

            // The object can destroy itself after a small delay.
            if (m_DestroyEvent == null && (m_DestroyOnCollision || forceDestruct || destructionDelay > 0))
            {
                m_DestroyEvent = SchedulerBase.ScheduleFixed(destructionDelay, Destruct, hit);
            }
        }
Esempio n. 12
0
 private static void SaveToGameConstantsFilePrepare([NotNull] string gameConstantsFilePath)
 {
     DamageUtility.CleanDamageDeclaration(gameConstantsFilePath);
     ArmourUtility.CleanArmourDeclaration(gameConstantsFilePath);
     DamageToArmourUtility.CleanDamageToArmourDeclaration(gameConstantsFilePath);
 }
Esempio n. 13
0
 private static void SaveToGameConstantsFileInternal([NotNull] string gameConstantsFilePath)
 {
     XmlUtility.ReplaceValueForTag(gameConstantsFilePath, Tags.DAMAGE_TYPES, DamageUtility.GetAllAsString());
     XmlUtility.ReplaceValueForTag(gameConstantsFilePath, Tags.ARMOR_TYPES, ArmourUtility.GetAllAsString());
     XmlUtility.InsertElement(gameConstantsFilePath, DamageToArmourUtility.ParseDamageToArmourMatrixAsXElement(), Tags.ARMOR_TYPES);
 }
Esempio n. 14
0
        /// <summary>
        /// Do the explosion.
        /// </summary>
        /// <param name="damageAmount">The amount of damage to apply to the hit objects.</param>
        /// <param name="impactForce">The amount of force to apply to the hit object.</param>
        /// <param name="impactForceFrames">The number of frames to add the force to.</param>
        /// <param name="originator">The originator of the object.</param>
        public void Explode(float damageAmount, float impactForce, int impactForceFrames, GameObject originator)
        {
            Rigidbody    colliderRigidbody = null;
            IForceObject forceObject       = null;
            var          hitCount          = Physics.OverlapSphereNonAlloc(m_Transform.position, m_Radius, m_CollidersHit, m_ImpactLayers, QueryTriggerInteraction.Ignore);

#if UNITY_EDITOR
            if (hitCount == m_MaxCollisionCount)
            {
                Debug.LogWarning("Warning: The maximum number of colliders have been hit by " + m_GameObject.name + ". Consider increasing the Max Collision Count value.");
            }
#endif
            for (int i = 0; i < hitCount; ++i)
            {
                // A GameObject can contain multiple colliders. Prevent the explosion from occurring on the same GameObject multiple times.
                if (m_ObjectExplosions.Contains(m_CollidersHit[i].gameObject))
                {
                    continue;
                }
                m_ObjectExplosions.Add(m_CollidersHit[i].gameObject);
                // The base character GameObject should only be checked once.
                if ((forceObject = m_CollidersHit[i].gameObject.GetCachedParentComponent <IForceObject>()) != null)
                {
                    if (m_ObjectExplosions.Contains(forceObject))
                    {
                        continue;
                    }
                    m_ObjectExplosions.Add(forceObject);
                }

                // OverlapSphere can return objects that are in a different room. Perform a cast to ensure the object is within the explosion range.
                if (m_LineOfSight)
                {
                    // Add a slight vertical offset to prevent a floor collider from getting in the way of the cast.
                    var position  = m_Transform.TransformPoint(0, 0.1f, 0);
                    var direction = m_CollidersHit[i].transform.position - position;
                    if (Physics.Raycast(position - direction.normalized * 0.1f, direction, out m_RaycastHit, direction.magnitude, m_ImpactLayers, QueryTriggerInteraction.Ignore) &&
                        !(m_RaycastHit.transform.IsChildOf(m_CollidersHit[i].transform)
#if FIRST_PERSON_CONTROLLER
                          // The cast should not hit any colliders who are a child of the camera.
                          || m_RaycastHit.transform.gameObject.GetCachedParentComponent <FirstPersonController.Character.FirstPersonObjects>() != null
#endif
                          ))
                    {
                        // If the collider is part of a character then ensure the head can't be hit.
                        var parentAnimator = m_CollidersHit[i].transform.gameObject.GetCachedParentComponent <Animator>();
                        if (parentAnimator != null && parentAnimator.isHuman)
                        {
                            var head = parentAnimator.GetBoneTransform(HumanBodyBones.Head);
                            direction = head.position - position;
                            if (Physics.Raycast(position, direction, out m_RaycastHit, direction.magnitude, m_ImpactLayers, QueryTriggerInteraction.Ignore) &&
                                !m_RaycastHit.transform.IsChildOf(m_CollidersHit[i].transform) && !m_CollidersHit[i].transform.IsChildOf(m_RaycastHit.transform) &&
                                m_RaycastHit.transform.IsChildOf(m_Transform)
#if FIRST_PERSON_CONTROLLER
                                // The cast should not hit any colliders who are a child of the camera.
                                && m_RaycastHit.transform.gameObject.GetCachedParentComponent <FirstPersonController.Character.FirstPersonObjects>() == null
#endif
                                )
                            {
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                }

                // The shield can absorb some (or none) of the damage from the explosion.
                var hitDamageAmount = damageAmount;
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
                ShieldCollider shieldCollider;
                if ((shieldCollider = m_CollidersHit[i].transform.gameObject.GetCachedComponent <ShieldCollider>()) != null)
                {
                    hitDamageAmount = shieldCollider.Shield.Damage(this, hitDamageAmount);
                }
#endif

                // ClosestPoint only works with a subset of collider types.
                Vector3 closestPoint;
                if (m_CollidersHit[i] is BoxCollider || m_CollidersHit[i] is SphereCollider || m_CollidersHit[i] is CapsuleCollider || (m_CollidersHit[i] is MeshCollider && (m_CollidersHit[i] as MeshCollider).convex))
                {
                    closestPoint = m_CollidersHit[i].ClosestPoint(m_Transform.position);
                }
                else
                {
                    closestPoint = m_CollidersHit[i].ClosestPointOnBounds(m_Transform.position);
                }
                var hitDirection = closestPoint - m_Transform.position;

                // Allow a custom event to be received.
                EventHandler.ExecuteEvent <float, Vector3, Vector3, GameObject, object, Collider>(m_CollidersHit[i].transform.gameObject, "OnObjectImpact", hitDamageAmount, closestPoint, hitDirection * m_ImpactForce, originator, this, m_CollidersHit[i]);
                if (m_OnImpactEvent != null)
                {
                    m_OnImpactEvent.Invoke(hitDamageAmount, closestPoint, hitDirection * m_ImpactForce, originator);
                }

                // If the shield didn't absorb all of the damage then it should be applied to the character.
                if (hitDamageAmount > 0)
                {
                    var damageTarget = DamageUtility.GetDamageTarget(m_CollidersHit[i].gameObject);
                    if (damageTarget != null)
                    {
                        // If the Damage Target exists it will apply an explosive force to the character/character in addition to deducting the health.
                        // Otherwise just apply the force to the character/rigidbody.
                        var pooledDamageData = GenericObjectPool.Get <DamageData>();
                        var damageModifier   = Mathf.Max(1 - (hitDirection.magnitude / m_Radius), 0.01f);
                        pooledDamageData.SetDamage(hitDamageAmount * damageModifier, m_Transform.position, hitDirection.normalized, impactForce * damageModifier, impactForceFrames, m_Radius, originator, this, null);
                        if (m_DamageProcessor == null)
                        {
                            m_DamageProcessor = DamageProcessor.Default;
                        }
                        m_DamageProcessor.Process(damageTarget, pooledDamageData);
                        GenericObjectPool.Return(pooledDamageData);
                    }
                    else if (forceObject != null)
                    {
                        var damageModifier = Mathf.Max(1 - (hitDirection.magnitude / m_Radius), 0.01f);
                        forceObject.AddForce(impactForce * damageModifier * hitDirection.normalized);
                    }
                    else if ((colliderRigidbody = m_CollidersHit[i].gameObject.GetCachedComponent <Rigidbody>()) != null)
                    {
                        colliderRigidbody.AddExplosionForce(impactForce * MathUtility.RigidbodyForceMultiplier, m_Transform.position, m_Radius);
                    }
                }
            }
            m_ObjectExplosions.Clear();

            // An audio clip can play when the object explodes.
            m_ExplosionAudioClipSet.PlayAudioClip(m_GameObject);

            m_DestructionEvent = SchedulerBase.Schedule(m_Lifespan, Destroy);
        }