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