feat(demo): 改造 Lucky Dice 交互演示
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
"name": "FishDice.Demo",
|
||||
"rootNamespace": "FishDice.Demo",
|
||||
"references": [
|
||||
"FishDice.Runtime"
|
||||
"FishDice.Runtime",
|
||||
"UnityEngine.UI"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -1,142 +1,307 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using FishDice.LuckyDice;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace FishDice.Demo
|
||||
{
|
||||
public sealed class LuckyDiceDemoController : MonoBehaviour
|
||||
{
|
||||
private static readonly LuckyDiceDemoScenario[] Scenarios =
|
||||
{
|
||||
new LuckyDiceDemoScenario("Normal Reward", "Numbers pay the base reward.", 0, 1),
|
||||
new LuckyDiceDemoScenario("Clover Bonus", "A number plus Clover grants reward and bonus.", 0, 5),
|
||||
new LuckyDiceDemoScenario("Lucky Dice: Rocket", "Two Clovers enter Lucky Dice and resolve Slap Down.", 5, 5, 0),
|
||||
new LuckyDiceDemoScenario("Lucky Dice: Thief", "Two Clovers enter Lucky Dice and resolve Treasure Heist.", 5, 5, 1)
|
||||
};
|
||||
private static readonly string[] NormalPreviewFaces = { "2", "3", "4", "5", "6", "Clover" };
|
||||
private static readonly string[] LuckyPreviewFaces = { "Rocket", "Thief" };
|
||||
public const string BuiltinFontResourcePath = "LegacyRuntime.ttf";
|
||||
|
||||
private readonly List<LuckyDiceDemoSnapshot> _history = new List<LuckyDiceDemoSnapshot>();
|
||||
private Vector2 _scroll;
|
||||
private LuckyDiceDemoSnapshot _current;
|
||||
private GUIStyle _titleStyle;
|
||||
private GUIStyle _labelStyle;
|
||||
private GUIStyle _summaryStyle;
|
||||
private readonly SystemRandomSource _flowRandom = new SystemRandomSource(new System.Random());
|
||||
private Text _titleText;
|
||||
private Text _statusText;
|
||||
private Text _detailText;
|
||||
private Text _rewardText;
|
||||
private Text[] _normalDiceTexts;
|
||||
private Text[] _luckyDiceTexts;
|
||||
private Button _primaryButton;
|
||||
private Text _primaryButtonText;
|
||||
private Coroutine _flowRoutine;
|
||||
private LuckyDiceDemoSnapshot _lastSnapshot;
|
||||
private Font _uiFont;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
RunScenario(Scenarios[0]);
|
||||
BuildUi();
|
||||
ShowReady();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
private void StartRoll()
|
||||
{
|
||||
EnsureStyles();
|
||||
|
||||
var margin = 24f;
|
||||
var width = Mathf.Min(780f, Screen.width - margin * 2f);
|
||||
var height = Mathf.Min(620f, Screen.height - margin * 2f);
|
||||
GUILayout.BeginArea(new Rect(margin, margin, width, height), GUI.skin.box);
|
||||
GUILayout.Label("FishDice Lucky Dice Demo", _titleStyle);
|
||||
GUILayout.Label("Runtime path: normal roll -> combo facts -> rule actions -> optional Lucky Dice target mode.", _labelStyle);
|
||||
GUILayout.Space(10f);
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Random Roll", GUILayout.Height(34f)))
|
||||
if (_flowRoutine != null)
|
||||
{
|
||||
RunRandom();
|
||||
StopCoroutine(_flowRoutine);
|
||||
}
|
||||
|
||||
foreach (var scenario in Scenarios)
|
||||
{
|
||||
if (GUILayout.Button(scenario.Title, GUILayout.Height(34f)))
|
||||
{
|
||||
RunScenario(scenario);
|
||||
}
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(12f);
|
||||
DrawSnapshot(_current);
|
||||
GUILayout.Space(12f);
|
||||
DrawHistory();
|
||||
GUILayout.EndArea();
|
||||
_flowRoutine = StartCoroutine(PlayRollFlow());
|
||||
}
|
||||
|
||||
private void RunScenario(LuckyDiceDemoScenario scenario)
|
||||
private IEnumerator PlayRollFlow()
|
||||
{
|
||||
SetCurrent(LuckyDiceDemoRunner.RunScenario(scenario));
|
||||
_primaryButton.interactable = false;
|
||||
_primaryButtonText.text = "投掷中";
|
||||
_rewardText.text = string.Empty;
|
||||
_detailText.text = string.Empty;
|
||||
SetLuckyDiceVisible(false);
|
||||
SetStatus("摇动普通骰子");
|
||||
|
||||
_lastSnapshot = LuckyDiceDemoRunner.RunRandom(_flowRandom);
|
||||
yield return AnimateDice(_normalDiceTexts, NormalPreviewFaces, 0.9f);
|
||||
ApplyDiceTexts(_normalDiceTexts, _lastSnapshot.NormalFaces);
|
||||
SetStatus("组合判定");
|
||||
_detailText.text = _lastSnapshot.ComboLine;
|
||||
yield return new WaitForSeconds(0.55f);
|
||||
|
||||
if (_lastSnapshot.OutcomeKind == "lucky_dice")
|
||||
{
|
||||
SetStatus("触发 Lucky Dice");
|
||||
_rewardText.text = "双 Clover 命中";
|
||||
yield return new WaitForSeconds(0.45f);
|
||||
SetLuckyDiceVisible(true);
|
||||
SetStatus("揭示特殊骰子");
|
||||
yield return AnimateDice(_luckyDiceTexts, LuckyPreviewFaces, 1.0f);
|
||||
ApplyDiceTexts(_luckyDiceTexts, _lastSnapshot.LuckyDiceSlotKeys);
|
||||
}
|
||||
|
||||
private void RunRandom()
|
||||
{
|
||||
SetCurrent(LuckyDiceDemoRunner.RunRandom());
|
||||
ShowResult(_lastSnapshot);
|
||||
_flowRoutine = null;
|
||||
}
|
||||
|
||||
private void SetCurrent(LuckyDiceDemoSnapshot snapshot)
|
||||
private IEnumerator AnimateDice(Text[] diceTexts, string[] previewFaces, float duration)
|
||||
{
|
||||
_current = snapshot;
|
||||
_history.Insert(0, snapshot);
|
||||
if (_history.Count > 8)
|
||||
var elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
_history.RemoveAt(_history.Count - 1);
|
||||
for (var i = 0; i < diceTexts.Length; i++)
|
||||
{
|
||||
diceTexts[i].text = previewFaces[Random.Range(0, previewFaces.Length)];
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(0.08f);
|
||||
elapsed += 0.08f;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSnapshot(LuckyDiceDemoSnapshot snapshot)
|
||||
private void ShowReady()
|
||||
{
|
||||
if (snapshot == null)
|
||||
_titleText.text = "Lucky Dice";
|
||||
SetStatus("准备投骰");
|
||||
_detailText.text = "普通骰子会随机落点,命中双 Clover 后进入 Lucky Dice。";
|
||||
_rewardText.text = string.Empty;
|
||||
ApplyDiceTexts(_normalDiceTexts, new[] { "?", "?" });
|
||||
ApplyDiceTexts(_luckyDiceTexts, new[] { "?", "?", "?" });
|
||||
SetLuckyDiceVisible(false);
|
||||
_primaryButton.interactable = true;
|
||||
_primaryButtonText.text = "投骰";
|
||||
}
|
||||
|
||||
private void ShowResult(LuckyDiceDemoSnapshot snapshot)
|
||||
{
|
||||
SetStatus(ResolveResultStatus(snapshot));
|
||||
_detailText.text = $"{snapshot.FaceLine}\n{snapshot.RuleLine}\n{snapshot.EffectLine}";
|
||||
_rewardText.text = snapshot.TargetModeLine == "Target Mode: -"
|
||||
? snapshot.Summary
|
||||
: $"{snapshot.Summary}\n{snapshot.TargetModeLine}";
|
||||
_primaryButton.interactable = true;
|
||||
_primaryButtonText.text = "再投一次";
|
||||
}
|
||||
|
||||
private static string ResolveResultStatus(LuckyDiceDemoSnapshot snapshot)
|
||||
{
|
||||
switch (snapshot.OutcomeKind)
|
||||
{
|
||||
case "lucky_dice":
|
||||
return "进入目标玩法";
|
||||
case "clover_bonus":
|
||||
return "获得 Clover Bonus";
|
||||
case "normal_reward":
|
||||
return "获得普通奖励";
|
||||
default:
|
||||
return "本轮结束";
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildUi()
|
||||
{
|
||||
EnsureEventSystem();
|
||||
|
||||
var canvasObject = new GameObject("LuckyDiceCanvas");
|
||||
canvasObject.transform.SetParent(transform, false);
|
||||
var canvas = canvasObject.AddComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.pixelPerfect = true;
|
||||
var scaler = canvasObject.AddComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize;
|
||||
scaler.scaleFactor = 1f;
|
||||
scaler.referencePixelsPerUnit = 100f;
|
||||
canvasObject.AddComponent<GraphicRaycaster>();
|
||||
|
||||
var root = CreatePanel("Root", canvasObject.transform, new Color(0.06f, 0.09f, 0.13f, 1f));
|
||||
Stretch(root.rectTransform);
|
||||
|
||||
var board = CreatePanel("Board", root.transform, new Color(0.12f, 0.16f, 0.22f, 0.96f));
|
||||
Center(board.rectTransform, new Vector2(760f, 600f));
|
||||
|
||||
_titleText = CreateText("Title", board.transform, "Lucky Dice", 34, FontStyle.Bold, Color.white);
|
||||
SetRect(_titleText.rectTransform, new Vector2(0f, 194f), new Vector2(680f, 48f));
|
||||
|
||||
_statusText = CreateText("Status", board.transform, string.Empty, 24, FontStyle.Bold, new Color(1f, 0.84f, 0.38f));
|
||||
SetRect(_statusText.rectTransform, new Vector2(0f, 142f), new Vector2(680f, 40f));
|
||||
|
||||
_normalDiceTexts = new[]
|
||||
{
|
||||
CreateDiceText("NormalDiceA", board.transform, new Vector2(-96f, 64f), new Color(0.96f, 0.97f, 1f)),
|
||||
CreateDiceText("NormalDiceB", board.transform, new Vector2(96f, 64f), new Color(0.96f, 0.97f, 1f))
|
||||
};
|
||||
|
||||
_luckyDiceTexts = new[]
|
||||
{
|
||||
CreateDiceText("LuckySlotA", board.transform, new Vector2(-150f, -48f), new Color(1f, 0.86f, 0.46f)),
|
||||
CreateDiceText("LuckySlotB", board.transform, new Vector2(0f, -48f), new Color(1f, 0.86f, 0.46f)),
|
||||
CreateDiceText("LuckySlotC", board.transform, new Vector2(150f, -48f), new Color(1f, 0.86f, 0.46f))
|
||||
};
|
||||
|
||||
_detailText = CreateText("Detail", board.transform, string.Empty, 16, FontStyle.Normal, new Color(0.82f, 0.88f, 0.94f));
|
||||
SetRect(_detailText.rectTransform, new Vector2(0f, -142f), new Vector2(650f, 86f));
|
||||
|
||||
_rewardText = CreateText("Reward", board.transform, string.Empty, 19, FontStyle.Bold, new Color(0.55f, 0.92f, 0.75f));
|
||||
SetRect(_rewardText.rectTransform, new Vector2(0f, -210f), new Vector2(650f, 56f));
|
||||
|
||||
_primaryButton = CreateButton("PrimaryButton", board.transform, "投骰", new Vector2(0f, -254f), new Vector2(190f, 48f));
|
||||
_primaryButton.onClick.AddListener(StartRoll);
|
||||
}
|
||||
|
||||
private static void EnsureEventSystem()
|
||||
{
|
||||
if (FindObjectOfType<EventSystem>() != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GUILayout.Label(snapshot.Title, _summaryStyle);
|
||||
GUILayout.Label(snapshot.Description, _labelStyle);
|
||||
GUILayout.Space(6f);
|
||||
GUILayout.Label(snapshot.FaceLine, _labelStyle);
|
||||
GUILayout.Label(snapshot.ComboLine, _labelStyle);
|
||||
GUILayout.Label(snapshot.RuleLine, _labelStyle);
|
||||
GUILayout.Label(snapshot.EffectLine, _labelStyle);
|
||||
GUILayout.Label(snapshot.LuckyDiceLine, _labelStyle);
|
||||
GUILayout.Label(snapshot.TargetModeLine, _labelStyle);
|
||||
GUILayout.Space(6f);
|
||||
GUILayout.Label(snapshot.Summary, _summaryStyle);
|
||||
var eventSystemObject = new GameObject("EventSystem");
|
||||
eventSystemObject.AddComponent<EventSystem>();
|
||||
eventSystemObject.AddComponent<StandaloneInputModule>();
|
||||
}
|
||||
|
||||
private void DrawHistory()
|
||||
private Text CreateDiceText(string name, Transform parent, Vector2 anchoredPosition, Color faceColor)
|
||||
{
|
||||
GUILayout.Label("Recent Rolls", _summaryStyle);
|
||||
_scroll = GUILayout.BeginScrollView(_scroll, GUILayout.Height(180f));
|
||||
foreach (var snapshot in _history)
|
||||
{
|
||||
GUILayout.Label($"{snapshot.Title} | {snapshot.FaceLine} | {snapshot.Summary}", _labelStyle);
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
var background = CreatePanel(name, parent, new Color(0.2f, 0.25f, 0.33f, 1f));
|
||||
SetRect(background.rectTransform, anchoredPosition, new Vector2(116f, 84f));
|
||||
|
||||
var text = CreateText(name + "Text", background.transform, "?", 24, FontStyle.Bold, faceColor);
|
||||
Stretch(text.rectTransform);
|
||||
return text;
|
||||
}
|
||||
|
||||
private void EnsureStyles()
|
||||
private Button CreateButton(string name, Transform parent, string label, Vector2 anchoredPosition, Vector2 size)
|
||||
{
|
||||
if (_titleStyle != null)
|
||||
{
|
||||
return;
|
||||
var image = CreatePanel(name, parent, new Color(0.92f, 0.56f, 0.16f, 1f));
|
||||
SetRect(image.rectTransform, anchoredPosition, size);
|
||||
var button = image.gameObject.AddComponent<Button>();
|
||||
_primaryButtonText = CreateText(name + "Text", image.transform, label, 20, FontStyle.Bold, Color.white);
|
||||
Stretch(_primaryButtonText.rectTransform);
|
||||
return button;
|
||||
}
|
||||
|
||||
_titleStyle = new GUIStyle(GUI.skin.label)
|
||||
private Image CreatePanel(string name, Transform parent, Color color)
|
||||
{
|
||||
fontSize = 26,
|
||||
fontStyle = FontStyle.Bold,
|
||||
normal = { textColor = Color.white },
|
||||
wordWrap = true
|
||||
};
|
||||
_labelStyle = new GUIStyle(GUI.skin.label)
|
||||
var gameObject = new GameObject(name, typeof(RectTransform), typeof(Image));
|
||||
gameObject.transform.SetParent(parent, false);
|
||||
var image = gameObject.GetComponent<Image>();
|
||||
image.color = color;
|
||||
return image;
|
||||
}
|
||||
|
||||
private Text CreateText(string name, Transform parent, string text, int fontSize, FontStyle fontStyle, Color color)
|
||||
{
|
||||
fontSize = 15,
|
||||
normal = { textColor = new Color(0.86f, 0.9f, 0.95f) },
|
||||
wordWrap = true
|
||||
};
|
||||
_summaryStyle = new GUIStyle(GUI.skin.label)
|
||||
var gameObject = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(Text));
|
||||
gameObject.transform.SetParent(parent, false);
|
||||
var label = gameObject.GetComponent<Text>();
|
||||
label.font = GetUiFont();
|
||||
label.text = text;
|
||||
label.fontSize = fontSize;
|
||||
label.fontStyle = fontStyle;
|
||||
label.color = color;
|
||||
label.alignment = TextAnchor.MiddleCenter;
|
||||
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
label.verticalOverflow = VerticalWrapMode.Overflow;
|
||||
label.alignByGeometry = true;
|
||||
label.raycastTarget = false;
|
||||
return label;
|
||||
}
|
||||
|
||||
private Font GetUiFont()
|
||||
{
|
||||
fontSize = 18,
|
||||
fontStyle = FontStyle.Bold,
|
||||
normal = { textColor = new Color(1f, 0.86f, 0.35f) },
|
||||
wordWrap = true
|
||||
};
|
||||
if (_uiFont == null)
|
||||
{
|
||||
_uiFont = Resources.GetBuiltinResource<Font>(BuiltinFontResourcePath);
|
||||
}
|
||||
|
||||
return _uiFont;
|
||||
}
|
||||
|
||||
private void SetStatus(string text)
|
||||
{
|
||||
_statusText.text = text;
|
||||
}
|
||||
|
||||
private void ApplyDiceTexts(Text[] diceTexts, string[] values)
|
||||
{
|
||||
for (var i = 0; i < diceTexts.Length; i++)
|
||||
{
|
||||
diceTexts[i].text = i < values.Length ? FormatFace(values[i]) : "-";
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatFace(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
return char.ToUpperInvariant(value[0]) + value.Substring(1);
|
||||
}
|
||||
|
||||
private void SetLuckyDiceVisible(bool visible)
|
||||
{
|
||||
foreach (var text in _luckyDiceTexts)
|
||||
{
|
||||
text.transform.parent.gameObject.SetActive(visible);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Center(RectTransform rectTransform, Vector2 size)
|
||||
{
|
||||
rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.pivot = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.sizeDelta = size;
|
||||
rectTransform.anchoredPosition = Vector2.zero;
|
||||
}
|
||||
|
||||
private static void SetRect(RectTransform rectTransform, Vector2 position, Vector2 size)
|
||||
{
|
||||
rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.pivot = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.sizeDelta = size;
|
||||
rectTransform.anchoredPosition = position;
|
||||
}
|
||||
|
||||
private static void Stretch(RectTransform rectTransform)
|
||||
{
|
||||
rectTransform.anchorMin = Vector2.zero;
|
||||
rectTransform.anchorMax = Vector2.one;
|
||||
rectTransform.offsetMin = Vector2.zero;
|
||||
rectTransform.offsetMax = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,15 @@ namespace FishDice.Demo
|
||||
return Run(scenario, new SystemRandomSource());
|
||||
}
|
||||
|
||||
public static LuckyDiceDemoSnapshot RunRandom(IRandomSource random)
|
||||
{
|
||||
var scenario = new LuckyDiceDemoScenario(
|
||||
"Random Roll",
|
||||
"Uses the default FishDice runtime config and the supplied random source.");
|
||||
|
||||
return Run(scenario, random);
|
||||
}
|
||||
|
||||
private static LuckyDiceDemoSnapshot Run(LuckyDiceDemoScenario scenario, IRandomSource random)
|
||||
{
|
||||
var flow = LuckyDiceRuntimeFactory.CreateDefault(random).CreateDefaultFlow();
|
||||
@@ -43,6 +52,11 @@ namespace FishDice.Demo
|
||||
var luckyDiceLine = FormatLuckyDice(result.LuckyDiceResult);
|
||||
var targetModeLine = "Target Mode: " + (result.TargetMode == null ? "-" : result.TargetMode.ModeKey);
|
||||
var summary = FormatSummary(result);
|
||||
var normalFaces = result.RollResult.Faces.Select(face => face.Key).ToArray();
|
||||
var luckyDiceSlots = result.LuckyDiceResult == null || result.LuckyDiceResult.SlotResultKeys == null
|
||||
? new string[0]
|
||||
: result.LuckyDiceResult.SlotResultKeys.ToArray();
|
||||
var outcomeKind = ResolveOutcomeKind(result);
|
||||
|
||||
return new LuckyDiceDemoSnapshot(
|
||||
scenario.Title,
|
||||
@@ -53,7 +67,10 @@ namespace FishDice.Demo
|
||||
effectLine,
|
||||
luckyDiceLine,
|
||||
targetModeLine,
|
||||
summary);
|
||||
summary,
|
||||
normalFaces,
|
||||
luckyDiceSlots,
|
||||
outcomeKind);
|
||||
}
|
||||
|
||||
private static string FormatLuckyDice(LuckyDiceSelectionResult result)
|
||||
@@ -86,6 +103,26 @@ namespace FishDice.Demo
|
||||
return "No configured outcome.";
|
||||
}
|
||||
|
||||
private static string ResolveOutcomeKind(RollFlowResult result)
|
||||
{
|
||||
if (result.TargetMode != null)
|
||||
{
|
||||
return "lucky_dice";
|
||||
}
|
||||
|
||||
if (result.Effects.OfType<MultiplierEffect>().Any())
|
||||
{
|
||||
return "clover_bonus";
|
||||
}
|
||||
|
||||
if (result.Effects.OfType<RewardEffect>().Any())
|
||||
{
|
||||
return "normal_reward";
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
private static string JoinOrDash(IEnumerable<string> values)
|
||||
{
|
||||
var materialized = values.Where(value => !string.IsNullOrEmpty(value)).ToArray();
|
||||
|
||||
@@ -11,7 +11,10 @@ namespace FishDice.Demo
|
||||
string effectLine,
|
||||
string luckyDiceLine,
|
||||
string targetModeLine,
|
||||
string summary)
|
||||
string summary,
|
||||
string[] normalFaces,
|
||||
string[] luckyDiceSlotKeys,
|
||||
string outcomeKind)
|
||||
{
|
||||
Title = title;
|
||||
Description = description;
|
||||
@@ -22,6 +25,9 @@ namespace FishDice.Demo
|
||||
LuckyDiceLine = luckyDiceLine;
|
||||
TargetModeLine = targetModeLine;
|
||||
Summary = summary;
|
||||
NormalFaces = normalFaces ?? new string[0];
|
||||
LuckyDiceSlotKeys = luckyDiceSlotKeys ?? new string[0];
|
||||
OutcomeKind = string.IsNullOrEmpty(outcomeKind) ? "none" : outcomeKind;
|
||||
}
|
||||
|
||||
public string Title { get; }
|
||||
@@ -41,5 +47,11 @@ namespace FishDice.Demo
|
||||
public string TargetModeLine { get; }
|
||||
|
||||
public string Summary { get; }
|
||||
|
||||
public string[] NormalFaces { get; }
|
||||
|
||||
public string[] LuckyDiceSlotKeys { get; }
|
||||
|
||||
public string OutcomeKind { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,28 @@ namespace FishDice.Tests.LuckyDice
|
||||
Assert.That(snapshot.LuckyDiceLine, Is.EqualTo("Lucky Dice: rocket x3"));
|
||||
Assert.That(snapshot.TargetModeLine, Is.EqualTo("Target Mode: slap_down_normal"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DemoRunner_exposes_structured_faces_for_player_ui_flow()
|
||||
{
|
||||
var normal = LuckyDiceDemoRunner.RunScenario(
|
||||
new LuckyDiceDemoScenario("Normal Reward", "Numbers pay the base reward.", 0, 1));
|
||||
var lucky = LuckyDiceDemoRunner.RunScenario(
|
||||
new LuckyDiceDemoScenario("Lucky Dice", "Clover pair enters the special dice flow.", 5, 5, 0));
|
||||
|
||||
Assert.That(normal.NormalFaces, Is.EqualTo(new[] { "2", "3" }));
|
||||
Assert.That(normal.LuckyDiceSlotKeys, Is.Empty);
|
||||
Assert.That(normal.OutcomeKind, Is.EqualTo("normal_reward"));
|
||||
|
||||
Assert.That(lucky.NormalFaces, Is.EqualTo(new[] { "clover", "clover" }));
|
||||
Assert.That(lucky.LuckyDiceSlotKeys, Is.EqualTo(new[] { "rocket", "rocket", "rocket" }));
|
||||
Assert.That(lucky.OutcomeKind, Is.EqualTo("lucky_dice"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DemoController_uses_current_unity_builtin_font_for_player_ui_text()
|
||||
{
|
||||
Assert.That(LuckyDiceDemoController.BuiltinFontResourcePath, Is.EqualTo("LegacyRuntime.ttf"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user