RizzeBattleRoyale/Assets/TPSBR/Scripts/Gameplay/Agent/Character/CharacterAnimationController.cs
2025-09-24 11:24:38 +05:00

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;
}
}
}