添加常驻角色状态面板

This commit is contained in:
milimoe 2025-09-05 23:44:49 +08:00
parent 6a23672af9
commit dfad02fd7c
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
6 changed files with 287 additions and 111 deletions

View File

@ -1,5 +1,4 @@
using System.Threading.Tasks;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
@ -11,6 +10,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
public GameMapViewer UI => ui;
private GameMapTesting? _game;
public bool TeamMode => _game?.TeamMode ?? false;
// 输入请求器实例
private readonly UserInputRequester<long> _characterSelectionRequester = new();
private readonly UserInputRequester<CharacterActionType> _actionTypeRequester = new();
@ -27,6 +28,28 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
await _game.StartGame(false, true);
}
public List<Team> GetTeams()
{
return _game?.GetTeams() ?? [];
}
public async Task SetTeamCharacters(IEnumerable<Character> teammates, IEnumerable<Character> enemies)
{
await UI.InvokeAsync(() =>
{
UI.TeammateCharacters.Clear();
foreach (Character character in teammates)
{
UI.TeammateCharacters.Add(new CharacterViewModel(character));
}
UI.EnemyCharacters.Clear();
foreach (Character character in enemies)
{
UI.EnemyCharacters.Add(new CharacterViewModel(character));
}
});
}
public async Task SetPreCastSuperSkill(Character character, Skill skill)
{
if (_game != null)

View File

@ -95,9 +95,10 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
// 创建顺序表并排序
Team? team1 = null, team2 = null;
if (isTeam)
{
tgq = new(characters, WriteLine)
tgq = new(WriteLine)
{
GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant
};
@ -138,12 +139,17 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{
c.Promotion = 300;
}
team1 = team;
}
else
{
team.Members.ForEach(c => c.Promotion = 400);
team2 = team;
}
}
// 初始化角色
_gamingQueue.InitCharacters(characters);
}
else
{
@ -153,6 +159,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
};
_gamingQueue = mgq;
}
if (team1 != null && team2 != null) await Controller.SetTeamCharacters(team1.Members, team2.Members);
// 加载地图和绑定事件
_gamingQueue.LoadGameMap(GameMap);
@ -322,6 +329,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
await Controller.UpdateBottomInfoPanel();
await Controller.UpdateQueue();
await Controller.UpdateCharacterPositionsOnMap();
if (team1 != null && team2 != null) await Controller.SetTeamCharacters(team1.Members, team2.Members);
if (roundMsg != "")
{
@ -748,5 +756,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
if (totalStats.ActionTurn != 0) totalStats.DamagePerTurn = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.ActionTurn);
if (totalStats.LiveTime != 0) totalStats.DamagePerSecond = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.LiveTime);
}
public List<Team> GetTeams()
{
if (_gamingQueue is TeamGamingQueue tgq)
{
return [.. tgq.Teams.Values];
}
return [];
}
}
}

View File

@ -117,6 +117,40 @@
</Trigger>
</Style.Triggers>
</Style>
<!-- 新增:角色摘要显示模板 -->
<DataTemplate x:Key="CharacterSummaryTemplate">
<Border BorderBrush="LightGray" BorderThickness="0,0,0,1" Padding="2" Margin="0,2"
Cursor="Hand"
Tag="{Binding}"
MouseLeftButtonDown="CharacterSummary_MouseLeftButtonDown">
<StackPanel>
<!-- 角色名称 -->
<TextBlock Text="{Binding Character.NickName}" FontWeight="SemiBold" Margin="0,0,5,0" FontSize="10"/>
<!-- HP 条 -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0.5">
<TextBlock Text="HP:" VerticalAlignment="Center" Width="20" FontSize="8"/>
<ProgressBar Value="{Binding Character.HP}" Maximum="{Binding Character.MaxHP}" Height="6" Width="40" Background="LightGray" BorderBrush="Gray" BorderThickness="0.5" Foreground="Green"/>
<TextBlock Text="{Binding Character.HP, StringFormat={}{0:0.##}}" Margin="3,0,0,0" VerticalAlignment="Center" FontSize="8"/>
</StackPanel>
<!-- MP 条 -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0.5">
<TextBlock Text="MP:" VerticalAlignment="Center" Width="20" FontSize="8"/>
<ProgressBar Value="{Binding Character.MP}" Maximum="{Binding Character.MaxMP}" Height="6" Width="40" Background="LightGray" BorderBrush="Gray" BorderThickness="0.5" Foreground="Blue"/>
<TextBlock Text="{Binding Character.MP, StringFormat={}{0:0.##}}" Margin="3,0,0,0" VerticalAlignment="Center" FontSize="8"/>
</StackPanel>
<!-- EP 条 -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0.5">
<TextBlock Text="EP:" VerticalAlignment="Center" Width="20" FontSize="8"/>
<ProgressBar Value="{Binding Character.EP}" Maximum="{Binding Character.GameplayEquilibriumConstant.MaxEP}" Height="6" Width="40" Background="LightGray" BorderBrush="Gray" BorderThickness="0.5" Foreground="Orange"/>
<TextBlock Text="{Binding Character.EP, StringFormat={}{0:0.##}}" Margin="3,0,0,0" VerticalAlignment="Center" FontSize="8"/>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</UserControl.Resources>
<Grid>
@ -540,6 +574,47 @@
Visibility="Collapsed"
Text="0 秒后继续..." />
<TextBlock x:Name="PointsTextBlock"
Panel.ZIndex="0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="0"
FontSize="18"
FontWeight="Bold"
Foreground="Orchid"
Background="{x:Null}"
Padding="0"
Visibility="Collapsed"
Text="团队模式比分" />
<!-- 新增:地图区内的角色列表面板 -->
<Grid Panel.ZIndex="40" Margin="0,100,0,0" Background="{x:Null}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!-- 左侧:我方/友方角色 -->
<ColumnDefinition Width="*"/>
<!-- 间隔 -->
<ColumnDefinition Width="Auto"/>
<!-- 右侧:敌方角色 -->
</Grid.ColumnDefinitions>
<!-- 左侧Promotion=200/300 的角色 -->
<StackPanel Grid.Column="0" VerticalAlignment="Top" Margin="5,5,0,5" Width="100">
<TextBlock x:Name="TeammateTextBlock" Text="我方角色" FontWeight="Bold" FontSize="12" Margin="0,0,0,5" Foreground="DarkSlateBlue"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="400">
<ItemsControl ItemsSource="{Binding TeammateCharacters, RelativeSource={RelativeSource AncestorType=UserControl}}" ItemTemplate="{StaticResource CharacterSummaryTemplate}"/>
</ScrollViewer>
</StackPanel>
<!-- 右侧Promotion=400 的角色 -->
<StackPanel Grid.Column="2" VerticalAlignment="Top" Margin="0,5,5,5" Width="100">
<TextBlock x:Name="EnemyTextBlock" Text="敌方角色" FontWeight="Bold" FontSize="12" Margin="0,0,0,5" Foreground="DarkRed" TextAlignment="Right"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="400">
<ItemsControl ItemsSource="{Binding EnemyCharacters, RelativeSource={RelativeSource AncestorType=UserControl}}" ItemTemplate="{StaticResource CharacterSummaryTemplate}"/>
</ScrollViewer>
</StackPanel>
</Grid>
</Grid>
</Border>
</ScrollViewer>
@ -744,7 +819,7 @@
<Border BorderBrush="LightGray" BorderThickness="0,1,0,0" Margin="0,10,0,0" Padding="0,10,0,0">
<StackPanel>
<TextBlock Text="详情描述" FontWeight="Bold" FontSize="14" Margin="0,0,0,5"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="140">
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="120">
<RichTextBox x:Name="DescriptionRichTextBox"
IsReadOnly="True"
BorderThickness="0"
@ -885,12 +960,10 @@
<Border BorderBrush="LightGray" BorderThickness="0,1,0,0" Margin="0,10,0,0" Padding="0,10,0,0">
<StackPanel>
<TextBlock Text="数据统计" FontWeight="Bold" FontSize="14" Margin="0,0,0,5"/>
<TextBlock x:Name="StatsRatingKillsAssistsDeathsTextBlock" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsLiveTimeRoundTurnTextBlock" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsControlHealShieldTextBlock" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsTotalDamageTextBlock" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsTotalTakenDamageTextBlock" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsTrueDamageTextBlock" Style="{StaticResource CharacterAttributeTextStyle}" Visibility="Collapsed"/>
<TextBlock x:Name="StatsTextBlock1" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsTextBlock2" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsTextBlock3" Style="{StaticResource CharacterAttributeTextStyle}"/>
<TextBlock x:Name="StatsTextBlock4" Style="{StaticResource CharacterAttributeTextStyle}"/>
<!-- 初始隐藏,有真实伤害时显示 -->
<TextBlock x:Name="StatsDamagePerSecondTurnTextBlock" Style="{StaticResource CharacterAttributeTextStyle}"/>
</StackPanel>

View File

@ -1,7 +1,9 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
@ -151,6 +153,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 用于 UI 绑定的 ViewModel 集合
public ObservableCollection<CharacterQueueItemViewModel> CharacterQueueDisplayItems { get; } = [];
public ObservableCollection<CharacterViewModel> TeammateCharacters { get; set; } = [];
public ObservableCollection<CharacterViewModel> EnemyCharacters { get; set; } = [];
// 技能组
public CharacterSkillsAndItemsViewModel CharacterSkillsAndItems { get; set; } = new();
@ -340,7 +344,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
return;
}
int maxLines = 300;
int maxLines = 150;
// 获取 FlowDocument
FlowDocument doc = DebugLogRichTextBox.Document;
@ -423,7 +427,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
Canvas.SetLeft(rect, grid.X * CurrentGameMap.Size);
Canvas.SetTop(rect, grid.Y * CurrentGameMap.Size);
Panel.SetZIndex(rect, 0); // 确保格子在底部
Panel.SetZIndex(rect, 5); // 确保格子在底部,但留出一些空间。
rect.MouseLeftButtonDown += Grid_MouseLeftButtonDown;
@ -438,6 +442,22 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
GameMapCanvas.Width = maxCanvasWidth;
GameMapCanvas.Height = maxCanvasHeight;
if (_controller.TeamMode && PlayerCharacter != null)
{
List<Team> teams = _controller.GetTeams();
foreach (Team team in teams)
{
if (team.IsOnThisTeam(PlayerCharacter))
{
TeammateTextBlock.Text = team.Name;
}
else
{
EnemyTextBlock.Text = team.Name;
}
}
}
}
/// <summary>
@ -519,6 +539,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
characterBorder.Background = Brushes.Gray;
}
characterBorder.Child = characterText;
characterBorder.BorderBrush = character.Promotion switch
{
200 => Brushes.BurlyWood,
300 => Brushes.SkyBlue,
400 => Brushes.Orchid,
_ => Brushes.Salmon
};
characterBorder.BorderThickness = new Thickness(2);
// 设置位置
Canvas.SetLeft(characterBorder, grid.X * CurrentGameMap.Size + offset);
@ -533,25 +561,26 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
_uiElementToCharacter.Add(characterBorder, character);
}
// 清除所有角色的高亮
foreach (Character character in _characterToUiElement.Keys)
{
Border border = _characterToUiElement[character];
border.BorderBrush = character.Promotion switch
{
200 => Brushes.BurlyWood,
300 => Brushes.SkyBlue,
400 => Brushes.Orchid,
_ => Brushes.Salmon
};
border.BorderThickness = new Thickness(2);
}
// 如果处于目标选择模式,重新应用高亮
if (_isSelectingTargets)
{
UpdateCharacterHighlights();
}
if (_controller.TeamMode && PlayerCharacter != null)
{
List<Team> teams = _controller.GetTeams();
if (teams.Count > 0)
{
PointsTextBlock.Visibility = Visibility.Visible;
PointsTextBlock.Text = $"{string.Join(" : ", teams.OrderBy(t => t.IsOnThisTeam(PlayerCharacter) ? 0 : 1).Select(t => $"{t.Name} ({t.Score})"))}";
}
}
else
{
PointsTextBlock.Visibility = Visibility.Visible;
PointsTextBlock.Text = $"剩余 {CharacterQueueDisplayItems.Count} 人";
}
}
/// <summary>
@ -829,14 +858,10 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
// 清空所有统计文本块
StatsRatingKillsAssistsDeathsTextBlock.Text = "";
StatsLiveTimeRoundTurnTextBlock.Text = "";
StatsControlHealShieldTextBlock.Text = "";
StatsTotalDamageTextBlock.Text = "";
StatsTotalTakenDamageTextBlock.Text = "";
StatsTrueDamageTextBlock.Text = "";
StatsDamagePerSecondTurnTextBlock.Text = "";
StatsTrueDamageTextBlock.Visibility = Visibility.Collapsed; // 默认隐藏真实伤害行
StatsTextBlock1.Text = "";
StatsTextBlock2.Text = "";
StatsTextBlock3.Text = "";
StatsTextBlock4.Text = "";
// 尝试将传入的 CharacterStatistics 对象转换为 dynamic 类型,以便访问其属性
Dictionary<Character, CharacterStatistics> dict = CharacterStatistics;
@ -845,46 +870,19 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
CharacterStatistics? stats = dict.Where(kv => kv.Key == CurrentCharacter).Select(kv => kv.Value).FirstOrDefault();
if (stats != null)
{
// 第一行:技术得分 / 击杀数 / 助攻数 / 死亡数
StatsRatingKillsAssistsDeathsTextBlock.Text = $"技术得分:{FunGameService.CalculateRating(stats):0.0#} / 击杀数:{stats.Kills} / 助攻数:{stats.Assists} / 死亡数:{stats.Deaths}";
// 第二行:存活时长 / 存活回合数 / 行动回合数
StatsLiveTimeRoundTurnTextBlock.Text = $"存活时长:{stats.LiveTime:0.##} / 存活回合数:{stats.LiveRound} / 行动回合数:{stats.ActionTurn}";
// 第三行:控制时长 / 总计治疗 / 护盾抵消
StatsControlHealShieldTextBlock.Text = $"控制时长:{stats.ControlTime:0.##} / 总计治疗:{stats.TotalHeal:0.##} / 护盾抵消:{stats.TotalShield:0.##}";
// 第四行:总计伤害 / 总计物理伤害 / 总计魔法伤害
StatsTotalDamageTextBlock.Text = $"总计伤害:{stats.TotalDamage:0.##} / 总计物理伤害:{stats.TotalPhysicalDamage:0.##} / 总计魔法伤害:{stats.TotalMagicDamage:0.##}";
// 第五行:总承受伤害 / 总承受物理伤害 / 总承受魔法伤害
StatsTotalTakenDamageTextBlock.Text = $"总承受伤害:{stats.TotalTakenDamage:0.##} / 总承受物理伤害:{stats.TotalTakenPhysicalDamage:0.##} / 总承受魔法伤害:{stats.TotalTakenMagicDamage:0.##}";
// 第六行:总计真实伤害 / 总承受真实伤害 (如果存在真实伤害则显示)
if (stats.TotalTrueDamage > 0 || stats.TotalTakenTrueDamage > 0)
{
StatsTrueDamageTextBlock.Text = $"总计真实伤害:{stats.TotalTrueDamage:0.##} / 总承受真实伤害:{stats.TotalTakenTrueDamage:0.##}";
StatsTrueDamageTextBlock.Visibility = Visibility.Visible;
}
else
{
StatsTrueDamageTextBlock.Visibility = Visibility.Collapsed;
}
// 第七行:每秒伤害 / 每回合伤害
StatsDamagePerSecondTurnTextBlock.Text = $"每秒伤害:{stats.DamagePerSecond:0.##} / 每回合伤害:{stats.DamagePerTurn:0.##}";
StatsTextBlock1.Text = $"击杀数:{stats.Kills} / 助攻数:{stats.Assists} / 死亡数:{stats.Deaths} / 每秒伤害:{stats.DamagePerSecond:0.##} / 每回合伤害:{stats.DamagePerTurn:0.##}";
StatsTextBlock2.Text = $"存活时长:{stats.LiveTime:0.##} / 存活回合数:{stats.LiveRound} / 行动回合数:{stats.ActionTurn} / 控制时长:{stats.ControlTime:0.##} / 总计治疗:{stats.TotalHeal:0.##} / 护盾抵消:{stats.TotalShield:0.##}";
StatsTextBlock3.Text = $"总计伤害:{stats.TotalDamage:0.##} / 总计物理伤害:{stats.TotalPhysicalDamage:0.##} / 总计魔法伤害:{stats.TotalMagicDamage:0.##} / 总计真实伤害:{stats.TotalTrueDamage:0.##}";
StatsTextBlock4.Text = $"总承受伤害:{stats.TotalTakenDamage:0.##} / 总承受物理伤害:{stats.TotalTakenPhysicalDamage:0.##} / 总承受魔法伤害:{stats.TotalTakenMagicDamage:0.##} / 总承受真实伤害:{stats.TotalTakenTrueDamage:0.##}";
}
}
else
{
// 当没有统计数据时,显示默认文本
StatsRatingKillsAssistsDeathsTextBlock.Text = "技术得分: - / 击杀数: - / 助攻数: -";
StatsLiveTimeRoundTurnTextBlock.Text = "存活时长: - / 存活回合数: - / 行动回合数: -";
StatsControlHealShieldTextBlock.Text = "控制时长: - / 总计治疗: - / 护盾抵消: -";
StatsTotalDamageTextBlock.Text = "总计伤害: - / 总计物理伤害: - / 总计魔法伤害: -";
StatsTotalTakenDamageTextBlock.Text = "总承受伤害: - / 总承受物理伤害: - / 总承受魔法伤害: -";
StatsTrueDamageTextBlock.Text = "总计真实伤害: - / 总承受真实伤害: -";
StatsDamagePerSecondTurnTextBlock.Text = "每秒伤害: - / 每回合伤害: -";
StatsTextBlock1.Text = "击杀数:- / 助攻数:- / 死亡数:- / 每秒伤害:- / 每回合伤害:-";
StatsTextBlock2.Text = "存活时长:- / 存活回合数:- / 行动回合数:- / 控制时长:- / 总计治疗:- / 护盾抵消:-";
StatsTextBlock3.Text = "总计伤害:- / 总计物理伤害:- / 总计魔法伤害:- / 总计真实伤害:-";
StatsTextBlock4.Text = "总承受伤害:- / 总承受物理伤害:- / 总承受魔法伤害:- / 总承受真实伤害:-";
}
}
@ -945,17 +943,57 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
}
/// <summary>
/// 处理角色列表项的点击事件。模拟地图上点击角色的行为。
/// </summary>
private async void CharacterSummary_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 确保点击的是一个 Border 且其 Tag 绑定了 CharacterViewModel
if (sender is Border border && border.Tag is CharacterViewModel vm)
{
Character clickedCharacter = vm.Character; // 从 ViewModel 中获取实际的 Character 对象
if (_isSelectingTargets)
{
await HandleTargetSelectionClick(clickedCharacter);
}
else if (CurrentGameMap != null && CurrentGameMap.Characters.TryGetValue(clickedCharacter, out Grid? characterGrid))
{
ClearGridHighlights();
if (_gridIdToUiElement.TryGetValue(characterGrid.Id, out Rectangle? gridRect))
{
gridRect.Stroke = Brushes.Red;
gridRect.StrokeThickness = 2;
}
UpdateGridInfoPanel(characterGrid);
await AppendDebugLog($"选中角色: {clickedCharacter.ToStringWithLevel()} (通过侧边面板点击)");
}
else
{
await AppendDebugLog($"错误: 无法找到角色 {clickedCharacter.NickName} 所在的格子。");
// 此时可以隐藏格子信息面板
GridInfoPanel.Visibility = Visibility.Collapsed;
}
// 标记事件已处理,防止冒泡到下方的 Grid_MouseLeftButtonDown 或 GameMapCanvas_MouseLeftButtonDown
e.Handled = true;
}
}
/// <summary>
/// 处理角色图标点击事件:选中角色并高亮其所在格子,或进行目标选择。
/// </summary>
private void CharacterIcon_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
private async void CharacterIcon_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Border clickedBorder && _uiElementToCharacter.TryGetValue(clickedBorder, out Character? character))
{
if (_isSelectingTargets)
{
// 如果处于目标选择模式,则处理目标选择逻辑
HandleTargetSelectionClick(character);
await HandleTargetSelectionClick(character);
}
else
{
@ -974,7 +1012,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
UpdateGridInfoPanel(grid);
}
_ = AppendDebugLog($"选中角色: {character.ToStringWithLevel()} (通过点击图标)");
await AppendDebugLog($"选中角色: {character.ToStringWithLevel()} (通过点击图标)");
}
e.Handled = true; // 阻止事件冒泡到下方的Grid_MouseLeftButtonDown 或 GameMapCanvas_MouseLeftButtonDown
}
@ -1570,12 +1608,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// 处理在目标选择模式下点击角色图标的逻辑。
/// </summary>
/// <param name="clickedCharacter">被点击的角色。</param>
private void HandleTargetSelectionClick(Character clickedCharacter)
private async Task HandleTargetSelectionClick(Character clickedCharacter)
{
// 检查是否是潜在目标
if (_potentialTargetsForSelection == null || !_potentialTargetsForSelection.Contains(clickedCharacter))
{
_ = AppendDebugLog($"无法选择 {clickedCharacter.NickName}:不是潜在目标。");
await AppendDebugLog($"无法选择 {clickedCharacter.NickName}:不是潜在目标。");
return;
}
@ -1600,7 +1638,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
if (!isValidTarget)
{
_ = AppendDebugLog($"无法选择 {clickedCharacter.NickName}:不符合目标选择规则。");
await AppendDebugLog($"无法选择 {clickedCharacter.NickName}:不符合目标选择规则。");
return;
}
@ -1612,7 +1650,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
}
else
{
_ = AppendDebugLog($"已达到最大目标数量 ({_maxTargetsForSelection})。");
await AppendDebugLog($"已达到最大目标数量 ({_maxTargetsForSelection})。");
}
}
UpdateCharacterHighlights(); // 更新地图上的高亮显示
@ -1623,27 +1661,32 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// </summary>
private void UpdateCharacterHighlights()
{
// 高亮潜在目标(黄色边框)
if (_potentialTargetsForSelection != null)
foreach (Character character in _characterToUiElement.Keys)
{
foreach (Character potentialTarget in _potentialTargetsForSelection)
{
if (_characterToUiElement.TryGetValue(potentialTarget, out Border? border))
{
border.BorderBrush = Brushes.Yellow;
border.BorderThickness = new Thickness(4);
}
}
}
Border border = _characterToUiElement[character];
// 高亮当前已选目标(红色边框)
foreach (Character selectedTarget in SelectedTargets)
{
if (_characterToUiElement.TryGetValue(selectedTarget, out Border? border))
// 恢复默认
border.BorderBrush = character.Promotion switch
{
200 => Brushes.BurlyWood,
300 => Brushes.SkyBlue,
400 => Brushes.Orchid,
_ => Brushes.Salmon
};
border.BorderThickness = new Thickness(2);
if (SelectedTargets.Contains(character))
{
// 高亮当前已选目标(红色边框)
border.BorderBrush = Brushes.Red; // 已选目标颜色
border.BorderThickness = new Thickness(6);
}
else if (_potentialTargetsForSelection.Contains(character))
{
// 高亮潜在目标(黄色边框)
border.BorderBrush = Brushes.Yellow;
border.BorderThickness = new Thickness(4);
}
}
}

View File

@ -110,4 +110,24 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
public Character Character { get; set; } = character;
public double ATDelay { get; set; } = atDelay;
}
public class CharacterViewModel(Character character) : INotifyPropertyChanged
{
public Character Character
{
get => _character;
set
{
_character = value;
OnPropertyChanged();
}
}
private Character _character = character;
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -30,11 +30,11 @@ FunGameService.InitFunGame();
FunGameSimulation.InitFunGameSimulation();
FunGameController controller = new(new Logger<FunGameController>(new LoggerFactory()));
HorseTest.HorseTest1();
//HorseTest.HorseTest1();
StoreTest.StoreTest1();
//StoreTest.StoreTest1();
await CharacterTest.CharacterTest2();
//await CharacterTest.CharacterTest2();
//ActivityTest.Test2();
@ -50,14 +50,14 @@ await CharacterTest.CharacterTest2();
// m.Level = 1;
// Console.WriteLine(m.GetInfo());
//}
foreach (Character c in FunGameConstant.Characters)
{
Character character = c.Copy();
character.Level = 1;
character.Recovery();
FunGameService.AddCharacterSkills(character, 1, 6, 6);
Console.WriteLine(character.GetInfo());
}
//foreach (Character c in FunGameConstant.Characters)
//{
// Character character = c.Copy();
// character.Level = 1;
// character.Recovery();
// FunGameService.AddCharacterSkills(character, 1, 6, 6);
// Console.WriteLine(character.GetInfo());
//}
//foreach (Skill s in FunGameConstant.Skills)
//{
// s.Level = 6;
@ -74,15 +74,15 @@ Console.ReadKey();
//Console.WriteLine(rounds.Count);
//Console.ReadKey();
//rounds.Clear();
while (true)
{
await FunGameBO5.StartBO5();
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.Escape)
{
break;
}
}
//while (true)
//{
// await FunGameBO5.StartBO5();
// ConsoleKeyInfo key = Console.ReadKey();
// if (key.Key == ConsoleKey.Escape)
// {
// break;
// }
//}
//await FunGameTesting.StartGame(true, false);
//Console.ReadKey();