using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Serialization; using Random = UnityEngine.Random; public class PldDogController : EnemyController { // ---- // 팔라딘 독 고유 액션 private static readonly int WindUp = Animator.StringToHash("WindUp"); private static readonly int Slash = Animator.StringToHash("Slash"); private static readonly int BoomShot = Animator.StringToHash("BoomShot"); [Header("공격 패턴 관련")] [SerializeField] private float patternInterval = 3f; [SerializeField] private float meleeRange = 2f; [SerializeField] private float bombTriggerDelay = 1.5f; [Header("폭탄 패턴 설정")] [SerializeField] private int bombCount = 1; [SerializeField] private Vector3 bombScale = new Vector3(5f, 5f, 5f); [Header("각종 데미지 이펙트 세트")] [SerializeField] private GameObject chariotSlashWarning; [SerializeField] private GameObject chariotSlash; [SerializeField] private GameObject boomExplosion; [Space(10)] [SerializeField] private GameObject verticalWarning; [SerializeField] private GameObject verticalSlash; [Space(10)] [SerializeField] private GameObject horizontalWarning; [SerializeField] private GameObject horizontalSlash; // SFX [Space(10)] [Header("SFX")] [SerializeField] private AudioClip slashSound; [SerializeField] private AudioClip boomSound; private float _patternTimer = 0f; private int _lastPatternIndex = -1; private bool _isPatternRunning = false; private bool _isFirstAttack = true; private List _patternActions; protected override void Awake() { base.Awake(); _patternActions = new List { ChariotSlashPattern, VerticalSlashPattern, HorizontalSlashPattern }; } public override void BattleSequence() { _patternTimer += Time.deltaTime; if (_isPatternRunning) return; float distanceToPlayer = Vector3.Distance(transform.position, TraceTargetTransform.position); if (distanceToPlayer <= meleeRange) // 근접 범위 { if (!Agent.isStopped) Agent.isStopped = true; if (!_isPatternRunning && (_isFirstAttack || _patternTimer >= patternInterval)) { ExecutePattern(); _isFirstAttack = false; } } else { if (Agent.isStopped) Agent.isStopped = false; Agent.SetDestination(TraceTargetTransform.position); if (!_isPatternRunning && _patternTimer >= patternInterval) { Debug.Log("## 폭탄 던질 조건 만족"); BombThrowPattern(); } } } private void ExecutePattern() { _isPatternRunning = true; Agent.isStopped = true; IsMeleeCombat = true; var available = Enumerable .Range(0, _patternActions.Count) .Where(i => i != _lastPatternIndex) .ToList(); int nextIndex = available[Random.Range(0, available.Count)]; _patternActions[nextIndex]?.Invoke(); _lastPatternIndex = nextIndex; } // 순환 패턴과 별개로 동작하는 특수 패턴 private void BombThrowPattern() { Debug.Log("BombThrowPattern: 보스가 폭탄을 던집니다."); SetAnimation(BoomShot); SoundManager.Instance.PlaySFX(boomSound); _isPatternRunning = true; Agent.isStopped = true; for (int i = 0; i < bombCount; i++) { Vector3 targetPos = TraceTargetTransform.position; targetPos.y += 0.1f; // 지면에 맞춤 var warning = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity); warning.transform.localScale = bombScale; var aoe = warning.GetComponent(); var effectData = new DamageEffectData { damage = (int)attackPower, radius = bombScale.x, delay = bombTriggerDelay, targetLayer = TargetLayerMask, explosionEffectPrefab = boomExplosion }; aoe.SetEffect(effectData, null, PatternClear); } } private void ChariotSlashPattern() { Debug.Log("ChariotSlashPattern: 보스가 차지 슬래시를 사용합니다."); WindUpAnimation(); var warning = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity) .GetComponent(); var effectData = new DamageEffectData { damage = (int)attackPower, radius = 7.5f, delay = 2.5f, targetLayer = TargetLayerMask, explosionEffectPrefab = chariotSlash }; warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); } private void VerticalSlashPattern() { Debug.Log("VerticalSlashPattern: 보스가 수직 슬래시를 사용합니다."); WindUpAnimation(); var warning = Instantiate(verticalWarning, transform.position, transform.rotation) .GetComponent(); var effectData = new DamageEffectData { damage = (int)attackPower, radius = 5f, delay = 2f, targetLayer = TargetLayerMask, explosionEffectPrefab = verticalSlash }; warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); } private void HorizontalSlashPattern() { Debug.Log("HorizontalSlashPattern: 보스가 횡적 슬래시를 사용합니다."); WindUpAnimation(); var warning = Instantiate(horizontalWarning, transform.position, transform.rotation) .GetComponent(); var effectData = new DamageEffectData { damage = (int)attackPower, radius = 15f, delay = 2f, targetLayer = TargetLayerMask, explosionEffectPrefab = horizontalSlash }; warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); } private void WindUpAnimation() { SetAnimation(WindUp); } private void SlashAnimationPlay() { SetAnimation(Slash); SoundManager.Instance.PlaySFX(slashSound); } private void PatternClear() { _isPatternRunning = false; IsMeleeCombat = false; _patternTimer = 0f; Agent.isStopped = false; } }