using UnityEngine; using System.Collections; public class PlayerAttack : MonoBehaviour { [Header("--- 참조 ---")] [SerializeField] private PlayerInteraction interaction; [SerializeField] private Stats stats; [SerializeField] private PlayerAnimator pAnim; [SerializeField] private PlayerHealth playerHealth; [SerializeField] private WeaponHitBox weaponHitBox; // ⚔️ 낫에 붙은 히트박스 [Header("--- 설정 ---")] [SerializeField] private float attackCooldown = 0.4f; [SerializeField] private float fullChargeTime = 2f; [SerializeField] private float postComboDelay = 1.2f; private float _lastAttackTime, _chargeTimer; private bool _isCharging, _canAttack = true, _isAttacking = false; private int _comboCount = 0; public float ChargeProgress => Mathf.Clamp01(_chargeTimer / fullChargeTime); public bool IsCharging => _isCharging; public bool IsAttacking => _isAttacking; private void Update() { if (_isCharging) { _chargeTimer += Time.deltaTime; if (Input.GetMouseButtonDown(1)) { CancelCharging(); } } } public void PerformNormalAttack() { if (!_canAttack || (playerHealth != null && playerHealth.isHit)) return; if (interaction.CurrentWeapon == null || pAnim == null) return; if (Time.time < _lastAttackTime + attackCooldown) return; _isAttacking = true; _comboCount = (_comboCount % 3) + 1; // 1 -> 2 -> 3 순환 pAnim.TriggerAttack(); _lastAttackTime = Time.time; } public void StartWeaponCollision() { if (weaponHitBox != null) { Debug.Log("[Attack] 낫 공격 판정 ON!"); weaponHitBox.EnableHitBox(20f); } } public void StopWeaponCollision() { if (weaponHitBox != null) { Debug.Log("[Attack] 낫 공격 판정 OFF!"); weaponHitBox.DisableHitBox(); } } // ⭐ [수정 완료] 오직 3타 막타일 때만 카메라 연출을 실행합니다. public void OnAttackShake() { if (CinemachineShake.Instance == null) return; // 3번째 콤보일 때만 묵직하게 흔들어줍니다. if (_comboCount == 3) { Debug.Log("[Shake] 3타 막타 카메라 연출 실행!"); CinemachineShake.Instance.HitSlow(0.2f, 0.05f); // 히트 슬로우 CinemachineShake.Instance.CameraKick(10f); // 카메라 킥 CinemachineShake.Instance.ShakeAttack(); // 진동 } // 🚫 else 구문을 삭제하여 1, 2타 시에는 아무것도 하지 않습니다. } public void OnAttackEnd() { StopWeaponCollision(); if (_comboCount == 3) { StartCoroutine(PostComboRecovery()); } else { _isAttacking = false; } } private IEnumerator PostComboRecovery() { _canAttack = false; _isAttacking = true; yield return new WaitForSeconds(postComboDelay); _canAttack = true; _isAttacking = false; _comboCount = 0; } public void CancelCharging() { _isCharging = false; _chargeTimer = 0f; if (pAnim != null) pAnim.SetCharging(false); if (CinemachineShake.Instance != null) CinemachineShake.Instance.SetZoom(false); } public void ReleaseAttack() { if (!_isCharging || interaction.CurrentWeapon == null) return; pAnim.TriggerThrow(); pAnim.SetCharging(false); Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Plane groundPlane = new Plane(Vector3.up, transform.position); float rayDistance; Vector3 targetDirection = transform.forward; if (groundPlane.Raycast(ray, out rayDistance)) { Vector3 pointOnGround = ray.GetPoint(rayDistance); targetDirection = (pointOnGround - transform.position).normalized; targetDirection.y = 0; } if (targetDirection != Vector3.zero) transform.rotation = Quaternion.LookRotation(targetDirection); GameObject weaponObj = interaction.CurrentWeapon.gameObject; weaponObj.transform.SetParent(null); int lv = _chargeTimer >= 2f ? 3 : (_chargeTimer >= 1f ? 2 : 1); float throwForce = interaction.CurrentWeapon.Config.GetForce(lv); float currentSpread = interaction.CurrentWeapon.Config.GetSpread(lv); Vector3 finalThrowDir = Quaternion.Euler(0, Random.Range(-currentSpread, currentSpread), 0) * targetDirection; interaction.CurrentWeapon.OnThrown(finalThrowDir, throwForce, lv, stats); if (CinemachineShake.Instance != null) { CinemachineShake.Instance.HitSlow(0.15f, 0.3f); CinemachineShake.Instance.SetZoom(false); CinemachineShake.Instance.ShakeAttack(); } interaction.ClearCurrentWeapon(); stats.ResetWeight(); _isCharging = false; _chargeTimer = 0f; } public void StartCharging() { if (playerHealth != null && playerHealth.isHit) return; if (interaction.CurrentWeapon == null) return; _isCharging = true; _chargeTimer = 0f; pAnim.SetCharging(true); if (CinemachineShake.Instance != null) CinemachineShake.Instance.SetZoom(true); } private void OnDrawGizmos() { Gizmos.color = Color.red; if (TryGetComponent(out var box)) { Gizmos.matrix = transform.localToWorldMatrix; Gizmos.DrawWireCube(box.center, box.size); } } }