From 4bd706c43c44cc0c3e16b900adde5d5ba0bb1333 Mon Sep 17 00:00:00 2001 From: milimoe Date: Mon, 19 Jan 2026 01:34:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=93=B6=E9=A2=88=E5=92=8C?= =?UTF-8?q?=E6=95=88=E8=83=BD=EF=BC=9B=E4=BF=AE=E5=A4=8D=E8=A3=85=E5=A4=87?= =?UTF-8?q?=E4=B8=BB=E5=8A=A8=E6=8A=80=E8=83=BD=E6=97=A0=E6=B3=95=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Entity/Skill/Effect.cs | 5 +++- Entity/Skill/Skill.cs | 23 ++++++++++++----- Model/DamageCalculationOptions.cs | 41 ++++++++++++++++++++++++++++-- Model/GamingQueue.cs | 42 ++++++++++++++++++++++++++----- 4 files changed, 96 insertions(+), 15 deletions(-) diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs index 43befac..7b87ec0 100644 --- a/Entity/Skill/Effect.cs +++ b/Entity/Skill/Effect.cs @@ -981,7 +981,10 @@ namespace Milimoe.FunGame.Core.Entity int changeCount = 0; DamageResult result = DamageResult.Normal; double damage = expectedDamage; - options ??= new(); + options ??= new(actor) + { + Skill = Skill + }; if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage; if (options.NeedCalculate && damageType != DamageType.True) { diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs index 08eb37e..2d51983 100644 --- a/Entity/Skill/Skill.cs +++ b/Entity/Skill/Skill.cs @@ -299,19 +299,29 @@ namespace Milimoe.FunGame.Core.Entity /// /// 魔法瓶颈 [ 智力相关 ] /// - public virtual double MagicBottleneck { get; set; } = 0; + public virtual double MagicBottleneck + { + get + { + return Math.Max(0, field); + } + set + { + field = Math.Max(0, value); + } + } /// - /// 魔法效能% [ 智力相关 ] 公式:魔法效能 = (角色智力 / 魔法瓶颈) ^ (魔法瓶颈 / 角色智力) - /// 该值决定魔法的实际施展效果(乘算),低于 1 时会使效果低于预期,最多增长至 2 倍 + /// 魔法效能% [ 智力相关 ] 该值决定魔法的实际施展效果(乘算),低于 1 时会使效果低于预期,最多增长至 2 倍 + /// 计算方法:以魔法瓶颈为100%,智力每低于瓶颈的 1%,效能就减少 1%,反之提升 /// 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); + if (MagicBottleneck == 0 || Character is null) return 1.0; + double percentageDiff = (Character.INT - MagicBottleneck) / MagicBottleneck; + return Math.Clamp(1.0 + percentageDiff, 0.01, 2.0); } } @@ -810,6 +820,7 @@ namespace Milimoe.FunGame.Core.Entity { if (IsMagic) { + if (MagicBottleneck > 0) builder.AppendLine($"魔法瓶颈:{MagicBottleneck:0.##}{(Character != null ? $"({MagicEfficacy * 100:0.##}%)" : "")}"); builder.AppendLine($"魔法消耗:{RealMPCost:0.##}{(showOriginal && RealMPCost != MPCost ? $"(原始值:{MPCost:0.##})" : "")}"); builder.AppendLine($"吟唱时间:{RealCastTime:0.##}{(showOriginal && RealCastTime != CastTime ? $"(原始值:{CastTime:0.##})" : "")}"); } diff --git a/Model/DamageCalculationOptions.cs b/Model/DamageCalculationOptions.cs index 52f0b26..d0aa5ce 100644 --- a/Model/DamageCalculationOptions.cs +++ b/Model/DamageCalculationOptions.cs @@ -3,10 +3,15 @@ namespace Milimoe.FunGame.Core.Model { /// - /// 精准的分步控制伤害计算 + /// 精准的分步控制伤害计算选项 /// - public class DamageCalculationOptions + public class DamageCalculationOptions(Character character) { + /// + /// 伤害来源 + /// + public Character Character { get; set; } = character; + /// /// 完整计算伤害 /// @@ -42,6 +47,33 @@ namespace Milimoe.FunGame.Core.Model /// public bool IgnoreImmune { get; set; } = false; + /// + /// 如果来源是技能 + /// + public Skill? Skill { get; set; } = null; + + /// + /// 是魔法技能 + /// + public bool IsMagicSkill => Skill?.IsMagic ?? false; + + /// + /// 魔法瓶颈 + /// + public double MagicBottleneck => IsMagicSkill ? (Skill?.MagicBottleneck ?? 0) : 0; + + /// + /// 魔法效能% + /// + public double MagicEfficacy => IsMagicSkill ? (Skill?.MagicEfficacy ?? 1) : 1; + + /// + /// 施法者智力 + /// + public double INT => Character.INT; + + /** == 调试数据记录 == **/ + /// /// 伤害基底(期望) /// @@ -67,6 +99,11 @@ namespace Milimoe.FunGame.Core.Model /// internal Dictionary AfterDamageBonus { get; set; } = []; + /// + /// 魔法效能修正 + /// + internal double MagicEfficacyDamage { get; set; } = 0; + /// /// 最终伤害 /// diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs index 7d8c05c..4b9f2e7 100644 --- a/Model/GamingQueue.cs +++ b/Model/GamingQueue.cs @@ -1002,7 +1002,9 @@ namespace Milimoe.FunGame.Core.Model return _isGameEnd; } - foreach (Skill skillTurnStart in skills) + List skillsTurnStart = [.. character.Skills]; + AddCharacterEquipSlotSkills(character, skillsTurnStart); + foreach (Skill skillTurnStart in skillsTurnStart) { skillTurnStart.OnTurnStart(character, selectableEnemys, selectableTeammates, skills, items); } @@ -2060,7 +2062,7 @@ namespace Milimoe.FunGame.Core.Model List characters = [actor, enemy]; bool isEvaded = damageResult == DamageResult.Evaded; List effects = []; - options ??= new(); + options ??= new(actor); if (options.ExpectedDamage == 0) options.ExpectedDamage = damage; Dictionary totalDamageBonus = []; @@ -2094,6 +2096,14 @@ namespace Milimoe.FunGame.Core.Model } } options.AfterDamageBonus = totalDamageBonus; + + // 魔法效能乘区 + if (options.IsMagicSkill) + { + options.MagicEfficacyDamage = damage * (options.MagicEfficacy - 1); + damage *= options.MagicEfficacy; + } + options.FinalDamage = damage; double actualDamage = damage; @@ -2351,8 +2361,9 @@ namespace Milimoe.FunGame.Core.Model { strAfterBonus = string.Join("", options.AfterDamageBonus.Select(kv => $"{(kv.Value >= 0 ? " + " : " - ")}{Math.Abs(kv.Value):0.##}({kv.Key.Name})")); } + string strMagicEfficacyDamage = options.MagicEfficacyDamage == 0 ? "" : ($"{(options.MagicEfficacyDamage >= 0 ? " + " : " - ")}{Math.Abs(options.MagicEfficacyDamage):0.##}(魔法效能:{options.MagicEfficacy * 100:0.##}%)"); string strShieldReduction = options.ShieldReduction == 0 ? "" : ($"{(options.ShieldReduction >= 0 ? " - " : " + ")}{Math.Abs(options.ShieldReduction):0.##}(护盾)"); - strDamageMessage += $"【{options.ExpectedDamage:0.##}(基础){strBeforeBonus}{strDefenseReduction}{strCriticalDamage}{strAfterBonus}{strShieldReduction} = {options.ActualDamage:0.##} 点{damageTypeString}】"; + strDamageMessage += $"【{options.ExpectedDamage:0.##}(基础){strBeforeBonus}{strDefenseReduction}{strCriticalDamage}{strAfterBonus}{strMagicEfficacyDamage}{strShieldReduction} = {options.ActualDamage:0.##} 点{damageTypeString}】"; } WriteLine(strDamageMessage); @@ -2796,6 +2807,21 @@ namespace Milimoe.FunGame.Core.Model #region 回合内-辅助方法 + /// + /// 将角色装备栏中的主动技能加入列表 + /// + /// + /// + public static void AddCharacterEquipSlotSkills(Character character, List list) + { + if (character.EquipSlot.MagicCardPack?.Skills.Active != null) list.Add(character.EquipSlot.MagicCardPack.Skills.Active); + if (character.EquipSlot.Weapon?.Skills.Active != null) list.Add(character.EquipSlot.Weapon.Skills.Active); + if (character.EquipSlot.Armor?.Skills.Active != null) list.Add(character.EquipSlot.Armor.Skills.Active); + if (character.EquipSlot.Shoes?.Skills.Active != null) list.Add(character.EquipSlot.Shoes.Skills.Active); + if (character.EquipSlot.Accessory1?.Skills.Active != null) list.Add(character.EquipSlot.Accessory1.Skills.Active); + if (character.EquipSlot.Accessory2?.Skills.Active != null) list.Add(character.EquipSlot.Accessory2.Skills.Active); + } + /// /// 取得回合开始时必需的列表 /// @@ -2809,7 +2835,11 @@ namespace Milimoe.FunGame.Core.Model List selectableEnemys = [.. allEnemys.Where(c => _queue.Contains(c) && !c.IsUnselectable)]; // 技能列表 - List skills = [.. character.Skills.Where(s => s.Level > 0 && s.SkillType != SkillType.Passive && s.Enable && !s.IsInEffect && s.CurrentCD == 0 && + List skills = [.. character.Skills]; + + // 将角色装备栏中的主动技能加入技能列表以供筛选 + AddCharacterEquipSlotSkills(character, skills); + skills = [.. 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))]; // 物品列表 @@ -3295,7 +3325,7 @@ namespace Milimoe.FunGame.Core.Model /// public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage, ref int changeCount, ref DamageCalculationOptions? options) { - options ??= new(); + options ??= new(actor); if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage; List characters = [actor, enemy]; DamageType damageType = DamageType.Physical; @@ -3429,7 +3459,7 @@ namespace Milimoe.FunGame.Core.Model /// public DamageResult CalculateMagicalDamage(Character actor, Character enemy, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage, ref int changeCount, ref DamageCalculationOptions? options) { - options ??= new(); + options ??= new(actor); if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage; List characters = [actor, enemy]; DamageType damageType = DamageType.Magical;