using System.Collections; using UnityEngine; using Yarn.Unity; namespace NightclubArcadia.Skills { /// /// Static Yarn adapter. No MonoBehaviour, no check math — translation only. /// Call sites: <<check persuasion standard>> / <<check intimidation hard -1>> /// public static class YarnSkillCommands { [YarnCommand("check")] public static IEnumerator Check(string skillId, string difficulty, int modifier = 0) { var runtime = SkillRuntime.Instance; if (runtime == null || runtime.Checks == null || runtime.DialogueRunner == null) { Debug.LogError("[YarnSkillCommands] <> called but SkillRuntime is not ready."); var fallbackRunner = runtime != null ? runtime.DialogueRunner : null; if (fallbackRunner == null) { fallbackRunner = Object.FindFirstObjectByType(); } WriteFailedResult(fallbackRunner, skillId, difficulty); yield break; } if (!DcBands.TryParse(difficulty, out var dc)) { Debug.LogError($"[YarnSkillCommands] <>: unknown difficulty; treating as Standard (11)."); dc = (int)DcBand.Standard; } if (runtime.Database == null || !runtime.Database.TryGet(skillId, out _)) { Debug.LogError($"[YarnSkillCommands] <>: no skill '{skillId}'."); } var result = runtime.Checks.Resolve(skillId, dc, modifier); WriteResult(runtime.DialogueRunner.VariableStorage, result); if (runtime.ResultView == null) { Debug.LogWarning("[YarnSkillCommands] SkillCheckResultView is not assigned; skipping roll banner."); yield break; } yield return runtime.StartCoroutine(runtime.ResultView.Show(result)); } [YarnFunction("skill_rank")] public static float SkillRank(string skillId) { var runtime = SkillRuntime.Instance; if (runtime == null || runtime.Skills == null) { return 0f; } return runtime.Skills.GetRank(skillId); } static void WriteResult(VariableStorageBehaviour storage, SkillCheckResult result) { if (storage == null) { return; } storage.SetValue("$check_result", result.Success); storage.SetValue("$check_roll", (float)result.Roll); storage.SetValue("$check_total", (float)result.Total); storage.SetValue("$check_dc", (float)result.DC); storage.SetValue("$check_modifier", (float)(result.RankMod + result.SituationalMod + result.StateMod)); storage.SetValue("$check_degree", DegreeToString(result.Degree)); storage.SetValue("$check_skill", result.SkillId ?? string.Empty); } static void WriteFailedResult(DialogueRunner runner, string skillId, string difficulty) { if (runner == null || runner.VariableStorage == null) { return; } DcBands.TryParse(difficulty, out var dc); if (dc == 0) { dc = (int)DcBand.Standard; } var storage = runner.VariableStorage; storage.SetValue("$check_result", false); storage.SetValue("$check_roll", 0f); storage.SetValue("$check_total", 0f); storage.SetValue("$check_dc", (float)dc); storage.SetValue("$check_modifier", 0f); storage.SetValue("$check_degree", "failure"); storage.SetValue("$check_skill", skillId ?? string.Empty); } static string DegreeToString(SkillCheckDegree degree) { return degree switch { SkillCheckDegree.CriticalFailure => "critical_failure", SkillCheckDegree.Failure => "failure", SkillCheckDegree.Success => "success", SkillCheckDegree.CriticalSuccess => "critical_success", _ => "failure", }; } } }