using System; using Colosseum.AI; using Colosseum.Enemy; using Unity.Behavior; using Unity.Properties; using UnityEngine; /// /// 지정된 패턴을 실행하는 범용 액션 노드입니다. /// Pattern 필드에 BossPatternData 에셋을 직접 할당합니다. /// 타겟 해석과 등록은 Condition에서 처리되므로, 이 액션은 순수하게 패턴만 실행합니다. /// 시그니처 패턴은 내부적으로 TryStartSignaturePattern 경로를 사용합니다. /// [Serializable, GeneratePropertyBag] [NodeDescription( name: "Use Pattern By Role", story: "[Pattern] 패턴 실행", category: "Action", id: "b2c3d4e5-1111-2222-3333-555566667777")] public partial class UsePatternByRoleAction : BossPatternActionBase { [SerializeReference] [Tooltip("실행할 패턴")] public BlackboardVariable Pattern; /// /// 시그니처 패턴 실행 상태 추적 /// private bool signatureStarted; protected override Status OnStart() { BossPatternData pattern = Pattern?.Value; if (pattern == null) return Status.Failure; if (pattern.IsSignature) return StartSignaturePattern(); // 타겟 해석은 ResolveStepTarget에서 처리됨 // 여기서는 RegisterPatternUse만 호출 (근접 패턴 전용) if (pattern.IsMelee) { BossCombatBehaviorContext context = GameObject.GetComponent(); context?.RegisterPatternUse(pattern); } // base.OnStart는 TryResolvePattern → ExecuteCurrentStep 호출 return base.OnStart(); } protected override Status OnUpdate() { BossPatternData pattern = Pattern?.Value; if (pattern == null) return Status.Failure; if (pattern.IsSignature) return UpdateSignaturePattern(); return base.OnUpdate(); } protected override void OnEnd() { if (signatureStarted) { signatureStarted = false; return; } base.OnEnd(); } /// /// 시그니처 패턴 시작 /// private Status StartSignaturePattern() { BossCombatBehaviorContext context = GameObject.GetComponent(); if (context == null) return Status.Failure; GameObject target = Target != null ? Target.Value : null; signatureStarted = context.TryStartSignaturePattern(target); return signatureStarted ? Status.Running : Status.Failure; } /// /// 시그니처 패턴 업데이트 /// private Status UpdateSignaturePattern() { if (!signatureStarted) return Status.Failure; BossCombatBehaviorContext context = GameObject.GetComponent(); if (context == null) return Status.Failure; return context.IsSignaturePatternActive ? Status.Running : Status.Success; } /// /// BossPatternActionBase.TryResolvePattern 구현. /// Condition에서 이미 타겟을 해석했으므로, Target.Value를 그대로 사용합니다. /// protected override bool TryResolvePattern(out BossPatternData pattern, out GameObject target) { pattern = Pattern?.Value; target = Target != null ? Target.Value : null; if (pattern == null) return false; if (!UsePatternAction.IsPatternReady(GameObject, pattern)) return false; if (target == null) return false; return true; } protected override GameObject ResolveStepTarget(GameObject fallbackTarget) { BossPatternData pattern = Pattern?.Value; if (pattern == null) return base.ResolveStepTarget(fallbackTarget); BossCombatBehaviorContext context = GameObject.GetComponent(); if (context == null) return base.ResolveStepTarget(fallbackTarget); TargetResolveMode targetMode = pattern.TargetMode; if (targetMode == TargetResolveMode.Mobility) return context.IsValidMobilityTarget(fallbackTarget) ? fallbackTarget : context.FindMobilityTarget(); if (targetMode == TargetResolveMode.Utility) return context.IsValidUtilityTarget(fallbackTarget) ? fallbackTarget : context.FindUtilityTarget(); return base.ResolveStepTarget(fallbackTarget); } }