// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using UltimateXR.Audio; using UltimateXR.Core.Components.Composite; using UltimateXR.Manipulation; using UnityEngine; namespace UltimateXR.Mechanics.Weapons { /// /// Component that, added to a with a collider, will allow to deflect shots coming from /// components. /// public class UxrProjectileDeflect : UxrGrabbableObjectComponent { #region Inspector Properties/Serialized Fields [SerializeField] private UxrAudioSample _audioDeflect; [SerializeField] private UxrImpactDecal _decalOnReflect; [SerializeField] private float _decalLife = 5.0f; [SerializeField] private float _decalFadeoutDuration = 1.0f; [SerializeField] private bool _twoSidedDecal; [SerializeField] private float _twoSidedDecalThickness = 0.01f; [SerializeField] private LayerMask _collideLayersAddOnReflect = 0; #endregion #region Public Types & Data /// /// Event called when a projectile got deflected after hitting the object. /// public event EventHandler ProjectileDeflected; /// /// Gets the sound to play when a projectile was deflected. /// public UxrAudioSample AudioDeflect => _audioDeflect; /// /// Gets the decal to instantiate when a projectile was deflected. /// public UxrImpactDecal DecalOnReflect => _decalOnReflect; /// /// Gets the decal life in seconds after which it will fade out and be destroyed. /// public float DecalLife => _decalLife; /// /// Gets the decal fadeout duration in seconds. /// public float DecalFadeoutDuration => _decalFadeoutDuration; /// /// Gets whether the decal requires to generate another copy on the other side. /// public bool TwoSidedDecal => _twoSidedDecal; /// /// Gets the object thickness in order to know how far the other side is to generate the copy on the backside of the /// impact. /// public float TwoSidedDecalThickness => _twoSidedDecalThickness; /// /// Optional layer mask to add to the collider after a projectile was deflected. /// public LayerMask CollideLayersAddOnReflect => _collideLayersAddOnReflect; /// /// Gets the owner in case the deflection object is part of an avatar or can be grabbed. /// public UxrActor Owner { get; private set; } #endregion #region Unity /// /// Initializes the component. /// protected override void Start() { base.Start(); Owner = GetComponentInParent(); } #endregion #region Event Trigger Methods /// /// Called when the object was grabbed. Will change the . /// /// Event parameters protected override void OnObjectGrabbed(UxrManipulationEventArgs e) { base.OnObjectGrabbed(e); if (e.IsGrabbedStateChanged && UxrGrabManager.Instance.GetGrabbingHand(e.GrabbableObject, e.GrabPointIndex, out UxrGrabber grabber)) { Owner = grabber.Avatar.GetComponentInChildren(); } } /// /// Called when the object was released. Will reset the . /// /// Event parameters protected override void OnObjectReleased(UxrManipulationEventArgs e) { base.OnObjectReleased(e); if (e.IsGrabbedStateChanged) { Owner = null; } } /// /// Called when the object was released. Will reset the . /// /// Event parameters protected override void OnObjectPlaced(UxrManipulationEventArgs e) { base.OnObjectPlaced(e); if (e.IsGrabbedStateChanged && UxrGrabManager.Instance.GetGrabbingHand(e.GrabbableObject, e.GrabPointIndex, out UxrGrabber grabber)) { Owner = null; } } /// /// Raises the event. /// /// Event parameters internal void RaiseProjectileDeflected(UxrDeflectEventArgs e) { ProjectileDeflected?.Invoke(this, e); } #endregion #region Protected Overrides UxrGrabbableObjectComponent /// /// The grabbable object is not required. When it is present it will be used to assign the so that /// the damage will be attributed to the actor instead of the original source. /// protected override bool IsGrabbableObjectRequired => false; #endregion } }