feat: 보스 공통 패턴 간격 추가

- BossBehaviorRuntimeState에 패턴 종료 후 공통 텀과 준비 판정을 추가\n- UsePatternAction이 런타임 패턴 실행 결과와 공통 텀을 함께 사용하도록 정리\n- 드로그 PlayMode 테스트에 패턴 종료 후 공통 간격 검증 케이스를 추가
This commit is contained in:
2026-04-10 07:57:15 +09:00
parent 4ba6d9d9ff
commit b019acd0a3
3 changed files with 120 additions and 7 deletions

View File

@@ -46,6 +46,8 @@ namespace Colosseum.Enemy
[Header("Pattern Flow")]
[Tooltip("대형 패턴(시그니처/기동/조합) 직후 기본 패턴 최소 순환 횟수")]
[Min(0)] [SerializeField] protected int basicLoopMinCountAfterBigPattern = 2;
[Tooltip("패턴 하나가 끝난 뒤 다음 패턴을 시작하기까지의 공통 텀")]
[Min(0f)] [SerializeField] protected float commonPatternInterval = 0.35f;
[Header("시그니처 효과 설정")]
[Tooltip("시그니처 패턴 차단에 필요한 누적 피해 비율")]
@@ -93,6 +95,7 @@ namespace Colosseum.Enemy
protected int basicLoopCountSinceLastBigPattern;
protected int currentPatternPhase = 1;
protected float currentPhaseStartTime;
protected float nextPatternReadyTime;
protected BossPatternExecutionResult lastPatternExecutionResult;
protected BossPatternData lastExecutedPattern;
protected GameObject lastReviveCaster;
@@ -124,6 +127,11 @@ namespace Colosseum.Enemy
/// </summary>
public int BasicLoopCountSinceLastBigPattern => basicLoopCountSinceLastBigPattern;
/// <summary>
/// 패턴 종료 후 다음 패턴 시작까지 남은 공통 텀입니다.
/// </summary>
public float RemainingPatternInterval => Mathf.Max(0f, nextPatternReadyTime - Time.time);
/// <summary>
/// 마지막 패턴 실행 결과
/// </summary>
@@ -276,6 +284,9 @@ namespace Colosseum.Enemy
{
lastExecutedPattern = pattern;
lastPatternExecutionResult = result;
if (pattern != null && IsTerminalPatternExecutionResult(result))
StartCommonPatternInterval();
}
/// <summary>
@@ -386,6 +397,9 @@ namespace Colosseum.Enemy
if (pattern == null || pattern.Steps == null || pattern.Steps.Count == 0)
return false;
if (!IsCommonPatternIntervalReady())
return false;
if (!patternCooldownTracker.TryGetValue(pattern, out float readyTime))
return true;
@@ -401,6 +415,22 @@ namespace Colosseum.Enemy
patternCooldownTracker[pattern] = Time.time + pattern.Cooldown;
}
/// <summary>
/// 공통 패턴 텀이 끝났는지 반환합니다.
/// </summary>
public bool IsCommonPatternIntervalReady()
{
return Time.time >= nextPatternReadyTime;
}
/// <summary>
/// 현재 시점부터 공통 패턴 텀을 다시 시작합니다.
/// </summary>
public void StartCommonPatternInterval()
{
nextPatternReadyTime = Time.time + Mathf.Max(0f, commonPatternInterval);
}
protected void StopMovement()
{
if (navMeshAgent == null || !navMeshAgent.enabled)
@@ -435,6 +465,7 @@ namespace Colosseum.Enemy
{
currentPatternPhase = 1;
currentPhaseStartTime = Time.time;
nextPatternReadyTime = 0f;
lastPatternExecutionResult = BossPatternExecutionResult.None;
lastExecutedPattern = null;
lastReviveCaster = null;
@@ -443,6 +474,13 @@ namespace Colosseum.Enemy
customPhaseConditions.Clear();
}
private static bool IsTerminalPatternExecutionResult(BossPatternExecutionResult result)
{
return result == BossPatternExecutionResult.Succeeded
|| result == BossPatternExecutionResult.Failed
|| result == BossPatternExecutionResult.Cancelled;
}
public override void OnNetworkDespawn()
{
if (IsServer)