// --------------------------------------------------------------------------------------------------------------------
//
// 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
}
}