using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; using RPGCreationKit; namespace RPGCreationKit.Player { public class PlayerMovements : PlayerStatus { [SerializeField] public CharacterController charController; [SerializeField] public MouseLook mouseLook; public bool isFreezed = false; protected bool controlsEnabled = true; protected bool movementsEnabled = true; public bool isInCutsceneMode = false; public bool isJumping = false; public bool isRunning = false; public bool iscrouching = false; [Space(5)] [SerializeField] private GameObject fpHandsContainer; [SerializeField] private float fpsHandOffsetStep = 2; [SerializeField] private Vector3 FPSHandsOffsetWhileStanding; [SerializeField] private Vector3 FPSHandsOffsetWhileCrouching; [SerializeField] [Range(0f, 1f)] private float m_RunstepLenghten; [SerializeField] private float m_StepInterval; [SerializeField] private AudioClip[] m_FootstepSounds; // an array of footstep sounds that will be randomly selected from. private float m_StepCycle; private float m_NextStep; public bool IsCrouching { get { return iscrouching; } set { if (charController.isGrounded && !crouchEditInProgress) { iscrouching = value; OnCrouchChanges(); } } } float x, z; Vector3 direction; public float curSpeed; public float walkSpeed = 5.0f; public float runSpeed = 7.5f; public float crouchSpeed = 2.5f; bool isSprintingFat = false; [SerializeField] private float sprintCost; public float jumpForce = 1.5f; public float gravity = -9.81f; public float m_StickToGroundForce = -7f; Vector3 velocity; private bool jump = false; private bool m_PreviouslyGrounded; public bool m_isMoving; private bool canStandUp = false; [SerializeField] private float cameraStandingY = 0f; [SerializeField] private float cameraCrouchingY = -.75f; [SerializeField] private float standingHeight = 2.7f; [SerializeField] private float crouchHeight = 1.7f; [SerializeField] private float crouchEditSpeed = 2f; public bool isInThirdPerson; public ThirdPersonPlayer thirdPersonModel; public void INPUT_MoveAxis(InputAction.CallbackContext value) { Vector2 dValue = value.ReadValue(); if (!inventory.IsOverencumbred()) { x = dValue.x; z = dValue.y; } else { x = 0; z = 0; AlertMessage.instance.InitAlertMessage("You are overencumbred.", 5, false); } } public void INPUT_JumpCmd(InputAction.CallbackContext value) { if (controlsEnabled && !isFreezed && PlayerCombat.instance.canAttack) if (charController.isGrounded && value.started) { if (!IsCrouching) jump = true; else INPUT_CrouchCmd(value); } } public void INPUT_RunCmd(InputAction.CallbackContext value) { if (controlsEnabled && !isFreezed) if (value.started && playerAttributes.CurStamina >= 5.0f) { if (charController.isGrounded) { if (!isRunning) { if (IsCrouching && canStandUp) { IsCrouching = false; isRunning = true; } else if (!IsCrouching) isRunning = true; } else isRunning = false; } } } public void INPUT_CrouchCmd(InputAction.CallbackContext value) { if (controlsEnabled && !isFreezed) if (value.started) { if (IsCrouching == true) { if (canStandUp) IsCrouching = false; } else IsCrouching = true; } } public void INPUT_ChangePersonCmd(InputAction.CallbackContext value) { if (controlsEnabled && !isFreezed && value.started) { if (!isInThirdPerson) { SwitchToThirdPerson(); } else { SwitchToFirstPerson(); } } } public override void Start() { base.Start(); m_PreviouslyGrounded = charController.isGrounded; thirdPersonModel = ThirdPersonPlayer.instance; } public override void Update() { base.Update(); if (!isFreezed) { HandleMovements(); if (IsCrouching) CanStandUpCheck(); BroadcastAnimatorToThirdPerson(); } } public virtual void FixedUpdate() { } private void HandleMovements() { if (charController.isGrounded && !jump) velocity.y = m_StickToGroundForce; if (movementsEnabled) direction = transform.right * x + transform.forward * z; else { direction = Vector3.zero; velocity = Vector3.zero; } curSpeed = (isRunning) ? runSpeed : (IsCrouching) ? crouchSpeed : walkSpeed; // Jump if (jump && charController.isGrounded) { velocity.y = Mathf.Sqrt(jumpForce * -2f * gravity); PlayerCombat.instance.fpcAnim.ResetTrigger("Land"); cameraAnim.m_Animator.SetTrigger("Jump"); PlayerCombat.instance.fpcAnim.SetTrigger("Jump"); ThirdPersonPlayer.instance.m_Animator.SetTrigger("Jump"); jump = false; } velocity.y += gravity * Time.deltaTime; if (!isInCutsceneMode) { m_isMoving = (direction == Vector3.zero) ? false : true; cameraAnim.m_Animator.SetBool("isMoving", m_isMoving); cameraAnim.m_Animator.SetBool("isWalking", !isRunning); } else { m_isMoving = false; cameraAnim.m_Animator.SetBool("isMoving", false); cameraAnim.m_Animator.SetBool("isWalking", false); } if (m_isMoving && isRunning) SprintFatigue(); if (!movementsEnabled) { direction = Vector3.zero; velocity = Vector3.zero; } direction.Normalize(); if(charController.enabled) charController.Move(((direction * curSpeed) + velocity) * Time.deltaTime); ClampStates(); if (!m_PreviouslyGrounded && charController.isGrounded) { // Landed isJumping = false; cameraAnim.m_Animator.SetTrigger("Land"); PlayerCombat.instance.fpcAnim.ResetTrigger("Jump"); PlayerCombat.instance.fpcAnim.SetTrigger("Land"); ThirdPersonPlayer.instance.m_Animator.SetTrigger("Land"); /* if (playerCombat.weaponDrawn && playerCombat.canAttack) { playerCombat.fpcAnim.SetTrigger("Land"); playerCombat.fpcAnim.ResetTrigger("Jump"); } */ } ProgressStepCycle(curSpeed); m_PreviouslyGrounded = charController.isGrounded; } /// /// Controls the states - never make Is Crouching and Is Running be both true at the same time etc /// private void ClampStates() { if (z <= .86f || IsCrouching) isRunning = false; if(playerAttributes.CurStamina <= 1.0f && isRunning) isRunning = false; if (isRunning && canStandUp) IsCrouching = false; } /// /// Modifies the Player dimensions when he's crouching /// private void OnCrouchChanges() { StartCoroutine(SmoothHeightChange()); StartCoroutine(SmoothFPHandsChange()); thirdPersonModel.m_Animator.SetBool("isCrouched", iscrouching); } private bool crouchEditInProgress = false; IEnumerator SmoothHeightChange() { crouchEditInProgress = true; if (IsCrouching) { Vector3 camTarget = new Vector3(cameraAnim.transform.localPosition.x, cameraCrouchingY, cameraAnim.transform.localPosition.z); // Lerp camera cameraAnim.LerpCamera(camTarget, crouchSpeed); while (charController.height > crouchHeight) { charController.height -= crouchEditSpeed * Time.deltaTime; charController.center = Vector3.down * (standingHeight - charController.height) / 2.0f; yield return null; } cameraAnim.MoveCamera(camTarget, true); charController.height = crouchHeight; } else { Vector3 camTarget = new Vector3(cameraAnim.transform.localPosition.x, cameraStandingY, cameraAnim.transform.localPosition.z); // Lerp camera cameraAnim.LerpCamera(camTarget, crouchEditSpeed); while (charController.height < standingHeight) { if(charController.height < standingHeight) charController.height += crouchEditSpeed * Time.deltaTime; charController.center = Vector3.down * (standingHeight - charController.height) / 2.0f; yield return null; } cameraAnim.MoveCamera(camTarget, true); charController.height = standingHeight; } crouchEditInProgress = false; yield return null; } IEnumerator SmoothFPHandsChange() { if (IsCrouching) { while (fpHandsContainer.transform.localPosition != FPSHandsOffsetWhileCrouching) { fpHandsContainer.transform.localPosition = Vector3.MoveTowards(fpHandsContainer.transform.localPosition, FPSHandsOffsetWhileCrouching, fpsHandOffsetStep * Time.deltaTime); yield return null; } fpHandsContainer.transform.localPosition = FPSHandsOffsetWhileCrouching; } else { while (fpHandsContainer.transform.localPosition != FPSHandsOffsetWhileStanding) { fpHandsContainer.transform.localPosition = Vector3.MoveTowards(fpHandsContainer.transform.localPosition, FPSHandsOffsetWhileStanding, fpsHandOffsetStep * Time.deltaTime); yield return null; } fpHandsContainer.transform.localPosition = FPSHandsOffsetWhileStanding; } } public void SprintFatigue() { if (isSprintingFat) return; StopRecoveringStamina(); StopCoroutine("ReduceFatigue"); StartCoroutine("ReduceFatigue"); } public IEnumerator ReduceFatigue() { while (m_isMoving && isRunning) { CancelInvoke("ResetRecover"); isSprintingFat = true; playerAttributes.CurStamina -= sprintCost * Time.deltaTime; if (playerAttributes.CurStamina <= 0) playerAttributes.CurStamina = 0; yield return null; } isSprintingFat = false; Invoke("ResetRecover", recoverAfterActionDelay); } public void EnableDisableControls(bool _enable) { if (_enable) { mouseLook.LockCursor(); // Enable them controlsEnabled = true; movementsEnabled = true; mouseLook.lookEnabled = true; } else { mouseLook.UnlockCursor(); // Disable them controlsEnabled = false; movementsEnabled = false; mouseLook.lookEnabled = false; } } public void FreezeOnly() { charController.enabled = false; isFreezed = true; direction = Vector3.zero; velocity = Vector3.zero; if (charController.enabled) charController.Move(Vector3.zero); } public void Unfreeze() { isFreezed = false; direction = Vector3.zero; velocity = Vector3.zero; if (charController.enabled) charController.Move(Vector3.zero); charController.enabled = true; } public float crouchRayDistance = 1.5f; public float crouchSphereRadius = 1f; public LayerMask crouchLayermask; private void CanStandUpCheck() { var coll = Physics.OverlapSphere(transform.position + (transform.up.normalized * crouchRayDistance), crouchSphereRadius, crouchLayermask); if (coll.Length <= 0) canStandUp = true; else canStandUp = false; } public void FreezeAndDisableControl() { charController.enabled = false; isFreezed = true; direction = Vector3.zero; velocity = Vector3.zero; if(charController.enabled) charController.Move(Vector3.zero); EnableDisableControls(false); } public void UnfreezeAndEnableControls() { isFreezed = false; direction = Vector3.zero; velocity = Vector3.zero; if(charController.enabled) charController.Move(Vector3.zero); EnableDisableControls(true); charController.enabled = true; } public bool IsControlledByPlayer() { return (!isFreezed && charController.enabled && movementsEnabled && controlsEnabled); } public void ForceCrouch() { iscrouching = true; OnCrouchChanges(); } private void PlayFootStepAudio() { if (!charController.isGrounded) { return; } // pick & play a random footstep sound from the array, // excluding sound at index 0 int n = Random.Range(1, m_FootstepSounds.Length); AudioClip swap = m_FootstepSounds[n]; GameAudioManager.instance.PlayOneShot(AudioSources.Player, m_FootstepSounds[n]); // move picked sound to index 0 so it's not picked next time m_FootstepSounds[n] = m_FootstepSounds[0]; m_FootstepSounds[0] = swap; } private void ProgressStepCycle(float speed) { if (charController.velocity.sqrMagnitude > 0 && (x != 0 || z != 0)) { m_StepCycle += (charController.velocity.magnitude + (speed * (!isRunning ? 1f : m_RunstepLenghten))) * Time.fixedDeltaTime; } if (!(m_StepCycle > m_NextStep)) { return; } m_NextStep = m_StepCycle + m_StepInterval; PlayFootStepAudio(); } public virtual void SwitchToThirdPerson() { thirdPersonModel.character.ShowAll(); cameraAnim.SwitchToTPSCamera(); isInThirdPerson = true; // Enable TPS weapon if (thirdPersonModel.currentWeaponOnHip != null) { if(thirdPersonModel.currentWeaponOnHip.GetComponent() != null) thirdPersonModel.currentWeaponOnHip.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; if(thirdPersonModel.currentWeaponOnHip.GetComponentInChildren() != null) thirdPersonModel.currentWeaponOnHip.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } if (thirdPersonModel.currentWeaponObject != null) { if(thirdPersonModel.currentWeaponObject.GetComponent() != null) thirdPersonModel.currentWeaponObject.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; if(thirdPersonModel.currentWeaponObject.GetComponentInChildren() != null) thirdPersonModel.currentWeaponObject.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } if (thirdPersonModel.currentWeaponOnHand != null) thirdPersonModel.currentWeaponOnHand.enabled = true; if (thirdPersonModel.currentAmmoObject != null) thirdPersonModel.currentAmmoObject.SetActive(true); if (Equipment.PlayerEquipment.currentShieldObject != null) { if(Equipment.PlayerEquipment.currentShieldObject.GetComponent() != null) Equipment.PlayerEquipment.currentShieldObject.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; if (Equipment.PlayerEquipment.currentShieldObject.GetComponentInChildren() != null) Equipment.PlayerEquipment.currentShieldObject.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } if(thirdPersonModel.projectile != null) { if (thirdPersonModel.projectile.GetComponent() != null) thirdPersonModel.projectile.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } // Disable FPS weapon if (PlayerCombat.instance.currentWeaponOnHand != null) { PlayerCombat.instance.currentWeaponOnHand.enabled = false; if (PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponent() != null) PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; if(PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponentInChildren() != null) PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; } } public virtual void SwitchToFirstPerson() { thirdPersonModel.character.HideAll(); cameraAnim.SwitchToFPSCamera(); isInThirdPerson = false; // Disable TPS weapon if(thirdPersonModel.currentWeaponOnHip != null) { if(thirdPersonModel.currentWeaponOnHip.GetComponent() != null) thirdPersonModel.currentWeaponOnHip.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; if(thirdPersonModel.currentWeaponOnHip.GetComponentInChildren() != null) thirdPersonModel.currentWeaponOnHip.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; } if (thirdPersonModel.currentWeaponObject != null) { if(thirdPersonModel.currentWeaponObject.GetComponent() != null) thirdPersonModel.currentWeaponObject.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; if(thirdPersonModel.currentWeaponObject.GetComponentInChildren() != null) thirdPersonModel.currentWeaponObject.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; } if (thirdPersonModel.currentWeaponOnHand != null) thirdPersonModel.currentWeaponOnHand.enabled = false; if (thirdPersonModel.currentAmmoObject != null) thirdPersonModel.currentAmmoObject.SetActive(false); if (Equipment.PlayerEquipment.currentShieldObject != null) { if (Equipment.PlayerEquipment.currentShieldObject.GetComponent() != null) Equipment.PlayerEquipment.currentShieldObject.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; if (Equipment.PlayerEquipment.currentShieldObject.GetComponentInChildren() != null) Equipment.PlayerEquipment.currentShieldObject.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; } if (thirdPersonModel.projectile != null) { if (thirdPersonModel.projectile.GetComponent() != null) thirdPersonModel.projectile.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; } // Enable FPS weapon if (PlayerCombat.instance.currentWeaponOnHand != null) { PlayerCombat.instance.currentWeaponOnHand.enabled = true; if(PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponent() != null) PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; if(PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponentInChildren() != null) PlayerCombat.instance.currentWeaponOnHand.gameObject.GetComponentInChildren().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } } /// /// Syncs the player's input to the third person /// public virtual void BroadcastAnimatorToThirdPerson() { // thirdPersonModel.m_Animator.SetFloat("Speed", (z), 0.25f, Time.deltaTime); thirdPersonModel.m_Animator.SetFloat("Speed", isRunning ? (z) : Mathf.Clamp(z, -1f, 0.5f), 0.25f, Time.deltaTime); thirdPersonModel.m_Animator.SetFloat("Sideways", (x), 0.25f, Time.deltaTime); // is Rotating thirdPersonModel.m_Animator.SetBool("isRotating", Mathf.Abs(mouseLook.x) > 20.0f ? true : false); } } }