From 6a23672af9fb417792817fce4b35287ecd809bd3 Mon Sep 17 00:00:00 2001 From: milimoe Date: Thu, 4 Sep 2025 01:48:58 +0800 Subject: [PATCH] =?UTF-8?q?UI=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=9B=A2=E9=98=9F?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Desktop/GameMapTesting/Converters.cs | 19 + Desktop/GameMapTesting/GameMapController.cs | 94 ++-- Desktop/GameMapTesting/GameMapTesting.cs | 235 ++++++--- Desktop/GameMapTesting/GameMapViewer.xaml | 498 ++++++++++++------ Desktop/GameMapTesting/GameMapViewer.xaml.cs | 263 +++++++-- ...terQueueItemViewModel.cs => ViewModels.cs} | 38 ++ 6 files changed, 818 insertions(+), 329 deletions(-) rename Desktop/GameMapTesting/{CharacterQueueItemViewModel.cs => ViewModels.cs} (73%) diff --git a/Desktop/GameMapTesting/Converters.cs b/Desktop/GameMapTesting/Converters.cs index ad92331..b1ef57f 100644 --- a/Desktop/GameMapTesting/Converters.cs +++ b/Desktop/GameMapTesting/Converters.cs @@ -1,10 +1,25 @@ using System.Globalization; using System.Windows.Data; using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { + public class ToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + // 如果值为 null,返回空字符串,否则返回其 ToString() 结果 + return value?.ToString()?.Trim() ?? string.Empty; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + public class FirstCharConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) @@ -111,6 +126,10 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting 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 NormalAttack a) + { + return a.Level > 0 && a.Enable; + } else if (values[0] is Item i) { return i.IsActive && i.Skills.Active != null && i.Enable && i.IsInGameItem && diff --git a/Desktop/GameMapTesting/GameMapController.cs b/Desktop/GameMapTesting/GameMapController.cs index 3c9b89d..2ab13c8 100644 --- a/Desktop/GameMapTesting/GameMapController.cs +++ b/Desktop/GameMapTesting/GameMapController.cs @@ -24,7 +24,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public async Task Start() { _game = new(this); - await _game.StartGame(false); + await _game.StartGame(false, true); } public async Task SetPreCastSuperSkill(Character character, Skill skill) @@ -35,16 +35,26 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } } - public void SetPredictCharacter(string name, double ht) + public void SetAutoMode(bool cancel, Character character) { - UI.Invoke(() => UI.SetPredictCharacter(name, ht)); + _game?.SetAutoMode(cancel, character); + } + + public void SetFastMode(bool on) + { + _game?.SetFastMode(on); + } + + public async Task SetPredictCharacter(string name, double ht) + { + await UI.InvokeAsync(() => UI.SetPredictCharacter(name, ht)); } public async Task RequestCharacterSelection(List availableCharacters) { await WriteLine("请选择你想玩的角色。"); return await _characterSelectionRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowCharacterSelectionPrompt(availableCharacters, callback)) + async (callback) => await UI.InvokeAsync(() => UI.ShowCharacterSelectionPrompt(availableCharacters, callback)) ); } @@ -52,7 +62,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { await WriteLine($"现在是 {character.NickName} 的回合,请选择行动。"); return await _actionTypeRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowActionButtons(character, availableItems, callback)) + async (callback) => await UI.InvokeAsync(() => UI.ShowActionButtons(character, availableItems, callback)) ); } @@ -60,17 +70,17 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { await WriteLine($"请为 {character.NickName} 选择目标 (最多 {skill.CanSelectTargetCount} 个)。"); List targetIds = await _targetSelectionRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowTargetSelectionUI(character, skill, enemys, teammates, callback)) + async (callback) => await UI.InvokeAsync(() => UI.ShowTargetSelectionUI(character, skill, enemys, teammates, callback)) ) ?? []; if (targetIds == null) return []; - return [.. enemys.Where(targetIds.Contains), .. teammates.Where(targetIds.Contains)]; + return [.. enemys.Union(teammates).Union([character]).Where(targetIds.Contains)]; } public async Task RequestSkillSelection(Character character, List availableSkills) { await WriteLine($"请为 {character.NickName} 选择一个技能。"); long? skillId = await _skillSelectionRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowSkillSelectionUI(character, callback)) + async (callback) => await UI.InvokeAsync(() => UI.ShowSkillSelectionUI(character, callback)) ); return skillId.HasValue ? availableSkills.FirstOrDefault(s => s.Id == skillId.Value) : null; } @@ -79,7 +89,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { await WriteLine($"请为 {character.NickName} 选择一个物品。"); long? itemId = await _itemSelectionRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowItemSelectionUI(character, callback)) + async (callback) => await UI.InvokeAsync(() => UI.ShowItemSelectionUI(character, callback)) ); return itemId.HasValue ? availableItems.FirstOrDefault(i => i.Id == itemId.Value) : null; } @@ -88,7 +98,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { await WriteLine(message); await _continuePromptRequester.RequestInput( - (callback) => UI.Invoke(() => UI.ShowContinuePrompt(message, callback)) + async (callback) => await UI.InvokeAsync(() => UI.ShowContinuePrompt(message, callback)) ); } @@ -97,52 +107,52 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting await WriteLine(message); // 调用 _continuePromptRequester 的 RequestInput 方法,它会等待回调被触发 await _continuePromptRequester.RequestInput( - (callback) => UI.Invoke(() => UI.StartCountdownForContinue(countdownSeconds, callback)) + async (callback) => await UI.InvokeAsync(() => UI.StartCountdownForContinue(countdownSeconds, callback)) ); } // --- GameMapViewer 调用这些方法来解决 UI 输入 --- - public void ResolveCharacterSelection(long characterId) + public async Task ResolveCharacterSelection(long characterId) { _characterSelectionRequester.ResolveInput(characterId); - UI.Invoke(() => UI.HideCharacterSelectionPrompt()); + await UI.InvokeAsync(() => UI.HideCharacterSelectionPrompt()); } - public void ResolveActionType(CharacterActionType actionType) + public async Task ResolveActionType(CharacterActionType actionType) { _actionTypeRequester.ResolveInput(actionType); - UI.Invoke(() => UI.HideActionButtons()); + await UI.InvokeAsync(() => UI.HideActionButtons()); } - public void ResolveTargetSelection(List targetIds) + public async Task ResolveTargetSelection(List targetIds) { _targetSelectionRequester.ResolveInput(targetIds); - UI.Invoke(() => UI.HideTargetSelectionUI()); + await UI.InvokeAsync(() => UI.HideTargetSelectionUI()); } - public void ResolveSkillSelection(long skillId) + public async Task ResolveSkillSelection(long skillId) { _skillSelectionRequester.ResolveInput(skillId); - UI.Invoke(() => UI.HideSkillSelectionUI()); + await UI.InvokeAsync(() => UI.HideSkillSelectionUI()); } - public void ResolveItemSelection(long itemId) + public async Task ResolveItemSelection(long itemId) { _itemSelectionRequester.ResolveInput(itemId); - UI.Invoke(() => UI.HideItemSelectionUI()); + await UI.InvokeAsync(() => UI.HideItemSelectionUI()); } - public void ResolveContinuePrompt() + public async Task ResolveContinuePrompt() { _continuePromptRequester.ResolveInput(true); // 任何值都可以,只要完成Task - UI.Invoke(() => UI.HideContinuePrompt()); + await UI.InvokeAsync(() => UI.HideContinuePrompt()); } - public void ResolveCountDownContinuePrompt() + public async Task ResolveCountDownContinuePrompt() { _continuePromptRequester.ResolveInput(true); - UI.Invoke(() => UI.HideContinuePrompt()); + await UI.InvokeAsync(() => UI.HideContinuePrompt()); } public bool IsTeammate(Character actor, Character target) @@ -157,70 +167,70 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public async Task UpdateBottomInfoPanel() { - await UI.Invoke(UI.UpdateBottomInfoPanel); + await UI.InvokeAsync(UI.UpdateBottomInfoPanel); } public async Task UpdateQueue() { - await UI.Invoke(UI.UpdateLeftQueuePanel); + await UI.InvokeAsync(UI.UpdateLeftQueuePanelGrid); } public async Task UpdateCharacterPositionsOnMap() { - await UI.Invoke(UI.UpdateCharacterPositionsOnMap); + await UI.InvokeAsync(UI.UpdateCharacterPositionsOnMap); } - public void SetQueue(Dictionary dict) + public async Task SetQueue(Dictionary dict) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.CharacterQueueData = dict; }); } - public void SetGameMap(GameMap map) + public async Task SetGameMap(GameMap map) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.CurrentGameMap = map; }); } - public void SetCurrentRound(int round) + public async Task SetCurrentRound(int round) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.CurrentRound = round; }); } - public void SetTurnRewards(Dictionary> rewards) + public async Task SetTurnRewards(Dictionary> rewards) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.TurnRewards = rewards; }); } - public void SetPlayerCharacter(Character character) + public async Task SetPlayerCharacter(Character character) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.PlayerCharacter = character; }); } - public void SetCurrentCharacter(Character character) + public async Task SetCurrentCharacter(Character character) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.CurrentCharacter = character; }); } - public void SetCharacterStatistics(Dictionary stats) + public async Task SetCharacterStatistics(Dictionary stats) { - UI.Invoke(() => + await UI.InvokeAsync(() => { UI.CharacterStatistics = stats; }); diff --git a/Desktop/GameMapTesting/GameMapTesting.cs b/Desktop/GameMapTesting/GameMapTesting.cs index 94f1f7f..12902c6 100644 --- a/Desktop/GameMapTesting/GameMapTesting.cs +++ b/Desktop/GameMapTesting/GameMapTesting.cs @@ -1,5 +1,4 @@ using System.Text; -// using System.Windows; // 不再需要,因为移除了 InputDialog using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Common.Addon; @@ -18,12 +17,16 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting public GamingQueue? GamingQueue => _gamingQueue; public GameMapController Controller { get; } public Dictionary CharacterStatistics { get; } = []; - public PluginConfig StatsConfig { get; } = new(nameof(FunGameSimulation), nameof(CharacterStatistics)); + public static Dictionary TeamCharacterStatistics { get; } = []; + public PluginConfig StatsConfig { get; } = new(nameof(GameMapTesting), nameof(CharacterStatistics)); + public PluginConfig TeamStatsConfig { get; } = new(nameof(GameMapTesting), nameof(TeamCharacterStatistics)); public GameMap GameMap { get; } = new TestMap(); public bool IsWeb { get; set; } = false; + public bool TeamMode { get; set; } = false; public string Msg { get; set; } = ""; private GamingQueue? _gamingQueue = null; + private bool _fastMode = false; public GameMapTesting(GameMapController controller) { @@ -31,15 +34,18 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting InitCharacter(); // 初始化角色统计数据 } - public async Task> StartGame(bool isWeb = false) + public async Task> StartGame(bool isWeb = false, bool isTeam = false) { IsWeb = isWeb; + TeamMode = isTeam; try { List result = []; Msg = ""; - List allCharactersInGame = [.. FunGameConstant.Characters]; // 使用不同的名称以避免与后面的 `characters` 冲突 + List allCharactersInGame = [.. FunGameConstant.Characters]; await Controller.WriteLine("--- 游戏开始 ---"); + TeamGamingQueue? tgq = null; + MixGamingQueue? mgq = null; int clevel = 60; int slevel = 6; @@ -70,7 +76,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting // 询问玩家需要选择哪个角色 (通过UI界面选择) Character? player = null; long selectedPlayerId = await Controller.RequestCharacterSelection(characters); // 异步等待UI选择 - Controller.ResolveCharacterSelection(selectedPlayerId); + await Controller.ResolveCharacterSelection(selectedPlayerId); if (selectedPlayerId != -1) { player = characters.FirstOrDefault(c => c.Id == selectedPlayerId); @@ -78,9 +84,8 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { await Controller.WriteLine($"选择了 [ {player} ]!"); player.Promotion = 200; - Controller.SetCurrentCharacter(player); - Controller.SetPlayerCharacter(player); - + await Controller.SetCurrentCharacter(player); + await Controller.SetPlayerCharacter(player); } } @@ -90,10 +95,64 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } // 创建顺序表并排序 - _gamingQueue = new MixGamingQueue(characters, WriteLine) + if (isTeam) { - GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant - }; + tgq = new(characters, WriteLine) + { + GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant + }; + _gamingQueue = tgq; + await Controller.WriteLine("=== 团队模式随机分组 ==="); + + // 打乱角色列表 + List shuffledCharacters = [.. characters.OrderBy(c => Random.Shared.Next())]; + + // 创建两个团队 + List group1 = []; + List group2 = []; + + // 将角色交替分配到两个团队中 + for (int cid = 0; cid < shuffledCharacters.Count; cid++) + { + Character thisCharacter = shuffledCharacters[cid]; + if (cid % 2 == 0) + { + group1.Add(thisCharacter); + } + else + { + group2.Add(thisCharacter); + } + } + + // 添加到团队字典,第一个为队长 + tgq.AddTeam($"{group1.First().NickName}的小队", group1); + tgq.AddTeam($"{group2.First().NickName}的小队", group2); + + foreach (Team team in tgq.Teams.Values) + { + await Controller.WriteLine($"团队【{team.Name}】的成员:\r\n{string.Join("\r\n", team.Members)}\r\n"); + if (team.IsOnThisTeam(player)) + { + foreach (Character c in team.Members.Except([player])) + { + c.Promotion = 300; + } + } + else + { + team.Members.ForEach(c => c.Promotion = 400); + } + } + } + else + { + mgq = new MixGamingQueue(characters, WriteLine) + { + GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant + }; + _gamingQueue = mgq; + } // 加载地图和绑定事件 _gamingQueue.LoadGameMap(GameMap); @@ -114,14 +173,14 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting allocated.Add(grid); map.SetCharacterCurrentGrid(character, grid); } - Controller.SetGameMap(map); + await Controller.SetGameMap(map); _gamingQueue.SelectTargetGrid += GamingQueue_SelectTargetGrid; _gamingQueue.CharacterMove += GamingQueue_CharacterMove; } // 绑定事件 - Controller.SetQueue(_gamingQueue.HardnessTime); - Controller.SetCharacterStatistics(_gamingQueue.CharacterStatistics); + await Controller.SetQueue(_gamingQueue.HardnessTime); + await Controller.SetCharacterStatistics(_gamingQueue.CharacterStatistics); _gamingQueue.TurnStart += GamingQueue_TurnStart; _gamingQueue.DecideAction += GamingQueue_DecideAction; _gamingQueue.SelectNormalAttackTargets += GamingQueue_SelectNormalAttackTargets; @@ -172,7 +231,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting await Controller.WriteLine($"你的角色是 [ {player} ],详细信息:{player.GetInfo()}"); // 总回合数 - int maxRound = 999; + int maxRound = isTeam ? 9999 : 999; // 随机回合奖励 Dictionary effects = []; @@ -187,7 +246,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); + await Controller.SetTurnRewards(_gamingQueue.RoundRewards); int i = 1; while (i < maxRound) @@ -195,23 +254,31 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting Msg = ""; if (i == maxRound - 1) { - await Controller.WriteLine($"=== 终局审判 ==="); - Dictionary hpPercentage = []; - foreach (Character c in characters) + if (isTeam) { - hpPercentage.TryAdd(c, c.HP / c.MaxHP); + WriteLine("两队打到天昏地暗,流局了!!"); + break; } - double max = hpPercentage.Values.Max(); - Character winner = hpPercentage.Keys.Where(c => hpPercentage[c] == max).First(); - await Controller.WriteLine("[ " + winner + " ] 成为了天选之人!!"); - foreach (Character c in characters.Where(c => c != winner && c.HP > 0)) + else { - await Controller.WriteLine("[ " + winner + " ] 对 [ " + c + " ] 造成了 99999999999 点真实伤害。"); - await _gamingQueue.DeathCalculationAsync(winner, c); - } - if (_gamingQueue is MixGamingQueue mix) - { - await mix.EndGameInfo(winner); + await Controller.WriteLine($"=== 终局审判 ==="); + Dictionary hpPercentage = []; + foreach (Character c in characters) + { + hpPercentage.TryAdd(c, c.HP / c.MaxHP); + } + double max = hpPercentage.Values.Max(); + Character winner = hpPercentage.Keys.Where(c => hpPercentage[c] == max).First(); + await Controller.WriteLine("[ " + winner + " ] 成为了天选之人!!"); + foreach (Character c in characters.Where(c => c != winner && c.HP > 0)) + { + await Controller.WriteLine("[ " + winner + " ] 对 [ " + c + " ] 造成了 99999999999 点真实伤害。"); + await _gamingQueue.DeathCalculationAsync(winner, c); + } + if (mgq != null) + { + await mgq.EndGameInfo(winner); + } } result.Add(Msg); break; @@ -225,7 +292,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting // 处理回合 if (characterToAct != null) { - Controller.SetCurrentRound(i); + await Controller.SetCurrentRound(i); await Controller.WriteLine($"=== 回合 {i++} ==="); await Controller.WriteLine("现在是 [ " + characterToAct + " ] 的回合!"); @@ -286,7 +353,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting await Controller.WriteLine($"总游戏时长:{totalTime:0.##} {_gamingQueue.GameplayEquilibriumConstant.InGameTime}"); // 赛后统计 - FunGameService.GetCharacterRating(_gamingQueue.CharacterStatistics, false, []); + FunGameService.GetCharacterRating(_gamingQueue.CharacterStatistics, isTeam, tgq != null ? tgq.EliminatedTeams : []); // 统计技术得分,评选 MVP Character? mvp = _gamingQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key).FirstOrDefault(); @@ -295,7 +362,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { CharacterStatistics stats = _gamingQueue.CharacterStatistics[mvp]; stats.MVPs++; - mvpBuilder.AppendLine($"[ {mvp.ToStringWithLevel()} ]"); + mvpBuilder.AppendLine($"{(tgq != null ? "[ " + tgq.GetTeamFromEliminated(mvp)?.Name + " ] " : "")}[ {mvp.ToStringWithLevel()} ]"); mvpBuilder.AppendLine($"技术得分:{stats.Rating:0.0#} / 击杀数:{stats.Kills} / 助攻数:{stats.Assists}{(_gamingQueue.MaxRespawnTimes != 0 ? " / 死亡数:" + stats.Deaths : "")}"); mvpBuilder.AppendLine($"存活时长:{stats.LiveTime:0.##} / 存活回合数:{stats.LiveRound} / 行动回合数:{stats.ActionTurn}"); mvpBuilder.AppendLine($"控制时长:{stats.ControlTime:0.##} / 总计治疗:{stats.TotalHeal:0.##} / 护盾抵消:{stats.TotalShield:0.##}"); @@ -327,7 +394,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { StringBuilder builder = new(); CharacterStatistics stats = _gamingQueue.CharacterStatistics[character]; - builder.AppendLine($"{(isWeb ? count + ". " : "")}[ {character.ToStringWithLevel()} ]"); + builder.AppendLine($"{(isWeb ? count + ". " : "")}[ {character.ToStringWithLevel()}{(tgq != null ? "(" + tgq.GetTeamFromEliminated(character)?.Name + ")" : "")} ]"); builder.AppendLine($"技术得分:{stats.Rating:0.0#} / 击杀数:{stats.Kills} / 助攻数:{stats.Assists}{(_gamingQueue.MaxRespawnTimes != 0 ? " / 死亡数:" + stats.Deaths : "")}"); builder.AppendLine($"存活时长:{stats.LiveTime:0.##} / 存活回合数:{stats.LiveRound} / 行动回合数:{stats.ActionTurn}"); builder.AppendLine($"控制时长:{stats.ControlTime:0.##} / 总计治疗:{stats.TotalHeal:0.##} / 护盾抵消:{stats.TotalShield:0.##}"); @@ -344,7 +411,9 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting await Controller.WriteLine(builder.ToString()); } - CharacterStatistics? totalStats = CharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); + CharacterStatistics? totalStats = isTeam ? + TeamCharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault() : + CharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); if (totalStats != null) { UpdateStatistics(totalStats, stats); @@ -361,13 +430,27 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } } - lock (StatsConfig) + if (isTeam) { - foreach (Character c in CharacterStatistics.Keys) + lock (TeamStatsConfig) { - StatsConfig.Add(c.ToStringWithOutUser(), CharacterStatistics[c]); + foreach (Character c in TeamCharacterStatistics.Keys) + { + TeamStatsConfig.Add(c.ToStringWithOutUser(), TeamCharacterStatistics[c]); + } + TeamStatsConfig.SaveConfig(); + } + } + else + { + lock (StatsConfig) + { + foreach (Character c in CharacterStatistics.Keys) + { + StatsConfig.Add(c.ToStringWithOutUser(), CharacterStatistics[c]); + } + StatsConfig.SaveConfig(); } - StatsConfig.SaveConfig(); } return result; @@ -400,31 +483,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { await Controller.UpdateQueue(); } - if (IsPlayer_OnlyTest(queue, character)) - { - //if (reason == QueueUpdatedReason.Action) - //{ - // queue.SetCharactersToAIControl(false, character); - //} - //if (reason == QueueUpdatedReason.PreCastSuperSkill) - //{ - // // 玩家释放爆发技后,需要等待玩家确认 - // await Controller.RequestContinuePrompt("你的下一回合需要选择爆发技目标,知晓请点击继续. . ."); - // Controller.ResolveContinuePrompt(); - //} - } - await Task.CompletedTask; } private async Task GamingQueue_TurnStart(GamingQueue queue, Character character, List enemys, List teammates, List skills, List items) { await Controller.UpdateBottomInfoPanel(); - if (IsPlayer_OnlyTest(queue, character)) - { - // 确保玩家角色在回合开始时取消AI托管,以便玩家可以控制 - //queue.SetCharactersToAIControl(cancel: true, character); - } - await Task.CompletedTask; return true; } @@ -439,7 +502,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting enemys, teammates ); - Controller.ResolveTargetSelection(selectedTargets); + await Controller.ResolveTargetSelection(selectedTargets); return selectedTargets ?? []; // 如果取消,返回空列表 } @@ -450,7 +513,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting // 通过UI请求物品选择 Item? selectedItem = await Controller.RequestItemSelection(character, items); - Controller.ResolveItemSelection(selectedItem?.Id ?? 0); + await Controller.ResolveItemSelection(selectedItem?.Id ?? 0); return selectedItem; } @@ -470,7 +533,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting enemys, teammates ); - Controller.ResolveTargetSelection(selectedTargets); + await Controller.ResolveTargetSelection(selectedTargets); return selectedTargets ?? []; // 如果取消,返回空列表 } @@ -481,27 +544,30 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting // 通过UI请求技能选择 Skill? selectedSkill = await Controller.RequestSkillSelection(character, skills); - Controller.ResolveSkillSelection(selectedSkill?.Id ?? 0); + await Controller.ResolveSkillSelection(selectedSkill?.Id ?? 0); return selectedSkill; } private async Task GamingQueue_TurnEnd(GamingQueue queue, Character character) { double ht = queue.HardnessTime[character]; - Controller.SetPredictCharacter(character.NickName, ht); + await Controller.SetPredictCharacter(character.NickName, ht); await Controller.UpdateBottomInfoPanel(); - if (IsRoundHasPlayer_OnlyTest(queue, character)) + if (!_fastMode) { - // 玩家回合结束,等待玩家确认 - await Controller.RequestContinuePrompt("你的回合(或与你相关的回合)已结束,请查看本回合日志,然后点击继续. . ."); - Controller.ResolveContinuePrompt(); + if (IsRoundHasPlayer_OnlyTest(queue, character)) + { + // 玩家回合结束,等待玩家确认 + await Controller.RequestContinuePrompt("你的回合(或与你相关的回合)已结束,请查看本回合日志,然后点击继续. . ."); + await Controller.ResolveContinuePrompt(); + } + else + { + await Controller.RequestCountDownContinuePrompt("该角色的回合已结束. . ."); + await Controller.ResolveCountDownContinuePrompt(); + } } - else - { - await Controller.RequestCountDownContinuePrompt("该角色的回合已结束. . ."); - Controller.ResolveCountDownContinuePrompt(); - } - await Task.CompletedTask; + else await Task.Delay(100); } private async Task GamingQueue_DecideAction(GamingQueue queue, Character character, List enemys, List teammates, List skills, List items) @@ -510,7 +576,7 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting { // 通过UI按钮请求行动类型 CharacterActionType actionType = await Controller.RequestActionType(character, items); - Controller.ResolveActionType(actionType); + await Controller.ResolveActionType(actionType); return actionType; } return CharacterActionType.None; // 非玩家角色,由AI处理,或默认None @@ -534,6 +600,16 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting } } + public void SetAutoMode(bool cancel, Character character) + { + _gamingQueue?.SetCharactersToAIControl(cancel, character); + } + + public void SetFastMode(bool on) + { + _fastMode = on; + } + public void WriteLine(string str) { Msg += str + "\r\n"; @@ -592,9 +668,11 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting foreach (Character c in FunGameConstant.Characters) { CharacterStatistics.Add(c, new()); + TeamCharacterStatistics.Add(c, new()); } StatsConfig.LoadConfig(); + TeamStatsConfig.LoadConfig(); foreach (Character character in CharacterStatistics.Keys) { if (StatsConfig.ContainsKey(character.ToStringWithOutUser())) @@ -602,6 +680,13 @@ namespace Milimoe.FunGame.Testing.Desktop.GameMapTesting CharacterStatistics[character] = StatsConfig.Get(character.ToStringWithOutUser()) ?? CharacterStatistics[character]; } } + foreach (Character character in TeamCharacterStatistics.Keys) + { + if (TeamStatsConfig.ContainsKey(character.ToStringWithOutUser())) + { + TeamCharacterStatistics[character] = TeamStatsConfig.Get(character.ToStringWithOutUser()) ?? TeamCharacterStatistics[character]; + } + } } public static void UpdateStatistics(CharacterStatistics totalStats, CharacterStatistics stats) diff --git a/Desktop/GameMapTesting/GameMapViewer.xaml b/Desktop/GameMapTesting/GameMapViewer.xaml index 534b7d8..f909054 100644 --- a/Desktop/GameMapTesting/GameMapViewer.xaml +++ b/Desktop/GameMapTesting/GameMapViewer.xaml @@ -69,6 +69,8 @@ + + + Foreground="White" + FontSize="10" + FontWeight="Bold" + HorizontalAlignment="Center" + VerticalAlignment="Center"/> + FontWeight="SemiBold" FontSize="10" Margin="0,0,0,2"/> + FontSize="11" Foreground="DimGray"/> + Text="{Binding PredictedTurnNumber, StringFormat=回合: {0}}" /> + Text="{Binding TurnRewardSkillName}" /> @@ -218,12 +240,12 @@ - + + Background="#FFE0FFFF"> @@ -235,18 +257,18 @@ + Panel.ZIndex="100" + HorizontalAlignment="Left" + VerticalAlignment="Top" + Margin="10" + Width="250" + MaxHeight="300" + Background="#CCFFFFFF" + BorderBrush="DarkGray" + BorderThickness="1" + CornerRadius="5" + Padding="10" + Visibility="Collapsed"> @@ -256,15 +278,42 @@ - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -281,17 +330,17 @@ + Panel.ZIndex="200" + HorizontalAlignment="Center" + VerticalAlignment="Center" + Width="400" + MaxHeight="600" + Background="#DDFFFFFF" + BorderBrush="DarkBlue" + BorderThickness="2" + CornerRadius="10" + Padding="20" + Visibility="Collapsed"> @@ -299,9 +348,9 @@ + Tag="{Binding}" + MouseLeftButtonDown="CharacterSelectionItem_MouseLeftButtonDown" + MouseEnter="CharacterSelectionItem_MouseEnter"> @@ -313,14 +362,14 @@ + IsReadOnly="True" + BorderThickness="0" + Background="Transparent" + Foreground="DimGray" + FontSize="11" + AcceptsReturn="True" + VerticalScrollBarVisibility="Disabled" + HorizontalScrollBarVisibility="Disabled"> 将鼠标悬停在角色名称上以查看详情。 @@ -331,17 +380,17 @@ + Panel.ZIndex="200" + HorizontalAlignment="Center" + VerticalAlignment="Center" + Width="400" + MaxHeight="600" + Background="#DDFFFFFF" + BorderBrush="DarkGreen" + BorderThickness="2" + CornerRadius="10" + Padding="20" + Visibility="Collapsed"> @@ -349,9 +398,9 @@ + Tag="{Binding}" + MouseLeftButtonDown="SkillItemSelectionItem_MouseLeftButtonDown" + MouseEnter="SkillItemSelectionItem_MouseEnter"> @@ -369,14 +418,14 @@ + IsReadOnly="True" + BorderThickness="0" + Background="Transparent" + Foreground="DimGray" + FontSize="11" + AcceptsReturn="True" + VerticalScrollBarVisibility="Disabled" + HorizontalScrollBarVisibility="Disabled"> 将鼠标悬停在名称上以查看详情。 @@ -388,18 +437,18 @@ + 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"> @@ -445,7 +494,7 @@