1359 lines
60 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using 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;
using Oshima.FunGame.OshimaModules.Characters;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Items;
using Oshima.FunGame.OshimaModules.Skills;
namespace Oshima.Core.Utils
{
public class FunGameSimulation
{
public static List<Character> Characters { get; } = [];
public static List<Skill> Skills { get; } = [];
public static List<Skill> Magics { get; } = [];
public static List<Item> Equipment { get; } = [];
public static List<Item> Items { get; } = [];
public static Dictionary<Character, CharacterStatistics> CharacterStatistics { get; } = [];
public static Dictionary<Character, CharacterStatistics> TeamCharacterStatistics { get; } = [];
public static PluginConfig StatsConfig { get; } = new(nameof(FunGameSimulation), nameof(CharacterStatistics));
public static PluginConfig TeamStatsConfig { get; } = new(nameof(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 InitFunGame()
{
Characters.Add(new OshimaShiya());
Characters.Add(new XinYin());
Characters.Add(new Yang());
Characters.Add(new NanGanYu());
Characters.Add(new NiuNan());
Characters.Add(new DokyoMayor());
Characters.Add(new MagicalGirl());
Characters.Add(new QingXiang());
Characters.Add(new QWQAQW());
Characters.Add(new ColdBlue());
Characters.Add(new dddovo());
Characters.Add(new Quduoduo());
foreach (Character c in Characters)
{
CharacterStatistics.Add(c, new());
}
StatsConfig.LoadConfig();
foreach (Character character in CharacterStatistics.Keys)
{
if (StatsConfig.ContainsKey(character.ToStringWithOutUser()))
{
CharacterStatistics[character] = StatsConfig.Get<CharacterStatistics>(character.ToStringWithOutUser()) ?? CharacterStatistics[character];
}
}
foreach (Character c in Characters)
{
TeamCharacterStatistics.Add(c, new());
}
TeamStatsConfig.LoadConfig();
foreach (Character character in TeamCharacterStatistics.Keys)
{
if (TeamStatsConfig.ContainsKey(character.ToStringWithOutUser()))
{
TeamCharacterStatistics[character] = TeamStatsConfig.Get<CharacterStatistics>(character.ToStringWithOutUser()) ?? TeamCharacterStatistics[character];
}
}
Dictionary<string, Item> exItems = Factory.GetGameModuleInstances<Item>(OshimaGameModuleConstant.General, OshimaGameModuleConstant.Item);
Equipment.AddRange(exItems.Values.Where(i => (int)i.ItemType >= 0 && (int)i.ItemType < 5));
Equipment.AddRange([new 10(), new 30(), new 50()]);
Items.AddRange(exItems.Values.Where(i => (int)i.ItemType > 4));
Skills.AddRange([new ()]);
Magics.AddRange([new (), new (), new (), new (), new (), new (), new (), new (), new (), new ()]);
}
public static List<string> StartGame(bool printout, bool isWeb = false, bool isTeam = false, bool deathMatchRoundDetail = false)
{
PrintOut = printout;
IsWeb = isWeb;
DeathMatchRoundDetail = deathMatchRoundDetail;
try
{
if (IsRuning) return ["游戏正在模拟中,请勿重复请求!"];
List<string> 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<Character> list = new(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<Character> 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;
//IEnumerable<Skill> magics = Magics.OrderBy(x => Random.Shared.Next()).Take(3);
//foreach (Skill magic in magics)
//{
// Skill m = magic.Copy();
// m.Character = c;
// m.Level = mlevel;
// c.Skills.Add(m);
//}
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
if (c == character1)
{
Skill META马 = new META马(c)
{
Level = 1
};
c.Skills.Add(META马);
Skill = new (c)
{
Level = mlevel
};
c.Skills.Add();
}
if (c == character2)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character3)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character4)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character5)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character6)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character7)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character8)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character9)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character10)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character11)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
if (c == character12)
{
Skill = new (c)
{
Level = 1
};
c.Skills.Add();
Skill = new (c)
{
Level = slevel
};
c.Skills.Add();
}
}
// 创建顺序表并排序
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;
(actionQueue, , , , , );
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<Character> shuffledCharacters = [.. characters.OrderBy(c => Random.Shared.Next())];
// 创建两个团队
List<Character> group1 = [];
List<Character> 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<int, List<Skill>> roundRewards = GenerateRoundRewards(maxRound);
int i = 1;
while (i < maxRound)
{
Msg = "";
if (i == maxRound - 1)
{
if (isTeam)
{
WriteLine("两队打到天昏地暗,流局了!!");
break;
}
else
{
WriteLine($"=== 终局审判 ===");
Dictionary<Character, double> = [];
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<Skill> skillRewards = [];
if (roundRewards.TryGetValue(i, out List<Skill>? effectList) && effectList != null)
{
skillRewards = new(effectList);
}
WriteLine($"=== Round {i++} ===");
WriteLine("现在是 [ " + characterToAct + (isTeam ? "" + (actionQueue.GetTeam(characterToAct)?.Name ?? "") + "" : "") + " ] 的回合!");
// 实际的回合奖励
List<Skill> realSkillRewards = [];
if (skillRewards.Count > 0)
{
foreach (Skill skill in skillRewards)
{
Dictionary<string, object> effectArgs = [];
if (RoundRewards.TryGetValue((EffectID)skill.Id, out Dictionary<string, object>? dict) && dict != null)
{
effectArgs = new(dict);
}
Dictionary<string, object> args = new()
{
{ "skill", skill },
{ "values", effectArgs }
};
skill.GamingQueue = actionQueue;
skill.Effects.Add(Factory.OpenFactory.GetInstance<Effect>(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();
}
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 = "";
(actionQueue, , , , , );
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);
int top = isWeb ? actionQueue.CharacterStatistics.Count : 0; // 回执多少个角色的统计信息
int count = 1;
if (isWeb)
{
WriteLine("=== 技术得分排行榜 ==="); // 这是输出在界面上的
Msg = $"=== 技术得分排行榜 TOP{top} ===\r\n"; // 这个是下一条给Result回执的标题覆盖掉上面方法里的赋值了
}
else
{
WriteLine("=== 本场比赛最佳角色 ===");
Msg = $"=== 本场比赛最佳角色 ===\r\n";
// 统计技术得分
Character? character = actionQueue.CharacterStatistics.OrderByDescending(d => d.Value.Rating).Select(d => d.Key).FirstOrDefault();
if (character != null)
{
CharacterStatistics stats = actionQueue.CharacterStatistics[character];
stats.MVPs++;
StringBuilder builder = new();
builder.AppendLine($"{(isWeb ? count + "." : (isTeam ? "[ " + 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}");
WriteLine(builder.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 = "季军";
}
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)
{
WriteLine($"社区送温暖了,现在随机发放空投!!");
foreach (Character character in queue.Queue)
{
Item[] = Equipment.Where(i => i.Id.ToString().StartsWith("11") && (int)i.QualityType == wQuality).ToArray();
Item[] = Equipment.Where(i => i.Id.ToString().StartsWith("12") && (int)i.QualityType == aQuality).ToArray();
Item[] = Equipment.Where(i => i.Id.ToString().StartsWith("13") && (int)i.QualityType == sQuality).ToArray();
Item[] = 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<Item> = [];
if (a != null) .Add(a);
if (b != null) .Add(b);
if (c != null) .Add(c);
if (d != null) .Add(d);
Item? = 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);
}
}
WriteLine("");
}
public static List<Item> GenerateMagicCards(int count, QualityType? qualityType = null)
{
List<Item> items = [];
for (int i = 0; i < count; i++)
{
items.Add(GenerateMagicCard(qualityType));
}
return items;
}
public static Item GenerateMagicCard(QualityType? qualityType = null)
{
Item item = Factory.GetItem();
item.Id = Convert.ToInt64("16" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 8));
item.Name = GenerateRandomChineseName();
item.ItemType = ItemType.MagicCard;
item.BackgroundStory = "这是一张随机生成的魔法卡。";
int total;
if (qualityType != null)
{
total = qualityType switch
{
QualityType.Green => Random.Shared.Next(7, 13),
QualityType.Blue => Random.Shared.Next(13, 19),
QualityType.Purple => Random.Shared.Next(19, 25),
QualityType.Orange => Random.Shared.Next(25, 31),
_ => Random.Shared.Next(1, 7)
};
item.QualityType = (QualityType)qualityType;
}
else
{
total = Random.Shared.Next(1, 31);
if (total > 6 && total <= 12)
{
item.QualityType = QualityType.Green;
}
else if (total > 12 && total <= 18)
{
item.QualityType = QualityType.Blue;
}
else if (total > 18 && total <= 24)
{
item.QualityType = QualityType.Purple;
}
else if (total > 24 && total <= 30)
{
item.QualityType = QualityType.Orange;
}
}
GenerateAndAddSkillToMagicCard(item, total);
return item;
}
public static void GenerateAndAddSkillToMagicCard(Item item, int total)
{
Skill magic = Magics[Random.Shared.Next(Magics.Count)].Copy();
magic.Level = (int)item.QualityType switch
{
2 => 2,
4 => 3,
6 => 4,
_ => 1
};
item.Skills.Active = magic;
// 初始化属性值
int str = 0, agi = 0, intelligence = 0;
// 随机决定将多少个属性赋给其中一个属性,确保至少一个不为零
int nonZeroAttributes = Random.Shared.Next(1, Math.Min(4, total + 1)); // 随机决定非零属性的数量,确保在 total = 1 时最多只有1个非零属性
// 根据非零属性数量分配属性点
if (nonZeroAttributes == 1)
{
// 只有一个属性不为零
int attribute = Random.Shared.Next(0, 3);
if (attribute == 0) str = total;
else if (attribute == 1) agi = total;
else intelligence = total;
}
else if (nonZeroAttributes == 2 && total >= 2)
{
// 两个属性不为零
int first = Random.Shared.Next(1, total); // 第一个属性的值
int second = total - first; // 第二个属性的值
int attribute = Random.Shared.Next(0, 3);
if (attribute == 0)
{
str = first;
}
else if (attribute == 1)
{
agi = first;
}
else
{
intelligence = first;
}
attribute = Random.Shared.Next(0, 3);
while ((attribute == 0 && str > 0) || (attribute == 1 && agi > 0) || (attribute == 2 && intelligence > 0))
{
attribute = Random.Shared.Next(0, 3);
}
if (attribute == 0)
{
str = second;
}
else if (attribute == 1)
{
agi = second;
}
else
{
intelligence = second;
}
}
else if (total >= 3)
{
// 三个属性都不为零
str = Random.Shared.Next(1, total - 1); // 第一个属性的值
agi = Random.Shared.Next(1, total - str); // 第二个属性的值
intelligence = total - str - agi; // 剩下的值给第三个属性
}
Skill skill = Factory.OpenFactory.GetInstance<Skill>(item.Id, item.Name, []);
GenerateAndAddEffectsToMagicCard(skill, str, agi, intelligence);
if (magic.Level > 1) item.Name += $" +{magic.Level - 1}";
skill.Level = 1;
item.Skills.Passives.Add(skill);
}
public static void GenerateAndAddEffectsToMagicCard(Skill skill, int str, int agi, int intelligence)
{
if (str > 0)
{
skill.Effects.Add(Factory.OpenFactory.GetInstance<Effect>((long)EffectID.ExSTR, "", new()
{
{ "skill", skill },
{
"values", new Dictionary<string, object>()
{
{ "exstr", str }
}
}
}));
}
if (agi > 0)
{
skill.Effects.Add(Factory.OpenFactory.GetInstance<Effect>((long)EffectID.ExAGI, "", new()
{
{ "skill", skill },
{
"values", new Dictionary<string, object>()
{
{ "exagi", agi }
}
}
}));
}
if (intelligence > 0)
{
skill.Effects.Add(Factory.OpenFactory.GetInstance<Effect>((long)EffectID.ExINT, "", new()
{
{ "skill", skill },
{
"values", new Dictionary<string, object>()
{
{ "exint", intelligence }
}
}
}));
}
}
public static Item? ConflateMagicCardPack(IEnumerable<Item> magicCards)
{
if (magicCards.Any())
{
List<Skill> magics = [.. magicCards.Where(i => i.Skills.Active != null).Select(i => i.Skills.Active)];
List<Skill> passives = [.. magicCards.SelectMany(i => i.Skills.Passives)];
Item item = Factory.GetItem();
item.Id = Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 8));
item.Name = GenerateRandomChineseName();
item.ItemType = ItemType.MagicCardPack;
item.BackgroundStory = "这是一个由三张魔法卡合成而来的魔法卡包。";
double str = 0, agi = 0, intelligence = 0;
foreach (Skill skill in passives)
{
Skill newSkill = skill.Copy();
foreach (Effect effect in newSkill.Effects)
{
switch ((EffectID)effect.Id)
{
case EffectID.ExSTR:
if (effect is ExSTR exstr)
{
str += exstr.Value;
}
break;
case EffectID.ExAGI:
if (effect is ExAGI exagi)
{
agi += exagi.Value;
}
break;
case EffectID.ExINT:
if (effect is ExINT exint)
{
intelligence += exint.Value;
}
break;
}
}
newSkill.Level = skill.Level;
item.Skills.Passives.Add(newSkill);
}
List<string> strings = [];
if (str > 0) strings.Add($"{str:0.##} 点力量");
if (agi > 0) strings.Add($"{agi:0.##} 点敏捷");
if (intelligence > 0) strings.Add($"{intelligence:0.##} 点智力");
foreach (Skill skill in magics)
{
Skill magic = skill.Copy();
magic.Level = skill.Level;
item.Skills.Magics.Add(magic);
}
item.Description = $"包含魔法:{string.Join("", item.Skills.Magics.Select(m => m.Name + $" +{m.Level - 1}"))}\r\n" +
$"增加角色属性:{string.Join("", strings)}";
double total = str + agi + intelligence;
if (total > 18 && total <= 36)
{
item.QualityType = QualityType.Green;
}
else if (total > 36 && total <= 54)
{
item.QualityType = QualityType.Blue;
}
else if (total > 54 && total <= 72)
{
item.QualityType = QualityType.Purple;
}
else if (total > 72 && total <= 90)
{
item.QualityType = QualityType.Orange;
}
return item;
}
return null;
}
public static Item? GenerateMagicCardPack(int magicCardCount, QualityType? qualityType = null)
{
List<Item> magicCards = GenerateMagicCards(magicCardCount, qualityType);
Item? magicCardPack = ConflateMagicCardPack(magicCards);
return magicCardPack;
}
public static void Reload()
{
Characters.Clear();
CharacterStatistics.Clear();
TeamCharacterStatistics.Clear();
Equipment.Clear();
Skills.Clear();
Magics.Clear();
InitFunGame();
}
public static Dictionary<EffectID, Dictionary<string, object>> 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) }
}
}
};
}
}
public static Dictionary<int, List<Skill>> GenerateRoundRewards(int maxRound)
{
Dictionary<int, List<Skill>> roundRewards = [];
int currentRound = 1;
while (currentRound <= maxRound)
{
currentRound += Random.Shared.Next(1, 9);
if (currentRound <= maxRound)
{
List<Skill> skills = [];
// 添加回合奖励特效
long effectID = (long)RoundRewards.Keys.ToArray()[Random.Shared.Next(RoundRewards.Count)];
Dictionary<string, object> args = [];
if (effectID > (long)EffectID.Active_Start)
{
args.Add("active", true);
args.Add("self", true);
args.Add("enemy", false);
}
skills.Add(Factory.OpenFactory.GetInstance<Skill>(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<Character, CharacterStatistics> statistics, bool isTeam, List<Team> 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);
}
public static string GenerateRandomChineseName()
{
// 定义一个包含常用汉字的字符串
string commonChineseCharacters = "云星宝灵梦龙花雨风叶山川月石羽水竹金" +
"玉海火雷光天地云凤虎虹珠华霞鹏雪银沙松桃兰竹青霜鸿康龙骏波泉河湖江泽" +
"洋林枫梅桂樱桐竹晴韵凌兰若悠碧涛渊风雷壁石剑影霖玄承珍雅耀星瑞龙鹤烟" +
"影凤燕霏翼羽翔璃绮纱绫绣锦瑜琼瑾璇璧琳琪琳瑶瑛芝杏茜荷莉莹菡莲诗羽珍" +
"瑰翠椒槐榆槿柱梧桐曜曙晶暖智煌熙灵霓珠熠燕熹熠碧瑶琳嘉琪瑶琴瑶琴碧曼" +
"菁蓉菲瑾淑妙惠嘉华秋涵智映巧慧茹瑜瑶荣菱霏曦容芬玲瑛琪瑜澜碧影凌清涛" +
"湘泽澄泓泓翠澜润璇珺湘晨曦晶翠瑾澜涟润淑洁悠雅翠霏涵淑珍绮翠润";
// 随机生成名字长度2到5个字
int nameLength = Random.Shared.Next(2, 6);
StringBuilder name = new();
for (int i = 0; i < nameLength; i++)
{
// 从常用汉字集中随机选择一个汉字
char chineseCharacter = commonChineseCharacters[Random.Shared.Next(commonChineseCharacters.Length)];
name.Append(chineseCharacter);
}
return name.ToString();
}
}
}