From 86e4611656341b630da639e99f933653015eca0b Mon Sep 17 00:00:00 2001 From: milimoe Date: Wed, 3 Sep 2025 00:07:29 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E4=B8=8D=E5=86=8D=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E7=A1=AC=E7=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CharacterQueueItemViewModel.cs | 75 +++ Desktop/GameMapTesting/Converters.cs | 129 +++++ Desktop/GameMapTesting/GameMapController.cs | 63 ++- Desktop/GameMapTesting/GameMapTesting.cs | 115 +++-- Desktop/GameMapTesting/GameMapViewer.xaml | 64 ++- Desktop/GameMapTesting/GameMapViewer.xaml.cs | 445 ++++++++++++------ 6 files changed, 693 insertions(+), 198 deletions(-) create mode 100644 Desktop/GameMapTesting/CharacterQueueItemViewModel.cs create mode 100644 Desktop/GameMapTesting/Converters.cs diff --git a/Desktop/GameMapTesting/CharacterQueueItemViewModel.cs b/Desktop/GameMapTesting/CharacterQueueItemViewModel.cs new file mode 100644 index 0000000..3ba7ff6 --- /dev/null +++ b/Desktop/GameMapTesting/CharacterQueueItemViewModel.cs @@ -0,0 +1,75 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Milimoe.FunGame.Core.Entity; + +namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting +{ + public class CharacterQueueItemViewModel(CharacterQueueItem model, Func>> getTurnRewards) : INotifyPropertyChanged + { + public CharacterQueueItem Model { get; } = model ?? throw new ArgumentNullException(nameof(model)); + public Character Character => Model.Character; + public double ATDelay => Model.ATDelay; + + private int _predictedTurnNumber; + public int PredictedTurnNumber + { + get => _predictedTurnNumber; + set + { + if (_predictedTurnNumber != value) + { + _predictedTurnNumber = value; + OnPropertyChanged(); + // 当回合数变化时,奖励信息可能也变化,因此需要更新 + UpdateRewardProperties(); + } + } + } + + private string _turnRewardSkillName = ""; + public string TurnRewardSkillName + { + get => _turnRewardSkillName; + set + { + if (_turnRewardSkillName != value) + { + _turnRewardSkillName = value; + OnPropertyChanged(); + OnPropertyChanged(nameof(HasTurnReward)); // 奖励名称变化时,通知可见性也可能变化 + } + } + } + + public bool HasTurnReward => !string.IsNullOrEmpty(TurnRewardSkillName); + + // 用于获取 TurnRewards 字典的委托,避免直接依赖 GameMapViewer + private readonly Func>> _getTurnRewards = getTurnRewards ?? throw new ArgumentNullException(nameof(getTurnRewards)); + + // 当 PredictedTurnNumber 或 TurnRewards 变化时调用此方法 + public void UpdateRewardProperties() + { + Dictionary> turnRewards = _getTurnRewards(); + if (turnRewards != null && turnRewards.TryGetValue(PredictedTurnNumber, out List? rewardSkills)) + { + TurnRewardSkillName = string.Join(";", rewardSkills.Select(s => s.Name.Replace("[R]", "").Trim())); + } + else + { + TurnRewardSkillName = ""; + } + } + + public event PropertyChangedEventHandler? PropertyChanged; + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public class CharacterQueueItem(Character character, double atDelay) + { + public Character Character { get; set; } = character; + public double ATDelay { get; set; } = atDelay; + } +} diff --git a/Desktop/GameMapTesting/Converters.cs b/Desktop/GameMapTesting/Converters.cs new file mode 100644 index 0000000..ad92331 --- /dev/null +++ b/Desktop/GameMapTesting/Converters.cs @@ -0,0 +1,129 @@ +using System.Globalization; +using System.Windows.Data; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting +{ + public class FirstCharConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is string s && s.Length > 0) + { + return s[0].ToString().ToUpper(); + } + return "?"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class CharacterToStringWithLevelConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Character character) + { + string name = character.ToString(); + if (character.CharacterState == CharacterState.Casting) + { + name += " - 吟唱"; + } + else if (character.CharacterState == CharacterState.PreCastSuperSkill) + { + name += " - 爆发技"; + } + return name; + } + return "[未知角色]"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + 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(); + } + } + + /// + /// 组合转换器:判断技能或物品是否可用。 + /// 接收 Skill/Item 对象和当前 Character 对象。 + /// + public class SkillUsabilityConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + // values[0] 应该是 Skill 或 Item 对象 + // values[1] 应该是 PlayerCharacter 对象 + 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(); + } + } +} diff --git a/Desktop/GameMapTesting/GameMapController.cs b/Desktop/GameMapTesting/GameMapController.cs index a986ea6..06b5d38 100644 --- a/Desktop/GameMapTesting/GameMapController.cs +++ b/Desktop/GameMapTesting/GameMapController.cs @@ -1,4 +1,5 @@ using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Constant; @@ -17,7 +18,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting private readonly UserInputRequester _itemSelectionRequester = new(); private readonly UserInputRequester _continuePromptRequester = new(); // 用于“按任意键继续”提示 - public void WriteLine(string str = "") => UI.AppendDebugLog(str); + public async Task WriteLine(string str = "") => await UI.AppendDebugLog(str); public async Task Start() { @@ -25,9 +26,22 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting await _game.StartGame(false); } + public async Task SetPreCastSuperSkill(Character character, Skill skill) + { + if (_game != null) + { + await _game.SetPreCastSuperSkill(character, skill); + } + } + + public void SetPredictCharacter(string name, double ht) + { + UI.Invoke(() => UI.SetPredictCharacter(name, ht)); + } + public async Task RequestCharacterSelection(List availableCharacters) { - WriteLine("请选择你想玩的角色。"); + await WriteLine("请选择你想玩的角色。"); return await _characterSelectionRequester.RequestInput( (callback) => UI.Invoke(() => UI.ShowCharacterSelectionPrompt(availableCharacters, callback)) ); @@ -35,17 +49,17 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public async Task RequestActionType(Character character, List availableItems) { - WriteLine($"现在是 {character.NickName} 的回合,请选择行动。"); + await WriteLine($"现在是 {character.NickName} 的回合,请选择行动。"); return await _actionTypeRequester.RequestInput( (callback) => UI.Invoke(() => UI.ShowActionButtons(character, availableItems, callback)) ); } - public async Task> RequestTargetSelection(Character actor, List potentialTargets, long maxTargets, bool canSelectSelf, bool canSelectEnemy, bool canSelectTeammate) + public async Task> RequestTargetSelection(Character actor, List potentialTargets, ISkill skill, long maxTargets, bool canSelectSelf, bool canSelectEnemy, bool canSelectTeammate) { - WriteLine($"请为 {actor.NickName} 选择目标 (最多 {maxTargets} 个)。"); + await WriteLine($"请为 {actor.NickName} 选择目标 (最多 {maxTargets} 个)。"); List targetIds = await _targetSelectionRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowTargetSelectionUI(actor, potentialTargets, maxTargets, canSelectSelf, canSelectEnemy, canSelectTeammate, callback)) + (callback) => UI.Invoke(() => UI.ShowTargetSelectionUI(actor, potentialTargets, skill, maxTargets, canSelectSelf, canSelectEnemy, canSelectTeammate, callback)) ) ?? []; if (targetIds == null) return []; return [.. potentialTargets.Where(targetIds.Contains)]; @@ -53,7 +67,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public async Task RequestSkillSelection(Character character, List availableSkills) { - WriteLine($"请为 {character.NickName} 选择一个技能。"); + await WriteLine($"请为 {character.NickName} 选择一个技能。"); long? skillId = await _skillSelectionRequester.RequestInput( (callback) => UI.Invoke(() => UI.ShowSkillSelectionUI(character, callback)) ); @@ -62,7 +76,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public async Task RequestItemSelection(Character character, List availableItems) { - WriteLine($"请为 {character.NickName} 选择一个物品。"); + await WriteLine($"请为 {character.NickName} 选择一个物品。"); long? itemId = await _itemSelectionRequester.RequestInput( (callback) => UI.Invoke(() => UI.ShowItemSelectionUI(character, callback)) ); @@ -71,12 +85,21 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public async Task RequestContinuePrompt(string message) { - WriteLine(message); + await WriteLine(message); await _continuePromptRequester.RequestInput( (callback) => UI.Invoke(() => UI.ShowContinuePrompt(message, callback)) ); } + public async Task RequestCountDownContinuePrompt(string message, int countdownSeconds = 2) + { + await WriteLine(message); + // 调用 _continuePromptRequester 的 RequestInput 方法,它会等待回调被触发 + await _continuePromptRequester.RequestInput( + (callback) => UI.Invoke(() => UI.StartCountdownForContinue(countdownSeconds, callback)) + ); + } + // --- GameMapViewer 调用这些方法来解决 UI 输入 --- public void ResolveCharacterSelection(long characterId) @@ -114,6 +137,12 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting _continuePromptRequester.ResolveInput(true); // 任何值都可以,只要完成Task UI.Invoke(() => UI.HideContinuePrompt()); } + + public void ResolveCountDownContinuePrompt() + { + _continuePromptRequester.ResolveInput(true); + UI.Invoke(() => UI.HideContinuePrompt()); + } public bool IsTeammate(Character actor, Character target) { @@ -155,6 +184,22 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting UI.CurrentGameMap = map; }); } + + public void SetCurrentRound(int round) + { + UI.Invoke(() => + { + UI.CurrentRound = round; + }); + } + + public void SetTurnRewards(Dictionary> rewards) + { + UI.Invoke(() => + { + UI.TurnRewards = rewards; + }); + } public void SetPlayerCharacter(Character character) { diff --git a/Desktop/GameMapTesting/GameMapTesting.cs b/Desktop/GameMapTesting/GameMapTesting.cs index 238e306..8950796 100644 --- a/Desktop/GameMapTesting/GameMapTesting.cs +++ b/Desktop/GameMapTesting/GameMapTesting.cs @@ -39,7 +39,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting List result = []; Msg = ""; List allCharactersInGame = [.. FunGameConstant.Characters]; // 使用不同的名称以避免与后面的 `characters` 冲突 - Controller.WriteLine("--- 游戏开始 ---"); + await Controller.WriteLine("--- 游戏开始 ---"); int clevel = 60; int slevel = 6; @@ -62,7 +62,10 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } // 显示角色信息 - characters.ForEach(c => Controller.WriteLine($"角色编号:{c.Id}\r\n{c.GetInfo()}")); + foreach (Character c in characters) + { + await Controller.WriteLine($"角色编号:{c.Id}\r\n{c.GetInfo()}"); + } // 询问玩家需要选择哪个角色 (通过UI界面选择) Character? player = null; @@ -73,7 +76,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting player = characters.FirstOrDefault(c => c.Id == selectedPlayerId); if (player != null) { - Controller.WriteLine($"选择了 [ {player} ]!"); + await Controller.WriteLine($"选择了 [ {player} ]!"); + player.Promotion = 200; Controller.SetCurrentCharacter(player); Controller.SetPlayerCharacter(player); @@ -137,9 +141,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting int qArmor = 5; int qShoes = 5; int qAccessory = 5; - WriteLine($"社区送温暖了,现在随机发放空投!!"); + await Controller.WriteLine($"社区送温暖了,现在随机发放空投!!"); DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory); - WriteLine(""); + await Controller.WriteLine(""); if (isWeb) result.Add("=== 空投 ===\r\n" + Msg); double nextDropItemTime = 40; if (qMagicCardPack < 5) qMagicCardPack++; @@ -149,20 +153,23 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting if (qAccessory < 5) qAccessory++; // 显示角色信息 - characters.ForEach(c => Controller.WriteLine(c.GetInfo())); + foreach (Character c in characters) + { + await Controller.WriteLine(c.GetInfo()); + } // 初始化队列,准备开始游戏 _gamingQueue.InitActionQueue(); _gamingQueue.SetCharactersToAIControl(false, characters); _gamingQueue.SetCharactersToAIControl(true, player); _gamingQueue.CustomData.Add("player", player); - Controller.WriteLine(); + await Controller.WriteLine(); // 显示初始顺序表 _gamingQueue.DisplayQueue(); - Controller.WriteLine(); + await Controller.WriteLine(); - Controller.WriteLine($"你的角色是 [ {player} ],详细信息:{player.GetInfo()}"); + await Controller.WriteLine($"你的角色是 [ {player} ],详细信息:{player.GetInfo()}"); // 总回合数 int maxRound = 999; @@ -180,6 +187,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting effects.Add(effectID, isActive); } _gamingQueue.InitRoundRewards(maxRound, 1, effects, id => FunGameConstant.RoundRewards[(EffectID)id]); + Controller.SetTurnRewards(_gamingQueue.RoundRewards); int i = 1; while (i < maxRound) @@ -187,7 +195,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting Msg = ""; if (i == maxRound - 1) { - WriteLine($"=== 终局审判 ==="); + await Controller.WriteLine($"=== 终局审判 ==="); Dictionary hpPercentage = []; foreach (Character c in characters) { @@ -195,10 +203,10 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } double max = hpPercentage.Values.Max(); Character winner = hpPercentage.Keys.Where(c => hpPercentage[c] == max).First(); - WriteLine("[ " + winner + " ] 成为了天选之人!!"); + await Controller.WriteLine("[ " + winner + " ] 成为了天选之人!!"); foreach (Character c in characters.Where(c => c != winner && c.HP > 0)) { - WriteLine("[ " + winner + " ] 对 [ " + c + " ] 造成了 99999999999 点真实伤害。"); + await Controller.WriteLine("[ " + winner + " ] 对 [ " + c + " ] 造成了 99999999999 点真实伤害。"); await _gamingQueue.DeathCalculationAsync(winner, c); } if (_gamingQueue is MixGamingQueue mix) @@ -217,8 +225,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting // 处理回合 if (characterToAct != null) { - WriteLine($"=== 回合 {i++} ==="); - WriteLine("现在是 [ " + characterToAct + " ] 的回合!"); + Controller.SetCurrentRound(i); + await Controller.WriteLine($"=== 回合 {i++} ==="); + await Controller.WriteLine("现在是 [ " + characterToAct + " ] 的回合!"); bool isGameEnd = await _gamingQueue.ProcessTurnAsync(characterToAct); @@ -229,7 +238,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } if (isWeb) _gamingQueue.DisplayQueue(); - WriteLine(""); + await Controller.WriteLine(""); } string roundMsg = ""; @@ -243,6 +252,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting double timeLapse = await _gamingQueue.TimeLapse(); totalTime += timeLapse; nextDropItemTime -= timeLapse; + Controller.UpdateBottomInfoPanel(); Controller.UpdateQueue(); Controller.UpdateCharacterPositionsOnMap(); @@ -259,9 +269,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { // 空投 Msg = ""; - WriteLine($"社区送温暖了,现在随机发放空投!!"); + await Controller.WriteLine($"社区送温暖了,现在随机发放空投!!"); DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory); - WriteLine(""); + await Controller.WriteLine(""); if (isWeb) result.Add("=== 空投 ===\r\n" + Msg); nextDropItemTime = 40; if (qMagicCardPack < 5) qMagicCardPack++; @@ -272,8 +282,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } } - Controller.WriteLine("--- 游戏结束 ---"); - Controller.WriteLine($"总游戏时长:{totalTime:0.##} {_gamingQueue.GameplayEquilibriumConstant.InGameTime}"); + await Controller.WriteLine("--- 游戏结束 ---"); + await Controller.WriteLine($"总游戏时长:{totalTime:0.##} {_gamingQueue.GameplayEquilibriumConstant.InGameTime}"); // 赛后统计 FunGameService.GetCharacterRating(_gamingQueue.CharacterStatistics, false, []); @@ -299,18 +309,18 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting int count = 1; if (isWeb) { - WriteLine("=== 技术得分排行榜 ==="); + await Controller.WriteLine("=== 技术得分排行榜 ==="); Msg = $"=== 技术得分排行榜 TOP{top} ===\r\n"; } else { StringBuilder ratingBuilder = new(); - WriteLine("=== 本场比赛最佳角色 ==="); + await Controller.WriteLine("=== 本场比赛最佳角色 ==="); Msg = $"=== 本场比赛最佳角色 ===\r\n"; - WriteLine(mvpBuilder.ToString() + "\r\n\r\n" + ratingBuilder.ToString()); + await Controller.WriteLine(mvpBuilder.ToString() + "\r\n\r\n" + ratingBuilder.ToString()); - Controller.WriteLine(); - Controller.WriteLine("=== 技术得分排行榜 ==="); + await Controller.WriteLine(); + await Controller.WriteLine("=== 技术得分排行榜 ==="); } foreach (Character character in _gamingQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) @@ -327,11 +337,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting builder.Append($"每秒伤害:{stats.DamagePerSecond:0.##} / 每回合伤害:{stats.DamagePerTurn:0.##}"); if (count++ <= top) { - WriteLine(builder.ToString()); + await Controller.WriteLine(builder.ToString()); } else { - Controller.WriteLine(builder.ToString()); + await Controller.WriteLine(builder.ToString()); } CharacterStatistics? totalStats = CharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); @@ -364,7 +374,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } catch (Exception ex) { - Controller.WriteLine(ex.ToString()); + await Controller.WriteLine(ex.ToString()); return [ex.ToString()]; } } @@ -380,26 +390,29 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting private async Task GamingQueue_CharacterMove(GamingQueue queue, Character actor, Grid grid) { + Controller.UpdateCharacterPositionsOnMap(); await Task.CompletedTask; } private async Task GamingQueue_QueueUpdated(GamingQueue queue, List characters, Character character, double hardnessTime, QueueUpdatedReason reason, string msg) { + if (reason != QueueUpdatedReason.Action) + { + Controller.UpdateQueue(); + } if (IsPlayer_OnlyTest(queue, character)) { - if (reason == QueueUpdatedReason.Action) - { - queue.SetCharactersToAIControl(false, character); - } - if (reason == QueueUpdatedReason.PreCastSuperSkill) - { - // 玩家释放爆发技后,需要等待玩家确认 - await Controller.RequestContinuePrompt("你的下一回合需要选择爆发技目标,知晓请点击继续. . ."); - Controller.ResolveContinuePrompt(); - } + //if (reason == QueueUpdatedReason.Action) + //{ + // queue.SetCharactersToAIControl(false, character); + //} + //if (reason == QueueUpdatedReason.PreCastSuperSkill) + //{ + // // 玩家释放爆发技后,需要等待玩家确认 + // await Controller.RequestContinuePrompt("你的下一回合需要选择爆发技目标,知晓请点击继续. . ."); + // Controller.ResolveContinuePrompt(); + //} } - Controller.UpdateQueue(); - Controller.UpdateCharacterPositionsOnMap(); await Task.CompletedTask; } @@ -409,7 +422,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting if (IsPlayer_OnlyTest(queue, character)) { // 确保玩家角色在回合开始时取消AI托管,以便玩家可以控制 - queue.SetCharactersToAIControl(cancel: true, character); + //queue.SetCharactersToAIControl(cancel: true, character); } await Task.CompletedTask; return true; @@ -428,6 +441,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting List selectedTargets = await Controller.RequestTargetSelection( character, potentialTargets, + attack, attack.CanSelectTargetCount, attack.CanSelectSelf, attack.CanSelectEnemy, @@ -461,6 +475,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting List? selectedTargets = await Controller.RequestTargetSelection( caster, potentialTargets, + skill, skill.CanSelectTargetCount, skill.CanSelectSelf, skill.CanSelectEnemy, @@ -483,6 +498,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting private async Task GamingQueue_TurnEnd(GamingQueue queue, Character character) { + double ht = queue.HardnessTime[character]; + Controller.SetPredictCharacter(character.NickName, ht); Controller.UpdateBottomInfoPanel(); if (IsRoundHasPlayer_OnlyTest(queue, character)) { @@ -490,6 +507,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting await Controller.RequestContinuePrompt("你的回合(或与你相关的回合)已结束,请查看本回合日志,然后点击继续. . ."); Controller.ResolveContinuePrompt(); } + else + { + await Controller.RequestCountDownContinuePrompt("该角色的回合已结束. . ."); + Controller.ResolveCountDownContinuePrompt(); + } await Task.CompletedTask; } @@ -507,7 +529,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting private static bool IsPlayer_OnlyTest(GamingQueue queue, Character current) { - return queue.CustomData.TryGetValue("player", out object? value) && value is Character player && player == current; + return queue.CustomData.TryGetValue("player", out object? value) && value is Character player && player == current && !queue.IsCharacterInAIControlling(current); } private static bool IsRoundHasPlayer_OnlyTest(GamingQueue queue, Character current) @@ -515,10 +537,18 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting return queue.CustomData.TryGetValue("player", out object? value) && value is Character player && (player == current || (current.CharacterState != CharacterState.Casting && queue.LastRound.Targets.Any(c => c == player))); } + public async Task SetPreCastSuperSkill(Character character, Skill skill) + { + if (_gamingQueue is GamingQueue queue) + { + await queue.SetCharacterPreCastSuperSkill(character, skill); + } + } + public void WriteLine(string str) { Msg += str + "\r\n"; - Controller.WriteLine(str); + _ = Controller.WriteLine(str); } public static void DropItems(GamingQueue queue, int mQuality, int wQuality, int aQuality, int sQuality, int acQuality) @@ -561,6 +591,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting for (int i = 0; i < 2; i++) { Item consumable = consumables[Random.Shared.Next(consumables.Length)].Copy(); + consumable.Character = character; character.Items.Add(consumable); } } diff --git a/Desktop/GameMapTesting/GameMapViewer.xaml b/Desktop/GameMapTesting/GameMapViewer.xaml index 795f6cd..6e3d477 100644 --- a/Desktop/GameMapTesting/GameMapViewer.xaml +++ b/Desktop/GameMapTesting/GameMapViewer.xaml @@ -137,20 +137,35 @@ - + - + - + + + + - - + + + + @@ -158,9 +173,19 @@ - + + + + + + + + + + + + + @@ -407,6 +443,19 @@ + + @@ -643,6 +692,7 @@