diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs
index badd996..9789a2c 100644
--- a/Entity/Skill/Effect.cs
+++ b/Entity/Skill/Effect.cs
@@ -455,7 +455,20 @@ namespace Milimoe.FunGame.Core.Entity
}
///
- /// 在技能释放前触发
+ /// 在技能释放前触发 [ 技能的特效组 ]
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void BeforeSkillCasted(Character caster, List targets, List grids, double mpCost = 0, double epCost = 0)
+ {
+
+ }
+
+ ///
+ /// 在技能释放前触发 [ 状态栏特效 ]
///
///
///
@@ -468,6 +481,17 @@ namespace Milimoe.FunGame.Core.Entity
return true;
}
+ ///
+ /// 在技能释放后触发 [ 技能的特效组 ]
+ ///
+ ///
+ ///
+ ///
+ public virtual void AfterSkillCasted(Character caster, List targets, List grids)
+ {
+
+ }
+
///
/// 在时间流逝期间应用生命/魔法回复前修改 [ 允许取消回复 ]
///
@@ -1051,21 +1075,24 @@ namespace Milimoe.FunGame.Core.Entity
///
///
///
- public DamageResult DamageToEnemy(Character actor, Character enemy, DamageType damageType, MagicType magicType, double expectedDamage, DamageCalculationOptions? options = null)
+ public DamageRecord DamageToEnemy(Character actor, Character enemy, DamageType damageType, MagicType magicType, double expectedDamage, DamageCalculationOptions? options = null)
{
- if (GamingQueue is null) return DamageResult.Evaded;
- int changeCount = 0;
- DamageResult result = DamageResult.Normal;
- double damage = expectedDamage;
- options ??= new(actor);
- options.Skill = Skill;
- if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage;
- if (options.NeedCalculate && damageType != DamageType.True)
+ if (GamingQueue != null)
{
- result = damageType == DamageType.Physical ? GamingQueue.CalculatePhysicalDamage(actor, enemy, false, expectedDamage, out damage, ref changeCount, ref options) : GamingQueue.CalculateMagicalDamage(actor, enemy, false, MagicType, expectedDamage, out damage, ref changeCount, ref options);
+ int changeCount = 0;
+ DamageResult result = DamageResult.Normal;
+ double damage = expectedDamage;
+ options ??= new(actor);
+ options.Skill = Skill;
+ if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage;
+ if (options.NeedCalculate && damageType != DamageType.True)
+ {
+ result = damageType == DamageType.Physical ? GamingQueue.CalculatePhysicalDamage(actor, enemy, false, expectedDamage, out damage, ref changeCount, ref options) : GamingQueue.CalculateMagicalDamage(actor, enemy, false, MagicType, expectedDamage, out damage, ref changeCount, ref options);
+ }
+ GamingQueue.DamageToEnemy(actor, enemy, damage, false, damageType, magicType, result, options);
+ return options?.GetDamageRecord(damageType, result) ?? new();
}
- GamingQueue.DamageToEnemy(actor, enemy, damage, false, damageType, magicType, result, options);
- return result;
+ return new();
}
///
diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs
index 590ec86..f914cb8 100644
--- a/Entity/Skill/Skill.cs
+++ b/Entity/Skill/Skill.cs
@@ -385,6 +385,10 @@ namespace Milimoe.FunGame.Core.Entity
SkillType = type;
CastAnywhere = SkillType == SkillType.Magic;
Character = character;
+ if (SkillType == SkillType.SuperSkill)
+ {
+ EPCost = 100;
+ }
}
///
@@ -712,7 +716,7 @@ namespace Milimoe.FunGame.Core.Entity
public void OnSkillCasting(IGamingQueue queue, Character caster, List targets, List grids)
{
GamingQueue = queue;
- foreach (Effect e in Effects)
+ foreach (Effect e in Effects.OrderByDescending(e => e.Priority))
{
e.GamingQueue = GamingQueue;
e.OnSkillCasting(caster, targets, grids);
@@ -722,10 +726,15 @@ namespace Milimoe.FunGame.Core.Entity
///
/// 技能效果触发前
///
- public void BeforeSkillCasted()
+ public void BeforeSkillCasted(Character caster, List targets, List grids)
{
LastCostMP = RealMPCost;
LastCostEP = RealEPCost;
+ foreach (Effect e in Effects.OrderByDescending(e => e.Priority))
+ {
+ e.GamingQueue = GamingQueue;
+ e.BeforeSkillCasted(caster, targets, grids, LastCostMP, LastCostEP);
+ }
}
///
@@ -762,13 +771,25 @@ namespace Milimoe.FunGame.Core.Entity
}
}
}
- foreach (Effect e in Effects)
+ foreach (Effect e in Effects.OrderByDescending(e => e.Priority))
{
e.GamingQueue = GamingQueue;
e.OnSkillCasted(caster, targets, grids, Values);
}
}
+ ///
+ /// 技能效果触发后
+ ///
+ public void AfterSkillCasted(Character caster, List targets, List grids)
+ {
+ foreach (Effect e in Effects.OrderByDescending(e => e.Priority))
+ {
+ e.GamingQueue = GamingQueue;
+ e.AfterSkillCasted(caster, targets, grids);
+ }
+ }
+
///
/// 对目标触发技能效果
///
@@ -776,7 +797,7 @@ namespace Milimoe.FunGame.Core.Entity
///
public void OnSkillCasted(User user, List targets)
{
- foreach (Effect e in Effects)
+ foreach (Effect e in Effects.OrderByDescending(e => e.Priority))
{
e.OnSkillCasted(user, targets, Values);
}
diff --git a/Library/Common/Addon/Example/ExampleSkill.cs b/Library/Common/Addon/Example/ExampleSkill.cs
index c443e1d..c506f02 100644
--- a/Library/Common/Addon/Example/ExampleSkill.cs
+++ b/Library/Common/Addon/Example/ExampleSkill.cs
@@ -324,7 +324,7 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
character.ExATK2 += ActualATKBonus;
character.PhysicalPenetration += ActualPhysicalPenetrationBonus;
character.ExEvadeRate += ActualEvadeRateBonus;
- if (character.Effects.FirstOrDefault(e => e is ExamplePassiveSkillEffect) is ExamplePassiveSkillEffect e)
+ if (character.Effects.FirstOrDefault(e => e is ExamplePassiveSkillEffect && e.Skill.Character == character) is ExamplePassiveSkillEffect e)
{
e.CD = 3;
if (e.CurrentCD > e.CD) e.CurrentCD = e.CD;
@@ -337,7 +337,7 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
character.ExATK2 -= ActualATKBonus;
character.PhysicalPenetration -= ActualPhysicalPenetrationBonus;
character.ExEvadeRate -= ActualEvadeRateBonus;
- if (character.Effects.FirstOrDefault(e => e is ExamplePassiveSkillEffect) is ExamplePassiveSkillEffect e)
+ if (character.Effects.FirstOrDefault(e => e is ExamplePassiveSkillEffect && e.Skill.Character == character) is ExamplePassiveSkillEffect e)
{
e.CD = 10;
}
diff --git a/Model/DamageCalculationOptions.cs b/Model/DamageCalculationOptions.cs
index 9e38a6a..450a5a2 100644
--- a/Model/DamageCalculationOptions.cs
+++ b/Model/DamageCalculationOptions.cs
@@ -1,4 +1,5 @@
using Milimoe.FunGame.Core.Entity;
+using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Model
{
@@ -74,6 +75,11 @@ namespace Milimoe.FunGame.Core.Model
/** == 调试数据记录 == **/
+ ///
+ /// 生成伤害记录
+ ///
+ public DamageRecord GetDamageRecord(DamageType type, DamageResult result) => new(type, result, ExpectedDamage, BeforeDamageBonus, CriticalDamage, DefenseReduction, AfterDamageBonus, MagicEfficacyDamage, FinalDamage, ShieldReduction, ActualDamage);
+
///
/// 伤害基底(期望)
///
diff --git a/Model/DamageRecord.cs b/Model/DamageRecord.cs
new file mode 100644
index 0000000..1dac148
--- /dev/null
+++ b/Model/DamageRecord.cs
@@ -0,0 +1,100 @@
+using Milimoe.FunGame.Core.Entity;
+using Milimoe.FunGame.Core.Library.Constant;
+
+namespace Milimoe.FunGame.Core.Model
+{
+ ///
+ /// 记录所有伤害的组成部分
+ ///
+ public readonly struct DamageRecord
+ {
+ ///
+ /// 记录所有伤害的组成部分
+ ///
+ public DamageRecord()
+ {
+ ExpectedDamage = 0;
+ BeforeDamageBonus = [];
+ CriticalDamage = 0;
+ DefenseReduction = 0;
+ AfterDamageBonus = [];
+ MagicEfficacyDamage = 0;
+ FinalDamage = 0;
+ ShieldReduction = 0;
+ ActualDamage = 0;
+ }
+
+ ///
+ /// 记录所有伤害的组成部分
+ ///
+ public DamageRecord(DamageType type, DamageResult result, double expectedDamage, Dictionary beforeDamageBonus, double criticalDamage, double defenseReduction, Dictionary afterDamageBonus, double magicEfficacyDamage, double finalDamage, double shieldReduction, double actualDamage)
+ {
+ DamageType = type;
+ DamageResult = result;
+ ExpectedDamage = expectedDamage;
+ BeforeDamageBonus = beforeDamageBonus;
+ CriticalDamage = criticalDamage;
+ DefenseReduction = defenseReduction;
+ AfterDamageBonus = afterDamageBonus;
+ MagicEfficacyDamage = magicEfficacyDamage;
+ FinalDamage = finalDamage;
+ ShieldReduction = shieldReduction;
+ ActualDamage = actualDamage;
+ }
+
+ ///
+ /// 伤害类型
+ ///
+ public DamageType DamageType { get; } = DamageType.Physical;
+
+ ///
+ /// 伤害结果
+ ///
+ public DamageResult DamageResult { get; } = DamageResult.Normal;
+
+ ///
+ /// 伤害基底(期望)
+ ///
+ public double ExpectedDamage { get; }
+
+ ///
+ /// 特效伤害加成记录(乘区1:暴击和减伤计算前)
+ ///
+ public Dictionary BeforeDamageBonus { get; }
+
+ ///
+ /// 暴击伤害
+ ///
+ public double CriticalDamage { get; }
+
+ ///
+ /// 伤害减免
+ ///
+ public double DefenseReduction { get; }
+
+ ///
+ /// 特效伤害加成记录(乘区2:暴击和减伤计算后)
+ ///
+ public Dictionary AfterDamageBonus { get; }
+
+ ///
+ /// 魔法效能修正
+ ///
+ public double MagicEfficacyDamage { get; }
+
+ ///
+ /// 最终伤害
+ ///
+ public double FinalDamage { get; }
+
+ ///
+ /// 护盾减免
+ ///
+ public double ShieldReduction { get; }
+
+ ///
+ /// 实际造成伤害
+ ///
+ public double ActualDamage { get; }
+ }
+}
diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs
index a53ee69..ae57b98 100644
--- a/Model/GamingQueue.cs
+++ b/Model/GamingQueue.cs
@@ -1583,7 +1583,7 @@ namespace Milimoe.FunGame.Core.Model
effect.AfterCharacterStartCasting(character, skill, targets);
}
- skill.BeforeSkillCasted();
+ skill.BeforeSkillCasted(character, targets, grids);
character.EP -= cost;
baseTime += skill.RealHardnessTime;
@@ -1596,6 +1596,8 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
+ skill.AfterSkillCasted(character, targets, grids);
+
effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
@@ -1659,7 +1661,7 @@ namespace Milimoe.FunGame.Core.Model
LastRound.ActionTypes.Add(CharacterActionType.CastSkill);
_castingSkills.Remove(character);
- skill.BeforeSkillCasted();
+ skill.BeforeSkillCasted(character, targets, grids);
character.MP -= cost;
baseTime += skill.RealHardnessTime;
@@ -1672,6 +1674,8 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
+ skill.AfterSkillCasted(character, targets, grids);
+
effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
@@ -1730,7 +1734,7 @@ namespace Milimoe.FunGame.Core.Model
CheckSkilledImmune(character, targets, skill);
LastRound.Targets[CharacterActionType.CastSuperSkill] = [.. targets];
- skill.BeforeSkillCasted();
+ skill.BeforeSkillCasted(character, targets, grids);
character.EP -= cost;
baseTime += skill.RealHardnessTime;
@@ -1744,6 +1748,8 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
+ skill.AfterSkillCasted(character, targets, grids);
+
effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
@@ -3106,7 +3112,7 @@ namespace Milimoe.FunGame.Core.Model
effect.AfterCharacterStartCasting(character, skill, targets);
}
- skill.BeforeSkillCasted();
+ skill.BeforeSkillCasted(character, targets, grids);
skill.CurrentCD = skill.RealCD;
skill.Enable = false;
@@ -3135,6 +3141,8 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
+ skill.AfterSkillCasted(character, targets, grids);
+
effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
diff --git a/Model/PrefabricatedEntity/CourageCommandSkill.cs b/Model/PrefabricatedEntity/CourageCommandSkill.cs
index c138fa0..10dc3b1 100644
--- a/Model/PrefabricatedEntity/CourageCommandSkill.cs
+++ b/Model/PrefabricatedEntity/CourageCommandSkill.cs
@@ -1,11 +1,12 @@
using Milimoe.FunGame.Core.Entity;
+using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Model.PrefabricatedEntity
{
///
/// 继承此类以表示勇气指令技能
///
- public class CourageCommandSkill(long id, string name, Dictionary args, Character? character = null) : OpenSkill(id, name, args, character)
+ public abstract class CourageCommandSkill(Character? character = null) : Skill(SkillType.Skill, character)
{
}
diff --git a/Model/PrefabricatedEntity/MagicCardPack.cs b/Model/PrefabricatedEntity/MagicCardPack.cs
index d19a338..3db5bff 100644
--- a/Model/PrefabricatedEntity/MagicCardPack.cs
+++ b/Model/PrefabricatedEntity/MagicCardPack.cs
@@ -6,7 +6,7 @@ namespace Milimoe.FunGame.Core.Model.PrefabricatedEntity
///
/// 魔法卡包的基础实现
///
- public class MagicCardPack : OpenItem
+ public class MagicCardPack : Item
{
public override ItemType ItemType => ItemType.MagicCardPack;
@@ -50,10 +50,12 @@ namespace Milimoe.FunGame.Core.Model.PrefabricatedEntity
///
private PrimaryAttribute _originalAttribute = PrimaryAttribute.None;
- public MagicCardPack(long id, string name, Dictionary args) : base(id, name, args)
+ public MagicCardPack(Dictionary? args = null) : base(ItemType.MagicCardPack)
{
+ args ??= [];
foreach (string key in args.Keys)
{
+ Others[key] = args[key];
switch (key.ToLower())
{
case "exstr":
diff --git a/Model/PrefabricatedEntity/NeuralCalibrationEffect.cs b/Model/PrefabricatedEntity/NeuralCalibrationEffect.cs
index d238f12..da06890 100644
--- a/Model/PrefabricatedEntity/NeuralCalibrationEffect.cs
+++ b/Model/PrefabricatedEntity/NeuralCalibrationEffect.cs
@@ -6,7 +6,7 @@ namespace Milimoe.FunGame.Core.Model.PrefabricatedEntity
///
/// 继承此类以表示神经校准特效
///
- public class NeuralCalibrationEffect : Effect
+ public abstract class NeuralCalibrationEffect : Effect
{
public WeaponType SupportedWeaponType { get; set; } = WeaponType.None;
}
diff --git a/Model/PrefabricatedEntity/SoulboundSkill.cs b/Model/PrefabricatedEntity/SoulboundSkill.cs
index b589668..60fa8d3 100644
--- a/Model/PrefabricatedEntity/SoulboundSkill.cs
+++ b/Model/PrefabricatedEntity/SoulboundSkill.cs
@@ -1,18 +1,62 @@
using Milimoe.FunGame.Core.Entity;
+using Milimoe.FunGame.Core.Library.Common.Addon;
+using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Model.PrefabricatedEntity
{
///
/// 继承此类以表示灵魂绑定技能
///
- public class SoulboundSkill(long id, string name, Dictionary args, Character? character = null) : OpenSkill(id, name, args, character)
+ ///
+ /// 灵魂绑定:一个至少消耗 100 能量、每额外消耗 20 能量效果增强 10% 的爆发技
+ ///
+ ///
+ public abstract class SoulboundSkill(Character? character = null) : Skill(SkillType.SuperSkill, character)
{
public override bool CostAllEP => true;
public override double MinCostEP => 100;
+ }
+
+ ///
+ /// 灵魂绑定专有特效
+ ///
+ public abstract class SoulboundEffect(SoulboundSkill skill) : Effect(skill)
+ {
+ ///
+ /// 所属的灵魂绑定技能
+ ///
+ public SoulboundSkill SoulboundSkill => skill;
///
- /// 每额外消耗 20 能量效果增强 10%
+ /// 增强系数,每额外消耗 20 能量效果增强 10%
///
- public virtual double Improvement => (LastCostEP - MinCostEP) / 20 * 0.1;
+ public double Improvement
+ {
+ get
+ {
+ double improvement = 0;
+ if (_improvement != null)
+ {
+ improvement = _improvement.Value;
+ }
+ else if (Skill.Character != null)
+ {
+ improvement = (Skill.Character.EP - skill.MinCostEP) / 20.0 * 0.1;
+ }
+ return improvement;
+ }
+ }
+
+ private double? _improvement = null;
+
+ public override void BeforeSkillCasted(Character caster, List targets, List grids, double mpCost = 0, double epCost = 0)
+ {
+ _improvement = (epCost - skill.MinCostEP) / 20.0 * 0.1;
+ }
+
+ public override void AfterSkillCasted(Character caster, List targets, List grids)
+ {
+ _improvement = null;
+ }
}
}