98 lines
3.3 KiB
C#
98 lines
3.3 KiB
C#
|
|
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();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|