using System; using System.Collections.Generic; using BumpCombat.Combat; using BumpCombat.Player; using BumpCombat.Progression; using BumpCombat.Defense.Comparison; using NUnit.Framework; using UnityEngine; using Object = UnityEngine.Object; namespace BumpCombat.Tests { public sealed class Defense25DLoadoutPlayModeTests { private readonly List definitions = new(); [TearDown] public void TearDown() { foreach (ActiveArtifactDefinition definition in definitions) Object.DestroyImmediate(definition); definitions.Clear(); } [Test] public void SourceCatalogsExposeAllSixActiveEffectsAndTwentyRelics() { Assert.That(Enum.GetValues(typeof(ActiveArtifactEffect)).Length, Is.EqualTo(6)); Assert.That(Enum.GetValues(typeof(PassiveRelicId)).Length, Is.EqualTo(20)); Assert.That(PassiveRelicRules.GetAvailableRelics(Array.Empty()).Length, Is.EqualTo(20)); } [Test] public void EveryActiveEffectDispatchesAndEveryRelicCanBeAcquired() { Defense25DLoadout loadout = NewLoadout(1000f, 6, 6); List activated = new(); foreach (ActiveArtifactEffect effect in Enum.GetValues(typeof(ActiveArtifactEffect))) { ActiveArtifactDefinition definition = Definition(effect, 1f, 2f); Assert.That(loadout.TryAddArtifact(definition), Is.True, effect.ToString()); Assert.That(loadout.Select(loadout.OwnedArtifactCount - 1), Is.True); loadout.ExecuteArtifact = use => { activated.Add(use.Effect); return true; }; Assert.That(loadout.TryUse(false), Is.True, effect.ToString()); } Assert.That(activated, Is.EquivalentTo(Enum.GetValues(typeof(ActiveArtifactEffect)))); foreach (PassiveRelicId relic in Enum.GetValues(typeof(PassiveRelicId))) Assert.That(loadout.TryAcquireRelic(relic), Is.True, relic.ToString()); Assert.That(loadout.OwnedRelicCount, Is.EqualTo(20)); } [Test] public void LoadoutEnforcesArtifactColorAndCapacityRules() { Defense25DLoadout loadout = NewLoadout(100f, 3, 1); ActiveArtifactDefinition dash = Definition(ActiveArtifactEffect.Dash, 10f, 30f); ActiveArtifactDefinition cyclone = Definition(ActiveArtifactEffect.Cyclone, 10f, 30f); ActiveArtifactDefinition pulse = Definition(ActiveArtifactEffect.Pulse, 10f, 30f); Assert.That(loadout.TryAddArtifact(dash), Is.True); Assert.That(loadout.TryAddArtifact(cyclone), Is.False); Assert.That(loadout.TryAddArtifact(pulse), Is.True); Assert.That(loadout.OwnedArtifactCount, Is.EqualTo(2)); } [Test] public void ChargeReleaseUsesDefinitionCostAndFailedExecutionKeepsGauge() { Defense25DLoadout loadout = NewLoadout(80f, 3, 1); ActiveArtifactDefinition definition = Definition(ActiveArtifactEffect.Pulse, 20f, 60f, 2f); Assert.That(loadout.TryAddArtifact(definition), Is.True); loadout.Select(0); loadout.ExecuteArtifact = _ => false; Assert.That(loadout.BeginCharge(), Is.True); loadout.AdvanceCharge(1f); Assert.That(loadout.ChargeProgress, Is.EqualTo(.5f).Within(.001f)); Assert.That(loadout.ReleaseCharge(), Is.False); Assert.That(loadout.Gauge, Is.EqualTo(80f)); Assert.That(loadout.IsCharging, Is.False); loadout.ExecuteArtifact = _ => true; Assert.That(loadout.TryUse(false), Is.True); Assert.That(loadout.Gauge, Is.EqualTo(60f)); } [Test] public void RunResetClearsOwnedStateAndRestoresStartingGauge() { Defense25DLoadout loadout = NewLoadout(25f, 3, 1); Assert.That(loadout.TryAddArtifact(Definition(ActiveArtifactEffect.Dash, 10f, 30f)), Is.True); Assert.That(loadout.TryAcquireRelic(PassiveRelicId.TwinHornTalisman), Is.True); loadout.ResetRun(); Assert.That(loadout.OwnedArtifactCount, Is.Zero); Assert.That(loadout.OwnedRelicCount, Is.Zero); Assert.That(loadout.Gauge, Is.EqualTo(25f)); } [Test] public void RelicOfferPrerequisitesAndTriggerDispatchAreEnforced() { Defense25DLoadout loadout = NewLoadout(50f, 3, 1); int triggers = 0; loadout.DispatchRelicTrigger = _ => triggers++; Assert.That(loadout.TryAcquireRelic(PassiveRelicId.EmberCarrier), Is.False); Assert.That(loadout.TryAcquireRelic(PassiveRelicId.EmberWick), Is.True); Assert.That(loadout.TryAcquireRelic(PassiveRelicId.EmberCarrier), Is.True); loadout.NotifyRelicTrigger(PassiveRelicId.EmberCarrier); loadout.NotifyRelicTrigger(PassiveRelicId.BloodFang); Assert.That(triggers, Is.EqualTo(1)); } private static Defense25DLoadout NewLoadout(float startingGauge, int maxArtifacts, int maxPerColor) => new(startingGauge, 100f, maxArtifacts, maxPerColor); private ActiveArtifactDefinition Definition( ActiveArtifactEffect effect, float normalCost, float chargedCost, float chargeDuration = .8f) { ActiveArtifactDefinition definition = ScriptableObject.CreateInstance(); definition.Configure(effect.ToString(), effect.ToString(), "*", effect, DamageTag.Collision, Color.white, Color.white, normalCost, chargedCost, chargeDuration, 1f, 2f, 1f, 2f, 1f, 2f); definitions.Add(definition); return definition; } } }