using System; using System.Collections.Generic; using UnityEngine; namespace Streamingle.Contents.BossRaid { [CreateAssetMenu(fileName = "BossData", menuName = "Streamingle/Contents/BossRaid/Boss Data")] public class BossData : ScriptableObject { #region Classes [Serializable] public class PhaseData { [Tooltip("이 페이즈가 시작되는 HP 비율 (0~1). 예: 0.5 = 50% 이하일 때 진입")] [Range(0f, 1f)] public float hpThreshold = 0.5f; [Tooltip("페이즈 이름 (연출 표시용)")] public string phaseName = "Phase"; [Tooltip("보스 색상 틴트 (분노 모드 등)")] public Color colorTint = Color.white; [Tooltip("데미지 배율 (보스가 더 세지는 등 연출용)")] [Min(0.1f)] public float damageMultiplier = 1f; public override string ToString() => $"{phaseName} (HP <= {hpThreshold * 100:F0}%)"; } [Serializable] public class VisualConfig { [Header("피격 플래시")] [Tooltip("피격 시 흰색 플래시 지속 시간")] [Range(0.01f, 0.5f)] public float hitFlashDuration = 0.1f; [Tooltip("피격 플래시 색상")] public Color hitFlashColor = Color.white; [Header("화면 흔들림")] [Tooltip("일반 히트 흔들림 강도")] [Range(0f, 1f)] public float normalShakeIntensity = 0.3f; [Tooltip("크리티컬 히트 흔들림 강도")] [Range(0f, 2f)] public float criticalShakeIntensity = 0.8f; [Tooltip("흔들림 지속 시간")] [Range(0.01f, 1f)] public float shakeDuration = 0.2f; [Header("히트스톱")] [Tooltip("히트스톱 지속 시간 (초)")] [Range(0f, 0.2f)] public float hitStopDuration = 0.05f; [Header("사망 연출")] [Tooltip("사망 연출 총 지속 시간")] [Range(0.5f, 5f)] public float deathDuration = 2f; } #endregion #region Fields [Header("기본 정보")] [Tooltip("보스 이름 (UI 표시용)")] public string bossName = "Boss"; [Tooltip("보스 프리팹")] public GameObject bossPrefab; [Header("스탯")] [Tooltip("최대 HP")] [Min(1)] public int maxHP = 1000; [Tooltip("기본 피격 데미지")] [Min(1)] public int baseDamage = 10; [Tooltip("데미지 랜덤 범위 (± 값)")] [Min(0)] public int damageVariance = 3; [Tooltip("크리티컬 확률 (0~1)")] [Range(0f, 1f)] public float criticalChance = 0.15f; [Tooltip("크리티컬 데미지 배율")] [Min(1f)] public float criticalMultiplier = 2f; [Header("페이즈")] [Tooltip("페이즈 목록 (hpThreshold 내림차순 권장)")] public List phases = new List { new PhaseData { hpThreshold = 1.0f, phaseName = "Phase 1", colorTint = Color.white, damageMultiplier = 1f }, new PhaseData { hpThreshold = 0.3f, phaseName = "Phase 2", colorTint = new Color(1f, 0.6f, 0.3f), damageMultiplier = 1.2f }, new PhaseData { hpThreshold = 0.2f, phaseName = "Phase 3", colorTint = new Color(1f, 0.2f, 0.2f), damageMultiplier = 1.5f }, }; [Header("비주얼")] public VisualConfig visual = new VisualConfig(); [Header("파티클 프리팹")] public GameObject hitParticlePrefab; public GameObject criticalParticlePrefab; public GameObject deathParticlePrefab; public GameObject victoryParticlePrefab; public GameObject phaseAuraParticlePrefab; #endregion #region Public Methods /// /// 현재 HP 비율에 해당하는 페이즈 인덱스를 반환합니다. /// public int GetPhaseIndex(float hpRatio) { int result = 0; for (int i = phases.Count - 1; i >= 0; i--) { if (hpRatio <= phases[i].hpThreshold) { result = i; break; } } return result; } /// /// 데미지를 계산합니다. (크리티컬 여부도 반환) /// public (int damage, bool isCritical) CalculateDamage(float phaseMultiplier = 1f) { bool isCritical = UnityEngine.Random.value < criticalChance; int base_dmg = baseDamage + UnityEngine.Random.Range(-damageVariance, damageVariance + 1); float multiplier = phaseMultiplier * (isCritical ? criticalMultiplier : 1f); int finalDamage = Mathf.Max(1, Mathf.RoundToInt(base_dmg * multiplier)); return (finalDamage, isCritical); } #endregion } }