Line endings: LF everywhere

.gitattributes forces LF (CRLF only for .bat/.cmd), core.autocrlf is off;
files that differed only by CRLF are normalized.
This commit is contained in:
cthangover committed 2026-10-21 13:29:39 +02:00
1 parent bd55716349
commit b5ad858c5e
51 files changed
+1781 -1751

No files matched your search

+78 -78
View File
@@ -1,78 +1,78 @@
using System.Collections.Generic;
using Cthangover.Mods.Dialog.Scenarios;
using Cthangover.Core.Utils;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Registry of <see cref="IScenarioCommandStrategy"/> implementations,
/// indexed by their <see cref="IScenarioCommandStrategy.Command"/> name.
/// It discovers nothing itself: <see cref="ScenarioCommandStrategyConsumer"/>
/// delivers the strategies of every mod as the kernel registers its
/// assembly and takes them back when the mod unloads, so the table never
/// holds a strategy of a dead assembly (which would pin it and keep running
/// its old code after a hot reload).
/// </summary>
public static class ScenarioCommandStrategyFactory
{
private static readonly Dictionary<string, IScenarioCommandStrategy> Strategies = new();
/// <summary>
/// Looks up the <see cref="IScenarioCommandStrategy"/> registered for <paramref name="command"/>.
/// Returns <c>null</c> if no strategy exists for the given command name.
/// </summary>
public static IScenarioCommandStrategy Get(string command)
{
Strategies.TryGetValue(command, out var strategy);
return strategy;
}
/// <summary>
/// Enumerates all registered DSL command names (lowercase).
/// </summary>
public static IEnumerable<string> GetAllCommandNames()
{
return Strategies.Keys;
}
/// <summary>
/// Returns the <see cref="ICommandReferenceMetadata"/> for a command if its
/// strategy implements that interface, or <c>null</c> otherwise. Used by the
/// build pipeline to collect asset dependencies from scenario scripts.
/// </summary>
public static ICommandReferenceMetadata GetReferenceMetadata(string command)
{
if (Strategies.TryGetValue(command, out var strategy) && strategy is ICommandReferenceMetadata meta)
return meta;
return null;
}
/// <summary>
/// Registers a strategy under its command name. The first strategy of a
/// command wins: a mod cannot silently take over a built-in command.
/// </summary>
public static void Register(IScenarioCommandStrategy strategy)
{
if (strategy != null && !Strategies.ContainsKey(strategy.Command))
Strategies[strategy.Command] = strategy;
}
/// <summary>
/// Removes <paramref name="strategy"/> (its mod is being unloaded). A
/// command owned by another strategy instance is left alone.
/// </summary>
public static void Unregister(IScenarioCommandStrategy strategy)
{
if (strategy != null && Strategies.TryGetValue(strategy.Command, out var registered) && registered == strategy)
Strategies.Remove(strategy.Command);
}
}
}
using System.Collections.Generic;
using Cthangover.Mods.Dialog.Scenarios;
using Cthangover.Core.Utils;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Registry of <see cref="IScenarioCommandStrategy"/> implementations,
/// indexed by their <see cref="IScenarioCommandStrategy.Command"/> name.
/// It discovers nothing itself: <see cref="ScenarioCommandStrategyConsumer"/>
/// delivers the strategies of every mod as the kernel registers its
/// assembly and takes them back when the mod unloads, so the table never
/// holds a strategy of a dead assembly (which would pin it and keep running
/// its old code after a hot reload).
/// </summary>
public static class ScenarioCommandStrategyFactory
{
private static readonly Dictionary<string, IScenarioCommandStrategy> Strategies = new();
/// <summary>
/// Looks up the <see cref="IScenarioCommandStrategy"/> registered for <paramref name="command"/>.
/// Returns <c>null</c> if no strategy exists for the given command name.
/// </summary>
public static IScenarioCommandStrategy Get(string command)
{
Strategies.TryGetValue(command, out var strategy);
return strategy;
}
/// <summary>
/// Enumerates all registered DSL command names (lowercase).
/// </summary>
public static IEnumerable<string> GetAllCommandNames()
{
return Strategies.Keys;
}
/// <summary>
/// Returns the <see cref="ICommandReferenceMetadata"/> for a command if its
/// strategy implements that interface, or <c>null</c> otherwise. Used by the
/// build pipeline to collect asset dependencies from scenario scripts.
/// </summary>
public static ICommandReferenceMetadata GetReferenceMetadata(string command)
{
if (Strategies.TryGetValue(command, out var strategy) && strategy is ICommandReferenceMetadata meta)
return meta;
return null;
}
/// <summary>
/// Registers a strategy under its command name. The first strategy of a
/// command wins: a mod cannot silently take over a built-in command.
/// </summary>
public static void Register(IScenarioCommandStrategy strategy)
{
if (strategy != null && !Strategies.ContainsKey(strategy.Command))
Strategies[strategy.Command] = strategy;
}
/// <summary>
/// Removes <paramref name="strategy"/> (its mod is being unloaded). A
/// command owned by another strategy instance is left alone.
/// </summary>
public static void Unregister(IScenarioCommandStrategy strategy)
{
if (strategy != null && Strategies.TryGetValue(strategy.Command, out var registered) && registered == strategy)
Strategies.Remove(strategy.Command);
}
}
}
+40 -40
View File
@@ -1,40 +1,40 @@
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Classifies the type of resource that the first positional argument of a
/// scenario command refers to. Used for dependency tracking — the build tool
/// can scan commands by their <see cref="ICommandReferenceMetadata"/> to
/// discover which assets (backgrounds, scenes, music, etc.) are referenced
/// and need to be packed into the final build.
/// </summary>
public enum PositionalReferenceKind
{
/// <summary>No resource reference in the first positional argument.</summary>
None,
/// <summary>A background image resource path.</summary>
Background,
/// <summary>A scene resource path (for scene switching).</summary>
Scene,
/// <summary>A music/audio resource path.</summary>
Music,
/// <summary>A sound effect resource path.</summary>
Sound,
/// <summary>An effect/shader resource path.</summary>
Effect,
/// <summary>An interactive action definition ID.</summary>
Action
}
/// <summary>
/// Optional interface for command strategies whose first positional argument
/// references an external resource. Strategies implementing this interface
/// are inspected by the build pipeline to collect asset dependencies.
/// </summary>
public interface ICommandReferenceMetadata
{
/// <summary>
/// The kind of resource referenced by the first positional argument of this command.
/// </summary>
PositionalReferenceKind Positional0Kind { get; }
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Classifies the type of resource that the first positional argument of a
/// scenario command refers to. Used for dependency tracking — the build tool
/// can scan commands by their <see cref="ICommandReferenceMetadata"/> to
/// discover which assets (backgrounds, scenes, music, etc.) are referenced
/// and need to be packed into the final build.
/// </summary>
public enum PositionalReferenceKind
{
/// <summary>No resource reference in the first positional argument.</summary>
None,
/// <summary>A background image resource path.</summary>
Background,
/// <summary>A scene resource path (for scene switching).</summary>
Scene,
/// <summary>A music/audio resource path.</summary>
Music,
/// <summary>A sound effect resource path.</summary>
Sound,
/// <summary>An effect/shader resource path.</summary>
Effect,
/// <summary>An interactive action definition ID.</summary>
Action
}
/// <summary>
/// Optional interface for command strategies whose first positional argument
/// references an external resource. Strategies implementing this interface
/// are inspected by the build pipeline to collect asset dependencies.
/// </summary>
public interface ICommandReferenceMetadata
{
/// <summary>
/// The kind of resource referenced by the first positional argument of this command.
/// </summary>
PositionalReferenceKind Positional0Kind { get; }
}
}
+31 -31
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,31 +9,31 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Strategy interface for handling a single DSL command type in scenario scripts.
/// Each command word (e.g. <c>text</c>, <c>music</c>, <c>goto</c>) maps to one
/// strategy implementation. The <see cref="ScenarioCommandStrategyFactory"/>
/// auto-discovers all implementations via reflection and dispatches commands
/// to the matching strategy during parsing.
/// </summary>
public interface IScenarioCommandStrategy
{
/// <summary>
/// The lowercase DSL command word this strategy handles (e.g. <c>"text"</c>, <c>"music"</c>).
/// </summary>
string Command { get; }
/// <summary>
/// Executes the command by appending one or more dialog actions to <paramref name="dlg"/>.
/// </summary>
/// <param name="dlg">The dialog queue to push actions onto.</param>
/// <param name="positional">Unnamed tokens following the command word in order.</param>
/// <param name="named">Key-value pairs parsed from <c>name=value</c> tokens (keys are lowercased).</param>
/// <param name="arrowTarget">The target label following a <c>-&gt;</c> arrow token, if present.</param>
/// <param name="locale">Optional localization provider for resolving <c>key=</c> lookups.</param>
void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale);
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Strategy interface for handling a single DSL command type in scenario scripts.
/// Each command word (e.g. <c>text</c>, <c>music</c>, <c>goto</c>) maps to one
/// strategy implementation. The <see cref="ScenarioCommandStrategyFactory"/>
/// auto-discovers all implementations via reflection and dispatches commands
/// to the matching strategy during parsing.
/// </summary>
public interface IScenarioCommandStrategy
{
/// <summary>
/// The lowercase DSL command word this strategy handles (e.g. <c>"text"</c>, <c>"music"</c>).
/// </summary>
string Command { get; }
/// <summary>
/// Executes the command by appending one or more dialog actions to <paramref name="dlg"/>.
/// </summary>
/// <param name="dlg">The dialog queue to push actions onto.</param>
/// <param name="positional">Unnamed tokens following the command word in order.</param>
/// <param name="named">Key-value pairs parsed from <c>name=value</c> tokens (keys are lowercased).</param>
/// <param name="arrowTarget">The target label following a <c>-&gt;</c> arrow token, if present.</param>
/// <param name="locale">Optional localization provider for resolving <c>key=</c> lookups.</param>
void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale);
}
}
+39 -39
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,39 +9,39 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>action</c> DSL command. Triggers a named interactive action
/// (defined in the action system) and forwards any extra named parameters as
/// context variables via <see cref="DialogQueue.Set"/>.
/// Implements <see cref="ICommandReferenceMetadata"/> to signal that the
/// first positional argument is an <see cref="PositionalReferenceKind.Action"/> reference.
/// </summary>
public class ActionCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "action";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Action;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var actionName = positional.Count > 0 ? positional[0] : "";
foreach (var kv in named)
{
if (kv.Key is "name" or "key") continue;
dlg.Set(kv.Key, kv.Value);
}
dlg.Action(actionName);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>action</c> DSL command. Triggers a named interactive action
/// (defined in the action system) and forwards any extra named parameters as
/// context variables via <see cref="DialogQueue.Set"/>.
/// Implements <see cref="ICommandReferenceMetadata"/> to signal that the
/// first positional argument is an <see cref="PositionalReferenceKind.Action"/> reference.
/// </summary>
public class ActionCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "action";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Action;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var actionName = positional.Count > 0 ? positional[0] : "";
foreach (var kv in named)
{
if (kv.Key is "name" or "key") continue;
dlg.Set(kv.Key, kv.Value);
}
dlg.Action(actionName);
}
}
}
+56 -56
View File
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,55 +10,55 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>animation</c> DSL command. Supports two modes:
/// (a) multiple sprites via <c>sprites=</c> named parameter, or
/// (b) a single sprite base with <c>start</c>, <c>count</c>, <c>speed</c>, and <c>loop</c> controls.
/// Delegates to <see cref="DialogQueue.Animation"/>.
/// </summary>
public class AnimationCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "animation";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "sprites", "speed", "loop", "start", "count" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (named.TryGetValue("sprites", out var spritesStr))
{
var sprites = new List<string>(spritesStr.Split(','));
var speed = named.TryGetValue("speed", out var sp) ? ParseFloat(sp) : 1f;
var loop = !named.TryGetValue("loop", out var lp) || lp == "true";
dlg.Animation(sprites, speed, 1f, loop);
}
else if (positional.Count > 0)
{
var sprite = positional[0];
var start = named.TryGetValue("start", out var st) ? ParseInt(st) : 0;
var count = named.TryGetValue("count", out var cn) ? ParseInt(cn) : 1;
var speed = named.TryGetValue("speed", out var sp) ? ParseFloat(sp) : 1f;
var loop = !named.TryGetValue("loop", out var lp) || lp == "true";
dlg.Animation(sprite, start, count, speed, 1f, loop);
}
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
private static int ParseInt(string s)
{
return int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var v) ? v : 0;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>animation</c> DSL command. Supports two modes:
/// (a) multiple sprites via <c>sprites=</c> named parameter, or
/// (b) a single sprite base with <c>start</c>, <c>count</c>, <c>speed</c>, and <c>loop</c> controls.
/// Delegates to <see cref="DialogQueue.Animation"/>.
/// </summary>
public class AnimationCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "animation";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "sprites", "speed", "loop", "start", "count" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (named.TryGetValue("sprites", out var spritesStr))
{
var sprites = new List<string>(spritesStr.Split(','));
var speed = named.TryGetValue("speed", out var sp) ? ParseFloat(sp) : 1f;
var loop = !named.TryGetValue("loop", out var lp) || lp == "true";
dlg.Animation(sprites, speed, 1f, loop);
}
else if (positional.Count > 0)
{
var sprite = positional[0];
var start = named.TryGetValue("start", out var st) ? ParseInt(st) : 0;
var count = named.TryGetValue("count", out var cn) ? ParseInt(cn) : 1;
var speed = named.TryGetValue("speed", out var sp) ? ParseFloat(sp) : 1f;
var loop = !named.TryGetValue("loop", out var lp) || lp == "true";
dlg.Animation(sprite, start, count, speed, 1f, loop);
}
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
private static int ParseInt(string s)
{
return int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var v) ? v : 0;
}
}
}
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Godot;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,47 +10,47 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>background_color</c> DSL command. Sets the dialog scene's
/// background color from a named color string (e.g. <c>black</c>, <c>red</c>)
/// or an HTML hex color (e.g. <c>#FF0000</c>). Delegates to <see cref="DialogQueue.BackgroundColor"/>.
/// </summary>
public class BackgroundColorCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "background_color";
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.BackgroundColor(ColorFromString(positional[0]));
}
private static Color ColorFromString(string s)
{
if (s.StartsWith('#'))
return Color.FromHtml(s.Substring(1));
var named = s.ToLowerInvariant() switch
{
"black" => Colors.Black,
"white" => Colors.White,
"red" => Colors.Red,
"green" => Colors.Green,
"blue" => Colors.Blue,
"yellow" => Colors.Yellow,
"gray" or "grey" => Colors.Gray,
_ => Colors.Black,
};
return named;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>background_color</c> DSL command. Sets the dialog scene's
/// background color from a named color string (e.g. <c>black</c>, <c>red</c>)
/// or an HTML hex color (e.g. <c>#FF0000</c>). Delegates to <see cref="DialogQueue.BackgroundColor"/>.
/// </summary>
public class BackgroundColorCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "background_color";
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.BackgroundColor(ColorFromString(positional[0]));
}
private static Color ColorFromString(string s)
{
if (s.StartsWith('#'))
return Color.FromHtml(s.Substring(1));
var named = s.ToLowerInvariant() switch
{
"black" => Colors.Black,
"white" => Colors.White,
"red" => Colors.Red,
"green" => Colors.Green,
"blue" => Colors.Blue,
"yellow" => Colors.Yellow,
"gray" or "grey" => Colors.Gray,
_ => Colors.Black,
};
return named;
}
}
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,30 +9,30 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>background</c> DSL command. Sets the dialog scene background
/// image from a resource path. Implements <see cref="ICommandReferenceMetadata"/>
/// with <see cref="PositionalReferenceKind.Background"/> so the build pipeline
/// can track referenced background assets.
/// </summary>
public class BackgroundCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "background";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Background;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.Background(positional.Count > 0 ? positional[0] : "");
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>background</c> DSL command. Sets the dialog scene background
/// image from a resource path. Implements <see cref="ICommandReferenceMetadata"/>
/// with <see cref="PositionalReferenceKind.Background"/> so the build pipeline
/// can track referenced background assets.
/// </summary>
public class BackgroundCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "background";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Background;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.Background(positional.Count > 0 ? positional[0] : "");
}
}
}
@@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action.Impls;
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action.Impls;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -11,38 +11,38 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>background_show_hide</c> DSL command. Animates the background
/// in (<c>show</c>) or out (<c>hide</c>) with configurable <c>duration</c> and
/// <c>wait</c> flag. Delegates to <see cref="DialogQueue.BackgroundShowHide"/>.
/// </summary>
public class BackgroundShowHideCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "background_show_hide";
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "duration", "wait" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var typeStr = positional.Count > 0 ? positional[0] : "show";
var type = typeStr.ToLowerInvariant() == "show"
? BackgroundActionType.Show
: BackgroundActionType.Hide;
var duration = named.TryGetValue("duration", out var dur) ? ParseFloat(dur) : 1f;
var wait = named.TryGetValue("wait", out var w) && w == "true";
dlg.BackgroundShowHide(type, duration, wait);
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>background_show_hide</c> DSL command. Animates the background
/// in (<c>show</c>) or out (<c>hide</c>) with configurable <c>duration</c> and
/// <c>wait</c> flag. Delegates to <see cref="DialogQueue.BackgroundShowHide"/>.
/// </summary>
public class BackgroundShowHideCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "background_show_hide";
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "duration", "wait" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var typeStr = positional.Count > 0 ? positional[0] : "show";
var type = typeStr.ToLowerInvariant() == "show"
? BackgroundActionType.Show
: BackgroundActionType.Hide;
var duration = named.TryGetValue("duration", out var dur) ? ParseFloat(dur) : 1f;
var wait = named.TryGetValue("wait", out var w) && w == "true";
dlg.BackgroundShowHide(type, duration, wait);
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
}
}
+50 -50
View File
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,49 +10,49 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>delay</c> DSL command. Pauses dialog execution for a
/// number of seconds, optionally displaying a text label during the pause.
/// If the <c>hidden</c> flag is set, the delay runs without visible text.
/// Supports localization via the <c>key=</c> named parameter.
/// </summary>
public class DelayCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "delay";
/// <inheritdoc/>
public int MaxPositional => 2;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key", "hidden" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var time = positional.Count > 0 ? ParseFloat(positional[0]) : 1f;
var hidden = positional.Count > 1 && positional[1] == "hidden"
|| named.TryGetValue("hidden", out var h) && h == "true";
var showText = hidden ? null
: positional.Count > 1 ? positional[1]
: null;
if (named.TryGetValue("key", out var key) && locale != null && showText != null)
{
var loc = locale.Get(key);
if (loc != null) showText = loc;
}
if (showText != null)
dlg.Delay(time, showText);
else
dlg.Delay(time, hidden);
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>delay</c> DSL command. Pauses dialog execution for a
/// number of seconds, optionally displaying a text label during the pause.
/// If the <c>hidden</c> flag is set, the delay runs without visible text.
/// Supports localization via the <c>key=</c> named parameter.
/// </summary>
public class DelayCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "delay";
/// <inheritdoc/>
public int MaxPositional => 2;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key", "hidden" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var time = positional.Count > 0 ? ParseFloat(positional[0]) : 1f;
var hidden = positional.Count > 1 && positional[1] == "hidden"
|| named.TryGetValue("hidden", out var h) && h == "true";
var showText = hidden ? null
: positional.Count > 1 ? positional[1]
: null;
if (named.TryGetValue("key", out var key) && locale != null && showText != null)
{
var loc = locale.Get(key);
if (loc != null) showText = loc;
}
if (showText != null)
dlg.Delay(time, showText);
else
dlg.Delay(time, hidden);
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
}
}
+30 -30
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,30 +9,30 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>effect</c> DSL command. Applies a named visual effect/shader
/// to the scene. Implements <see cref="ICommandReferenceMetadata"/> with
/// <see cref="PositionalReferenceKind.Effect"/> for build-time dependency tracking.
/// </summary>
public class EffectCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "effect";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Effect;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.Effect(positional[0]);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>effect</c> DSL command. Applies a named visual effect/shader
/// to the scene. Implements <see cref="ICommandReferenceMetadata"/> with
/// <see cref="PositionalReferenceKind.Effect"/> for build-time dependency tracking.
/// </summary>
public class EffectCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "effect";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Effect;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.Effect(positional[0]);
}
}
}
+26 -26
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,26 +9,26 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>empty</c> DSL command. Queues a no-op placeholder action
/// (<see cref="ActionEmpty"/>) that is skipped instantly — the DSL-level label
/// mechanism (<c>:label</c> via <see cref="DialogQueue.Point"/>) is built on the
/// same action type, and a bare <c>empty</c> line works as a placeholder marker.
/// </summary>
public class EmptyCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "empty";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.Empty();
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>empty</c> DSL command. Queues a no-op placeholder action
/// (<see cref="ActionEmpty"/>) that is skipped instantly — the DSL-level label
/// mechanism (<c>:label</c> via <see cref="DialogQueue.Point"/>) is built on the
/// same action type, and a bare <c>empty</c> line works as a placeholder marker.
/// </summary>
public class EmptyCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "empty";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.Empty();
}
}
}
+25 -25
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,25 +9,25 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>end</c> DSL command. Marks the end of the dialog sequence,
/// terminating execution of the current scenario. Typically used at the final
/// line of a scenario script to signal the dialog engine to close or transition.
/// </summary>
public class EndCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "end";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.End();
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>end</c> DSL command. Marks the end of the dialog sequence,
/// terminating execution of the current scenario. Typically used at the final
/// line of a scenario script to signal the dialog engine to close or transition.
/// </summary>
public class EndCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "end";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.End();
}
}
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,27 +9,27 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>foreground</c> DSL command. Places a foreground overlay
/// image on top of the scene (above background and characters). The first
/// positional argument specifies the resource path to the image asset.
/// </summary>
public class ForegroundCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "foreground";
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.Foreground(positional.Count > 0 ? positional[0] : "");
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>foreground</c> DSL command. Places a foreground overlay
/// image on top of the scene (above background and characters). The first
/// positional argument specifies the resource path to the image asset.
/// </summary>
public class ForegroundCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "foreground";
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.Foreground(positional.Count > 0 ? positional[0] : "");
}
}
}
+35 -35
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,35 +9,35 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>goto</c> DSL command. Jumps execution to a labeled anchor
/// point (<c>:labelname</c>) in the scenario script. Supports two forms:
/// <c>goto target_name</c> via <c>target=</c> named parameter, or
/// <c>goto -&gt; target_name</c> via the arrow target syntax.
/// </summary>
public class GotoCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "goto";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "target" };
/// <inheritdoc/>
public string JumpTargetNamedKey => "target";
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (!string.IsNullOrEmpty(arrowTarget))
dlg.GoTo(arrowTarget);
else if (named.TryGetValue("target", out var target))
dlg.GoTo(target);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>goto</c> DSL command. Jumps execution to a labeled anchor
/// point (<c>:labelname</c>) in the scenario script. Supports two forms:
/// <c>goto target_name</c> via <c>target=</c> named parameter, or
/// <c>goto -&gt; target_name</c> via the arrow target syntax.
/// </summary>
public class GotoCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "goto";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "target" };
/// <inheritdoc/>
public string JumpTargetNamedKey => "target";
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (!string.IsNullOrEmpty(arrowTarget))
dlg.GoTo(arrowTarget);
else if (named.TryGetValue("target", out var target))
dlg.GoTo(target);
}
}
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,25 +9,25 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>hide_dialog</c> DSL command. Hides the dialog UI panel
/// (text box, avatars, and UI chrome) from the screen. The inverse of
/// <see cref="ShowDialogCommandStrategy"/>.
/// </summary>
public class HideDialogCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "hide_dialog";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.HideDialog();
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>hide_dialog</c> DSL command. Hides the dialog UI panel
/// (text box, avatars, and UI chrome) from the screen. The inverse of
/// <see cref="ShowDialogCommandStrategy"/>.
/// </summary>
public class HideDialogCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "hide_dialog";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.HideDialog();
}
}
}
+29 -29
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,29 +9,29 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios.Impls
{
/// <summary>
/// Handles the <c>light_set</c> DSL command. Passes a JSON string that
/// describes lighting configuration to the dialog engine via
/// <see cref="DialogQueue.LightSet"/>. The JSON structure is forwarded
/// as-is to the rendering layer for point-light setup.
/// </summary>
public class LightSetCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "light_set";
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional,
Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var json = positional.Count > 0 ? positional[0] : null;
dlg.LightSet(json);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios.Impls
{
/// <summary>
/// Handles the <c>light_set</c> DSL command. Passes a JSON string that
/// describes lighting configuration to the dialog engine via
/// <see cref="DialogQueue.LightSet"/>. The JSON structure is forwarded
/// as-is to the rendering layer for point-light setup.
/// </summary>
public class LightSetCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "light_set";
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional,
Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var json = positional.Count > 0 ? positional[0] : null;
dlg.LightSet(json);
}
}
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,26 +9,26 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>light_use_time</c> DSL command. Toggles whether the
/// scene lighting should be driven by the simulated time-of-day system.
/// Passes a boolean flag to <see cref="DialogQueue.LightUseTime"/>.
/// </summary>
public class LightUseTimeCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "light_use_time";
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var val = positional.Count > 0 ? positional[0] : "true";
dlg.LightUseTime(val == "true");
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>light_use_time</c> DSL command. Toggles whether the
/// scene lighting should be driven by the simulated time-of-day system.
/// Passes a boolean flag to <see cref="DialogQueue.LightUseTime"/>.
/// </summary>
public class LightUseTimeCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "light_use_time";
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var val = positional.Count > 0 ? positional[0] : "true";
dlg.LightUseTime(val == "true");
}
}
}
+31 -31
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,31 +9,31 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>music</c> DSL command. Starts playing a background music
/// track from the given resource path. Implements <see cref="ICommandReferenceMetadata"/>
/// with <see cref="PositionalReferenceKind.Music"/> so the build pipeline
/// can track referenced audio assets.
/// </summary>
public class MusicCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "music";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Music;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.Music(positional[0]);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>music</c> DSL command. Starts playing a background music
/// track from the given resource path. Implements <see cref="ICommandReferenceMetadata"/>
/// with <see cref="PositionalReferenceKind.Music"/> so the build pipeline
/// can track referenced audio assets.
/// </summary>
public class MusicCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "music";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Music;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.Music(positional[0]);
}
}
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,25 +9,25 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>music_pause</c> DSL command. Pauses the currently
/// playing background music stream. Playback can be resumed later with
/// <see cref="MusicPlayCommandStrategy"/>.
/// </summary>
public class MusicPauseCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "music_pause";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.MusicPause();
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>music_pause</c> DSL command. Pauses the currently
/// playing background music stream. Playback can be resumed later with
/// <see cref="MusicPlayCommandStrategy"/>.
/// </summary>
public class MusicPauseCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "music_pause";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.MusicPause();
}
}
}
+24 -24
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,24 +9,24 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>music_play</c> DSL command. Resumes the currently
/// paused background music stream. Has no effect if music is already playing.
/// </summary>
public class MusicPlayCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "music_play";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.MusicPlay();
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>music_play</c> DSL command. Resumes the currently
/// paused background music stream. Has no effect if music is already playing.
/// </summary>
public class MusicPlayCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "music_play";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.MusicPlay();
}
}
}
+46 -46
View File
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,45 +10,45 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>ptext</c> DSL command. A "plain text" variant of
/// <see cref="TextCommandStrategy"/> that skips speaker attribution
/// but still supports <c>first</c>/<c>second</c> avatar faces and
/// <c>hide_color</c> and <c>wait</c> behavior flags. Text content
/// can be provided directly or resolved via a <c>key=</c> localization key.
/// </summary>
public class PTextCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "ptext";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key", "first", "second", "hide_color", "wait" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var textVal = positional.Count > 0 ? positional[0] : "";
if (named.TryGetValue("key", out var key) && locale != null)
{
var loc = locale.Get(key);
if (loc != null) textVal = loc;
}
var first = named.TryGetValue("first", out var f) ? f : null;
var second = named.TryGetValue("second", out var s) ? s : null;
var hideColor = named.TryGetValue("hide_color", out var hc) && hc == "true";
var action = dlg.PText(textVal, first, second, hideColor);
if (named.TryGetValue("wait", out var wait) && wait == "false")
action.WaitType = WaitType.NoWait;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>ptext</c> DSL command. A "plain text" variant of
/// <see cref="TextCommandStrategy"/> that skips speaker attribution
/// but still supports <c>first</c>/<c>second</c> avatar faces and
/// <c>hide_color</c> and <c>wait</c> behavior flags. Text content
/// can be provided directly or resolved via a <c>key=</c> localization key.
/// </summary>
public class PTextCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "ptext";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key", "first", "second", "hide_color", "wait" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var textVal = positional.Count > 0 ? positional[0] : "";
if (named.TryGetValue("key", out var key) && locale != null)
{
var loc = locale.Get(key);
if (loc != null) textVal = loc;
}
var first = named.TryGetValue("first", out var f) ? f : null;
var second = named.TryGetValue("second", out var s) ? s : null;
var hideColor = named.TryGetValue("hide_color", out var hc) && hc == "true";
var action = dlg.PText(textVal, first, second, hideColor);
if (named.TryGetValue("wait", out var wait) && wait == "false")
action.WaitType = WaitType.NoWait;
}
}
}
+31 -31
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,31 +9,31 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>set</c> DSL command. Stores an arbitrary key-value pair
/// into the dialog session's variable state via <see cref="DialogQueue.Set"/>.
/// Values are read back later through <c>${var}</c> substitution in
/// <c>ptext</c> lines and via <see cref="Cthangover.Core.Actions.IActionContext.GetParam"/>
/// in scenario actions.
/// </summary>
public class SetCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "set";
/// <inheritdoc/>
public int MinPositional => 2;
/// <inheritdoc/>
public int MaxPositional => 2;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var name = positional.Count > 0 ? positional[0] : "";
var value = positional.Count > 1 ? positional[1] : "";
dlg.Set(name, value);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>set</c> DSL command. Stores an arbitrary key-value pair
/// into the dialog session's variable state via <see cref="DialogQueue.Set"/>.
/// Values are read back later through <c>${var}</c> substitution in
/// <c>ptext</c> lines and via <see cref="Cthangover.Core.Actions.IActionContext.GetParam"/>
/// in scenario actions.
/// </summary>
public class SetCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "set";
/// <inheritdoc/>
public int MinPositional => 2;
/// <inheritdoc/>
public int MaxPositional => 2;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var name = positional.Count > 0 ? positional[0] : "";
var value = positional.Count > 1 ? positional[1] : "";
dlg.Set(name, value);
}
}
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,25 +9,25 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>show_dialog</c> DSL command. Makes the dialog UI panel
/// (text box, avatars, and UI chrome) visible on screen. The inverse of
/// <see cref="HideDialogCommandStrategy"/>.
/// </summary>
public class ShowDialogCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "show_dialog";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.ShowDialog();
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>show_dialog</c> DSL command. Makes the dialog UI panel
/// (text box, avatars, and UI chrome) visible on screen. The inverse of
/// <see cref="HideDialogCommandStrategy"/>.
/// </summary>
public class ShowDialogCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "show_dialog";
/// <inheritdoc/>
public int MaxPositional => 0;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
dlg.ShowDialog();
}
}
}
+31 -31
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,31 +9,31 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>sound</c> DSL command. Plays a one-shot sound effect
/// from the given resource path. Implements <see cref="ICommandReferenceMetadata"/>
/// with <see cref="PositionalReferenceKind.Sound"/> so the build pipeline
/// can track referenced audio assets.
/// </summary>
public class SoundCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "sound";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Sound;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.Sound(positional[0]);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>sound</c> DSL command. Plays a one-shot sound effect
/// from the given resource path. Implements <see cref="ICommandReferenceMetadata"/>
/// with <see cref="PositionalReferenceKind.Sound"/> so the build pipeline
/// can track referenced audio assets.
/// </summary>
public class SoundCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "sound";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Sound;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
if (positional.Count > 0)
dlg.Sound(positional[0]);
}
}
}
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using System.Globalization;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,41 +10,41 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>switch_scene</c> DSL command. Transitions to a new Godot
/// scene (PackedScene) with configurable transition <c>speed</c> and an
/// optional <c>hidden</c> mode that shows only the scene background during
/// the transition. Implements <see cref="ICommandReferenceMetadata"/> with
/// <see cref="PositionalReferenceKind.Scene"/> for build-time dependency tracking.
/// </summary>
public class SwitchSceneCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "switch_scene";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Scene;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "speed", "hidden" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var scene = positional.Count > 0 ? positional[0] : "";
var speed = named.TryGetValue("speed", out var sp) ? ParseFloat(sp) : 4f;
var hidden = named.TryGetValue("hidden", out var h) && h == "true";
dlg.SwitchScene(scene, speed, hidden);
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>switch_scene</c> DSL command. Transitions to a new Godot
/// scene (PackedScene) with configurable transition <c>speed</c> and an
/// optional <c>hidden</c> mode that shows only the scene background during
/// the transition. Implements <see cref="ICommandReferenceMetadata"/> with
/// <see cref="PositionalReferenceKind.Scene"/> for build-time dependency tracking.
/// </summary>
public class SwitchSceneCommandStrategy : IScenarioCommandStrategy, ICommandReferenceMetadata, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "switch_scene";
/// <inheritdoc/>
public PositionalReferenceKind Positional0Kind => PositionalReferenceKind.Scene;
/// <inheritdoc/>
public int MinPositional => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "speed", "hidden" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var scene = positional.Count > 0 ? positional[0] : "";
var speed = named.TryGetValue("speed", out var sp) ? ParseFloat(sp) : 4f;
var hidden = named.TryGetValue("hidden", out var h) && h == "true";
dlg.SwitchScene(scene, speed, hidden);
}
private static float ParseFloat(string s)
{
return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0f;
}
}
}
+46 -46
View File
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,45 +10,45 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>text</c> DSL command, the primary dialog display instruction.
/// Shows character text with optional <c>first</c>/<c>second</c> speaker
/// avatar faces, <c>hide_color</c> tint suppression, and a <c>wait</c> flag
/// that controls whether the dialog waits for user input before continuing.
/// Text can be literal or resolved from a <c>key=</c> localization entry.
/// </summary>
public class TextCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "text";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key", "first", "second", "hide_color", "wait" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var textVal = positional.Count > 0 ? positional[0] : "";
if (named.TryGetValue("key", out var key) && locale != null)
{
var loc = locale.Get(key);
if (loc != null) textVal = loc;
}
var first = named.TryGetValue("first", out var f) ? f : null;
var second = named.TryGetValue("second", out var s) ? s : null;
var hideColor = named.TryGetValue("hide_color", out var hc) && hc == "true";
var action = dlg.Text(textVal, first, second, hideColor);
if (named.TryGetValue("wait", out var wait) && wait == "false")
action.WaitType = WaitType.NoWait;
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>text</c> DSL command, the primary dialog display instruction.
/// Shows character text with optional <c>first</c>/<c>second</c> speaker
/// avatar faces, <c>hide_color</c> tint suppression, and a <c>wait</c> flag
/// that controls whether the dialog waits for user input before continuing.
/// Text can be literal or resolved from a <c>key=</c> localization entry.
/// </summary>
public class TextCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "text";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key", "first", "second", "hide_color", "wait" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var textVal = positional.Count > 0 ? positional[0] : "";
if (named.TryGetValue("key", out var key) && locale != null)
{
var loc = locale.Get(key);
if (loc != null) textVal = loc;
}
var first = named.TryGetValue("first", out var f) ? f : null;
var second = named.TryGetValue("second", out var s) ? s : null;
var hideColor = named.TryGetValue("hide_color", out var hc) && hc == "true";
var action = dlg.Text(textVal, first, second, hideColor);
if (named.TryGetValue("wait", out var wait) && wait == "false")
action.WaitType = WaitType.NoWait;
}
}
}
+37 -37
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -9,37 +9,37 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>title</c> DSL command. Displays a centered title/caption
/// text on screen, typically used for chapter headings or location labels.
/// Text can be literal or resolved from a <c>key=</c> localization entry.
/// Silently does nothing if no text value is provided or resolved.
/// </summary>
public class TitleCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "title";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var textVal = positional.Count > 0 ? positional[0] : null;
if (named.TryGetValue("key", out var key) && locale != null)
{
var loc = locale.Get(key);
if (loc != null) textVal = loc;
}
if (textVal != null)
dlg.Title(textVal);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Handles the <c>title</c> DSL command. Displays a centered title/caption
/// text on screen, typically used for chapter headings or location labels.
/// Text can be literal or resolved from a <c>key=</c> localization entry.
/// Silently does nothing if no text value is provided or resolved.
/// </summary>
public class TitleCommandStrategy : IScenarioCommandStrategy, IScenarioCommandSpec
{
/// <inheritdoc/>
public string Command => "title";
/// <inheritdoc/>
public int MinArguments => 1;
/// <inheritdoc/>
public int MaxPositional => 1;
/// <inheritdoc/>
public IReadOnlyList<string> AllowedNamed => new[] { "key" };
/// <inheritdoc/>
public void Execute(DialogQueue dlg, List<string> positional, Dictionary<string, string> named, string arrowTarget, ILocalizationProvider locale)
{
var textVal = positional.Count > 0 ? positional[0] : null;
if (named.TryGetValue("key", out var key) && locale != null)
{
var loc = locale.Get(key);
if (loc != null) textVal = loc;
}
if (textVal != null)
dlg.Title(textVal);
}
}
}
+66 -66
View File
@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Core.Mods;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action;
using Cthangover.Mods.Dialog.Action.Impls;
using Cthangover.Core.Utils;
using Godot;
using System;
using System.Collections.Generic;
using Cthangover.Core.Localization;
using Cthangover.Core.Mods;
using Cthangover.Mods.Dialog;
using Cthangover.Mods.Dialog.Action;
using Cthangover.Mods.Dialog.Action.Impls;
using Cthangover.Core.Utils;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -15,60 +15,60 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Converts scenario DSL text or files into <see cref="DialogQueue"/> instances.
/// Wraps <see cref="ScenarioParser"/> with a configurable <see cref="ILocalizationProvider"/>
/// that defaults to <see cref="GodotTranslationProvider.Instance"/> when none is supplied.
/// </summary>
public class ScenarioConverter
{
private readonly ILocalizationProvider locale;
/// <summary>
/// Creates a converter with an optional localization provider.
/// </summary>
/// <param name="locale">Localization provider for <c>key=</c> text lookups. Defaults to Godot translations.</param>
public ScenarioConverter(ILocalizationProvider locale = null)
{
this.locale = locale ?? GodotTranslationProvider.Instance;
}
/// <summary>
/// Parses raw scenario script text into a dialog queue using the configured locale.
/// </summary>
public DialogQueue Convert(string text)
{
return ScenarioParser.Parse(text, locale);
}
/// <summary>
/// Reads a scenario file from disk and parses it into a dialog queue.
/// </summary>
/// <param name="path">Filesystem path to the <c>.scenario</c> file.</param>
/// <returns>The parsed <see cref="DialogQueue"/>, or <c>null</c> if the file could not be opened.</returns>
public DialogQueue ConvertFile(string path)
{
foreach (var kvp in ModRegistry.Instance.Mods)
{
var text = kvp.Value.FileProvider.ReadFileText(path);
if (text != null)
return Convert(text);
}
var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
if (file == null)
{
GameLogger.Log("CONVERTER", $"Failed to open '{path}'", LogLevel.Error);
return null;
}
var fileText = file.GetAsText();
file.Close();
return Convert(fileText);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Converts scenario DSL text or files into <see cref="DialogQueue"/> instances.
/// Wraps <see cref="ScenarioParser"/> with a configurable <see cref="ILocalizationProvider"/>
/// that defaults to <see cref="GodotTranslationProvider.Instance"/> when none is supplied.
/// </summary>
public class ScenarioConverter
{
private readonly ILocalizationProvider locale;
/// <summary>
/// Creates a converter with an optional localization provider.
/// </summary>
/// <param name="locale">Localization provider for <c>key=</c> text lookups. Defaults to Godot translations.</param>
public ScenarioConverter(ILocalizationProvider locale = null)
{
this.locale = locale ?? GodotTranslationProvider.Instance;
}
/// <summary>
/// Parses raw scenario script text into a dialog queue using the configured locale.
/// </summary>
public DialogQueue Convert(string text)
{
return ScenarioParser.Parse(text, locale);
}
/// <summary>
/// Reads a scenario file from disk and parses it into a dialog queue.
/// </summary>
/// <param name="path">Filesystem path to the <c>.scenario</c> file.</param>
/// <returns>The parsed <see cref="DialogQueue"/>, or <c>null</c> if the file could not be opened.</returns>
public DialogQueue ConvertFile(string path)
{
foreach (var kvp in ModRegistry.Instance.Mods)
{
var text = kvp.Value.FileProvider.ReadFileText(path);
if (text != null)
return Convert(text);
}
var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
if (file == null)
{
GameLogger.Log("CONVERTER", $"Failed to open '{path}'", LogLevel.Error);
return null;
}
var fileText = file.GetAsText();
file.Close();
return Convert(fileText);
}
}
}
+46 -46
View File
@@ -1,7 +1,7 @@
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.Utils;
using Godot;
using Cthangover.Core.Localization;
using Cthangover.Mods.Dialog;
using Cthangover.Core.Utils;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -10,45 +10,45 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Loads a <c>.scenario</c> file from disk, reads its text content, and
/// parses it via <see cref="ScenarioParser.Parse"/> into a <see cref="DialogQueue"/>.
/// Uses <see cref="GodotTranslationProvider.Instance"/> as the default localization source.
/// </summary>
public static class ScenarioLoader
{
/// <summary>
/// Loads and parses a scenario file using the default Godot translation provider.
/// </summary>
/// <param name="path">Filesystem path to the <c>.scenario</c> file.</param>
/// <returns>The parsed <see cref="DialogQueue"/>, or <c>null</c> if the file could not be opened.</returns>
public static DialogQueue Load(string path)
{
return Load(path, GodotTranslationProvider.Instance);
}
/// <summary>
/// Loads and parses a scenario file with a custom localization provider for text lookups.
/// </summary>
/// <param name="path">Filesystem path to the <c>.scenario</c> file.</param>
/// <param name="provider">Localization provider to resolve <c>key=</c> references during parsing.</param>
/// <returns>The parsed <see cref="DialogQueue"/>, or <c>null</c> if the file could not be opened.</returns>
public static DialogQueue Load(string path, ILocalizationProvider provider)
{
var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
if (file == null)
{
GameLogger.Log("SCENE", $"ScenarioLoader: failed to open '{path}'", LogLevel.Error);
return null;
}
var text = file.GetAsText();
file.Close();
return ScenarioParser.Parse(text, provider);
}
}
}
namespace Cthangover.Mods.Dialog.Scenarios
{
/// <summary>
/// Loads a <c>.scenario</c> file from disk, reads its text content, and
/// parses it via <see cref="ScenarioParser.Parse"/> into a <see cref="DialogQueue"/>.
/// Uses <see cref="GodotTranslationProvider.Instance"/> as the default localization source.
/// </summary>
public static class ScenarioLoader
{
/// <summary>
/// Loads and parses a scenario file using the default Godot translation provider.
/// </summary>
/// <param name="path">Filesystem path to the <c>.scenario</c> file.</param>
/// <returns>The parsed <see cref="DialogQueue"/>, or <c>null</c> if the file could not be opened.</returns>
public static DialogQueue Load(string path)
{
return Load(path, GodotTranslationProvider.Instance);
}
/// <summary>
/// Loads and parses a scenario file with a custom localization provider for text lookups.
/// </summary>
/// <param name="path">Filesystem path to the <c>.scenario</c> file.</param>
/// <param name="provider">Localization provider to resolve <c>key=</c> references during parsing.</param>
/// <returns>The parsed <see cref="DialogQueue"/>, or <c>null</c> if the file could not be opened.</returns>
public static DialogQueue Load(string path, ILocalizationProvider provider)
{
var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
if (file == null)
{
GameLogger.Log("SCENE", $"ScenarioLoader: failed to open '{path}'", LogLevel.Error);
return null;
}
var text = file.GetAsText();
file.Close();
return ScenarioParser.Parse(text, provider);
}
}
}
+14 -14
View File
@@ -1,14 +1,14 @@
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// High-level action category discriminator. Currently minimal (Text, End)
/// — may expand as additional action families are added.
/// </summary>
public enum ActionType
{
/// <summary>A dialog text display action that pauses for click input.</summary>
Text,
/// <summary>Terminates the dialog queue.</summary>
End
}
}
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// High-level action category discriminator. Currently minimal (Text, End)
/// — may expand as additional action families are added.
/// </summary>
public enum ActionType
{
/// <summary>A dialog text display action that pauses for click input.</summary>
Text,
/// <summary>Terminates the dialog queue.</summary>
End
}
}
+17 -17
View File
@@ -1,17 +1,17 @@
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Controls when an action's Construct() fires. OnStartQueue — construct
/// when the dialog queue is first loaded (good for preloading); OnStartAction —
/// lazy-construct just before the action runs (saves resources for unreached
/// branches). Default for most actions is OnStartAction.
/// </summary>
public enum ConstructType
{
/// <summary>Construct when the dialog queue is first loaded. Useful for actions that need to preload resources.</summary>
OnStartQueue,
/// <summary>Construct lazily just before the action runs. Default for most actions — saves resources for unreached branches.</summary>
OnStartAction
}
}
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Controls when an action's Construct() fires. OnStartQueue — construct
/// when the dialog queue is first loaded (good for preloading); OnStartAction —
/// lazy-construct just before the action runs (saves resources for unreached
/// branches). Default for most actions is OnStartAction.
/// </summary>
public enum ConstructType
{
/// <summary>Construct when the dialog queue is first loaded. Useful for actions that need to preload resources.</summary>
OnStartQueue,
/// <summary>Construct lazily just before the action runs. Default for most actions — saves resources for unreached branches.</summary>
OnStartAction
}
}
+20 -20
View File
@@ -1,20 +1,20 @@
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Controls when an action's Destruct() fires. OnEndAction — immediately after
/// the action advances (typical for most commands). OnDelayed — deferred until
/// specifically cleaned up (for visual state that must persist across actions).
/// OnEndQueue — destruct when the entire dialog queue finishes (for resources
/// that must survive the whole dialog but not beyond).
/// </summary>
public enum DestructType
{
/// <summary>Destruct immediately when the action is advanced past. Default for most commands.</summary>
OnEndAction,
/// <summary>Destruct is deferred — must be manually triggered or triggered via <see cref="ActionCommand.DelayedDestruct"/>.</summary>
OnDelayed,
/// <summary>Destruct when the entire dialog queue finishes. Use for resources that must survive the whole dialog but not beyond.</summary>
OnEndQueue,
}
}
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Controls when an action's Destruct() fires. OnEndAction — immediately after
/// the action advances (typical for most commands). OnDelayed — deferred until
/// specifically cleaned up (for visual state that must persist across actions).
/// OnEndQueue — destruct when the entire dialog queue finishes (for resources
/// that must survive the whole dialog but not beyond).
/// </summary>
public enum DestructType
{
/// <summary>Destruct immediately when the action is advanced past. Default for most commands.</summary>
OnEndAction,
/// <summary>Destruct is deferred — must be manually triggered or triggered via <see cref="ActionCommand.DelayedDestruct"/>.</summary>
OnDelayed,
/// <summary>Destruct when the entire dialog queue finishes. Use for resources that must survive the whole dialog but not beyond.</summary>
OnEndQueue,
}
}
+13 -13
View File
@@ -1,13 +1,13 @@
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Minimal destructible contract — anything in the dialog runtime's object list
/// that must be cleaned up when a dialog ends.
/// </summary>
public interface IActionDestruct
{
/// <summary>Called to release resources, disconnect signals, and mark the object as finished. Must be idempotent.</summary>
void Destruct();
}
}
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Minimal destructible contract — anything in the dialog runtime's object list
/// that must be cleaned up when a dialog ends.
/// </summary>
public interface IActionDestruct
{
/// <summary>Called to release resources, disconnect signals, and mark the object as finished. Must be idempotent.</summary>
void Destruct();
}
}
+81 -81
View File
@@ -1,81 +1,81 @@
using Cthangover.Core.Factories.Impls;
using Cthangover.Core.Scenes;
using Cthangover.Mods.Dialog.Action;
using Cthangover.Mods.Time;
using Cthangover.Mods.Interface.View;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Sets the scene background on the ViewBox, including depth and albedo maps
/// for the lighting system. Resolves textures through BackgroundFactory on
/// construction (OnStartQueue) — depth and albedo are loaded from the same
/// sprite ID with "_depth" / "_albedo" suffixes. Kills any in-progress
/// background transition before setting the new texture. Textures are nulled
/// after application to prevent stale reuse across dialog restarts.
/// Sets SceneContextNode.LastBackgroundID so the scene manager can restore
/// the correct background on scene revisit.
/// </summary>
public class ActionBackground : ActionCommand
{
/// <summary>Sprite resource ID resolved through <see cref="BackgroundFactory"/> on construction. Also loads depth (_depth) and albedo (_albedo) variants.</summary>
public string SpriteID { get; set; }
/// <summary>Direct texture override. When non-null, bypasses factory resolution. Set to null after application to prevent stale reuse.</summary>
public Texture2D Texture { get; set; }
/// <summary>Depth map for the lighting system, loaded from <see cref="SpriteID"/> + "_depth".</summary>
public Texture2D DepthTexture { get; set; }
/// <summary>Albedo color map for the lighting system, loaded from <see cref="SpriteID"/> + "_albedo".</summary>
public Texture2D AlbedoTexture { get; set; }
/// <summary>Preloads textures when the dialog queue is first created, resolving SpriteID through the factory.</summary>
public override ConstructType ConstructType { get; set; } = ConstructType.OnStartQueue;
/// <summary>Background is set imperatively — the dialog continues immediately.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Resolves <see cref="SpriteID"/> plus its <c>_depth</c>/<c>_albedo</c> variants through the background factory.</summary>
public override void DoConstruct()
{
base.DoConstruct();
if (Texture == null && !string.IsNullOrEmpty(SpriteID))
Texture = BackgroundFactory.Instance.Get(SpriteID);
if (!string.IsNullOrEmpty(SpriteID))
{
DepthTexture = BackgroundFactory.Instance.Get(SpriteID + "_depth");
AlbedoTexture = BackgroundFactory.Instance.Get(SpriteID + "_albedo");
}
}
/// <summary>
/// Applies the background to the ViewBox, kills any in-flight background
/// transition and feeds the depth/albedo maps to the light controller.
/// Consumed textures are nulled so a reused action cannot re-apply stale data.
/// </summary>
public override void DoRun(DialogRuntime runtime)
{
if (Texture == null)
return;
SceneContextNode.LastBackgroundID = SpriteID;
var viewBox = Scene.Find<ViewBox>("ViewBox");
viewBox?.KillTransitionTween();
viewBox?.SetBackgroundTexture(Texture);
var controller = UiLightController.Instance;
controller?.SetupDepthMap(DepthTexture);
controller?.SetupAlbedoMap(AlbedoTexture);
Texture = null;
DepthTexture = null;
AlbedoTexture = null;
}
}
}
using Cthangover.Core.Factories.Impls;
using Cthangover.Core.Scenes;
using Cthangover.Mods.Dialog.Action;
using Cthangover.Mods.Time;
using Cthangover.Mods.Interface.View;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Sets the scene background on the ViewBox, including depth and albedo maps
/// for the lighting system. Resolves textures through BackgroundFactory on
/// construction (OnStartQueue) — depth and albedo are loaded from the same
/// sprite ID with "_depth" / "_albedo" suffixes. Kills any in-progress
/// background transition before setting the new texture. Textures are nulled
/// after application to prevent stale reuse across dialog restarts.
/// Sets SceneContextNode.LastBackgroundID so the scene manager can restore
/// the correct background on scene revisit.
/// </summary>
public class ActionBackground : ActionCommand
{
/// <summary>Sprite resource ID resolved through <see cref="BackgroundFactory"/> on construction. Also loads depth (_depth) and albedo (_albedo) variants.</summary>
public string SpriteID { get; set; }
/// <summary>Direct texture override. When non-null, bypasses factory resolution. Set to null after application to prevent stale reuse.</summary>
public Texture2D Texture { get; set; }
/// <summary>Depth map for the lighting system, loaded from <see cref="SpriteID"/> + "_depth".</summary>
public Texture2D DepthTexture { get; set; }
/// <summary>Albedo color map for the lighting system, loaded from <see cref="SpriteID"/> + "_albedo".</summary>
public Texture2D AlbedoTexture { get; set; }
/// <summary>Preloads textures when the dialog queue is first created, resolving SpriteID through the factory.</summary>
public override ConstructType ConstructType { get; set; } = ConstructType.OnStartQueue;
/// <summary>Background is set imperatively — the dialog continues immediately.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Resolves <see cref="SpriteID"/> plus its <c>_depth</c>/<c>_albedo</c> variants through the background factory.</summary>
public override void DoConstruct()
{
base.DoConstruct();
if (Texture == null && !string.IsNullOrEmpty(SpriteID))
Texture = BackgroundFactory.Instance.Get(SpriteID);
if (!string.IsNullOrEmpty(SpriteID))
{
DepthTexture = BackgroundFactory.Instance.Get(SpriteID + "_depth");
AlbedoTexture = BackgroundFactory.Instance.Get(SpriteID + "_albedo");
}
}
/// <summary>
/// Applies the background to the ViewBox, kills any in-flight background
/// transition and feeds the depth/albedo maps to the light controller.
/// Consumed textures are nulled so a reused action cannot re-apply stale data.
/// </summary>
public override void DoRun(DialogRuntime runtime)
{
if (Texture == null)
return;
SceneContextNode.LastBackgroundID = SpriteID;
var viewBox = Scene.Find<ViewBox>("ViewBox");
viewBox?.KillTransitionTween();
viewBox?.SetBackgroundTexture(Texture);
var controller = UiLightController.Instance;
controller?.SetupDepthMap(DepthTexture);
controller?.SetupAlbedoMap(AlbedoTexture);
Texture = null;
DepthTexture = null;
AlbedoTexture = null;
}
}
}
@@ -1,5 +1,5 @@
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -8,26 +8,26 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Sets the background tint color. DoRun is currently a no-op — the Color
/// property is stored for external systems to read. Likely intended as a
/// declarative instruction consumed by a background-rendering node rather
/// than applied imperatively.
/// </summary>
public class ActionBackgroundColor : ActionCommand
{
/// <summary>Target tint color. Stored declaratively — consumed by background-rendering nodes rather than applied imperatively here.</summary>
public Color Color { get; set; } = Colors.Black;
/// <summary>Imperative — the dialog continues immediately after this action is processed.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Deliberate no-op: the tint is declarative data for background-rendering nodes, not applied here.</summary>
public override void DoRun(DialogRuntime runtime)
{
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Sets the background tint color. DoRun is currently a no-op — the Color
/// property is stored for external systems to read. Likely intended as a
/// declarative instruction consumed by a background-rendering node rather
/// than applied imperatively.
/// </summary>
public class ActionBackgroundColor : ActionCommand
{
/// <summary>Target tint color. Stored declaratively — consumed by background-rendering nodes rather than applied imperatively here.</summary>
public Color Color { get; set; } = Colors.Black;
/// <summary>Imperative — the dialog continues immediately after this action is processed.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Deliberate no-op: the tint is declarative data for background-rendering nodes, not applied here.</summary>
public override void DoRun(DialogRuntime runtime)
{
}
}
}
+48 -48
View File
@@ -1,5 +1,5 @@
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -8,49 +8,49 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Waits for a fixed duration. When HiddenMode is true, hides the dialog
/// body for the duration (for dramatic pauses or cutscene beats). ShowText,
/// if set, displays a temporary message during the wait. DoDestruct is a
/// no-op because body visibility is implicitly restored on next Show.
/// </summary>
public class ActionDelay : ActionCommand
{
/// <summary>When true, hides the dialog body for the duration of the wait (dramatic pauses, cutscene beats).</summary>
public bool HiddenMode { get; set; }
/// <summary>Optional temporary text displayed while waiting. Set to null to keep the current dialog text.</summary>
public string ShowText { get; set; }
/// <summary>Pauses the dialog until <see cref="WaitTime"/> elapses.</summary>
public override WaitType WaitType { get; set; } = WaitType.WaitTime;
/// <summary>Duration of the pause in seconds. Default 1.0.</summary>
public override float WaitTime { get; set; } = 1f;
/// <summary>Shows the optional <see cref="ShowText"/> and, in <see cref="HiddenMode"/>, hides the dialog body for the pause duration.</summary>
public override void DoRun(DialogRuntime runtime)
{
var dialogBox = runtime.DialogBox;
if (dialogBox == null)
return;
if (ShowText != null)
dialogBox.SetText(ShowText);
if (HiddenMode)
dialogBox.Body.SetDeferred("visible", false);
}
/// <summary>No-op: the dialog body hidden by <see cref="HiddenMode"/> is restored implicitly by the next show.</summary>
public override void DoDestruct()
{
base.DoDestruct();
if (HiddenMode)
{
// Body restored on next Show
}
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Waits for a fixed duration. When HiddenMode is true, hides the dialog
/// body for the duration (for dramatic pauses or cutscene beats). ShowText,
/// if set, displays a temporary message during the wait. DoDestruct is a
/// no-op because body visibility is implicitly restored on next Show.
/// </summary>
public class ActionDelay : ActionCommand
{
/// <summary>When true, hides the dialog body for the duration of the wait (dramatic pauses, cutscene beats).</summary>
public bool HiddenMode { get; set; }
/// <summary>Optional temporary text displayed while waiting. Set to null to keep the current dialog text.</summary>
public string ShowText { get; set; }
/// <summary>Pauses the dialog until <see cref="WaitTime"/> elapses.</summary>
public override WaitType WaitType { get; set; } = WaitType.WaitTime;
/// <summary>Duration of the pause in seconds. Default 1.0.</summary>
public override float WaitTime { get; set; } = 1f;
/// <summary>Shows the optional <see cref="ShowText"/> and, in <see cref="HiddenMode"/>, hides the dialog body for the pause duration.</summary>
public override void DoRun(DialogRuntime runtime)
{
var dialogBox = runtime.DialogBox;
if (dialogBox == null)
return;
if (ShowText != null)
dialogBox.SetText(ShowText);
if (HiddenMode)
dialogBox.Body.SetDeferred("visible", false);
}
/// <summary>No-op: the dialog body hidden by <see cref="HiddenMode"/> is restored implicitly by the next show.</summary>
public override void DoDestruct()
{
base.DoDestruct();
if (HiddenMode)
{
// Body restored on next Show
}
}
}
}
+21 -21
View File
@@ -1,5 +1,5 @@
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -8,22 +8,22 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// No-op placeholder action. Used as a labeled jump target (Point) for GoTo
/// commands — provides an addressable marker in the dialog sequence without
/// any visible effect. NoWait so the dialog skips through labels instantly.
/// </summary>
public class ActionEmpty : ActionCommand
{
/// <summary>Label actions skip immediately so the dialog doesn't pause on markers.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>No-op: the action exists only to carry the jump-target ID.</summary>
public override void DoRun(DialogRuntime runtime)
{
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// No-op placeholder action. Used as a labeled jump target (Point) for GoTo
/// commands — provides an addressable marker in the dialog sequence without
/// any visible effect. NoWait so the dialog skips through labels instantly.
/// </summary>
public class ActionEmpty : ActionCommand
{
/// <summary>Label actions skip immediately so the dialog doesn't pause on markers.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>No-op: the action exists only to carry the jump-target ID.</summary>
public override void DoRun(DialogRuntime runtime)
{
}
}
}
+22 -22
View File
@@ -1,5 +1,5 @@
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -8,23 +8,23 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Terminates the dialog queue immediately. Calls Runtime.End() which
/// destructs all remaining actions, processes the cleanup queue, hides
/// the dialog box, and fires the dialog-end event.
/// </summary>
public class ActionEnd : ActionCommand
{
/// <summary>Ends the dialog queue immediately — no pause, no return.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Terminates the queue via <see cref="DialogRuntime.End"/> — destructs remainders, runs cleanup, hides the box, fires the end event.</summary>
public override void DoRun(DialogRuntime runtime)
{
runtime.End();
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Terminates the dialog queue immediately. Calls Runtime.End() which
/// destructs all remaining actions, processes the cleanup queue, hides
/// the dialog box, and fires the dialog-end event.
/// </summary>
public class ActionEnd : ActionCommand
{
/// <summary>Ends the dialog queue immediately — no pause, no return.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Terminates the queue via <see cref="DialogRuntime.End"/> — destructs remainders, runs cleanup, hides the box, fires the end event.</summary>
public override void DoRun(DialogRuntime runtime)
{
runtime.End();
}
}
}
+25 -25
View File
@@ -1,5 +1,5 @@
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Mods.Dialog.Action;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -8,26 +8,26 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Unconditional jump to a labeled action in the dialog queue. NoWait so
/// the jump happens transparently. The target is resolved by action ID
/// (set via ActionCommand.SetID or the Point()/Empty() fluent methods).
/// </summary>
public class ActionGoTo : ActionCommand
{
/// <summary>Target action ID to jump to. Resolved by linear search through the dialog queue.</summary>
public string GoTo { get; set; }
/// <summary>Jump happens transparently — the dialog continues from the target without pausing.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Jumps the queue index to the action whose ID matches <see cref="GoTo"/>.</summary>
public override void DoRun(DialogRuntime runtime)
{
runtime.TryGoTo(GoTo);
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Unconditional jump to a labeled action in the dialog queue. NoWait so
/// the jump happens transparently. The target is resolved by action ID
/// (set via ActionCommand.SetID or the Point()/Empty() fluent methods).
/// </summary>
public class ActionGoTo : ActionCommand
{
/// <summary>Target action ID to jump to. Resolved by linear search through the dialog queue.</summary>
public string GoTo { get; set; }
/// <summary>Jump happens transparently — the dialog continues from the target without pausing.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Jumps the queue index to the action whose ID matches <see cref="GoTo"/>.</summary>
public override void DoRun(DialogRuntime runtime)
{
runtime.TryGoTo(GoTo);
}
}
}
+24 -24
View File
@@ -1,24 +1,24 @@
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Hides the dialog box. Used in cutscenes where UI chrome should be
/// temporarily hidden while animations or background transitions play.
/// Paired with ActionShowDialog to restore visibility.
/// </summary>
public class ActionHideDialog : ActionCommand
{
/// <summary>Hides the dialog immediately — the queue continues without pause.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Hides the dialog box chrome while keeping the queue running.</summary>
public override void DoRun(DialogRuntime runtime)
{
var dialogBox = runtime.DialogBox;
if (dialogBox == null)
return;
dialogBox.Visible = false;
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Hides the dialog box. Used in cutscenes where UI chrome should be
/// temporarily hidden while animations or background transitions play.
/// Paired with ActionShowDialog to restore visibility.
/// </summary>
public class ActionHideDialog : ActionCommand
{
/// <summary>Hides the dialog immediately — the queue continues without pause.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Hides the dialog box chrome while keeping the queue running.</summary>
public override void DoRun(DialogRuntime runtime)
{
var dialogBox = runtime.DialogBox;
if (dialogBox == null)
return;
dialogBox.Visible = false;
}
}
}
+40 -40
View File
@@ -1,40 +1,40 @@
using Cthangover.Mods.Time;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Applies static lights from a JSON string to the UiLightController.
/// An empty or null string clears all static lights. The JSON is deserialized
/// into LightDef objects with viewport-relative coordinates, which are then
/// converted to pixel positions. Supports up to 10 static lights plus the
/// player's dynamic lamp.
/// </summary>
public class ActionLightSet : ActionCommand
{
/// <summary>JSON string defining static light positions and properties. Empty or null clears all static lights.</summary>
public string LightsJson { get; set; }
/// <summary>Lights are set imperatively — the dialog continues immediately.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Clears static lights when <see cref="LightsJson"/> is empty, otherwise parses and applies the light definitions to the scene's <see cref="UiLightController"/>.</summary>
public override void DoRun(DialogRuntime runtime)
{
var controller = Scene.Find<UiLightController>("Lights");
if (controller == null)
return;
if (string.IsNullOrEmpty(LightsJson))
controller.ClearStaticLights();
else
controller.SetStaticLights(LightsJson);
}
}
}
using Cthangover.Mods.Time;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Applies static lights from a JSON string to the UiLightController.
/// An empty or null string clears all static lights. The JSON is deserialized
/// into LightDef objects with viewport-relative coordinates, which are then
/// converted to pixel positions. Supports up to 10 static lights plus the
/// player's dynamic lamp.
/// </summary>
public class ActionLightSet : ActionCommand
{
/// <summary>JSON string defining static light positions and properties. Empty or null clears all static lights.</summary>
public string LightsJson { get; set; }
/// <summary>Lights are set imperatively — the dialog continues immediately.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Clears static lights when <see cref="LightsJson"/> is empty, otherwise parses and applies the light definitions to the scene's <see cref="UiLightController"/>.</summary>
public override void DoRun(DialogRuntime runtime)
{
var controller = Scene.Find<UiLightController>("Lights");
if (controller == null)
return;
if (string.IsNullOrEmpty(LightsJson))
controller.ClearStaticLights();
else
controller.SetStaticLights(LightsJson);
}
}
}
@@ -1,33 +1,33 @@
using Cthangover.Mods.Dialog.Action;
using Cthangover.Mods.Time;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Toggles the light controller's time-of-day mode. When UseTime is false,
/// static lighting is used; when true, lighting responds to the in-game clock.
/// </summary>
public class ActionLightUseTime : ActionCommand
{
/// <summary>True = lights respond to in-game time of day; false = static lighting mode.</summary>
public bool UseTime { get; set; } = true;
/// <summary>Time mode toggle is instant — the dialog continues without pause.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Switches the scene's <see cref="UiLightController"/> between time-of-day lighting and static lights.</summary>
public override void DoRun(DialogRuntime runtime)
{
var controller = Scene.Find<UiLightController>("Lights");
if (controller != null)
controller.IsUseLight = UseTime;
}
}
}
using Cthangover.Mods.Dialog.Action;
using Cthangover.Mods.Time;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Toggles the light controller's time-of-day mode. When UseTime is false,
/// static lighting is used; when true, lighting responds to the in-game clock.
/// </summary>
public class ActionLightUseTime : ActionCommand
{
/// <summary>True = lights respond to in-game time of day; false = static lighting mode.</summary>
public bool UseTime { get; set; } = true;
/// <summary>Time mode toggle is instant — the dialog continues without pause.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Switches the scene's <see cref="UiLightController"/> between time-of-day lighting and static lights.</summary>
public override void DoRun(DialogRuntime runtime)
{
var controller = Scene.Find<UiLightController>("Lights");
if (controller != null)
controller.IsUseLight = UseTime;
}
}
}
+37 -37
View File
@@ -1,37 +1,37 @@
using Cthangover.Core.Audio;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Starts background music playback via IAudioService. Uses MusicType.Ambient
/// so the music layer is treated as atmospheric background rather than UI
/// feedback. If the same music track is already playing, the audio service handles
/// deduplication.
/// </summary>
public class ActionMusic : ActionCommand
{
/// <summary>Music track identifier resolved through the audio system. Empty strings are silently ignored.</summary>
public string Music { get; set; }
/// <summary>Music starts playing in the background — the dialog continues immediately.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Starts the named track as ambient background music through <see cref="IAudioService"/>; empty names are ignored.</summary>
public override void DoRun(DialogRuntime runtime)
{
if (string.IsNullOrEmpty(Music))
return;
var audioService = Scene.Find<Node>("AudioService") as IAudioService;
audioService?.PlayMusic(Music, MusicType.Ambient);
}
}
}
using Cthangover.Core.Audio;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Starts background music playback via IAudioService. Uses MusicType.Ambient
/// so the music layer is treated as atmospheric background rather than UI
/// feedback. If the same music track is already playing, the audio service handles
/// deduplication.
/// </summary>
public class ActionMusic : ActionCommand
{
/// <summary>Music track identifier resolved through the audio system. Empty strings are silently ignored.</summary>
public string Music { get; set; }
/// <summary>Music starts playing in the background — the dialog continues immediately.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Starts the named track as ambient background music through <see cref="IAudioService"/>; empty names are ignored.</summary>
public override void DoRun(DialogRuntime runtime)
{
if (string.IsNullOrEmpty(Music))
return;
var audioService = Scene.Find<Node>("AudioService") as IAudioService;
audioService?.PlayMusic(Music, MusicType.Ambient);
}
}
}
+29 -29
View File
@@ -1,29 +1,29 @@
using Cthangover.Core.Audio;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Pauses background music playback via IAudioService without stopping the
/// track. Can be resumed with ActionMusicPlay.
/// </summary>
public class ActionMusicPause : ActionCommand
{
/// <summary>Pause is instant — the dialog continues without waiting for audio acknowledgment.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Pauses the current music track without stopping it, so <see cref="ActionMusicPlay"/> can resume it.</summary>
public override void DoRun(DialogRuntime runtime)
{
var audioService = Scene.Find<Node>("AudioService") as IAudioService;
audioService?.PauseMusic(true);
}
}
}
using Cthangover.Core.Audio;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Pauses background music playback via IAudioService without stopping the
/// track. Can be resumed with ActionMusicPlay.
/// </summary>
public class ActionMusicPause : ActionCommand
{
/// <summary>Pause is instant — the dialog continues without waiting for audio acknowledgment.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Pauses the current music track without stopping it, so <see cref="ActionMusicPlay"/> can resume it.</summary>
public override void DoRun(DialogRuntime runtime)
{
var audioService = Scene.Find<Node>("AudioService") as IAudioService;
audioService?.PauseMusic(true);
}
}
}
+28 -28
View File
@@ -1,28 +1,28 @@
using Cthangover.Core.Audio;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Resumes paused background music. Paired with ActionMusicPause.
/// </summary>
public class ActionMusicPlay : ActionCommand
{
/// <summary>Resume is instant — the dialog continues without waiting for audio.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Resumes music paused by <see cref="ActionMusicPause"/>.</summary>
public override void DoRun(DialogRuntime runtime)
{
var audioService = Scene.Find<Node>("AudioService") as IAudioService;
audioService?.PauseMusic(false);
}
}
}
using Cthangover.Core.Audio;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Resumes paused background music. Paired with ActionMusicPause.
/// </summary>
public class ActionMusicPlay : ActionCommand
{
/// <summary>Resume is instant — the dialog continues without waiting for audio.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Resumes music paused by <see cref="ActionMusicPause"/>.</summary>
public override void DoRun(DialogRuntime runtime)
{
var audioService = Scene.Find<Node>("AudioService") as IAudioService;
audioService?.PauseMusic(false);
}
}
}
+31 -31
View File
@@ -1,4 +1,4 @@
using Cthangover.Core.Utils;
using Cthangover.Core.Utils;
using Cthangover.Core.UI;
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Core.UI.Dialog;
@@ -7,33 +7,33 @@ using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Executes an arbitrary Action delegate inside the dialog queue.
/// Allows imperative code injection (e.g. quest state changes, UI toggles)
/// without creating a dedicated action class. NoWait so the queue advances
/// immediately after the delegate returns.
/// </summary>
public class ActionRun : ActionCommand
{
/// <summary>Arbitrary delegate executed during dialog sequencing. Null delegates are logged and skipped.</summary>
public System.Action Executable { get; set; }
/// <summary>The delegate runs and the dialog advances — no pausing.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Invokes <see cref="Executable"/>; a null delegate is logged and skipped so the queue keeps flowing.</summary>
public override void DoRun(DialogRuntime runtime)
{
if (Executable == null)
{
GameLogger.Log("DIALOG", "ActionRun: Executable delegate is null", LogLevel.Error);
return;
}
Executable();
}
}
}
namespace Cthangover.Mods.Dialog.Action.Impls
{
/// <summary>
/// Executes an arbitrary Action delegate inside the dialog queue.
/// Allows imperative code injection (e.g. quest state changes, UI toggles)
/// without creating a dedicated action class. NoWait so the queue advances
/// immediately after the delegate returns.
/// </summary>
public class ActionRun : ActionCommand
{
/// <summary>Arbitrary delegate executed during dialog sequencing. Null delegates are logged and skipped.</summary>
public System.Action Executable { get; set; }
/// <summary>The delegate runs and the dialog advances — no pausing.</summary>
public override WaitType WaitType { get; set; } = WaitType.NoWait;
/// <summary>Invokes <see cref="Executable"/>; a null delegate is logged and skipped so the queue keeps flowing.</summary>
public override void DoRun(DialogRuntime runtime)
{
if (Executable == null)
{
GameLogger.Log("DIALOG", "ActionRun: Executable delegate is null", LogLevel.Error);
return;
}
Executable();
}
}
}
+24 -24
View File
@@ -1,24 +1,24 @@
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Determines how the DialogRuntime advances past this action. NoWait chains
/// immediately to the next action (for imperative commands). WaitClick pauses
/// until user input (click/key). WaitSelect pauses for variant selection.
/// WaitTime pauses for a fixed duration. WaitEvent pauses until an external
/// event marks the action as destructed.
/// </summary>
public enum WaitType
{
/// <summary>Don't wait — the runtime advances to the next action immediately in the same Run call.</summary>
NoWait,
/// <summary>Pause until the player clicks or presses the accept key. Used by dialog text actions.</summary>
WaitClick,
/// <summary>Pause until the player selects a choice variant. Used by choice menus.</summary>
WaitSelect,
/// <summary>Pause for a fixed duration in seconds (<see cref="ActionCommand.WaitTime"/>).</summary>
WaitTime,
/// <summary>Pause until an external event marks the action as destructed (<see cref="ActionCommand.IsDestructed"/>).</summary>
WaitEvent,
}
}
namespace Cthangover.Mods.Dialog.Action
{
/// <summary>
/// Determines how the DialogRuntime advances past this action. NoWait chains
/// immediately to the next action (for imperative commands). WaitClick pauses
/// until user input (click/key). WaitSelect pauses for variant selection.
/// WaitTime pauses for a fixed duration. WaitEvent pauses until an external
/// event marks the action as destructed.
/// </summary>
public enum WaitType
{
/// <summary>Don't wait — the runtime advances to the next action immediately in the same Run call.</summary>
NoWait,
/// <summary>Pause until the player clicks or presses the accept key. Used by dialog text actions.</summary>
WaitClick,
/// <summary>Pause until the player selects a choice variant. Used by choice menus.</summary>
WaitSelect,
/// <summary>Pause for a fixed duration in seconds (<see cref="ActionCommand.WaitTime"/>).</summary>
WaitTime,
/// <summary>Pause until an external event marks the action as destructed (<see cref="ActionCommand.IsDestructed"/>).</summary>
WaitEvent,
}
}
+70 -70
View File
@@ -1,70 +1,70 @@
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Mods.Dialog.Action.Impls;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog
{
/// <summary>
/// Renders a single dialog choice option. Walks up the scene tree in OnReady
/// to find the nearest IDialogBox parent — this avoids coupling to a specific
/// dialog implementation and lets answer items work regardless of nesting depth.
/// On click, calls SelectVariant on the found dialog box, passing the bound
/// SelectVariant model (which carries the GoTo target and display text).
/// </summary>
public partial class AnswerItem : ListItem<SelectVariant>
{
[Export] private Label textField;
private DialogBox dialogBox;
/// <summary>Binds the choice button from the answer_item scene prefab and finds the owning dialog box by walking up the tree, so items work at any nesting depth.</summary>
protected override void OnReady()
{
textField ??= GetNode<Label>("Button/TextLabel");
var btn = GetNode<Button>("Button");
if (btn != null)
btn.Pressed += OnClick;
if (dialogBox == null)
{
var parent = GetParent();
while (parent != null)
{
if (parent is DialogBox db)
{
dialogBox = db;
break;
}
parent = parent.GetParent();
}
}
}
/// <summary>Binds the variant model and sets the button label text to <see cref="SelectVariant.Text"/>.</summary>
public override void Construct(SelectVariant variant)
{
base.Construct(variant);
textField.Text = variant.Text;
}
private void OnClick()
{
dialogBox?.SelectVariant(Model);
}
/// <summary>Required by <see cref="IListItem{TModel}"/>. Intentionally empty — the parent AnswerBox handles cleanup.</summary>
public override void Destruct()
{ }
}
}
using Cthangover.Mods.Interface.Base.Lists;
using Cthangover.Mods.Dialog.Action.Impls;
using Godot;
using Cthangover.Core.UI;
using Cthangover.Core.UI.Dialog;
using Cthangover.Core.UI.Event;
using Cthangover.Core.UI.Executable;
using Cthangover.Core.Scenarios;
using Cthangover.Core.Scenes;
using Cthangover.Core.Interactive;
namespace Cthangover.Mods.Dialog
{
/// <summary>
/// Renders a single dialog choice option. Walks up the scene tree in OnReady
/// to find the nearest IDialogBox parent — this avoids coupling to a specific
/// dialog implementation and lets answer items work regardless of nesting depth.
/// On click, calls SelectVariant on the found dialog box, passing the bound
/// SelectVariant model (which carries the GoTo target and display text).
/// </summary>
public partial class AnswerItem : ListItem<SelectVariant>
{
[Export] private Label textField;
private DialogBox dialogBox;
/// <summary>Binds the choice button from the answer_item scene prefab and finds the owning dialog box by walking up the tree, so items work at any nesting depth.</summary>
protected override void OnReady()
{
textField ??= GetNode<Label>("Button/TextLabel");
var btn = GetNode<Button>("Button");
if (btn != null)
btn.Pressed += OnClick;
if (dialogBox == null)
{
var parent = GetParent();
while (parent != null)
{
if (parent is DialogBox db)
{
dialogBox = db;
break;
}
parent = parent.GetParent();
}
}
}
/// <summary>Binds the variant model and sets the button label text to <see cref="SelectVariant.Text"/>.</summary>
public override void Construct(SelectVariant variant)
{
base.Construct(variant);
textField.Text = variant.Text;
}
private void OnClick()
{
dialogBox?.SelectVariant(Model);
}
/// <summary>Required by <see cref="IListItem{TModel}"/>. Intentionally empty — the parent AnswerBox handles cleanup.</summary>
public override void Destruct()
{ }
}
}
@@ -1,27 +1,27 @@
namespace Cthangover.Mods.Dialog.Executable
{
using Cthangover.Core.UI.Executable;
/// <summary>
/// Simplest IEventObject implementation: carries an ID and self-destructs
/// via QueueFree when Destruct() is called. Used as a base for scene objects
/// that must be tracked by the event system for cleanup.
/// </summary>
public partial class IdentifiableEventObjectBehaviour : Godot.Node, IEventObject
{
/// <summary>
/// Identifier for this event object. Set externally to allow the event
/// tracking system to locate and manage this instance.
/// </summary>
public string ID { get; private set; }
/// <summary>
/// Signals cleanup by calling <c>QueueFree</c> to remove this node from
/// the scene tree and release resources.
/// </summary>
public void Destruct()
{
QueueFree();
}
}
}
namespace Cthangover.Mods.Dialog.Executable
{
using Cthangover.Core.UI.Executable;
/// <summary>
/// Simplest IEventObject implementation: carries an ID and self-destructs
/// via QueueFree when Destruct() is called. Used as a base for scene objects
/// that must be tracked by the event system for cleanup.
/// </summary>
public partial class IdentifiableEventObjectBehaviour : Godot.Node, IEventObject
{
/// <summary>
/// Identifier for this event object. Set externally to allow the event
/// tracking system to locate and manage this instance.
/// </summary>
public string ID { get; private set; }
/// <summary>
/// Signals cleanup by calling <c>QueueFree</c> to remove this node from
/// the scene tree and release resources.
/// </summary>
public void Destruct()
{
QueueFree();
}
}
}