304 lines
8.1 KiB
C#
304 lines
8.1 KiB
C#
|
namespace TPSBR
|
||
|
{
|
||
|
using UnityEngine;
|
||
|
using Fusion.Addons.KCC;
|
||
|
using Fusion.Addons.AnimationController;
|
||
|
|
||
|
[DefaultExecutionOrder(3)]
|
||
|
public sealed class CharacterAnimationController : AnimationController
|
||
|
{
|
||
|
// PRIVATE MEMBERS
|
||
|
|
||
|
[SerializeField]
|
||
|
private Transform _leftHand;
|
||
|
[SerializeField]
|
||
|
private Transform _leftLowerArm;
|
||
|
[SerializeField]
|
||
|
private Transform _leftUpperArm;
|
||
|
[SerializeField][Range(0.0f, 1.0f)]
|
||
|
private float _aimSnapPower = 0.5f;
|
||
|
|
||
|
private KCC _kcc;
|
||
|
private Agent _agent;
|
||
|
private Weapons _weapons;
|
||
|
private Jetpack _jetpack;
|
||
|
|
||
|
private LocomotionLayer _locomotion;
|
||
|
private FullBodyLayer _fullBody;
|
||
|
private LowerBodyLayer _lowerBody;
|
||
|
private UpperBodyLayer _upperBody;
|
||
|
private ShootLayer _shoot;
|
||
|
private LookLayer _look;
|
||
|
|
||
|
// PUBLIC METHODS
|
||
|
|
||
|
public bool CanJump()
|
||
|
{
|
||
|
if (_fullBody.IsActive() == true)
|
||
|
{
|
||
|
if (_fullBody.Jump.IsActive(true) == true)
|
||
|
return false;
|
||
|
if (_fullBody.Fall.IsActive(true) == true)
|
||
|
return false;
|
||
|
if (_fullBody.Dead.IsActive(true) == true)
|
||
|
return false;
|
||
|
if (_fullBody.Jetpack.IsActive(true) == true)
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public bool CanSwitchWeapons(bool force)
|
||
|
{
|
||
|
if (_fullBody.IsActive() == true)
|
||
|
{
|
||
|
if (_fullBody.Dead.IsActive() == true)
|
||
|
return false;
|
||
|
if (_fullBody.Jetpack.IsActive() == true)
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (_upperBody.IsActive() == true)
|
||
|
{
|
||
|
if (_upperBody.Grenade.IsActive() == true && _upperBody.Grenade.CanSwitchWeapon() == false)
|
||
|
return false;
|
||
|
if (force == false && (_upperBody.Equip.IsActive() == true || _upperBody.Unequip.IsActive() == true))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void SetDead(bool isDead)
|
||
|
{
|
||
|
if (isDead == true)
|
||
|
{
|
||
|
_fullBody.Dead.Activate(0.2f);
|
||
|
|
||
|
if (_kcc.Data.IsGrounded == true)
|
||
|
{
|
||
|
_kcc.SetColliderLayer(LayerMask.NameToLayer("Ignore Raycast"));
|
||
|
_kcc.SetCollisionLayerMask(_kcc.Settings.CollisionLayerMask & ~(1 << LayerMask.NameToLayer("AgentKCC")));
|
||
|
}
|
||
|
|
||
|
_upperBody.DeactivateAllStates(0.2f, true);
|
||
|
_look.DeactivateAllStates(0.2f, true);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_fullBody.Dead.Deactivate(0.2f);
|
||
|
_kcc.SetShape(EKCCShape.Capsule);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool StartFire()
|
||
|
{
|
||
|
if (_fullBody.Dead.IsActive() == true)
|
||
|
return false;
|
||
|
if (_upperBody.HasActiveState() == true)
|
||
|
return false;
|
||
|
|
||
|
_shoot.Shoot.SetAnimationTime(0.0f);
|
||
|
_shoot.Shoot.Activate(0.2f);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void ProcessThrow(bool start, bool hold)
|
||
|
{
|
||
|
_upperBody.Grenade.ProcessThrow(start, hold);
|
||
|
}
|
||
|
|
||
|
public bool StartReload()
|
||
|
{
|
||
|
if (_upperBody.Grenade.IsActive() == true)
|
||
|
return _upperBody.Grenade.ProcessReload();
|
||
|
|
||
|
if (_fullBody.Dead.IsActive() == true)
|
||
|
return false;
|
||
|
if (_upperBody.Reload.IsActive() == true)
|
||
|
return true;
|
||
|
if (_upperBody.HasActiveState() == true)
|
||
|
return false;
|
||
|
|
||
|
_upperBody.Reload.Activate(0.2f);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void SwitchWeapons()
|
||
|
{
|
||
|
_upperBody.Reload.Deactivate(0.2f);
|
||
|
|
||
|
if (_weapons.PendingWeapon is ThrowableWeapon)
|
||
|
{
|
||
|
_upperBody.Grenade.Equip();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (_weapons.PendingWeaponSlot > 0)
|
||
|
{
|
||
|
_weapons.DisarmCurrentWeapon();
|
||
|
|
||
|
_upperBody.Equip.SetAnimationTime(0.0f);
|
||
|
_upperBody.Equip.Activate(0.2f);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_upperBody.Unequip.SetAnimationTime(0.0f);
|
||
|
_upperBody.Unequip.Activate(0.2f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Turn(float angle)
|
||
|
{
|
||
|
_lowerBody.Turn.Refresh(angle);
|
||
|
}
|
||
|
|
||
|
public void RefreshSnapping()
|
||
|
{
|
||
|
SnapWeapon();
|
||
|
}
|
||
|
|
||
|
// AnimationController INTERFACE
|
||
|
|
||
|
protected override void OnSpawned()
|
||
|
{
|
||
|
if (HasStateAuthority == true)
|
||
|
{
|
||
|
Animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
|
||
|
}
|
||
|
|
||
|
_locomotion.Move.Activate(0.0f);
|
||
|
|
||
|
if (_weapons.IsSwitchingWeapon() == true)
|
||
|
{
|
||
|
SwitchWeapons();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnFixedUpdate()
|
||
|
{
|
||
|
if (_jetpack.IsActive == true && _fullBody.Jetpack.IsActive() == false)
|
||
|
{
|
||
|
_upperBody.Reload.Deactivate(0.2f);
|
||
|
|
||
|
_weapons.DisarmCurrentWeapon();
|
||
|
|
||
|
_fullBody.Jetpack.Activate(0.1f);
|
||
|
}
|
||
|
else if (_jetpack.IsActive == false && _fullBody.Jetpack.IsActive() == true)
|
||
|
{
|
||
|
_fullBody.Jetpack.Deactivate(0.1f);
|
||
|
|
||
|
SwitchWeapons(); // Equip pending weapon
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnEvaluate()
|
||
|
{
|
||
|
SnapWeapon();
|
||
|
}
|
||
|
|
||
|
// MonoBehaviour INTERFACE
|
||
|
|
||
|
protected override void Awake()
|
||
|
{
|
||
|
base.Awake();
|
||
|
|
||
|
_kcc = this.GetComponentNoAlloc<KCC>();
|
||
|
_agent = this.GetComponentNoAlloc<Agent>();
|
||
|
_weapons = this.GetComponentNoAlloc<Weapons>();
|
||
|
_jetpack = this.GetComponentNoAlloc<Jetpack>();
|
||
|
|
||
|
_locomotion = FindLayer<LocomotionLayer>();
|
||
|
_fullBody = FindLayer<FullBodyLayer>();
|
||
|
_lowerBody = FindLayer<LowerBodyLayer>();
|
||
|
_upperBody = FindLayer<UpperBodyLayer>();
|
||
|
_shoot = FindLayer<ShootLayer>();
|
||
|
_look = FindLayer<LookLayer>();
|
||
|
|
||
|
_kcc.MoveState = _locomotion.FindState<MoveState>();
|
||
|
}
|
||
|
|
||
|
// PRIVATE METHODS
|
||
|
|
||
|
private void SnapWeapon()
|
||
|
{
|
||
|
if (ApplicationSettings.IsBatchServer == true)
|
||
|
return;
|
||
|
if (_weapons.CurrentWeapon == null || CanSnapHand() == false)
|
||
|
return;
|
||
|
|
||
|
Transform weaponHandle = _weapons.CurrentWeaponHandle;
|
||
|
if (HasInputAuthority == true || _agent.IsObserved == true)
|
||
|
{
|
||
|
weaponHandle.localRotation = _weapons.CurrentWeaponBaseRotation;
|
||
|
|
||
|
Quaternion handleRotation = weaponHandle.rotation;
|
||
|
Quaternion targetRotation = Quaternion.LookRotation(_agent.Context.Camera.transform.position + _agent.Context.Camera.transform.forward * 100.0f - weaponHandle.position);
|
||
|
|
||
|
float snapPower = Mathf.Clamp(Mathf.Abs(_kcc.FixedData.LookPitch) / 60.0f, _aimSnapPower, 1.0f);
|
||
|
Vector3 snapRotation = Quaternion.Slerp(handleRotation, targetRotation, snapPower).eulerAngles;
|
||
|
|
||
|
snapRotation.y = targetRotation.eulerAngles.y;
|
||
|
|
||
|
weaponHandle.rotation = Quaternion.Euler(snapRotation);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
weaponHandle.rotation = Quaternion.LookRotation(_kcc.FixedData.LookDirection);
|
||
|
}
|
||
|
|
||
|
Transform leftHandTarget = _weapons.CurrentWeapon.LeftHandTarget;
|
||
|
if (leftHandTarget != null)
|
||
|
{
|
||
|
bool leftSide = _agent.LeftSide;
|
||
|
|
||
|
Vector3 leftHandLocalPosition = _leftLowerArm.InverseTransformPoint(_leftHand.position);
|
||
|
Vector3 leftHandTargetLocalPosition = _leftLowerArm.InverseTransformPoint(leftHandTarget.position);
|
||
|
Quaternion leftLowerArmRotation = Quaternion.FromToRotation(leftHandLocalPosition, leftHandTargetLocalPosition);
|
||
|
|
||
|
_leftLowerArm.rotation *= leftSide == true ? Quaternion.Inverse(leftLowerArmRotation) : leftLowerArmRotation;
|
||
|
|
||
|
for (int i = 0; i < 2; ++i)
|
||
|
{
|
||
|
Vector3 leftLowerArmOffset = leftHandTarget.position - _leftHand.position;
|
||
|
Vector3 leftLowerArmTargetPosition = _leftLowerArm.position + leftLowerArmOffset;
|
||
|
Vector3 leftLowerArmLocalPosition = _leftUpperArm.InverseTransformPoint(_leftLowerArm.position);
|
||
|
Vector3 leftLowerArmTargetLocalPosition = _leftUpperArm.InverseTransformPoint(leftLowerArmTargetPosition);
|
||
|
Quaternion leftUpperArmRotation = Quaternion.FromToRotation(leftLowerArmLocalPosition, leftLowerArmTargetLocalPosition);
|
||
|
|
||
|
_leftUpperArm.rotation *= leftSide == true ? Quaternion.Inverse(leftUpperArmRotation) : leftUpperArmRotation;
|
||
|
|
||
|
leftHandLocalPosition = _leftLowerArm.InverseTransformPoint(_leftHand.position);
|
||
|
leftHandTargetLocalPosition = _leftLowerArm.InverseTransformPoint(leftHandTarget.position);
|
||
|
leftLowerArmRotation = Quaternion.FromToRotation(leftHandLocalPosition, leftHandTargetLocalPosition);
|
||
|
|
||
|
_leftLowerArm.rotation *= leftSide == true ? Quaternion.Inverse(leftLowerArmRotation) : leftLowerArmRotation;
|
||
|
}
|
||
|
|
||
|
_leftHand.position = leftHandTarget.position;
|
||
|
_leftHand.rotation = leftHandTarget.rotation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool CanSnapHand()
|
||
|
{
|
||
|
if (_fullBody.Dead.IsActive() == true || _fullBody.Jetpack.IsActive() == true)
|
||
|
return false;
|
||
|
|
||
|
if (_upperBody.HasActiveState() == true)
|
||
|
{
|
||
|
if (_upperBody.Reload.IsFinished(0.85f) == true)
|
||
|
return true;
|
||
|
if (_upperBody.Equip.IsFinished(0.75f) == true)
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|