using Dreamteck.Splines; using PathCreation; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; public class ShipPathFollower : MonoBehaviour, ITextChangable { public float speed = 10f; public float minSpeed = 1f; public float maxSpeed = 20f; public float frictionForce = 0.1f; public float gravityForce = 1f; public float slopeRange = 60f; public float cutsceneSpeed = 50f; [SerializeField] private SplineFollower follower; public AnimationCurve speedGain; public AnimationCurve speedLoss; public float brakeSpeed = 0f; public float brakeReleaseSpeed = 0f; private float brakeTime = 0f; private float brakeForce = 0f; private float addForce = 0f; public float soundFadeLength = 0.15f; public UnityEvent OnTextChange => _OnTextChange; private UnityEvent _OnTextChange = new UnityEvent(); public UnityEvent OnSpeedChange; public UnityEvent OnSpeedPercentChange; public UnityEvent OnBoostPercentChange; public float SpeedPercent; private float _boostSpeed; [SerializeField] private float _boostBreakSpeed; private PlayerInputHandler playerInput; public bool IsBot = false; // Update is called once per frame private void Start() { playerInput = GetComponent(); } void Update() { if (_isCutsceneMovement) return; if (!IsBot && playerInput.Boost) { AddForce(1); } float dot = Vector3.Dot(this.transform.forward, Vector3.down); float dotPercent = Mathf.Lerp(-slopeRange / 90f, slopeRange / 90f, (dot + 1f) / 2f); speed -= Time.deltaTime * frictionForce * (1f - brakeForce); float speedAdd = 0f; float speedPercent = Mathf.InverseLerp(minSpeed, maxSpeed, speed); if (dotPercent > 0f) { speedAdd = gravityForce * dotPercent * speedGain.Evaluate(speedPercent) * Time.deltaTime; } else { speedAdd = gravityForce * dotPercent * speedLoss.Evaluate(1f - speedPercent) * Time.deltaTime; } speed += speedAdd * (1f - brakeForce); _boostSpeed -= Time.deltaTime * _boostBreakSpeed; _boostSpeed = Mathf.Clamp(_boostSpeed, 0, float.MaxValue); speed = Mathf.Clamp(speed, minSpeed, maxSpeed + _boostSpeed); if (addForce > 0f) { float lastAdd = addForce; addForce = Mathf.MoveTowards(addForce, 0f, Time.deltaTime * 30f); speed += lastAdd - addForce; } follower.followSpeed = speed; follower.followSpeed *= (1f - brakeForce); if (brakeTime > Time.time) brakeForce = Mathf.MoveTowards(brakeForce, 1f, Time.deltaTime * brakeSpeed); else brakeForce = Mathf.MoveTowards(brakeForce, 0f, Time.deltaTime * brakeReleaseSpeed); SpeedPercent = Mathf.Clamp01(speed / maxSpeed) * (1f - brakeForce); _OnTextChange?.Invoke((int)speed); OnSpeedChange?.Invoke(speed); OnSpeedPercentChange?.Invoke(SpeedPercent); } public void AddBrake(float time) { brakeTime = Time.time + time; } public UnityEvent OnBreak; public void FastBreak(float multiplier) { speed *= multiplier; OnBreak?.Invoke(); } public void FastBoost(float value) { _boostSpeed = value; speed += _boostSpeed; } public void RemoveBrake() { brakeTime = 0f; } public void ChangeMaxSpeed(float newSpeed) { maxSpeed = newSpeed; } public void AddForce(float amount) { addForce = amount; } private bool _isCutsceneMovement = false; public void CutsceneMovement() { _isCutsceneMovement = true; speed = cutsceneSpeed; } }