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;
pAnim.TriggerAttack();
_lastAttackTime = Time.time;
}
// ⭐ [수정] 휘두를 때 데미지를 실어서 판정을 켭니다.
public void StartWeaponCollision()
{
if (weaponHitBox != null)
{
Debug.Log("[Attack] 낫 공격 판정 ON!");
// stats에 설정된 공격력을 가져와서 전달하면 더 좋습니다.
weaponHitBox.EnableHitBox(20f);
}
}
// ⭐ [수정] 휘두르기가 끝나면 확실하게 판정을 끕니다.
public void StopWeaponCollision()
{
if (weaponHitBox != null)
{
Debug.Log("[Attack] 낫 공격 판정 OFF!");
weaponHitBox.DisableHitBox();
}
}
public void OnAttackShake()
{
if (CinemachineShake.Instance == null) return;
if (_comboCount == 3)
{
CinemachineShake.Instance.HitSlow(0.2f, 0.05f);
CinemachineShake.Instance.CameraKick(10f);
CinemachineShake.Instance.ShakeAttack();
}
else
{
CinemachineShake.Instance.HitSlow(0.1f, 0.2f);
CinemachineShake.Instance.ShakeAttack();
}
}
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);
}
}
}