普攻添加选取目标的方法

This commit is contained in:
milimoe 2025-09-03 01:13:20 +08:00
parent 86e4611656
commit 1fc654df06
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
4 changed files with 158 additions and 78 deletions

View File

@ -1,4 +1,5 @@
using Milimoe.FunGame.Core.Entity; using System.Threading.Tasks;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
@ -55,14 +56,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
); );
} }
public async Task<List<Character>> RequestTargetSelection(Character actor, List<Character> potentialTargets, ISkill skill, long maxTargets, bool canSelectSelf, bool canSelectEnemy, bool canSelectTeammate) public async Task<List<Character>> RequestTargetSelection(Character character, ISkill skill, List<Character> enemys, List<Character> teammates)
{ {
await WriteLine($"请为 {actor.NickName} 选择目标 (最多 {maxTargets} 个)。"); await WriteLine($"请为 {character.NickName} 选择目标 (最多 {skill.CanSelectTargetCount} 个)。");
List<Character> targetIds = await _targetSelectionRequester.RequestInput( List<Character> targetIds = await _targetSelectionRequester.RequestInput(
(callback) => UI.Invoke(() => UI.ShowTargetSelectionUI(actor, potentialTargets, skill, maxTargets, canSelectSelf, canSelectEnemy, canSelectTeammate, callback)) (callback) => UI.Invoke(() => UI.ShowTargetSelectionUI(character, skill, enemys, teammates, callback))
) ?? []; ) ?? [];
if (targetIds == null) return []; if (targetIds == null) return [];
return [.. potentialTargets.Where(targetIds.Contains)]; return [.. enemys.Where(targetIds.Contains), .. teammates.Where(targetIds.Contains)];
} }
public async Task<Skill?> RequestSkillSelection(Character character, List<Skill> availableSkills) public async Task<Skill?> RequestSkillSelection(Character character, List<Skill> availableSkills)
@ -154,19 +155,19 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
return false; return false;
} }
public void UpdateBottomInfoPanel() public async Task UpdateBottomInfoPanel()
{ {
UI.Invoke(UI.UpdateBottomInfoPanel); await UI.Invoke(UI.UpdateBottomInfoPanel);
} }
public void UpdateQueue() public async Task UpdateQueue()
{ {
UI.Invoke(UI.UpdateLeftQueuePanel); await UI.Invoke(UI.UpdateLeftQueuePanel);
} }
public void UpdateCharacterPositionsOnMap() public async Task UpdateCharacterPositionsOnMap()
{ {
UI.Invoke(UI.UpdateCharacterPositionsOnMap); await UI.Invoke(UI.UpdateCharacterPositionsOnMap);
} }
public void SetQueue(Dictionary<Character, double> dict) public void SetQueue(Dictionary<Character, double> dict)

View File

@ -219,8 +219,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 检查是否有角色可以行动 // 检查是否有角色可以行动
Character? characterToAct = await _gamingQueue.NextCharacterAsync(); Character? characterToAct = await _gamingQueue.NextCharacterAsync();
Controller.UpdateQueue(); await Controller.UpdateQueue();
Controller.UpdateCharacterPositionsOnMap(); await Controller.UpdateCharacterPositionsOnMap();
// 处理回合 // 处理回合
if (characterToAct != null) if (characterToAct != null)
@ -252,9 +252,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
double timeLapse = await _gamingQueue.TimeLapse(); double timeLapse = await _gamingQueue.TimeLapse();
totalTime += timeLapse; totalTime += timeLapse;
nextDropItemTime -= timeLapse; nextDropItemTime -= timeLapse;
Controller.UpdateBottomInfoPanel(); await Controller.UpdateBottomInfoPanel();
Controller.UpdateQueue(); await Controller.UpdateQueue();
Controller.UpdateCharacterPositionsOnMap(); await Controller.UpdateCharacterPositionsOnMap();
if (roundMsg != "") if (roundMsg != "")
{ {
@ -390,7 +390,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private async Task GamingQueue_CharacterMove(GamingQueue queue, Character actor, Grid grid) private async Task GamingQueue_CharacterMove(GamingQueue queue, Character actor, Grid grid)
{ {
Controller.UpdateCharacterPositionsOnMap(); await Controller.UpdateCharacterPositionsOnMap();
await Task.CompletedTask; await Task.CompletedTask;
} }
@ -398,7 +398,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
if (reason != QueueUpdatedReason.Action) if (reason != QueueUpdatedReason.Action)
{ {
Controller.UpdateQueue(); await Controller.UpdateQueue();
} }
if (IsPlayer_OnlyTest(queue, character)) if (IsPlayer_OnlyTest(queue, character))
{ {
@ -418,7 +418,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private async Task<bool> GamingQueue_TurnStart(GamingQueue queue, Character character, List<Character> enemys, List<Character> teammates, List<Skill> skills, List<Item> items) private async Task<bool> GamingQueue_TurnStart(GamingQueue queue, Character character, List<Character> enemys, List<Character> teammates, List<Skill> skills, List<Item> items)
{ {
Controller.UpdateBottomInfoPanel(); await Controller.UpdateBottomInfoPanel();
if (IsPlayer_OnlyTest(queue, character)) if (IsPlayer_OnlyTest(queue, character))
{ {
// 确保玩家角色在回合开始时取消AI托管以便玩家可以控制 // 确保玩家角色在回合开始时取消AI托管以便玩家可以控制
@ -432,20 +432,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
if (!IsPlayer_OnlyTest(queue, character)) return []; if (!IsPlayer_OnlyTest(queue, character)) return [];
List<Character> potentialTargets = [];
if (attack.CanSelectEnemy) potentialTargets.AddRange(enemys);
if (attack.CanSelectTeammate) potentialTargets.AddRange(teammates);
if (attack.CanSelectSelf) potentialTargets.Add(character);
// 通过UI请求目标选择 // 通过UI请求目标选择
List<Character> selectedTargets = await Controller.RequestTargetSelection( List<Character> selectedTargets = await Controller.RequestTargetSelection(
character, character,
potentialTargets,
attack, attack,
attack.CanSelectTargetCount, enemys,
attack.CanSelectSelf, teammates
attack.CanSelectEnemy,
attack.CanSelectTeammate
); );
Controller.ResolveTargetSelection(selectedTargets); Controller.ResolveTargetSelection(selectedTargets);
@ -474,12 +466,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 通过UI请求目标选择 // 通过UI请求目标选择
List<Character>? selectedTargets = await Controller.RequestTargetSelection( List<Character>? selectedTargets = await Controller.RequestTargetSelection(
caster, caster,
potentialTargets,
skill, skill,
skill.CanSelectTargetCount, enemys,
skill.CanSelectSelf, teammates
skill.CanSelectEnemy,
skill.CanSelectTeammate
); );
Controller.ResolveTargetSelection(selectedTargets); Controller.ResolveTargetSelection(selectedTargets);
@ -500,7 +489,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
double ht = queue.HardnessTime[character]; double ht = queue.HardnessTime[character];
Controller.SetPredictCharacter(character.NickName, ht); Controller.SetPredictCharacter(character.NickName, ht);
Controller.UpdateBottomInfoPanel(); await Controller.UpdateBottomInfoPanel();
if (IsRoundHasPlayer_OnlyTest(queue, character)) if (IsRoundHasPlayer_OnlyTest(queue, character))
{ {
// 玩家回合结束,等待玩家确认 // 玩家回合结束,等待玩家确认

View File

@ -119,9 +119,9 @@
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="0.3*"/>
<!-- 左侧动态队列 --> <!-- 左侧动态队列 -->
<ColumnDefinition Width="*"/> <ColumnDefinition Width="1*"/>
<!-- 地图区域 --> <!-- 地图区域 -->
<ColumnDefinition Width="0.8*"/> <ColumnDefinition Width="0.8*"/>
<!-- 新增:右侧调试日志 --> <!-- 新增:右侧调试日志 -->
@ -407,11 +407,46 @@
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="0,0,0,1" Padding="2" Margin="0,2"> <Border BorderBrush="LightGray" BorderThickness="0,0,0,1" Padding="2" Margin="0,2">
<StackPanel Orientation="Horizontal"> <Grid>
<TextBlock Text="{Binding NickName}" FontWeight="SemiBold" Margin="0,0,5,0"/> <Grid.ColumnDefinitions>
<Button Content="X" Margin="5,0,0,0" Tag="{Binding Id}" Click="RemoveTarget_Click" <ColumnDefinition Width="*"/>
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"/> <!-- 用于名称和属性条 -->
<ColumnDefinition Width="Auto"/>
<!-- 用于 "X" 按钮 -->
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<!-- 角色名称 -->
<TextBlock Text="{Binding NickName}" FontWeight="SemiBold" Margin="0,0,5,0" FontSize="11"/>
<!-- HP 条 -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,1">
<TextBlock Text="HP:" VerticalAlignment="Center" Width="25" FontSize="9"/>
<ProgressBar Value="{Binding HP}" Maximum="{Binding MaxHP}" Height="8" Width="100" Background="LightGray" BorderBrush="Gray" BorderThickness="0.5" Foreground="Green"/>
<TextBlock Text="{Binding HP, StringFormat={}{0:0.##}}" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="9"/>
<TextBlock Text="{Binding MaxHP, StringFormat=/{0:0.##}}" VerticalAlignment="Center" FontSize="9"/>
</StackPanel> </StackPanel>
<!-- MP 条 -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,1">
<TextBlock Text="MP:" VerticalAlignment="Center" Width="25" FontSize="9"/>
<ProgressBar Value="{Binding MP}" Maximum="{Binding MaxMP}" Height="8" Width="100" Background="LightGray" BorderBrush="Gray" BorderThickness="0.5" Foreground="Blue"/>
<TextBlock Text="{Binding MP, StringFormat={}{0:0.##}}" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="9"/>
<TextBlock Text="{Binding MaxMP, StringFormat=/{0:0.##}}" VerticalAlignment="Center" FontSize="9"/>
</StackPanel>
<!-- EP 条 -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,1">
<TextBlock Text="EP:" VerticalAlignment="Center" Width="25" FontSize="9"/>
<ProgressBar Value="{Binding EP}" Maximum="{Binding GameplayEquilibriumConstant.MaxEP}" Height="8" Width="100" Background="LightGray" BorderBrush="Gray" BorderThickness="0.5" Foreground="Orange"/>
<TextBlock Text="{Binding EP, StringFormat={}{0:0.##}}" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="9"/>
<TextBlock Text="{Binding GameplayEquilibriumConstant.MaxEP, StringFormat=/{0:0.##}}" VerticalAlignment="Center" FontSize="9"/>
</StackPanel>
</StackPanel>
<!-- 移除按钮 -->
<Button Grid.Column="1" Content="X" Margin="5,0,0,0" Tag="{Binding Id}" Click="RemoveTarget_Click"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" VerticalAlignment="Center"/>
</Grid>
</Border> </Border>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>

View File

@ -3,6 +3,7 @@ using System.Collections.Specialized;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
@ -62,7 +63,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private Character? _actingCharacterForTargetSelection; private Character? _actingCharacterForTargetSelection;
private List<Character> _potentialTargetsForSelection = []; private List<Character> _potentialTargetsForSelection = [];
private long _maxTargetsForSelection; private long _maxTargetsForSelection;
private bool _canSelectSelf, _canSelectEnemy, _canSelectTeammate; private bool _canSelectAllTeammates, _canSelectAllEnemies, _canSelectSelf, _canSelectEnemy, _canSelectTeammate;
private bool _isSelectingTargets = false; // 标记当前是否处于目标选择模式 private bool _isSelectingTargets = false; // 标记当前是否处于目标选择模式
private readonly CharacterQueueItem _selectionPredictCharacter = new(Factory.GetCharacter(), 0); // 选择时进行下轮预测(用于行动顺序表显示) private readonly CharacterQueueItem _selectionPredictCharacter = new(Factory.GetCharacter(), 0); // 选择时进行下轮预测(用于行动顺序表显示)
@ -212,7 +213,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
if (!this.Dispatcher.CheckAccess()) if (!this.Dispatcher.CheckAccess())
{ {
await this.Dispatcher.BeginInvoke(async () => await action()); await this.Dispatcher.InvokeAsync(async () => await action());
} }
else await action(); else await action();
} }
@ -232,8 +233,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private static void OnCurrentGameMapChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnCurrentGameMapChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
GameMapViewer viewer = (GameMapViewer)d; GameMapViewer viewer = (GameMapViewer)d;
viewer.RenderMap(); _ = viewer.RenderMap();
viewer.UpdateCharacterPositionsOnMap(); _ = viewer.UpdateCharacterPositionsOnMap();
} }
// CurrentRound // CurrentRound
@ -285,8 +286,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private static void OnCurrentCharacterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnCurrentCharacterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
GameMapViewer viewer = (GameMapViewer)d; GameMapViewer viewer = (GameMapViewer)d;
viewer.UpdateBottomInfoPanel(); _ = viewer.UpdateBottomInfoPanel();
viewer.UpdateCharacterStatisticsPanel(); // 角色改变时也更新统计面板 _ = viewer.UpdateCharacterStatisticsPanel(); // 角色改变时也更新统计面板
// 角色改变时,清除装备/状态描述 // 角色改变时,清除装备/状态描述
SetRichTextBoxText(viewer.DescriptionRichTextBox, "点击装备或状态图标查看详情。"); SetRichTextBoxText(viewer.DescriptionRichTextBox, "点击装备或状态图标查看详情。");
viewer.ClearEquipSlotHighlights(); viewer.ClearEquipSlotHighlights();
@ -297,21 +298,21 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private static void OnCharacterQueueDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnCharacterQueueDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
GameMapViewer viewer = (GameMapViewer)d; GameMapViewer viewer = (GameMapViewer)d;
viewer.UpdateLeftQueuePanel(); _ = viewer.UpdateLeftQueuePanel();
} }
// 新增当CharacterStatistics属性改变时更新数据统计面板 // 新增当CharacterStatistics属性改变时更新数据统计面板
private static void OnCharacterStatisticsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnCharacterStatisticsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
GameMapViewer viewer = (GameMapViewer)d; GameMapViewer viewer = (GameMapViewer)d;
viewer.UpdateCharacterStatisticsPanel(); _ = viewer.UpdateCharacterStatisticsPanel();
} }
// 新增当MaxRespawnTimes属性改变时更新数据统计面板因为会影响死亡数显示 // 新增当MaxRespawnTimes属性改变时更新数据统计面板因为会影响死亡数显示
private static void OnMaxRespawnTimesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnMaxRespawnTimesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
GameMapViewer viewer = (GameMapViewer)d; GameMapViewer viewer = (GameMapViewer)d;
viewer.UpdateCharacterStatisticsPanel(); _ = viewer.UpdateCharacterStatisticsPanel();
} }
/// <summary> /// <summary>
@ -323,7 +324,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 检查当前线程是否是UI线程 // 检查当前线程是否是UI线程
if (!this.Dispatcher.CheckAccess()) if (!this.Dispatcher.CheckAccess())
{ {
await this.Dispatcher.BeginInvoke(new Action(async () => await AppendDebugLog(message))); await this.Dispatcher.InvokeAsync(async () => await AppendDebugLog(message));
return; return;
} }
@ -369,8 +370,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 渲染地图根据CurrentGameMap对象在Canvas上绘制所有格子 /// 渲染地图根据CurrentGameMap对象在Canvas上绘制所有格子
/// </summary> /// </summary>
private void RenderMap() private async Task RenderMap()
{ {
if (!this.Dispatcher.CheckAccess())
{
await this.Dispatcher.InvokeAsync(async () => await RenderMap());
return;
}
GameMapCanvas.Children.Clear(); // 清除Canvas上所有旧的UI元素 (包括角色图标,后续会重新绘制) GameMapCanvas.Children.Clear(); // 清除Canvas上所有旧的UI元素 (包括角色图标,后续会重新绘制)
_gridIdToUiElement.Clear(); // 清除旧的关联 _gridIdToUiElement.Clear(); // 清除旧的关联
_uiElementToGrid.Clear(); // 清除旧的关联 _uiElementToGrid.Clear(); // 清除旧的关联
@ -424,11 +431,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 在地图上更新所有角色的位置和显示。 /// 在地图上更新所有角色的位置和显示。
/// </summary> /// </summary>
public void UpdateCharacterPositionsOnMap() /// <summary>
/// 在地图上更新所有角色的位置和显示。
/// </summary>
public async Task UpdateCharacterPositionsOnMap()
{ {
if (!this.Dispatcher.CheckAccess()) if (!this.Dispatcher.CheckAccess())
{ {
this.Dispatcher.Invoke(() => UpdateCharacterPositionsOnMap()); await this.Dispatcher.InvokeAsync(async () => await UpdateCharacterPositionsOnMap());
return; return;
} }
@ -463,11 +473,39 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
IsHitTestVisible = true // 确保角色图标可以被点击 IsHitTestVisible = true // 确保角色图标可以被点击
}; };
// --- 根据HP动态设置背景颜色 END ---
TextBlock characterText = new() TextBlock characterText = new()
{ {
Style = (Style)this.FindResource("CharacterIconTextStyle"), Style = (Style)this.FindResource("CharacterIconTextStyle"),
Text = character.NickName.Length > 0 ? character.NickName[0].ToString().ToUpper() : "?" Text = character.NickName.Length > 0 ? character.NickName[0].ToString().ToUpper() : "?"
}; };
// --- 根据HP动态设置背景颜色 START ---
double hpPercentage = character.HP / character.MaxHP;
if (hpPercentage > 0.75)
{
characterBorder.Background = Brushes.Green;
}
else if (hpPercentage > 0.50)
{
characterBorder.Background = Brushes.Yellow;
characterText.Foreground = Brushes.Black;
}
else if (hpPercentage > 0.25)
{
characterBorder.Background = Brushes.Orange;
characterText.Foreground = Brushes.Black;
}
else if (hpPercentage > 0)
{
characterBorder.Background = Brushes.Red;
}
else
{
characterBorder.Background = Brushes.Gray;
}
characterBorder.Child = characterText; characterBorder.Child = characterText;
// 设置位置 // 设置位置
@ -493,12 +531,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 更新左侧动态队列面板显示角色及其AT Delay。 /// 更新左侧动态队列面板显示角色及其AT Delay。
/// </summary> /// </summary>
public void UpdateLeftQueuePanel() public async Task UpdateLeftQueuePanel()
{ {
// 确保在UI线程上执行 // 确保在UI线程上执行
if (!this.Dispatcher.CheckAccess()) if (!this.Dispatcher.CheckAccess())
{ {
this.Dispatcher.Invoke(() => UpdateLeftQueuePanel()); await this.Dispatcher.InvokeAsync(async () => await UpdateLeftQueuePanel());
return; return;
} }
@ -522,12 +560,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 更新底部信息面板显示当前角色的详细信息、装备和状态。 /// 更新底部信息面板显示当前角色的详细信息、装备和状态。
/// </summary> /// </summary>
public void UpdateBottomInfoPanel() public async Task UpdateBottomInfoPanel()
{ {
// 确保在UI线程上执行 // 确保在UI线程上执行
if (!this.Dispatcher.CheckAccess()) if (!this.Dispatcher.CheckAccess())
{ {
this.Dispatcher.Invoke(() => UpdateBottomInfoPanel()); await this.Dispatcher.InvokeAsync(async () => await UpdateBottomInfoPanel());
return; return;
} }
@ -715,7 +753,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
} }
// 更新数据统计面板 // 更新数据统计面板
UpdateCharacterStatisticsPanel(); await UpdateCharacterStatisticsPanel();
} }
/// <summary> /// <summary>
@ -749,11 +787,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 更新数据统计面板显示指定角色的统计信息。 /// 更新数据统计面板显示指定角色的统计信息。
/// </summary> /// </summary>
public void UpdateCharacterStatisticsPanel() public async Task UpdateCharacterStatisticsPanel()
{ {
if (!this.Dispatcher.CheckAccess()) if (!this.Dispatcher.CheckAccess())
{ {
this.Dispatcher.Invoke(() => UpdateCharacterStatisticsPanel()); await this.Dispatcher.Invoke(async () => await UpdateCharacterStatisticsPanel());
return; return;
} }
@ -1292,32 +1330,49 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 显示目标选择UI。 /// 显示目标选择UI。
/// </summary> /// </summary>
/// <param name="actor">发起行动的角色。</param> /// <param name="character">发起行动的角色。</param>
/// <param name="potentialTargets">所有潜在的可选目标列表。</param> /// <param name="skill">请求选择目标的技能/普攻。</param>
/// <param name="skill">请求选择目标的技能。</param> /// <param name="enemys">所有可选敌方目标列表。</param>
/// <param name="maxTargets">最大可选目标数量。</param> /// <param name="teammates">所有可选友方目标列表。</param>
/// <param name="canSelectSelf">是否可选择自身。</param>
/// <param name="canSelectEnemy">是否可选择敌方。</param>
/// <param name="canSelectTeammate">是否可选择友方。</param>
/// <param name="callback">选择完成后调用的回调函数。</param> /// <param name="callback">选择完成后调用的回调函数。</param>
public void ShowTargetSelectionUI(Character actor, List<Character> potentialTargets, ISkill skill, long maxTargets, bool canSelectSelf, bool canSelectEnemy, bool canSelectTeammate, Action<List<Character>> callback) public void ShowTargetSelectionUI(Character character, ISkill skill, List<Character> enemys, List<Character> teammates, Action<List<Character>> callback)
{ {
_resolveTargetSelection = callback; _resolveTargetSelection = callback;
_actingCharacterForTargetSelection = actor; _actingCharacterForTargetSelection = character;
_potentialTargetsForSelection = potentialTargets; _potentialTargetsForSelection = skill.GetSelectableTargets(character, enemys, teammates);
_maxTargetsForSelection = maxTargets; _maxTargetsForSelection = skill.CanSelectTargetCount;
_canSelectSelf = canSelectSelf; _canSelectAllTeammates = skill.SelectAllTeammates;
_canSelectEnemy = canSelectEnemy; _canSelectAllEnemies = skill.SelectAllEnemies;
_canSelectTeammate = canSelectTeammate; _canSelectSelf = skill.CanSelectSelf;
_canSelectEnemy = skill.CanSelectEnemy;
_canSelectTeammate = skill.CanSelectTeammate;
_isSelectingTargets = true; // 进入目标选择模式 _isSelectingTargets = true; // 进入目标选择模式
SelectedTargets.Clear(); // 清空之前的选择 SelectedTargets.Clear(); // 清空之前的选择
TargetSelectionTitle.Text = $"选择 {actor.NickName} 的目标 (最多 {maxTargets} 个)"; TargetSelectionTitle.Text = $"选择 {character.NickName} 的目标 (最多 {skill.CanSelectTargetCount} 个)";
TargetSelectionOverlay.Visibility = Visibility.Visible; TargetSelectionOverlay.Visibility = Visibility.Visible;
if (_canSelectAllTeammates)
{
foreach (Character teammate in teammates)
{
SelectedTargets.Add(teammate);
}
}
else if (_canSelectAllEnemies)
{
foreach (Character enemy in enemys)
{
SelectedTargets.Add(enemy);
}
}
else if (_canSelectSelf && !_canSelectEnemy && !_canSelectTeammate)
{
SelectedTargets.Add(character);
}
if (!CharacterQueueItems.Contains(_selectionPredictCharacter)) if (!CharacterQueueItems.Contains(_selectionPredictCharacter))
{ {
SetPredictCharacter(actor.NickName, skill.RealHardnessTime); SetPredictCharacter(character.NickName, skill.RealHardnessTime);
} }
// 更新地图上角色的高亮,以显示潜在目标和已选目标 // 更新地图上角色的高亮,以显示潜在目标和已选目标