using BumpCombat.Core; using System; using BumpCombat.Constants; using BumpCombat.Player; using UnityEngine; namespace BumpCombat.Progression { [RequireComponent(typeof(PlayerStats))] public sealed class ExperienceSystem : MonoBehaviour { private PlayerStats playerStats; private float fractionalExperience; public event Action OnExperienceChanged; public event Action OnLevelGained; public event Action OnExperienceOrbPickedUp; public int Level { get; private set; } = 1; public int CurrentExperience { get; private set; } public int RequiredExperience => RequiredExperienceForLevel(Level); private void Awake() { playerStats = GetComponent(); } private void Start() { OnExperienceChanged?.Invoke(CurrentExperience, RequiredExperience, Level); } public void AddExperience(int amount) { AddExperienceInternal(amount); } public void AddMissionExperience(int amount) { AddExperienceInternal(amount); } public void CollectExperienceOrb(int amount) { AddExperienceInternal(amount); OnExperienceOrbPickedUp?.Invoke(); } private void AddExperienceInternal(int amount) { fractionalExperience += Mathf.Max(0f, playerStats.Evaluate( CharacterStat.ExperienceGain, Mathf.Max(0, amount))); int wholeExperience = Mathf.FloorToInt( fractionalExperience + 0.0001f); fractionalExperience = Mathf.Max( 0f, fractionalExperience - wholeExperience); CurrentExperience += wholeExperience; while (CurrentExperience >= RequiredExperience) { CurrentExperience -= RequiredExperience; Level++; OnLevelGained?.Invoke(Level); } OnExperienceChanged?.Invoke(CurrentExperience, RequiredExperience, Level); } public static int RequiredExperienceForLevel(int level) { LevelUpConstants tuning = GameplayConstants.Current.LevelUp; return tuning.BaseExperienceToNextLevel + (Mathf.Max(1, level) - 1) * tuning.AdditionalExperiencePerLevel; } } }