This commit is contained in:
milimoe 2025-09-02 01:00:50 +08:00
parent e119aa3b69
commit ba70102207
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
4 changed files with 331 additions and 95 deletions

View File

@ -33,11 +33,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
);
}
public async Task<CharacterActionType> RequestActionType(Character character, List<Skill> availableSkills, List<Item> availableItems)
public async Task<CharacterActionType> RequestActionType(Character character, List<Item> availableItems)
{
WriteLine($"现在是 {character.NickName} 的回合,请选择行动。");
return await _actionTypeRequester.RequestInput(
(callback) => UI.Invoke(() => UI.ShowActionButtons(character, availableSkills, availableItems, callback))
(callback) => UI.Invoke(() => UI.ShowActionButtons(character, availableItems, callback))
);
}
@ -55,7 +55,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
WriteLine($"请为 {character.NickName} 选择一个技能。");
long? skillId = await _skillSelectionRequester.RequestInput(
(callback) => UI.Invoke(() => UI.ShowSkillSelectionUI(character, availableSkills, callback))
(callback) => UI.Invoke(() => UI.ShowSkillSelectionUI(character, callback))
);
return skillId.HasValue ? availableSkills.FirstOrDefault(s => s.Id == skillId.Value) : null;
}
@ -64,7 +64,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
WriteLine($"请为 {character.NickName} 选择一个物品。");
long? itemId = await _itemSelectionRequester.RequestInput(
(callback) => UI.Invoke(() => UI.ShowItemSelectionUI(availableItems, callback))
(callback) => UI.Invoke(() => UI.ShowItemSelectionUI(character, callback))
);
return itemId.HasValue ? availableItems.FirstOrDefault(i => i.Id == itemId.Value) : null;
}

View File

@ -2,7 +2,6 @@
// using System.Windows; // 不再需要,因为移除了 InputDialog
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Model;
@ -137,7 +136,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
int qWeapon = 5;
int qArmor = 5;
int qShoes = 5;
int qAccessory = 4;
int qAccessory = 5;
WriteLine($"社区送温暖了,现在随机发放空投!!");
DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory);
WriteLine("");
@ -499,7 +498,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
if (IsPlayer_OnlyTest(queue, character))
{
// 通过UI按钮请求行动类型
CharacterActionType actionType = await Controller.RequestActionType(character, skills, items);
CharacterActionType actionType = await Controller.RequestActionType(character, items);
Controller.ResolveActionType(actionType);
return actionType;
}

View File

@ -1,4 +1,5 @@
<UserControl x:Class="Milimoe.FunGame.Testing.Desktop.GameMapTesting.GameMapViewer"
x:Name="GameMapViewerControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -64,6 +65,10 @@
<local:FirstCharConverter x:Key="FirstCharConverter"/>
<!-- 新增:队列项中角色名称和等级文本的转换器 -->
<local:CharacterToStringWithLevelConverter x:Key="CharacterToStringWithLevelConverter"/>
<!-- 新增:技能/物品名称格式化转换器 -->
<local:SkillItemFormatterConverter x:Key="SkillItemFormatterConverter"/>
<!-- 新增:技能/物品可用性判断转换器 -->
<local:SkillUsabilityConverter x:Key="SkillUsabilityConverter"/>
<!-- 新增:角色图标的样式 (圆形) -->
<Style x:Key="CharacterIconStyle" TargetType="Border">
@ -97,6 +102,17 @@
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Cyan"/>
</Trigger>
<!-- 当 Border 禁用时的样式 -->
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#FFE0E0E0"/>
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="Cursor" Value="Arrow"/>
<!-- 鼠标变为默认箭头 -->
<!-- 可以通过设置 TextElement.Foreground 来影响内部 TextBlock 的颜色 -->
<Setter Property="TextElement.Foreground" Value="DimGray"/>
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
<Setter Property="ToolTip" Value="无法使用:条件不满足"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
@ -107,7 +123,7 @@
<!-- 左侧动态队列 -->
<ColumnDefinition Width="*"/>
<!-- 地图区域 -->
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="0.8*"/>
<!-- 新增:右侧调试日志 -->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
@ -213,8 +229,6 @@
<TextBlock Text="{Binding NickName}" FontWeight="SemiBold" Margin="0,0,5,0"/>
<TextBlock Text="{Binding HP, StringFormat=HP:{0:0.##}}"/>
<TextBlock Text="{Binding MaxHP, StringFormat=/{0:0.##}}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding MP, StringFormat=MP:{0:0.##}}"/>
<TextBlock Text="{Binding MaxMP, StringFormat=/{0:0.##}}"/>
</StackPanel>
</Border>
</DataTemplate>
@ -235,7 +249,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="400"
MaxHeight="400"
MaxHeight="600"
Background="#DDFFFFFF"
BorderBrush="DarkBlue"
BorderThickness="2"
@ -244,19 +258,38 @@
Visibility="Collapsed">
<StackPanel>
<TextBlock Text="请选择你的角色" FontWeight="Bold" FontSize="16" Margin="0,0,0,10" HorizontalAlignment="Center"/>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="300">
<ItemsControl x:Name="CharacterSelectionItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource SelectionItemStyle}"
Tag="{Binding Id}"
MouseLeftButtonDown="CharacterSelectionItem_MouseLeftButtonDown">
Tag="{Binding}"
MouseLeftButtonDown="CharacterSelectionItem_MouseLeftButtonDown"
MouseEnter="CharacterSelectionItem_MouseEnter">
<TextBlock Text="{Binding NickName}" FontSize="14" FontWeight="SemiBold"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- 新增:角色详情显示区域 -->
<TextBlock Text="角色详情" FontWeight="Bold" FontSize="14" Margin="0,10,0,5" HorizontalAlignment="Center"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="200">
<!-- 限制详情区域高度 -->
<RichTextBox x:Name="CharacterDetailsRichTextBox"
IsReadOnly="True"
BorderThickness="0"
Background="Transparent"
Foreground="DimGray"
FontSize="11"
AcceptsReturn="True"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled">
<FlowDocument>
<Paragraph Margin="0">将鼠标悬停在角色名称上以查看详情。</Paragraph>
</FlowDocument>
</RichTextBox>
</ScrollViewer>
</StackPanel>
</Border>
@ -266,7 +299,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="400"
MaxHeight="400"
MaxHeight="600"
Background="#DDFFFFFF"
BorderBrush="DarkGreen"
BorderThickness="2"
@ -275,19 +308,44 @@
Visibility="Collapsed">
<StackPanel>
<TextBlock x:Name="SkillItemSelectionTitle" Text="请选择技能/物品" FontWeight="Bold" FontSize="16" Margin="0,0,0,10" HorizontalAlignment="Center"/>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="300">
<ItemsControl x:Name="SkillItemSelectionItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource SelectionItemStyle}"
Tag="{Binding Id}"
MouseLeftButtonDown="SkillItemSelectionItem_MouseLeftButtonDown">
<TextBlock Text="{Binding Name}" FontSize="14" FontWeight="SemiBold"/>
Tag="{Binding}"
MouseLeftButtonDown="SkillItemSelectionItem_MouseLeftButtonDown"
MouseEnter="SkillItemSelectionItem_MouseEnter">
<Border.IsEnabled>
<MultiBinding Converter="{StaticResource SkillUsabilityConverter}">
<Binding Path="."/>
<Binding ElementName="GameMapViewerControl" Path="PlayerCharacter"/>
</MultiBinding>
</Border.IsEnabled>
<TextBlock Text="{Binding Converter={StaticResource SkillItemFormatterConverter}}" FontSize="14" FontWeight="SemiBold"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- 新增:详情显示区域 -->
<TextBlock x:Name="SkillItemDescription" Text="技能/物品详情" FontWeight="Bold" FontSize="14" Margin="0,10,0,5" HorizontalAlignment="Center"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="200">
<!-- 限制详情区域高度 -->
<RichTextBox x:Name="SkillItemDetailsRichTextBox"
IsReadOnly="True"
BorderThickness="0"
Background="Transparent"
Foreground="DimGray"
FontSize="11"
AcceptsReturn="True"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled">
<FlowDocument>
<Paragraph Margin="0">将鼠标悬停在名称上以查看详情。</Paragraph>
</FlowDocument>
</RichTextBox>
</ScrollViewer>
<Button Content="取消" Margin="0,10,0,0" HorizontalAlignment="Right" Click="CancelSkillItemSelection_Click"/>
</StackPanel>
</Border>
@ -355,22 +413,31 @@
<!-- 新增:右侧调试日志面板 -->
<Border Grid.Column="2" Grid.Row="0" BorderBrush="LightGray" BorderThickness="1" Margin="5" Padding="5">
<StackPanel Background="#FFF0F8FF">
<!-- AliceBlue -->
<TextBlock Text="调试日志" Margin="0,0,0,10" FontWeight="Bold" FontSize="14"/>
<ScrollViewer x:Name="DebugLogScrollViewer"
<Grid Background="#FFF0F8FF">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="调试日志" Margin="0,0,0,10" FontWeight="Bold" FontSize="14"/>
<ScrollViewer Grid.Row="1" x:Name="DebugLogScrollViewer"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
Height="Auto">
<!-- 移除MaxHeight让它填充可用空间 -->
<TextBlock x:Name="DebugLogTextBlock"
ScrollViewer.CanContentScroll="True"
HorizontalScrollBarVisibility="Disabled">
<!-- 修改:将 TextBlock 替换为 RichTextBox -->
<RichTextBox x:Name="DebugLogRichTextBox"
IsReadOnly="True"
BorderThickness="0"
Background="Transparent"
Foreground="DimGray"
TextWrapping="Wrap"
Text="调试日志:" />
FontSize="11"
AcceptsReturn="True"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled">
<FlowDocument>
<Paragraph Margin="0">调试日志:</Paragraph>
</FlowDocument>
</RichTextBox>
</ScrollViewer>
</StackPanel>
</Grid>
</Border>
<!-- 底部信息界面面板 (横向填充) -->
@ -500,7 +567,8 @@
</Border>
<!-- 新增中间部分:装备和状态 -->
<Border Grid.Column="1" BorderBrush="LightGray" BorderThickness="0,0,1,0" Margin="0,0,5,0" Padding="5">
<Border Grid.Column="1" BorderBrush="LightGray" BorderThickness="0,0,1,0" Margin="0,0,5,0" Padding="5"
x:Name="EquipStatusInfoBorder" MouseLeftButtonDown="EquipStatusInfoBorder_MouseLeftButtonDown">
<StackPanel Orientation="Vertical">
<!-- 装备栏 -->
<TextBlock Text="装备" FontWeight="Bold" FontSize="14" Margin="0,0,0,5"/>
@ -544,7 +612,19 @@
<StackPanel>
<TextBlock Text="详情描述" FontWeight="Bold" FontSize="14" Margin="0,0,0,5"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="80">
<TextBlock x:Name="DescriptionTextBlock" Text="点击装备或状态图标查看详情。" TextWrapping="Wrap" FontSize="11" Foreground="DimGray"/>
<RichTextBox x:Name="DescriptionRichTextBox"
IsReadOnly="True"
BorderThickness="0"
Background="Transparent"
Foreground="DimGray"
FontSize="11"
AcceptsReturn="True"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled">
<FlowDocument>
<Paragraph Margin="0">点击装备或状态图标查看详情。</Paragraph>
</FlowDocument>
</RichTextBox>
</ScrollViewer>
</StackPanel>
</Border>
@ -560,8 +640,7 @@
<!-- Tag 属性用于在 Click 事件中识别是哪个动作 -->
<Button x:Name="MoveButton" Content="移动" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.Move}" IsEnabled="False"/>
<Button x:Name="AttackButton" Content="普通攻击" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.NormalAttack}" IsEnabled="False"/>
<Button x:Name="SkillButton" Content="释放战技" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.PreCastSkill}" IsEnabled="False"/>
<Button x:Name="CastButton" Content="吟唱魔法" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.PreCastSkill}" IsEnabled="False"/>
<Button x:Name="SkillButton" Content="战技/魔法" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.PreCastSkill}" IsEnabled="False"/>
<Button x:Name="UseItemButton" Content="使用物品" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.UseItem}" IsEnabled="False"/>
<Button x:Name="EndTurnButton" Content="结束回合" Width="100" Height="30" Margin="5" Click="ActionButton_Click" Tag="{x:Static constant:CharacterActionType.EndTurn}" IsEnabled="False"/>
</WrapPanel>

View File

@ -3,6 +3,7 @@ using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Milimoe.FunGame.Core.Api.Utility;
@ -14,14 +15,14 @@ using static Milimoe.FunGame.Core.Library.Constant.General;
using Brushes = System.Windows.Media.Brushes;
using Button = System.Windows.Controls.Button;
using Grid = Milimoe.FunGame.Core.Library.Common.Addon.Grid;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using Panel = System.Windows.Controls.Panel;
using Rectangle = System.Windows.Shapes.Rectangle;
using RichTextBox = System.Windows.Controls.RichTextBox;
using UserControl = System.Windows.Controls.UserControl;
namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
// ... (CharacterQueueItem, FirstCharConverter, CharacterToStringWithLevelConverter 保持不变) ...
public class CharacterQueueItem(Character character, double atDelay)
{
public Character Character { get; set; } = character;
@ -62,6 +63,85 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
}
public class SkillItemFormatterConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string name = "";
if (value is Skill skill)
{
Character? character = skill.Character;
name = $"【{(skill.IsSuperSkill ? "" : (skill.IsMagic ? "" : ""))}】{skill.Name}";
if (skill.CurrentCD > 0)
{
name += $" - 冷却剩余 {skill.CurrentCD:0.##} 秒";
}
else if (skill.RealEPCost > 0 && skill.RealMPCost > 0 && character != null && character.EP < skill.RealEPCost && character.MP < skill.RealMPCost)
{
name += $" - 能量/魔法要求 {skill.RealEPCost:0.##} / {skill.RealMPCost:0.##} 点";
}
else if (skill.RealEPCost > 0 && character != null && character.EP < skill.RealEPCost)
{
name += $" - 能量不足,要求 {skill.RealEPCost:0.##} 点";
}
else if (skill.RealMPCost > 0 && character != null && character.MP < skill.RealMPCost)
{
name += $" - 魔法不足,要求 {skill.RealMPCost:0.##} 点";
}
}
else if (value is Item item)
{
name = item.Name;
}
else
{
name = value?.ToString() ?? name;
}
return name;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// 组合转换器:判断技能或物品是否可用。
/// 接收 Skill/Item 对象和当前 Character 对象。
/// </summary>
public class SkillUsabilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
// values[0] 应该是 Skill 或 Item 对象
// values[1] 应该是 CurrentCharacter 对象
if (values.Length < 2 || values[1] is not Character character)
{
return false;
}
if (values[0] is Skill s)
{
return s.Level > 0 && s.SkillType != SkillType.Passive && s.Enable && !s.IsInEffect && s.CurrentCD == 0 &&
((s.SkillType == SkillType.SuperSkill || s.SkillType == SkillType.Skill) && s.RealEPCost <= character.EP || s.SkillType == SkillType.Magic && s.RealMPCost <= character.MP);
}
else if (values[0] is Item i)
{
return i.IsActive && i.Skills.Active != null && i.Enable && i.IsInGameItem &&
i.Skills.Active.SkillType == SkillType.Item && i.Skills.Active.Enable && !i.Skills.Active.IsInEffect && i.Skills.Active.CurrentCD == 0 &&
i.Skills.Active.RealMPCost <= character.MP && i.Skills.Active.RealEPCost <= character.EP;
}
return false;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// GameMapViewer.xaml 的交互逻辑
/// </summary>
@ -234,7 +314,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
viewer.UpdateBottomInfoPanel();
viewer.UpdateCharacterStatisticsPanel(); // 角色改变时也更新统计面板
// 角色改变时,清除装备/状态描述
viewer.DescriptionTextBlock.Text = "点击装备或状态图标查看详情。";
SetRichTextBoxText(viewer.DescriptionRichTextBox, "点击装备或状态图标查看详情。");
viewer.ClearEquipSlotHighlights();
viewer.ClearStatusIconHighlights();
}
@ -275,23 +355,36 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
int maxLines = 1000;
string currentText = DebugLogTextBlock.Text;
List<string> lines = [.. currentText.Split([Environment.NewLine], StringSplitOptions.None)];
if (lines.Count == 1 && lines[0] == "调试日志:")
// 获取 FlowDocument
FlowDocument doc = DebugLogRichTextBox.Document;
if (doc == null)
{
lines.Clear();
doc = new FlowDocument();
DebugLogRichTextBox.Document = doc;
}
lines.Add($"{message}");
while (lines.Count > maxLines)
// 如果是初始的“调试日志:”段落,则清空它
if (doc.Blocks.FirstBlock is Paragraph firstParagraph && firstParagraph.Inlines.FirstInline is Run firstRun && firstRun.Text == "调试日志:")
{
lines.RemoveAt(0);
doc.Blocks.Clear();
}
DebugLogTextBlock.Text = string.Join(Environment.NewLine, lines);
DebugLogScrollViewer?.ScrollToEnd();
// 添加新的段落
Paragraph newParagraph = new(new Run(message))
{
Margin = new Thickness(0) // 移除默认段落间距
};
doc.Blocks.Add(newParagraph);
// 限制行数
while (doc.Blocks.Count > maxLines)
{
doc.Blocks.Remove(doc.Blocks.FirstBlock);
}
// 滚动到底部
DebugLogRichTextBox.ScrollToEnd();
DebugLogScrollViewer.ScrollToEnd();
}
/// <summary>
@ -460,7 +553,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
// 每次更新面板时,清除装备/状态描述和高亮
DescriptionTextBlock.Text = "点击装备或状态图标查看详情。";
SetRichTextBoxText(DescriptionRichTextBox, "点击装备或状态图标查看详情。"); // 新代码
ClearEquipSlotHighlights();
ClearStatusIconHighlights();
@ -541,7 +634,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
Border effectBorder = new()
{
Style = (Style)this.FindResource("StatusIconStyle"),
ToolTip = effect.Description ?? effect.GetType().Name // 鼠标悬停显示完整效果名称或描述
ToolTip = effect.ToString() // 鼠标悬停显示完整效果名称或描述
};
TextBlock effectText = new()
{
@ -658,7 +751,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
textBlock.Text = item.Name.Length > 0 ? item.Name[0].ToString().ToUpper() : defaultText;
parentBorder.Background = Brushes.LightGreen; // 装备槽有物品时显示浅绿色背景
textBlock.Foreground = Brushes.Black; // 文本颜色变深
parentBorder.ToolTip = item.Description ?? item.Name; // 显示物品名称或描述作为ToolTip
parentBorder.ToolTip = item.ToString(); // 显示物品名称或描述作为ToolTip
}
else
{
@ -700,9 +793,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
CharacterStatistics? stats = dict.Where(kv => kv.Key == CurrentCharacter).Select(kv => kv.Value).FirstOrDefault();
if (stats != null)
{
// 第一行:技术得分 / 击杀数 / 助攻数 / 死亡数 (可选)
string deathPart = (MaxRespawnTimes != 0) ? $" / 死亡数:{stats.Deaths}" : "";
StatsRatingKillsAssistsDeathsTextBlock.Text = $"技术得分:{FunGameService.CalculateRating(stats):0.0#} / 击杀数:{stats.Kills} / 助攻数:{stats.Assists}{deathPart}";
// 第一行:技术得分 / 击杀数 / 助攻数 / 死亡数
StatsRatingKillsAssistsDeathsTextBlock.Text = $"技术得分:{FunGameService.CalculateRating(stats):0.0#} / 击杀数:{stats.Kills} / 助攻数:{stats.Assists} / 死亡数:{stats.Deaths}";
// 第二行:存活时长 / 存活回合数 / 行动回合数
StatsLiveTimeRoundTurnTextBlock.Text = $"存活时长:{stats.LiveTime:0.##} / 存活回合数:{stats.LiveRound} / 行动回合数:{stats.ActionTurn}";
@ -848,12 +940,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
if (e.OriginalSource == GameMapCanvas)
{
AppendDebugLog("点击了地图空白区域。");
// 隐藏格子信息面板
GridInfoPanel.Visibility = Visibility.Collapsed;
// 清除所有格子的边框高亮
ClearGridHighlights();
// 调用关闭格子信息面板的逻辑,它现在也会重置描述和高亮
CloseGridInfoButton_Click(new(), new());
// 将当前角色设置回玩家角色
this.CurrentCharacter = this.PlayerCharacter;
e.Handled = true; // 标记事件已处理,防止冒泡
}
}
@ -869,6 +960,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
CurrentCharacter = PlayerCharacter;
}
// 新增:关闭格子信息面板时,重置装备/状态描述和高亮
ResetDescriptionAndHighlights();
}
/// <summary>
@ -883,14 +976,13 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
}
// --- 新增:装备槽位点击事件和辅助方法 ---
private void EquipSlot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Border clickedBorder)
{
ClearEquipSlotHighlights(); // 清除所有装备槽位的旧高亮
ClearStatusIconHighlights(); // 清除所有状态图标的旧高亮
clickedBorder.BorderBrush = Brushes.Blue; // 高亮当前点击的槽位
ClearEquipSlotHighlights();
ClearStatusIconHighlights();
clickedBorder.BorderBrush = Brushes.Blue;
clickedBorder.BorderThickness = new Thickness(2);
Item? item = null;
@ -906,12 +998,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
if (item != null)
{
DescriptionTextBlock.Text = item.Description ?? item.Name; // 显示物品描述,如果不存在则显示名称
SetRichTextBoxText(DescriptionRichTextBox, item.ToString());
AppendDebugLog($"查看装备: {item.Name}");
}
else
{
DescriptionTextBlock.Text = "此槽位未装备物品。";
SetRichTextBoxText(DescriptionRichTextBox, "此槽位未装备物品。");
AppendDebugLog("查看空装备槽位。");
}
}
@ -946,7 +1038,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
clickedBorder.BorderBrush = Brushes.Blue; // 高亮当前点击的状态图标
clickedBorder.BorderThickness = new Thickness(1.5);
DescriptionTextBlock.Text = effect.Description ?? effect.GetType().Name; // 显示效果描述,如果不存在则显示类型名称
SetRichTextBoxText(DescriptionRichTextBox, effect.ToString());
AppendDebugLog($"查看状态: {effect.GetType().Name}");
}
}
@ -974,7 +1066,6 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
MoveButton.IsEnabled = enabled;
AttackButton.IsEnabled = enabled;
SkillButton.IsEnabled = enabled;
CastButton.IsEnabled = enabled;
UseItemButton.IsEnabled = enabled;
EndTurnButton.IsEnabled = enabled;
}
@ -1001,6 +1092,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
_resolveCharacterSelection = callback;
CharacterSelectionItemsControl.ItemsSource = availableCharacters;
SetRichTextBoxText(CharacterDetailsRichTextBox, "将鼠标悬停在角色名称上查看详情。");
CharacterSelectionOverlay.Visibility = Visibility.Visible;
}
@ -1009,9 +1101,22 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// </summary>
private void CharacterSelectionItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Border border && border.Tag is long characterId)
if (sender is Border border && border.Tag is Character character)
{
_resolveCharacterSelection?.Invoke(characterId);
_resolveCharacterSelection?.Invoke(character.Id);
}
}
/// <summary>
/// 角色选择项的鼠标进入事件。
/// </summary>
private void CharacterSelectionItem_MouseEnter(object sender, MouseEventArgs e)
{
// Tag 现在是 Character 对象
if (sender is Border border && border.Tag is Character hoveredCharacter)
{
string details = hoveredCharacter.GetInfo();
SetRichTextBoxText(CharacterDetailsRichTextBox, details);
}
}
@ -1023,26 +1128,25 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
CharacterSelectionOverlay.Visibility = Visibility.Collapsed;
CharacterSelectionItemsControl.ItemsSource = null;
_resolveCharacterSelection = null;
SetRichTextBoxText(CharacterDetailsRichTextBox, "");
}
/// <summary>
/// 显示行动按钮,并根据可用技能和物品启用/禁用相关按钮。
/// </summary>
/// <param name="character">当前行动的角色。</param>
/// <param name="availableSkills">可用的技能列表。</param>
/// <param name="availableItems">可用的物品列表。</param>
/// <param name="callback">选择行动后调用的回调函数。</param>
public void ShowActionButtons(Character character, List<Skill> availableSkills, List<Item> availableItems, Action<CharacterActionType> callback)
public void ShowActionButtons(Character character, List<Item> availableItems, Action<CharacterActionType> callback)
{
_resolveActionType = callback;
SetActionButtonsEnabled(true);
// 根据实际情况启用/禁用技能和物品按钮
// 技能按钮:检查是否有任何技能是当前角色可施放的
SkillButton.IsEnabled = character.Skills.Any(availableSkills.Contains);
// 物品按钮:检查是否有任何物品可用
MoveButton.IsEnabled = character.CharacterState != CharacterState.NotActionable && character.CharacterState != CharacterState.ActionRestricted;
AttackButton.IsEnabled = character.CharacterState != CharacterState.NotActionable && character.CharacterState != CharacterState.ActionRestricted &&
character.CharacterState != CharacterState.BattleRestricted && character.CharacterState != CharacterState.AttackRestricted;
SkillButton.IsEnabled = true;
UseItemButton.IsEnabled = availableItems.Count != 0;
// 移动按钮:假设总是可用,或者需要更复杂的逻辑来判断
// 如果当前角色不是正在行动的角色更新CurrentCharacter
if (CurrentCharacter != character)
@ -1063,27 +1167,30 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary>
/// 显示技能选择UI。
/// </summary>
/// <param name="availableSkills">可供选择的技能列表。</param>
/// <param name="character">可供选择的技能列表。</param>
/// <param name="callback">选择完成后调用的回调函数。</param>
public void ShowSkillSelectionUI(Character character, List<Skill> availableSkills, Action<long> callback)
public void ShowSkillSelectionUI(Character character, Action<long> callback)
{
_resolveSkillSelection = callback;
SkillItemSelectionTitle.Text = "请选择技能";
// 只显示当前角色可施放的技能
SkillItemSelectionItemsControl.ItemsSource = character.Skills.Where(availableSkills.Contains).ToList();
SkillItemDescription.Text = "技能详情";
SetRichTextBoxText(SkillItemDetailsRichTextBox, "将鼠标悬停在名称上以查看详情。");
SkillItemSelectionItemsControl.ItemsSource = character.Skills.Where(s => s.SkillType != SkillType.Passive).ToList();
SkillItemSelectionOverlay.Visibility = Visibility.Visible;
}
/// <summary>
/// 显示物品选择UI。
/// </summary>
/// <param name="availableItems">可供选择的物品列表。</param>
/// <param name="character">可供选择的物品列表。</param>
/// <param name="callback">选择完成后调用的回调函数。</param>
public void ShowItemSelectionUI(List<Item> availableItems, Action<long> callback)
public void ShowItemSelectionUI(Character character, Action<long> callback)
{
_resolveItemSelection = callback;
SkillItemSelectionTitle.Text = "请选择物品";
SkillItemSelectionItemsControl.ItemsSource = availableItems;
SkillItemDescription.Text = "物品详情";
SetRichTextBoxText(SkillItemDetailsRichTextBox, "将鼠标悬停在名称上以查看详情。");
SkillItemSelectionItemsControl.ItemsSource = character.Items;
SkillItemSelectionOverlay.Visibility = Visibility.Visible;
}
@ -1092,31 +1199,53 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// </summary>
private void SkillItemSelectionItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Border border && border.Tag is long id)
if (sender is Border border)
{
if (SkillItemSelectionTitle.Text == "请选择技能")
if (border.Tag is Skill skill)
{
_resolveSkillSelection?.Invoke(id);
_resolveSkillSelection?.Invoke(skill.Id);
}
else if (SkillItemSelectionTitle.Text == "请选择物品")
else if (border.Tag is Item item)
{
_resolveItemSelection?.Invoke(id);
_resolveItemSelection?.Invoke(item.Id);
}
}
}
/// <summary>
/// 角色选择项的鼠标进入事件。
/// </summary>
private void SkillItemSelectionItem_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
string details = "";
if (border.Tag is Skill hoveredSkill)
{
details = hoveredSkill.ToString();
}
else if (border.Tag is Item hoveredItem)
{
details = hoveredItem.ToString();
}
SetRichTextBoxText(SkillItemDetailsRichTextBox, details);
}
}
/// <summary>
/// 取消技能/物品选择的点击事件。
/// </summary>
private void CancelSkillItemSelection_Click(object sender, RoutedEventArgs e)
{
if (SkillItemSelectionTitle.Text == "请选择技能")
if (SkillItemDescription.Text == "技能详情")
{
_resolveSkillSelection?.Invoke(-1); // 返回-1表示取消
SkillItemDescription.Text = "";
_resolveSkillSelection?.Invoke(-1);
}
else if (SkillItemSelectionTitle.Text == "请选择物品")
else if (SkillItemDescription.Text == "物品详情")
{
_resolveItemSelection?.Invoke(-1); // 返回-1表示取消
SkillItemDescription.Text = "";
_resolveItemSelection?.Invoke(-1);
}
}
@ -1342,5 +1471,34 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
return new SolidColorBrush(System.Windows.Media.Color.FromArgb(color.A, color.R, color.G, color.B));
}
private void EquipStatusInfoBorder_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 只有当点击事件的原始源是Border本身时才处理这意味着没有点击到任何子元素如装备槽位或状态图标
if (sender is Border clickedBorder && e.OriginalSource == clickedBorder)
{
ResetDescriptionAndHighlights();
AppendDebugLog("点击了装备/状态区域空白处。");
e.Handled = true; // 标记事件已处理
}
}
private void ResetDescriptionAndHighlights()
{
SetRichTextBoxText(DescriptionRichTextBox, "点击装备或状态图标查看详情。");
ClearEquipSlotHighlights();
ClearStatusIconHighlights();
}
/// <summary>
/// 设置 RichTextBox 的纯文本内容。
/// </summary>
/// <param name="richTextBox">要设置内容的 RichTextBox。</param>
/// <param name="text">要设置的纯文本。</param>
private static void SetRichTextBoxText(RichTextBox richTextBox, string text)
{
richTextBox.Document.Blocks.Clear();
richTextBox.Document.Blocks.Add(new Paragraph(new Run(text)) { Margin = new Thickness(0) });
}
}
}