projectEli/Assets/NeoFPS/Core/Camera/AdditiveEffects/RotationBob.cs
2022-11-06 20:28:33 -05:00

182 lines
6.0 KiB
C#

using NeoFPS.CharacterMotion;
using NeoFPS.ModularFirearms;
using NeoSaveGames;
using NeoSaveGames.Serialization;
using System;
using UnityEngine;
namespace NeoFPS
{
public class RotationBob : MonoBehaviour, IAdditiveTransform, INeoSerializableComponent
{
[SerializeField, Tooltip("The angle range range around each axis.")]
private Vector3 m_RotationRange = new Vector3(1f, 0.5f, 1f);
[SerializeField, Tooltip("The curve over one step cycle for the weapon bob.")]
private AnimationCurve m_BobCurve = new AnimationCurve(
new Keyframe(0f, 0f), new Keyframe(0.5f, 1f),
new Keyframe(1f, 0f), new Keyframe(1.5f, -1f),
new Keyframe(2f, 0f)); // curve for head bob
[SerializeField, Range(0f, 5f), Tooltip("At or below this speed the bob will be scaled to zero.")]
private float m_MinLerpSpeed = 0.5f;
[SerializeField, Range(0.25f, 10f), Tooltip("At or above this speed the bob will have its full effect.")]
private float m_MaxLerpSpeed = 2f;
[SerializeField, Range(0f, 1f), Tooltip("A multiplier for the rotation when aiming down sights. This can be used to prevent excessive crosshair wander.")]
private float m_AimingMultiplier = 0.25f;
private static readonly NeoSerializationKey k_FadeKey = new NeoSerializationKey("fade");
private const float k_FadeDuration = 1f;
private IAdditiveTransformHandler m_Handler = null;
private IModularFirearm m_Firearm = null;
private IAimer m_Aimer = null;
private MotionController m_Controller = null;
private Vector3 m_Euler = Vector3.zero;
private float m_FadeTime = 0f;
private float m_CurrentStrength = 0f;
private float m_TargetStrength = 1f;
public Quaternion rotation
{
get { return Quaternion.Euler(m_Euler * m_CurrentStrength); }
}
public Vector3 position
{
get { return Vector3.zero; }
}
public float strength
{
get { return m_TargetStrength; }
set { m_TargetStrength = value; }
}
public bool bypassPositionMultiplier
{
get { return false; }
}
public bool bypassRotationMultiplier
{
get { return false; }
}
#if UNITY_EDITOR
void OnValidate()
{
if (m_MaxLerpSpeed < m_MinLerpSpeed + 0.1f)
m_MaxLerpSpeed = m_MinLerpSpeed + 0.1f;
m_RotationRange.x = Mathf.Clamp(m_RotationRange.x, -5f, 5f);
m_RotationRange.y = Mathf.Clamp(m_RotationRange.y, -5f, 5f);
m_RotationRange.z = Mathf.Clamp(m_RotationRange.z, -5f, 5f);
m_BobCurve.preWrapMode = WrapMode.Loop;
m_BobCurve.postWrapMode = WrapMode.Loop;
}
#endif
void Awake()
{
// Get relevant components
m_Handler = GetComponent<IAdditiveTransformHandler>();
m_Firearm = GetComponentInParent<IModularFirearm>();
m_BobCurve.preWrapMode = WrapMode.Loop;
m_BobCurve.postWrapMode = WrapMode.Loop;
}
private void OnAimerChange(IModularFirearm firearm, IAimer aimer)
{
m_Aimer = aimer;
}
void Start()
{
m_Controller = GetComponentInParent<MotionController>();
if (m_Firearm != null)
{
m_Firearm.onAimerChange += OnAimerChange;
OnAimerChange(m_Firearm, m_Firearm.aimer);
}
}
void OnEnable()
{
m_Handler.ApplyAdditiveEffect(this);
m_CurrentStrength = 0f;
if (m_Firearm != null)
{
m_Firearm.onAimerChange += OnAimerChange;
OnAimerChange(m_Firearm, m_Firearm.aimer);
}
}
void OnDisable()
{
m_Handler.RemoveAdditiveEffect(this);
if (m_Firearm != null)
{
m_Firearm.onAimerChange -= OnAimerChange;
m_Aimer = null;
}
}
void FixedUpdate()
{
// Interpolate user strength
float multiplier = (m_Aimer != null && m_Aimer.isAiming) ? m_AimingMultiplier : 1f;
m_CurrentStrength = Mathf.Lerp(m_CurrentStrength, multiplier * m_TargetStrength, Time.deltaTime * 5f);
}
public void UpdateTransform()
{
if (m_Controller != null && m_Controller.strideLength != 0f)
{
float speed = m_Controller.smoothedStepRate;
if (speed < m_MinLerpSpeed)
FadeOut();
else
{
// Get the bob amount
m_Euler = new Vector3(
m_BobCurve.Evaluate(m_Controller.stepCounter * 2f) * m_RotationRange.x * 0.5f,
m_BobCurve.Evaluate(m_Controller.stepCounter) * m_RotationRange.y * 0.5f,
m_BobCurve.Evaluate(m_Controller.stepCounter * 2f + 0.5f) * m_RotationRange.z * 0.5f
);
if (speed < m_MaxLerpSpeed)
{
float lerp = (m_Controller.smoothedStepRate - m_MinLerpSpeed) / (m_MaxLerpSpeed - m_MinLerpSpeed);
m_Euler *= lerp;
}
m_FadeTime = 0f;
}
}
else
FadeOut();
}
void FadeOut()
{
m_FadeTime += Time.deltaTime;
if (m_FadeTime > k_FadeDuration)
m_Euler = Vector3.zero;
else
m_Euler *= 1f - Time.deltaTime;
}
public void WriteProperties(INeoSerializer writer, NeoSerializedGameObject nsgo, SaveMode saveMode)
{
writer.WriteValue(k_FadeKey, m_FadeTime);
}
public void ReadProperties(INeoDeserializer reader, NeoSerializedGameObject nsgo)
{
reader.TryReadValue(k_FadeKey, out m_FadeTime, m_FadeTime);
}
}
}