diff --git a/Api/Utility/Singleton.cs b/Api/Utility/Singleton.cs index 6c71a06..3451e8a 100644 --- a/Api/Utility/Singleton.cs +++ b/Api/Utility/Singleton.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections.Concurrent; namespace Milimoe.FunGame.Core.Api.Utility { @@ -8,7 +8,7 @@ namespace Milimoe.FunGame.Core.Api.Utility /// public class Singleton { - private static readonly Hashtable SingletonTable = new(); + private static readonly ConcurrentDictionary SingletonTable = []; /// /// 查询目标的类是否已经有实例 @@ -17,31 +17,25 @@ namespace Milimoe.FunGame.Core.Api.Utility /// public static bool IsExist(object single) { - return SingletonTable.ContainsKey(single.GetType().ToString()); + Type type = single.GetType(); + string name = type.FullName ?? type.ToString(); + return SingletonTable.ContainsKey(name); } /// - /// 将目标和目标的类添加至单例表 + /// 将目标和目标的类添加至单例表,如果存在,将更新此类单例 /// /// 单例对象 + /// 存入基类 /// - /// 添加单例到单例表时遇到错误 - public static bool Add(object single) + public static void AddOrUpdate(object single, bool baseClass = false) { - string type = single.GetType().ToString(); - if (!SingletonTable.ContainsKey(type)) + if (single != null) { - try - { - SingletonTable.Add(type, single); - } - catch - { - throw new SingletonAddException(); - } - return true; + Type? type = baseClass ? single.GetType().BaseType : single.GetType(); + string name = type?.FullName ?? type?.ToString() ?? ""; + if (name != "") SingletonTable.AddOrUpdate(name, single, (key, oldValue) => single); } - return false; } /// @@ -51,16 +45,9 @@ namespace Milimoe.FunGame.Core.Api.Utility /// public static bool Remove(object single) { - string type = single.GetType().ToString(); - if (!SingletonTable.ContainsKey(type)) - { - return false; - } - else - { - SingletonTable.Remove(type); - return true; - } + Type type = single.GetType(); + string name = type.FullName ?? type.ToString(); + return SingletonTable.TryRemove(name, out _); } /// @@ -68,24 +55,14 @@ namespace Milimoe.FunGame.Core.Api.Utility /// /// 目标类 /// - /// 不能从单例表中获取到指定的单例 public static T? Get() { - T? single = default; - string type = typeof(T).ToString(); - if (SingletonTable.ContainsKey(type)) + string name = typeof(T).FullName ?? typeof(T).ToString(); + if (SingletonTable.TryGetValue(name, out object? value) && value is T single) { - try - { - single = (T?)SingletonTable[type]; - } - catch - { - throw new SingletonGetException(); - } - if (single != null) return single; + return single; } - return single; + return default; } /// @@ -93,23 +70,14 @@ namespace Milimoe.FunGame.Core.Api.Utility /// /// 目标类 /// - /// 不能从单例表中获取到指定的单例 public static object? Get(Type type) { - object? single = default; - if (SingletonTable.ContainsKey(type)) + string name = type.FullName ?? type.ToString(); + if (SingletonTable.TryGetValue(name, out var value)) { - try - { - single = SingletonTable[type]; - } - catch - { - throw new SingletonGetException(); - } - if (single != null) return single; + return value; } - return single; + return null; } } } diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs index 5b8b20f..3eb9d80 100644 --- a/Entity/Character/Character.cs +++ b/Entity/Character/Character.cs @@ -69,31 +69,31 @@ namespace Milimoe.FunGame.Core.Entity { get { - if (Promotion > 998) + if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdSUpperLimit) { return RoleRating.X; } - else if (Promotion > 850 && Promotion <= 998) + else if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdAPlusUpperLimit && Promotion <= General.GameplayEquilibriumConstant.PromotionThresholdSUpperLimit) { return RoleRating.S; } - else if (Promotion > 700 && Promotion <= 850) + else if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdAUpperLimit && Promotion <= General.GameplayEquilibriumConstant.PromotionThresholdAPlusUpperLimit) { return RoleRating.APlus; } - else if (Promotion > 550 && Promotion <= 700) + else if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdBUpperLimit && Promotion <= General.GameplayEquilibriumConstant.PromotionThresholdAUpperLimit) { return RoleRating.A; } - else if (Promotion > 400 && Promotion <= 550) + else if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdCUpperLimit && Promotion <= General.GameplayEquilibriumConstant.PromotionThresholdBUpperLimit) { return RoleRating.B; } - else if (Promotion > 300 && Promotion <= 400) + else if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdDUpperLimit && Promotion <= General.GameplayEquilibriumConstant.PromotionThresholdCUpperLimit) { return RoleRating.C; } - else if (Promotion > 200 && Promotion <= 300) + else if (Promotion > General.GameplayEquilibriumConstant.PromotionThresholdEUpperLimit && Promotion <= General.GameplayEquilibriumConstant.PromotionThresholdDUpperLimit) { return RoleRating.D; } @@ -121,11 +121,11 @@ namespace Milimoe.FunGame.Core.Entity { get { - return _Level > 0 ? _Level : 1; + return _Level >= 1 ? _Level : 1; } set { - _Level = Math.Min(Math.Max(1, value), 60); + _Level = Math.Min(Math.Max(1, value), General.GameplayEquilibriumConstant.MaxLevel); OnAttributeChanged(); Recovery(); } @@ -165,17 +165,17 @@ namespace Milimoe.FunGame.Core.Entity /// 初始生命值 [ 初始设定 ] /// [InitRequired] - public double InitialHP { get; set; } = 60; + public double InitialHP { get; set; } = General.GameplayEquilibriumConstant.InitialHP; /// /// 基础生命值 [ 与初始设定和等级相关 ] [ 与基础力量相关 ] /// - public double BaseHP => Calculation.Round2Digits(InitialHP + (Level - 1) * (17 + 0.68 * InitialHP) + BaseSTR * 9); + public double BaseHP => InitialHP + (Level - 1) * (General.GameplayEquilibriumConstant.LevelToHPFactor + General.GameplayEquilibriumConstant.HPGrowthFactor * InitialHP) + BaseSTR * General.GameplayEquilibriumConstant.STRtoHPFactor; /// /// 额外生命值 [ 与额外力量相关 ] /// - public double ExHP => Calculation.Round2Digits(ExSTR * 9); + public double ExHP => ExSTR * General.GameplayEquilibriumConstant.STRtoHPFactor; /// /// 额外生命值2 [ 与技能和物品相关 ] @@ -185,7 +185,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 最大生命值 = 基础生命值 + 额外生命值 + 额外生命值2 /// - public double MaxHP => Calculation.Round2Digits(BaseHP + ExHP + ExHP2); + public double MaxHP => BaseHP + ExHP + ExHP2; /// /// 当前生命值 [ 战斗相关 ] @@ -198,7 +198,7 @@ namespace Milimoe.FunGame.Core.Entity } set { - _HP = Calculation.Round2Digits(value); + _HP = value; if (_HP > MaxHP) _HP = MaxHP; else if (_HP < 0) _HP = 0; } @@ -208,17 +208,17 @@ namespace Milimoe.FunGame.Core.Entity /// 初始魔法值 [ 初始设定 ] /// [InitRequired] - public double InitialMP { get; set; } = 10; + public double InitialMP { get; set; } = General.GameplayEquilibriumConstant.InitialMP; /// /// 基础魔法值 [ 与初始设定和等级相关 ] [ 与基础智力相关 ] /// - public double BaseMP => Calculation.Round2Digits(InitialMP + (Level - 1) * (1.5 + 0.14 * InitialMP) + BaseINT * 8); + public double BaseMP => InitialMP + (Level - 1) * (General.GameplayEquilibriumConstant.LevelToMPFactor + General.GameplayEquilibriumConstant.MPGrowthFactor * InitialMP) + BaseINT * General.GameplayEquilibriumConstant.INTtoMPFactor; /// /// 额外魔法值 [ 与额外智力相关 ] /// - public double ExMP => Calculation.Round2Digits(ExINT * 8); + public double ExMP => ExINT * General.GameplayEquilibriumConstant.INTtoMPFactor; /// /// 额外魔法值2 [ 与技能和物品相关 ] @@ -228,7 +228,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 最大魔法值 = 基础魔法值 + 额外魔法值 + 额外魔法值2 /// - public double MaxMP => Calculation.Round2Digits(BaseMP + ExMP + ExMP2); + public double MaxMP => BaseMP + ExMP + ExMP2; /// /// 当前魔法值 [ 战斗相关 ] @@ -241,7 +241,7 @@ namespace Milimoe.FunGame.Core.Entity } set { - _MP = Calculation.Round2Digits(value); + _MP = value; if (_MP > MaxMP) _MP = MaxMP; else if (_MP < 0) _MP = 0; } @@ -254,12 +254,12 @@ namespace Milimoe.FunGame.Core.Entity { get { - return _EP < 0 ? 0 : (_EP > 200 ? 200 : _EP); + return _EP < 0 ? 0 : (_EP > General.GameplayEquilibriumConstant.MaxEP ? General.GameplayEquilibriumConstant.MaxEP : _EP); } set { - _EP = Calculation.Round2Digits(value); - if (_EP > 200) _EP = 200; + _EP = value; + if (_EP > General.GameplayEquilibriumConstant.MaxEP) _EP = General.GameplayEquilibriumConstant.MaxEP; else if (_EP < 0) _EP = 0; } } @@ -268,7 +268,7 @@ namespace Milimoe.FunGame.Core.Entity /// 初始攻击力 [ 初始设定 ] /// [InitRequired] - public double InitialATK { get; set; } = 15; + public double InitialATK { get; set; } = General.GameplayEquilibriumConstant.InitialATK; /// /// 基础攻击力 [ 与初始设定和等级相关 ] [ 与核心属性相关 ] @@ -277,18 +277,18 @@ namespace Milimoe.FunGame.Core.Entity { get { - double atk = Calculation.Round2Digits(InitialATK + (Level - 1) * (0.95 + 0.045 * InitialATK)); + double atk = InitialATK + (Level - 1) * (General.GameplayEquilibriumConstant.LevelToATKFactor + General.GameplayEquilibriumConstant.ATKGrowthFactor * InitialATK); if (PrimaryAttribute == PrimaryAttribute.AGI) { - return Calculation.Round2Digits(atk + BaseAGI); + return atk + BaseAGI; } else if (PrimaryAttribute == PrimaryAttribute.INT) { - return Calculation.Round2Digits(atk + BaseINT); + return atk + BaseINT; } else // 默认STR { - return Calculation.Round2Digits(atk + BaseSTR); + return atk + BaseSTR; } } } @@ -323,23 +323,23 @@ namespace Milimoe.FunGame.Core.Entity /// /// 攻击力 = 基础攻击力 + 额外攻击力 + 额外攻击力2 /// - public double ATK => Calculation.Round2Digits(BaseATK + ExATK + ExATK2); + public double ATK => BaseATK + ExATK + ExATK2; /// /// 初始物理护甲 [ 初始设定 ] /// [InitRequired] - public double InitialDEF { get; set; } = 5; + public double InitialDEF { get; set; } = General.GameplayEquilibriumConstant.InitialDEF; /// /// 基础物理护甲 [ 与初始设定相关 ] [ 与基础力量相关 ] /// - public double BaseDEF => Calculation.Round2Digits(InitialDEF + BaseSTR * 0.75); + public double BaseDEF => InitialDEF + BaseSTR * General.GameplayEquilibriumConstant.STRtoDEFFactor; /// /// 额外物理护甲 [ 与额外力量相关 ] /// - public double ExDEF => Calculation.Round2Digits(ExSTR * 0.75); + public double ExDEF => ExSTR * General.GameplayEquilibriumConstant.STRtoDEFFactor; /// /// 额外物理护甲2 [ 与技能和物品相关 ] @@ -349,7 +349,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 物理护甲 = 基础物理护甲 + 额外物理护甲 + 额外物理护甲2 /// - public double DEF => Calculation.Round2Digits(BaseDEF + ExDEF + ExDEF2); + public double DEF => BaseDEF + ExDEF + ExDEF2; /// /// 物理伤害减免(%) = [ 与物理护甲相关 ] + 额外物理伤害减免(%) @@ -358,7 +358,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - double value = Calculation.Round4Digits((DEF / (DEF + 120)) + ExPDR); + double value = (DEF / (DEF + General.GameplayEquilibriumConstant.DEFReductionFactor)) + ExPDR; return Calculation.PercentageCheck(value); } } @@ -384,7 +384,7 @@ namespace Milimoe.FunGame.Core.Entity } set { - _PhysicalPenetration = Calculation.PercentageCheck(Calculation.Round4Digits(value)); + _PhysicalPenetration = Calculation.PercentageCheck(value); } } @@ -399,7 +399,7 @@ namespace Milimoe.FunGame.Core.Entity } set { - _MagicalPenetration = Calculation.PercentageCheck(Calculation.Round4Digits(value)); + _MagicalPenetration = Calculation.PercentageCheck(value); } } @@ -412,7 +412,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 生命回复力 = [ 与初始设定相关 ] [ 与力量相关 ] + 额外生命回复力 /// - public double HR => Calculation.Round2Digits(InitialHR + STR * 0.25 + ExHR); + public double HR => InitialHR + STR * General.GameplayEquilibriumConstant.STRtoHRFactor + ExHR; /// /// 额外生命回复力 [ 与技能和物品相关 ] @@ -428,7 +428,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 魔法回复力 = [ 与初始设定相关 ] [ 与智力相关 ] + 额外魔法回复力 /// - public double MR => Calculation.Round2Digits(InitialMR + INT * 0.1 + ExMR); + public double MR => InitialMR + INT * General.GameplayEquilibriumConstant.INTtoMRFactor + ExMR; /// /// 额外魔法回复力 [ 与技能和物品相关 ] @@ -527,17 +527,17 @@ namespace Milimoe.FunGame.Core.Entity /// /// 基础力量 [ 与初始设定和等级相关 ] /// - public double BaseSTR => Calculation.Round2Digits(InitialSTR + STRGrowth * (Level - 1)); + public double BaseSTR => InitialSTR + STRGrowth * (Level - 1); /// /// 基础敏捷 [ 与初始设定和等级相关 ] /// - public double BaseAGI => Calculation.Round2Digits(InitialAGI + AGIGrowth * (Level - 1)); + public double BaseAGI => InitialAGI + AGIGrowth * (Level - 1); /// /// 基础智力 [ 与初始设定和等级相关 ] /// - public double BaseINT => Calculation.Round2Digits(InitialINT + INTGrowth * (Level - 1)); + public double BaseINT => InitialINT + INTGrowth * (Level - 1); /// /// 额外力量 [ 与技能和物品相关 ] @@ -557,17 +557,17 @@ namespace Milimoe.FunGame.Core.Entity /// /// 力量 = 基础力量 + 额外力量 /// - public double STR => Calculation.Round2Digits(BaseSTR + ExSTR); + public double STR => BaseSTR + ExSTR; /// /// 敏捷 = 基础敏捷 + 额外敏捷 /// - public double AGI => Calculation.Round2Digits(BaseAGI + ExAGI); + public double AGI => BaseAGI + ExAGI; /// /// 智力 = 基础智力 + 额外智力 /// - public double INT => Calculation.Round2Digits(BaseINT + ExINT); + public double INT => BaseINT + ExINT; /// /// 力量成长值(+BaseSTR/Lv) @@ -593,7 +593,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 行动速度 = [ 与初始设定相关 ][ 与敏捷相关 ] + 额外行动速度 /// - public double SPD => Calculation.Round2Digits(InitialSPD + AGI * 0.65 + ExSPD); + public double SPD => InitialSPD + AGI * General.GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; /// /// 额外行动速度 [ 与技能和物品相关 ] @@ -607,7 +607,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - double value = Calculation.Round4Digits(SPD / 1500.00 + ExActionCoefficient); + double value = SPD / General.GameplayEquilibriumConstant.SPDUpperLimit + ExActionCoefficient; return Calculation.PercentageCheck(value); } } @@ -629,7 +629,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - double value = Calculation.Round4Digits(INT * 0.0025 + ExCDR); + double value = INT * General.GameplayEquilibriumConstant.INTtoCDRMultiplier + ExCDR; return Calculation.PercentageCheck(value); } } @@ -652,7 +652,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - double value = Calculation.Round4Digits(0.05 + AGI * 0.0025 + ExCritRate); + double value = General.GameplayEquilibriumConstant.CritRate + AGI * General.GameplayEquilibriumConstant.AGItoCritRateMultiplier + ExCritRate; return Calculation.PercentageCheck(value); } } @@ -669,7 +669,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - return Calculation.Round4Digits(1.25 + STR * 0.00575 + ExCritDMG); + return General.GameplayEquilibriumConstant.CritDMG + STR * General.GameplayEquilibriumConstant.STRtoCritDMGMultiplier + ExCritDMG; } } @@ -685,7 +685,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - double value = Calculation.Round4Digits(0.05 + AGI * 0.0025 + ExEvadeRate); + double value = General.GameplayEquilibriumConstant.EvadeRate + AGI * General.GameplayEquilibriumConstant.AGItoEvadeRateMultiplier + ExEvadeRate; return Calculation.PercentageCheck(value); } } @@ -783,8 +783,8 @@ namespace Milimoe.FunGame.Core.Entity { if (time > 0) { - HP = Math.Min(MaxHP, Calculation.Round2Digits(HP + HR * time)); - MP = Math.Min(MaxMP, Calculation.Round2Digits(MP + MR * time)); + HP = Math.Min(MaxHP, HP + HR * time); + MP = Math.Min(MaxMP, MP + MR * time); if (EP != -1) this.EP = EP; } } @@ -798,10 +798,10 @@ namespace Milimoe.FunGame.Core.Entity /// public void Recovery(double pastHP, double pastMP, double pastMaxHP, double pastMaxMP) { - double pHP = Calculation.Round4Digits(pastHP / pastMaxHP); - double pMP = Calculation.Round4Digits(pastMP / pastMaxMP); - HP = Calculation.Round2Digits(MaxHP * pHP); - MP = Calculation.Round2Digits(MaxMP * pMP); + double pHP = pastHP / pastMaxHP; + double pMP = pastMP / pastMaxMP; + HP = MaxHP * pHP; + MP = MaxMP * pMP; } /// @@ -1070,22 +1070,22 @@ namespace Milimoe.FunGame.Core.Entity StringBuilder builder = new(); builder.AppendLine(ToStringWithLevel()); - builder.AppendLine($"生命值:{HP} / {MaxHP}" + (ExHP + ExHP2 > 0 ? $" [{BaseHP} + {ExHP + ExHP2}]" : "")); - builder.AppendLine($"魔法值:{MP} / {MaxMP}" + (ExMP + ExMP2 > 0 ? $" [{BaseMP} + {ExMP + ExMP2}]" : "")); - builder.AppendLine($"能量值:{EP} / 200"); - builder.AppendLine($"攻击力:{ATK}" + (ExATK + ExATK2 > 0 ? $" [{BaseATK} + {ExATK + ExATK2}]" : "")); - builder.AppendLine($"物理护甲:{DEF}" + (ExDEF + ExDEF2 > 0 ? $" [{BaseDEF} + {ExDEF + ExDEF2}]" : "") + $" ({PDR * 100:0.##}%)"); - double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + - MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (ExHP + ExHP2 > 0 ? $" [{BaseHP:0.##} + {(ExHP + ExHP2):0.##}]" : "")); + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (ExMP + ExMP2 > 0 ? $" [{BaseMP:0.##} + {(ExMP + ExMP2):0.##}]" : "")); + builder.AppendLine($"能量值:{EP:0.##} / {General.GameplayEquilibriumConstant.MaxEP:0.##}"); + builder.AppendLine($"攻击力:{ATK:0.##}" + (ExATK + ExATK2 > 0 ? $" [{BaseATK:0.##} + {ExATK + ExATK2:0.##}]" : "")); + builder.AppendLine($"物理护甲:{DEF:0.##}" + (ExDEF + ExDEF2 > 0 ? $" [{BaseDEF:0.##} + {ExDEF + ExDEF2:0.##}]" : "") + $" ({PDR * 100:0.##}%)"); + double mdf = (MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9; builder.AppendLine($"魔法抗性:{mdf * 100:0.##}%(平均)"); - double exSPD = Calculation.Round2Digits(AGI * 0.65 + ExSPD); - builder.AppendLine($"行动速度:{SPD}" + (exSPD > 0 ? $" [{InitialSPD} + {exSPD}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); + double exSPD = AGI * General.GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; + builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD > 0 ? $" [{InitialSPD:0.##} + {exSPD:0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}"); - builder.AppendLine($"力量:{STR}" + (ExSTR > 0 ? $" [{BaseSTR} + {ExSTR}]" : "")); - builder.AppendLine($"敏捷:{AGI}" + (ExAGI > 0 ? $" [{BaseAGI} + {ExAGI}]" : "")); - builder.AppendLine($"智力:{INT}" + (ExINT > 0 ? $" [{BaseINT} + {ExINT}]" : "")); - builder.AppendLine($"生命回复:{HR}" + (ExHR > 0 ? $" [{Calculation.Round2Digits(InitialHR + STR * 0.25)} + {ExHR}]" : "")); - builder.AppendLine($"魔法回复:{MR}" + (ExMR > 0 ? $" [{Calculation.Round2Digits(InitialMR + INT * 0.1)} + {ExMR}]" : "")); + builder.AppendLine($"力量:{STR:0.##}" + (ExSTR > 0 ? $" [{BaseSTR:0.##} + {ExSTR:0.##}]" : "")); + builder.AppendLine($"敏捷:{AGI:0.##}" + (ExAGI > 0 ? $" [{BaseAGI:0.##} + {ExAGI:0.##}]" : "")); + builder.AppendLine($"智力:{INT:0.##}" + (ExINT > 0 ? $" [{BaseINT:0.##} + {ExINT:0.##}]" : "")); + builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR > 0 ? $" [{InitialHR + STR * 0.25:0.##} + {ExHR:0.##}]" : "")); + builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR > 0 ? $" [{InitialMR + INT * 0.1:0.##} + {ExMR:0.##}]" : "")); builder.AppendLine($"暴击率:{CritRate * 100:0.##}%"); builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%"); builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%"); @@ -1189,11 +1189,11 @@ namespace Milimoe.FunGame.Core.Entity StringBuilder builder = new(); builder.AppendLine(ToStringWithLevel()); - builder.AppendLine($"生命值:{HP} / {MaxHP}" + (ExHP + ExHP2 > 0 ? $" [{BaseHP} + {ExHP + ExHP2}]" : "")); - builder.AppendLine($"魔法值:{MP} / {MaxMP}" + (ExMP + ExMP2 > 0 ? $" [{BaseMP} + {ExMP + ExMP2}]" : "")); - builder.AppendLine($"能量值:{EP} / 200"); - builder.AppendLine($"攻击力:{ATK}" + (ExATK + ExATK2 > 0 ? $" [{BaseATK} + {ExATK + ExATK2}]" : "")); - builder.AppendLine($"核心属性:{PrimaryAttributeValue}" + (ExPrimaryAttributeValue > 0 ? $" [{BasePrimaryAttributeValue} + {ExPrimaryAttributeValue}]" : "")); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (ExHP + ExHP2 > 0 ? $" [{BaseHP:0.##} + {ExHP + ExHP2:0.##}]" : "")); + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (ExMP + ExMP2 > 0 ? $" [{BaseMP:0.##} + {ExMP + ExMP2:0.##}]" : "")); + builder.AppendLine($"能量值:{EP:0.##} / {General.GameplayEquilibriumConstant.MaxEP:0.##}"); + builder.AppendLine($"攻击力:{ATK:0.##}" + (ExATK + ExATK2 > 0 ? $" [{BaseATK:0.##} + {ExATK + ExATK2:0.##}]" : "")); + builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}" + (ExPrimaryAttributeValue > 0 ? $" [{BasePrimaryAttributeValue:0.##} + {ExPrimaryAttributeValue:0.##}]" : "")); if (CharacterState != CharacterState.Actionable) { @@ -1210,7 +1210,7 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine("角色是不可选中的"); } - builder.AppendLine($"硬直时间:{hardnessTimes}"); + builder.AppendLine($"硬直时间:{hardnessTimes:0.##}"); if (Effects.Count > 0) { diff --git a/Entity/Item/Item.cs b/Entity/Item/Item.cs index b71deac..136793a 100644 --- a/Entity/Item/Item.cs +++ b/Entity/Item/Item.cs @@ -1,8 +1,8 @@ using System.Text; -using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Entity { @@ -307,7 +307,7 @@ namespace Milimoe.FunGame.Core.Entity StringBuilder builder = new(); builder.AppendLine($"【{Name}】"); - builder.AppendLine($"{ItemSet.GetItemTypeName(ItemType)}" + (IsPurchasable && Price > 0 ? $" 售价:{Price}" : "")); + builder.AppendLine($"{ItemSet.GetItemTypeName(ItemType)}" + (IsPurchasable && Price > 0 ? $" 售价:{Price:0.##}" : "")); if (RemainUseTimes > 0) { diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs index b6ea370..9c45dcd 100644 --- a/Entity/Skill/Effect.cs +++ b/Entity/Skill/Effect.cs @@ -2,6 +2,7 @@ using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Entity { @@ -423,7 +424,7 @@ namespace Milimoe.FunGame.Core.Entity string isDurative = ""; if (Durative) { - isDurative = "(剩余:" + RemainDuration + " 时间)"; + isDurative = $"(剩余:{RemainDuration:0.##} 时间)"; } else if (DurationTurn > 0) { diff --git a/Entity/Skill/NormalAttack.cs b/Entity/Skill/NormalAttack.cs index 152b3ac..7fc5c91 100644 --- a/Entity/Skill/NormalAttack.cs +++ b/Entity/Skill/NormalAttack.cs @@ -2,6 +2,7 @@ using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Entity { @@ -15,7 +16,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 普通攻击说明 /// - public string Description => $"对目标敌人造成 {Calculation.Round4Digits((1.0 + 0.05 * (Level - 1)) * 100)}% [ {Damage} ] 点{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。"; + public string Description => $"对目标敌人造成 {(1.0 + 0.05 * (Level - 1)) * 100:0.##}% [ {Damage:0.##} ] 点{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。"; /// /// 所属的角色 @@ -25,7 +26,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 普通攻击的伤害 /// - public double Damage => Calculation.Round2Digits(Character.ATK * (1.0 + 0.05 * (Level - 1))); + public double Damage => Character.ATK * (1.0 + 0.05 * (Level - 1)); /// /// 普通攻击等级 @@ -38,7 +39,7 @@ namespace Milimoe.FunGame.Core.Entity } set { - _Level = Math.Min(Math.Max(1, value), 8); + _Level = Math.Min(Math.Max(1, value), General.GameplayEquilibriumConstant.MaxNormalAttackLevel); } } diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs index 147e630..67b7641 100644 --- a/Entity/Skill/Skill.cs +++ b/Entity/Skill/Skill.cs @@ -2,6 +2,7 @@ using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Entity { @@ -36,7 +37,7 @@ namespace Milimoe.FunGame.Core.Entity } set { - int max = IsSuperSkill ? 6 : (IsMagic ? 8 : 6); + int max = SkillSet.GetSkillMaxLevel(SkillType); _Level = Math.Min(Math.Max(0, value), max); OnLevelUp(); } @@ -79,7 +80,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 实际魔法消耗 [ 魔法 ] /// - public double RealMPCost => Calculation.Round2Digits(Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00125)))); + public double RealMPCost => Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00125))); /// /// 魔法消耗 [ 魔法 ] @@ -90,7 +91,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 实际吟唱时间 [ 魔法 ] /// - public double RealCastTime => Calculation.Round2Digits(Math.Max(0, CastTime * (1 - Calculation.PercentageCheck(Character?.AccelerationCoefficient ?? 0)))); + public double RealCastTime => Math.Max(0, CastTime * (1 - Calculation.PercentageCheck(Character?.AccelerationCoefficient ?? 0))); /// /// 吟唱时间 [ 魔法 ] @@ -101,7 +102,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 实际能量消耗 [ 战技 ] /// - public double RealEPCost => IsSuperSkill ? EPCost : Calculation.Round2Digits(Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00075)))); + public double RealEPCost => IsSuperSkill ? EPCost : Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00075))); /// /// 能量消耗 [ 战技 ] @@ -112,7 +113,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 实际冷却时间 /// - public double RealCD => Calculation.Round2Digits(Math.Max(0, CD * (1 - Character?.CDR ?? 0))); + public double RealCD => Math.Max(0, CD * (1 - Character?.CDR ?? 0)); /// /// 冷却时间 @@ -245,7 +246,7 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine("技能描述:" + Description); if (CurrentCD > 0) { - builder.AppendLine("正在冷却:剩余 " + CurrentCD + " 时间"); + builder.AppendLine($"正在冷却:剩余 {CurrentCD:0.##} 时间"); } if (!Enable) { @@ -261,34 +262,34 @@ namespace Milimoe.FunGame.Core.Entity { if (RealMPCost > 0) { - builder.AppendLine("魔法消耗:" + RealMPCost); + builder.AppendLine($"魔法消耗:{RealMPCost:0.##}"); } if (RealEPCost > 0) { - builder.AppendLine("能量消耗:" + RealEPCost); + builder.AppendLine($"能量消耗:{RealEPCost:0.##}"); } } else { if (IsSuperSkill) { - builder.AppendLine("能量消耗:" + RealEPCost); + builder.AppendLine($"能量消耗:{RealEPCost:0.##}"); } else { if (IsMagic) { - builder.AppendLine("魔法消耗:" + RealMPCost); - builder.AppendLine("吟唱时间:" + RealCastTime); + builder.AppendLine($"魔法消耗:{RealMPCost:0.##}"); + builder.AppendLine($"吟唱时间:{RealCastTime:0.##}"); } else { - builder.AppendLine("能量消耗:" + RealEPCost); + builder.AppendLine($"能量消耗:{RealEPCost::0.##}"); } } } - builder.AppendLine("冷却时间:" + RealCD); - builder.AppendLine("硬直时间:" + HardnessTime); + builder.AppendLine($"冷却时间:{RealCD:0.##}"); + builder.AppendLine($"硬直时间:{HardnessTime:0.##}"); } return builder.ToString(); diff --git a/Interface/Base/Addons/IGameModuleServer.cs b/Interface/Base/Addons/IGameModuleServer.cs index 0ee4fca..c5033e1 100644 --- a/Interface/Base/Addons/IGameModuleServer.cs +++ b/Interface/Base/Addons/IGameModuleServer.cs @@ -4,7 +4,7 @@ using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Interface.Addons { - public interface IGameModuleServer : IAddon, IAddonController, IGameModuleDepend + public interface IGameModuleServer : IAddon, IServerAddon, IAddonController, IGameModuleDepend { public bool StartServer(string GameModule, Room Room, List Users, IServerModel RoomMasterServerModel, Dictionary ServerModels, params object[] args); diff --git a/Interface/Base/Addons/IServerAddon.cs b/Interface/Base/Addons/IServerAddon.cs new file mode 100644 index 0000000..6a22bb1 --- /dev/null +++ b/Interface/Base/Addons/IServerAddon.cs @@ -0,0 +1,10 @@ +using Milimoe.FunGame.Core.Api.Transmittal; + +namespace Milimoe.FunGame.Core.Interface.Addons +{ + public interface IServerAddon + { + public SQLHelper? SQLHelper { get; } + public MailSender? MailSender { get; } + } +} diff --git a/Interface/Base/IGamingQueue.cs b/Interface/Base/IGamingQueue.cs new file mode 100644 index 0000000..8bb4756 --- /dev/null +++ b/Interface/Base/IGamingQueue.cs @@ -0,0 +1,103 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Interface.Base +{ + /// + /// 回合制游戏的基础队列 + /// + public interface IGamingQueue + { + /// + /// 用于文本输出 + /// + public Action WriteLine { get; } + + /// + /// 当前的行动顺序 + /// + public List Queue { get; } + + /// + /// 当前已死亡的角色顺序(第一个是最早死的) + /// + public List Eliminated { get; } + + /// + /// 角色数据 + /// + public Dictionary CharacterStatistics { get; } + + /// + /// 游戏运行的时间 + /// + public double TotalTime { get; } + + /// + /// 游戏运行的回合 + /// 对于某角色而言,在其行动的回合叫 Turn,而所有角色行动的回合,都称之为 Round。 + /// + public int TotalRound { get; } + + /// + /// 显示队列信息 + /// + public void DisplayQueue(); + + /// + /// 处理回合动作 + /// + /// + /// + public bool ProcessTurn(Character character); + + /// + /// 造成伤害 + /// + /// + /// + /// + /// + /// + /// + /// + public void DamageToEnemy(Character actor, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage = false, MagicType magicType = MagicType.None, DamageResult damageResult = DamageResult.Normal); + + /// + /// 计算物理伤害 + /// + /// + /// + /// + /// + /// + /// + public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage); + + /// + /// 计算魔法伤害 + /// + /// + /// + /// + /// + /// + /// + /// + public DamageResult CalculateMagicalDamage(Character actor, Character enemy, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage); + + /// + /// 死亡结算 + /// + /// + /// + public void DeathCalculation(Character killer, Character death); + + /// + /// 打断施法 + /// + /// + /// + public void InterruptCasting(Character caster, Character interrupter); + } +} diff --git a/Library/Common/Addon/GameModuleServer.cs b/Library/Common/Addon/GameModuleServer.cs index f269398..8ec102b 100644 --- a/Library/Common/Addon/GameModuleServer.cs +++ b/Library/Common/Addon/GameModuleServer.cs @@ -1,3 +1,5 @@ +using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Interface.Addons; @@ -53,6 +55,16 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// private BaseAddonController? _Controller; + /// + /// 全局数据库连接器 + /// + public SQLHelper? SQLHelper => Singleton.Get(); + + /// + /// 全局邮件发送器 + /// + public MailSender? MailSender => Singleton.Get(); + /// /// 启动服务器监听 请在此处实现服务器逻辑 /// diff --git a/Library/Common/Addon/ServerPlugin.cs b/Library/Common/Addon/ServerPlugin.cs index 3430e86..8db1831 100644 --- a/Library/Common/Addon/ServerPlugin.cs +++ b/Library/Common/Addon/ServerPlugin.cs @@ -1,11 +1,13 @@ -using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Interface; using Milimoe.FunGame.Core.Interface.Addons; using Milimoe.FunGame.Core.Library.Common.Event; namespace Milimoe.FunGame.Core.Library.Common.Addon { - public abstract class ServerPlugin : IPlugin + public abstract class ServerPlugin : IPlugin, IServerAddon { /// /// 插件名称 @@ -36,6 +38,16 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon set => _Controller = value; } + /// + /// 全局数据库连接器 + /// + public SQLHelper? SQLHelper => Singleton.Get(); + + /// + /// 全局邮件发送器 + /// + public MailSender? MailSender => Singleton.Get(); + /// /// 控制器内部变量 /// diff --git a/Library/Common/Addon/WebAPIPlugin.cs b/Library/Common/Addon/WebAPIPlugin.cs index 0e6d7c2..c6c5d86 100644 --- a/Library/Common/Addon/WebAPIPlugin.cs +++ b/Library/Common/Addon/WebAPIPlugin.cs @@ -1,9 +1,11 @@ -using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Interface.Addons; namespace Milimoe.FunGame.Core.Library.Common.Addon { - public abstract class WebAPIPlugin : IAddon, IAddonController + public abstract class WebAPIPlugin : IAddon, IServerAddon, IAddonController { /// /// 插件名称 @@ -39,6 +41,16 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// private BaseAddonController? _Controller; + /// + /// 全局数据库连接器 + /// + public SQLHelper? SQLHelper => Singleton.Get(); + + /// + /// 全局邮件发送器 + /// + public MailSender? MailSender => Singleton.Get(); + /// /// 加载标记 /// diff --git a/Library/Constant/ConstantSet.cs b/Library/Constant/ConstantSet.cs index 54ba832..8e1091a 100644 --- a/Library/Constant/ConstantSet.cs +++ b/Library/Constant/ConstantSet.cs @@ -519,5 +519,17 @@ namespace Milimoe.FunGame.Core.Library.Constant _ => SkillType.Passive, }; } + + public static int GetSkillMaxLevel(SkillType type) + { + return type switch + { + SkillType.Magic => General.GameplayEquilibriumConstant.MaxMagicLevel, + SkillType.Skill => General.GameplayEquilibriumConstant.MaxSkillLevel, + SkillType.SuperSkill => General.GameplayEquilibriumConstant.MaxSuperSkillLevel, + SkillType.Item => General.GameplayEquilibriumConstant.MaxSkillLevel, + _ => General.GameplayEquilibriumConstant.MaxPassiveSkillLevel + }; + } } } diff --git a/Library/Constant/General.cs b/Library/Constant/General.cs index d59e8aa..70c82d2 100644 --- a/Library/Constant/General.cs +++ b/Library/Constant/General.cs @@ -1,5 +1,6 @@ using System.Text; using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Library.Constant { @@ -55,6 +56,11 @@ namespace Milimoe.FunGame.Core.Library.Constant /// public static DateTime DefaultTime => new(1970, 1, 1, 8, 0, 0); + /// + /// 游戏平衡常数 + /// + public static EquilibriumConstant GameplayEquilibriumConstant { get; set; } = new(); + #endregion #region Const diff --git a/Api/Utility/ActionQueue.cs b/Model/ActionQueue.cs similarity index 94% rename from Api/Utility/ActionQueue.cs rename to Model/ActionQueue.cs index 5d56639..583ae01 100644 --- a/Api/Utility/ActionQueue.cs +++ b/Model/ActionQueue.cs @@ -1,12 +1,14 @@ -using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Interface.Base; using Milimoe.FunGame.Core.Library.Constant; -namespace Milimoe.FunGame.Core.Api.Utility +namespace Milimoe.FunGame.Core.Model { /// /// 行动顺序表 /// - public class ActionQueue + public class ActionQueue : IGamingQueue { /// /// 用于文本输出 @@ -341,7 +343,7 @@ namespace Milimoe.FunGame.Core.Api.Utility // 技能列表 List skills = [.. character.Skills.Where(s => s.Level > 0 && s.SkillType != SkillType.Passive && s.Enable && !s.IsInEffect && s.CurrentCD == 0 && - (((s.SkillType == SkillType.SuperSkill || s.SkillType == SkillType.Skill) && s.RealEPCost <= character.EP) || (s.SkillType == SkillType.Magic && s.RealMPCost <= character.MP)))]; + ((s.SkillType == SkillType.SuperSkill || s.SkillType == SkillType.Skill) && s.RealEPCost <= character.EP || s.SkillType == SkillType.Magic && s.RealMPCost <= character.MP))]; // 物品列表 List items = [.. character.Items.Where(i => i.IsActive && i.Skills.Active != null && i.Enable && i.IsInGameItem && @@ -510,7 +512,7 @@ namespace Milimoe.FunGame.Core.Api.Utility { skill.OnSkillCasting(this, character); - character.EP = Calculation.Round2Digits(character.EP - cost); + character.EP -= cost; baseTime = skill.HardnessTime; skill.CurrentCD = skill.RealCD; skill.Enable = false; @@ -535,7 +537,7 @@ namespace Milimoe.FunGame.Core.Api.Utility // 判断是否能够释放技能 if (CheckCanCast(character, skill, out double cost)) { - character.MP = Calculation.Round2Digits(character.MP - cost); + character.MP -= cost; baseTime = skill.HardnessTime; skill.CurrentCD = skill.RealCD; skill.Enable = false; @@ -565,7 +567,7 @@ namespace Milimoe.FunGame.Core.Api.Utility // 判断是否能够释放技能 if (CheckCanCast(character, skill, out double cost)) { - character.EP = Calculation.Round2Digits(character.EP - cost); + character.EP -= cost; baseTime = skill.HardnessTime; skill.CurrentCD = skill.RealCD; skill.Enable = false; @@ -682,36 +684,36 @@ namespace Milimoe.FunGame.Core.Api.Utility _stats[character].DamagePerSecond = Calculation.Round2Digits(_stats[character].TotalDamage / _stats[character].LiveTime); // 回血回蓝 - double recoveryHP = Calculation.Round2Digits(character.HR * timeToReduce); - double recoveryMP = Calculation.Round2Digits(character.MR * timeToReduce); - double needHP = Calculation.Round2Digits(character.MaxHP - character.HP); - double needMP = Calculation.Round2Digits(character.MaxMP - character.MP); + double recoveryHP = character.HR * timeToReduce; + double recoveryMP = character.MR * timeToReduce; + double needHP = character.MaxHP - character.HP; + double needMP = character.MaxMP - character.MP; double reallyReHP = needHP >= recoveryHP ? recoveryHP : needHP; double reallyReMP = needMP >= recoveryMP ? recoveryMP : needMP; if (reallyReHP > 0 && reallyReMP > 0) { - character.HP = Calculation.Round2Digits(character.HP + reallyReHP); - character.MP = Calculation.Round2Digits(character.MP + reallyReMP); - WriteLine("角色 " + character.NickName + " 回血:" + recoveryHP + " / " + "回蓝:" + recoveryMP); + character.HP += reallyReHP; + character.MP += reallyReMP; + WriteLine($"角色 {character.NickName} 回血:{recoveryHP:0.##} / 回蓝:{recoveryMP:0.##}"); } else { if (reallyReHP > 0) { - character.HP = Calculation.Round2Digits(character.HP + reallyReHP); - WriteLine("角色 " + character.NickName + " 回血:" + recoveryHP); + character.HP += reallyReHP; + WriteLine($"角色 {character.NickName} 回血:{recoveryHP:0.##}"); } if (reallyReMP > 0) { - character.MP = Calculation.Round2Digits(character.MP + reallyReMP); - WriteLine("角色 " + character.NickName + " 回蓝:" + recoveryMP); + character.MP += reallyReMP; + WriteLine($"角色 {character.NickName} 回蓝:{recoveryMP:0.##}"); } } // 减少所有技能的冷却时间 foreach (Skill skill in character.Skills) { - skill.CurrentCD = Calculation.Round2Digits(skill.CurrentCD - timeToReduce); + skill.CurrentCD -= timeToReduce; if (skill.CurrentCD <= 0) { skill.CurrentCD = 0; @@ -738,7 +740,7 @@ namespace Milimoe.FunGame.Core.Api.Utility if (effect.Durative) { - effect.RemainDuration = Calculation.Round2Digits(effect.RemainDuration - timeToReduce); + effect.RemainDuration -= timeToReduce; if (effect.RemainDuration <= 0) { effect.RemainDuration = 0; @@ -782,10 +784,10 @@ namespace Milimoe.FunGame.Core.Api.Utility if (isMagicDamage) { string dmgType = CharacterSet.GetMagicDamageName(magicType); - WriteLine("[ " + enemy + $" ] 受到了 {damage} 点{dmgType}!"); + WriteLine("[ " + enemy + $" ] 受到了 {damage:0.##} 点{dmgType}!"); } - else WriteLine("[ " + enemy + $" ] 受到了 {damage} 点物理伤害!"); - enemy.HP = Calculation.Round2Digits(enemy.HP - damage); + else WriteLine("[ " + enemy + $" ] 受到了 {damage:0.##} 点物理伤害!"); + enemy.HP -= damage; // 统计伤害 CalculateCharacterDamageStatistics(actor, enemy, damage, isMagicDamage); @@ -820,7 +822,7 @@ namespace Milimoe.FunGame.Core.Api.Utility { effect.AfterDeathCalculation(enemy, actor, _continuousKilling, _earnedMoney); } - if (_queue.Remove(enemy) && (!_queue.Where(c => c != actor).Any())) + if (_queue.Remove(enemy) && !_queue.Where(c => c != actor).Any()) { // 没有其他的角色了,游戏结束 EndGameInfo(actor); @@ -836,7 +838,7 @@ namespace Milimoe.FunGame.Core.Api.Utility /// 最大获取量 public static double GetEP(double a, double b, double max) { - return Calculation.Round2Digits(Math.Min((a + Random.Shared.Next(30)) * b, max)); + return Math.Min((a + Random.Shared.Next(30)) * b, max); } /// @@ -891,19 +893,19 @@ namespace Milimoe.FunGame.Core.Api.Utility } // 物理穿透后的护甲 - double penetratedDEF = Calculation.Round2Digits((1 - actor.PhysicalPenetration) * enemy.DEF); + double penetratedDEF = (1 - actor.PhysicalPenetration) * enemy.DEF; // 物理伤害减免 - double physicalDamageReduction = Calculation.Round4Digits(penetratedDEF / (penetratedDEF + 120)); + double physicalDamageReduction = penetratedDEF / (penetratedDEF + 120); // 最终的物理伤害 - finalDamage = Calculation.Round2Digits(expectedDamage * (1 - physicalDamageReduction)); + finalDamage = expectedDamage * (1 - physicalDamageReduction); // 暴击判定 dice = Random.Shared.NextDouble(); if (dice < actor.CritRate) { - finalDamage = Calculation.Round2Digits(finalDamage * actor.CritDMG); // 暴击伤害倍率加成 + finalDamage *= actor.CritDMG; // 暴击伤害倍率加成 WriteLine("暴击生效!!"); foreach (Effect effect in actor.Effects.Where(e => e.Level > 0).ToList()) { @@ -981,16 +983,16 @@ namespace Milimoe.FunGame.Core.Api.Utility }; // 魔法穿透后的魔法抗性 - MDF = Calculation.Round2Digits((1 - actor.MagicalPenetration) * MDF); + MDF = (1 - actor.MagicalPenetration) * MDF; // 最终的魔法伤害 - finalDamage = Calculation.Round2Digits(expectedDamage * (1 - MDF)); + finalDamage = expectedDamage * (1 - MDF); // 暴击判定 dice = Random.Shared.NextDouble(); if (dice < actor.CritRate) { - finalDamage = Calculation.Round2Digits(finalDamage * actor.CritDMG); // 暴击伤害倍率加成 + finalDamage *= actor.CritDMG; // 暴击伤害倍率加成 WriteLine("暴击生效!!"); foreach (Effect effect in actor.Effects.Where(e => e.Level > 0).ToList()) { @@ -1016,7 +1018,7 @@ namespace Milimoe.FunGame.Core.Api.Utility int money = Random.Shared.Next(250, 350); Character[] assists = _assistDamage.Keys.Where(c => c != death && _assistDamage[c].GetPercentage(death) > 0.10).ToArray(); - double totalDamagePercentage = Calculation.Round4Digits(_assistDamage.Keys.Where(assists.Contains).Select(c => _assistDamage[c].GetPercentage(death)).Sum()); + double totalDamagePercentage = _assistDamage.Keys.Where(assists.Contains).Select(c => _assistDamage[c].GetPercentage(death)).Sum(); int totalMoney = Math.Min(Convert.ToInt32(money * totalDamagePercentage), 425); // 防止刷伤害设置金钱上限 // 按伤害比分配金钱 只有造成10%伤害以上才能参与 @@ -1039,7 +1041,7 @@ namespace Milimoe.FunGame.Core.Api.Utility { money += (coefficient + 1) * Random.Shared.Next(50, 100); string termination = CharacterSet.GetContinuousKilling(coefficient); - string msg = $"[ {killer} ] 终结了 [ {death} ]{(termination != "" ? " 的" + termination : "")},获得 {money} 金钱!"; + string msg = $"[ {killer} ] 终结了 [ {death} ]{(termination != "" ? " 的" + termination : "")},获得 {money} {General.GameplayEquilibriumConstant.InGameCurrency}!"; if (assists.Length > 1) { msg += "助攻:[ " + string.Join(" ] / [ ", assists.Where(c => c != killer)) + " ]"; @@ -1048,7 +1050,7 @@ namespace Milimoe.FunGame.Core.Api.Utility } else { - string msg = $"[ {killer} ] 杀死了 [ {death} ],获得 {money} 金钱!"; + string msg = $"[ {killer} ] 杀死了 [ {death} ],获得 {money} {General.GameplayEquilibriumConstant.InGameCurrency}!"; if (assists.Length > 1) { msg += "助攻:[ " + string.Join(" ] / [ ", assists.Where(c => c != killer)) + " ]"; @@ -1094,7 +1096,7 @@ namespace Milimoe.FunGame.Core.Api.Utility for (int i = _eliminated.Count - 1; i >= 0; i--) { Character ec = _eliminated[i]; - string topCharacter = ec.ToString() + (_continuousKilling.TryGetValue(ec, out int kills) && kills > 1 ? $" [ {CharacterSet.GetContinuousKilling(kills)} ]" : "") + (_earnedMoney.TryGetValue(ec, out int earned) ? $" [ 已赚取 {earned} 金钱 ]" : ""); + string topCharacter = ec.ToString() + (_continuousKilling.TryGetValue(ec, out int kills) && kills > 1 ? $" [ {CharacterSet.GetContinuousKilling(kills)} ]" : "") + (_earnedMoney.TryGetValue(ec, out int earned) ? $" [ 已赚取 {earned} {General.GameplayEquilibriumConstant.InGameCurrency} ]" : ""); if (top == 1) { WriteLine("冠军:" + topCharacter); @@ -1300,6 +1302,11 @@ namespace Milimoe.FunGame.Core.Api.Utility } } + /// + /// 装备物品 + /// + /// + /// public void Equip(Character character, Item item) { if (character.Equip(item)) @@ -1309,6 +1316,12 @@ namespace Milimoe.FunGame.Core.Api.Utility } } + /// + /// 装备物品到指定栏位 + /// + /// + /// + /// public void Equip(Character character, EquipItemToSlot type, Item item) { if (character.Equip(item, type)) @@ -1317,6 +1330,11 @@ namespace Milimoe.FunGame.Core.Api.Utility } } + /// + /// 取消装备 + /// + /// + /// public void UnEquip(Character character, EquipItemToSlot type) { Item? item = character.UnEquip(type); diff --git a/Model/EquilibriumConstant.cs b/Model/EquilibriumConstant.cs new file mode 100644 index 0000000..ed17e9d --- /dev/null +++ b/Model/EquilibriumConstant.cs @@ -0,0 +1,243 @@ +namespace Milimoe.FunGame.Core.Model +{ + /// + /// 游戏平衡常数 + /// + public class EquilibriumConstant + { + /// + /// 游戏货币名称 + /// + public string InGameCurrency { get; set; } = "金币"; + + /// + /// 晋升点数上限 + /// + public int PromotionThresholdXUpperLimit { get; set; } = 999; + + /// + /// 角色评级 S 的晋升点数上限 + /// + public int PromotionThresholdSUpperLimit { get; set; } = 998; + + /// + /// 角色评级 A+ 的晋升点数上限 + /// + public int PromotionThresholdAPlusUpperLimit { get; set; } = 850; + + /// + /// 角色评级 A 的晋升点数上限 + /// + public int PromotionThresholdAUpperLimit { get; set; } = 700; + + /// + /// 角色评级 B 的晋升点数上限 + /// + public int PromotionThresholdBUpperLimit { get; set; } = 550; + + /// + /// 角色评级 C 的晋升点数上限 + /// + public int PromotionThresholdCUpperLimit { get; set; } = 400; + + /// + /// 角色评级 D 的晋升点数上限 + /// + public int PromotionThresholdDUpperLimit { get; set; } = 300; + + /// + /// 角色评级 E 的晋升点数上限 + /// + public int PromotionThresholdEUpperLimit { get; set; } = 200; + + /// + /// 初始生命值 + /// + public double InitialHP { get; set; } = 60; + + /// + /// 初始魔法值 + /// + public double InitialMP { get; set; } = 10; + + /// + /// 角色最高等级 + /// + public int MaxLevel { get; set; } = 60; + + /// + /// 魔法最高等级 + /// + public int MaxMagicLevel { get; set; } = 8; + + /// + /// 战技最高等级 + /// + public int MaxSkillLevel { get; set; } = 6; + + /// + /// 爆发技最高等级 + /// + public int MaxSuperSkillLevel { get; set; } = 6; + + /// + /// 被动最高等级 + /// + public int MaxPassiveSkillLevel { get; set; } = 6; + + /// + /// 普通攻击最高等级 + /// + public int MaxNormalAttackLevel { get; set; } = 8; + + /// + /// 最大能量值 + /// + public double MaxEP { get; set; } = 200; + + /// + /// 初始攻击力 + /// + public double InitialATK { get; set; } = 15; + + /// + /// 初始物理护甲 + /// + public double InitialDEF { get; set; } = 5; + + /// + /// 初始力量 + /// + public double InitialSTR { get; set; } = 0; + + /// + /// 初始敏捷 + /// + public double InitialAGI { get; set; } = 0; + + /// + /// 初始智力 + /// + public double InitialINT { get; set; } = 0; + + /// + /// 力量成长 + /// + public double STRGrowth { get; set; } = 0; + + /// + /// 敏捷成长 + /// + public double AGIGrowth { get; set; } = 0; + + /// + /// 智力成长 + /// + public double INTGrowth { get; set; } = 0; + + /// + /// 初始暴击率 + /// + public double CritRate { get; set; } = 0.05; + + /// + /// 初始暴击伤害 + /// + public double CritDMG { get; set; } = 1.25; + + /// + /// 初始闪避率 + /// + public double EvadeRate { get; set; } = 0.05; + + /// + /// 每级增加基础生命值 + /// + public double LevelToHPFactor { get; set; } = 17; + + /// + /// 生命值增长因子 + /// + public double HPGrowthFactor { get; set; } = 0.68; + + /// + /// 每级增加基础魔法值 + /// + public double LevelToMPFactor { get; set; } = 1.5; + + /// + /// 魔法值增长因子 + /// + public double MPGrowthFactor { get; set; } = 1.5; + + /// + /// 每级增加基础攻击力 + /// + public double LevelToATKFactor { get; set; } = 0.95; + + /// + /// 攻击力增长因子 + /// + public double ATKGrowthFactor { get; set; } = 0.045; + + /// + /// 物理伤害减免因子 + /// + public double DEFReductionFactor { get; set; } = 120; + + /// + /// 行动速度上限 + /// + public double SPDUpperLimit { get; set; } = 1500; + + /// + /// 每 1 点力量增加生命值 + /// + public double STRtoHPFactor { get; set; } = 9; + + /// + /// 每 1 点力量增加生命回复力 + /// + public double STRtoHRFactor { get; set; } = 0.25; + + /// + /// 每 1 点力量增加物理护甲 + /// + public double STRtoDEFFactor { get; set; } = 0.75; + + /// + /// 每 1 点力量增加暴击伤害 + /// + public double STRtoCritDMGMultiplier { get; set; } = 0.00575; + + /// + /// 每 1 点智力增加魔法值 + /// + public double INTtoMPFactor { get; set; } = 8; + + /// + /// 每 1 点智力增加冷却缩减 + /// + public double INTtoCDRMultiplier { get; set; } = 0.0025; + + /// + /// 每 1 点智力增加魔法回复力 + /// + public double INTtoMRFactor { get; set; } = 0.1; + + /// + /// 每 1 点敏捷增加行动速度 + /// + public double AGItoSPDMultiplier { get; set; } = 0.65; + + /// + /// 每 1 点敏捷增加暴击率 + /// + public double AGItoCritRateMultiplier { get; set; } = 0.0025; + + /// + /// 每 1 点敏捷增加闪避率 + /// + public double AGItoEvadeRateMultiplier { get; set; } = 0.0025; + } +}