using System; using UnityEngine; using UnityEngine.Serialization; public class MovePlayer : CoreBehaviour { public class XpositionWanted { public float xRef; public float xOffset; } public Rigidbody body; public SwerveXInputHandler swerveInput; public SwerveXSmoothMover swerveSmoothMove; public GameObject toMove; public GameObject umbrella; [SerializeField] [FormerlySerializedAs("turnZoneHandler")] private TurnZoneHandler _turnZoneHandler; [SerializeField] [FormerlySerializedAs("visualRotation")] private GameObject _visualRotation; private float _lastPosY; private float _speed; private Player player; private bool _isTurn; private Section _curSectionTurn; private float _curStartYTurn; private float speedRatio = 1f; private float _desiredRotVisual; private float _needWaitToMove; private int LayerGround; private float _prevSetX; private XpositionWanted _xPositionWanted; private Vector3 _targetPos; private Vector3 _oldPosition; public float smoothTimeY; public float maxSpeedY; private float _currentYSpeed; public float curSpeed { get; private set; } public bool verti { get; private set; } = true; public float speed { get { return _speed; } private set { _speed = value; player.anim.SetFloat("Speed", value); } } public void Setup(Player p) { LayerGround = LayerMask.GetMask("Ground"); player = p; SetUmbrellaParent(base.transform, (Transform t) => t.name == "mixamorig:RightHand"); ActiveUmbrella(active: false); swerveInput.trackWidth = base.CoreDef.levelWidth; swerveSmoothMove.maxSpeed = base.CoreDef.player.lateralMaxSpeed; swerveSmoothMove.smoothTime = base.CoreDef.player.lateralSmoothTime; maxSpeedY = base.CoreDef.player.heightMaxSpeed; smoothTimeY = base.CoreDef.player.heightSmoothTime; _desiredRotVisual = _visualRotation.transform.localEulerAngles.y; _lastPosY = 0f; _turnZoneHandler.onTurn += OnTurn; } private Transform SetUmbrellaParent(Transform parent, Func query) { Transform found = null; if (parent.childCount > 0) { for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (query(child)) { Vector3 localPosition = umbrella.transform.localPosition; Vector3 localEulerAngles = umbrella.transform.localEulerAngles; umbrella.transform.SetParent(child); umbrella.transform.localPosition = localPosition; umbrella.transform.localEulerAngles = localEulerAngles; return child; } found = SetUmbrellaParent(child, query); } } return found; } private void ActiveUmbrella(bool active) { umbrella.SetActive(active); player.anim.SetBool("Flying", active); } public void Go() { curSpeed = base.CoreDef.player.RunningSpeed; swerveInput.activeControl(active: true); } private void FixedUpdate() { if (player.Win) { RotateWin(); speed = 0f; return; } if (!player.Started || player.isDie) { speed = 0f; return; } speed = Vector3.Distance(_oldPosition, toMove.transform.position) / Time.deltaTime / base.CoreDef.player.RunningSpeed; _oldPosition = toMove.transform.position; if (_needWaitToMove > 0f) { _needWaitToMove -= Time.deltaTime; if (_needWaitToMove <= 0f) { swerveInput.activeControl(active: true); } return; } Vector3 pos = base.transform.position; Vector3 localPos = toMove.transform.localPosition; if (!player.winHandler.Won && !player.isDie) { UpdateRotationPlayerVisual(); if (!player.winHandler.isWinning || player.winHandler.moveActive) { swerveSmoothMove.ApplyMove(ref localPos, swerveInput.TargetWorldX, speedRatio); } else { swerveSmoothMove.ApplyMove(ref localPos, 0f, speedRatio); } UpdatePosY(ref localPos); toMove.transform.localPosition = localPos; } if (_isTurn) { UpdateTurn(pos); } UpdateRunning(ref pos); } public void ChangeSpeedRatio(float richPoorValue) { if (base.CoreDef.player.slowSpeedWhenPoor) { speedRatio = richPoorValue / (float)base.CoreDef.player.maxValueRich + 1f; } } private void UpdateRunning(ref Vector3 pos) { pos += toMove.transform.forward * (curSpeed * speedRatio * Time.deltaTime); base.transform.position = pos; } private void UpdateTurn(Vector3 pos) { float y = _curSectionTurn.GetYRotationTurnSection(pos, _curStartYTurn, this); base.transform.eulerAngles = new Vector3(base.transform.eulerAngles.x, y, base.transform.eulerAngles.z); } private void OnTurn(Section sectionTurn) { _curSectionTurn = sectionTurn; _isTurn = true; _curStartYTurn = WrapAngle(sectionTurn.transform.eulerAngles.y); } private static float WrapAngle(float angle) { angle %= 360f; if (angle > 180f) { angle -= 360f; } return angle; } public void EndTurn() { _isTurn = false; verti = !verti; } private void UpdatePosY(ref Vector3 pos) { if (Physics.Raycast(toMove.transform.position + Vector3.up, Vector3.down, out var hitInfo, base.CoreDef.player.maxDistRaycast, LayerGround)) { float y = hitInfo.point.y; if (_lastPosY - y > base.CoreDef.player.minDistSnapGround) { ActiveUmbrella(active: true); y = Mathf.SmoothDamp(toMove.transform.position.y, y, ref _currentYSpeed, smoothTimeY, maxSpeedY, Time.deltaTime); } else { ActiveUmbrella(active: false); } pos.y = y; _lastPosY = y; } } public void Revive() { _desiredRotVisual = 0f; _lastPosY = 0f; toMove.transform.localPosition = Vector3.zero; } private void UpdateRotationPlayerVisual() { if (player.winHandler.isWinning && !player.winHandler.moveActive) { _desiredRotVisual = 0f; } else if (swerveInput.deltaX > 0f) { _desiredRotVisual = base.CoreDef.player.maxRot; } else if (swerveInput.deltaX < 0f) { _desiredRotVisual = 0f - base.CoreDef.player.maxRot; } else { _desiredRotVisual = 0f; } _desiredRotVisual = Mathf.Clamp(_desiredRotVisual, 0f - base.CoreDef.player.maxRot, base.CoreDef.player.maxRot); Quaternion target = Quaternion.Euler(0f, _desiredRotVisual, 0f); _visualRotation.transform.localRotation = Quaternion.Lerp(_visualRotation.transform.localRotation, target, Time.deltaTime * base.CoreDef.player.rotSpeed); } private void RotateWin() { _visualRotation.transform.localRotation = Quaternion.RotateTowards(_visualRotation.transform.localRotation, Quaternion.Euler(0f, 180f, 0f), base.CoreDef.player.rotateWinSpeed * Time.deltaTime); } public void WaitBeforeMove(float time) { _needWaitToMove = time; swerveInput.activeControl(active: false); } private void OnDrawGizmos() { Gizmos.color = Color.magenta; Gizmos.DrawRay(toMove.transform.position + Vector3.up, Vector3.down * base.CoreDef.player.maxDistRaycast); } }