diff --git a/OshimaCore/Configs/GeneralSettings.cs b/OshimaCore/Configs/GeneralSettings.cs index 99e45e3..a8004f3 100644 --- a/OshimaCore/Configs/GeneralSettings.cs +++ b/OshimaCore/Configs/GeneralSettings.cs @@ -16,6 +16,8 @@ namespace Oshima.Core.Configs public static int BlackFrozenTime { get; set; } = 150; + public static List TokenList { get; set; } = []; + public static PluginConfig Configs { get; set; } = new("rainbot", "config"); public static void LoadSetting() @@ -38,6 +40,10 @@ namespace Oshima.Core.Configs { BlackFrozenTime = Convert.ToInt32((long)value); } + if (configs.TryGetValue("TokenList", out value) && value != null) + { + TokenList = (List)value; + } } public static void SaveConfig() @@ -46,6 +52,7 @@ namespace Oshima.Core.Configs Configs.Add("Master", Master); Configs.Add("BlackTimes", BlackTimes); Configs.Add("BlackFrozenTime", BlackFrozenTime); + Configs.Add("TokenList", TokenList); Configs.SaveConfig(); } } diff --git a/OshimaCore/Controllers/FunGameController.cs b/OshimaCore/Controllers/FunGameController.cs index ed75801..d590a34 100644 --- a/OshimaCore/Controllers/FunGameController.cs +++ b/OshimaCore/Controllers/FunGameController.cs @@ -1,4 +1,5 @@ using System.Text; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Milimoe.FunGame.Core.Api.Utility; @@ -12,6 +13,7 @@ using Oshima.FunGame.OshimaModules.Items; namespace Oshima.Core.Controllers { + [Authorize(AuthenticationSchemes = "CustomBearer")] [ApiController] [Route("[controller]")] public class FunGameController(ILogger logger) : ControllerBase @@ -28,7 +30,7 @@ namespace Oshima.Core.Controllers bool web = isweb ?? true; bool team = isteam ?? false; bool all = showall ?? false; - return FunGameActionQueue.StartSimulationGame(false, web, team, all); + return FunGameSimulation.StartSimulationGame(false, web, team, all); } [HttpGet("stats")] @@ -37,7 +39,7 @@ namespace Oshima.Core.Controllers if (id != null && id > 0 && id <= FunGameService.Characters.Count) { Character character = FunGameService.Characters[Convert.ToInt32(id) - 1]; - if (FunGameActionQueue.CharacterStatistics.TryGetValue(character, out CharacterStatistics? stats) && stats != null) + if (FunGameSimulation.CharacterStatistics.TryGetValue(character, out CharacterStatistics? stats) && stats != null) { StringBuilder builder = new(); @@ -67,14 +69,14 @@ namespace Oshima.Core.Controllers builder.AppendLine($"总计前三数:{stats.Top3s}"); builder.AppendLine($"总计败场数:{stats.Loses}"); - List names = [.. FunGameActionQueue.CharacterStatistics.OrderByDescending(kv => kv.Value.MVPs).Select(kv => kv.Key.GetName())]; + List names = [.. FunGameSimulation.CharacterStatistics.OrderByDescending(kv => kv.Value.MVPs).Select(kv => kv.Key.GetName())]; builder.AppendLine($"MVP次数:{stats.MVPs}(#{names.IndexOf(character.GetName()) + 1})"); - names = [.. FunGameActionQueue.CharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key.GetName())]; + names = [.. FunGameSimulation.CharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key.GetName())]; builder.AppendLine($"胜率:{stats.Winrates * 100:0.##}%(#{names.IndexOf(character.GetName()) + 1})"); builder.AppendLine($"前三率:{stats.Top3rates * 100:0.##}%"); - names = [.. FunGameActionQueue.CharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key.GetName())]; + names = [.. FunGameSimulation.CharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key.GetName())]; builder.AppendLine($"技术得分:{stats.Rating:0.0#}(#{names.IndexOf(character.GetName()) + 1})"); builder.AppendLine($"上次排名:{stats.LastRank} / 场均名次:{stats.AvgRank:0.##}"); @@ -91,7 +93,7 @@ namespace Oshima.Core.Controllers if (id != null && id > 0 && id <= FunGameService.Characters.Count) { Character character = FunGameService.Characters[Convert.ToInt32(id) - 1]; - if (FunGameActionQueue.TeamCharacterStatistics.TryGetValue(character, out CharacterStatistics? stats) && stats != null) + if (FunGameSimulation.TeamCharacterStatistics.TryGetValue(character, out CharacterStatistics? stats) && stats != null) { StringBuilder builder = new(); @@ -121,11 +123,11 @@ namespace Oshima.Core.Controllers builder.AppendLine($"总计胜场数:{stats.Wins}"); builder.AppendLine($"总计败场数:{stats.Loses}"); - List names = [.. FunGameActionQueue.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.MVPs).Select(kv => kv.Key.GetName())]; + List names = [.. FunGameSimulation.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.MVPs).Select(kv => kv.Key.GetName())]; builder.AppendLine($"MVP次数:{stats.MVPs}(#{names.IndexOf(character.GetName()) + 1})"); - names = [.. FunGameActionQueue.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key.GetName())]; + names = [.. FunGameSimulation.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key.GetName())]; builder.AppendLine($"胜率:{stats.Winrates * 100:0.##}%(#{names.IndexOf(character.GetName()) + 1})"); - names = [.. FunGameActionQueue.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key.GetName())]; + names = [.. FunGameSimulation.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key.GetName())]; builder.AppendLine($"技术得分:{stats.Rating:0.0#}(#{names.IndexOf(character.GetName()) + 1})"); return NetworkUtility.JsonSerialize(builder.ToString()); @@ -141,11 +143,11 @@ namespace Oshima.Core.Controllers if (team) { List strings = []; - IEnumerable ratings = FunGameActionQueue.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key); + IEnumerable ratings = FunGameSimulation.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key); foreach (Character character in ratings) { StringBuilder builder = new(); - CharacterStatistics stats = FunGameActionQueue.TeamCharacterStatistics[character]; + CharacterStatistics stats = FunGameSimulation.TeamCharacterStatistics[character]; builder.AppendLine(character.ToString()); builder.AppendLine($"总计参赛数:{stats.Plays}"); builder.AppendLine($"总计冠军数:{stats.Wins}"); @@ -159,11 +161,11 @@ namespace Oshima.Core.Controllers else { List strings = []; - IEnumerable ratings = FunGameActionQueue.CharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key); + IEnumerable ratings = FunGameSimulation.CharacterStatistics.OrderByDescending(kv => kv.Value.Winrates).Select(kv => kv.Key); foreach (Character character in ratings) { StringBuilder builder = new(); - CharacterStatistics stats = FunGameActionQueue.CharacterStatistics[character]; + CharacterStatistics stats = FunGameSimulation.CharacterStatistics[character]; builder.AppendLine(character.ToString()); builder.AppendLine($"总计参赛数:{stats.Plays}"); builder.AppendLine($"总计冠军数:{stats.Wins}"); @@ -185,11 +187,11 @@ namespace Oshima.Core.Controllers if (team) { List strings = []; - IEnumerable ratings = FunGameActionQueue.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key); + IEnumerable ratings = FunGameSimulation.TeamCharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key); foreach (Character character in ratings) { StringBuilder builder = new(); - CharacterStatistics stats = FunGameActionQueue.TeamCharacterStatistics[character]; + CharacterStatistics stats = FunGameSimulation.TeamCharacterStatistics[character]; builder.AppendLine(character.ToString()); builder.AppendLine($"总计参赛数:{stats.Plays}"); builder.AppendLine($"总计冠军数:{stats.Wins}"); @@ -203,11 +205,11 @@ namespace Oshima.Core.Controllers else { List strings = []; - IEnumerable ratings = FunGameActionQueue.CharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key); + IEnumerable ratings = FunGameSimulation.CharacterStatistics.OrderByDescending(kv => kv.Value.Rating).Select(kv => kv.Key); foreach (Character character in ratings) { StringBuilder builder = new(); - CharacterStatistics stats = FunGameActionQueue.CharacterStatistics[character]; + CharacterStatistics stats = FunGameSimulation.CharacterStatistics[character]; builder.AppendLine(character.ToString()); builder.AppendLine($"总计参赛数:{stats.Plays}"); builder.AppendLine($"总计冠军数:{stats.Wins}"); @@ -352,6 +354,49 @@ namespace Oshima.Core.Controllers } } + [HttpPost("showsaved")] + public string ShowSaved([FromQuery] long? qq = null) + { + long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + StringBuilder builder = new(); + builder.AppendLine($"☆★☆ {user.Username}的存档信息 ☆★☆"); + builder.AppendLine($"{General.GameplayEquilibriumConstant.InGameCurrency}:{user.Inventory.Credits:0.00}"); + builder.AppendLine($"{General.GameplayEquilibriumConstant.InGameMaterial}:{user.Inventory.Materials:0.00}"); + builder.AppendLine($"角色数量:{user.Inventory.Characters.Count}"); + builder.AppendLine($"主战角色:{user.Inventory.MainCharacter.ToStringWithLevelWithOutUser()}"); + Character[] squad = [.. user.Inventory.Characters.Where(c => user.Inventory.Squad.Contains(c.Id))]; + Dictionary characters = user.Inventory.Characters + .Select((character, index) => new { character, index }) + .ToDictionary(x => x.character, x => x.index + 1); + builder.AppendLine($"小队成员:{(squad.Length > 0 ? string.Join(" / ", squad.Select(c => $"[#{characters[c]}]{c.Name}({c.Level})")) : "空")}"); + if (user.Inventory.Training.Count > 0) + { + builder.AppendLine($"正在练级:{string.Join(" / ", user.Inventory.Characters.Where(c => user.Inventory.Training.ContainsKey(c.Id)).Select(c => c.ToStringWithLevelWithOutUser()))}"); + } + builder.AppendLine($"物品数量:{user.Inventory.Items.Count}"); + builder.AppendLine($"所属社团:无"); + builder.AppendLine($"注册时间:{user.RegTime.ToString(General.GeneralDateTimeFormatChinese)}"); + builder.AppendLine($"最后访问:{user.LastTime.ToString(General.GeneralDateTimeFormatChinese)}"); + + user.LastTime = DateTime.Now; + pc.Add("user", user); + pc.SaveConfig(); + return NetworkUtility.JsonSerialize(builder.ToString().Trim()); + } + else + { + return NetworkUtility.JsonSerialize(noSaved); + } + } + [HttpPost("rename")] public string ReName([FromQuery] long? qq = null) { @@ -1165,6 +1210,92 @@ namespace Oshima.Core.Controllers return NetworkUtility.JsonSerialize(e.ToString()); } } + + [HttpPost("showcharacterskills")] + public string GetCharacterSkills([FromQuery] long? qq = null, [FromQuery] int? seq = null) + { + try + { + long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + int cIndex = seq ?? 0; + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + if (cIndex == 0) + { + return NetworkUtility.JsonSerialize($"这是你的主战角色技能信息:\r\n{user.Inventory.MainCharacter.GetSkillInfo().Trim()}"); + } + else + { + if (cIndex > 0 && cIndex <= user.Inventory.Characters.Count) + { + Character character = user.Inventory.Characters.ToList()[cIndex - 1]; + return NetworkUtility.JsonSerialize($"这是你库存中序号为 {cIndex} 的角色技能信息:\r\n{character.GetSkillInfo().Trim()}"); + } + else + { + return NetworkUtility.JsonSerialize($"没有找到与这个序号相对应的角色!"); + } + } + } + else + { + return NetworkUtility.JsonSerialize(noSaved); + } + } + catch (Exception e) + { + return NetworkUtility.JsonSerialize(e.ToString()); + } + } + + [HttpPost("showcharacteritems")] + public string GetCharacterItems([FromQuery] long? qq = null, [FromQuery] int? seq = null) + { + try + { + long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + int cIndex = seq ?? 0; + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + if (cIndex == 0) + { + return NetworkUtility.JsonSerialize($"这是你的主战角色装备物品信息:\r\n{user.Inventory.MainCharacter.GetItemInfo(showEXP: true).Trim()}"); + } + else + { + if (cIndex > 0 && cIndex <= user.Inventory.Characters.Count) + { + Character character = user.Inventory.Characters.ToList()[cIndex - 1]; + return NetworkUtility.JsonSerialize($"这是你库存中序号为 {cIndex} 的角色装备物品信息:\r\n{character.GetItemInfo(showEXP: true).Trim()}"); + } + else + { + return NetworkUtility.JsonSerialize($"没有找到与这个序号相对应的角色!"); + } + } + } + else + { + return NetworkUtility.JsonSerialize(noSaved); + } + } + catch (Exception e) + { + return NetworkUtility.JsonSerialize(e.ToString()); + } + } [HttpPost("showiteminfo")] public string GetItemInfoFromInventory([FromQuery] long? qq = null, [FromQuery] int? seq = null) @@ -1358,7 +1489,7 @@ namespace Oshima.Core.Controllers if (user1 != null && user2 != null) { - return FunGameActionQueue.StartGame([user1.Inventory.MainCharacter, user2.Inventory.MainCharacter], false, false, false, false, showAllRound); + return FunGameActionQueue.NewAndStartGame([user1.Inventory.MainCharacter, user2.Inventory.MainCharacter], false, false, false, false, showAllRound); } else { @@ -2316,7 +2447,7 @@ namespace Oshima.Core.Controllers user.LastTime = DateTime.Now; pc.Add("user", user); pc.SaveConfig(); - return NetworkUtility.JsonSerialize($"角色 [{character}] 开始练级,请过一段时间后进行【练级结算】,时间越长奖励越丰盛!练级时间最长 1440 分钟(24小时),超时将无任何收益,请及时领取奖励。"); + return NetworkUtility.JsonSerialize($"角色 [{character}] 开始练级,请过一段时间后进行【练级结算】,时间越长奖励越丰盛!练级时间上限 1440 分钟(24小时),超时将不会再产生收益,请按时领取奖励!"); } else { @@ -2856,7 +2987,7 @@ namespace Oshima.Core.Controllers } Character boss2 = CharacterBuilder.Build(boss, false, true, null, FunGameService.AllItems, FunGameService.AllSkills, false); - List msgs = FunGameActionQueue.StartGame([user.Inventory.MainCharacter, boss2], false, false, false, false, showAllRound); + List msgs = FunGameActionQueue.NewAndStartGame([user.Inventory.MainCharacter, boss2], false, false, false, false, showAllRound); if (boss2.HP <= 0) { @@ -2991,11 +3122,115 @@ namespace Oshima.Core.Controllers } } + [HttpPost("setsquad")] + public string SetSquad([FromQuery] long? qq = null, [FromBody] int[]? c = null) + { + try + { + long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + int[] characterIndexs = c ?? []; + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + user.Inventory.Squad.Clear(); + foreach (int characterIndex in characterIndexs) + { + Character? character = null; + if (characterIndex > 0 && characterIndex <= user.Inventory.Characters.Count) + { + character = user.Inventory.Characters.ToList()[characterIndex - 1]; + } + else + { + return NetworkUtility.JsonSerialize($"设置失败:没有找到与序号 {characterIndex} 相对应的角色!"); + } + user.Inventory.Squad.Add(character.Id); + } + + user.LastTime = DateTime.Now; + pc.Add("user", user); + pc.SaveConfig(); + return NetworkUtility.JsonSerialize($"设置小队成员成功!当前小队角色如下:\r\n" + + string.Join("\r\n", user.Inventory.Characters.Where(c => user.Inventory.Squad.Contains(c.Id)))); + } + else + { + return NetworkUtility.JsonSerialize(noSaved); + } + } + catch (Exception e) + { + return NetworkUtility.JsonSerialize(e.ToString()); + } + } + + [HttpPost("clearsquad")] + public string ClearSquad([FromQuery] long? qq = null, [FromBody] int[]? c = null) + { + try + { + long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + int[] characterIndexs = c ?? []; + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + user.Inventory.Squad.Clear(); + user.LastTime = DateTime.Now; + pc.Add("user", user); + pc.SaveConfig(); + return NetworkUtility.JsonSerialize($"清空小队成员成功!"); + } + else + { + return NetworkUtility.JsonSerialize(noSaved); + } + } + catch (Exception e) + { + return NetworkUtility.JsonSerialize(e.ToString()); + } + } + + [HttpPost("showsquad")] + public string ShowSquad([FromQuery] long? qq = null) + { + try + { + long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + return NetworkUtility.JsonSerialize($"你的当前小队角色如下:\r\n" + + string.Join("\r\n", user.Inventory.Characters.Where(c => user.Inventory.Squad.Contains(c.Id)))); + } + else + { + return NetworkUtility.JsonSerialize(noSaved); + } + } + catch (Exception e) + { + return NetworkUtility.JsonSerialize(e.ToString()); + } + } + [HttpPost("fightbossteam")] public List FightBossTeam([FromQuery] long? qq = null, [FromQuery] int? index = null, [FromQuery] bool? all = null) { - return []; - long userid = qq ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); int bossIndex = index ?? 0; bool showAllRound = all ?? false; @@ -3013,14 +3248,15 @@ namespace Oshima.Core.Controllers if (squad.All(c => c.HP < c.MaxHP * 0.1)) { - return [$"小队角色均重伤未愈,当前生命值低于 10%,请先等待生命值自动回复或重组小队!", - "当前小队角色如下:", + return [$"小队角色均重伤未愈,当前生命值低于 10%,请先等待生命值自动回复或重组小队!\r\n" + + "当前小队角色如下:\r\n" + string.Join("\r\n", user.Inventory.Characters.Where(c => user.Inventory.Squad.Contains(c.Id)))]; } Character boss2 = CharacterBuilder.Build(boss, false, true, null, FunGameService.AllItems, FunGameService.AllSkills, false); - //List msgs = FunGameActionQueue.StartGameTeam; - List msgs = []; + Team team1 = new($"{user.Username}的小队", squad); + Team team2 = new($"Boss", [boss2]); + List msgs = FunGameActionQueue.NewAndStartTeamGame([team1, team2], showAllRound: showAllRound); if (boss2.HP <= 0) { @@ -3059,7 +3295,7 @@ namespace Oshima.Core.Controllers if (master != null && master == GeneralSettings.Master) { FunGameService.Reload(); - FunGameActionQueue.InitFunGameActionQueue(); + FunGameSimulation.InitFunGameSimulation(); return NetworkUtility.JsonSerialize("FunGame已重新加载。"); } return NetworkUtility.JsonSerialize("提供的参数不正确。"); diff --git a/OshimaCore/Controllers/TestController.cs b/OshimaCore/Controllers/TestController.cs index 98ccec8..d6623bf 100644 --- a/OshimaCore/Controllers/TestController.cs +++ b/OshimaCore/Controllers/TestController.cs @@ -3,9 +3,9 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Api.Utility; -using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Exception; using Milimoe.FunGame.Core.Library.SQLScript.Common; +using Oshima.Core.Configs; using Oshima.Core.Constant; using TaskScheduler = Milimoe.FunGame.Core.Api.Utility.TaskScheduler; @@ -47,7 +47,7 @@ namespace Oshima.Core.Controllers } catch (Exception e) { - Statics.RunningPlugin.Controller?.Error(e); + Statics.RunningPlugin.Controller.Error(e); return NetworkUtility.JsonSerialize("鏃犳硶璋冪敤姝ゆ帴鍙c傚師鍥狅細\r\n" + e.GetErrorInfo()); } } @@ -59,5 +59,28 @@ namespace Oshima.Core.Controllers { return NetworkUtility.JsonSerialize(TaskScheduler.Shared.GetRunTimeInfo(name)); } + + [HttpGet("sendtest")] + public string SendTest(long key, string to) + { + if (Statics.RunningPlugin != null && key == GeneralSettings.Master) + { + try + { + MailSender? sender = Statics.RunningPlugin.Controller.MailSender; + if (sender != null && sender.Send(new(sender, "Test Mail", "Hello!", to)) == Milimoe.FunGame.Core.Library.Constant.MailSendResult.Success) + { + return NetworkUtility.JsonSerialize("鍙戦佹垚鍔熴"); + } + return NetworkUtility.JsonSerialize("鍙戦佸け璐ャ"); + } + catch (Exception e) + { + Statics.RunningPlugin.Controller.Error(e); + return NetworkUtility.JsonSerialize("鏃犳硶璋冪敤姝ゆ帴鍙c傚師鍥狅細\r\n" + e.GetErrorInfo()); + } + } + return NetworkUtility.JsonSerialize("鏃犳硶璋冪敤姝ゆ帴鍙c"); + } } } diff --git a/OshimaCore/OshimaWebAPI.cs b/OshimaCore/OshimaWebAPI.cs index 32aad35..f04ef39 100644 --- a/OshimaCore/OshimaWebAPI.cs +++ b/OshimaCore/OshimaWebAPI.cs @@ -23,7 +23,7 @@ namespace Oshima.Core.WebAPI { if (input.StartsWith("fungametest")) { - FunGameActionQueue.StartSimulationGame(true, true); + FunGameSimulation.StartSimulationGame(true, true); } // OSM鎸囦护 if (input.Length >= 4 && input[..4].Equals(".osm", StringComparison.CurrentCultureIgnoreCase)) @@ -46,7 +46,8 @@ namespace Oshima.Core.WebAPI SayNo.InitSayNo(); Ignore.InitIgnore(); FunGameService.InitFunGame(); - FunGameActionQueue.InitFunGameActionQueue(); + FunGameSimulation.InitFunGameSimulation(); + WebAPIAuthenticator.WebAPICustomBearerTokenAuthenticator += CustomBearerTokenAuthenticator; TaskScheduler.Shared.AddTask("閲嶇疆姣忔棩杩愬娍", new TimeSpan(0, 0, 0), () => { Controller.WriteLine("宸查噸缃墍鏈変汉鐨勪粖鏃ヨ繍鍔"); @@ -88,5 +89,14 @@ namespace Oshima.Core.WebAPI Controller.WriteLine("鍒锋柊boss"); }, true); } + + private string CustomBearerTokenAuthenticator(string token) + { + if (GeneralSettings.TokenList.Contains(token)) + { + return "APIUser"; + } + return ""; + } } } diff --git a/OshimaCore/Utils/FunGameActionQueue.cs b/OshimaCore/Utils/FunGameActionQueue.cs index 9dde426..fccf4b8 100644 --- a/OshimaCore/Utils/FunGameActionQueue.cs +++ b/OshimaCore/Utils/FunGameActionQueue.cs @@ -1,579 +1,30 @@ 锘縰sing System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Entity; -using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Model; using Oshima.FunGame.OshimaModules.Effects.OpenEffects; -using Oshima.FunGame.OshimaModules.Skills; namespace Oshima.Core.Utils { public class FunGameActionQueue { - public static Dictionary CharacterStatistics { get; } = []; - public static Dictionary TeamCharacterStatistics { get; } = []; - public static PluginConfig StatsConfig { get; } = new("FunGameSimulation", nameof(CharacterStatistics)); - public static PluginConfig TeamStatsConfig { get; } = new("FunGameSimulation", nameof(TeamCharacterStatistics)); - public static bool IsRuning { get; set; } = false; - public static bool IsWeb { get; set; } = false; - public static bool PrintOut { get; set; } = false; - public static bool DeathMatchRoundDetail { get; set; } = false; - public static string Msg { get; set; } = ""; + public ActionQueue ActionQueue { get; set; } = new(); + public bool IsWeb { get; set; } = false; + public bool PrintOut { get; set; } = false; + public bool DeathMatchRoundDetail { get; set; } = false; + public List Result { get; } = []; - public static void InitFunGameActionQueue() - { - CharacterStatistics.Clear(); - TeamCharacterStatistics.Clear(); - - foreach (Character c in FunGameService.Characters) - { - CharacterStatistics.Add(c, new()); - } - - StatsConfig.LoadConfig(); - foreach (Character character in CharacterStatistics.Keys) - { - if (StatsConfig.ContainsKey(character.ToStringWithOutUser())) - { - CharacterStatistics[character] = StatsConfig.Get(character.ToStringWithOutUser()) ?? CharacterStatistics[character]; - } - } - - foreach (Character c in FunGameService.Characters) - { - TeamCharacterStatistics.Add(c, new()); - } - - TeamStatsConfig.LoadConfig(); - foreach (Character character in TeamCharacterStatistics.Keys) - { - if (TeamStatsConfig.ContainsKey(character.ToStringWithOutUser())) - { - TeamCharacterStatistics[character] = TeamStatsConfig.Get(character.ToStringWithOutUser()) ?? TeamCharacterStatistics[character]; - } - } - } - - public static List StartSimulationGame(bool printout, bool isWeb = false, bool isTeam = false, bool deathMatchRoundDetail = false) + private string _msg = ""; + + public List StartGame(List characters, bool printout = false, bool isWeb = false, bool deathMatchRoundDetail = false, bool showRoundEndDetail = false, bool showAllRound = false) { + Result.Clear(); PrintOut = printout; IsWeb = isWeb; DeathMatchRoundDetail = deathMatchRoundDetail; try { - if (IsRuning) return ["娓告垙姝e湪妯℃嫙涓紝璇峰嬁閲嶅璇锋眰锛"]; - - List result = []; - Msg = ""; - - IsRuning = true; - - // M = 0, W = 7, P1 = 1, P3 = 1 - // M = 1, W = 6, P1 = 2, P3 = 0 - // M = 2, W = 4, P1 = 0, P3 = 2 - // M = 2, W = 5, P1 = 0, P3 = 0 - // M = 3, W = 3, P1 = 1, P3 = 1 - // M = 4, W = 2, P1 = 2, P3 = 0 - // M = 5, W = 0, P1 = 0, P3 = 2 - // M = 5, W = 1, P1 = 0, P3 = 0 - - List list = new(FunGameService.Characters); - - if (list.Count > 11) - { - if (PrintOut) Console.WriteLine(); - if (PrintOut) Console.WriteLine("Start!!!"); - if (PrintOut) Console.WriteLine(); - - Character character1 = list[0].Copy(); - Character character2 = list[1].Copy(); - Character character3 = list[2].Copy(); - Character character4 = list[3].Copy(); - Character character5 = list[4].Copy(); - Character character6 = list[5].Copy(); - Character character7 = list[6].Copy(); - Character character8 = list[7].Copy(); - Character character9 = list[8].Copy(); - Character character10 = list[9].Copy(); - Character character11 = list[10].Copy(); - Character character12 = list[11].Copy(); - - List characters = [ - character1, character2, character3, character4, - character5, character6, character7, character8, - character9, character10, character11, character12 - ]; - - int clevel = 60; - int slevel = 6; - int mlevel = 8; - - // 鍗囩骇鍜岃祴鑳 - for (int index = 0; index < characters.Count; index++) - { - Character c = characters[index]; - c.Level = clevel; - c.NormalAttack.Level = mlevel; - FunGameService.AddCharacterSkills(c, 1, slevel, slevel); - } - - // 鍒涘缓椤哄簭琛ㄥ苟鎺掑簭 - ActionQueue actionQueue = new(characters, isTeam, WriteLine); - if (isTeam) - { - actionQueue.MaxRespawnTimes = -1; - actionQueue.MaxScoreToWin = 30; - } - if (PrintOut) Console.WriteLine(); - - // 鎬绘父鎴忔椂闀 - double totalTime = 0; - - // 寮濮嬬┖鎶 - Msg = ""; - int 鍙戞斁鐨勫崱鍖呭搧璐 = 0; - int 鍙戞斁鐨勬鍣ㄥ搧璐 = 0; - int 鍙戞斁鐨勯槻鍏峰搧璐 = 0; - int 鍙戞斁鐨勯瀷瀛愬搧璐 = 0; - int 鍙戞斁鐨勯グ鍝佸搧璐 = 0; - WriteLine($"绀惧尯閫佹俯鏆栦簡锛岀幇鍦ㄩ殢鏈哄彂鏀剧┖鎶曪紒锛"); - 绌烘姇(actionQueue, 鍙戞斁鐨勫崱鍖呭搧璐, 鍙戞斁鐨勬鍣ㄥ搧璐, 鍙戞斁鐨勯槻鍏峰搧璐, 鍙戞斁鐨勯瀷瀛愬搧璐, 鍙戞斁鐨勯グ鍝佸搧璐); - WriteLine(""); - if (isWeb) result.Add("=== 绌烘姇 ===\r\n" + Msg); - double 涓嬩竴娆$┖鎶 = isTeam ? 80 : 40; - if (鍙戞斁鐨勫崱鍖呭搧璐 < 4) - { - 鍙戞斁鐨勫崱鍖呭搧璐++; - } - if (鍙戞斁鐨勬鍣ㄥ搧璐 < 4) - { - 鍙戞斁鐨勬鍣ㄥ搧璐++; - } - if (鍙戞斁鐨勯槻鍏峰搧璐 < 1) - { - 鍙戞斁鐨勯槻鍏峰搧璐++; - } - if (鍙戞斁鐨勯瀷瀛愬搧璐 < 1) - { - 鍙戞斁鐨勯瀷瀛愬搧璐++; - } - if (鍙戞斁鐨勯グ鍝佸搧璐 < 3) - { - 鍙戞斁鐨勯グ鍝佸搧璐++; - } - - // 鏄剧ず瑙掕壊淇℃伅 - if (PrintOut) characters.ForEach(c => Console.WriteLine(c.GetInfo())); - - // 鍥犺祴浜堜簡瑁呭锛屾墍浠ユ竻闄ゆ帓搴忛噸鏂版帓 - actionQueue.ClearQueue(); - actionQueue.InitCharacterQueue(characters); - if (PrintOut) Console.WriteLine(); - - // 鍥㈤槦妯″紡 - if (isTeam) - { - Msg = "=== 鍥㈤槦妯″紡闅忔満鍒嗙粍 ===\r\n\r\n"; - // 鎵撲贡瑙掕壊鍒楄〃 - List shuffledCharacters = [.. characters.OrderBy(c => Random.Shared.Next())]; - - // 鍒涘缓涓や釜鍥㈤槦 - List group1 = []; - List group2 = []; - - // 灏嗚鑹蹭氦鏇垮垎閰嶅埌涓や釜鍥㈤槦涓 - for (int cid = 0; cid < shuffledCharacters.Count; cid++) - { - if (cid % 2 == 0) - { - group1.Add(shuffledCharacters[cid]); - } - else - { - group2.Add(shuffledCharacters[cid]); - } - } - - // 娣诲姞鍒板洟闃熷瓧鍏 - actionQueue.AddTeam("闃熶紞涓", group1); - actionQueue.AddTeam("闃熶紞浜", group2); - - foreach (string team in actionQueue.Teams.Keys) - { - WriteLine($"鍥㈤槦銆恵team}銆戠殑鎴愬憳锛歕r\n{string.Join("\r\n", actionQueue.Teams[team].Members)}\r\n"); - } - result.Add(Msg); - } - - // 鏄剧ず鍒濆椤哄簭琛 - actionQueue.DisplayQueue(); - if (PrintOut) Console.WriteLine(); - - // 鎬诲洖鍚堟暟 - int maxRound = isTeam ? 9999 : 999; - - // 闅忔満鍥炲悎濂栧姳 - Dictionary> roundRewards = GenerateRoundRewards(maxRound); - - int i = 1; - while (i < maxRound) - { - Msg = ""; - if (i == maxRound - 1) - { - if (isTeam) - { - WriteLine("涓ら槦鎵撳埌澶╂槒鍦版殫锛屾祦灞浜嗭紒锛"); - break; - } - else - { - WriteLine($"=== 缁堝眬瀹″垽 ==="); - Dictionary 浠栦滑鐨勮閲忕櫨鍒嗘瘮 = []; - foreach (Character c in characters) - { - 浠栦滑鐨勮閲忕櫨鍒嗘瘮.TryAdd(c, c.HP / c.MaxHP); - } - double max = 浠栦滑鐨勮閲忕櫨鍒嗘瘮.Values.Max(); - Character winner = 浠栦滑鐨勮閲忕櫨鍒嗘瘮.Keys.Where(c => 浠栦滑鐨勮閲忕櫨鍒嗘瘮[c] == max).First(); - WriteLine("[ " + winner + " ] 鎴愪负浜嗗ぉ閫変箣浜猴紒锛"); - foreach (Character c in characters.Where(c => c != winner && c.HP > 0)) - { - WriteLine("[ " + winner + " ] 瀵 [ " + c + " ] 閫犳垚浜 99999999999 鐐圭湡瀹炰激瀹炽"); - actionQueue.DeathCalculation(winner, c); - } - actionQueue.EndGameInfo(winner); - result.Add(Msg); - break; - } - } - - // 妫鏌ユ槸鍚︽湁瑙掕壊鍙互琛屽姩 - Character? characterToAct = actionQueue.NextCharacter(); - - // 澶勭悊鍥炲悎 - if (characterToAct != null) - { - // 鑾峰彇鍥炲悎濂栧姳 - List skillRewards = []; - if (roundRewards.TryGetValue(i, out List? effectList) && effectList != null) - { - skillRewards = new(effectList); - } - - WriteLine($"=== Round {i++} ==="); - WriteLine("鐜板湪鏄 [ " + characterToAct + (isTeam ? "锛" + (actionQueue.GetTeam(characterToAct)?.Name ?? "") + "锛" : "") + " ] 鐨勫洖鍚堬紒"); - - // 瀹為檯鐨勫洖鍚堝鍔 - List realSkillRewards = []; - if (skillRewards.Count > 0) - { - foreach (Skill skill in skillRewards) - { - Dictionary effectArgs = []; - if (RoundRewards.TryGetValue((EffectID)skill.Id, out Dictionary? dict) && dict != null) - { - effectArgs = new(dict); - } - Dictionary args = new() - { - { "skill", skill }, - { "values", effectArgs } - }; - skill.GamingQueue = actionQueue; - skill.Effects.Add(Factory.OpenFactory.GetInstance(skill.Id, "", args)); - skill.Character = characterToAct; - skill.Level = 1; - actionQueue.LastRound.RoundRewards.Add(skill); - WriteLine($"[ {characterToAct} ] 鑾峰緱浜嗗洖鍚堝鍔憋紒{skill.Description}".Trim()); - if (skill.IsActive) - { - actionQueue.LastRound.Targets.Add(characterToAct); - skill.OnSkillCasted(actionQueue, characterToAct, [characterToAct]); - } - else - { - characterToAct.Skills.Add(skill); - realSkillRewards.Add(skill); - } - } - } - - bool isGameEnd = actionQueue.ProcessTurn(characterToAct); - - if (realSkillRewards.Count > 0) - { - foreach (Skill skill in realSkillRewards) - { - foreach (Effect e in skill.Effects) - { - e.OnEffectLost(characterToAct); - characterToAct.Effects.Remove(e); - } - characterToAct.Skills.Remove(skill); - skill.Character = null; - } - } - - if (isGameEnd) - { - result.Add(Msg); - break; - } - - actionQueue.DisplayQueue(); - WriteLine(""); - } - - string roundMsg = ""; - if (actionQueue.LastRound.HasKill) - { - roundMsg = Msg; - if (!deathMatchRoundDetail) - { - roundMsg = actionQueue.LastRound.ToString().Trim() + $"\r\n{(isTeam ? $"姣斿垎锛歿string.Join(" / ", actionQueue.Teams.Values.Select(t => $"{t.Name}({t.Score})"))}锛屽嚮鏉鏉ヨ嚜{actionQueue.GetTeam(actionQueue.LastRound.Actor)}" : "")}\r\n"; - } - Msg = ""; - } - - // 妯℃嫙鏃堕棿娴侀 - double timeLapse = actionQueue.TimeLapse(); - totalTime += timeLapse; - 涓嬩竴娆$┖鎶 -= timeLapse; - - if (roundMsg != "") - { - if ((isTeam && deathMatchRoundDetail || !isTeam) && isWeb) - { - roundMsg += "\r\n" + Msg; - } - result.Add(roundMsg); - } - - if (涓嬩竴娆$┖鎶 <= 0) - { - // 绌烘姇 - Msg = ""; - WriteLine($"绀惧尯閫佹俯鏆栦簡锛岀幇鍦ㄩ殢鏈哄彂鏀剧┖鎶曪紒锛"); - 绌烘姇(actionQueue, 鍙戞斁鐨勫崱鍖呭搧璐, 鍙戞斁鐨勬鍣ㄥ搧璐, 鍙戞斁鐨勯槻鍏峰搧璐, 鍙戞斁鐨勯瀷瀛愬搧璐, 鍙戞斁鐨勯グ鍝佸搧璐); - WriteLine(""); - if (isWeb) result.Add("=== 绌烘姇 ===\r\n" + Msg); - 涓嬩竴娆$┖鎶 = isTeam ? 100 : 40; - if (鍙戞斁鐨勫崱鍖呭搧璐 < 4) - { - 鍙戞斁鐨勫崱鍖呭搧璐++; - } - if (鍙戞斁鐨勬鍣ㄥ搧璐 < 4) - { - 鍙戞斁鐨勬鍣ㄥ搧璐++; - } - if (鍙戞斁鐨勯槻鍏峰搧璐 < 1) - { - 鍙戞斁鐨勯槻鍏峰搧璐++; - } - if (鍙戞斁鐨勯瀷瀛愬搧璐 < 1) - { - 鍙戞斁鐨勯瀷瀛愬搧璐++; - } - if (鍙戞斁鐨勯グ鍝佸搧璐 < 3) - { - 鍙戞斁鐨勯グ鍝佸搧璐++; - } - } - } - - if (PrintOut) - { - Console.WriteLine("--- End ---"); - Console.WriteLine($"鎬绘父鎴忔椂闀匡細{totalTime:0.##}"); - Console.WriteLine(""); - } - - // 璧涘悗缁熻 - GetCharacterRating(actionQueue.CharacterStatistics, isTeam, actionQueue.EliminatedTeams); - - // 缁熻鎶鏈緱鍒嗭紝璇勯 MVP - Character? mvp = actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key).FirstOrDefault(); - StringBuilder mvpBuilder = new(); - if (mvp != null) - { - CharacterStatistics stats = actionQueue.CharacterStatistics[mvp]; - stats.MVPs++; - mvpBuilder.AppendLine($"{(isTeam ? "[ " + actionQueue.GetTeamFromEliminated(mvp)?.Name + " ] " : "")}[ {mvp.ToStringWithLevel()} ]"); - mvpBuilder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.##} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); - mvpBuilder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); - mvpBuilder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); - mvpBuilder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); - mvpBuilder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); - } - - int top = isWeb ? actionQueue.CharacterStatistics.Count : 0; // 鍥炴墽澶氬皯涓鑹茬殑缁熻淇℃伅 - int count = 1; - if (isWeb) - { - WriteLine("=== 鎶鏈緱鍒嗘帓琛屾 ==="); // 杩欐槸杈撳嚭鍦ㄧ晫闈笂鐨 - Msg = $"=== 鎶鏈緱鍒嗘帓琛屾 TOP{top} ===\r\n"; // 杩欎釜鏄笅涓鏉$粰Result鍥炴墽鐨勬爣棰橈紝瑕嗙洊鎺変笂闈㈡柟娉曢噷鐨勮祴鍊间簡 - } - else - { - WriteLine("=== 鏈満姣旇禌鏈浣宠鑹 ==="); - Msg = $"=== 鏈満姣旇禌鏈浣宠鑹 ===\r\n"; - WriteLine(mvpBuilder.ToString()); - - if (PrintOut) - { - Console.WriteLine(); - Console.WriteLine("=== 鎶鏈緱鍒嗘帓琛屾 ==="); - } - } - - if (isTeam) - { - foreach (Character character in actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) - { - StringBuilder builder = new(); - CharacterStatistics stats = actionQueue.CharacterStatistics[character]; - builder.AppendLine($"{(isWeb ? count + "." : ("[ " + actionQueue.GetTeamFromEliminated(character)?.Name + " ]" ?? ""))} [ {character.ToStringWithLevel()} ]"); - builder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.##} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); - builder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); - builder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); - builder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); - builder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); - if (count++ <= top) - { - WriteLine(builder.ToString()); - } - else - { - if (PrintOut) Console.WriteLine(builder.ToString()); - } - - CharacterStatistics? totalStats = TeamCharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); - if (totalStats != null) - { - UpdateStatistics(totalStats, stats); - } - } - } - else - { - foreach (Character character in actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) - { - StringBuilder builder = new(); - CharacterStatistics stats = actionQueue.CharacterStatistics[character]; - builder.AppendLine($"{(isWeb ? count + ". " : "")}[ {character.ToStringWithLevel()} ]"); - builder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.##} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); - builder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); - builder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); - builder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); - builder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); - if (count++ <= top) - { - WriteLine(builder.ToString()); - } - else - { - if (PrintOut) Console.WriteLine(builder.ToString()); - } - - CharacterStatistics? totalStats = CharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); - if (totalStats != null) - { - UpdateStatistics(totalStats, stats); - } - } - } - - result.Add(Msg); - - // 鏄剧ず姣忎釜瑙掕壊鐨勪俊鎭 - if (isWeb) - { - if (isTeam) - { - top = 1; - for (i = actionQueue.EliminatedTeams.Count - 1; i >= 0; i--) - { - Team team = actionQueue.EliminatedTeams[i]; - string topTeam = ""; - if (top == 1) - { - topTeam = "鍐犲啗"; - } - if (top == 2) - { - topTeam = "浜氬啗"; - } - if (top == 3) - { - topTeam = "瀛e啗"; - } - if (top > 3) - { - topTeam = $"绗 {top} 鍚"; - } - foreach (Character character in team.Members) - { - result.Add($"== {topTeam}鍥㈤槦 [ {team.Name} ] ==\r\n== 瑙掕壊锛歔 {character} ] ==\r\n{character.GetInfo()}"); - } - top++; - } - } - else - { - for (i = actionQueue.Eliminated.Count - 1; i >= 0; i--) - { - Character character = actionQueue.Eliminated[i]; - result.Add($"=== 瑙掕壊 [ {character} ] ===\r\n{character.GetInfo()}"); - } - } - } - - if (isTeam) - { - lock (TeamStatsConfig) - { - 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(); - } - } - - IsRuning = false; - } - - return result; - } - catch (Exception ex) - { - IsRuning = false; - Console.WriteLine(ex); - return [ex.ToString()]; - } - } - - public static List StartGame(List characters, bool printout, bool isWeb = false, bool deathMatchRoundDetail = false, bool showRoundEndDetail = false, bool showAllRound = false) - { - PrintOut = printout; - IsWeb = isWeb; - DeathMatchRoundDetail = deathMatchRoundDetail; - try - { - List result = []; - Msg = ""; + _msg = ""; if (PrintOut) Console.WriteLine(); if (PrintOut) Console.WriteLine("Start!!!"); @@ -597,12 +48,12 @@ namespace Oshima.Core.Utils int maxRound = 999; // 闅忔満鍥炲悎濂栧姳 - Dictionary> roundRewards = GenerateRoundRewards(maxRound); + Dictionary> roundRewards = FunGameService.GenerateRoundRewards(maxRound); int i = 1; while (i < maxRound) { - Msg = ""; + _msg = ""; if (i == maxRound - 1) { WriteLine($"=== 缁堝眬瀹″垽 ==="); @@ -620,7 +71,7 @@ namespace Oshima.Core.Utils actionQueue.DeathCalculation(winner, c); } actionQueue.EndGameInfo(winner); - result.Add(Msg); + Result.Add(_msg); break; } @@ -647,7 +98,7 @@ namespace Oshima.Core.Utils foreach (Skill skill in skillRewards) { Dictionary effectArgs = []; - if (RoundRewards.TryGetValue((EffectID)skill.Id, out Dictionary? dict) && dict != null) + if (FunGameService.RoundRewards.TryGetValue((EffectID)skill.Id, out Dictionary? dict) && dict != null) { effectArgs = new(dict); } @@ -693,7 +144,7 @@ namespace Oshima.Core.Utils if (isGameEnd) { - result.Add(Msg); + Result.Add(_msg); break; } @@ -704,7 +155,7 @@ namespace Oshima.Core.Utils string roundMsg = ""; if (actionQueue.LastRound.HasKill || showAllRound) { - roundMsg = Msg; + roundMsg = _msg; if (!deathMatchRoundDetail) { roundMsg = actionQueue.LastRound.ToString().Trim() + "\r\n"; @@ -716,7 +167,7 @@ namespace Oshima.Core.Utils } } } - Msg = ""; + _msg = ""; } // 妯℃嫙鏃堕棿娴侀 @@ -727,9 +178,9 @@ namespace Oshima.Core.Utils { if (isWeb) { - roundMsg += "\r\n" + Msg; + roundMsg += "\r\n" + _msg; } - result.Add(roundMsg); + Result.Add(roundMsg); } } @@ -741,7 +192,7 @@ namespace Oshima.Core.Utils } // 璧涘悗缁熻 - GetCharacterRating(actionQueue.CharacterStatistics, false, actionQueue.EliminatedTeams); + FunGameService.GetCharacterRating(actionQueue.CharacterStatistics, false, actionQueue.EliminatedTeams); // 缁熻鎶鏈緱鍒嗭紝璇勯 MVP Character? mvp = actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key).FirstOrDefault(); @@ -751,7 +202,7 @@ namespace Oshima.Core.Utils CharacterStatistics stats = actionQueue.CharacterStatistics[mvp]; stats.MVPs++; mvpBuilder.AppendLine($"[ {mvp.ToStringWithLevel()} ]"); - mvpBuilder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.##} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); + mvpBuilder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.0#} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); mvpBuilder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); mvpBuilder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); mvpBuilder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); @@ -760,14 +211,14 @@ namespace Oshima.Core.Utils int top = isWeb ? actionQueue.CharacterStatistics.Count : 2; // 鍥炴墽澶氬皯涓鑹茬殑缁熻淇℃伅 int count = 1; - Msg = $"=== 鎶鏈緱鍒嗘帓琛屾 TOP{top} ===\r\n"; + _msg = $"=== 鎶鏈緱鍒嗘帓琛屾 TOP{top} ===\r\n"; foreach (Character character in actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) { StringBuilder builder = new(); CharacterStatistics stats = actionQueue.CharacterStatistics[character]; builder.AppendLine($"{count + ". "}[ {character.ToStringWithLevel()} ]"); - builder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.##} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); + builder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.0#} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); builder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); builder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); builder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); @@ -781,9 +232,13 @@ namespace Oshima.Core.Utils { if (PrintOut) Console.WriteLine(builder.ToString()); } + if (character.User != null) + { + character.User.Inventory.Credits += stats.TotalEarnedMoney; + } } - result.Add(Msg); + Result.Add(_msg); // 鏄剧ず姣忎釜瑙掕壊鐨勪俊鎭 if (isWeb) @@ -791,11 +246,11 @@ namespace Oshima.Core.Utils for (i = actionQueue.Eliminated.Count - 1; i >= 0; i--) { Character character = actionQueue.Eliminated[i]; - result.Add($"=== 瑙掕壊 [ {character} ] ===\r\n{character.GetInfo()}"); + Result.Add($"=== 瑙掕壊 [ {character} ] ===\r\n{character.GetInfo()}"); } } - return result; + return Result; } catch (Exception ex) { @@ -804,277 +259,247 @@ namespace Oshima.Core.Utils } } - public static void WriteLine(string str) + public List StartTeamGame(List teams, int maxRespawnTimes = 0, int maxScoreToWin = 0, bool printout = false, bool isWeb = false, bool deathMatchRoundDetail = false, bool showRoundEndDetail = false, bool showAllRound = false) { - Msg += str + "\r\n"; + Result.Clear(); + PrintOut = printout; + IsWeb = isWeb; + DeathMatchRoundDetail = deathMatchRoundDetail; + try + { + _msg = ""; + + if (teams.Count > 1) + { + if (PrintOut) Console.WriteLine(); + if (PrintOut) Console.WriteLine("Start!!!"); + if (PrintOut) Console.WriteLine(); + + List characters = [.. teams.SelectMany(t => t.Members)]; + + // 鍒涘缓椤哄簭琛ㄥ苟鎺掑簭 + ActionQueue actionQueue = new(characters, true, WriteLine) + { + MaxRespawnTimes = maxRespawnTimes, + MaxScoreToWin = maxScoreToWin + }; + if (PrintOut) Console.WriteLine(); + + // 鎬绘父鎴忔椂闀 + double totalTime = 0; + + // 鏄剧ず瑙掕壊淇℃伅 + if (PrintOut) characters.ForEach(c => Console.WriteLine(c.GetInfo())); + + // 娣诲姞鍒板洟闃熷瓧鍏 + foreach (Team team in teams) + { + actionQueue.AddTeam(team.Name, team.Members); + Result.Add($"鍥㈤槦銆恵team}銆戠殑鎴愬憳锛歕r\n{string.Join("\r\n", team.Members)}\r\n"); + } + + // 鏄剧ず鍒濆椤哄簭琛 + actionQueue.DisplayQueue(); + if (PrintOut) Console.WriteLine(); + + // 鎬诲洖鍚堟暟 + int maxRound = 9999; + + // 闅忔満鍥炲悎濂栧姳 + Dictionary> roundRewards = FunGameService.GenerateRoundRewards(maxRound); + + int i = 1; + while (i < maxRound) + { + _msg = ""; + if (i == maxRound - 1) + { + WriteLine("涓ら槦鎵撳埌澶╂槒鍦版殫锛屾祦灞浜嗭紒锛"); + break; + } + + // 妫鏌ユ槸鍚︽湁瑙掕壊鍙互琛屽姩 + Character? characterToAct = actionQueue.NextCharacter(); + + // 澶勭悊鍥炲悎 + if (characterToAct != null) + { + // 鑾峰彇鍥炲悎濂栧姳 + List skillRewards = []; + if (roundRewards.TryGetValue(i, out List? effectList) && effectList != null) + { + skillRewards = new(effectList); + } + + WriteLine($"=== Round {i++} ==="); + WriteLine("鐜板湪鏄 [ " + characterToAct + "锛" + (actionQueue.GetTeam(characterToAct)?.Name ?? "") + "锛" + " ] 鐨勫洖鍚堬紒"); + + // 瀹為檯鐨勫洖鍚堝鍔 + List realSkillRewards = []; + if (skillRewards.Count > 0) + { + foreach (Skill skill in skillRewards) + { + Dictionary effectArgs = []; + if (FunGameService.RoundRewards.TryGetValue((EffectID)skill.Id, out Dictionary? dict) && dict != null) + { + effectArgs = new(dict); + } + Dictionary args = new() + { + { "skill", skill }, + { "values", effectArgs } + }; + skill.GamingQueue = actionQueue; + skill.Effects.Add(Factory.OpenFactory.GetInstance(skill.Id, "", args)); + skill.Character = characterToAct; + skill.Level = 1; + actionQueue.LastRound.RoundRewards.Add(skill); + WriteLine($"[ {characterToAct} ] 鑾峰緱浜嗗洖鍚堝鍔憋紒{skill.Description}".Trim()); + if (skill.IsActive) + { + actionQueue.LastRound.Targets.Add(characterToAct); + skill.OnSkillCasted(actionQueue, characterToAct, [characterToAct]); + } + else + { + characterToAct.Skills.Add(skill); + realSkillRewards.Add(skill); + } + } + } + + bool isGameEnd = actionQueue.ProcessTurn(characterToAct); + + if (realSkillRewards.Count > 0) + { + foreach (Skill skill in realSkillRewards) + { + foreach (Effect e in skill.Effects) + { + e.OnEffectLost(characterToAct); + characterToAct.Effects.Remove(e); + } + characterToAct.Skills.Remove(skill); + skill.Character = null; + } + } + + if (isGameEnd) + { + Result.Add(_msg); + break; + } + + if (showRoundEndDetail) actionQueue.DisplayQueue(); + WriteLine(""); + } + + string roundMsg = ""; + if (actionQueue.LastRound.HasKill || showAllRound) + { + roundMsg = _msg; + if (!deathMatchRoundDetail) + { + roundMsg = actionQueue.LastRound.ToString().Trim() + $"\r\n" + + (actionQueue.LastRound.HasKill ? $"姣斿垎锛歿string.Join(" / ", actionQueue.Teams.Values.Select(t => $"{t.Name}({t.Score})"))}" + + $"锛屽嚮鏉鏉ヨ嚜{actionQueue.GetTeam(actionQueue.LastRound.Actor)}\r\n" : ""); + if (showAllRound) + { + Character[] showHPMP = [actionQueue.LastRound.Actor, .. actionQueue.LastRound.Targets]; + foreach (Character character in showHPMP) + { + roundMsg += $"[ {character} ] 鐢熷懡鍊硷細{character.HP:0.##}/{character.MaxHP:0.##} / 榄旀硶鍊硷細{character.MP:0.##}/{character.MaxMP:0.##}\r\n"; + } + } + } + _msg = ""; + } + + // 妯℃嫙鏃堕棿娴侀 + double timeLapse = actionQueue.TimeLapse(); + totalTime += timeLapse; + + if (roundMsg != "") + { + if (deathMatchRoundDetail && isWeb) + { + roundMsg += "\r\n" + _msg; + } + Result.Add(roundMsg); + } + } + + if (PrintOut) + { + Console.WriteLine("--- End ---"); + Console.WriteLine($"鎬绘父鎴忔椂闀匡細{totalTime:0.##}"); + Console.WriteLine(""); + } + + // 璧涘悗缁熻 + FunGameService.GetCharacterRating(actionQueue.CharacterStatistics, true, actionQueue.EliminatedTeams); + + // 缁熻鎶鏈緱鍒嗭紝璇勯 MVP + StringBuilder mvpBuilder = new(); + Character? mvp = actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key).FirstOrDefault(); + if (mvp != null) + { + CharacterStatistics stats = actionQueue.CharacterStatistics[mvp]; + stats.MVPs++; + Team? team = actionQueue.GetTeamFromEliminated(mvp); + mvpBuilder.AppendLine($"=== 鏈満姣旇禌鏈浣宠鑹 ==="); + mvpBuilder.AppendLine($"{(team != null ? "[ " + team.Name + " ] " : "")}[ {mvp.ToStringWithLevel()} ]"); + mvpBuilder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.0#} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); + mvpBuilder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); + mvpBuilder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); + mvpBuilder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); + mvpBuilder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); + } + + // 璧涘悗鏁版嵁 + StringBuilder ratingBuilder = new(); + ratingBuilder.AppendLine($"=== 璧涘悗鏁版嵁 ==="); + foreach (Team team in teams) + { + ratingBuilder.AppendLine($"鈽--- [ {team} ] ---鈽"); + foreach (Character character in actionQueue.CharacterStatistics.Where(d => team.Members.Contains(d.Key)) + .OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) + { + CharacterStatistics stats = actionQueue.CharacterStatistics[character]; + ratingBuilder.AppendLine($"[ {stats.Rating:0.0#} ] {character}锛坽stats.Kills} / {stats.Assists} / {stats.Deaths}锛"); + if (character.User != null) + { + character.User.Inventory.Credits += stats.TotalEarnedMoney; + } + } + } + Result.Add(mvpBuilder.ToString() + "\r\n\r\n" + ratingBuilder.ToString()); + } + + return Result; + } + catch (Exception ex) + { + Console.WriteLine(ex); + return [ex.ToString()]; + } + } + + public void WriteLine(string str) + { + _msg += str + "\r\n"; if (PrintOut) Console.WriteLine(str); } - public static void 绌烘姇(ActionQueue queue, int mQuality, int wQuality, int aQuality, int sQuality, int acQuality) + public static List NewAndStartGame(List characters, bool printout = false, bool isWeb = false, bool deathMatchRoundDetail = false, bool showRoundEndDetail = false, bool showAllRound = false) { - foreach (Character character in queue.Queue) - { - Item[] 姝﹀櫒 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("11") && (int)i.QualityType == wQuality).ToArray(); - Item[] 闃插叿 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("12") && (int)i.QualityType == aQuality).ToArray(); - Item[] 闉嬪瓙 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("13") && (int)i.QualityType == sQuality).ToArray(); - Item[] 楗板搧 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("14") && (int)i.QualityType == acQuality).ToArray(); - Item? a = null, b = null, c = null, d = null; - if (姝﹀櫒.Length > 0) - { - a = 姝﹀櫒[Random.Shared.Next(姝﹀櫒.Length)]; - } - if (闃插叿.Length > 0) - { - b = 闃插叿[Random.Shared.Next(闃插叿.Length)]; - } - if (闉嬪瓙.Length > 0) - { - c = 闉嬪瓙[Random.Shared.Next(闉嬪瓙.Length)]; - } - if (楗板搧.Length > 0) - { - d = 楗板搧[Random.Shared.Next(楗板搧.Length)]; - } - List 杩欐鍙戞斁鐨勭┖鎶 = []; - if (a != null) 杩欐鍙戞斁鐨勭┖鎶.Add(a); - if (b != null) 杩欐鍙戞斁鐨勭┖鎶.Add(b); - if (c != null) 杩欐鍙戞斁鐨勭┖鎶.Add(c); - if (d != null) 杩欐鍙戞斁鐨勭┖鎶.Add(d); - Item? 榄旀硶鍗″寘 = FunGameService.GenerateMagicCardPack(3, (QualityType)mQuality); - if (榄旀硶鍗″寘 != null) - { - foreach (Skill magic in 榄旀硶鍗″寘.Skills.Magics) - { - magic.Level = 8; - } - 榄旀硶鍗″寘.SetGamingQueue(queue); - queue.Equip(character, 榄旀硶鍗″寘); - } - foreach (Item item in 杩欐鍙戞斁鐨勭┖鎶) - { - Item realItem = item.Copy(); - realItem.SetGamingQueue(queue); - queue.Equip(character, realItem); - } - } + return new FunGameActionQueue().StartGame(characters, printout, isWeb, deathMatchRoundDetail, showRoundEndDetail, showAllRound); } - public static Dictionary> RoundRewards + public static List NewAndStartTeamGame(List teams, int maxRespawnTimes = 0, int maxScoreToWin = 0, bool printout = false, bool isWeb = false, bool deathMatchRoundDetail = false, bool showRoundEndDetail = false, bool showAllRound = false) { - get - { - return new() - { - { - EffectID.ExATK, - new() - { - { "exatk", Random.Shared.Next(40, 80) } - } - }, - { - EffectID.ExCritRate, - new() - { - { "excr", Math.Clamp(Random.Shared.NextDouble(), 0.25, 0.5) } - } - }, - { - EffectID.ExCritDMG, - new() - { - { "excrd", Math.Clamp(Random.Shared.NextDouble(), 0.5, 1) } - } - }, - { - EffectID.ExATK2, - new() - { - { "exatk", Math.Clamp(Random.Shared.NextDouble(), 0.15, 0.3) } - } - }, - { - EffectID.RecoverHP, - new() - { - { "hp", Random.Shared.Next(160, 640) } - } - }, - { - EffectID.RecoverMP, - new() - { - { "mp", Random.Shared.Next(140, 490) } - } - }, - { - EffectID.RecoverHP2, - new() - { - { "hp", Math.Clamp(Random.Shared.NextDouble(), 0.04, 0.08) } - } - }, - { - EffectID.RecoverMP2, - new() - { - { "mp", Math.Clamp(Random.Shared.NextDouble(), 0.09, 0.18) } - } - }, - { - EffectID.GetEP, - new() - { - { "ep", Random.Shared.Next(20, 40) } - } - } - }; - } - } - - public static Dictionary> GenerateRoundRewards(int maxRound) - { - Dictionary> roundRewards = []; - - int currentRound = 1; - while (currentRound <= maxRound) - { - currentRound += Random.Shared.Next(1, 9); - - if (currentRound <= maxRound) - { - List skills = []; - - // 娣诲姞鍥炲悎濂栧姳鐗规晥 - long effectID = (long)RoundRewards.Keys.ToArray()[Random.Shared.Next(RoundRewards.Count)]; - Dictionary args = []; - if (effectID > (long)EffectID.Active_Start) - { - args.Add("active", true); - args.Add("self", true); - args.Add("enemy", false); - } - - skills.Add(Factory.OpenFactory.GetInstance(effectID, "鍥炲悎濂栧姳", args)); - - roundRewards[currentRound] = skills; - } - } - - return roundRewards; - } - - public static void UpdateStatistics(CharacterStatistics totalStats, CharacterStatistics stats) - { - // 缁熻姝よ鑹茬殑鎵鏈夋暟鎹 - totalStats.TotalDamage = Calculation.Round2Digits(totalStats.TotalDamage + stats.TotalDamage); - totalStats.TotalPhysicalDamage = Calculation.Round2Digits(totalStats.TotalPhysicalDamage + stats.TotalPhysicalDamage); - totalStats.TotalMagicDamage = Calculation.Round2Digits(totalStats.TotalMagicDamage + stats.TotalMagicDamage); - totalStats.TotalRealDamage = Calculation.Round2Digits(totalStats.TotalRealDamage + stats.TotalRealDamage); - totalStats.TotalTakenDamage = Calculation.Round2Digits(totalStats.TotalTakenDamage + stats.TotalTakenDamage); - totalStats.TotalTakenPhysicalDamage = Calculation.Round2Digits(totalStats.TotalTakenPhysicalDamage + stats.TotalTakenPhysicalDamage); - totalStats.TotalTakenMagicDamage = Calculation.Round2Digits(totalStats.TotalTakenMagicDamage + stats.TotalTakenMagicDamage); - totalStats.TotalTakenRealDamage = Calculation.Round2Digits(totalStats.TotalTakenRealDamage + stats.TotalTakenRealDamage); - totalStats.LiveRound += stats.LiveRound; - totalStats.ActionTurn += stats.ActionTurn; - totalStats.LiveTime = Calculation.Round2Digits(totalStats.LiveTime + stats.LiveTime); - totalStats.TotalEarnedMoney += stats.TotalEarnedMoney; - totalStats.Kills += stats.Kills; - totalStats.Deaths += stats.Deaths; - totalStats.Assists += stats.Assists; - totalStats.FirstKills += stats.FirstKills; - totalStats.FirstDeaths += stats.FirstDeaths; - totalStats.LastRank = stats.LastRank; - double totalRank = totalStats.AvgRank * totalStats.Plays + totalStats.LastRank; - double totalRating = totalStats.Rating * totalStats.Plays + stats.Rating; - totalStats.Plays += stats.Plays; - if (totalStats.Plays != 0) totalStats.AvgRank = Calculation.Round2Digits(totalRank / totalStats.Plays); - else totalStats.AvgRank = stats.LastRank; - if (totalStats.Plays != 0) totalStats.Rating = Calculation.Round4Digits(totalRating / totalStats.Plays); - else totalStats.Rating = stats.Rating; - totalStats.Wins += stats.Wins; - totalStats.Top3s += stats.Top3s; - totalStats.Loses += stats.Loses; - totalStats.MVPs += stats.MVPs; - if (totalStats.Plays != 0) - { - totalStats.AvgDamage = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.Plays); - totalStats.AvgPhysicalDamage = Calculation.Round2Digits(totalStats.TotalPhysicalDamage / totalStats.Plays); - totalStats.AvgMagicDamage = Calculation.Round2Digits(totalStats.TotalMagicDamage / totalStats.Plays); - totalStats.AvgRealDamage = Calculation.Round2Digits(totalStats.TotalRealDamage / totalStats.Plays); - totalStats.AvgTakenDamage = Calculation.Round2Digits(totalStats.TotalTakenDamage / totalStats.Plays); - totalStats.AvgTakenPhysicalDamage = Calculation.Round2Digits(totalStats.TotalTakenPhysicalDamage / totalStats.Plays); - totalStats.AvgTakenMagicDamage = Calculation.Round2Digits(totalStats.TotalTakenMagicDamage / totalStats.Plays); - totalStats.AvgTakenRealDamage = Calculation.Round2Digits(totalStats.TotalTakenRealDamage / totalStats.Plays); - totalStats.AvgLiveRound = totalStats.LiveRound / totalStats.Plays; - totalStats.AvgActionTurn = totalStats.ActionTurn / totalStats.Plays; - totalStats.AvgLiveTime = Calculation.Round2Digits(totalStats.LiveTime / totalStats.Plays); - totalStats.AvgEarnedMoney = totalStats.TotalEarnedMoney / totalStats.Plays; - totalStats.Winrates = Calculation.Round4Digits(Convert.ToDouble(totalStats.Wins) / Convert.ToDouble(totalStats.Plays)); - totalStats.Top3rates = Calculation.Round4Digits(Convert.ToDouble(totalStats.Top3s) / Convert.ToDouble(totalStats.Plays)); - } - if (totalStats.LiveRound != 0) totalStats.DamagePerRound = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.LiveRound); - if (totalStats.ActionTurn != 0) totalStats.DamagePerTurn = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.ActionTurn); - if (totalStats.LiveTime != 0) totalStats.DamagePerSecond = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.LiveTime); - } - - public static void GetCharacterRating(Dictionary statistics, bool isTeam, List teams) - { - foreach (Character character in statistics.Keys) - { - Team? team = null; - if (isTeam) - { - team = teams.Where(t => t.IsOnThisTeam(character)).FirstOrDefault(); - } - statistics[character].Rating = CalculateRating(statistics[character], team); - } - } - - public static double CalculateRating(CharacterStatistics stats, Team? team = null) - { - // 鍩虹寰楀垎 - double baseScore = (stats.Kills + stats.Assists) / (stats.Kills + stats.Assists + stats.Deaths + 0.01); - if (team is null) - { - baseScore += stats.Kills * 0.1; - if (stats.Deaths == 0) - { - baseScore += 0.5; - } - } - else - { - baseScore = baseScore * 0.6 + 0.4 * (stats.Kills / (stats.Kills + stats.Deaths + 0.01)); - } - - // 浼ゅ璐$尞 - double logDamageContribution = Math.Log(1 + (stats.TotalDamage / (stats.TotalTakenDamage + 1e-6))); - - // 瀛樻椿鏃堕棿璐$尞 - double liveTimeContribution = Math.Log(1 + (stats.LiveTime / (stats.TotalTakenDamage + 0.01) * 100)); - - // 鍥㈤槦妯″紡鍙傚洟鐜囧姞鎴 - double teamContribution = 0; - if (team != null) - { - teamContribution = (stats.Kills + stats.Assists) / (team.Score + 0.01); - if (team.IsWinner) - { - teamContribution += 0.15; - } - } - - // 鏉冮噸璁剧疆 - double k = stats.Deaths > 0 ? 0.2 : 0.075; // 浼ゅ璐$尞鏉冮噸 - double l = stats.Deaths > 0 ? 0.2 : 0.05; // 瀛樻椿鏃堕棿鏉冮噸 - double t = stats.Deaths > 0 ? 0.2 : 0.075; // 鍙傚洟鐜囨潈閲 - - // 璁$畻鏈缁堣瘎鍒 - double rating = baseScore + k * logDamageContribution + l * liveTimeContribution + t * teamContribution; - - // 纭繚璇勫垎鍦ㄥ悎鐞嗚寖鍥村唴 - return Math.Max(0.01, rating); + return new FunGameActionQueue().StartTeamGame(teams, maxRespawnTimes, maxScoreToWin, printout, isWeb, deathMatchRoundDetail, showRoundEndDetail, showAllRound); } } } diff --git a/OshimaCore/Utils/FunGameService.cs b/OshimaCore/Utils/FunGameService.cs index bc11612..57c952b 100644 --- a/OshimaCore/Utils/FunGameService.cs +++ b/OshimaCore/Utils/FunGameService.cs @@ -1,7 +1,6 @@ 锘縰sing System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Entity; -using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; using Oshima.FunGame.OshimaModules; using Oshima.FunGame.OshimaModules.Characters; @@ -1111,6 +1110,7 @@ namespace Oshima.Core.Utils Item? magicCardPack = GenerateMagicCardPack(5, (QualityType)4); if (magicCardPack != null) { + magicCardPack.QualityType = QualityType.Red; foreach (Skill magic in magicCardPack.Skills.Magics) { magic.Level = mLevel; @@ -1389,5 +1389,169 @@ namespace Oshima.Core.Utils }; } } + + public static Dictionary> RoundRewards + { + get + { + return new() + { + { + EffectID.ExATK, + new() + { + { "exatk", Random.Shared.Next(40, 80) } + } + }, + { + EffectID.ExCritRate, + new() + { + { "excr", Math.Clamp(Random.Shared.NextDouble(), 0.25, 0.5) } + } + }, + { + EffectID.ExCritDMG, + new() + { + { "excrd", Math.Clamp(Random.Shared.NextDouble(), 0.5, 1) } + } + }, + { + EffectID.ExATK2, + new() + { + { "exatk", Math.Clamp(Random.Shared.NextDouble(), 0.15, 0.3) } + } + }, + { + EffectID.RecoverHP, + new() + { + { "hp", Random.Shared.Next(160, 640) } + } + }, + { + EffectID.RecoverMP, + new() + { + { "mp", Random.Shared.Next(140, 490) } + } + }, + { + EffectID.RecoverHP2, + new() + { + { "hp", Math.Clamp(Random.Shared.NextDouble(), 0.04, 0.08) } + } + }, + { + EffectID.RecoverMP2, + new() + { + { "mp", Math.Clamp(Random.Shared.NextDouble(), 0.09, 0.18) } + } + }, + { + EffectID.GetEP, + new() + { + { "ep", Random.Shared.Next(20, 40) } + } + } + }; + } + } + + public static Dictionary> GenerateRoundRewards(int maxRound) + { + Dictionary> roundRewards = []; + + int currentRound = 1; + while (currentRound <= maxRound) + { + currentRound += Random.Shared.Next(1, 9); + + if (currentRound <= maxRound) + { + List skills = []; + + // 娣诲姞鍥炲悎濂栧姳鐗规晥 + long effectID = (long)RoundRewards.Keys.ToArray()[Random.Shared.Next(RoundRewards.Count)]; + Dictionary args = []; + if (effectID > (long)EffectID.Active_Start) + { + args.Add("active", true); + args.Add("self", true); + args.Add("enemy", false); + } + + skills.Add(Factory.OpenFactory.GetInstance(effectID, "鍥炲悎濂栧姳", args)); + + roundRewards[currentRound] = skills; + } + } + + return roundRewards; + } + + public static double CalculateRating(CharacterStatistics stats, Team? team = null) + { + // 鍩虹寰楀垎 + double baseScore = (stats.Kills + stats.Assists) / (stats.Kills + stats.Assists + stats.Deaths + 0.01); + if (team is null) + { + baseScore += stats.Kills * 0.1; + if (stats.Deaths == 0) + { + baseScore += 0.5; + } + } + else + { + baseScore = baseScore * 0.6 + 0.4 * (stats.Kills / (stats.Kills + stats.Deaths + 0.01)); + } + + // 浼ゅ璐$尞 + double logDamageContribution = Math.Log(1 + (stats.TotalDamage / (stats.TotalTakenDamage + 1e-6))); + + // 瀛樻椿鏃堕棿璐$尞 + double liveTimeContribution = Math.Log(1 + (stats.LiveTime / (stats.TotalTakenDamage + 0.01) * 100)); + + // 鍥㈤槦妯″紡鍙傚洟鐜囧姞鎴 + double teamContribution = 0; + if (team != null) + { + teamContribution = (stats.Kills + stats.Assists) / (team.Score + 0.01); + if (team.IsWinner) + { + teamContribution += 0.15; + } + } + + // 鏉冮噸璁剧疆 + double k = stats.Deaths > 0 ? 0.2 : 0.075; // 浼ゅ璐$尞鏉冮噸 + double l = stats.Deaths > 0 ? 0.2 : 0.05; // 瀛樻椿鏃堕棿鏉冮噸 + double t = stats.Deaths > 0 ? 0.2 : 0.075; // 鍙傚洟鐜囨潈閲 + + // 璁$畻鏈缁堣瘎鍒 + double rating = baseScore + k * logDamageContribution + l * liveTimeContribution + t * teamContribution; + + // 纭繚璇勫垎鍦ㄥ悎鐞嗚寖鍥村唴 + return Math.Max(0.01, rating); + } + + public static void GetCharacterRating(Dictionary statistics, bool isTeam, List teams) + { + foreach (Character character in statistics.Keys) + { + Team? team = null; + if (isTeam) + { + team = teams.Where(t => t.IsOnThisTeam(character)).FirstOrDefault(); + } + statistics[character].Rating = CalculateRating(statistics[character], team); + } + } } } diff --git a/OshimaCore/Utils/FunGameSimulation.cs b/OshimaCore/Utils/FunGameSimulation.cs new file mode 100644 index 0000000..812c850 --- /dev/null +++ b/OshimaCore/Utils/FunGameSimulation.cs @@ -0,0 +1,691 @@ +锘縰sing System.Text; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; +using Oshima.FunGame.OshimaModules.Effects.OpenEffects; + +namespace Oshima.Core.Utils +{ + public class FunGameSimulation + { + public static Dictionary CharacterStatistics { get; } = []; + public static Dictionary TeamCharacterStatistics { get; } = []; + public static PluginConfig StatsConfig { get; } = new("FunGameSimulation", nameof(CharacterStatistics)); + public static PluginConfig TeamStatsConfig { get; } = new("FunGameSimulation", nameof(TeamCharacterStatistics)); + public static bool IsRuning { get; set; } = false; + public static bool IsWeb { get; set; } = false; + public static bool PrintOut { get; set; } = false; + public static bool DeathMatchRoundDetail { get; set; } = false; + public static string Msg { get; set; } = ""; + + public static void InitFunGameSimulation() + { + CharacterStatistics.Clear(); + TeamCharacterStatistics.Clear(); + + foreach (Character c in FunGameService.Characters) + { + CharacterStatistics.Add(c, new()); + } + + StatsConfig.LoadConfig(); + foreach (Character character in CharacterStatistics.Keys) + { + if (StatsConfig.ContainsKey(character.ToStringWithOutUser())) + { + CharacterStatistics[character] = StatsConfig.Get(character.ToStringWithOutUser()) ?? CharacterStatistics[character]; + } + } + + foreach (Character c in FunGameService.Characters) + { + TeamCharacterStatistics.Add(c, new()); + } + + TeamStatsConfig.LoadConfig(); + foreach (Character character in TeamCharacterStatistics.Keys) + { + if (TeamStatsConfig.ContainsKey(character.ToStringWithOutUser())) + { + TeamCharacterStatistics[character] = TeamStatsConfig.Get(character.ToStringWithOutUser()) ?? TeamCharacterStatistics[character]; + } + } + } + + public static List StartSimulationGame(bool printout, bool isWeb = false, bool isTeam = false, bool deathMatchRoundDetail = false) + { + PrintOut = printout; + IsWeb = isWeb; + DeathMatchRoundDetail = deathMatchRoundDetail; + try + { + if (IsRuning) return ["娓告垙姝e湪妯℃嫙涓紝璇峰嬁閲嶅璇锋眰锛"]; + + List result = []; + Msg = ""; + + IsRuning = true; + + // M = 0, W = 7, P1 = 1, P3 = 1 + // M = 1, W = 6, P1 = 2, P3 = 0 + // M = 2, W = 4, P1 = 0, P3 = 2 + // M = 2, W = 5, P1 = 0, P3 = 0 + // M = 3, W = 3, P1 = 1, P3 = 1 + // M = 4, W = 2, P1 = 2, P3 = 0 + // M = 5, W = 0, P1 = 0, P3 = 2 + // M = 5, W = 1, P1 = 0, P3 = 0 + + List list = new(FunGameService.Characters); + + if (list.Count > 11) + { + if (PrintOut) Console.WriteLine(); + if (PrintOut) Console.WriteLine("Start!!!"); + if (PrintOut) Console.WriteLine(); + + Character character1 = list[0].Copy(); + Character character2 = list[1].Copy(); + Character character3 = list[2].Copy(); + Character character4 = list[3].Copy(); + Character character5 = list[4].Copy(); + Character character6 = list[5].Copy(); + Character character7 = list[6].Copy(); + Character character8 = list[7].Copy(); + Character character9 = list[8].Copy(); + Character character10 = list[9].Copy(); + Character character11 = list[10].Copy(); + Character character12 = list[11].Copy(); + + List characters = [ + character1, character2, character3, character4, + character5, character6, character7, character8, + character9, character10, character11, character12 + ]; + + int clevel = 60; + int slevel = 6; + int mlevel = 8; + + // 鍗囩骇鍜岃祴鑳 + for (int index = 0; index < characters.Count; index++) + { + Character c = characters[index]; + c.Level = clevel; + c.NormalAttack.Level = mlevel; + FunGameService.AddCharacterSkills(c, 1, slevel, slevel); + } + + // 鍒涘缓椤哄簭琛ㄥ苟鎺掑簭 + ActionQueue actionQueue = new(characters, isTeam, WriteLine); + if (isTeam) + { + actionQueue.MaxRespawnTimes = -1; + actionQueue.MaxScoreToWin = 30; + } + if (PrintOut) Console.WriteLine(); + + // 鎬绘父鎴忔椂闀 + double totalTime = 0; + + // 寮濮嬬┖鎶 + Msg = ""; + int 鍙戞斁鐨勫崱鍖呭搧璐 = 0; + int 鍙戞斁鐨勬鍣ㄥ搧璐 = 0; + int 鍙戞斁鐨勯槻鍏峰搧璐 = 0; + int 鍙戞斁鐨勯瀷瀛愬搧璐 = 0; + int 鍙戞斁鐨勯グ鍝佸搧璐 = 0; + WriteLine($"绀惧尯閫佹俯鏆栦簡锛岀幇鍦ㄩ殢鏈哄彂鏀剧┖鎶曪紒锛"); + 绌烘姇(actionQueue, 鍙戞斁鐨勫崱鍖呭搧璐, 鍙戞斁鐨勬鍣ㄥ搧璐, 鍙戞斁鐨勯槻鍏峰搧璐, 鍙戞斁鐨勯瀷瀛愬搧璐, 鍙戞斁鐨勯グ鍝佸搧璐); + WriteLine(""); + if (isWeb) result.Add("=== 绌烘姇 ===\r\n" + Msg); + double 涓嬩竴娆$┖鎶 = isTeam ? 80 : 40; + if (鍙戞斁鐨勫崱鍖呭搧璐 < 4) + { + 鍙戞斁鐨勫崱鍖呭搧璐++; + } + if (鍙戞斁鐨勬鍣ㄥ搧璐 < 4) + { + 鍙戞斁鐨勬鍣ㄥ搧璐++; + } + if (鍙戞斁鐨勯槻鍏峰搧璐 < 1) + { + 鍙戞斁鐨勯槻鍏峰搧璐++; + } + if (鍙戞斁鐨勯瀷瀛愬搧璐 < 1) + { + 鍙戞斁鐨勯瀷瀛愬搧璐++; + } + if (鍙戞斁鐨勯グ鍝佸搧璐 < 3) + { + 鍙戞斁鐨勯グ鍝佸搧璐++; + } + + // 鏄剧ず瑙掕壊淇℃伅 + if (PrintOut) characters.ForEach(c => Console.WriteLine(c.GetInfo())); + + // 鍥犺祴浜堜簡瑁呭锛屾墍浠ユ竻闄ゆ帓搴忛噸鏂版帓 + actionQueue.ClearQueue(); + actionQueue.InitCharacterQueue(characters); + if (PrintOut) Console.WriteLine(); + + // 鍥㈤槦妯″紡 + if (isTeam) + { + Msg = "=== 鍥㈤槦妯″紡闅忔満鍒嗙粍 ===\r\n\r\n"; + // 鎵撲贡瑙掕壊鍒楄〃 + List shuffledCharacters = [.. characters.OrderBy(c => Random.Shared.Next())]; + + // 鍒涘缓涓や釜鍥㈤槦 + List group1 = []; + List group2 = []; + + // 灏嗚鑹蹭氦鏇垮垎閰嶅埌涓や釜鍥㈤槦涓 + for (int cid = 0; cid < shuffledCharacters.Count; cid++) + { + if (cid % 2 == 0) + { + group1.Add(shuffledCharacters[cid]); + } + else + { + group2.Add(shuffledCharacters[cid]); + } + } + + // 娣诲姞鍒板洟闃熷瓧鍏 + actionQueue.AddTeam("闃熶紞涓", group1); + actionQueue.AddTeam("闃熶紞浜", group2); + + foreach (string team in actionQueue.Teams.Keys) + { + WriteLine($"鍥㈤槦銆恵team}銆戠殑鎴愬憳锛歕r\n{string.Join("\r\n", actionQueue.Teams[team].Members)}\r\n"); + } + result.Add(Msg); + } + + // 鏄剧ず鍒濆椤哄簭琛 + actionQueue.DisplayQueue(); + if (PrintOut) Console.WriteLine(); + + // 鎬诲洖鍚堟暟 + int maxRound = isTeam ? 9999 : 999; + + // 闅忔満鍥炲悎濂栧姳 + Dictionary> roundRewards = FunGameService.GenerateRoundRewards(maxRound); + + int i = 1; + while (i < maxRound) + { + Msg = ""; + if (i == maxRound - 1) + { + if (isTeam) + { + WriteLine("涓ら槦鎵撳埌澶╂槒鍦版殫锛屾祦灞浜嗭紒锛"); + break; + } + else + { + WriteLine($"=== 缁堝眬瀹″垽 ==="); + Dictionary 浠栦滑鐨勮閲忕櫨鍒嗘瘮 = []; + foreach (Character c in characters) + { + 浠栦滑鐨勮閲忕櫨鍒嗘瘮.TryAdd(c, c.HP / c.MaxHP); + } + double max = 浠栦滑鐨勮閲忕櫨鍒嗘瘮.Values.Max(); + Character winner = 浠栦滑鐨勮閲忕櫨鍒嗘瘮.Keys.Where(c => 浠栦滑鐨勮閲忕櫨鍒嗘瘮[c] == max).First(); + WriteLine("[ " + winner + " ] 鎴愪负浜嗗ぉ閫変箣浜猴紒锛"); + foreach (Character c in characters.Where(c => c != winner && c.HP > 0)) + { + WriteLine("[ " + winner + " ] 瀵 [ " + c + " ] 閫犳垚浜 99999999999 鐐圭湡瀹炰激瀹炽"); + actionQueue.DeathCalculation(winner, c); + } + actionQueue.EndGameInfo(winner); + result.Add(Msg); + break; + } + } + + // 妫鏌ユ槸鍚︽湁瑙掕壊鍙互琛屽姩 + Character? characterToAct = actionQueue.NextCharacter(); + + // 澶勭悊鍥炲悎 + if (characterToAct != null) + { + // 鑾峰彇鍥炲悎濂栧姳 + List skillRewards = []; + if (roundRewards.TryGetValue(i, out List? effectList) && effectList != null) + { + skillRewards = new(effectList); + } + + WriteLine($"=== Round {i++} ==="); + WriteLine("鐜板湪鏄 [ " + characterToAct + (isTeam ? "锛" + (actionQueue.GetTeam(characterToAct)?.Name ?? "") + "锛" : "") + " ] 鐨勫洖鍚堬紒"); + + // 瀹為檯鐨勫洖鍚堝鍔 + List realSkillRewards = []; + if (skillRewards.Count > 0) + { + foreach (Skill skill in skillRewards) + { + Dictionary effectArgs = []; + if (FunGameService.RoundRewards.TryGetValue((EffectID)skill.Id, out Dictionary? dict) && dict != null) + { + effectArgs = new(dict); + } + Dictionary args = new() + { + { "skill", skill }, + { "values", effectArgs } + }; + skill.GamingQueue = actionQueue; + skill.Effects.Add(Factory.OpenFactory.GetInstance(skill.Id, "", args)); + skill.Character = characterToAct; + skill.Level = 1; + actionQueue.LastRound.RoundRewards.Add(skill); + WriteLine($"[ {characterToAct} ] 鑾峰緱浜嗗洖鍚堝鍔憋紒{skill.Description}".Trim()); + if (skill.IsActive) + { + actionQueue.LastRound.Targets.Add(characterToAct); + skill.OnSkillCasted(actionQueue, characterToAct, [characterToAct]); + } + else + { + characterToAct.Skills.Add(skill); + realSkillRewards.Add(skill); + } + } + } + + bool isGameEnd = actionQueue.ProcessTurn(characterToAct); + + if (realSkillRewards.Count > 0) + { + foreach (Skill skill in realSkillRewards) + { + foreach (Effect e in skill.Effects) + { + e.OnEffectLost(characterToAct); + characterToAct.Effects.Remove(e); + } + characterToAct.Skills.Remove(skill); + skill.Character = null; + } + } + + if (isGameEnd) + { + result.Add(Msg); + break; + } + + actionQueue.DisplayQueue(); + WriteLine(""); + } + + string roundMsg = ""; + if (actionQueue.LastRound.HasKill) + { + roundMsg = Msg; + if (!deathMatchRoundDetail) + { + roundMsg = actionQueue.LastRound.ToString().Trim() + $"\r\n{(isTeam ? $"姣斿垎锛歿string.Join(" / ", actionQueue.Teams.Values.Select(t => $"{t.Name}({t.Score})"))}锛屽嚮鏉鏉ヨ嚜{actionQueue.GetTeam(actionQueue.LastRound.Actor)}" : "")}\r\n"; + } + Msg = ""; + } + + // 妯℃嫙鏃堕棿娴侀 + double timeLapse = actionQueue.TimeLapse(); + totalTime += timeLapse; + 涓嬩竴娆$┖鎶 -= timeLapse; + + if (roundMsg != "") + { + if ((isTeam && deathMatchRoundDetail || !isTeam) && isWeb) + { + roundMsg += "\r\n" + Msg; + } + result.Add(roundMsg); + } + + if (涓嬩竴娆$┖鎶 <= 0) + { + // 绌烘姇 + Msg = ""; + WriteLine($"绀惧尯閫佹俯鏆栦簡锛岀幇鍦ㄩ殢鏈哄彂鏀剧┖鎶曪紒锛"); + 绌烘姇(actionQueue, 鍙戞斁鐨勫崱鍖呭搧璐, 鍙戞斁鐨勬鍣ㄥ搧璐, 鍙戞斁鐨勯槻鍏峰搧璐, 鍙戞斁鐨勯瀷瀛愬搧璐, 鍙戞斁鐨勯グ鍝佸搧璐); + WriteLine(""); + if (isWeb) result.Add("=== 绌烘姇 ===\r\n" + Msg); + 涓嬩竴娆$┖鎶 = isTeam ? 100 : 40; + if (鍙戞斁鐨勫崱鍖呭搧璐 < 4) + { + 鍙戞斁鐨勫崱鍖呭搧璐++; + } + if (鍙戞斁鐨勬鍣ㄥ搧璐 < 4) + { + 鍙戞斁鐨勬鍣ㄥ搧璐++; + } + if (鍙戞斁鐨勯槻鍏峰搧璐 < 1) + { + 鍙戞斁鐨勯槻鍏峰搧璐++; + } + if (鍙戞斁鐨勯瀷瀛愬搧璐 < 1) + { + 鍙戞斁鐨勯瀷瀛愬搧璐++; + } + if (鍙戞斁鐨勯グ鍝佸搧璐 < 3) + { + 鍙戞斁鐨勯グ鍝佸搧璐++; + } + } + } + + if (PrintOut) + { + Console.WriteLine("--- End ---"); + Console.WriteLine($"鎬绘父鎴忔椂闀匡細{totalTime:0.##}"); + Console.WriteLine(""); + } + + // 璧涘悗缁熻 + FunGameService.GetCharacterRating(actionQueue.CharacterStatistics, isTeam, actionQueue.EliminatedTeams); + + // 缁熻鎶鏈緱鍒嗭紝璇勯 MVP + Character? mvp = actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key).FirstOrDefault(); + StringBuilder mvpBuilder = new(); + if (mvp != null) + { + CharacterStatistics stats = actionQueue.CharacterStatistics[mvp]; + stats.MVPs++; + mvpBuilder.AppendLine($"{(isTeam ? "[ " + actionQueue.GetTeamFromEliminated(mvp)?.Name + " ] " : "")}[ {mvp.ToStringWithLevel()} ]"); + mvpBuilder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.0#} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); + mvpBuilder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); + mvpBuilder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); + mvpBuilder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); + mvpBuilder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); + } + + int top = isWeb ? actionQueue.CharacterStatistics.Count : 0; // 鍥炴墽澶氬皯涓鑹茬殑缁熻淇℃伅 + int count = 1; + if (isWeb) + { + WriteLine("=== 鎶鏈緱鍒嗘帓琛屾 ==="); // 杩欐槸杈撳嚭鍦ㄧ晫闈笂鐨 + Msg = $"=== 鎶鏈緱鍒嗘帓琛屾 TOP{top} ===\r\n"; // 杩欎釜鏄笅涓鏉$粰Result鍥炴墽鐨勬爣棰橈紝瑕嗙洊鎺変笂闈㈡柟娉曢噷鐨勮祴鍊间簡 + } + else + { + StringBuilder ratingBuilder = new(); + if (isTeam) + { + ratingBuilder.AppendLine($"=== 璧涘悗鏁版嵁 ==="); + foreach (Team team in actionQueue.EliminatedTeams) + { + ratingBuilder.AppendLine($"鈽--- [ {team} ] ---鈽"); + foreach (Character character in actionQueue.CharacterStatistics.Where(d => team.Members.Contains(d.Key)) + .OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) + { + CharacterStatistics stats = actionQueue.CharacterStatistics[character]; + ratingBuilder.AppendLine($"[ {stats.Rating:0.0#} ] {character}锛坽stats.Kills} / {stats.Assists} / {stats.Deaths}锛"); + } + } + } + WriteLine("=== 鏈満姣旇禌鏈浣宠鑹 ==="); + Msg = $"=== 鏈満姣旇禌鏈浣宠鑹 ===\r\n"; + WriteLine(mvpBuilder.ToString() + "\r\n\r\n" + ratingBuilder.ToString()); + + if (PrintOut) + { + Console.WriteLine(); + Console.WriteLine("=== 鎶鏈緱鍒嗘帓琛屾 ==="); + } + } + + if (isTeam) + { + foreach (Character character in actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) + { + StringBuilder builder = new(); + CharacterStatistics stats = actionQueue.CharacterStatistics[character]; + builder.AppendLine($"{(isWeb ? count + "." : ("[ " + actionQueue.GetTeamFromEliminated(character)?.Name + " ]" ?? ""))} [ {character.ToStringWithLevel()} ]"); + builder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.0#} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); + builder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); + builder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); + builder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); + builder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); + if (count++ <= top) + { + WriteLine(builder.ToString()); + } + else + { + if (PrintOut) Console.WriteLine(builder.ToString()); + } + + CharacterStatistics? totalStats = TeamCharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); + if (totalStats != null) + { + UpdateStatistics(totalStats, stats); + } + } + } + else + { + foreach (Character character in actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key)) + { + StringBuilder builder = new(); + CharacterStatistics stats = actionQueue.CharacterStatistics[character]; + builder.AppendLine($"{(isWeb ? count + ". " : "")}[ {character.ToStringWithLevel()} ]"); + builder.AppendLine($"鎶鏈緱鍒嗭細{stats.Rating:0.0#} / 鍑绘潃鏁帮細{stats.Kills} / 鍔╂敾鏁帮細{stats.Assists}{(actionQueue.MaxRespawnTimes != 0 ? " / 姝讳骸鏁帮細" + stats.Deaths : "")}"); + builder.AppendLine($"瀛樻椿鏃堕暱锛歿stats.LiveTime} / 瀛樻椿鍥炲悎鏁帮細{stats.LiveRound} / 琛屽姩鍥炲悎鏁帮細{stats.ActionTurn}"); + builder.AppendLine($"鎬昏浼ゅ锛歿stats.TotalDamage} / 鎬昏鐗╃悊浼ゅ锛歿stats.TotalPhysicalDamage} / 鎬昏榄旀硶浼ゅ锛歿stats.TotalMagicDamage}"); + builder.AppendLine($"鎬绘壙鍙椾激瀹筹細{stats.TotalTakenDamage} / 鎬绘壙鍙楃墿鐞嗕激瀹筹細{stats.TotalTakenPhysicalDamage} / 鎬绘壙鍙楅瓟娉曚激瀹筹細{stats.TotalTakenMagicDamage}"); + builder.Append($"姣忕浼ゅ锛歿stats.DamagePerSecond} / 姣忓洖鍚堜激瀹筹細{stats.DamagePerTurn}"); + if (count++ <= top) + { + WriteLine(builder.ToString()); + } + else + { + if (PrintOut) Console.WriteLine(builder.ToString()); + } + + CharacterStatistics? totalStats = CharacterStatistics.Where(kv => kv.Key.GetName() == character.GetName()).Select(kv => kv.Value).FirstOrDefault(); + if (totalStats != null) + { + UpdateStatistics(totalStats, stats); + } + } + } + + result.Add(Msg); + + // 鏄剧ず姣忎釜瑙掕壊鐨勪俊鎭 + if (isWeb) + { + if (isTeam) + { + top = 1; + for (i = actionQueue.EliminatedTeams.Count - 1; i >= 0; i--) + { + Team team = actionQueue.EliminatedTeams[i]; + string topTeam = ""; + if (top == 1) + { + topTeam = "鍐犲啗"; + } + if (top == 2) + { + topTeam = "浜氬啗"; + } + if (top == 3) + { + topTeam = "瀛e啗"; + } + if (top > 3) + { + topTeam = $"绗 {top} 鍚"; + } + foreach (Character character in team.Members) + { + result.Add($"== {topTeam}鍥㈤槦 [ {team.Name} ] ==\r\n== 瑙掕壊锛歔 {character} ] ==\r\n{character.GetInfo()}"); + } + top++; + } + } + else + { + for (i = actionQueue.Eliminated.Count - 1; i >= 0; i--) + { + Character character = actionQueue.Eliminated[i]; + result.Add($"=== 瑙掕壊 [ {character} ] ===\r\n{character.GetInfo()}"); + } + } + } + + if (isTeam) + { + lock (TeamStatsConfig) + { + 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(); + } + } + + IsRuning = false; + } + + return result; + } + catch (Exception ex) + { + IsRuning = false; + Console.WriteLine(ex); + return [ex.ToString()]; + } + } + + public static void WriteLine(string str) + { + Msg += str + "\r\n"; + if (PrintOut) Console.WriteLine(str); + } + + public static void 绌烘姇(ActionQueue queue, int mQuality, int wQuality, int aQuality, int sQuality, int acQuality) + { + foreach (Character character in queue.Queue) + { + Item[] 姝﹀櫒 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("11") && (int)i.QualityType == wQuality).ToArray(); + Item[] 闃插叿 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("12") && (int)i.QualityType == aQuality).ToArray(); + Item[] 闉嬪瓙 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("13") && (int)i.QualityType == sQuality).ToArray(); + Item[] 楗板搧 = FunGameService.Equipment.Where(i => i.Id.ToString().StartsWith("14") && (int)i.QualityType == acQuality).ToArray(); + Item? a = null, b = null, c = null, d = null; + if (姝﹀櫒.Length > 0) + { + a = 姝﹀櫒[Random.Shared.Next(姝﹀櫒.Length)]; + } + if (闃插叿.Length > 0) + { + b = 闃插叿[Random.Shared.Next(闃插叿.Length)]; + } + if (闉嬪瓙.Length > 0) + { + c = 闉嬪瓙[Random.Shared.Next(闉嬪瓙.Length)]; + } + if (楗板搧.Length > 0) + { + d = 楗板搧[Random.Shared.Next(楗板搧.Length)]; + } + List 杩欐鍙戞斁鐨勭┖鎶 = []; + if (a != null) 杩欐鍙戞斁鐨勭┖鎶.Add(a); + if (b != null) 杩欐鍙戞斁鐨勭┖鎶.Add(b); + if (c != null) 杩欐鍙戞斁鐨勭┖鎶.Add(c); + if (d != null) 杩欐鍙戞斁鐨勭┖鎶.Add(d); + Item? 榄旀硶鍗″寘 = FunGameService.GenerateMagicCardPack(3, (QualityType)mQuality); + if (榄旀硶鍗″寘 != null) + { + foreach (Skill magic in 榄旀硶鍗″寘.Skills.Magics) + { + magic.Level = 8; + } + 榄旀硶鍗″寘.SetGamingQueue(queue); + queue.Equip(character, 榄旀硶鍗″寘); + } + foreach (Item item in 杩欐鍙戞斁鐨勭┖鎶) + { + Item realItem = item.Copy(); + realItem.SetGamingQueue(queue); + queue.Equip(character, realItem); + } + } + } + + public static void UpdateStatistics(CharacterStatistics totalStats, CharacterStatistics stats) + { + // 缁熻姝よ鑹茬殑鎵鏈夋暟鎹 + totalStats.TotalDamage = Calculation.Round2Digits(totalStats.TotalDamage + stats.TotalDamage); + totalStats.TotalPhysicalDamage = Calculation.Round2Digits(totalStats.TotalPhysicalDamage + stats.TotalPhysicalDamage); + totalStats.TotalMagicDamage = Calculation.Round2Digits(totalStats.TotalMagicDamage + stats.TotalMagicDamage); + totalStats.TotalRealDamage = Calculation.Round2Digits(totalStats.TotalRealDamage + stats.TotalRealDamage); + totalStats.TotalTakenDamage = Calculation.Round2Digits(totalStats.TotalTakenDamage + stats.TotalTakenDamage); + totalStats.TotalTakenPhysicalDamage = Calculation.Round2Digits(totalStats.TotalTakenPhysicalDamage + stats.TotalTakenPhysicalDamage); + totalStats.TotalTakenMagicDamage = Calculation.Round2Digits(totalStats.TotalTakenMagicDamage + stats.TotalTakenMagicDamage); + totalStats.TotalTakenRealDamage = Calculation.Round2Digits(totalStats.TotalTakenRealDamage + stats.TotalTakenRealDamage); + totalStats.LiveRound += stats.LiveRound; + totalStats.ActionTurn += stats.ActionTurn; + totalStats.LiveTime = Calculation.Round2Digits(totalStats.LiveTime + stats.LiveTime); + totalStats.TotalEarnedMoney += stats.TotalEarnedMoney; + totalStats.Kills += stats.Kills; + totalStats.Deaths += stats.Deaths; + totalStats.Assists += stats.Assists; + totalStats.FirstKills += stats.FirstKills; + totalStats.FirstDeaths += stats.FirstDeaths; + totalStats.LastRank = stats.LastRank; + double totalRank = totalStats.AvgRank * totalStats.Plays + totalStats.LastRank; + double totalRating = totalStats.Rating * totalStats.Plays + stats.Rating; + totalStats.Plays += stats.Plays; + if (totalStats.Plays != 0) totalStats.AvgRank = Calculation.Round2Digits(totalRank / totalStats.Plays); + else totalStats.AvgRank = stats.LastRank; + if (totalStats.Plays != 0) totalStats.Rating = Calculation.Round4Digits(totalRating / totalStats.Plays); + else totalStats.Rating = stats.Rating; + totalStats.Wins += stats.Wins; + totalStats.Top3s += stats.Top3s; + totalStats.Loses += stats.Loses; + totalStats.MVPs += stats.MVPs; + if (totalStats.Plays != 0) + { + totalStats.AvgDamage = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.Plays); + totalStats.AvgPhysicalDamage = Calculation.Round2Digits(totalStats.TotalPhysicalDamage / totalStats.Plays); + totalStats.AvgMagicDamage = Calculation.Round2Digits(totalStats.TotalMagicDamage / totalStats.Plays); + totalStats.AvgRealDamage = Calculation.Round2Digits(totalStats.TotalRealDamage / totalStats.Plays); + totalStats.AvgTakenDamage = Calculation.Round2Digits(totalStats.TotalTakenDamage / totalStats.Plays); + totalStats.AvgTakenPhysicalDamage = Calculation.Round2Digits(totalStats.TotalTakenPhysicalDamage / totalStats.Plays); + totalStats.AvgTakenMagicDamage = Calculation.Round2Digits(totalStats.TotalTakenMagicDamage / totalStats.Plays); + totalStats.AvgTakenRealDamage = Calculation.Round2Digits(totalStats.TotalTakenRealDamage / totalStats.Plays); + totalStats.AvgLiveRound = totalStats.LiveRound / totalStats.Plays; + totalStats.AvgActionTurn = totalStats.ActionTurn / totalStats.Plays; + totalStats.AvgLiveTime = Calculation.Round2Digits(totalStats.LiveTime / totalStats.Plays); + totalStats.AvgEarnedMoney = totalStats.TotalEarnedMoney / totalStats.Plays; + totalStats.Winrates = Calculation.Round4Digits(Convert.ToDouble(totalStats.Wins) / Convert.ToDouble(totalStats.Plays)); + totalStats.Top3rates = Calculation.Round4Digits(Convert.ToDouble(totalStats.Top3s) / Convert.ToDouble(totalStats.Plays)); + } + if (totalStats.LiveRound != 0) totalStats.DamagePerRound = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.LiveRound); + if (totalStats.ActionTurn != 0) totalStats.DamagePerTurn = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.ActionTurn); + if (totalStats.LiveTime != 0) totalStats.DamagePerSecond = Calculation.Round2Digits(totalStats.TotalDamage / totalStats.LiveTime); + } + } +} diff --git a/OshimaModules/Skills/MagicalGirl/姣佺伃涔嬪娍.cs b/OshimaModules/Skills/MagicalGirl/姣佺伃涔嬪娍.cs index 733bc1d..c43017b 100644 --- a/OshimaModules/Skills/MagicalGirl/姣佺伃涔嬪娍.cs +++ b/OshimaModules/Skills/MagicalGirl/姣佺伃涔嬪娍.cs @@ -50,8 +50,11 @@ namespace Oshima.FunGame.OshimaModules.Skills public override void OnTimeElapsed(Character character, double eapsed) { - 绱浼ゅ += 浼ゅ鎻愬崌 * eapsed; - WriteLine($"[ {character} ] 鐨 [ {Name} ] 鏁堟灉澧炲姞浜嗭紝褰撳墠鎬绘彁鍗囷細{绱浼ゅ * 100:0.##}%銆"); + if (GamingQueue != null) + { + 绱浼ゅ += 浼ゅ鎻愬崌 * eapsed; + WriteLine($"[ {character} ] 鐨 [ {Name} ] 鏁堟灉澧炲姞浜嗭紝褰撳墠鎬绘彁鍗囷細{绱浼ゅ * 100:0.##}%銆"); + } } } }