Untitled
unknown
plain_text
a year ago
42 kB
13
Indexable
using System;
using UnityEngine;
using System.Collections;
using MFPS.PlayerController;
using UnityEngine.Serialization;
using MFPS.Runtime.Level;
[RequireComponent(typeof(CharacterController))]
public class bl_FirstPersonController : bl_FirstPersonControllerBase
{
#region Public members
[Header("Settings")] public float WalkSpeed = 4.5f;
[FormerlySerializedAs("m_CrouchSpeed")]
public float runSpeed = 8;
public float stealthSpeed = 1;
[FormerlySerializedAs("m_CrouchSpeed")]
public float crouchSpeed = 2;
public float slideSpeed = 10;
[FormerlySerializedAs("m_ClimbSpeed")] public float climbSpeed = 1f;
[FormerlySerializedAs("m_JumpSpeed")] public float jumpSpeed;
public float acceleration = 9;
public float slopeFriction = 3f;
public float crouchTransitionSpeed = 0.25f;
public float crouchHeight = 1.4f;
public bool canSlide = true;
[Range(0.2f, 1.5f)] public float slideTime = 0.75f;
[Range(1, 12)] public float slideFriction = 10;
[Range(0.1f, 2.5f)] public float slideCoolDown = 1.2f;
public float slideCameraTiltAngle = -22;
[Range(0, 2)] public float JumpMinRate = 0.82f;
public float jumpMomentumBooster = 2;
public float momentunDecaySpeed = 5;
[Range(0, 2)] public float AirControlMultiplier = 0.8f;
public float m_StickToGroundForce;
public float m_GravityMultiplier;
[LovattoToogle] public bool RunFovEffect = true;
public float runFOVAmount = 8;
[LovattoToogle] public bool KeepToCrouch = true;
public bool canStealthMode = true;
[Header("Falling")] [LovattoToogle] public bool FallDamage = true;
[Range(0.1f, 5f)] public float SafeFallDistance = 3;
[Range(3, 25)] public float DeathFallDistance = 15;
public PlayerRunToAimBehave runToAimBehave = PlayerRunToAimBehave.StopRunning;
[Header("Dropping")] public float dropControlSpeed = 25;
public Vector2 dropTiltSpeedRange = new Vector2(20, 60);
[Header("Mouse Look"), FormerlySerializedAs("m_MouseLook")]
public MouseLook mouseLook;
[FormerlySerializedAs("HeatRoot")] public Transform headRoot;
public Transform CameraRoot;
[Header("HeadBob")] [Range(0, 1.2f)] public float headBobMagnitude = 0.9f;
public float headVerticalBobMagnitude = 0.4f;
public LerpControlledBob m_JumpBob = new LerpControlledBob();
[Header("FootSteps")] public bl_Footstep footstep;
public AudioClip jumpSound; // the sound played when character leaves the ground.
public AudioClip landSound; // the sound played when character touches back on ground.
public AudioClip slideSound;
[Header("UI")] public Sprite StandIcon;
public Sprite CrouchIcon;
#endregion
#region Public properties
public float RunFov{ get; set; } = 0;
public CollisionFlags m_CollisionFlags{ get; set; }
public override Vector3 Velocity{ get; set; }
public override float VelocityMagnitude{ get; set; }
public override bool isControlable{ get; set; } = true;
public bool isSprintLock{ get; set; } = false;
#endregion
#region Private members
private bool hasPlatformJump = false;
private float PlatformJumpForce = 0;
public bool m_Jump;
private Vector2 m_Input = new Vector2();
private Vector3 targetDirection, moveDirection = Vector3.zero;
private bool m_PreviouslyGrounded;
private bool m_Jumping = false;
private bool Crounching = false;
private AudioSource m_AudioSource;
public bool Finish = false;
private Vector3 defaultCameraRPosition;
private bool isClimbing, isAiming = false;
private bl_Ladder m_Ladder;
private bool MoveToStarted = false;
#if MFPSM
private VariableJoystick Joystick;
#endif
private float PostGroundVerticalPos = 0;
private bool isFalling = false;
private int JumpDirection = 0;
private float HigherPointOnJump;
private CharacterController m_CharacterController;
private float lastJumpTime = 0;
private float WeaponWeight = 1;
private bool hasTouchGround = false;
private bool JumpInmune = false;
private Transform m_Transform;
private RaycastHit[] SurfaceRay = new RaycastHit[1];
private Vector3 desiredMove, momentum = Vector3.zero;
private float VerticalInput, HorizontalInput;
private bool lastCrouchState = false;
private float fallingTime = 0;
private bool haslanding = false;
private float capsuleRadious;
private readonly Vector3 feetPositionOffset = new Vector3(0, 0.8f, 0);
private float slideForce = 0;
private float lastSlideTime = 0;
private bl_PlayerReferences playerReferences;
private Vector3 forwardVector = Vector3.forward;
private PlayerState lastState = PlayerState.Idle;
private bool forcedCrouch = false;
private Vector3 surfaceNormal, surfacePoint = Vector3.zero;
private float defaultStepOffset = 0.4f;
private float desiredSpeed = 4;
private float defaultHeight = 2;
#endregion
#region Unity Methods
/// <summary>
///
/// </summary>
protected override void Awake(){
if (!photonView.IsMine)
return;
base.Awake();
m_Transform = transform;
playerReferences = GetComponent<bl_PlayerReferences>();
m_CharacterController = playerReferences.characterController;
#if MFPSM
Joystick = FindObjectOfType<VariableJoystick>();
#endif
defaultCameraRPosition = CameraRoot.localPosition;
m_AudioSource = gameObject.AddComponent<AudioSource>();
mouseLook.Init(m_Transform, headRoot);
lastJumpTime = Time.time;
defaultStepOffset = m_CharacterController.stepOffset;
capsuleRadious = m_CharacterController.radius * 0.1f;
defaultHeight = m_CharacterController.height;
isControlable = bl_MatchTimeManagerBase.HaveTimeStarted();
}
/// <summary>
///
/// </summary>
protected override void OnEnable(){
bl_EventHandler.onRoundEnd += OnRoundEnd;
bl_EventHandler.onChangeWeapon += OnChangeWeapon;
bl_EventHandler.onMatchStart += OnMatchStart;
bl_EventHandler.onGameSettingsChange += OnGameSettingsChanged;
bl_EventHandler.onLocalAimChanged += OnAimChange;
#if MFPSM
bl_TouchHelper.OnCrouch += OnCrouchClicked;
bl_TouchHelper.OnJump += OnJump;
bl_TouchHelper.OnProne += OnProne;
bl_TouchHelper.OnSprintLock += OnSprintLock;
#endif
}
/// <summary>
///
/// </summary>
protected override void OnDisable(){
bl_EventHandler.onRoundEnd -= OnRoundEnd;
bl_EventHandler.onChangeWeapon -= OnChangeWeapon;
bl_EventHandler.onMatchStart -= OnMatchStart;
bl_EventHandler.onGameSettingsChange -= OnGameSettingsChanged;
bl_EventHandler.onLocalAimChanged -= OnAimChange;
#if MFPSM
bl_TouchHelper.OnCrouch -= OnCrouchClicked;
bl_TouchHelper.OnJump -= OnJump;
bl_TouchHelper.OnProne -= OnProne;
bl_TouchHelper.OnSprintLock -= OnSprintLock;
#endif
}
/// <summary>
///
/// </summary>
public override void OnUpdate(){
Velocity = m_CharacterController.velocity;
VelocityMagnitude = Velocity.magnitude;
if (Finish)
return;
MovementInput();
GroundDetection();
CheckStates();
}
/// <summary>
///
/// </summary>
public override void OnLateUpdate(){
UpdateMouseLook();
if (m_CharacterController == null || !m_CharacterController.enabled) return;
moveDirection = Vector3.Lerp(moveDirection, targetDirection, acceleration * Time.deltaTime);
// apply the movement direction in the character controller
// apply the movement in LateUpdate to avoid the camera jerky/jitter effect when move and rotate the player camera.
m_CollisionFlags = m_CharacterController.Move(moveDirection * Time.deltaTime);
}
/// <summary>
///
/// </summary>
public void FixedUpdate(){
if (Finish || m_CharacterController == null || !m_CharacterController.enabled || MoveToStarted)
return;
//if player focus is in game
if (bl_RoomMenu.Instance.isCursorLocked && !bl_GameData.Instance.isChating){
//determine the player speed
GetInput(out float s);
desiredSpeed = Mathf.Lerp(desiredSpeed, s, Time.fixedDeltaTime * 8);
speed = desiredSpeed;
}
else if (State != PlayerState.Sliding) //if player is not focus in game
{
m_Input = Vector2.zero;
}
if (isClimbing && m_Ladder != null){
//climbing control
OnClimbing();
}
else{
//player movement
Move();
}
}
#endregion
/// <summary>
/// Triggered when the state of this player controller has changed.
/// </summary>
private void OnStateChanged(PlayerState from, PlayerState to){
if (from == PlayerState.Crouching || to == PlayerState.Crouching){
DoCrouchTransition();
}
else if (from == PlayerState.Sliding || to == PlayerState.Sliding){
DoCrouchTransition();
}
else if (from == PlayerState.Proning || to == PlayerState.Proning){
DoCrouchTransition();
}
bl_EventHandler.DispatchLocalPlayerStateChange(from, to);
}
/// <summary>
/// Handle the player input key/buttons for the player controller
/// </summary>
void MovementInput(){
if (State == PlayerState.Sliding){
slideForce -= Time.deltaTime * slideFriction;
speed = slideForce;
if (bl_GameInput.Jump()){
State = PlayerState.Jumping;
m_Jump = true;
}
else return;
}
ProneInput();
if (bl_UtilityHelper.isMobile) return;
if (!m_Jump && State != PlayerState.Crouching && State != PlayerState.Proning && (Time.time - lastJumpTime) >
JumpMinRate){
m_Jump = bl_GameInput.Jump();
}
if (State != PlayerState.Jumping && State != PlayerState.Climbing){
if (forcedCrouch) return;
if (KeepToCrouch){
Crounching = bl_GameInput.Crouch();
if (Crounching != lastCrouchState){
OnCrouchChanged();
lastCrouchState = Crounching;
}
}
else{
if (bl_GameInput.Crouch(GameInputType.Down)){
Crounching = !Crounching;
OnCrouchChanged();
}
}
}
}
/// <summary>
/// Check when the player is in a surface (not jumping or falling)
/// </summary>
void GroundDetection(){
//if the player has touch the ground after falling
if (!m_PreviouslyGrounded && m_CharacterController.isGrounded){
OnLand();
}
else if (m_PreviouslyGrounded && !m_CharacterController.isGrounded) //when the player start jumping
{
if (!isFalling){
PostGroundVerticalPos = m_Transform.position.y;
isFalling = true;
fallingTime = Time.time;
}
}
if (isFalling){
VerticalDirectionCheck();
}
if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded){
targetDirection.y = 0f;
}
if (forcedCrouch){
if ((Time.frameCount % 10) == 0){
if (!IsHeadHampered()){
forcedCrouch = false;
State = PlayerState.Idle;
}
}
}
m_PreviouslyGrounded = m_CharacterController.isGrounded;
}
/// <summary>
/// Apply the movement direction to the CharacterController
/// </summary>
void Move(){
//if the player is touching the surface
if (m_CharacterController.isGrounded){
OnSurface();
//vertical resistance
moveDirection.y = -m_StickToGroundForce;
hasTouchGround = true;
//has a pending jump
if (m_Jump || hasPlatformJump){
DoJump();
}
}
else //if the player is not touching the ground
{
//if the player is dropping
if (State == PlayerState.Dropping){
//handle the air movement in different process
OnDropping();
return;
}
else if (State == PlayerState.Gliding){
//handle the gliding movement in different function
OnGliding();
return;
}
OnAir();
}
}
/// <summary>
/// Control the player when is in a surface
/// </summary>
void OnSurface(){
// always move along the camera forward as it is the direction that it being aimed at
// desiredMove = (m_Transform.forward * m_Input.y) + (m_Transform.right * m_Input.x);
desiredMove.Set(m_Input.x, 0.0f, m_Input.y);
desiredMove = m_Transform.TransformDirection(desiredMove);
// get a normal for the surface that is being touched to move along it
Physics.SphereCastNonAlloc(m_Transform.localPosition, capsuleRadious, Vector3.down, SurfaceRay,
m_CharacterController.height * 0.5f, Physics.AllLayers, QueryTriggerInteraction.Ignore);
//determine the movement angle based in the normal of the current player surface
desiredMove = Vector3.ProjectOnPlane(desiredMove, SurfaceRay[0].normal);
targetDirection.x = desiredMove.x * speed;
targetDirection.z = desiredMove.z * speed;
SlopeControl();
}
/// <summary>
/// Control the player when is in air (not dropping nor gliding)
/// </summary>
void OnAir(){
desiredMove = (m_Transform.forward * Mathf.Clamp01(m_Input.y)) + (m_Transform.right * m_Input.x);
desiredMove += momentum;
targetDirection += Physics.gravity * m_GravityMultiplier * Time.fixedDeltaTime;
targetDirection.x = (desiredMove.x * speed) * AirControlMultiplier;
targetDirection.z = (desiredMove.z * speed) * AirControlMultiplier;
momentum = Vector3.Lerp(momentum, Vector3.zero, Time.fixedDeltaTime * momentunDecaySpeed);
}
/// <summary>
/// Called when the player hit a surface after falling/jumping
/// </summary>
void OnLand(){
//land camera effect
StartCoroutine(m_JumpBob.DoBobCycle());
isFalling = false;
float fallDistance = CalculateFall();
bl_EventHandler.DispatchPlayerLandEvent(fallDistance);
haslanding = true;
JumpDirection = 0;
targetDirection.y = 0f;
m_Jumping = false;
m_CharacterController.stepOffset = defaultStepOffset;
if (State != PlayerState.Crouching && State != PlayerState.Proning)
State = PlayerState.Idle;
}
/// <summary>
///
/// </summary>
void OnCrouchChanged(){
Proning = false;
if (Crounching){
State = PlayerState.Crouching;
bl_UIReferences.Instance.PlayerUI.PlayerStateIcon.sprite = CrouchIcon;
//Slide implementation
if (canSlide && VelocityMagnitude > WalkSpeed && GetLocalVelocity().z > 0.1f){
DoSlide();
}
}
else{
if (!IsHeadHampered()){
State = PlayerState.Idle;
bl_UIReferences.Instance.PlayerUI.PlayerStateIcon.sprite = StandIcon;
}
else forcedCrouch = true;
}
}
/// <summary>
///
/// </summary>
public void DoCrouchTransition(){
StopCoroutine(nameof(CrouchTransition));
StartCoroutine(nameof(CrouchTransition));
}
/// <summary>
///
/// </summary>
/// <returns></returns>
IEnumerator CrouchTransition(){
float height = 2f;
float radius = 0.4f;
Vector3 center = Vector3.up;
Vector3 verticalCameraPos = defaultCameraRPosition;
float transitionTime = crouchTransitionSpeed;
//
if (Crounching || State == PlayerState.Sliding){
height = 1.4f;
verticalCameraPos.y = 1.2f;
}
else if (State == PlayerState.Proning){
height = proneCapsuleHeight;
radius = proneCapsuleHeight;
verticalCameraPos.y = proneCameraHeight;
transitionTime = proneTransitionTime;
}
//
float originHeight = m_CharacterController.height;
Vector3 originCenter = m_CharacterController.center;
Vector3 originCameraPosition = CameraRoot.localPosition;
center.y = height / 2f;
m_CharacterController.radius = radius;
float d = 0;
while (d < 1){
d += Time.deltaTime / transitionTime;
m_CharacterController.height = Mathf.Lerp(originHeight, height, d);
m_CharacterController.center = Vector3.Lerp(originCenter, center, d);
CameraRoot.localPosition = Vector3.Lerp(originCameraPosition, verticalCameraPos, d);
yield return null;
}
}
/// <summary>
/// Make the player jump
/// </summary>
public override void DoJump(){
momentum = desiredMove * jumpMomentumBooster;
moveDirection.y = (hasPlatformJump) ? PlatformJumpForce : jumpSpeed;
targetDirection.y = moveDirection.y;
PlayJumpSound();
m_Jump = false;
m_Jumping = true;
hasPlatformJump = false;
if (State == PlayerState.Sliding) mouseLook.SetTiltAngle(0);
Crounching = false;
Proning = false;
State = PlayerState.Jumping;
lastJumpTime = Time.time;
m_CharacterController.stepOffset = 0;
}
/// <summary>
/// Make the player slide
/// </summary>
public override void DoSlide(){
if ((Time.time - lastSlideTime) < slideTime * slideCoolDown)
return; //wait the equivalent of one extra slide before be able to slide again
if (m_Jumping) return;
Vector3 startPosition = (m_Transform.position - feetPositionOffset) +
(m_Transform.forward * m_CharacterController.radius);
if (Physics.Linecast(startPosition, startPosition + m_Transform.forward))
return; //there is something in front of the feet's
State = PlayerState.Sliding;
slideForce = slideSpeed; //slide force will be continually decreasing
speed = slideSpeed;
//playerReferences.gunManager.HeadAnimator.Play("slide-start", 0, 0); // if you want to use an animation instead
mouseLook.SetTiltAngle(slideCameraTiltAngle);
if (slideSound != null){
m_AudioSource.clip = slideSound;
m_AudioSource.volume = 0.7f;
m_AudioSource.Play();
}
mouseLook.UseOnlyCameraRotation();
this.InvokeAfter(slideTime, () => {
if (Crounching && !bl_UtilityHelper.isMobile)
State = PlayerState.Crouching;
else if (State != PlayerState.Jumping)
State = PlayerState.Idle;
Crounching = false;
DoCrouchTransition();
lastSlideTime = Time.time;
mouseLook.SetTiltAngle(0);
mouseLook.PortBodyOrientationToCamera();
});
}
/// <summary>
/// Detect slope limit and apply slide physics.
/// </summary>
void SlopeControl(){
float angle = Vector3.Angle(Vector3.up, surfaceNormal);
if (angle <= m_CharacterController.slopeLimit || angle >= 75) return;
Vector3 direction = Vector3.up - surfaceNormal * Vector3.Dot(Vector3.up, surfaceNormal);
float speed = slideSpeed + 1 + Time.deltaTime;
targetDirection += direction * -speed;
targetDirection.y = targetDirection.y - surfacePoint.y;
}
/// <summary>
/// Make the player dropping
/// </summary>
public override void DoDrop(){
if (isGrounded){
Debug.Log("Can't drop when player is in a surface");
return;
}
State = PlayerState.Dropping;
}
/// <summary>
/// Called each frame when the player is dropping (fall control is On)
/// </summary>
void OnDropping(){
//get the camera upside down angle
float tilt = Mathf.InverseLerp(0, 90, mouseLook.VerticalAngle);
//normalize it
tilt = Mathf.Clamp01(tilt);
if (mouseLook.VerticalAngle <= 0 || mouseLook.VerticalAngle >= 180) tilt = 0;
//get the forward direction of the player camera
desiredMove = headRoot.forward * Mathf.Clamp01(m_Input.y);
if (desiredMove.y > 0) desiredMove.y = 0;
//calculate the drop speed based in the upside down camera angle
float dropSpeed = Mathf.Lerp(m_GravityMultiplier * dropTiltSpeedRange.x,
m_GravityMultiplier * dropTiltSpeedRange.y, tilt);
targetDirection = Physics.gravity * dropSpeed * Time.fixedDeltaTime;
//if the player press the vertical input -> add velocity in the direction where the camera is looking at
targetDirection += desiredMove * dropControlSpeed;
//apply the movement direction in the character controller
m_CollisionFlags = m_CharacterController.Move(targetDirection * Time.fixedDeltaTime);
}
/// <summary>
/// Make the player glide
/// </summary>
public override void DoGliding(){
if (isGrounded){
Debug.Log("Can't gliding when player is in a surface");
return;
}
State = PlayerState.Gliding;
}
/// <summary>
/// Called each frame when the player is gliding
/// </summary>
void OnGliding(){
desiredMove = (m_Transform.forward * m_Input.y) + (m_Transform.right * m_Input.x);
//how much can the player control the player when is in air.
float airControlMult = AirControlMultiplier * 5;
//fall gravity amount
float gravity = m_GravityMultiplier * 15;
targetDirection = Physics.gravity * gravity * Time.fixedDeltaTime;
targetDirection.x = (desiredMove.x * speed) * airControlMult;
targetDirection.z = (desiredMove.z * speed) * airControlMult;
m_CollisionFlags = m_CharacterController.Move(targetDirection * Time.fixedDeltaTime);
}
/// <summary>
///
/// </summary>
void OnClimbing(){
if (m_Ladder.HasPending){
if (!MoveToStarted){
StartCoroutine(MoveTo(m_Ladder.GetCurrent, false));
}
}
else{
desiredMove = m_Ladder.transform.rotation * forwardVector * m_Input.y;
targetDirection.y = desiredMove.y * climbSpeed;
targetDirection.x = desiredMove.x * climbSpeed;
targetDirection.z = desiredMove.z * climbSpeed;
if (bl_GameInput.Jump()){
ToggleClimbing();
m_Ladder.JumpOut();
targetDirection.y = jumpSpeed;
targetDirection.z = 30;
lastJumpTime = Time.time;
}
m_CollisionFlags = m_CharacterController.Move(targetDirection * Time.smoothDeltaTime);
}
}
/// <summary>
/// Math behind the fall damage calculation
/// </summary>
private float CalculateFall(){
float fallDistance = HigherPointOnJump - m_Transform.position.y;
if (JumpDirection == -1){
float normalized = PostGroundVerticalPos - m_Transform.position.y;
fallDistance = Mathf.Abs(normalized);
}
if (FallDamage && hasTouchGround && haslanding){
if (JumpInmune){
JumpInmune = false;
return fallDistance;
}
if ((Time.time - fallingTime) <= 0.4f){
bl_EventHandler.DispatchPlayerLandEvent(0.2f);
return fallDistance;
}
float ave = fallDistance / DeathFallDistance;
if (fallDistance > SafeFallDistance){
int damage = Mathf.FloorToInt(ave * 100);
playerReferences.playerHealthManager.DoFallDamage(damage);
}
PlayLandingSound(ave);
fallingTime = Time.time;
}
else PlayLandingSound(1);
return fallDistance;
}
/// <summary>
/// Check in which vertical direction is the player translating to
/// </summary>
void VerticalDirectionCheck(){
if (m_Transform.position.y == PostGroundVerticalPos) return;
//if the direction has not been decided yet
if (JumpDirection == 0){
//is the player below or above from the surface he was?
// 1 = above (jump), -1 = below (falling)
JumpDirection = (m_Transform.position.y > PostGroundVerticalPos) ? 1 : -1;
}
else if (JumpDirection == 1) //if the player jump
{
//but not start falling
if (m_Transform.position.y < PostGroundVerticalPos){
//get the higher point he reached jumping
HigherPointOnJump = PostGroundVerticalPos;
}
else //if still going up
{
PostGroundVerticalPos = m_Transform.position.y;
}
}
else //if the player was falling without jumping
{
}
}
/// <summary>
///
/// </summary>
private void GetInput(out float outputSpeed){
if (!isControlable){
m_Input = Vector2.zero;
outputSpeed = 0;
return;
}
// Read input
HorizontalInput = bl_GameInput.Horizontal;
VerticalInput = bl_GameInput.Vertical;
#if MFPSM
if (bl_UtilityHelper.isMobile){
HorizontalInput = Joystick.Horizontal;
if (isSprintLock){
VerticalInput = 1.25f;
}
else{
VerticalInput = Joystick.Vertical;
VerticalInput = VerticalInput * 1.25f;
}
}
#endif
if (State == PlayerState.Sliding){
VerticalInput = 1;
HorizontalInput = 0;
}
// m_Input = Vector2.Lerp(m_Input, new Vector2(HorizontalInput, VerticalInput), Time.deltaTime * 25);
m_Input.Set(HorizontalInput, VerticalInput);
float inputMagnitude = m_Input.magnitude;
//if the player is dropping, the speed is calculated in the dropping function
if (State == PlayerState.Dropping || State == PlayerState.Gliding){
outputSpeed = 0;
return;
}
if (State != PlayerState.Climbing && State != PlayerState.Sliding){
if (inputMagnitude > 0 && State != PlayerState.Crouching && State != PlayerState.Proning){
if (VelocityMagnitude > 0){
float forwardVelocity = GetLocalVelocity().z;
if (!bl_UtilityHelper.isMobile){
// On standalone builds, walk/run speed is modified by a key press.
// keep track of whether or not the character is walking or running
if (bl_GameInput.Run() && forwardVelocity > 0.1f){
if (runToAimBehave == PlayerRunToAimBehave.AimWhileRunning)
State = PlayerState.Running;
else if (runToAimBehave == PlayerRunToAimBehave.StopRunning)
State = isAiming ? PlayerState.Walking : PlayerState.Running;
}
else if (canStealthMode && bl_GameInput.Stealth() && VelocityMagnitude > 0.1f){
State = PlayerState.Stealth;
}
else{
State = PlayerState.Walking;
}
}
else{
if (VerticalInput > 1 && forwardVelocity > 0.1f){
State = PlayerState.Running;
}
else if (canStealthMode && VerticalInput > 0.05f && VerticalInput <= 0.15f){
State = PlayerState.Stealth;
}
else{
State = PlayerState.Walking;
}
}
}
else{
if (State != PlayerState.Jumping){
State = PlayerState.Idle;
}
}
}
else if (m_CharacterController.isGrounded){
if (State != PlayerState.Jumping && State != PlayerState.Crouching && State != PlayerState.Proning){
State = PlayerState.Idle;
}
}
}
if (State == PlayerState.Proning){
outputSpeed = proneSpeed;
}
else if (Crounching){
outputSpeed = (State == PlayerState.Crouching) ? crouchSpeed : runSpeed;
if (State == PlayerState.Sliding){
outputSpeed += 1;
}
}
else{
// set the desired speed to be walking or running
outputSpeed = (State == PlayerState.Running && m_CharacterController.isGrounded) ? runSpeed : WalkSpeed;
if (State == PlayerState.Stealth){
outputSpeed = stealthSpeed;
}
}
// normalize input if it exceeds 1 in combined length:
if (inputMagnitude > 1){
m_Input.Normalize();
}
if (RunFovEffect){
float rf = (State == PlayerState.Running && m_CharacterController.isGrounded) ? runFOVAmount : 0;
RunFov = Mathf.Lerp(RunFov, rf, Time.deltaTime * 6);
}
}
/// <summary>
///
/// </summary>
public override void PlayFootStepSound(){
if (State == PlayerState.Sliding) return;
if (!m_CharacterController.isGrounded && !isClimbing)
return;
if (!isClimbing){
if (State == PlayerState.Stealth || State == PlayerState.Crouching){
footstep?.SetVolumeMuliplier(footstep.stealthModeVolumeMultiplier);
}
else footstep?.SetVolumeMuliplier(1f);
footstep?.DetectAndPlaySurface();
}
else{
footstep?.PlayStepForTag("Generic");
}
}
/// <summary>
///
/// </summary>
public override void PlatformJump(float force){
hasPlatformJump = true;
PlatformJumpForce = force;
JumpInmune = true;
}
#if MFPSM
/// <summary>
///
/// </summary>
void OnCrouchClicked(){
Crounching = !Crounching;
OnCrouchChanged();
}
void OnJump(){
if (!m_Jump && State != PlayerState.Crouching){
m_Jump = true;
}
}
void OnProne(){
if (CanProne()){
Proning = !Proning;
Crounching = false;
OnProneChanged();
}
}
void OnSprintLock(){
isSprintLock = !isSprintLock;
}
#endif
/// <summary>
///
/// </summary>
public override void UpdateMouseLook(){
mouseLook.Update();
if (bl_GameInput.InputFocus != MFPSInputFocus.Player) return;
if (!isClimbing){
mouseLook.UpdateLook(m_Transform, headRoot);
}
else{
mouseLook.UpdateLook(m_Transform, headRoot, m_Ladder.InsertionPoint);
}
}
/// <summary>
///
/// </summary>
private void CheckStates(){
if (lastState == State) return;
OnStateChanged(lastState, State);
lastState = State;
}
/// <summary>
///
/// </summary>
private void PlayLandingSound(float vol = 1){
vol = Mathf.Clamp(vol, 0.05f, 1);
m_AudioSource.clip = landSound;
m_AudioSource.volume = vol;
m_AudioSource.Play();
}
/// <summary>
///
/// </summary>
private void PlayJumpSound(){
m_AudioSource.volume = 1;
m_AudioSource.clip = jumpSound;
m_AudioSource.Play();
}
/// <summary>
/// Check if the player has a obstacle above the head
/// </summary>
/// <returns></returns>
public bool IsHeadHampered(){
Vector3 origin = m_Transform.localPosition + m_CharacterController.center +
Vector3.up * m_CharacterController.height * 0.5F;
float dist = 2.05f - m_CharacterController.height;
return Physics.Raycast(origin, Vector3.up, dist);
}
#region External Events
void OnRoundEnd(){
Finish = true;
}
void OnChangeWeapon(int id){
isAiming = false;
var currentWeapon = playerReferences.gunManager.GetCurrentWeapon();
if (currentWeapon != null){
WeaponWeight = currentWeapon.WeaponWeight;
}
else{
WeaponWeight = 0;
}
}
void OnMatchStart(){
isControlable = true;
}
void OnGameSettingsChanged() => mouseLook.FetchSettings();
void OnAimChange(bool aim){
isAiming = aim;
mouseLook.OnAimChange(aim);
}
#endregion
/// <summary>
///
/// </summary>
private void ToggleClimbing(){
isClimbing = !isClimbing;
State = (isClimbing) ? PlayerState.Climbing : PlayerState.Idle;
if (isClimbing)
bl_InputInteractionIndicator.ShowIndication(bl_Input.GetButtonName("Jump"), bl_GameTexts.JumpOffLadder);
else bl_InputInteractionIndicator.SetActiveIfSame(false, bl_GameTexts.JumpOffLadder);
}
/// <summary>
///
/// </summary>
IEnumerator MoveTo(Vector3 pos, bool down){
if (m_Transform == null) m_Transform = transform;
MoveToStarted = true;
float t = 0;
Vector3 from = m_Transform.position;
while (t < 1){
t += Time.deltaTime / 0.4f;
m_Transform.position = Vector3.Lerp(from, pos, t);
yield return null;
}
if (down){
bl_EventHandler.onPlayerLand(0.5f);
}
if (m_Ladder != null){
m_Ladder.HasPending = false;
}
MoveToStarted = false;
}
/// <summary>
///
/// </summary>
/// <param name="other"></param>
void OnTriggerEnter(Collider other){
if (!photonView.IsMine) return;
if (other.transform.parent == null)
return;
var ladder = other.GetComponentInParent<bl_Ladder>();
if (ladder != null){
if (!ladder.CanUse)
return;
m_Ladder = ladder;
if (other.transform.name == bl_Ladder.BottomColName){
m_Ladder.InsertionPoint = other.transform;
if (!isClimbing){
JumpInmune = true;
m_Ladder.ToBottom();
ToggleClimbing();
}
else{
ToggleClimbing();
m_Ladder.HasPending = false;
}
}
else if (other.transform.name == bl_Ladder.TopColName){
m_Ladder.InsertionPoint = other.transform;
if (isClimbing){
m_Ladder.SetToTop();
if (!MoveToStarted){
StartCoroutine(MoveTo(m_Ladder.GetCurrent, true));
}
}
else{
m_Ladder.ToMiddle();
}
ToggleClimbing();
}
}
}
/// <summary>
///
/// </summary>
private void OnControllerColliderHit(ControllerColliderHit hit){
surfaceNormal = hit.normal;
surfacePoint = hit.point;
/// Enable this if you want player controller apply force on contact to rigidbodys
/// is commented by default for performance matters.
/* Rigidbody body = hit.collider.attachedRigidbody;
//dont move the rigidbody if the character is on top of it
if (m_CollisionFlags == CollisionFlags.Below)
{
return;
}
if (body == null || body.isKinematic)
{
return;
}
body.AddForceAtPosition(m_CharacterController.velocity * 0.1f, hit.point, ForceMode.Impulse);*/
}
internal float _speed = 0;
public float speed{
get{ return _speed; }
set{
_speed = value - WeaponWeight;
float min = 1.75f;
if (State == PlayerState.Stealth || State == PlayerState.Proning){
min = 1;
}
_speed = Mathf.Max(_speed, min);
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override float GetCurrentSpeed(){
return speed;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override float GetSpeedOnState(PlayerState playerState, bool includeModifiers){
switch (playerState){
case PlayerState.Walking:
return includeModifiers ? WalkSpeed - WeaponWeight : WalkSpeed;
case PlayerState.Running:
return includeModifiers ? runSpeed - WeaponWeight : runSpeed;
case PlayerState.Crouching:
return includeModifiers ? crouchSpeed - WeaponWeight : crouchSpeed;
case PlayerState.Dropping:
return dropTiltSpeedRange.y;
case PlayerState.Proning:
return proneSpeed;
}
return includeModifiers ? WalkSpeed - WeaponWeight : WalkSpeed;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override PlayerRunToAimBehave GetRunToAimBehave(){
return runToAimBehave;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override MouseLookBase GetMouseLook(){
return mouseLook;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override bl_Footstep GetFootStep(){
return footstep;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override float GetSprintFov(){
return RunFov;
}
/// <summary>
///
/// </summary>
/// <param name="vertical"></param>
/// <returns></returns>
public override float GetHeadBobMagnitudes(bool vertical){
if (vertical) return headVerticalBobMagnitude;
return headBobMagnitude;
}
public Vector3 GetLocalVelocity() => m_Transform.InverseTransformDirection(Velocity);
public Vector3 MovementDirection => targetDirection;
public override bool isGrounded{
get{ return m_CharacterController.isGrounded; }
}
[SerializeField]
public class LerpControlledBob
{
public float BobDuration;
public float BobAmount;
private float m_Offset = 0f;
// provides the offset that can be used
public float Offset(){
return m_Offset;
}
public IEnumerator DoBobCycle(){
// make the camera move down slightly
float t = 0f;
while (t < BobDuration){
m_Offset = Mathf.Lerp(0f, BobAmount, t / BobDuration);
t += Time.deltaTime;
yield return new WaitForFixedUpdate();
}
// make it move back to neutral
t = 0f;
while (t < BobDuration){
m_Offset = Mathf.Lerp(BobAmount, 0f, t / BobDuration);
t += Time.deltaTime;
yield return new WaitForFixedUpdate();
}
m_Offset = 0f;
}
}
#region Prone
[Header("Prone")] public bool enableProne = true;
public float proneSpeed = 1;
public float proneCapsuleHeight = 0.25f;
public float proneCameraHeight = 0.1f;
public float proneTransitionTime = 0.5f;
public Sprite proneIcon;
//
public bool Proning = false;
/// <summary>
///
/// </summary>
private void ProneInput(){
if (CanProne()){
if (bl_GameInput.Prone()){
Proning = !Proning;
Crounching = false;
OnProneChanged();
}
}
}
void OnProneChanged(){
if (Proning){
State = PlayerState.Proning;
bl_UIReferences.Instance.PlayerUI.PlayerStateIcon.sprite = proneIcon;
}
else{
if (!IsHeadHampered()){
State = PlayerState.Idle;
bl_UIReferences.Instance.PlayerUI.PlayerStateIcon.sprite = StandIcon;
}
else forcedCrouch = true;
}
}
private bool CanProne(){
if (!enableProne || !isGrounded){
return false;
}
return State != PlayerState.Jumping && State != PlayerState.Climbing;
}
#endregion
}Editor is loading...
Leave a Comment