public void MoveGrounded(float speed) { Vector3 targetVector = RawTargetVector(speed); targetAngle = Vector3.SignedAngle(Vector3.forward, targetVector.normalized, Vector3.up); targetSpeed = UMath.GetHorizontalMag(targetVector); anim.SetFloat("SignedTargetAngle", targetAngle); anim.SetFloat("TargetAngle", Mathf.Abs(targetAngle)); anim.SetFloat("TargetSpeed", targetSpeed); // Allows Lara to smoothly take off if (localVelocity.sqrMagnitude == 0f && targetVector.magnitude > 0.1f) { Vector3 camForward = cam.forward; camForward.y = 0f; camForward.Normalize(); // Finds correct forward direction for local velocity localVelocity = Quaternion.FromToRotation(camForward, transform.forward) * (Vector3.forward * 0.1f); } localVelocity = Vector3.Slerp(localVelocity, targetVector, Time.deltaTime * speedChangeRate); velocity = Quaternion.Euler(0f, cam.eulerAngles.y, 0f) * localVelocity; float actualSpeed = direction * UMath.GetHorizontalMag(velocity); anim.SetFloat("Speed", actualSpeed); }
public override void Update(PlayerController player) { if (Time.time - timeTracker >= grabTime) { if (ledgeInfo.Type == LedgeType.Monkey || (UMath.GetHorizontalMag(player.Velocity) > 2f && HasFeetRoom())) { player.Anim.SetTrigger("DeepGrab"); } if (UMath.GetHorizontalMag(player.Velocity) > 0.2f) { player.Anim.SetTrigger("Grab"); } else { player.Anim.SetTrigger("StandGrab"); } player.transform.position = grabPoint; if (ledgeInfo.Type == LedgeType.Free) { player.StateMachine.GoToState <Freeclimb>(); } else if (ledgeInfo.Type == LedgeType.Monkey) { player.StateMachine.GoToState <MonkeySwing>(); } else { player.StateMachine.GoToState <Climbing>(); } } }
private bool TryReachLedge(PlayerController player, float zVel, ref float yVel, bool allowClearingBoost = true) { // Doing standing jump, allow player to grab if close if (zVel < 0.5f) { zVel = 0.5f; } // Need to check where player will be relative to ledge float timeAtPeak = yVel / player.Gravity; // v = u + at Vector3 relative = ledgeInfo.Point - player.transform.position; float displacement = UMath.GetHorizontalMag(relative); // Maximum to account for when player hits wall but keeps moving up float timeAtLedge = Mathf.Max(UMath.TimeAtHorizontalPoint(zVel, displacement), timeAtPeak); float vertPos = UMath.PredictDisplacement(yVel, timeAtLedge, -player.Gravity); if (vertPos >= relative.y - 2.6f && vertPos <= relative.y - 0.8f) // Distance is great, do auto-grab { player.StateMachine.GoToState <AutoGrabbing>(ledgeInfo); return(true); } else if (allowClearingBoost && vertPos < relative.y && vertPos > relative.y - 0.8f) // she hits it around the hip just adjust up velocity to clear it { float time; Vector3 adjustedVel = UMath.VelocityToReachPoint(player.transform.position, ledgeInfo.Point, zVel, player.Gravity, out time); yVel = adjustedVel.y; } return(false); }
public void RotateToCamera() { if (UMath.GetHorizontalMag(velocity) > 0.1f) { Quaternion target = Quaternion.LookRotation(cam.transform.forward, Vector3.up); target = Quaternion.Euler(0f, target.eulerAngles.y, 0f); transform.rotation = target; } }
public override void Update(PlayerController player) { if (player.Grounded) { Debug.Log("Unfortunately grounded my love"); player.StateMachine.GoToState <Locomotion>(); return; } if (Time.time - timeTracker >= grabTime) { // adjust to align with moving ledge if (ledgeInfo.Collider != null) { Vector3 change = ledgeInfo.Collider.transform.position - initialColliderPos; grabPoint += change; } if (ledgeInfo.Type != LedgeType.HorPole) { if (UMath.GetHorizontalMag(player.Velocity) > 2f && HasFeetRoom()) { player.Anim.SetTrigger("DeepGrab"); } if (UMath.GetHorizontalMag(player.Velocity) > 0.2f) { player.Anim.SetTrigger("Grab"); } else { player.Anim.SetTrigger("StandGrab"); } } player.transform.position = grabPoint; player.transform.rotation = targetRot; if (ledgeInfo.Type == LedgeType.Free) { player.StateMachine.GoToState <Freeclimb>(); } else if (ledgeInfo.Type == LedgeType.Monkey) { player.StateMachine.GoToState <MonkeySwing>(); } else { player.StateMachine.GoToState <Climbing>(); } } }
// This method is necessary as Lara must run backwards 50% of the time public void RotateToVelocityStrafe(float smoothing = 8f) { if (UMath.GetHorizontalMag(velocity) < 0.1f) { return; } float theAngle = Mathf.Atan2(velocity.x, velocity.z) * Mathf.Rad2Deg; if (targetAngle < -50f || targetAngle > 140f) { if (direction != -1) { adjustRotCombat = true; } direction = -1; } else if (targetAngle > -40f && targetAngle < 130f) { if (direction != 1) { adjustRotCombat = true; } direction = 1; } if (direction == -1) { theAngle += 180f; } Quaternion target = Quaternion.Euler(0.0f, theAngle, 0.0f); if (!adjustRotCombat) { transform.rotation = target; } else { if (Mathf.Abs(Quaternion.Angle(target, transform.rotation)) > 10f) { transform.rotation = Quaternion.Slerp(transform.rotation, target, smoothing * Time.deltaTime); } else { adjustRotCombat = false; } } }
public void RotateToVelocityGround(float smoothing = 0f) { direction = 1; if (UMath.GetHorizontalMag(velocity) < 0.1f) { return; } Quaternion target = Quaternion.Euler(0.0f, Mathf.Atan2(velocity.x, velocity.z) * Mathf.Rad2Deg, 0.0f); if (smoothing == 0f) { transform.rotation = target; } else { transform.rotation = Quaternion.Slerp(transform.rotation, target, smoothing * Time.deltaTime); } }
public override void Update(PlayerController player) { // Handle Lara screaming if (player.VerticalSpeed <= -player.DeathVelocity && !hasScreamed) { player.SFX.PlayScreamSound(); hasScreamed = true; } AnimatorStateInfo animState = player.Anim.GetCurrentAnimatorStateInfo(0); float targetSpeed = UMath.GetHorizontalMag(player.RawTargetVector()); player.Anim.SetFloat("YSpeed", player.VerticalSpeed); player.Anim.SetFloat("TargetSpeed", targetSpeed); // Useful for transitioning to other movements if (player.Grounded) { // Causes recalculation of local velocity player.Velocity = player.Velocity; // Apply damage if necessary if (player.VelocityLastFrame.y < -player.DamageVelocity) { int healthToLose = (int)((Mathf.Abs(player.VelocityLastFrame.y) - player.DamageVelocity) * 100f / (player.DeathVelocity - player.DamageVelocity)); player.Stats.Health -= healthToLose; // Stops any screaming currently happening player.GetComponent <AudioSource>().Stop(); if (player.Stats.Health == 0) { player.SFX.PlayHitGroundSound(); return; // Player transitioning into death so ignore rest } } // Smooth transition to slope sliding if (player.Ground.Tag == "Slope") { player.StateMachine.GoToState <Sliding>(); return; } // Determine proper land animation trigger string landType = animState.IsName("Dive") ? "DiveLand" : (player.VelocityLastFrame.y > -player.DamageVelocity ? "Land" : "HardLand"); player.Anim.SetTrigger(landType); // Stops player moving forward on landing if (targetSpeed < 0.1f) { player.ImpulseVelocity(Vector3.down * player.Gravity); } player.StateMachine.GoToState <Locomotion>(); return; } else if (!player.Anim.GetBool("isDive")) // Other actions that be performed while not diving { if (Input.GetKeyDown(player.Inputf.action) && !player.UpperStateMachine.IsInState <UpperCombat>()) { player.StateMachine.GoToState <Grabbing>(); } else if (Input.GetKey(player.Inputf.drawWeapon) || Input.GetAxisRaw("CombatTrigger") > 0.1f) { if (player.VerticalSpeed > -player.DamageVelocity) { player.UpperStateMachine.GoToState <UpperCombat>(); } } } }
public override void Update(PlayerController player) { AnimatorStateInfo animState = player.Anim.GetCurrentAnimatorStateInfo(0); AnimatorTransitionInfo transInfo = player.Anim.GetAnimatorTransitionInfo(0); // Used to determine if forward or up stand jump float targetSpeed = UMath.GetHorizontalMag(player.RawTargetVector()); player.Anim.SetFloat("TargetSpeed", targetSpeed); bool isDive = player.Anim.GetBool("isDive"); if (!player.AutoLedgeTarget && Input.GetKey(player.Inputf.action) && !isDive) { isGrabbing = true; } // Allows player to smoothly turn round during stand jump if ((animState.IsName("Still_Compress_Forward") || animState.IsName("Compress")) && !noRotate && !hasJumped) { player.MoveGrounded(1f); player.RotateToVelocityGround(); } if (Input.GetKey(player.Inputf.crouch) && !hasJumped) { player.Anim.SetBool("isDive", true); isDive = true; } bool isRunJump = animState.IsName("RunJump") || animState.IsName("RunJumpM") || animState.IsName("Dive"); bool isStandJump = animState.IsName("StandJump") || transInfo.IsName("Still_Compress_Forward -> StandJump"); bool isJumpUp = animState.IsName("JumpUp"); if ((isRunJump || isStandJump || isJumpUp) && !hasJumped) { player.UseRootMotion = false; float zVel = isRunJump ? player.RunJumpVel : isStandJump ? player.StandJumpVel : 0.1f; float yVel = player.JumpYVel; // Snaps forward standing jumps to right direction (more responsive) if (isStandJump && !noRotate) { Vector3 targetJumpDir = player.RawTargetVector(1f, true); if (targetJumpDir.sqrMagnitude != 0f) // Stops Lara snapping to (0,0,1) { Quaternion rotationTarget = Quaternion.LookRotation(targetJumpDir, Vector3.up); player.transform.rotation = rotationTarget; } } // Checks for ledges if (player.AutoLedgeTarget && !isDive) { Vector3 autoGrabCastStart = player.transform.position + Vector3.down * 2.5f; float autoGrabMaxHeight = 2.5f + player.JumpHeight + player.GrabUpOffset; ledgesDetected = ledgeDetector.FindLedgeJump(autoGrabCastStart, player.transform.forward, 6.2f, autoGrabMaxHeight, out ledgeInfo, player); if (ledgesDetected && TryReachLedge(player, zVel, ref yVel)) { return; // Can reach ledge - ignore code left in this state } else { // Check for monkeys and poles Vector3 start = player.transform.position + Vector3.up * player.CharControl.height; Vector3 dir = isJumpUp ? Vector3.up : player.transform.forward + Vector3.up; ledgesDetected = ledgeDetector.FindAboveHead(start, dir, 4f, out ledgeInfo); if (ledgesDetected) { player.StateMachine.GoToState <AutoGrabbing>(ledgeInfo); return; } } } player.ImpulseVelocity(player.transform.forward * zVel + Vector3.up * yVel); hasJumped = true; } else if (hasJumped) { if (isGrabbing) { player.StateMachine.GoToState <Grabbing>(); return; } else { player.StateMachine.GoToState <InAir>(); return; } } }
public override void Update(PlayerController player) { // Handle Lara screaming if (player.VerticalSpeed <= -player.DeathVelocity && !screamed) { player.SFX.PlayScreamSound(); screamed = true; } AnimatorStateInfo animState = player.Anim.GetCurrentAnimatorStateInfo(0); player.Anim.SetFloat("YSpeed", player.VerticalSpeed); float targetSpeed = UMath.GetHorizontalMag(player.RawTargetVector()); player.Anim.SetFloat("TargetSpeed", targetSpeed); if (player.Grounded) { // Apply damage if necessary if (player.VelocityLastFrame.y < -player.DamageVelocity) { int healthToLose = (int)((Mathf.Abs(player.VelocityLastFrame.y) - player.DamageVelocity) * 100f / (player.DeathVelocity - player.DamageVelocity)); player.Stats.Health -= healthToLose; player.GetComponent <AudioSource>().Stop(); if (player.Stats.Health == 0) { player.SFX.PlayHitGroundSound(); } } // Smooth transition to slope sliding if (player.Ground.Tag == "Slope") { player.StateMachine.GoToState <Sliding>(); return; } // Determine proper land animation trigger string landType = animState.IsName("Dive") ? "DiveLand" : (player.VelocityLastFrame.y > -player.DamageVelocity ? "Land" : "HardLand"); player.Anim.SetTrigger(landType); // Stops player moving forward on landing if (player.RawTargetVector().magnitude < 0.1f) { player.ImpulseVelocity(Vector3.down * player.Gravity); } // Don't want player to come out of death state if (player.Stats.IsAlive()) { player.StateMachine.GoToState <Locomotion>(); } return; } else if (!player.Anim.GetBool("isDive")) { if (Input.GetKeyDown(player.Inputf.action) && !player.UpperStateMachine.IsInState <UpperCombat>()) { player.StateMachine.GoToState <Grabbing>(); } else if (Input.GetKey(player.Inputf.drawWeapon) || Input.GetAxisRaw("CombatTrigger") > 0.1f) { if (player.VerticalSpeed > -player.DamageVelocity) { player.UpperStateMachine.GoToState <UpperCombat>(); } } } }