添加移动选择目标功能

This commit is contained in:
milimoe 2025-09-07 22:42:33 +08:00
parent 0d1f1b5321
commit 146b42bff3
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
4 changed files with 266 additions and 46 deletions

View File

@ -13,11 +13,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
public bool TeamMode => _game?.TeamMode ?? false; public bool TeamMode => _game?.TeamMode ?? false;
// 输入请求器实例 // 输入请求器实例
private readonly UserInputRequester<long> _characterSelectionRequester = new(); private readonly UserInputRequester<Character> _characterSelectionRequester = new();
private readonly UserInputRequester<Grid> _targetGridSelectionRequester = new();
private readonly UserInputRequester<CharacterActionType> _actionTypeRequester = new(); private readonly UserInputRequester<CharacterActionType> _actionTypeRequester = new();
private readonly UserInputRequester<List<Character>> _targetSelectionRequester = new(); private readonly UserInputRequester<List<Character>> _targetSelectionRequester = new();
private readonly UserInputRequester<long> _skillSelectionRequester = new(); private readonly UserInputRequester<Skill> _skillSelectionRequester = new();
private readonly UserInputRequester<long> _itemSelectionRequester = new(); private readonly UserInputRequester<Item> _itemSelectionRequester = new();
private readonly UserInputRequester<bool> _continuePromptRequester = new(); // 用于“按任意键继续”提示 private readonly UserInputRequester<bool> _continuePromptRequester = new(); // 用于“按任意键继续”提示
public async Task WriteLine(string str = "") => await UI.AppendDebugLog(str); public async Task WriteLine(string str = "") => await UI.AppendDebugLog(str);
@ -73,7 +74,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
await UI.InvokeAsync(() => UI.SetPredictCharacter(name, ht)); await UI.InvokeAsync(() => UI.SetPredictCharacter(name, ht));
} }
public async Task<long> RequestCharacterSelection(List<Character> availableCharacters) public async Task<Character?> RequestCharacterSelection(List<Character> availableCharacters)
{ {
await WriteLine("请选择你想玩的角色。"); await WriteLine("请选择你想玩的角色。");
return await _characterSelectionRequester.RequestInput( return await _characterSelectionRequester.RequestInput(
@ -89,6 +90,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
); );
} }
public async Task<Grid?> RequestTargetGridSelection(Character character, Grid currentGrid, List<Grid> selectable)
{
await WriteLine($"请选择一个目标地点。");
return await _targetGridSelectionRequester.RequestInput(
async (callback) => await UI.InvokeAsync(() => UI.ShowTargetGridSelectionUI(character, currentGrid, selectable, callback))
);
}
public async Task<List<Character>> RequestTargetSelection(Character character, ISkill skill, List<Character> enemys, List<Character> teammates) public async Task<List<Character>> RequestTargetSelection(Character character, ISkill skill, List<Character> enemys, List<Character> teammates)
{ {
List<Character> selectable = skill.GetSelectableTargets(character, enemys, teammates); List<Character> selectable = skill.GetSelectableTargets(character, enemys, teammates);
@ -103,19 +112,19 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
public async Task<Skill?> RequestSkillSelection(Character character, List<Skill> availableSkills) public async Task<Skill?> RequestSkillSelection(Character character, List<Skill> availableSkills)
{ {
await WriteLine($"请为 {character.NickName} 选择一个技能。"); await WriteLine($"请为 {character.NickName} 选择一个技能。");
long? skillId = await _skillSelectionRequester.RequestInput( Skill? skill = await _skillSelectionRequester.RequestInput(
async (callback) => await UI.InvokeAsync(() => UI.ShowSkillSelectionUI(character, callback)) async (callback) => await UI.InvokeAsync(() => UI.ShowSkillSelectionUI(character, callback))
); );
return skillId.HasValue ? availableSkills.FirstOrDefault(s => s.Id == skillId.Value) : null; return availableSkills.Any(s => s == skill) ? skill : null;
} }
public async Task<Item?> RequestItemSelection(Character character, List<Item> availableItems) public async Task<Item?> RequestItemSelection(Character character, List<Item> availableItems)
{ {
await WriteLine($"请为 {character.NickName} 选择一个物品。"); await WriteLine($"请为 {character.NickName} 选择一个物品。");
long? itemId = await _itemSelectionRequester.RequestInput( Item? item = await _itemSelectionRequester.RequestInput(
async (callback) => await UI.InvokeAsync(() => UI.ShowItemSelectionUI(character, callback)) async (callback) => await UI.InvokeAsync(() => UI.ShowItemSelectionUI(character, callback))
); );
return itemId.HasValue ? availableItems.FirstOrDefault(i => i.Id == itemId.Value) : null; return availableItems.Any(i => i == item) ? item : null;
} }
public async Task RequestContinuePrompt(string message) public async Task RequestContinuePrompt(string message)
@ -137,9 +146,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// --- GameMapViewer 调用这些方法来解决 UI 输入 --- // --- GameMapViewer 调用这些方法来解决 UI 输入 ---
public async Task ResolveCharacterSelection(long characterId) public async Task ResolveCharacterSelection(Character? character)
{ {
_characterSelectionRequester.ResolveInput(characterId); _characterSelectionRequester.ResolveInput(character);
await UI.InvokeAsync(() => UI.HideCharacterSelectionPrompt()); await UI.InvokeAsync(() => UI.HideCharacterSelectionPrompt());
} }
@ -155,15 +164,21 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
await UI.InvokeAsync(() => UI.HideTargetSelectionUI()); await UI.InvokeAsync(() => UI.HideTargetSelectionUI());
} }
public async Task ResolveSkillSelection(long skillId) public async Task ResolveTargetGridSelection(Grid? grid)
{ {
_skillSelectionRequester.ResolveInput(skillId); _targetGridSelectionRequester.ResolveInput(grid);
await UI.InvokeAsync(() => UI.HideTargetGridSelectionUI());
}
public async Task ResolveSkillSelection(Skill? skill)
{
_skillSelectionRequester.ResolveInput(skill);
await UI.InvokeAsync(() => UI.HideSkillSelectionUI()); await UI.InvokeAsync(() => UI.HideSkillSelectionUI());
} }
public async Task ResolveItemSelection(long itemId) public async Task ResolveItemSelection(Item? item)
{ {
_itemSelectionRequester.ResolveInput(itemId); _itemSelectionRequester.ResolveInput(item);
await UI.InvokeAsync(() => UI.HideItemSelectionUI()); await UI.InvokeAsync(() => UI.HideItemSelectionUI());
} }

View File

@ -59,11 +59,16 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
c.Level = clevel; c.Level = clevel;
c.NormalAttack.Level = mlevel; c.NormalAttack.Level = mlevel;
FunGameService.AddCharacterSkills(c, 1, slevel, slevel); FunGameService.AddCharacterSkills(c, 1, slevel, slevel);
Skill = new (c) Skill skill = new (c)
{ {
Level = slevel Level = slevel
}; };
c.Skills.Add(); c.Skills.Add(skill);
Skill passive = new (c)
{
Level = 1
};
c.Skills.Add(passive);
characters.Add(c); characters.Add(c);
} }
@ -75,11 +80,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 询问玩家需要选择哪个角色 (通过UI界面选择) // 询问玩家需要选择哪个角色 (通过UI界面选择)
Character? player = null; Character? player = null;
long selectedPlayerId = await Controller.RequestCharacterSelection(characters); // 异步等待UI选择 Character? selectedPlayer = await Controller.RequestCharacterSelection(characters); // 异步等待UI选择
await Controller.ResolveCharacterSelection(selectedPlayerId); await Controller.ResolveCharacterSelection(selectedPlayer);
if (selectedPlayerId != -1) if (selectedPlayer != null)
{ {
player = characters.FirstOrDefault(c => c.Id == selectedPlayerId); player = characters.FirstOrDefault(c => c == selectedPlayer);
if (player != null) if (player != null)
{ {
await Controller.WriteLine($"选择了 [ {player} ]"); await Controller.WriteLine($"选择了 [ {player} ]");
@ -303,6 +308,13 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
await Controller.WriteLine($"=== 回合 {i++} ==="); await Controller.WriteLine($"=== 回合 {i++} ===");
await Controller.WriteLine("现在是 [ " + characterToAct + " ] 的回合!"); await Controller.WriteLine("现在是 [ " + characterToAct + " ] 的回合!");
// 获取该角色当前位置
if (_gamingQueue.Map != null)
{
Grid? currentGrid = _gamingQueue.Map.GetCharacterCurrentGrid(characterToAct);
if (currentGrid != null) _gamingQueue.CustomData["currentGrid"] = currentGrid;
}
bool isGameEnd = await _gamingQueue.ProcessTurnAsync(characterToAct); bool isGameEnd = await _gamingQueue.ProcessTurnAsync(characterToAct);
if (isGameEnd) if (isGameEnd)
@ -472,17 +484,32 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private async Task<Grid> GamingQueue_SelectTargetGrid(GamingQueue queue, Character character, List<Character> enemys, List<Character> teammates, GameMap map) private async Task<Grid> GamingQueue_SelectTargetGrid(GamingQueue queue, Character character, List<Character> enemys, List<Character> teammates, GameMap map)
{ {
// 目前格子选择未直接绑定到UI按钮。 if (!IsPlayer_OnlyTest(queue, character) || _gamingQueue is null || _gamingQueue.Map is null) return Grid.Empty;
// 如果“移动”动作被完全实现这里需要一个UI提示来选择目标格子。
// 为简化目前返回一个空Grid。 Grid current = Grid.Empty;
await Task.CompletedTask; // 模拟异步操作 if (_gamingQueue.CustomData.TryGetValue("currentGrid", out object? currentGrid) && currentGrid is Grid grid)
return Grid.Empty; {
current = grid;
}
if (current == Grid.Empty)
{
return current;
}
// 通过UI请求目标选择
Grid? selectedTargetGrid = await Controller.RequestTargetGridSelection(
character,
current,
_gamingQueue.Map.GetGridsByRange(current, character.MOV)
);
await Controller.ResolveTargetGridSelection(selectedTargetGrid);
return selectedTargetGrid ?? Grid.Empty;
} }
private async Task GamingQueue_CharacterMove(GamingQueue queue, Character actor, Grid grid) private async Task GamingQueue_CharacterMove(GamingQueue queue, Character actor, Grid grid)
{ {
await Controller.UpdateCharacterPositionsOnMap(); await Controller.UpdateCharacterPositionsOnMap();
await Task.CompletedTask;
} }
private async Task GamingQueue_QueueUpdated(GamingQueue queue, List<Character> characters, Character character, double hardnessTime, QueueUpdatedReason reason, string msg) private async Task GamingQueue_QueueUpdated(GamingQueue queue, List<Character> characters, Character character, double hardnessTime, QueueUpdatedReason reason, string msg)
@ -521,7 +548,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 通过UI请求物品选择 // 通过UI请求物品选择
Item? selectedItem = await Controller.RequestItemSelection(character, items); Item? selectedItem = await Controller.RequestItemSelection(character, items);
await Controller.ResolveItemSelection(selectedItem?.Id ?? 0); await Controller.ResolveItemSelection(selectedItem);
return selectedItem; return selectedItem;
} }
@ -552,7 +579,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 通过UI请求技能选择 // 通过UI请求技能选择
Skill? selectedSkill = await Controller.RequestSkillSelection(character, skills); Skill? selectedSkill = await Controller.RequestSkillSelection(character, skills);
await Controller.ResolveSkillSelection(selectedSkill?.Id ?? 0); await Controller.ResolveSkillSelection(selectedSkill);
return selectedSkill; return selectedSkill;
} }

View File

@ -542,6 +542,54 @@
</StackPanel> </StackPanel>
</Border> </Border>
<!-- 新增:移动格子选择确认面板 (Overlay) -->
<Border x:Name="TargetGridSelectionOverlay"
Panel.ZIndex="200"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="10"
Width="250"
MaxHeight="300"
Background="#CCFFFFFF"
BorderBrush="DarkRed"
BorderThickness="1"
CornerRadius="5"
Padding="10"
Visibility="Collapsed">
<StackPanel>
<TextBlock x:Name="TargetGridSelectionTitle" Text="选择目标格子" FontWeight="Bold" FontSize="14" Margin="0,0,0,5"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="200">
<ItemsControl x:Name="SelectedTargetGridControl" ItemsSource="{Binding SelectedTargetGrid, RelativeSource={RelativeSource AncestorType=UserControl}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="0,0,0,1" Padding="2" Margin="0,2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<!-- 用于 "X" 按钮 -->
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<!-- 格子信息 -->
<TextBlock Text="{Binding}" FontWeight="SemiBold" Margin="0,0,5,0" FontSize="11"/>
</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>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
<Button Content="确认" Margin="0,0,5,0" Click="ConfirmTargetGrid_Click"/>
<Button Content="取消" Click="CancelTargetGridSelection_Click"/>
</StackPanel>
</StackPanel>
</Border>
<!-- 新增:继续提示面板 (Overlay) --> <!-- 新增:继续提示面板 (Overlay) -->
<Border x:Name="ContinuePromptOverlay" <Border x:Name="ContinuePromptOverlay"
Panel.ZIndex="200" Panel.ZIndex="200"

View File

@ -46,16 +46,20 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 新增用于目标选择UI的ObservableCollection // 新增用于目标选择UI的ObservableCollection
public ObservableCollection<Character> SelectedTargets { get; set; } = []; public ObservableCollection<Character> SelectedTargets { get; set; } = [];
// 新增用于移动目标选择UI的ObservableCollection
public ObservableCollection<Grid> SelectedTargetGrid { get; set; } = [];
// 新增:倒计时相关的字段 // 新增:倒计时相关的字段
private int _remainingCountdownSeconds; private int _remainingCountdownSeconds;
private Action<bool>? _currentContinueCallback; private Action<bool>? _currentContinueCallback;
// 回调Action用于将UI选择结果传递给Controller // 回调Action用于将UI选择结果传递给Controller
private Action<long>? _resolveCharacterSelection; private Action<Character?>? _resolveCharacterSelection;
private Action<Grid?>? _resolveTargetGridSelection;
private Action<CharacterActionType>? _resolveActionType; private Action<CharacterActionType>? _resolveActionType;
private Action<List<Character>>? _resolveTargetSelection; private Action<List<Character>>? _resolveTargetSelection;
private Action<long>? _resolveSkillSelection; private Action<Skill?>? _resolveSkillSelection;
private Action<long>? _resolveItemSelection; private Action<Item?>? _resolveItemSelection;
private Action<bool>? _resolveContinuePrompt; private Action<bool>? _resolveContinuePrompt;
// 目标选择的内部状态 // 目标选择的内部状态
@ -65,6 +69,10 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private bool _canSelectAllTeammates, _canSelectAllEnemies, _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); // 选择时进行下轮预测(用于行动顺序表显示)
private Grid? _actingCharacterCurrentGridForTargetSelection;
private bool _isSelectingTargetGrid = false; // 标记当前是否处于格子选择模式
private List<Grid> _potentialTargetGridForSelection = [];
private Brush DefaultGridBrush { get; } = ToWpfBrush(System.Drawing.Color.Gray);
// 新增:用于跟踪当前高亮的技能和物品图标 // 新增:用于跟踪当前高亮的技能和物品图标
private Border? _highlightedSkillIcon; private Border? _highlightedSkillIcon;
@ -900,7 +908,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// <summary> /// <summary>
/// 处理格子点击事件:更新格子信息面板并高亮选中格子,并设置当前角色 /// 处理格子点击事件:更新格子信息面板并高亮选中格子,并设置当前角色
/// </summary> /// </summary>
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) private async void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{ {
if (sender is Rectangle clickedRect && _uiElementToGrid.TryGetValue(clickedRect, out Grid? grid)) if (sender is Rectangle clickedRect && _uiElementToGrid.TryGetValue(clickedRect, out Grid? grid))
{ {
@ -916,6 +924,15 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
// 更新格子信息面板 // 更新格子信息面板
UpdateGridInfoPanel(grid); UpdateGridInfoPanel(grid);
await AppendDebugLog($"选中格子: ID={grid.Id}, 坐标=({grid.X},{grid.Y},{grid.Z})");
if (_isSelectingTargetGrid)
{
await HandleTargetGridSelectionClick(grid);
e.Handled = true;
return;
}
// --- 设置 CurrentCharacter 属性 --- // --- 设置 CurrentCharacter 属性 ---
// 如果格子上有角色,则默认选中第一个角色。 // 如果格子上有角色,则默认选中第一个角色。
if (grid.Characters.Count != 0) if (grid.Characters.Count != 0)
@ -928,7 +945,6 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
this.CurrentCharacter = this.PlayerCharacter; this.CurrentCharacter = this.PlayerCharacter;
} }
_ = AppendDebugLog($"选中格子: ID={grid.Id}, 坐标=({grid.X},{grid.Y},{grid.Z})");
e.Handled = true; // 标记事件已处理防止冒泡到Canvas e.Handled = true; // 标记事件已处理防止冒泡到Canvas
} }
} }
@ -951,6 +967,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
ClearGridHighlights(); ClearGridHighlights();
if (_isSelectingTargetGrid)
{
await HandleTargetGridSelectionClick(characterGrid);
}
if (_gridIdToUiElement.TryGetValue(characterGrid.Id, out Rectangle? gridRect)) if (_gridIdToUiElement.TryGetValue(characterGrid.Id, out Rectangle? gridRect))
{ {
gridRect.Stroke = Brushes.Red; gridRect.Stroke = Brushes.Red;
@ -987,9 +1008,6 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
} }
else else
{ {
// 否则正常选中角色并更新UI
this.CurrentCharacter = character; // 设置当前选中角色
// 找到角色所在的格子 // 找到角色所在的格子
if (CurrentGameMap != null && CurrentGameMap.Characters.TryGetValue(character, out Grid? grid)) if (CurrentGameMap != null && CurrentGameMap.Characters.TryGetValue(character, out Grid? grid))
{ {
@ -1001,7 +1019,16 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
gridRect.StrokeThickness = 2; // 更粗的边框 gridRect.StrokeThickness = 2; // 更粗的边框
} }
UpdateGridInfoPanel(grid); UpdateGridInfoPanel(grid);
if (_isSelectingTargetGrid)
{
await HandleTargetGridSelectionClick(grid);
return;
}
} }
// 正常选中角色并更新UI
this.CurrentCharacter = character; // 设置当前选中角色
await AppendDebugLog($"选中角色: {character.ToStringWithLevel()} (通过点击图标)"); await AppendDebugLog($"选中角色: {character.ToStringWithLevel()} (通过点击图标)");
} }
e.Handled = true; // 阻止事件冒泡到下方的Grid_MouseLeftButtonDown 或 GameMapCanvas_MouseLeftButtonDown e.Handled = true; // 阻止事件冒泡到下方的Grid_MouseLeftButtonDown 或 GameMapCanvas_MouseLeftButtonDown
@ -1014,7 +1041,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
private void GameMapCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) private void GameMapCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{ {
// 如果处于目标选择模式,不响应空白区域点击 // 如果处于目标选择模式,不响应空白区域点击
if (_isSelectingTargets) return; if (_isSelectingTargets || _isSelectingTargetGrid) return;
// 只有当点击事件的原始源是Canvas本身时才处理这意味着没有点击到任何子元素如格子或角色图标 // 只有当点击事件的原始源是Canvas本身时才处理这意味着没有点击到任何子元素如格子或角色图标
if (e.OriginalSource == GameMapCanvas) if (e.OriginalSource == GameMapCanvas)
@ -1345,7 +1372,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// </summary> /// </summary>
/// <param name="availableCharacters">可供选择的角色列表。</param> /// <param name="availableCharacters">可供选择的角色列表。</param>
/// <param name="callback">选择完成后调用的回调函数。</param> /// <param name="callback">选择完成后调用的回调函数。</param>
public void ShowCharacterSelectionPrompt(List<Character> availableCharacters, Action<long> callback) public void ShowCharacterSelectionPrompt(List<Character> availableCharacters, Action<Character?> callback)
{ {
_resolveCharacterSelection = callback; _resolveCharacterSelection = callback;
CharacterSelectionItemsControl.ItemsSource = availableCharacters; CharacterSelectionItemsControl.ItemsSource = availableCharacters;
@ -1360,7 +1387,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
if (sender is Border border && border.Tag is Character character) if (sender is Border border && border.Tag is Character character)
{ {
_resolveCharacterSelection?.Invoke(character.Id); _resolveCharacterSelection?.Invoke(character);
} }
} }
@ -1426,7 +1453,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// </summary> /// </summary>
/// <param name="character">可供选择的技能列表。</param> /// <param name="character">可供选择的技能列表。</param>
/// <param name="callback">选择完成后调用的回调函数。</param> /// <param name="callback">选择完成后调用的回调函数。</param>
public void ShowSkillSelectionUI(Character character, Action<long> callback) public void ShowSkillSelectionUI(Character character, Action<Skill?> callback)
{ {
_resolveSkillSelection = callback; _resolveSkillSelection = callback;
SkillItemSelectionTitle.Text = "请选择技能"; SkillItemSelectionTitle.Text = "请选择技能";
@ -1441,7 +1468,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
/// </summary> /// </summary>
/// <param name="character">可供选择的物品列表。</param> /// <param name="character">可供选择的物品列表。</param>
/// <param name="callback">选择完成后调用的回调函数。</param> /// <param name="callback">选择完成后调用的回调函数。</param>
public void ShowItemSelectionUI(Character character, Action<long> callback) public void ShowItemSelectionUI(Character character, Action<Item?> callback)
{ {
_resolveItemSelection = callback; _resolveItemSelection = callback;
SkillItemSelectionTitle.Text = "请选择物品"; SkillItemSelectionTitle.Text = "请选择物品";
@ -1460,11 +1487,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
{ {
if (border.Tag is Skill skill) if (border.Tag is Skill skill)
{ {
_resolveSkillSelection?.Invoke(skill.Id); _resolveSkillSelection?.Invoke(skill);
} }
else if (border.Tag is Item item) else if (border.Tag is Item item)
{ {
_resolveItemSelection?.Invoke(item.Id); _resolveItemSelection?.Invoke(item);
} }
} }
} }
@ -1512,12 +1539,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
if (SkillItemDescription.Text == "技能详情") if (SkillItemDescription.Text == "技能详情")
{ {
SkillItemDescription.Text = ""; SkillItemDescription.Text = "";
_resolveSkillSelection?.Invoke(-1); _resolveSkillSelection?.Invoke(null);
} }
else if (SkillItemDescription.Text == "物品详情") else if (SkillItemDescription.Text == "物品详情")
{ {
SkillItemDescription.Text = ""; SkillItemDescription.Text = "";
_resolveItemSelection?.Invoke(-1); _resolveItemSelection?.Invoke(null);
} }
CharacterQueueItems.Remove(_selectionPredictCharacter); CharacterQueueItems.Remove(_selectionPredictCharacter);
} }
@ -1595,6 +1622,28 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
UpdateCharacterHighlights(); UpdateCharacterHighlights();
} }
/// <summary>
/// 显示移动目标选择UI。
/// </summary>
/// <param name="character"></param>
/// <param name="currentGrid"></param>
/// <param name="selectable"></param>
/// <param name="callback"></param>
public void ShowTargetGridSelectionUI(Character character, Grid currentGrid, List<Grid> selectable, Action<Grid?> callback)
{
_resolveTargetGridSelection = callback;
_actingCharacterForTargetSelection = character;
_actingCharacterCurrentGridForTargetSelection = currentGrid;
_potentialTargetGridForSelection = selectable;
_isSelectingTargetGrid = true;
SelectedTargetGrid.Clear(); // 清空之前的选择
TargetGridSelectionOverlay.Visibility = Visibility.Visible;
// 更新地图上格子的高亮,以显示潜在目标和已选目标
UpdateGridHighlights();
}
/// <summary> /// <summary>
/// 处理在目标选择模式下点击角色图标的逻辑。 /// 处理在目标选择模式下点击角色图标的逻辑。
/// </summary> /// </summary>
@ -1647,6 +1696,33 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
UpdateCharacterHighlights(); // 更新地图上的高亮显示 UpdateCharacterHighlights(); // 更新地图上的高亮显示
} }
/// <summary>
/// 处理在移动目标选择模式下点击角色图标的逻辑。
/// </summary>
/// <param name="clickedGrid">被点击的格子。</param>
private async Task HandleTargetGridSelectionClick(Grid clickedGrid)
{
// 检查是否是潜在目标
if (_potentialTargetGridForSelection == null || !_potentialTargetGridForSelection.Contains(clickedGrid))
{
await AppendDebugLog($"无法选择 {clickedGrid}:不是潜在目标。");
return;
}
if (!SelectedTargetGrid.Remove(clickedGrid))
{
if (SelectedTargetGrid.Count < 1)
{
SelectedTargetGrid.Add(clickedGrid);
}
else
{
await AppendDebugLog($"已选择过目标。");
}
}
UpdateGridHighlights(); // 更新地图上的高亮显示
}
/// <summary> /// <summary>
/// 更新地图上角色的高亮显示,区分潜在目标和已选目标。 /// 更新地图上角色的高亮显示,区分潜在目标和已选目标。
/// </summary> /// </summary>
@ -1681,6 +1757,30 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
} }
} }
/// <summary>
/// 更新地图上格子的高亮显示,区分潜在目标和已选目标。
/// </summary>
private void UpdateGridHighlights()
{
foreach (Rectangle rectangle in _uiElementToGrid.Keys)
{
Grid grid = _uiElementToGrid[rectangle];
if (SelectedTargetGrid.Contains(grid))
{
rectangle.Fill = Brushes.Red; // 已选目标颜色
}
else if (_potentialTargetGridForSelection.Contains(grid))
{
rectangle.Fill = Brushes.Yellow;
}
else
{
rectangle.Fill = DefaultGridBrush;
}
}
}
/// <summary> /// <summary>
/// 从已选目标列表中移除一个角色。 /// 从已选目标列表中移除一个角色。
/// </summary> /// </summary>
@ -1714,6 +1814,22 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
CharacterQueueItems.Remove(_selectionPredictCharacter); CharacterQueueItems.Remove(_selectionPredictCharacter);
} }
/// <summary>
/// 确认目标格子选择的点击事件。
/// </summary>
private void ConfirmTargetGrid_Click(object sender, RoutedEventArgs e)
{
_resolveTargetGridSelection?.Invoke(SelectedTargetGrid.FirstOrDefault());
}
/// <summary>
/// 取消目标格子选择的点击事件。
/// </summary>
private void CancelTargetGridSelection_Click(object sender, RoutedEventArgs e)
{
_resolveTargetGridSelection?.Invoke(null); // 返回空表示取消
}
/// <summary> /// <summary>
/// 隐藏目标选择UI。 /// 隐藏目标选择UI。
/// </summary> /// </summary>
@ -1728,6 +1844,20 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting
UpdateCharacterHighlights(); // 清除所有高亮 UpdateCharacterHighlights(); // 清除所有高亮
} }
/// <summary>
/// 隐藏移动目标选择UI。
/// </summary>
public void HideTargetGridSelectionUI()
{
TargetGridSelectionOverlay.Visibility = Visibility.Collapsed;
SelectedTargetGrid.Clear();
_isSelectingTargetGrid = false;
_actingCharacterCurrentGridForTargetSelection = null;
_potentialTargetGridForSelection = [];
_resolveTargetGridSelection = null;
UpdateGridHighlights();
}
/// <summary> /// <summary>
/// 显示“继续”提示面板。 /// 显示“继续”提示面板。
/// </summary> /// </summary>