diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs
index ee9fa3f..08eb37e 100644
--- a/Entity/Skill/Skill.cs
+++ b/Entity/Skill/Skill.cs
@@ -194,7 +194,7 @@ namespace Milimoe.FunGame.Core.Entity
///
/// 实际魔法消耗 [ 魔法 ]
///
- public double RealMPCost => Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * GameplayEquilibriumConstant.INTtoCastMPReduce)));
+ public double RealMPCost => FreeCostMP ? 0 : Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * GameplayEquilibriumConstant.INTtoCastMPReduce)));
///
/// 魔法消耗 [ 魔法 ]
@@ -202,6 +202,11 @@ namespace Milimoe.FunGame.Core.Entity
[InitOptional]
public virtual double MPCost { get; set; } = 0;
+ ///
+ /// 无魔法消耗 [ 运行时 ]
+ ///
+ public bool FreeCostMP { get; set; } = false;
+
///
/// 吟唱时间 [ 魔法 ]
///
@@ -216,7 +221,7 @@ namespace Milimoe.FunGame.Core.Entity
///
/// 实际能量消耗 [ 战技 ]
///
- public double RealEPCost => CostAllEP ? Math.Max(MinCostEP, Character?.EP ?? MinCostEP) : (IsSuperSkill ? EPCost : Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * GameplayEquilibriumConstant.INTtoCastEPReduce))));
+ public double RealEPCost => FreeCostEP ? 0 : (CostAllEP ? Math.Max(MinCostEP, Character?.EP ?? MinCostEP) : (IsSuperSkill ? EPCost : Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * GameplayEquilibriumConstant.INTtoCastEPReduce)))));
///
/// 能量消耗 [ 战技 ]
@@ -234,6 +239,11 @@ namespace Milimoe.FunGame.Core.Entity
///
public virtual double MinCostEP { get; set; } = 100;
+ ///
+ /// 无能量消耗 [ 运行时 ]
+ ///
+ public bool FreeCostEP { get; set; } = false;
+
///
/// 上一次释放此技能消耗的魔法 [ 魔法 ]
///
@@ -247,7 +257,7 @@ namespace Milimoe.FunGame.Core.Entity
///
/// 实际冷却时间
///
- public double RealCD => Math.Max(0, CD * (1 - (Character?.CDR ?? 0)));
+ public double RealCD => InstantReset ? 0 : Math.Max(0, CD * (1 - (Character?.CDR ?? 0)));
///
/// 冷却时间
@@ -260,6 +270,11 @@ namespace Milimoe.FunGame.Core.Entity
///
public double CurrentCD { get; set; } = 0;
+ ///
+ /// 无 CD [ 运行时 ]
+ ///
+ public bool InstantReset { get; set; } = false;
+
///
/// 硬直时间
///
@@ -281,6 +296,25 @@ namespace Milimoe.FunGame.Core.Entity
///
public double RealHardnessTime => Math.Max(0, (HardnessTime + ExHardnessTime) * (1 + ExHardnessTime2) * (1 - Calculation.PercentageCheck(Character?.ActionCoefficient ?? 0)));
+ ///
+ /// 魔法瓶颈 [ 智力相关 ]
+ ///
+ public virtual double MagicBottleneck { get; set; } = 0;
+
+ ///
+ /// 魔法效能% [ 智力相关 ] 公式:魔法效能 = (角色智力 / 魔法瓶颈) ^ (魔法瓶颈 / 角色智力)
+ /// 该值决定魔法的实际施展效果(乘算),低于 1 时会使效果低于预期,最多增长至 2 倍
+ ///
+ public double MagicEfficacy
+ {
+ get
+ {
+ if (MagicBottleneck == 0) return 1.0;
+ if (Character is null || Character.INT == 0) return 0.01;
+ return Math.Clamp(Math.Pow((Character.INT / MagicBottleneck), (MagicBottleneck / Character.INT)), 0.01, 2.0);
+ }
+ }
+
///
/// 效果列表
///
@@ -858,8 +892,12 @@ namespace Milimoe.FunGame.Core.Entity
skill.MPCost = skillDefined.MPCost;
skill.CastTime = skillDefined.CastTime;
skill.EPCost = skillDefined.EPCost;
+ skill.FreeCostMP = skillDefined.FreeCostMP;
+ skill.FreeCostEP = skillDefined.FreeCostEP;
skill.CD = skillDefined.CD;
+ skill.InstantReset = skillDefined.InstantReset;
skill.HardnessTime = skillDefined.HardnessTime;
+ skill.MagicBottleneck = skillDefined.MagicBottleneck;
skill.GamingQueue = skillDefined.GamingQueue;
if (skill is OpenSkill)
{
diff --git a/Library/Common/JsonConverter/SkillConverter.cs b/Library/Common/JsonConverter/SkillConverter.cs
index 9acf066..3aa325f 100644
--- a/Library/Common/JsonConverter/SkillConverter.cs
+++ b/Library/Common/JsonConverter/SkillConverter.cs
@@ -71,6 +71,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.MPCost):
result.MPCost = reader.GetDouble();
break;
+ case nameof(Skill.FreeCostMP):
+ result.FreeCostMP = reader.GetBoolean();
+ break;
case nameof(Skill.EPCost):
result.EPCost = reader.GetDouble();
break;
@@ -80,6 +83,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.MinCostEP):
result.MinCostEP = reader.GetDouble();
break;
+ case nameof(Skill.FreeCostEP):
+ result.FreeCostEP = reader.GetBoolean();
+ break;
case nameof(Skill.CastTime):
result.CastTime = reader.GetDouble();
break;
@@ -89,6 +95,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.CurrentCD):
result.CurrentCD = reader.GetDouble();
break;
+ case nameof(Skill.InstantReset):
+ result.InstantReset = reader.GetBoolean();
+ break;
case nameof(Skill.HardnessTime):
result.HardnessTime = reader.GetDouble();
break;
@@ -98,6 +107,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.ExHardnessTime2):
result.ExHardnessTime2 = reader.GetDouble();
break;
+ case nameof(Skill.MagicBottleneck):
+ result.MagicBottleneck = reader.GetDouble();
+ break;
case nameof(Skill.Effects):
HashSet effects = NetworkUtility.JsonDeserialize>(ref reader, options) ?? [];
foreach (Effect effect in effects)
@@ -141,15 +153,19 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
if (!value.Enable) writer.WriteBoolean(nameof(Skill.Enable), value.Enable);
if (value.IsInEffect) writer.WriteBoolean(nameof(Skill.IsInEffect), value.IsInEffect);
if (value.MPCost > 0) writer.WriteNumber(nameof(Skill.MPCost), value.MPCost);
+ if (!value.FreeCostMP) writer.WriteBoolean(nameof(Skill.FreeCostMP), value.FreeCostMP);
if (value.EPCost > 0) writer.WriteNumber(nameof(Skill.EPCost), value.EPCost);
if (value.CostAllEP) writer.WriteBoolean(nameof(Skill.CostAllEP), value.CostAllEP);
if (value.MinCostEP > 0) writer.WriteNumber(nameof(Skill.MinCostEP), value.MinCostEP);
+ if (!value.FreeCostEP) writer.WriteBoolean(nameof(Skill.FreeCostEP), value.FreeCostEP);
if (value.CastTime > 0) writer.WriteNumber(nameof(Skill.CastTime), value.CastTime);
if (value.CD > 0) writer.WriteNumber(nameof(Skill.CD), value.CD);
if (value.CurrentCD > 0) writer.WriteNumber(nameof(Skill.CurrentCD), value.CurrentCD);
+ if (!value.InstantReset) writer.WriteBoolean(nameof(Skill.InstantReset), value.InstantReset);
if (value.HardnessTime > 0) writer.WriteNumber(nameof(Skill.HardnessTime), value.HardnessTime);
if (value.ExHardnessTime != 0) writer.WriteNumber(nameof(Skill.ExHardnessTime), value.ExHardnessTime);
if (value.ExHardnessTime2 != 0) writer.WriteNumber(nameof(Skill.ExHardnessTime2), value.ExHardnessTime2);
+ if (value.MagicBottleneck != 0) writer.WriteNumber(nameof(Skill.MagicBottleneck), value.MagicBottleneck);
writer.WritePropertyName(nameof(Skill.Effects));
JsonSerializer.Serialize(writer, value.Effects, options);
writer.WritePropertyName(nameof(Skill.Values));