projectEli/Assets/NeoFPS/Core/MotionGraphs/States/GrappleSwingState.cs
2022-11-06 20:28:33 -05:00

169 lines
5.9 KiB
C#

using UnityEngine;
using NeoFPS.CharacterMotion;
using NeoFPS.CharacterMotion.MotionData;
using NeoFPS.CharacterMotion.Parameters;
using NeoFPS.CharacterMotion.States;
using NeoSaveGames.Serialization;
namespace NeoFPS.CharacterMotion.States
{
[MotionGraphElement("Misc/GrappleSwingState", "GrappleSwingState")]
[HelpURL("https://docs.neofps.com/manual/motiongraphref-mgs-grappleswingstate.html")]
public class GrappleSwingState : MotionGraphState
{
[SerializeField, Tooltip("The point in space that the grapple is tethered to.")]
private VectorParameter m_GrapplePoint = null;
[SerializeField, Tooltip("When entering the state, a target distance will be calculated based on multiplying the current distance to the grapple point by this multiplier.")]
private float m_TargetDistanceMultiplier = 0.75f;
[SerializeField, Tooltip("Below this distance from the grapple point, the character will actually be pushed away.")]
private float m_MinDistance = 2f;
[SerializeField, Tooltip("The acceleration towards the grapple point per meter distance above the target distance.")]
private float m_AccelerationPerMeter = 15f;
[SerializeField, Tooltip("The maximum acceleration towards the grapple point.")]
private float m_MaxAccel = 40f;
private Vector3 m_OutVelocity = Vector3.zero;
private float m_TargetLength = 0f;
public override bool completed
{
get { return m_GrapplePoint == null || m_GrapplePoint.value == Vector3.zero; }
}
public override Vector3 moveVector
{
get { return m_OutVelocity * Time.deltaTime; }
}
public override bool applyGravity
{
get { return true; }
}
public override bool applyGroundingForce
{
get { return false; }
}
public override void OnValidate()
{
base.OnValidate();
}
public override bool CheckCanEnter()
{
return m_GrapplePoint != null && m_GrapplePoint.value != Vector3.zero;
}
public override void OnEnter()
{
base.OnEnter();
m_TargetLength = Vector3.Magnitude(m_GrapplePoint.value - GetCenterPoint()) * m_TargetDistanceMultiplier;
if (m_TargetLength < m_MinDistance)
m_TargetLength = m_MinDistance;
}
public override void OnExit()
{
base.OnExit();
m_OutVelocity = Vector3.zero;
}
Vector3 GetCenterPoint()
{
return controller.localTransform.position + controller.localTransform.up * characterController.height;
}
public override void Update()
{
base.Update();
m_OutVelocity = characterController.velocity;
if (m_GrapplePoint.value != Vector3.zero)
{
var deltaPos = m_GrapplePoint.value - GetCenterPoint();
float distance = Vector3.Magnitude(deltaPos);
if (distance > m_TargetLength)
{
deltaPos.Normalize();
float pull = m_AccelerationPerMeter * (distance - m_TargetLength);
if (pull > m_MaxAccel)
pull = m_MaxAccel;
pull *= Time.deltaTime;
if (Vector3.Dot(m_OutVelocity, deltaPos) < 0f)
{
Vector3 target = Vector3.ProjectOnPlane(m_OutVelocity, deltaPos);
m_OutVelocity = Vector3.Lerp(m_OutVelocity, target, 0.25f);
}
m_OutVelocity += deltaPos * pull;
}
else
{
if (distance < m_MinDistance)
{
deltaPos.Normalize();
float push = m_AccelerationPerMeter * (m_MinDistance - distance);
if (push > m_MaxAccel)
push = m_MaxAccel;
push *= -Time.deltaTime;
if (Vector3.Dot(m_OutVelocity, deltaPos) > 0f)
{
Vector3 target = Vector3.ProjectOnPlane(m_OutVelocity, deltaPos);
m_OutVelocity = Vector3.Lerp(m_OutVelocity, target, 0.25f);
}
m_OutVelocity += deltaPos * push;
}
else
{
if (Vector3.Dot(m_OutVelocity, deltaPos) < 0f)
{
Vector3 target = Vector3.ProjectOnPlane(m_OutVelocity, deltaPos);
m_OutVelocity = Vector3.Lerp(m_OutVelocity, target, 0.25f);
}
}
}
}
}
public override void ChangeFrameOfReference(Vector3 deltaPos, Quaternion deltaRot)
{
base.ChangeFrameOfReference(deltaPos, deltaRot);
m_GrapplePoint.value = Vector3.zero;
}
public override void CheckReferences(IMotionGraphMap map)
{
m_GrapplePoint = map.Swap(m_GrapplePoint);
base.CheckReferences(map);
}
private static readonly NeoSerializationKey k_TargetLengthKey = new NeoSerializationKey("targetLength");
/*
public override void WriteProperties(INeoSerializer writer)
{
base.WriteProperties(writer);
// Optional - write any data saved by the NeoSave system here
writer.WriteValue(k_OutVelocityKey, m_OutVelocity);
}
public override void ReadProperties(INeoDeserializer reader)
{
base.ReadProperties(reader);
// Optional - read any data saved by the NeoSave system here
reader.TryReadValue(k_OutVelocityKey, out m_OutVelocity, m_OutVelocity);
}
*/
}
}