mirror of
https://github.com/milimoe/FunGame-Testing.git
synced 2025-04-22 12:19:34 +08:00
添加视觉小说编辑器
This commit is contained in:
parent
e24346bf57
commit
7ff4b56444
8
Desktop/App.xaml
Normal file
8
Desktop/App.xaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<Application x:Class="Milimoe.FunGame.Testing.Desktop.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
StartupUri="Solutions/NovelEditor/NovelEditor.xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
12
Desktop/App.xaml.cs
Normal file
12
Desktop/App.xaml.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Application = System.Windows.Application;
|
||||||
|
|
||||||
|
namespace Milimoe.FunGame.Testing.Desktop
|
||||||
|
{
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<BaseOutputPath>..\bin\</BaseOutputPath>
|
<BaseOutputPath>..\bin\</BaseOutputPath>
|
||||||
<RootNamespace>Milimoe.$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
|
<RootNamespace>Milimoe.$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
|
||||||
|
<UseWPF>True</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@ -22,6 +23,10 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="App.xaml" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="FunGame.Core">
|
<Reference Include="FunGame.Core">
|
||||||
<HintPath>..\..\FunGame.Core\bin\Debug\net9.0\FunGame.Core.dll</HintPath>
|
<HintPath>..\..\FunGame.Core\bin\Debug\net9.0\FunGame.Core.dll</HintPath>
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
using Milimoe.FunGame.Testing.Desktop.Solutions;
|
//using Milimoe.FunGame.Testing.Desktop.Solutions;
|
||||||
|
|
||||||
namespace Desktop
|
//namespace Desktop
|
||||||
{
|
//{
|
||||||
internal static class Program
|
// internal static class Program
|
||||||
{
|
// {
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// The main entry point for the application.
|
// /// The main entry point for the application.
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
[STAThread]
|
// [STAThread]
|
||||||
static void Main()
|
// static void Main()
|
||||||
{
|
// {
|
||||||
// To customize application configuration such as set high DPI settings or default font,
|
// // To customize application configuration such as set high DPI settings or default font,
|
||||||
// see https://aka.ms/applicationconfiguration.
|
// // see https://aka.ms/applicationconfiguration.
|
||||||
ApplicationConfiguration.Initialize();
|
// ApplicationConfiguration.Initialize();
|
||||||
//Application.Run(new ChessBoardExample.ChessBoardExample());
|
// //Application.Run(new ChessBoardExample.ChessBoardExample());
|
||||||
Application.Run(new EntityEditor());
|
// Application.Run(new EntityEditor());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
89
Desktop/Solutions/NovelEditor/NovelEditor.xaml
Normal file
89
Desktop/Solutions/NovelEditor/NovelEditor.xaml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<Window x:Class="Milimoe.FunGame.Testing.Desktop.Solutions.NovelEditor.NovelEditor"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:Milimoe.FunGame.Testing.Desktop.Solutions.NovelEditor"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="NovelEditor" Height="450" Width="800"
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="200"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- 左侧:节点列表和操作按钮 -->
|
||||||
|
<StackPanel Grid.Column="0" Margin="10">
|
||||||
|
<Button Content="添加节点" Click="AddNodeButton_Click" Margin="0,0,0,10"/>
|
||||||
|
<Button Content="编辑节点" Click="EditNodeButton_Click" Margin="0,0,0,10"/>
|
||||||
|
<ListBox x:Name="NodeListBox" SelectionChanged="NodeListBox_SelectionChanged" d:ItemsSource="{d:SampleData ItemCount=5}">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding Key}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- 右侧:节点详情 -->
|
||||||
|
<ScrollViewer Grid.Column="1" Margin="10">
|
||||||
|
<StackPanel Grid.Column="1" Margin="10">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Text="节点详情" FontSize="16" FontWeight="Bold" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
|
<!-- 导航按钮 -->
|
||||||
|
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
|
<Button Content="上一个" Click="PreviousSentence_Click" Margin="5,0,0,0" Width="80"/>
|
||||||
|
<Button Content="下一个" Click="NextSentence_Click" Margin="5,0,0,0" Width="80"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock x:Name="NodeKeyText" Margin="0,8,0,0" LineHeight="20" />
|
||||||
|
<TextBlock x:Name="NodeNameText" Margin="0,8,0,0" LineHeight="20" />
|
||||||
|
<TextBlock x:Name="NodeContentText" Margin="0,8,0,0" TextWrapping="Wrap" LineHeight="20"/>
|
||||||
|
|
||||||
|
<!-- 显示条件 -->
|
||||||
|
<TextBlock Text="显示条件" FontSize="14" FontWeight="Bold" Margin="0,10,0,0"/>
|
||||||
|
<TextBlock x:Name="NodeConditionsText" Margin="0,5,0,0" TextWrapping="Wrap" LineHeight="20" />
|
||||||
|
|
||||||
|
<!-- 选项 -->
|
||||||
|
<TextBlock Text="选项" FontSize="14" FontWeight="Bold" Margin="0,10,0,0"/>
|
||||||
|
<ListBox x:Name="OptionsListBox" d:ItemsSource="{d:SampleData ItemCount=5}" HorizontalContentAlignment="Stretch">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Width="auto">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<!-- 使用 ItemsControl 为每个 TargetNode 创建一个按钮 -->
|
||||||
|
<ItemsControl Grid.Column="1" ItemsSource="{Binding Targets}" HorizontalAlignment="Right">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<DockPanel LastChildFill="False" HorizontalAlignment="Right"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Button Content="{Binding Key}" Click="OptionButton_Click" Tag="{Binding}" Margin="5" Width="80" DockPanel.Dock="Right"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
<StackPanel Grid.Column="0">
|
||||||
|
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
|
||||||
|
<TextBlock Text="{Binding Conditions}" Margin="10,0,0,0" TextWrapping="Wrap" Foreground="Gray"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
218
Desktop/Solutions/NovelEditor/NovelEditor.xaml.cs
Normal file
218
Desktop/Solutions/NovelEditor/NovelEditor.xaml.cs
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
|
using Milimoe.FunGame.Core.Entity;
|
||||||
|
using Milimoe.FunGame.Core.Model;
|
||||||
|
using Button = System.Windows.Controls.Button;
|
||||||
|
using MessageBox = System.Windows.MessageBox;
|
||||||
|
|
||||||
|
namespace Milimoe.FunGame.Testing.Desktop.Solutions.NovelEditor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// NovelEditor.xaml 的交互逻辑
|
||||||
|
/// </summary>
|
||||||
|
public partial class NovelEditor : Window
|
||||||
|
{
|
||||||
|
public static Dictionary<Character, int> Likability { get; } = [];
|
||||||
|
public static Dictionary<string, Func<bool>> Conditions { get; } = [];
|
||||||
|
public static Character MainCharacter { get; set; } = Factory.GetCharacter();
|
||||||
|
public static Character 马猴烧酒 { get; set; } = Factory.GetCharacter();
|
||||||
|
|
||||||
|
private readonly NovelConfig _config;
|
||||||
|
|
||||||
|
public NovelEditor()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
MainCharacter.Name = "主角";
|
||||||
|
MainCharacter.NickName = "主角";
|
||||||
|
马猴烧酒.Name = "马猴烧酒";
|
||||||
|
马猴烧酒.NickName = "魔法少女";
|
||||||
|
Likability.Add(马猴烧酒, 100);
|
||||||
|
|
||||||
|
Conditions.Add("马猴烧酒的好感度低于50", () => 好感度低于50(马猴烧酒));
|
||||||
|
Conditions.Add("主角攻击力大于20", () => 攻击力大于20(MainCharacter));
|
||||||
|
Conditions.Add("马猴烧酒攻击力大于20", () => 攻击力大于20(马猴烧酒));
|
||||||
|
|
||||||
|
// 如果需要,初始化小说
|
||||||
|
//NovelTest.CreateNovels();
|
||||||
|
|
||||||
|
// 小说配置
|
||||||
|
_config = new NovelConfig("novel1", "chapter1");
|
||||||
|
LoadNovelData();
|
||||||
|
|
||||||
|
// 绑定节点列表
|
||||||
|
NodeListBox.ItemsSource = _config.Values;
|
||||||
|
if (_config.Count > 0)
|
||||||
|
{
|
||||||
|
NodeListBox.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadNovelData()
|
||||||
|
{
|
||||||
|
// 加载已有的小说数据
|
||||||
|
_config.LoadConfig(Conditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NodeListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (NodeListBox.SelectedItem is NovelNode selectedNode)
|
||||||
|
{
|
||||||
|
// 显示节点详情
|
||||||
|
NodeKeyText.Text = "编号:" + selectedNode.Key;
|
||||||
|
NodeNameText.Text = "角色:" + selectedNode.Name;
|
||||||
|
NodeContentText.Text = "文本:" + selectedNode.Content;
|
||||||
|
|
||||||
|
// 显示节点的显示条件
|
||||||
|
NodeConditionsText.Text = FormatConditions(selectedNode);
|
||||||
|
|
||||||
|
// 显示选项
|
||||||
|
OptionsListBox.ItemsSource = selectedNode.Options.Select(option => new
|
||||||
|
{
|
||||||
|
option.Name,
|
||||||
|
option.Targets,
|
||||||
|
Conditions = FormatOptionConditions(option)
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void PreviousSentence_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (NodeListBox.SelectedItem is NovelNode selectedNode)
|
||||||
|
{
|
||||||
|
if (selectedNode.Previous is null)
|
||||||
|
{
|
||||||
|
if (NodeListBox.SelectedIndex - 1 >= 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show("此节点没有定义上一个节点!现在跳转列表的上一个节点。");
|
||||||
|
NodeListBox.SelectedIndex--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox.Show("此节点没有定义上一个节点,并且已经达到列表顶部!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NodeListBox.SelectedItem = selectedNode.Previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NextSentence_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (NodeListBox.SelectedItem is NovelNode selectedNode)
|
||||||
|
{
|
||||||
|
NovelNode? next = selectedNode.Next;
|
||||||
|
if (next is null)
|
||||||
|
{
|
||||||
|
if (NodeListBox.SelectedIndex + 1 < NodeListBox.Items.Count)
|
||||||
|
{
|
||||||
|
MessageBox.Show("此节点没有定义下一个节点!现在跳转列表的下一个节点。");
|
||||||
|
NodeListBox.SelectedIndex++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox.Show("此节点没有定义下一个节点,并且已经到达列表底部!现在跳转到列表的起始处。");
|
||||||
|
NodeListBox.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NodeListBox.SelectedItem = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatConditions(NovelNode node)
|
||||||
|
{
|
||||||
|
List<string> conditions = [];
|
||||||
|
|
||||||
|
if (node.AndPredicates.Count != 0)
|
||||||
|
{
|
||||||
|
conditions.Add("需满足以下所有条件:");
|
||||||
|
foreach (string condition in node.AndPredicates.Keys)
|
||||||
|
{
|
||||||
|
conditions.Add($"- {condition}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.OrPredicates.Count != 0)
|
||||||
|
{
|
||||||
|
conditions.Add("需满足以下任意一个条件:");
|
||||||
|
foreach (string condition in node.OrPredicates.Keys)
|
||||||
|
{
|
||||||
|
conditions.Add($"- {condition}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conditions.Count != 0 ? string.Join(Environment.NewLine, conditions) : "无显示条件";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatOptionConditions(NovelOption option)
|
||||||
|
{
|
||||||
|
List<string> conditions = [];
|
||||||
|
|
||||||
|
if (option.AndPredicates.Count != 0)
|
||||||
|
{
|
||||||
|
conditions.Add("需满足以下所有条件:");
|
||||||
|
foreach (string condition in option.AndPredicates.Keys)
|
||||||
|
{
|
||||||
|
conditions.Add($"- {condition}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option.OrPredicates.Count != 0)
|
||||||
|
{
|
||||||
|
conditions.Add("需满足以下任意一个条件:");
|
||||||
|
foreach (string condition in option.OrPredicates.Keys)
|
||||||
|
{
|
||||||
|
conditions.Add($"- {condition}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conditions.Count != 0 ? string.Join(Environment.NewLine, conditions) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddNodeButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
NovelNode newNode = new()
|
||||||
|
{
|
||||||
|
Key = "示例节点编号",
|
||||||
|
Name = "示例发言人",
|
||||||
|
Content = "示例发言内容"
|
||||||
|
};
|
||||||
|
|
||||||
|
_config.Add(newNode.Key, newNode);
|
||||||
|
NodeListBox.Items.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditNodeButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (NodeListBox.SelectedItem is NovelNode selectedNode)
|
||||||
|
{
|
||||||
|
selectedNode.Content = "此示例节点已被编辑";
|
||||||
|
NodeContentText.Text = "文本:" + selectedNode.Content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OptionButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is Button button && button.Tag is NovelNode node && NodeListBox.Items.OfType<NovelNode>().FirstOrDefault(n => n.Key == node.Key) is NovelNode target)
|
||||||
|
{
|
||||||
|
NodeListBox.SelectedItem = target;
|
||||||
|
NodeListBox.ScrollIntoView(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool 攻击力大于20(Character character)
|
||||||
|
{
|
||||||
|
return character.ATK > 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool 好感度低于50(Character character)
|
||||||
|
{
|
||||||
|
return Likability[character] > 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
Desktop/Solutions/NovelEditor/NovelTest.cs
Normal file
104
Desktop/Solutions/NovelEditor/NovelTest.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
|
using Milimoe.FunGame.Core.Model;
|
||||||
|
|
||||||
|
namespace Milimoe.FunGame.Testing.Desktop.Solutions.NovelEditor
|
||||||
|
{
|
||||||
|
internal class NovelTest
|
||||||
|
{
|
||||||
|
internal static void CreateNovels()
|
||||||
|
{
|
||||||
|
NovelNode node1 = new()
|
||||||
|
{
|
||||||
|
Key = "node1",
|
||||||
|
Name = "声音",
|
||||||
|
Content = "听说你在等我?我来了!"
|
||||||
|
};
|
||||||
|
NovelNode node2 = new()
|
||||||
|
{
|
||||||
|
Key = "node2",
|
||||||
|
Name = NovelEditor.MainCharacter.NickName,
|
||||||
|
Content = "什么人!"
|
||||||
|
};
|
||||||
|
node1.NextNodes.Add(node2);
|
||||||
|
node2.Previous = node1;
|
||||||
|
NovelOption option1 = new()
|
||||||
|
{
|
||||||
|
Key = "option1",
|
||||||
|
Name = "你好。"
|
||||||
|
};
|
||||||
|
NovelOption option2 = new()
|
||||||
|
{
|
||||||
|
Key = "option2",
|
||||||
|
Name = "我不认识你。",
|
||||||
|
AndPredicates = new()
|
||||||
|
{
|
||||||
|
{ "主角攻击力大于20", NovelEditor.Conditions["主角攻击力大于20"] }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NovelNode node3 = new()
|
||||||
|
{
|
||||||
|
Key = "node3",
|
||||||
|
Name = NovelEditor.马猴烧酒.NickName,
|
||||||
|
Content = "你好,我叫【马猴烧酒】!",
|
||||||
|
Options = [option1, option2]
|
||||||
|
};
|
||||||
|
NovelNode node4 = new()
|
||||||
|
{
|
||||||
|
Key = "node4",
|
||||||
|
Name = NovelEditor.马猴烧酒.NickName,
|
||||||
|
Content = "你的名字是?"
|
||||||
|
};
|
||||||
|
NovelNode node5 = new()
|
||||||
|
{
|
||||||
|
Key = "node5",
|
||||||
|
Name = NovelEditor.马猴烧酒.NickName,
|
||||||
|
Content = "滚,谁要认识你?"
|
||||||
|
};
|
||||||
|
node2.NextNodes.Add(node3);
|
||||||
|
option1.Targets.Add(node4);
|
||||||
|
option2.Targets.Add(node5);
|
||||||
|
NovelNode node6 = new()
|
||||||
|
{
|
||||||
|
Key = "node6",
|
||||||
|
Content = "旁白:示例结束。"
|
||||||
|
};
|
||||||
|
NovelOption option3 = new()
|
||||||
|
{
|
||||||
|
Key = "option3",
|
||||||
|
Name = "重新开始游戏",
|
||||||
|
Targets = [node1]
|
||||||
|
};
|
||||||
|
NovelNode node7 = new()
|
||||||
|
{
|
||||||
|
Key = "node7",
|
||||||
|
Priority = 2,
|
||||||
|
Content = "旁白:示例结束,你被马猴烧酒吃掉了。",
|
||||||
|
Options = [option3],
|
||||||
|
AndPredicates = new()
|
||||||
|
{
|
||||||
|
{ "主角攻击力大于20", NovelEditor.Conditions["主角攻击力大于20"] }
|
||||||
|
},
|
||||||
|
OrPredicates = new()
|
||||||
|
{
|
||||||
|
{ "马猴烧酒的好感度低于50", NovelEditor.Conditions["马猴烧酒的好感度低于50"] },
|
||||||
|
{ "马猴烧酒攻击力大于20", NovelEditor.Conditions["马猴烧酒攻击力大于20"] }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
node4.NextNodes.Add(node6);
|
||||||
|
node5.NextNodes.Add(node6);
|
||||||
|
node5.NextNodes.Add(node7);
|
||||||
|
|
||||||
|
NovelConfig config = new("novel1", "chapter1")
|
||||||
|
{
|
||||||
|
{ node1.Key, node1 },
|
||||||
|
{ node2.Key, node2 },
|
||||||
|
{ node3.Key, node3 },
|
||||||
|
{ node4.Key, node4 },
|
||||||
|
{ node5.Key, node5 },
|
||||||
|
{ node6.Key, node6 },
|
||||||
|
{ node7.Key, node7 }
|
||||||
|
};
|
||||||
|
config.SaveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ using Oshima.FunGame.OshimaModules;
|
|||||||
using Oshima.FunGame.OshimaServers.Service;
|
using Oshima.FunGame.OshimaServers.Service;
|
||||||
using Oshima.FunGame.WebAPI.Controllers;
|
using Oshima.FunGame.WebAPI.Controllers;
|
||||||
|
|
||||||
//7
|
_ = new Milimoe.FunGame.Testing.Solutions.Novels();
|
||||||
|
|
||||||
//_ = new Milimoe.FunGame.Testing.Tests.CheckDLL();
|
//_ = new Milimoe.FunGame.Testing.Tests.CheckDLL();
|
||||||
|
|
||||||
|
214
Library/Solutions/Novels.cs
Normal file
214
Library/Solutions/Novels.cs
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
|
using Milimoe.FunGame.Core.Entity;
|
||||||
|
using Milimoe.FunGame.Core.Model;
|
||||||
|
using MilimoeFunGame.Testing.Characters;
|
||||||
|
|
||||||
|
namespace Milimoe.FunGame.Testing.Solutions
|
||||||
|
{
|
||||||
|
public class Novels
|
||||||
|
{
|
||||||
|
public static Dictionary<Character, int> Likability { get; } = [];
|
||||||
|
public static Dictionary<string, Func<bool>> Conditions { get; } = [];
|
||||||
|
|
||||||
|
public static bool 攻击力大于20(Character character)
|
||||||
|
{
|
||||||
|
return character.ATK > 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool 好感度低于50(Character character)
|
||||||
|
{
|
||||||
|
return Likability[character] > 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Novels()
|
||||||
|
{
|
||||||
|
Character main = OshimaCharacters.Oshima;
|
||||||
|
Character character = OshimaCharacters.马猴烧酒;
|
||||||
|
Likability.Add(character, 100);
|
||||||
|
|
||||||
|
Conditions.Add("马猴烧酒的好感度低于50", () => 好感度低于50(character));
|
||||||
|
Conditions.Add("主角攻击力大于20", () => 攻击力大于20(main));
|
||||||
|
Conditions.Add("马猴烧酒攻击力大于20", () => 攻击力大于20(character));
|
||||||
|
NovelNode node1 = new()
|
||||||
|
{
|
||||||
|
Key = "node1",
|
||||||
|
Name = "声音",
|
||||||
|
Content = "听说你在等我?我来了!"
|
||||||
|
};
|
||||||
|
NovelNode node2 = new()
|
||||||
|
{
|
||||||
|
Key = "node2",
|
||||||
|
Name = main.NickName,
|
||||||
|
Content = "什么人!"
|
||||||
|
};
|
||||||
|
node1.NextNodes.Add(node2);
|
||||||
|
node2.Previous = node1;
|
||||||
|
NovelOption option1 = new()
|
||||||
|
{
|
||||||
|
Key = "option1",
|
||||||
|
Name = "你好。"
|
||||||
|
};
|
||||||
|
NovelOption option2 = new()
|
||||||
|
{
|
||||||
|
Key = "option2",
|
||||||
|
Name = "我不认识你。",
|
||||||
|
AndPredicates = new()
|
||||||
|
{
|
||||||
|
{ "主角攻击力大于20", Conditions["主角攻击力大于20"] }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NovelNode node3 = new()
|
||||||
|
{
|
||||||
|
Key = "node3",
|
||||||
|
Name = character.NickName,
|
||||||
|
Content = "你好,我叫【马猴烧酒】!",
|
||||||
|
Options = [option1, option2]
|
||||||
|
};
|
||||||
|
NovelNode node4 = new()
|
||||||
|
{
|
||||||
|
Key = "node4",
|
||||||
|
Name = character.NickName,
|
||||||
|
Content = "你的名字是?"
|
||||||
|
};
|
||||||
|
NovelNode node5 = new()
|
||||||
|
{
|
||||||
|
Key = "node5",
|
||||||
|
Name = character.NickName,
|
||||||
|
Content = "滚,谁要认识你?"
|
||||||
|
};
|
||||||
|
node2.NextNodes.Add(node3);
|
||||||
|
option1.Targets.Add(node4);
|
||||||
|
option2.Targets.Add(node5);
|
||||||
|
NovelNode node6 = new()
|
||||||
|
{
|
||||||
|
Key = "node6",
|
||||||
|
Content = "旁白:示例结束。"
|
||||||
|
};
|
||||||
|
NovelNode node7 = new()
|
||||||
|
{
|
||||||
|
Key = "node7",
|
||||||
|
Priority = 2,
|
||||||
|
Content = "旁白:示例结束,你被马猴烧酒吃掉了。",
|
||||||
|
AndPredicates = new()
|
||||||
|
{
|
||||||
|
{ "主角攻击力大于20", Conditions["主角攻击力大于20"] }
|
||||||
|
},
|
||||||
|
OrPredicates = new()
|
||||||
|
{
|
||||||
|
{ "马猴烧酒的好感度低于50", Conditions["马猴烧酒的好感度低于50"] },
|
||||||
|
{ "马猴烧酒攻击力大于20", Conditions["马猴烧酒攻击力大于20"] }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
node4.NextNodes.Add(node6);
|
||||||
|
node5.NextNodes.Add(node6);
|
||||||
|
node5.NextNodes.Add(node7);
|
||||||
|
|
||||||
|
NovelConfig config = new("novel1", "chapter1")
|
||||||
|
{
|
||||||
|
{ node1.Key, node1 },
|
||||||
|
{ node2.Key, node2 },
|
||||||
|
{ node3.Key, node3 },
|
||||||
|
{ node4.Key, node4 },
|
||||||
|
{ node5.Key, node5 },
|
||||||
|
{ node6.Key, node6 },
|
||||||
|
{ node7.Key, node7 }
|
||||||
|
};
|
||||||
|
config.SaveConfig();
|
||||||
|
|
||||||
|
NovelConfig config2 = new("novel1", "chapter1");
|
||||||
|
config2.LoadConfig(Conditions);
|
||||||
|
|
||||||
|
foreach (NovelNode node in config2.Values)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new();
|
||||||
|
builder.AppendLine("== 节点:" + node.Key + " ==");
|
||||||
|
|
||||||
|
if (node.AndPredicates.Union(node.OrPredicates).Any())
|
||||||
|
{
|
||||||
|
builder.AppendLine("对话触发条件(需满足以下所有条件):");
|
||||||
|
int count = 0;
|
||||||
|
if (node.AndPredicates.Count > 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
builder.AppendLine(count + ". " + "满足以下所有子条件:");
|
||||||
|
int subCount = 0;
|
||||||
|
foreach (string ap in node.AndPredicates.Keys)
|
||||||
|
{
|
||||||
|
subCount++;
|
||||||
|
builder.AppendLine("(" + subCount + ") " + ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.OrPredicates.Count > 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
builder.AppendLine(count + ". " + "满足以下任意一个子条件:");
|
||||||
|
int subCount = 0;
|
||||||
|
foreach (string op in node.OrPredicates.Keys)
|
||||||
|
{
|
||||||
|
subCount++;
|
||||||
|
builder.AppendLine("(" + subCount + ") " + op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.Name != "")
|
||||||
|
{
|
||||||
|
builder.Append(node.Name + "说:");
|
||||||
|
}
|
||||||
|
builder.AppendLine(node.Content);
|
||||||
|
|
||||||
|
if (node.Options.Count > 0)
|
||||||
|
{
|
||||||
|
builder.AppendLine("选项:");
|
||||||
|
int count = 0;
|
||||||
|
foreach (NovelOption option in node.Options)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
builder.AppendLine(count + ". " + option.Name + "【可跳转:" + string.Join(",", option.Targets.Select(t => t.Key)) + "】");
|
||||||
|
if (option.AndPredicates.Union(option.OrPredicates).Any())
|
||||||
|
{
|
||||||
|
builder.AppendLine("选项显示条件(需满足以下所有条件):");
|
||||||
|
int optionCount = 0;
|
||||||
|
if (option.AndPredicates.Count > 0)
|
||||||
|
{
|
||||||
|
optionCount++;
|
||||||
|
builder.AppendLine(optionCount + ". " + "满足以下所有子条件:");
|
||||||
|
int subCount = 0;
|
||||||
|
foreach (string ap in option.AndPredicates.Keys)
|
||||||
|
{
|
||||||
|
subCount++;
|
||||||
|
builder.AppendLine("(" + subCount + ") " + ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (option.OrPredicates.Count > 0)
|
||||||
|
{
|
||||||
|
optionCount++;
|
||||||
|
builder.AppendLine(optionCount + ". " + "满足以下任意一个子条件:");
|
||||||
|
int subCount = 0;
|
||||||
|
foreach (string op in option.OrPredicates.Keys)
|
||||||
|
{
|
||||||
|
subCount++;
|
||||||
|
builder.AppendLine("(" + subCount + ") " + op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.NextNodes.Count > 0)
|
||||||
|
{
|
||||||
|
builder.AppendLine("下一句对话:");
|
||||||
|
int count = 0;
|
||||||
|
foreach (NovelNode next in node.NextNodes)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
builder.AppendLine(count + ". " + next.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(builder.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user