using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Serialization; namespace RayFire { [Serializable] public class RFDamage { [FormerlySerializedAs ("enable")] public bool en; [FormerlySerializedAs ("maxDamage")] public float max; [FormerlySerializedAs ("currentDamage")] public float cur; [FormerlySerializedAs ("collect")] public bool col; [FormerlySerializedAs ("multiplier")] public float mlt; [FormerlySerializedAs ("toShards")] public bool shr; /// ///////////////////////////////////////////////////////// /// Constructor /// ///////////////////////////////////////////////////////// // Constructor public RFDamage() { InitValues(); } // Reset public void InitValues() { en = false; max = 100f; cur = 0f; col = false; mlt = 1f; shr = false; } // Reset public void LocalReset() { cur = 0f; } // Pool Reset public void GlobalReset() { InitValues(); } // Copy from public void CopyFrom(RFDamage source) { en = source.en; max = source.max; col = source.col; mlt = source.mlt; shr = source.shr; LocalReset(); } /// ///////////////////////////////////////////////////////// /// Methods /// ///////////////////////////////////////////////////////// // Apply damage public static bool ApplyDamage (RayfireRigid scr, float value, Vector3 point, float radius, Collider collider) { // Initialize if not if (scr.initialized == false) { scr.Initialize(); // Set birth time before actual time to avoid BirthTime limitations check. scr.limitations.birthTime -= (scr.limitations.time + 1f); } // Already demolished or should be if (scr.limitations.demolished == true || scr.limitations.demolitionShould == true) return false; // Apply damage and get demolition state bool demolitionState = ApplyTo (scr, value, point, radius, collider); // Check for activation if (scr.activation.dmg > 0 && scr.damage.cur > scr.activation.dmg) scr.Activate(); // TODO demolish first to activate only demolished fragments AND activate if object can't be demolished // Set demolition info if (demolitionState == true) { // Demolition available check if (scr.DemolitionState() == false) return false; // Set damage position scr.limitations.contactVector3 = point; scr.clsDemol.damageRadius = radius; // Set small radius for cluster demolition by gun with 0 radius. IMPORTANT if (radius == 0) scr.clsDemol.damageRadius = 0.05f; // Demolish object scr.limitations.demolitionShould = true; // Demolish scr.DemolishForced(); // Mesh Was demolished if (scr.limitations.demolished == true) return true; // Cluster was if (scr.IsCluster == true) if (scr.HasFragments == true) return true; } return false; } // Add damage public static bool ApplyTo(RayfireRigid scr, float value, Vector3 point, float radius = 0f, Collider collider = null) { // Apply damage to connected cluster per shard level if (scr.objTp == ObjectType.ConnectedCluster && scr.damage.shr == true) return ApplyToShard (scr, value, point, radius, collider); // Apply to rigid itself return ApplyToRigid (scr, value); } /// ///////////////////////////////////////////////////////// /// To rigid /// ///////////////////////////////////////////////////////// // Add damage to Rigid public static bool ApplyToRigid(RayfireRigid scr, float damageValue) { // Add damage scr.damage.cur += damageValue; // Check if (scr.damage.en == true && scr.damage.cur >= scr.damage.max) return true; return false; } /// ///////////////////////////////////////////////////////// /// To shards /// ///////////////////////////////////////////////////////// // Add damage to shard public static bool ApplyToShard (RayfireRigid scr, float value, Vector3 point, float radius, Collider collider) { // Add damage by collider if (collider != null) return ApplyToShard (scr, value, collider); // Add damage by radius if (radius > 0) return ApplyToShards (scr, value, point, radius); return false; } // Add damage to shard by collider public static bool ApplyToShard(RayfireRigid scr, float value, Collider collider) { for (int i = 0; i < scr.clsDemol.cluster.shards.Count; i++) if (scr.clsDemol.cluster.shards[i].col == collider) { // Apply damage to shard scr.clsDemol.cluster.shards[i].dm += value; // Flag damaged shard if (scr.clsDemol.cluster.shards[i].dm > scr.damage.max) return true; // Skip checking whole list break; } return false; } // Add damage to shards in radius public static bool ApplyToShards(RayfireRigid scr, float value, Vector3 point, float radius) { // TODO use mask // bool maxReached = false; // int mask = scr.gameObject.layer; Collider[] colliders = Physics.OverlapSphere (point, radius); HashSet collidersHash = new HashSet(colliders); // Apply damage to shard for (int i = 0; i < scr.clsDemol.cluster.shards.Count; i++) if (collidersHash.Contains (scr.clsDemol.cluster.shards[i].col) == true) scr.clsDemol.cluster.shards[i].dm += value; // Flag damaged shard for (int i = 0; i < scr.clsDemol.cluster.shards.Count; i++) if (scr.clsDemol.cluster.shards[i].dm > scr.damage.max) return true; return false; } } }