/// --------------------------------------------- /// Ultimate Character Controller /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.UltimateCharacterController.Objects { using Opsive.Shared.Game; using Opsive.UltimateCharacterController.Game; using Opsive.UltimateCharacterController.SurfaceSystem; using UnityEngine; /// /// The Projectile component moves a Destructible object along the specified path. Can apply damage at the collision point. /// public class Grenade : Destructible { [Tooltip("The length of time before the grenade destructs.")] [SerializeField] protected float m_Lifespan = 5; [Tooltip("A reference to the pin that is removed.")] [SerializeField] protected Transform m_Pin; public float Lifespan { get { return m_Lifespan; } set { m_Lifespan = value; } } public Transform Pin { get { return m_Pin; } set { m_Pin = value; } } protected ScheduledEventBase m_ScheduledDeactivation; private Transform m_PinParent; private Vector3 m_PinLocalPosition; private Quaternion m_PinLocalRotation; /// /// Initialize the default values. /// protected override void Awake() { base.Awake(); // Remember the pin location so it can be reattached. if (m_Pin != null) { m_PinParent = m_Pin.parent; m_PinLocalPosition = m_Pin.localPosition; m_PinLocalRotation = m_Pin.localRotation; } } /// /// The grenade has been enabled. /// protected override void OnEnable() { base.OnEnable(); DetachAttachPin(null); } /// /// Initializes the object. /// /// The velocity to apply. /// The torque to apply. /// The amount of damage to apply to the hit object. /// The amount of force to apply to the hit object. /// The number of frames to add the force to. /// The layers that the projectile can impact with. /// The name of the state to activate upon impact. /// The number of seconds until the impact state is disabled. /// A reference to the Surface Impact triggered when the object hits an object. /// The object that instantiated the trajectory object. /// Should a collision check against the originator be performed? public virtual void Initialize(Vector3 velocity, Vector3 torque, float damageAmount, float impactForce, int impactForceFrames, LayerMask impactLayers, string impactStateName, float impactStateDisableTimer, SurfaceImpact surfaceImpact, GameObject originator, bool originatorCollisionCheck) { InitializeDestructibleProperties(damageAmount, impactForce, impactForceFrames, impactLayers, impactStateName, impactStateDisableTimer, surfaceImpact); base.Initialize(velocity, torque, originator, originatorCollisionCheck); } /// /// The grenade should start to cook. /// /// The object that instantiated the trajectory object. public void StartCooking(GameObject originator) { SetOriginator(originator, Vector3.up); // The grenade should destruct after a specified amount of time. m_ScheduledDeactivation = Scheduler.Schedule(m_Lifespan, Deactivate); } /// /// Detaches or attach the pin. /// /// The transform that the pin should be attached to. If null the pin will move back to the starting location. public void DetachAttachPin(Transform attachTransform) { if (m_Pin == null || m_PinParent == null) { return; } if (attachTransform != null) { m_Pin.parent = attachTransform; } else { // Attach the pin back to the original transform. m_Pin.parent = m_PinParent; m_Pin.localPosition = m_PinLocalPosition; m_Pin.localRotation = m_PinLocalRotation; } } /// /// The grenade has reached its lifespan. /// protected void Deactivate() { Scheduler.Cancel(m_ScheduledDeactivation); InitializeComponentReferences(); // The grenade may explode before Awake is called. // Change the layer of the GameObject so the explosion doesn't detect the grenade when performing its overlap check. var prevLayer = m_GameObject.layer; m_GameObject.layer = LayerManager.IgnoreRaycast; Destruct(null); m_GameObject.layer = prevLayer; } } }