using Platformer.Mechanics; using UnityEngine; using static Platformer.Core.Simulation; namespace Platformer.Gameplay { /// /// Periodic PlayerAttack event emitter — BT7-Plan PD 지시 2026-04-24 VS 순수형 자동 발동. /// Player GameObject에 부착되어 초마다 이벤트를 Schedule. /// /// 기획 balance/01 v0.2 확정 전 임시 기본값: 0.5초 간격 · Phase 3-B 튠 대상. /// 카드·특성 효과로 주기 수정이 필요해지면 외부에서 을 직접 조작하거나 /// 를 통해 합산한다 (P13-1 공용 모듈 인터페이스 전략). /// /// /// 설계 근거: PlayerAttack.Execute는 이벤트 처리 로직, 본 컴포넌트는 발화 트리거. /// 단일 책임 원칙 + 범용성 (C11) — 타이머 컴포넌트만 교체하면 발화 방식 전환 가능. /// /// [RequireComponent(typeof(PlayerController))] public class PlayerAttackTicker : MonoBehaviour { /// /// 공격 자동 발동 주기(초). balance/01 v0.2 확정 후 튠 대상. /// [Tooltip("공격 자동 발동 주기(초). 카드·특성으로 증감 가능.")] public float attackInterval = 0.5f; /// /// 게임 시작 직후 첫 발화까지 지연(초). 플레이어 소환 애니메이션 여유. /// [Tooltip("게임 시작 직후 첫 발화까지의 지연(초). Spawn 애니메이션 여유.")] public float startupDelay = 0.3f; PlayerController player; float attackTimer; void Awake() { player = GetComponent(); attackTimer = Mathf.Max(startupDelay, 0f); } void Update() { // 컨트롤 비활성 상태(마을 이동·메뉴 등)에서는 자동 공격 중단 if (player == null || !player.controlEnabled) { return; } // 유효 간격이 0 이하이면 tick 중단 (디자이너 실수 방지) if (attackInterval <= 0f) { return; } attackTimer -= Time.deltaTime; if (attackTimer <= 0f) { attackTimer += attackInterval; var ev = Schedule(); ev.player = player; ev.direction = player.Facing; } } /// /// 카드·특성 효과가 공격 주기를 배수로 조정할 때 사용하는 편의 API. /// /// 1.0 미만이면 주기 단축(발동 가속), 1.0 초과면 둔화. public void ApplyIntervalMultiplier(float multiplier) { if (multiplier <= 0f) return; attackInterval = Mathf.Max(0.05f, attackInterval * multiplier); } } }