using System; using LuxWater; using UFS2.Gameplay; using UltimateWater; using UnityEngine; using UnityEngine.AzureSky; using UnityEngine.Rendering.PostProcessing; public class SmoothFollowUnderwater : MonoBehaviour { public enum ViewType { FloatView = 0, BaitView = 1, Null = 2 } private static ViewType LastViewType = ViewType.Null; [SerializeField] private ViewType viewType = ViewType.BaitView; [SerializeField] public Transform target; [HideInInspector] public FRod currentRod; private static float currentDistance = 3f; [SerializeField] [Tooltip("The height we want the camera to be above the target")] private float height = 5f; [SerializeField] private float orgHeight = 0.5f; [SerializeField] private float rotationDamping; [SerializeField] private float heightDamping; private float currentFieldOfView; public float startZoom = 1f; public float startZoomFloat = 1f; public float minZoom; public float maxZoom = 10f; public float minZoomFloat; public float maxZoomFloat = 10f; private float speedZoom; [SerializeField] private Camera mCamera; private static float rotation = 0f; private LuxWater_WaterVolume waterUnderWaterVolume; private WaterCamera uwsWaterCamera; private float mouseSensitivity = 10.5f; private AudioSource ownAudio; private AudioSource[] audios; private bool isCollide; [SerializeField] private LayerMask underwaterLayersMask; [SerializeField] private LayerMask topwaterLayersMask; [SerializeField] private LayerMask collisionMask; [SerializeField] private float rayDistanceFromGround = 0.05f; [SerializeField] private float heightFromWater = -0.05f; [SerializeField] private Transform _CameraTransform; [SerializeField] private Transform _CameraRoot; private AzureFogScattering fog; private RaycastHit rayHit; private static Vector3 _cameraLastLocalPos; private static Quaternion _cameraLastLocalRot; private static Quaternion _rootLastLocalRot; private int collideCount; public static event Action OnCameraTransformUpdate; public static event Action OnExitFromCamera; public static event Action OnEnterCamera; public static event Action OnBaitViewChange; public static event Action OnFloatViewChange; private void Start() { ownAudio = GetComponentInChildren(); mCamera = Camera.main; EnableDisableAllAudioOnScene(val: false); SmoothFollowUnderwater.OnBaitViewChange?.Invoke(); SmoothFollowUnderwater.OnEnterCamera?.Invoke(); PostProcessLayer component = mCamera.GetComponent(); if ((bool)component) { component.antialiasingMode = (PostProcessLayer.Antialiasing)Singleton.Instance.SettingsData.AntiAliasingModeIndex; } mouseSensitivity = Singleton.Instance.SettingsData.MouseSensitivityValue; if (LastViewType == ViewType.Null) { viewType = ViewType.BaitView; } LastViewType = viewType; UpdateUnderwaterVolume(); SetStartPosition(); } private void UpdateUnderwaterVolume() { ownAudio.volume = Singleton.Instance.SettingsData.UnderwaterVolume; } private void OnApplicationPause(bool pauseStatus) { if (pauseStatus) { UpdateUnderwaterVolume(); } } private void Update() { ControllerHandler(); } private void LateUpdate() { if (!(target == null)) { base.transform.position = target.position; _CameraRoot.transform.localRotation = Quaternion.Euler(0f, rotation, 0f); SmoothFollowUnderwater.OnCameraTransformUpdate?.Invoke(_CameraTransform); GameWaterSystem.FindWaterLevelAtLocation(base.transform.position, out var waterLevel); Vector3 dir = target.position - _CameraTransform.position; RaycastHandler(dir); float b = (isCollide ? rayHit.distance : currentDistance); currentDistance = Mathf.Lerp(_CameraTransform.localPosition.z, b, Time.deltaTime); float value = target.position.y + height; value = Mathf.Clamp(value, float.NegativeInfinity, heightFromWater + waterLevel); if (viewType == ViewType.FloatView && (bool)currentRod.currentFloat) { value = height + orgHeight + waterLevel; } if (viewType == ViewType.FloatView && (bool)currentRod.currentLure && currentRod.currentLure.waterDisplacement.moveCharacteristic == FWaterDisplacement.MoveCharacteristic.TopWater) { value = height + orgHeight + waterLevel; } _CameraTransform.localPosition = new Vector3(0f, value, currentDistance); _CameraTransform.position = new Vector3(_CameraTransform.position.x, value, _CameraTransform.position.z); if (target.position.y > _CameraTransform.position.y) { _CameraTransform.LookAt(new Vector3(target.position.x, _CameraTransform.position.y, target.position.z)); } else { _CameraTransform.LookAt(target); } SoundEnableHandler(); } } private void SetStartPosition() { _CameraTransform.localPosition = _cameraLastLocalPos; _CameraTransform.localRotation = _cameraLastLocalRot; _CameraRoot.localRotation = _cameraLastLocalRot; } private void OnDestroy() { if ((bool)waterUnderWaterVolume) { waterUnderWaterVolume.enabled = false; } EnableDisableAllAudioOnScene(val: true); _cameraLastLocalPos = _CameraTransform.localPosition; _cameraLastLocalRot = _CameraTransform.localRotation; _rootLastLocalRot = _CameraRoot.localRotation; SmoothFollowUnderwater.OnExitFromCamera?.Invoke(); } private void RaycastHandler(Vector3 dir) { dir = (_CameraTransform.position - target.position).normalized; bool flag = Physics.SphereCast(new Ray(target.position, dir.normalized), maxDistance: currentDistance + 0.05f, radius: 0.1f, hitInfo: out rayHit, layerMask: collisionMask); isCollide = flag; } private void ControllerHandler() { _ = (bool)FishEntity.CurrentFishInFight; if (InputManager.isUnderwaterCameraFloatZoom) { if ((bool)currentRod.currentFloat) { viewType = ((viewType != ViewType.BaitView) ? ViewType.BaitView : ViewType.FloatView); } if ((bool)currentRod.currentLure) { if (currentRod.currentLure.waterDisplacement.moveCharacteristic == FWaterDisplacement.MoveCharacteristic.TopWater) { viewType = ((viewType != ViewType.BaitView) ? ViewType.BaitView : ViewType.FloatView); } else { viewType = ViewType.BaitView; } } } switch (viewType) { case ViewType.FloatView: target = (currentRod.currentFloat ? currentRod.currentFloat.transform : target); SmoothFollowUnderwater.OnFloatViewChange?.Invoke(); break; case ViewType.BaitView: target = (currentRod.currentBait ? currentRod.currentBait.transform : target); SmoothFollowUnderwater.OnBaitViewChange?.Invoke(); break; } if (target == null) { target = currentRod.LureHookWaterDisplacement.transform; } rotation += Mathf.Clamp(GameManager.Instance.player.GetAxis("cameraHorizontal") * mouseSensitivity * Time.deltaTime + GameManager.Instance.player.GetAxis("cameraHorizontalGamepad") * 50f * Time.deltaTime, -17.5f, 17.5f); if (isCollide) { return; } float num = Time.deltaTime * 120f; if (InputManager.isUnderwaterCameraZoomDown) { currentDistance = Mathf.MoveTowards(currentDistance, maxZoom, Time.deltaTime * speedZoom); if (currentDistance != maxZoom) { speedZoom += num; } } else if (InputManager.isUnderwaterCameraZoomUp) { currentDistance = Mathf.MoveTowards(currentDistance, minZoom, Time.deltaTime * speedZoom); if (currentDistance != minZoom) { speedZoom += num; } } else { speedZoom = 0f; } } private void SoundEnableHandler() { if (!ownAudio.enabled && GameWaterSystem.IsPositionUnderWater(_CameraTransform.position)) { Debug.Log("Wylacz dzwieki otoczenia"); EnableDisableAllAudioOnScene(val: false); ownAudio.enabled = true; } else if (ownAudio.enabled && !GameWaterSystem.IsPositionUnderWater(_CameraTransform.position)) { Debug.Log("Wlacz dzwieki otoczenia"); EnableDisableAllAudioOnScene(val: true); ownAudio.enabled = false; } } private void EnableDisableAllAudioOnScene(bool val) { audios = UnityEngine.Object.FindObjectsOfType(); for (int i = 0; i < audios.Length; i++) { if (ownAudio != audios[i]) { audios[i].mute = !val; } } } }