EerieVillage/Assets/Scripts/Progression/LevelXPTableLoader.cs

98 lines
3.3 KiB
C#
Raw Normal View History

BT12-MVP-A Phase 2-A: 경험치·레벨업 시스템 코드 + JSON 테이블 PD 직접 지시 2026-05-08 — (b) 채택 + JSON 테이블 영역 관리. 신규 영역 (8 파일): - Assets/Resources/Progression/level_xp_table.json — Lv 1~30 EXP 테이블 (balance-designer SOT) - Assets/Scripts/Progression/LevelXPTableLoader.cs — Resources.Load + JsonUtility 캐시 - Assets/Scripts/Progression/PlayerProgression.cs — Level·EXP 진행도 (BT12-Dev v1 PlayerStats와 직무 분리) - Assets/Scripts/Progression/ExperienceSystem.cs — EXP 발급 정적 게이트웨이 - Assets/Scripts/Progression/SkillCardPlaceholder.cs — placeholder ScriptableObject - Assets/Scripts/Progression/SkillCardPlaceholderPool.cs — 카드 풀·Draw3Random - Assets/Scripts/Progression/LevelUpManager.cs — 레벨업 발화·일시정지·UI placeholder (Phase 2-B 통합) 기존 파일 수정 (2 파일): - EnemyDeath.cs Execute 마지막 영역 ExperienceSystem.OnEnemyKilled 호출 - PlayerController.cs Awake PlayerProgression 자동 부착 회귀 위험: - BT5-Dev 발판/몬스터 영역 영향 X (EnemyDeath 호출 마지막·PlayerController 자동 부착) - BT7-Dev VS 순수형 영향 X (Schedule 영역 변경 X) - BT12-Dev v1 영역 충돌 X (PlayerStats 분리·신규 namespace EerieVillage.Progression) Phase 2-A 영역 검증: - 적 처치 → EXP 누적 → Lv 임계점 → Console [LevelUpManager] 영역 출력 확증 - Phase 2-B 영역 = SkillSelectionUI prefab + 5 placeholder asset + Scene 통합
2026-05-08 08:53:39 +00:00
using System.Collections.Generic;
using UnityEngine;
namespace EerieVillage.Progression
{
/// <summary>
/// JSON 영역 레벨업 EXP 테이블 로더. Resources.Load + JsonUtility 활용.
/// 정적 캐시 — 첫 호출 시점 1회 로드 (게임 영역 1회).
/// SOT: Assets/Resources/Progression/level_xp_table.json (balance-designer SOT).
/// PD 직접 지시 2026-05-08 — 코드 산식 폐기·JSON 테이블 영역 관리.
/// </summary>
public static class LevelXPTableLoader
{
[System.Serializable]
public class LevelXPEntry
{
public int level;
public int xp_to_next;
}
[System.Serializable]
public class LevelXPTable
{
public string version;
public string description;
public string fallback_formula;
public int max_level_in_table;
public LevelXPEntry[] table;
}
const string RESOURCE_PATH = "Progression/level_xp_table";
const int FALLBACK_BASE = 100;
const int FALLBACK_INCREMENT = 20;
static Dictionary<int, int> _cache;
static int _maxLevelInTable;
static int _lastTableXP;
public static void EnsureLoaded()
{
if (_cache != null) return;
_cache = new Dictionary<int, int>();
_maxLevelInTable = 0;
_lastTableXP = FALLBACK_BASE;
var ta = Resources.Load<TextAsset>(RESOURCE_PATH);
if (ta == null)
{
Debug.LogWarning($"[LevelXPTableLoader] Resources/{RESOURCE_PATH}.json 부재 — fallback 활성");
return;
}
try
{
var data = JsonUtility.FromJson<LevelXPTable>(ta.text);
if (data == null || data.table == null)
{
Debug.LogWarning("[LevelXPTableLoader] JSON 파싱 실패 — fallback 활성");
return;
}
_maxLevelInTable = data.max_level_in_table;
foreach (var entry in data.table)
{
_cache[entry.level] = entry.xp_to_next;
if (entry.level == _maxLevelInTable) _lastTableXP = entry.xp_to_next;
}
}
catch (System.Exception e)
{
Debug.LogError($"[LevelXPTableLoader] 파싱 예외 — {e.Message}");
}
}
/// <summary>
/// 지정 level → 다음 레벨 도달 EXP. 테이블 미정의 영역 = fallback (last_xp + 20 × overflow).
/// </summary>
public static int GetXPToNextLevel(int level)
{
EnsureLoaded();
if (level <= 0) return FALLBACK_BASE;
if (_cache.TryGetValue(level, out int xp)) return xp;
if (_maxLevelInTable > 0 && level > _maxLevelInTable)
{
return _lastTableXP + FALLBACK_INCREMENT * (level - _maxLevelInTable);
}
return FALLBACK_BASE + level * FALLBACK_INCREMENT;
}
/// <summary>테이블 재로드 (Editor 영역 hot-reload 용).</summary>
public static void Reload()
{
_cache = null;
EnsureLoaded();
}
}
}