Files

85 lines
2.6 KiB
C#

using System;
namespace NightclubArcadia.Skills
{
/// <summary>
/// Pure check math. Exactly three modifier sources: rank, situational, state.
/// No UnityEngine types. No side effects on PlayerSkills / VariableStorage / UI.
/// </summary>
public sealed class SkillCheckSystem
{
readonly SkillDatabase _database;
readonly PlayerSkills _skills;
readonly SkillStateModifiers _state;
readonly IRollSource _rolls;
public SkillCheckSystem(
SkillDatabase database,
PlayerSkills skills,
SkillStateModifiers state,
IRollSource rolls)
{
_database = database ?? throw new ArgumentNullException(nameof(database));
_skills = skills ?? throw new ArgumentNullException(nameof(skills));
_state = state ?? throw new ArgumentNullException(nameof(state));
_rolls = rolls ?? throw new ArgumentNullException(nameof(rolls));
}
public SkillCheckResult Resolve(string skillId, int dc, int situationalMod)
{
skillId ??= string.Empty;
string displayName;
int rankMod;
if (_database.TryGet(skillId, out var def) && def != null)
{
displayName = string.IsNullOrEmpty(def.DisplayName)
? def.Id.ToUpperInvariant()
: def.DisplayName;
rankMod = _skills.GetRank(skillId);
}
else
{
displayName = skillId.ToUpperInvariant();
rankMod = 0;
}
var roll = _rolls.Roll(20);
var stateMod = _state.TotalFor(skillId);
var total = roll + rankMod + situationalMod + stateMod;
bool success;
SkillCheckDegree degree;
if (roll == 1)
{
success = false;
degree = SkillCheckDegree.CriticalFailure;
}
else if (roll == 20)
{
success = true;
degree = SkillCheckDegree.CriticalSuccess;
}
else
{
success = total >= dc;
degree = success ? SkillCheckDegree.Success : SkillCheckDegree.Failure;
}
return new SkillCheckResult(
skillId,
displayName,
roll,
rankMod,
situationalMod,
stateMod,
total,
dc,
success,
degree);
}
}
}