- 드로그 BT를 페이즈 전환, 부활 트리거, 가중치 근접 패턴 중심으로 재구성 - 땅 울리기 및 콤보-기본기1_3 패턴/스킬/이펙트를 추가하고 기존 평타 파생 자산을 정리 - 드로그 행동 검증용 PlayMode/Editor 테스트와 관련 런타임 상태 추적을 추가
116 lines
3.6 KiB
C#
116 lines
3.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
using Colosseum.AI.BehaviorActions.Conditions;
|
|
|
|
namespace Colosseum.AI
|
|
{
|
|
/// <summary>
|
|
/// 가중치 기반 패턴 선택 후보를 표현합니다.
|
|
/// </summary>
|
|
public readonly struct WeightedPatternCandidate
|
|
{
|
|
public WeightedPatternCandidate(BossPatternData pattern, float weight)
|
|
{
|
|
Pattern = pattern;
|
|
Weight = weight;
|
|
}
|
|
|
|
public BossPatternData Pattern { get; }
|
|
|
|
public float Weight { get; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 준비된 패턴 후보 중 하나를 가중치 기반으로 선택합니다.
|
|
/// </summary>
|
|
public static class WeightedPatternSelector
|
|
{
|
|
public static bool HasAnyReadyPattern(GameObject owner, IReadOnlyList<WeightedPatternCandidate> candidates)
|
|
{
|
|
if (owner == null || candidates == null)
|
|
return false;
|
|
|
|
for (int i = 0; i < candidates.Count; i++)
|
|
{
|
|
WeightedPatternCandidate candidate = candidates[i];
|
|
if (candidate.Pattern == null || candidate.Weight <= 0f)
|
|
continue;
|
|
|
|
if (PatternReadyHelper.IsPatternReady(owner, candidate.Pattern))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool TrySelectReadyPattern(GameObject owner, IReadOnlyList<WeightedPatternCandidate> candidates, out BossPatternData selectedPattern)
|
|
{
|
|
if (owner == null)
|
|
{
|
|
selectedPattern = null;
|
|
return false;
|
|
}
|
|
|
|
return TrySelectPattern(
|
|
candidates,
|
|
pattern => PatternReadyHelper.IsPatternReady(owner, pattern),
|
|
UnityEngine.Random.value,
|
|
out selectedPattern);
|
|
}
|
|
|
|
public static bool TrySelectPattern(
|
|
IReadOnlyList<WeightedPatternCandidate> candidates,
|
|
Predicate<BossPatternData> isPatternReady,
|
|
float normalizedRoll,
|
|
out BossPatternData selectedPattern)
|
|
{
|
|
selectedPattern = null;
|
|
|
|
if (candidates == null || isPatternReady == null)
|
|
return false;
|
|
|
|
List<WeightedPatternCandidate> readyCandidates = new List<WeightedPatternCandidate>(candidates.Count);
|
|
float totalWeight = 0f;
|
|
|
|
for (int i = 0; i < candidates.Count; i++)
|
|
{
|
|
WeightedPatternCandidate candidate = candidates[i];
|
|
if (candidate.Pattern == null || candidate.Weight <= 0f)
|
|
continue;
|
|
|
|
if (!isPatternReady(candidate.Pattern))
|
|
continue;
|
|
|
|
readyCandidates.Add(candidate);
|
|
totalWeight += candidate.Weight;
|
|
}
|
|
|
|
if (readyCandidates.Count == 0 || totalWeight <= 0f)
|
|
return false;
|
|
|
|
float clampedRoll = Mathf.Clamp01(normalizedRoll);
|
|
float targetWeight = clampedRoll >= 1f
|
|
? totalWeight
|
|
: totalWeight * clampedRoll;
|
|
float cumulativeWeight = 0f;
|
|
|
|
for (int i = 0; i < readyCandidates.Count; i++)
|
|
{
|
|
WeightedPatternCandidate candidate = readyCandidates[i];
|
|
cumulativeWeight += candidate.Weight;
|
|
|
|
if (targetWeight < cumulativeWeight || i == readyCandidates.Count - 1)
|
|
{
|
|
selectedPattern = candidate.Pattern;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|