using System.Collections.Generic; using NUnit.Framework; using NightclubArcadia.Skills; using UnityEngine; namespace NightclubArcadia.Skills.Tests { public class SkillCheckSystemTests { sealed class FixedRollSource : IRollSource { readonly int _value; public FixedRollSource(int value) => _value = value; public int Roll(int sides) => _value; } SkillDatabase CreateDatabase(params (string id, string display, int rank)[] skills) { var db = ScriptableObject.CreateInstance(); var list = new List(); foreach (var (id, display, rank) in skills) { var def = ScriptableObject.CreateInstance(); def.EditorSet(id, display, SkillDomain.Presence, string.Empty, rank, Color.white); list.Add(def); } db.EditorSetSkills(list); return db; } [Test] public void Resolve_SumsModifiers_AndSucceedsWhenTotalMeetsDc() { var db = CreateDatabase(("persuasion", "Persuasion", 2)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); var result = system.Resolve("persuasion", 12, 1); Assert.AreEqual(13, result.Total); Assert.IsTrue(result.Success); Assert.AreEqual(SkillCheckDegree.Success, result.Degree); Assert.AreEqual(2, result.RankMod); Assert.AreEqual(1, result.SituationalMod); Assert.AreEqual(0, result.StateMod); } [Test] public void Resolve_NaturalOne_IsCriticalFailureEvenIfModifiersWouldPass() { var db = CreateDatabase(("persuasion", "Persuasion", 10)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(1)); var result = system.Resolve("persuasion", 5, 5); Assert.IsFalse(result.Success); Assert.AreEqual(SkillCheckDegree.CriticalFailure, result.Degree); } [Test] public void Resolve_NaturalTwenty_IsCriticalSuccessEvenIfBelowDc() { var db = CreateDatabase(("persuasion", "Persuasion", 0)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(20)); var result = system.Resolve("persuasion", 25, 0); Assert.IsTrue(result.Success); Assert.AreEqual(SkillCheckDegree.CriticalSuccess, result.Degree); } [Test] public void Resolve_ExactDc_IsSuccess() { var db = CreateDatabase(("persuasion", "Persuasion", 1)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); var result = system.Resolve("persuasion", 11, 0); Assert.AreEqual(11, result.Total); Assert.IsTrue(result.Success); } [Test] public void Resolve_AppliesNegativeAndWildcardStateModifiers() { var db = CreateDatabase(("reflexes", "Reflexes", 1)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); state.Set("drunk", "reflexes", -2); state.Set("crowd", "*", -1); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); var result = system.Resolve("reflexes", 5, 0); Assert.AreEqual(-3, result.StateMod); Assert.AreEqual(8, result.Total); } [Test] public void Resolve_UnknownSkill_DoesNotThrow_AndUsesZeroRank() { var db = CreateDatabase(("persuasion", "Persuasion", 3)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); SkillCheckResult result = default; Assert.DoesNotThrow(() => result = system.Resolve("nosuchskill", 10, 0)); Assert.AreEqual(0, result.RankMod); Assert.AreEqual("NOSUCHSKILL", result.SkillDisplayName); } [Test] public void Resolve_DoesNotMutatePlayerSkills() { var db = CreateDatabase(("persuasion", "Persuasion", 2)); var skills = new PlayerSkills(db); var before = skills.GetRank("persuasion"); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); system.Resolve("persuasion", 10, 0); Assert.AreEqual(before, skills.GetRank("persuasion")); Assert.AreEqual(1, skills.AllRanks.Count); } } }