using UnityEngine; using Unheimlich.Core; using Unheimlich.Core.Audio; using Unheimlich.Features.OctoArms; using InputManager = Unheimlich.Core.Input.InputManager; using System; using System.Collections; namespace Unheimlich.Features.Diapason { public class DiapasonEquipmentManager : MonoBehaviour { [Header("References")] [SerializeField] private OctoIkArmsImproved _armsSystem; [SerializeField] private GameObject _diapasonPrefab; [SerializeField] private int _equipmentArmIndex = 1; [Header("Detection Settings")] [SerializeField] private LayerMask _soundEmitterLayer; [SerializeField] private float _detectionRadius = 0.15f; [SerializeField] private Transform[] _detectionPoints; [Header("Visual Feedback")] [SerializeField] private GameObject _contactFeedbackPrefab; [Header("Diapason Animation")] [SerializeField] private string _vibratingBoolParam = "IsVibrating"; [SerializeField] private string _tapTriggerParam = "Tap"; [Header("Tap Settings")] [SerializeField] private AudioClip _tapSound; [SerializeField] [Range(0f, 1f)] private float _tapVolume = 1f; [SerializeField] private float _vibrationDuration = 15f; public bool IsEquipped => _isEquipped; public AudioListenable CurrentDetectedEmitter => _currentDetectedEmitter; public bool CanTap => _isEquipped && _currentDetectedEmitter != null && !_isVibrating && !_currentDetectedEmitter.HasBeenTapped; public event Action OnEmitterDetected; public event Action OnEmitterLost; private GameObject _spawnedDiapason; private bool _isEquipped = false; private AudioListenable _currentDetectedEmitter; private GameObject _contactFeedback; private bool _isVibrating = false; private AudioSource _audioSource; private Coroutine _vibrationCoroutine; private Animator _diapasonAnimator; private ParticleSystem _diapasonParticles; void Awake() { if (_armsSystem == null) { _armsSystem = GetComponent(); if (_armsSystem == null) { Debug.LogError("[DiapasonEquipment] OctoIkArmsImproved not found!"); } } _audioSource = GetComponent(); if (_audioSource == null) { _audioSource = gameObject.AddComponent(); } } void Update() { if (_isEquipped && _armsSystem.GetArmState(_equipmentArmIndex) == ArmState.Equipped) { CheckForSoundEmitters(); var fireAction = InputManager.GetFireAction(); if (fireAction != null && fireAction.WasPressedThisFrame()) { if (CanTap) TapDiapason(); } } } public void EquipDiapason() { if (_isEquipped) { Debug.LogWarning("[DiapasonEquipment] Diapason already equipped!"); return; } if (_diapasonPrefab == null) { Debug.LogError("[DiapasonEquipment] Diapason prefab not assigned!"); return; } _spawnedDiapason = Instantiate(_diapasonPrefab); _spawnedDiapason.SetActive(true); _diapasonAnimator = _spawnedDiapason.GetComponentInChildren(true); if (_diapasonAnimator == null) { Debug.LogWarning("[DiapasonEquipment] No Animator found on spawned diapason"); } else { _diapasonAnimator.enabled = false; } _diapasonParticles = _spawnedDiapason.GetComponentInChildren(true); if (_diapasonParticles == null) { Debug.LogWarning("[DiapasonEquipment] No ParticleSystem found on spawned diapason"); } _armsSystem.EquipObjectOnArm(_equipmentArmIndex, _spawnedDiapason, () => { _isEquipped = true; OnDiapasonEquipped(); }); } public void UnequipDiapason() { if (!_isEquipped) { Debug.LogWarning("[DiapasonEquipment] Diapason not equipped!"); return; } if (_vibrationCoroutine != null) { StopCoroutine(_vibrationCoroutine); _vibrationCoroutine = null; } if (_currentDetectedEmitter != null) { _currentDetectedEmitter.SetConcentrating(false); _currentDetectedEmitter.StopListening(cancelConcentrationFade: false); _currentDetectedEmitter = null; } _armsSystem.UnequipObjectFromArm(_equipmentArmIndex, () => { _isEquipped = false; _spawnedDiapason = null; OnDiapasonUnequipped(); }); } private void CheckForSoundEmitters() { if (_detectionPoints == null || _detectionPoints.Length == 0) return; AudioListenable closestEmitter = null; float closestDistance = float.MaxValue; foreach (Transform detectionPoint in _detectionPoints) { if (detectionPoint == null) continue; Collider[] hits = Physics.OverlapSphere(detectionPoint.position, _detectionRadius, _soundEmitterLayer); foreach (Collider hit in hits) { AudioListenable emitter = hit.GetComponent(); if (emitter != null) { float distance = Vector3.Distance(detectionPoint.position, hit.transform.position); if (distance < closestDistance) { closestDistance = distance; closestEmitter = emitter; } } } } if (closestEmitter != _currentDetectedEmitter) { if (_currentDetectedEmitter != null) { OnEmitterExited(_currentDetectedEmitter); } _currentDetectedEmitter = closestEmitter; if (_currentDetectedEmitter != null) { OnEmitterEntered(_currentDetectedEmitter); } } } private void OnDiapasonEquipped() { PlayerEvents.TriggerDiapasonEquip(); if (_diapasonAnimator != null) { _diapasonAnimator.enabled = true; _diapasonAnimator.SetBool(_vibratingBoolParam, false); } if (_diapasonParticles != null) { _diapasonParticles.Stop(); var emission = _diapasonParticles.emission; emission.enabled = false; } } private void OnDiapasonUnequipped() { PlayerEvents.TriggerDiapasonUnequip(); _isVibrating = false; _diapasonAnimator = null; _diapasonParticles = null; } public void TapDiapason() { if (!CanTap) { Debug.LogWarning("[DiapasonEquipment] Cannot tap: not equipped, no contact, or already tapped"); return; } TapAnimationSettings tapSettings = null; if (_spawnedDiapason != null) { EquippableTapSettings equippable = _spawnedDiapason.GetComponent(); if (equippable != null) { tapSettings = equippable.TapSettings; } } ArmEquipment equipment = _armsSystem.GetArmEquipment(_equipmentArmIndex); if (equipment != null && tapSettings != null) { equipment.PlayTapAnimation(tapSettings); equipment.StartShake(tapSettings); } if (_tapSound != null && _audioSource != null) { _audioSource.PlayOneShot(_tapSound, _tapVolume); } if (_diapasonAnimator != null) { _diapasonAnimator.SetTrigger(_tapTriggerParam); _diapasonAnimator.SetBool(_vibratingBoolParam, true); } if (_diapasonParticles != null) { var emission = _diapasonParticles.emission; emission.enabled = true; _diapasonParticles.Play(); } _isVibrating = true; if (_currentDetectedEmitter != null) { _currentDetectedEmitter.StartListening(transform.position); } PlayerEvents.TriggerDiapasonTap(); if (_vibrationCoroutine != null) StopCoroutine(_vibrationCoroutine); _vibrationCoroutine = StartCoroutine(StopVibrationAfterDuration()); } private IEnumerator StopVibrationAfterDuration() { yield return new WaitForSeconds(_vibrationDuration); if (_diapasonAnimator != null) { _diapasonAnimator.SetBool(_vibratingBoolParam, false); } if (_diapasonParticles != null) { _diapasonParticles.Stop(); var emission = _diapasonParticles.emission; emission.enabled = false; } if (_currentDetectedEmitter != null) { _currentDetectedEmitter.StopListening(); } ArmEquipment equipment = _armsSystem.GetArmEquipment(_equipmentArmIndex); if (equipment != null) { equipment.StopShake(); } _isVibrating = false; _vibrationCoroutine = null; } private void OnEmitterEntered(AudioListenable emitter) { emitter.SetConcentrating(true); if (_contactFeedbackPrefab != null && _contactFeedback == null) { _contactFeedback = Instantiate(_contactFeedbackPrefab, emitter.transform); _contactFeedback.transform.localPosition = Vector3.zero; } OnEmitterDetected?.Invoke(emitter); } private void OnEmitterExited(AudioListenable emitter) { emitter.SetConcentrating(false); if (!emitter.HasBeenTapped) { emitter.StopListening(); } if (_contactFeedback != null) { Destroy(_contactFeedback); _contactFeedback = null; } if (_diapasonAnimator != null) { _diapasonAnimator.SetBool(_vibratingBoolParam, false); } if (_diapasonParticles != null) { _diapasonParticles.Stop(); var emission = _diapasonParticles.emission; emission.enabled = false; } _isVibrating = false; OnEmitterLost?.Invoke(emitter); } void OnDrawGizmosSelected() { if (_detectionPoints == null || !_isEquipped) return; Gizmos.color = Color.yellow; foreach (Transform detectionPoint in _detectionPoints) { if (detectionPoint != null) { Gizmos.DrawWireSphere(detectionPoint.position, _detectionRadius); } } } } }