154 lines
5.0 KiB
C#

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<PhaseData> phases = new List<PhaseData>
{
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
/// <summary>
/// 현재 HP 비율에 해당하는 페이즈 인덱스를 반환합니다.
/// </summary>
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;
}
/// <summary>
/// 데미지를 계산합니다. (크리티컬 여부도 반환)
/// </summary>
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
}
}