BITFALL/Assets/Artists/Scripts/Player/CharacterControllerPro/PlayerChatacterMotionBasedS...

375 lines
11 KiB
C#
Raw Normal View History

2023-08-27 02:58:19 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
2023-10-20 19:31:12 +08:00
using System.ComponentModel.Composition;
using System.Linq;
2023-11-15 23:54:54 +08:00
using BITFALL.Player.Equip;
2023-08-27 02:58:19 +08:00
using BITFALL.Player.Movement;
2023-10-20 19:31:12 +08:00
using BITKit;
using BITKit.Entities;
using BITKit.Selection;
2023-08-27 02:58:19 +08:00
using BITKit.StateMachine;
2023-10-20 19:31:12 +08:00
using JetBrains.Annotations;
using Unity.Mathematics;
2023-08-27 02:58:19 +08:00
using UnityEngine;
2023-10-20 19:31:12 +08:00
using UnityEngine.AI;
using UnityEngine.Splines;
using UnityEngine.UI;
2023-08-27 02:58:19 +08:00
namespace BITFALL.Entities.Player.Movement.States
{
[Serializable]
public class Climb : PlayerCharacterState,IPlayerClimbState
{
[SerializeField] protected float lerpDelta = 5;
2023-10-20 19:31:12 +08:00
private IntervalUpdate cancelInterval = new(0.16f);
2023-11-15 23:54:54 +08:00
2023-08-27 02:58:19 +08:00
public override void OnStateEntry(IState old)
{
2023-10-20 19:31:12 +08:00
base.OnStateEntry(old);
2023-08-27 02:58:19 +08:00
actor.alwaysNotGrounded = true;
actor.ForceNotGrounded();
actor.ColliderComponent.enabled = false;
2023-10-20 19:31:12 +08:00
cancelInterval.Reset();
2023-08-27 02:58:19 +08:00
}
public override void OnStateUpdate(float deltaTime)
{
2023-10-20 19:31:12 +08:00
var distance = Vector3.Distance(characterController.ExpectClimb.shouldBe,
characterController.transform.position);
if (
distance<=0.16f
|| actor.IsStable
|| cancelInterval.AllowUpdate && actor.Velocity.sqrMagnitude<=0.16f
)
2023-08-27 02:58:19 +08:00
{
2023-10-20 19:31:12 +08:00
Exit();
2023-08-27 02:58:19 +08:00
}
}
public override void OnStateExit(IState old, IState newState)
{
actor.alwaysNotGrounded = false;
actor.ColliderComponent.enabled = true;
characterController.ExpectJump.Reset();
actor.ForceGrounded();
2023-11-15 23:54:54 +08:00
2023-08-27 02:58:19 +08:00
}
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
2023-10-02 23:24:56 +08:00
currentVelocity =(characterController.ExpectClimb.shouldBe - characterController.transform.position)*lerpDelta;
2023-08-27 02:58:19 +08:00
}
2023-10-20 19:31:12 +08:00
public override void AfterUpdateMovement(float deltaTime)
{
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
}
}
[Serializable]
public sealed class Link:PlayerCharacterState,IPlayerLinkState
{
public int LinkArea { get; private set; }
private OffMeshLink _offMeshLink;
private ISplineContainer _splineContainer;
private float progress;
private float increment;
2023-11-15 23:54:54 +08:00
[Inject] private IEquipService _equipService;
2023-10-20 19:31:12 +08:00
public override void OnStateEntry(IState old)
{
base.OnStateEntry(old);
characterController.ExpectCrouch.Reset();
characterController.ExpectJump.Reset();
actor.ForceNotGrounded();
actor.RigidbodyComponent.IsKinematic = true;
actor.ColliderComponent.enabled = false;
Init(characterController.OffMeshLink);
characterController.LimitViewAngle = 45;
2023-11-15 23:54:54 +08:00
_equipService.AllowEquip.AddDisableElements(this);
2023-10-20 19:31:12 +08:00
}
public override void OnStateExit(IState old, IState newState)
{
base.OnStateExit(old, newState);
actor.RigidbodyComponent.IsKinematic = false;
actor.ColliderComponent.enabled = true;
characterController.LimitViewAngle = 0;
2023-11-15 23:54:54 +08:00
_equipService.AllowEquip.RemoveDisableElements(this);
2023-10-20 19:31:12 +08:00
}
private void Init(OffMeshLink offMeshLink)
{
var offsetTransform = offMeshLink.transform;
_offMeshLink = offMeshLink;
offMeshLink.TryGetComponent<ISplineContainer>(out _splineContainer);
LinkArea = offMeshLink.area;
if (_splineContainer is not null)
{
var isStart =
Vector3.Distance(
actor.Position,
offsetTransform.TransformPoint(_splineContainer.Splines[0].Knots.First().Position)
) <
Vector3.Distance(
actor.Position,
offsetTransform.TransformPoint(_splineContainer.Splines[0].Knots.Last().Position)
);
progress = isStart ? 0 : 1;
increment = isStart ? 1 : -1;
}
else
{
var offset = Mathf.Lerp(offMeshLink.startTransform.position.y,offMeshLink.endTransform.position.y,0.5f);
var offsetPos = actor.Position;
offsetPos.y = offset;
actor.ForceNotGrounded();
actor.Position = Vector3.MoveTowards(actor.Position, offsetPos, 0.64f);
progress = 0.5f;
}
}
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
{
if (_splineContainer is null)
{
actor.Rotation = Quaternion.Lerp(
actor.Rotation,
Quaternion.Inverse(_offMeshLink.transform.rotation),
5 * deltaTime
);
}
}
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
actor.ForceNotGrounded();
if (_offMeshLink is null) return;
switch (_splineContainer)
{
case null:
var positionA = _offMeshLink.startTransform.position;
var positionB = positionA;
positionB.y = _offMeshLink.endTransform.position.y;
var positionC = actor.Position + Vector3.up * (characterController.MovementInput.z * deltaTime * 3);
Vector3 vectorAC = positionC - positionA;
Vector3 vectorAB = positionB - positionA;
Vector3 closestPoint = positionA + Vector3.Project(vectorAC, vectorAB);
actor.Position = closestPoint;
//currentVelocity = Vector3.Lerp(currentVelocity , (closestPoint - actor.Position) , 5 * deltaTime);
break;
case not null:
var trans = _offMeshLink.transform;
var pos =trans.position + trans.rotation * _splineContainer.Splines[0].EvaluatePosition(progress +=increment * deltaTime);
actor.Position =Vector3.Lerp(actor.Position , pos , 8*deltaTime) ;
break;
}
}
public override void OnStateUpdate(float deltaTime)
{
if (characterController.ExpectJump.shouldBe|| characterController.ExpectCrouch.shouldBe)
{
Exit();
return;
}
switch (_offMeshLink,_splineContainer)
{
case (null,null):
Exit();
break;
case (not null,not null):
if (progress is > 1.1f or < -0.1f)
{
Exit();
}
break;
case (not null,null):
if (actor.Position.y > _offMeshLink.endTransform.position.y)
{
Exit();
actor.Position = _offMeshLink.endTransform.position;
}else if (actor.Position.y < _offMeshLink.startTransform.position.y)
{
Exit();
actor.Position = _offMeshLink.startTransform.position;
}
break;
}
}
public override void AfterUpdateMovement(float deltaTime)
{
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
}
}
2023-10-24 23:37:59 +08:00
[Serializable]
public sealed class Dodge : PlayerCharacterState,IPlayerDodgeState
{
[SerializeField] private int costStamina = 10;
[SerializeField] private AnimationCurve curve;
[SerializeField] private float duration = 0.32f;
private int direction;
private float process;
[Inject] private IHealth _health;
public override void Initialize()
{
base.Initialize();
_health.OnDamageFactory += OnDamageFactory;
}
public override void OnStateEntry(IState old)
{
base.OnStateEntry(old);
direction = characterController.MovementInput.x > 0 ? 1 : -1;
process = 0;
characterController.Stamina-= costStamina;
}
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
currentVelocity = actor.transform.right * (direction * curve.Evaluate(process+=deltaTime / duration));
}
public override void AfterUpdateMovement(float deltaTime)
{
if(process>=1)
Exit();
}
private int OnDamageFactory(DamageMessage msg, int currentDamage)
{
if (characterController.CurrentState is not IPlayerDodgeState || msg.Initiator is not Entity initiator)
return currentDamage;
var _direction = characterController.Position - initiator.transform.position;
var verticalAngle = Vector3.Angle(initiator.transform.forward, _direction) - 90.0f;
Debug.Log(verticalAngle);
return 0;
}
}
2023-10-20 19:31:12 +08:00
[Serializable]
public sealed class Fixed:PlayerCharacterState,IPlayerFixedState
{
public object FixedObject=>_fixedPlace;
public float3 FixedPosition=>_fixedPlace.FixedPosition;
public quaternion FixedRotation=>_fixedPlace.FixedRotation;
public float3 FixedLocalPosition => throw new NotImplementedException();
public quaternion FixedLocalRotation => throw new NotImplementedException();
private IPlayerFixedPlace _fixedPlace;
[Inject] private ISelector _selector;
2023-11-15 23:54:54 +08:00
[Inject] private IEquipService _equipService;
2023-10-20 19:31:12 +08:00
public override void Initialize()
{
base.Initialize();
_selector.OnActive+=OnSelectorActive;
}
public override void OnStateEntry(IState old)
{
base.OnStateEntry(old);
//actor.enabled = false;
//actor.RigidbodyComponent.IsKinematic = true;
actor.ColliderComponent.enabled = false;
actor.PhysicsComponent.enabled = false;
actor.alwaysNotGrounded = true;
characterController.ExpectCrouch.Reset();
characterController.LimitViewAngle = 100;
2023-11-15 23:54:54 +08:00
_equipService.AllowEquip.AddDisableElements(this);
2023-10-20 19:31:12 +08:00
}
public override void OnStateExit(IState old, IState newState)
{
base.OnStateExit(old, newState);
//actor.RigidbodyComponent.IsKinematic = false;
actor.ColliderComponent.enabled = true;
actor.alwaysNotGrounded = false;
actor.PhysicsComponent.enabled = true;
//actor.enabled = true;
characterController.LimitViewAngle = 0;
2023-11-15 23:54:54 +08:00
_equipService.AllowEquip.RemoveDisableElements(this);
2023-10-20 19:31:12 +08:00
}
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
actor.Position = FixedPosition;
}
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
{
currentRotation = FixedRotation;
//actor.Rotation = FixedRotation;
}
public override void AfterUpdateMovement(float deltaTime)
{
base.AfterUpdateMovement(deltaTime);
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
if (characterController.ExpectCrouch.shouldBe && _fixedPlace.Exit(characterController.Entity))
{
characterController.ExpectCrouch.Reset();
Exit();
}else if (_fixedPlace is null)
{
Exit();
}
}
private void OnSelectorActive(ISelectable obj)
{
if (obj is not MonoBehaviour monoBehaviour ||
monoBehaviour.TryGetComponent<IPlayerFixedPlace>(out var fixedPlace) is false) return;
if (_fixedPlace?.Exit(characterController.Entity) is false)
{
return;
}
if (fixedPlace.Entry(characterController.Entity))
{
_fixedPlace = fixedPlace;
characterController.TransitionState<Fixed>();
return;
}
_fixedPlace = null;
}
public override void OnStateUpdate(float deltaTime)
{
}
protected override void Exit()
{
base.Exit();
if (_fixedPlace is not null)
{
actor.Position = _fixedPlace.ExitPosition;
}
_fixedPlace = null;
}
2023-08-27 02:58:19 +08:00
}
}