154 lines
5.2 KiB
C#
154 lines
5.2 KiB
C#
using System.Collections;
|
|
using HurricaneVR.Framework.Core;
|
|
using HurricaneVR.Framework.Core.Grabbers;
|
|
using HurricaneVR.Framework.Core.Utils;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace HurricaneVR.Framework.Weapons
|
|
{
|
|
public class HVRSlide : HVRGrabbable
|
|
{
|
|
[Header("Slide Events")]
|
|
|
|
public UnityEvent FullRelease = new UnityEvent();
|
|
public UnityEvent EjectReached = new UnityEvent();
|
|
|
|
[Header("Slide Settings")]
|
|
[Tooltip("Forward speed of the slide when released")]
|
|
public float ForwardSpeed = 10f;
|
|
[Tooltip("Faux difficulty for pulling back the charging handle")]
|
|
public float Difficulty = .05f;
|
|
|
|
[Header("Required Tracking Transforms")]
|
|
[Tooltip("Maximum charging handle back position")]
|
|
public Transform MaximumPosition;
|
|
[Tooltip("Position to reach to eject the chambered round")]
|
|
public Transform EjectPosition;
|
|
[Tooltip("Position to reach that charging handle release will chamber a round.")]
|
|
public Transform RequiredChamberedPosition;
|
|
[Tooltip("Forward resting position of the charging handle")]
|
|
public Transform Forward;
|
|
[Tooltip("Dummy transform on the gun to track where the grabber started grabbing")]
|
|
public Transform GrabbedPositionTracker;
|
|
|
|
|
|
private float _chamberedRequiredDistance;
|
|
private float _maximumDistance;
|
|
private float _ejectDistance;
|
|
private Vector3 _startPosition;
|
|
private Coroutine _forwardRoutine;
|
|
|
|
private bool _chamberDistanceReached;
|
|
private bool _ejectDistanceReached;
|
|
private bool _emptyPushedBack;
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
|
|
_chamberedRequiredDistance = Vector3.Distance(RequiredChamberedPosition.localPosition, Forward.localPosition);
|
|
_maximumDistance = Vector3.Distance(MaximumPosition.localPosition, Forward.localPosition);
|
|
_ejectDistance = Vector3.Distance(EjectPosition.localPosition, Forward.localPosition);
|
|
_startPosition = Forward.localPosition;
|
|
}
|
|
|
|
protected override void ProcessUpdate()
|
|
{
|
|
base.ProcessUpdate();
|
|
|
|
if (PrimaryGrabber && !_emptyPushedBack)
|
|
{
|
|
var pullDirection = (PrimaryGrabber.transform.position - GrabbedPositionTracker.transform.position);
|
|
var backDirection = (MaximumPosition.position - Forward.position).normalized * 10;
|
|
var amount = Vector3.Dot(pullDirection, backDirection);
|
|
|
|
if (amount > 0)
|
|
{
|
|
transform.position = Forward.position + backDirection.normalized * amount * Difficulty;
|
|
|
|
var distance = Vector3.Distance(transform.position, Forward.position);
|
|
|
|
if (distance > _ejectDistance && !_ejectDistanceReached)
|
|
{
|
|
EjectReached.Invoke();
|
|
_ejectDistanceReached = true;
|
|
}
|
|
|
|
if (distance > _chamberedRequiredDistance)
|
|
{
|
|
if (!_chamberDistanceReached)
|
|
{
|
|
_chamberDistanceReached = true;
|
|
}
|
|
|
|
if (distance > _maximumDistance)
|
|
{
|
|
transform.position = Forward.position + backDirection.normalized * _maximumDistance;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnGrabbed(HVRGrabberBase grabber)
|
|
{
|
|
_emptyPushedBack = false;
|
|
base.OnGrabbed(grabber);
|
|
GrabbedPositionTracker.transform.localPosition = transform.InverseTransformPoint(grabber.transform.position);
|
|
}
|
|
|
|
protected override void OnReleased(HVRGrabberBase grabber)
|
|
{
|
|
base.OnReleased(grabber);
|
|
if (_emptyPushedBack)
|
|
return;
|
|
Close();
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
if (_forwardRoutine != null)
|
|
return;
|
|
StartCoroutine(ForwardRoutine());
|
|
}
|
|
|
|
private IEnumerator ForwardRoutine()
|
|
{
|
|
CanBeGrabbed = false;
|
|
|
|
while (true)
|
|
{
|
|
var distance = Vector3.Distance(transform.localPosition, _startPosition);
|
|
var travel = ForwardSpeed * Time.deltaTime;
|
|
|
|
if (distance < travel)
|
|
{
|
|
transform.localPosition = _startPosition;
|
|
break;
|
|
}
|
|
|
|
transform.localPosition = Vector3.MoveTowards(transform.localPosition, _startPosition, travel);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
_forwardRoutine = null;
|
|
CanBeGrabbed = true;
|
|
|
|
if (_chamberDistanceReached)
|
|
{
|
|
FullRelease.Invoke();
|
|
}
|
|
_chamberDistanceReached = false;
|
|
_ejectDistanceReached = false;
|
|
_emptyPushedBack = false;
|
|
}
|
|
|
|
public virtual void PushBack()
|
|
{
|
|
transform.position = EjectPosition.position;
|
|
_emptyPushedBack = true;
|
|
}
|
|
}
|
|
} |