From a2fcbce15716347310edaa7c26cf45e2a3ed4b32 Mon Sep 17 00:00:00 2001 From: milimoe <110188673+milimoe@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:19:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=89=B9=E6=95=88=E6=8A=A4?= =?UTF-8?q?=E7=9B=BE=E3=80=81=E6=B7=B7=E5=90=88=E6=8A=A4=E7=9B=BE=E5=80=BC?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E7=B1=BB=E5=9E=8B=E6=8A=A4=E7=9B=BE?= =?UTF-8?q?=E5=80=BC=E7=9A=84=E8=AE=A1=E7=AE=97=E9=80=BB=E8=BE=91=20(#140)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加特效护盾、混合护盾值,优化类型护盾值的计算逻辑 * 附属特效不再强制隐藏 --- Entity/Character/Character.cs | 5 + Entity/Character/Shield.cs | 80 ++++++- Entity/Character/Unit.cs | 30 ++- Entity/Skill/Effect.cs | 38 +++- Entity/Statistics/CharacterStatistics.cs | 2 + .../Common/JsonConverter/ShieldConverter.cs | 4 + Library/Constant/TypeEnum.cs | 9 + Model/GamingQueue.cs | 209 ++++++++++++------ 8 files changed, 298 insertions(+), 79 deletions(-) diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs index 5d698ce..5c368ec 100644 --- a/Entity/Character/Character.cs +++ b/Entity/Character/Character.cs @@ -1346,6 +1346,7 @@ namespace Milimoe.FunGame.Core.Entity List shield = []; if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); @@ -1479,6 +1480,7 @@ namespace Milimoe.FunGame.Core.Entity List shield = []; if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); @@ -1586,6 +1588,7 @@ namespace Milimoe.FunGame.Core.Entity List shield = []; if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); @@ -1638,6 +1641,7 @@ namespace Milimoe.FunGame.Core.Entity List shield = []; if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); @@ -1725,6 +1729,7 @@ namespace Milimoe.FunGame.Core.Entity List shield = []; if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); diff --git a/Entity/Character/Shield.cs b/Entity/Character/Shield.cs index 8cc3654..8901f35 100644 --- a/Entity/Character/Shield.cs +++ b/Entity/Character/Shield.cs @@ -7,6 +7,11 @@ namespace Milimoe.FunGame.Core.Entity /// public class Shield { + /// + /// 绑定到特效的护盾对象。键为特效,值为对应的护盾对象。 + /// + public Dictionary ShieldOfEffects { get; } = []; + /// /// 物理护盾 /// @@ -57,15 +62,20 @@ namespace Milimoe.FunGame.Core.Entity /// public double SpatioTemporal { get; set; } = 0; + /// + /// 混合护盾 + /// + public double Mix { get; set; } = 0; + /// /// 总计物理护盾 /// - public double TotalPhysical => Physical; + public double TotalPhysical => Physical + ShieldOfEffects.Values.Where(soe => !soe.IsMagic && soe.Shield > 0).Sum(soe => soe.Shield); /// /// 总计魔法护盾 /// - public double TotalMagicial => None + Starmark + PurityNatural + PurityContemporary + Bright + Shadow + Element + Aster + SpatioTemporal; + public double TotalMagicial => None + Starmark + PurityNatural + PurityContemporary + Bright + Shadow + Element + Aster + SpatioTemporal + ShieldOfEffects.Values.Where(soe => soe.IsMagic && soe.Shield > 0).Sum(soe => soe.Shield); /// /// 获取或设置护盾值 @@ -73,7 +83,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// /// - public double this[bool isMagic = false, MagicType type = MagicType.None] + public double this[bool isMagic, MagicType type = MagicType.None] { get { @@ -137,7 +147,45 @@ namespace Milimoe.FunGame.Core.Entity } /// - /// 复制一个护盾对象 + /// 添加一个绑定到特效的护盾,注意:如果特效已经存在护盾,则会覆盖原有护盾。 + /// + /// + public void AddShieldOfEffect(ShieldOfEffect soe) + { + ShieldOfEffects[soe.Effect] = soe; + } + + /// + /// 移除某个特效的护盾 + /// + /// + public void RemoveShieldOfEffect(Effect effect) + { + ShieldOfEffects.Remove(effect); + } + + /// + /// 计算并更新特效的护盾值,如果护盾值小于等于 0,则移除该特效的护盾。 + /// + /// + /// + /// + public double CalculateShieldOfEffect(Effect effect, double damage) + { + if (ShieldOfEffects.TryGetValue(effect, out ShieldOfEffect? soe)) + { + soe.Calculate(damage); + if (soe.Shield <= 0) + { + soe.Shield = 0; + ShieldOfEffects.Remove(effect); + } + } + return soe?.Shield ?? 0; + } + + /// + /// 复制一个护盾对象。注意:不会复制绑定到特效的护盾对象。 /// /// public Shield Copy() @@ -153,8 +201,30 @@ namespace Milimoe.FunGame.Core.Entity Shadow = Shadow, Element = Element, Aster = Aster, - SpatioTemporal = SpatioTemporal + SpatioTemporal = SpatioTemporal, + Mix = Mix }; } } + + /// + /// 绑定到特效的护盾对象。这个类没有 JSON 转换器支持。 + /// + /// + /// + /// + /// + public class ShieldOfEffect(Effect effect, double shield, bool isMagic = false, MagicType type = MagicType.None) + { + public Effect Effect { get; } = effect; + public bool IsMagic { get; set; } = isMagic; + public MagicType MagicType { get; set; } = type; + public double Shield { get; set; } = shield; + + public double Calculate(double damage) + { + Shield -= damage; + return Shield; + } + } } diff --git a/Entity/Character/Unit.cs b/Entity/Character/Unit.cs index ba229da..d553f00 100644 --- a/Entity/Character/Unit.cs +++ b/Entity/Character/Unit.cs @@ -54,7 +54,11 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}"); double exHP = ExHP + ExHP2 + ExHP3; - builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + List shield = []; + if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); + if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); double exATK = ExATK + ExATK2 + ExATK3; @@ -177,7 +181,11 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}"); double exHP = ExHP + ExHP2 + ExHP3; - builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + List shield = []; + if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); + if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); double exATK = ExATK + ExATK2 + ExATK3; @@ -274,7 +282,11 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine(ToStringWithLevel()); double exHP = ExHP + ExHP2 + ExHP3; - builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + List shield = []; + if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); + if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); double exATK = ExATK + ExATK2 + ExATK3; @@ -321,7 +333,11 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine(ToStringWithLevel()); double exHP = ExHP + ExHP2 + ExHP3; - builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + List shield = []; + if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); + if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); double exATK = ExATK + ExATK2 + ExATK3; @@ -399,7 +415,11 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}"); double exHP = ExHP + ExHP2 + ExHP3; - builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + List shield = []; + if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); + if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial:0.##}"); + if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}"); + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); double exATK = ExATK + ExATK2 + ExATK3; diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs index 4b01e7c..e02cc55 100644 --- a/Entity/Skill/Effect.cs +++ b/Entity/Skill/Effect.cs @@ -73,7 +73,7 @@ namespace Milimoe.FunGame.Core.Entity /// /// 是否显示在状态栏 /// - public bool ShowInStatusBar => !ForceHideInStatusBar && !IsSubsidiary && (Skill.Item is null || (Durative && Duration > 0) || DurationTurn > 0 || DurativeWithoutDuration); + public bool ShowInStatusBar => !ForceHideInStatusBar && (Skill.Item is null || (Durative && Duration > 0) || DurationTurn > 0 || DurativeWithoutDuration); /// /// 特效是否生效 @@ -659,26 +659,50 @@ namespace Milimoe.FunGame.Core.Entity /// /// /// - /// + /// /// - /// 返回 false 可以阻止后续扣除角色护盾 - public virtual bool BeforeShieldCalculation(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, double shield, ref string message) + /// 返回 false 可以跳过护盾结算 + public virtual bool BeforeShieldCalculation(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, ref double damageReduce, ref string message) { return true; } /// - /// 当角色护盾破碎时 + /// 在角色护盾有效防御时 [ 破碎本身不会触发此钩子,但破碎后化解可触发 ] /// /// /// /// /// /// - /// + /// + public virtual void OnShieldNeutralizeDamage(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, ShieldType shieldType) + { + + } + + /// + /// 当角色护盾破碎时 [ 非绑定特效,只有同种类型的总护盾值小于等于 0 时触发 ] + /// + /// + /// + /// /// /// 返回 false 可以阻止后续扣除角色生命值 - public virtual bool OnShieldBroken(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, double shield, double overFlowing) + public virtual bool OnShieldBroken(Character character, Character attacker, ShieldType type, double overFlowing) + { + return true; + } + + /// + /// 当角色护盾破碎时 [ 绑定特效的护盾值小于等于 0 时便会触发 ] + /// + /// + /// + /// + /// + /// 返回 false 可以阻止后续扣除角色生命值 + public virtual bool OnShieldBroken(Character character, Character attacker, Effect effect, double overFlowing) { return true; } diff --git a/Entity/Statistics/CharacterStatistics.cs b/Entity/Statistics/CharacterStatistics.cs index d13f023..95211e2 100644 --- a/Entity/Statistics/CharacterStatistics.cs +++ b/Entity/Statistics/CharacterStatistics.cs @@ -20,6 +20,8 @@ public double AvgTakenRealDamage { get; set; } = 0; public double TotalHeal { get; set; } = 0; public double AvgHeal { get; set; } = 0; + public double TotalShield { get; set; } = 0; + public double AvgShield { get; set; } = 0; public int LiveRound { get; set; } = 0; public int AvgLiveRound { get; set; } = 0; public int ActionTurn { get; set; } = 0; diff --git a/Library/Common/JsonConverter/ShieldConverter.cs b/Library/Common/JsonConverter/ShieldConverter.cs index b105e6c..9004e73 100644 --- a/Library/Common/JsonConverter/ShieldConverter.cs +++ b/Library/Common/JsonConverter/ShieldConverter.cs @@ -45,6 +45,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter case nameof(Shield.SpatioTemporal): result.SpatioTemporal = reader.GetDouble(); break; + case nameof(Shield.Mix): + result.Mix = reader.GetDouble(); + break; } } @@ -62,6 +65,7 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter writer.WriteNumber(nameof(Shield.Element), value.Element); writer.WriteNumber(nameof(Shield.Aster), value.Aster); writer.WriteNumber(nameof(Shield.SpatioTemporal), value.SpatioTemporal); + writer.WriteNumber(nameof(Shield.Mix), value.Mix); writer.WriteEndObject(); } diff --git a/Library/Constant/TypeEnum.cs b/Library/Constant/TypeEnum.cs index 3e5d73a..828e18a 100644 --- a/Library/Constant/TypeEnum.cs +++ b/Library/Constant/TypeEnum.cs @@ -1030,4 +1030,13 @@ namespace Milimoe.FunGame.Core.Library.Constant All, Special } + + public enum ShieldType + { + None, + Physical, + Magical, + Mix, + Effect + } } diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs index 9d0d794..5fc847c 100644 --- a/Model/GamingQueue.cs +++ b/Model/GamingQueue.cs @@ -591,6 +591,11 @@ namespace Milimoe.FunGame.Core.Model List effects = [.. character.Effects]; foreach (Effect effect in effects) { + if (!character.Shield.ShieldOfEffects.ContainsKey(effect)) + { + character.Shield.RemoveShieldOfEffect(effect); + } + if (effect.Level == 0) { character.Effects.Remove(effect); @@ -1380,7 +1385,8 @@ namespace Milimoe.FunGame.Core.Model // 闪避了就没伤害了 if (damageResult != DamageResult.Evaded) { - // 计算伤害免疫 + // 开始计算伤害免疫 + // 此变量为是否无视免疫 bool ignore = false; // 技能免疫无法免疫普通攻击,但是魔法免疫和物理免疫可以 bool isImmune = (isNormalAttack && (enemy.ImmuneType == ImmuneType.All || enemy.ImmuneType == ImmuneType.Physical || enemy.ImmuneType == ImmuneType.Magical)) || @@ -1422,85 +1428,163 @@ namespace Milimoe.FunGame.Core.Model damageResult = DamageResult.Immune; LastRound.IsImmune[enemy] = true; WriteLine($"[ {enemy} ] 免疫了此伤害!"); + actualDamage = 0; } else { if (damage < 0) damage = 0; - // 检查护盾 - double shield = enemy.Shield[isMagicDamage, magicType]; - string shieldMsg = ""; - if (shield > 0) - { - bool change = false; + string damageType = isMagicDamage ? CharacterSet.GetMagicDamageName(magicType) : "物理伤害"; - // 看特效有没有特殊护盾逻辑 - effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + // 在护盾结算前,特效可以有自己的逻辑 + bool change = false; + string shieldMsg = ""; + effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect in effects) + { + double damageReduce = 0; + if (!effect.BeforeShieldCalculation(enemy, actor, isMagicDamage, magicType, damage, ref damageReduce, ref shieldMsg)) + { + change = true; + } + if (damageReduce != 0) + { + actualDamage -= damageReduce; + if (actualDamage < 0) actualDamage = 0; + } + } + + // 检查护盾 + if (!change) + { + double remain = actualDamage; + + // 检查特效护盾 + effects = [.. enemy.Shield.ShieldOfEffects.Keys]; foreach (Effect effect in effects) { - if (!effect.BeforeShieldCalculation(enemy, actor, isMagicDamage, magicType, damage, shield, ref shieldMsg)) + ShieldOfEffect soe = enemy.Shield.ShieldOfEffects[effect]; + if (soe.IsMagic == isMagicDamage && (!isMagicDamage || soe.MagicType == magicType) && soe.Shield > 0) { - change = true; - } - } - - if (!change) - { - double remain = shield - damage; - if (remain < 0) - { - remain = Math.Abs(remain); - enemy.Shield[isMagicDamage, magicType] = 0; - - change = false; - effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; - foreach (Effect effect in effects) + double effectShield = soe.Shield; + // 判断护盾余额 + if (enemy.Shield.CalculateShieldOfEffect(effect, remain) > 0) { - if (!effect.OnShieldBroken(enemy, actor, isMagicDamage, magicType, damage, shield, remain)) - { - change = true; - } - } - - if (!change) - { - enemy.HP -= remain; - shieldMsg = $"(护盾抵消了 {shield:0.##} 点并破碎,角色承受了 {remain:0.##} 点)"; - actualDamage = remain; + WriteLine($"[ {enemy} ] 发动了 [ {effect.Skill.Name} ] 的护盾效果,抵消了 {remain:0.##} 点{damageType}!"); + remain = 0; } else { - shieldMsg = $"(护盾抵消了 {shield:0.##} 点并破碎,角色没有承受伤害)"; - damageResult = DamageResult.Shield; - actualDamage = 0; + WriteLine($"[ {enemy} ] 发动了 [ {effect.Skill.Name} ] 的护盾效果,抵消了 {effectShield:0.##} 点{damageType},护盾已破碎!"); + remain -= effectShield; + Effect[] effects2 = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect2 in effects2) + { + if (!effect2.OnShieldBroken(enemy, actor, effect, remain)) + { + WriteLine($"[ {(enemy.Effects.Contains(effect2) ? enemy : actor)} ] 因护盾破碎而发动了 [ {effect2.Skill.Name} ],化解了本次伤害!"); + remain = 0; + } + } + } + if (remain <= 0) + { + Effect[] effects2 = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect2 in effects2) + { + effect2.OnShieldNeutralizeDamage(enemy, actor, isMagicDamage, magicType, damage, ShieldType.Effect); + } + break; } } - else - { - enemy.Shield[isMagicDamage, magicType] = remain; - shieldMsg = $"(护盾抵消了 {damage:0.##} 点,剩余可用 {remain:0.##} 点)"; - damageResult = DamageResult.Shield; - actualDamage = 0; - } } - else - { - if (shieldMsg.Trim() == "") - { - shieldMsg = $"(护盾已使其无效化)"; - } - damageResult = DamageResult.Shield; - actualDamage = 0; - } - } - else enemy.HP -= damage; - if (isMagicDamage) - { - string dmgType = CharacterSet.GetMagicDamageName(magicType); - WriteLine($"[ {enemy} ] 受到了 {damage:0.##} 点{dmgType}!{shieldMsg}"); + // 如果伤害仍然大于0,继续检查护盾 + if (remain > 0) + { + // 检查指定类型的护盾值 + double shield = enemy.Shield[isMagicDamage, magicType]; + if (shield > 0) + { + shield -= remain; + string shieldTypeString = isMagicDamage ? "魔法" : "物理"; + ShieldType shieldType = isMagicDamage ? ShieldType.Magical : ShieldType.Physical; + if (shield > 0) + { + WriteLine($"[ {enemy} ] 的{shieldTypeString}护盾抵消了 {remain:0.##} 点{damageType}!"); + enemy.Shield[isMagicDamage, magicType] -= remain; + remain = 0; + effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect in effects) + { + effect.OnShieldNeutralizeDamage(enemy, actor, isMagicDamage, magicType, damage, shieldType); + } + } + else + { + WriteLine($"[ {enemy} ] 的{shieldTypeString}护盾抵消了 {enemy.Shield[isMagicDamage, magicType]:0.##} 点{damageType}并破碎!"); + remain -= enemy.Shield[isMagicDamage, magicType]; + enemy.Shield[isMagicDamage, magicType] = 0; + if (isMagicDamage && enemy.Shield.TotalMagicial <= 0 || !isMagicDamage && enemy.Shield.TotalPhysical <= 0) + { + effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect in effects) + { + if (!effect.OnShieldBroken(enemy, actor, shieldType, remain)) + { + WriteLine($"[ {(enemy.Effects.Contains(effect) ? enemy : actor)} ] 因护盾破碎而发动了 [ {effect.Skill.Name} ],化解了本次伤害!"); + remain = 0; + } + } + } + } + } + + // 检查混合护盾 + if (remain > 0 && enemy.Shield.Mix > 0) + { + shield = enemy.Shield.Mix; + shield -= remain; + if (shield > 0) + { + WriteLine($"[ {enemy} ] 的混合护盾抵消了 {remain:0.##} 点{damageType}!"); + enemy.Shield.Mix -= remain; + remain = 0; + effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect in effects) + { + effect.OnShieldNeutralizeDamage(enemy, actor, isMagicDamage, magicType, damage, ShieldType.Mix); + } + } + else + { + WriteLine($"[ {enemy} ] 的混合护盾抵消了 {enemy.Shield.Mix:0.##} 点{damageType}并破碎!"); + remain -= enemy.Shield.Mix; + enemy.Shield.Mix = 0; + effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; + foreach (Effect effect in effects) + { + if (!effect.OnShieldBroken(enemy, actor, ShieldType.Mix, remain)) + { + WriteLine($"[ {(enemy.Effects.Contains(effect) ? enemy : actor)} ] 因护盾破碎而发动了 [ {effect.Skill.Name} ],化解了本次伤害!"); + remain = 0; + } + } + } + } + } + + actualDamage = remain; } - else WriteLine($"[ {enemy} ] 受到了 {damage:0.##} 点物理伤害!{shieldMsg}"); + + // 统计护盾 + if (damage > actualDamage && _stats.TryGetValue(actor, out CharacterStatistics? stats) && stats != null) + { + stats.TotalShield += damage - actualDamage; + } + + enemy.HP -= actualDamage; + WriteLine($"[ {enemy} ] 受到了 {actualDamage:0.##} 点{damageType}!{shieldMsg}"); // 生命偷取,攻击者为全额 double steal = damage * actor.Lifesteal; @@ -1543,6 +1627,7 @@ namespace Milimoe.FunGame.Core.Model else { LastRound.IsEvaded[enemy] = true; + actualDamage = 0; } await OnDamageToEnemyAsync(actor, enemy, damage, actualDamage, isNormalAttack, isMagicDamage, magicType, damageResult);