private void ResetPlayer()
    {
        _canLaunchGrapple = true;
        _robotMesh.SetActive(true);
        _grappleTarget.transform.parent   = _grappleSlot.transform;
        _grappleTarget.transform.position = _grappleSlot.transform.position;
        _grappleMeshFollower.GrappleReset();
        _armLine.enabled = false;
        if (_currentCheckpoint == null)
        {
            //_velocity = new Vector3(0f, 20f, 0f);
            _velocity          = Vector3.zero;
            _playerMovement    = false;
            transform.position = Vector3.zero;
        }
        else
        {
            _velocity          = Vector3.zero;
            _playerMovement    = false;
            transform.position = new Vector3(_currentCheckpoint.transform.position.x, _currentCheckpoint.transform.position.y - 5f, 0f);
        }
        _currentGrappleState = _grappleStates._idle;

        //Reset dem Screws
        ScrewController[] screws = GameObject.FindObjectsOfType <ScrewController>();
        foreach (ScrewController screw in screws)
        {
            screw.ResetScrewCompletely();
        }
    }
    public void AttachGrapple(Vector3 attachPoint)
    {
        _attachPoint = attachPoint;
        if (_currentGrappleState == _grappleStates._shooting)
        {
            _grappleTarget.transform.position = _attachPoint;
            Vector3 dir = (transform.position - _attachPoint).normalized;
            _radius = Vector3.Distance(transform.position, _attachPoint);
            _angle  = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;

            _currentRotationSpeed = _velocity.magnitude;

            //get angle from attach point
            float incomingAngle = Vector3.SignedAngle((attachPoint - transform.position).normalized, _velocity.normalized, Vector3.forward);

            if (Mathf.Sign(incomingAngle) > 0)
            {
                _rotationDirection = -1;
            }
            else
            {
                _rotationDirection = 1;
            }

            if (transform.position.x > _attachPoint.x)
            {
                _lookDir = -1;
            }
            else
            {
                _lookDir = 1;
            }
            _currentGrappleState = _grappleStates._attached;
        }
    }
    private void Start()
    {
        _inputManager        = GetComponent <PlayerInputManager>();
        _currentGrappleState = _grappleStates._idle;
        _armLine.enabled     = false;

        _playerMovement = false;
    }
 public void RetractGrapple()
 {
     _grappleTarget.transform.position = Vector3.MoveTowards(_grappleTarget.transform.position, _grappleSlot.transform.position, _grappleSpeed * Time.deltaTime);
     if (Vector3.Distance(_grappleTarget.transform.position, _grappleSlot.transform.position) < 0.5f)
     {
         _armLine.enabled = false;
         _grappleMeshFollower.GrappleEnd();
         _grappleTarget.transform.parent   = _grappleSlot.transform;
         _grappleTarget.transform.position = _grappleSlot.transform.position;
         _currentGrappleState = _grappleStates._idle;
     }
 }
    private void ShootGrapple()
    {
        float distanceFromPlayer = Vector3.Distance(transform.position, _grappleTarget.transform.position);
        float distanceToTarget   = Vector3.Distance(_grappleTarget.transform.position, _targetPosition);

        if (distanceFromPlayer < _maxGrappleDistance && distanceToTarget > 0.1f)
        {
            _grappleTarget.transform.position = Vector3.MoveTowards(_grappleTarget.transform.position, _targetPosition, _grappleSpeed * Time.deltaTime);
        }
        else
        {
            _currentGrappleState = _grappleStates._retracting;
        }
    }
    private void Update()
    {
        //poll input
        _hDir = _inputManager.GetHorizontal();
        bool grapple         = _inputManager.GetGrapple();
        bool grappleReleased = _inputManager.GrappleReleased();

        if (grappleReleased)
        {
            _canLaunchGrapple = true;
        }

        if (Mathf.Abs(_hDir) > 0f)
        {
            _lookDir = Mathf.Sign(_hDir);
        }

        switch (_currentGrappleState)
        {
        case _grappleStates._idle:
            AirMovement();
            LookRotationFree();

            if (_canLaunchGrapple && grapple)
            {
                if (!_playerMovement)
                {
                    _playerMovement = true;
                }

                _grappleMeshFollower.GrappleStart();
                _grappleTarget.transform.parent = _playerRoot;
                _armLine.enabled  = true;
                _canLaunchGrapple = false;
                Vector3 mousePosition = Input.mousePosition;
                mousePosition.z = -Camera.main.transform.position.z;
                Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(mousePosition);
                _targetPosition      = mouseWorldPosition;
                _currentGrappleState = _grappleStates._shooting;
                FindTarget();
            }
            break;

        case _grappleStates._shooting:
            AirMovement();
            LookRotationFree();
            ShootGrapple();

            if (!grapple)
            {
                _currentGrappleState = _grappleStates._retracting;
            }
            break;

        case _grappleStates._retracting:
            AirMovement();
            LookRotationFree();
            RetractGrapple();
            break;

        case _grappleStates._attached:
            GrappleMovement();
            LookRotationGrapple();

            if (!grapple)
            {
                Vector3 dir = (transform.position - _attachPoint).normalized;
                if (_rotationDirection > 0f)
                {
                    _velocity = new Vector3(-dir.y, dir.x, 0f).normalized *_currentRotationSpeed;
                }
                else
                {
                    _velocity = new Vector3(dir.y, -dir.x, 0f).normalized *_currentRotationSpeed;
                }
                _currentGrappleState = _grappleStates._retracting;
            }
            break;

        default:
            break;
        }

        _armLine.SetPosition(0, _visualGrappleSlot.transform.position);
        _armLine.SetPosition(1, _grappleTarget.transform.position);
    }
 public void ReleaseGrapple()
 {
     _currentGrappleState = _grappleStates._retracting;
 }