Scenario conditions in dialogs: option if= hides choices, when moved here from stat checks; command schemas
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dde5262aa0
commit
68ed11cadc
14 files changed
+542
-3
No files matched your search
@@ -0,0 +1,43 @@
|
||||
namespace Cthangover.Mods.Dialog.Scenarios
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Cthangover.Core.Localization;
|
||||
using Cthangover.Core.Scenes;
|
||||
using Cthangover.Mods.Dialog;
|
||||
|
||||
/// <summary>
|
||||
/// A conditional jump in the middle of a dialog:
|
||||
/// <code>when "stat(cha) >= 5 && door == 'open'" -> :persuaded [else=refused]</code>
|
||||
/// evaluates the shared condition language (flags, quests, stats, equipment, GDScript
|
||||
/// conditions — everything mods registered) at the moment the line runs, and jumps to
|
||||
/// the arrow label when it holds, to <c>else</c> when it does not (or goes on).
|
||||
/// <para/>
|
||||
/// It is the RPG Maker "Conditional Branch" without a new syntax: the condition is the
|
||||
/// same text a scenario header's <c>condition:</c> takes. Several words without quotes
|
||||
/// are joined back with spaces, so short conditions need no quotes.
|
||||
/// </summary>
|
||||
public class WhenCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Command => "when";
|
||||
|
||||
/// <inheritdoc />
|
||||
public int MinPositional => 1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<string> AllowedNamed => new[] { "else" };
|
||||
|
||||
/// <inheritdoc />
|
||||
public string JumpTargetNamedKey => "else";
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
|
||||
{
|
||||
var condition = string.Join(" ", positional);
|
||||
named.TryGetValue("else", out var otherwise);
|
||||
dlg.IfGoTo(() => ScenarioCondition.Evaluate(condition), Label(arrowTarget), Label(otherwise));
|
||||
}
|
||||
|
||||
private static string Label(string target) => string.IsNullOrWhiteSpace(target) ? null : target.Trim().TrimStart(':');
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,10 @@ namespace Cthangover.Mods.Dialog.Scenarios
|
||||
|
||||
if (pendingSelect.Variants == null)
|
||||
pendingSelect.Variants = new List<SelectVariant>();
|
||||
pendingSelect.Variants.Add(SelectVariant.New(optText, goTo));
|
||||
var variant = SelectVariant.New(optText, goTo);
|
||||
if (named.TryGetValue("if", out var condition))
|
||||
variant.Condition = condition;
|
||||
pendingSelect.Variants.Add(variant);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cthangover.Core.Utils;
|
||||
using Cthangover.Mods.Dialog.Action;
|
||||
using Godot;
|
||||
using Cthangover.Core.UI;
|
||||
@@ -35,16 +37,29 @@ namespace Cthangover.Mods.Dialog.Action.Impls
|
||||
public override WaitType WaitType { get; set; } = WaitType.WaitSelect;
|
||||
|
||||
/// <summary>Substitutes variables in the variants and context text, then shows the answer box; the runtime stays paused until a variant is picked.</summary>
|
||||
/// <summary>
|
||||
/// Offers the options whose conditions hold now. When none does, the choice is
|
||||
/// skipped and the dialog goes on with the next line, so a choice of only gated
|
||||
/// options never leaves the player stuck.
|
||||
/// </summary>
|
||||
public override void DoRun(DialogRuntime runtime)
|
||||
{
|
||||
var dialogBox = runtime.DialogBox;
|
||||
if (dialogBox == null)
|
||||
return;
|
||||
|
||||
foreach (var variant in Variants)
|
||||
var shown = Variants.Where(v => v.IsShown()).ToList();
|
||||
WaitType = shown.Count == 0 ? WaitType.NoWait : WaitType.WaitSelect;
|
||||
if (shown.Count == 0)
|
||||
{
|
||||
GameLogger.Log("DIALOG", "select: no option is shown (all conditions false), going on", LogLevel.Debug);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var variant in shown)
|
||||
variant.Text = runtime.ProcessText(variant.Text);
|
||||
|
||||
dialogBox.SetVariants(Variants);
|
||||
dialogBox.SetVariants(shown);
|
||||
dialogBox.SetText(runtime.ProcessText(Text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,16 @@ namespace Cthangover.Mods.Dialog.Action.Impls
|
||||
/// <summary>Target action ID to jump to via <see cref="DialogRuntime.TryGoTo"/> when this variant is selected.</summary>
|
||||
public string GoTo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Condition of the shared condition language (<c>option "…" if=… -> :label</c>); the
|
||||
/// option is shown only while it holds. Null = always shown. Evaluated each time the
|
||||
/// choice appears, so a stat, a flag or an item gained a moment ago counts.
|
||||
/// </summary>
|
||||
public string Condition { get; set; }
|
||||
|
||||
/// <summary>Whether the option is offered now.</summary>
|
||||
public bool IsShown() => string.IsNullOrWhiteSpace(Condition) || ScenarioCondition.Evaluate(Condition);
|
||||
|
||||
/// <summary>Generates a new unique action ID for use as a GoTo target (e.g. with <see cref="DialogQueue.Point"/>).</summary>
|
||||
public static string Point => Guid.NewGuid().ToString();
|
||||
|
||||
|
||||
Reference in new issue
Block a user