[Stats] 캐릭터 스탯 시스템 구현

- 6가지 기본 스탯 추가 (STR, DEX, INT, VIT, WIS, SPI)
- 스탯 수정자 시스템 (Flat, PercentAdd, PercentMult)
- 파생 스탯 계산 (체력/마나/대미지/회복력)
- 스킬 효과에 스탯 기반 대미지/회복량 적용
- 마나 비용 체크 및 소모 로직 추가
This commit is contained in:
2026-03-10 13:19:55 +09:00
parent 217378edde
commit 0286237b98
8 changed files with 355 additions and 19 deletions

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
namespace Colosseum.Stats
{
/// <summary>
/// 개별 스탯 클래스. 기본값과 수정자를 관리하고 최종 값을 계산.
/// </summary>
[Serializable]
public class CharacterStat
{
[UnityEngine.Tooltip("기본 값")]
[UnityEngine.SerializeField] private float baseValue = 10f;
private readonly List<StatModifier> modifiers = new List<StatModifier>();
private bool isDirty = true;
private float cachedValue;
public float BaseValue
{
get => baseValue;
set
{
baseValue = value;
isDirty = true;
}
}
public CharacterStat() { }
public CharacterStat(float baseValue)
{
this.baseValue = baseValue;
}
/// <summary>
/// 최종 스탯 값. 수정자 적용 후 계산.
/// </summary>
public float FinalValue
{
get
{
if (!isDirty) return cachedValue;
float finalValue = baseValue;
// 1. Flat 수정자 적용
for (int i = 0; i < modifiers.Count; i++)
{
if (modifiers[i].Type == StatModType.Flat)
finalValue += modifiers[i].Value;
}
// 2. PercentAdd 수정자 적용 (합산 후 곱셈)
float percentAdd = 0f;
for (int i = 0; i < modifiers.Count; i++)
{
if (modifiers[i].Type == StatModType.PercentAdd)
percentAdd += modifiers[i].Value;
}
finalValue *= (1f + percentAdd);
// 3. PercentMult 수정자 적용 (개별 곱셈)
for (int i = 0; i < modifiers.Count; i++)
{
if (modifiers[i].Type == StatModType.PercentMult)
finalValue *= modifiers[i].Value;
}
cachedValue = finalValue;
isDirty = false;
return cachedValue;
}
}
/// <summary>
/// 수정자 추가
/// </summary>
public void AddModifier(StatModifier modifier)
{
modifiers.Add(modifier);
isDirty = true;
}
/// <summary>
/// 수정자 제거
/// </summary>
public bool RemoveModifier(StatModifier modifier)
{
bool removed = modifiers.Remove(modifier);
if (removed) isDirty = true;
return removed;
}
/// <summary>
/// 특정 출처의 모든 수정자 제거
/// </summary>
public void RemoveAllModifiersFromSource(object source)
{
modifiers.RemoveAll(m => m.Source == source);
isDirty = true;
}
/// <summary>
/// 모든 수정자 제거
/// </summary>
public void ClearModifiers()
{
modifiers.Clear();
isDirty = true;
}
}
}

View File

@@ -0,0 +1,60 @@
using UnityEngine;
namespace Colosseum.Stats
{
/// <summary>
/// 캐릭터 스탯 관리 컴포넌트.
/// 6개 기본 스탯과 파생 스탯을 관리.
/// </summary>
public class CharacterStats : MonoBehaviour
{
[Header("기본 스탯")]
[SerializeField] private CharacterStat strength = new CharacterStat(10f);
[SerializeField] private CharacterStat dexterity = new CharacterStat(10f);
[SerializeField] private CharacterStat intelligence = new CharacterStat(10f);
[SerializeField] private CharacterStat vitality = new CharacterStat(10f);
[SerializeField] private CharacterStat wisdom = new CharacterStat(10f);
[SerializeField] private CharacterStat spirit = new CharacterStat(10f);
// 기본 스탯 접근자
public CharacterStat Strength => strength;
public CharacterStat Dexterity => dexterity;
public CharacterStat Intelligence => intelligence;
public CharacterStat Vitality => vitality;
public CharacterStat Wisdom => wisdom;
public CharacterStat Spirit => spirit;
// 파생 스탯 프로퍼티
// 최대 체력 = VIT * 10
public float MaxHealth => vitality.FinalValue * 10f;
// 최대 마나 = SPI * 5
public float MaxMana => spirit.FinalValue * 5f;
// 물리 대미지 = STR * 2
public float PhysicalDamage => strength.FinalValue * 2f;
// 마법 대미지 = INT * 2
public float MagicDamage => intelligence.FinalValue * 2f;
// 회복력 = WIS * 1.5
public float HealPower => wisdom.FinalValue * 1.5f;
/// <summary>
/// 스탯 타입으로 CharacterStat 가져오기
/// </summary>
public CharacterStat GetStat(StatType statType)
{
return statType switch
{
StatType.Strength => strength,
StatType.Dexterity => dexterity,
StatType.Intelligence => intelligence,
StatType.Vitality => vitality,
StatType.Wisdom => wisdom,
StatType.Spirit => spirit,
_ => null,
};
}
}
}

View File

@@ -0,0 +1,35 @@
namespace Colosseum.Stats
{
/// <summary>
/// 스탯 수정자 타입
/// </summary>
public enum StatModType
{
Flat, // 고정값 추가 (예: +10)
PercentAdd, // 퍼센트 추가 (예: +10% → 1.1배)
PercentMult, // 퍼센트 곱셈 (예: x1.5)
}
/// <summary>
/// 스탯 수정자. 버프/장비 등에 의한 스탯 변경을 관리.
/// </summary>
public readonly struct StatModifier
{
public readonly float Value;
public readonly StatModType Type;
public readonly object Source;
/// <summary>
/// 스탯 수정자 생성
/// </summary>
/// <param name="value">수정값</param>
/// <param name="type">수정 타입</param>
/// <param name="source">출처 (버프 제거용)</param>
public StatModifier(float value, StatModType type, object source = null)
{
Value = value;
Type = type;
Source = source;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Colosseum.Stats
{
/// <summary>
/// 캐릭터 기본 스탯 타입
/// </summary>
public enum StatType
{
Strength, // STR - 무기 공격 대미지
Dexterity, // DEX - 원거리 조준/대미지, 근거리 공격 속도
Intelligence, // INT - 마법 공격 대미지
Vitality, // VIT - 최대 체력
Wisdom, // WIS - 회복량
Spirit, // SPI - 최대 마나
}
}