using BumpCombat.Core; using System.Collections.Generic; using System.Reflection; using BumpCombat.Player; using BumpCombat.Progression; using NUnit.Framework; using UnityEngine; namespace BumpCombat.Tests { public sealed class ExperienceSystemTests { [TestCase(1, 10)] [TestCase(2, 15)] [TestCase(3, 20)] [TestCase(10, 55)] public void RequiredExperienceForLevel_UsesWorkOrderFormula(int level, int expected) { Assert.That(ExperienceSystem.RequiredExperienceForLevel(level), Is.EqualTo(expected)); } [Test] public void AddExperience_UsesPlayerStatsExperienceGain() { GameObject owner = new("ExperienceSystem Tests"); try { PlayerStats stats = owner.AddComponent(); ExperienceSystem experience = owner.AddComponent(); typeof(ExperienceSystem) .GetMethod( "Awake", BindingFlags.Instance | BindingFlags.NonPublic) ?.Invoke(experience, null); stats.AddModifier(new StatModifier( "experience-increased", CharacterStat.ExperienceGain, ModifierOperation.Increased, 0.1f)); int levelEvents = 0; int experienceEvents = 0; experience.OnLevelGained += _ => levelEvents++; experience.OnExperienceChanged += (_, _, _) => experienceEvents++; experience.AddExperience(10); Assert.That(experience.Level, Is.EqualTo(2)); Assert.That(experience.CurrentExperience, Is.EqualTo(1)); Assert.That(levelEvents, Is.EqualTo(1)); Assert.That(experienceEvents, Is.EqualTo(1)); } finally { Object.DestroyImmediate(owner); } } [Test] public void ExperienceProgress_AddEvaluatedCarriesFractionsAcrossMultipleLevels() { ExperienceProgress progress = new(); List gainedLevels = new(); List<(int Current, int Required, int Level)> changes = new(); progress.LevelGained += gainedLevels.Add; progress.ExperienceChanged += (current, required, level) => changes.Add((current, required, level)); progress.Reset(); progress.AddEvaluated(0.6f); progress.AddEvaluated(0.6f); Assert.That(progress.Level, Is.EqualTo(1)); Assert.That(progress.CurrentExperience, Is.EqualTo(1)); Assert.That(gainedLevels, Is.Empty); progress.AddEvaluated( ExperienceSystem.RequiredExperienceForLevel(1) + ExperienceSystem.RequiredExperienceForLevel(2) + 1.5f); Assert.That(progress.Level, Is.EqualTo(3)); Assert.That(progress.CurrentExperience, Is.EqualTo(2)); Assert.That(progress.RequiredExperience, Is.EqualTo(ExperienceSystem.RequiredExperienceForLevel(3))); Assert.That(gainedLevels, Is.EqualTo(new[] { 2, 3 })); Assert.That(changes.Count, Is.EqualTo(3)); Assert.That(changes[^1], Is.EqualTo((2, ExperienceSystem.RequiredExperienceForLevel(3), 3))); } [Test] public void ExperienceProgress_ResetClearsFractionalExperience() { ExperienceProgress progress = new(); progress.AddEvaluated(0.6f); progress.Reset(); progress.AddEvaluated(0.6f); Assert.That(progress.Level, Is.EqualTo(1)); Assert.That(progress.CurrentExperience, Is.EqualTo(0)); } } }