Project_WL/Assets/WL/Scripts/Player/PlayerProgress.cs

67 lines
2.5 KiB
C#

using System;
using UnityEngine;
namespace WL.Player
{
/// <summary>
/// 플레이어 레벨·경험치 런타임 상태 (PD #727). 씬에 1개("PlayerProgress")를 둔다.
/// 값은 PlayerProgressSettings 에서 읽고(C45), 바뀔 때 Changed 를 발화한다 — HUD 가 구독한다.
/// 경험치는 Enemy.AnyDied(처치 1회)마다 설정의 xpPerKill 만큼 더한다 — 표기가 실제로 움직이도록 최소 연결(임시값).
/// </summary>
public class PlayerProgress : MonoBehaviour
{
[Header("설정 (ScriptableObject)")]
[SerializeField] private PlayerProgressSettings settings;
public int Level { get; private set; }
public long Xp { get; private set; }
public long XpToNext { get; private set; }
public PlayerProgressSettings Settings { get { return settings; } }
/// <summary>레벨·경험치가 바뀔 때.</summary>
public event Action Changed;
private void Awake() { ResetFromSettings(); }
private void OnEnable() { Enemy.AnyDied += OnAnyEnemyDied; }
private void OnDisable() { Enemy.AnyDied -= OnAnyEnemyDied; }
private void OnAnyEnemyDied(Enemy e)
{
if (e != null && e.IsInvincible) return; // 무적 더미 봇은 죽지 않지만 방어적으로 제외
OnEnemyKilled();
}
/// <summary>설정값으로 되돌린다(시작 시·검증용).</summary>
public void ResetFromSettings()
{
Level = settings != null ? Mathf.Max(settings.startLevel, 1) : 1;
Xp = settings != null ? Math.Max(settings.startXp, 0L) : 0L;
XpToNext = settings != null ? settings.XpToNext(Level) : 100L;
if (Changed != null) Changed();
}
/// <summary>경험치를 더하고 필요 경험치를 넘으면 레벨업한다(여러 단계 연속 가능).</summary>
public void AddXp(long amount)
{
if (amount <= 0) return;
Xp += amount;
int guard = 0;
while (Xp >= XpToNext && guard++ < 1000)
{
Xp -= XpToNext;
Level++;
XpToNext = settings != null ? settings.XpToNext(Level) : XpToNext;
}
if (Changed != null) Changed();
}
/// <summary>몬스터 처치 보상(설정 xpPerKill). 처치 이벤트 연결 시 호출한다.</summary>
public void OnEnemyKilled()
{
if (settings == null) return;
AddXp(settings.xpPerKill);
}
}
}