添加特效护盾、混合护盾值,优化类型护盾值的计算逻辑 (#140)

* 添加特效护盾、混合护盾值,优化类型护盾值的计算逻辑

* 附属特效不再强制隐藏
This commit is contained in:
milimoe 2025-06-18 21:19:52 +08:00 committed by GitHub
parent 17914f1128
commit a2fcbce157
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 298 additions and 79 deletions

View File

@ -1346,6 +1346,7 @@ namespace Milimoe.FunGame.Core.Entity
List<string> 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<string> 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<string> 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<string> 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<string> 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.##}]" : ""));

View File

@ -7,6 +7,11 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public class Shield
{
/// <summary>
/// 绑定到特效的护盾对象。键为特效,值为对应的护盾对象。
/// </summary>
public Dictionary<Effect, ShieldOfEffect> ShieldOfEffects { get; } = [];
/// <summary>
/// 物理护盾
/// </summary>
@ -57,15 +62,20 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public double SpatioTemporal { get; set; } = 0;
/// <summary>
/// 混合护盾
/// </summary>
public double Mix { get; set; } = 0;
/// <summary>
/// 总计物理护盾
/// </summary>
public double TotalPhysical => Physical;
public double TotalPhysical => Physical + ShieldOfEffects.Values.Where(soe => !soe.IsMagic && soe.Shield > 0).Sum(soe => soe.Shield);
/// <summary>
/// 总计魔法护盾
/// </summary>
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);
/// <summary>
/// 获取或设置护盾值
@ -73,7 +83,7 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="isMagic"></param>
/// <param name="type"></param>
/// <returns></returns>
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
}
/// <summary>
/// 复制一个护盾对象
/// 添加一个绑定到特效的护盾,注意:如果特效已经存在护盾,则会覆盖原有护盾。
/// </summary>
/// <param name="soe"></param>
public void AddShieldOfEffect(ShieldOfEffect soe)
{
ShieldOfEffects[soe.Effect] = soe;
}
/// <summary>
/// 移除某个特效的护盾
/// </summary>
/// <param name="effect"></param>
public void RemoveShieldOfEffect(Effect effect)
{
ShieldOfEffects.Remove(effect);
}
/// <summary>
/// 计算并更新特效的护盾值,如果护盾值小于等于 0则移除该特效的护盾。
/// </summary>
/// <param name="effect"></param>
/// <param name="damage"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 复制一个护盾对象。注意:不会复制绑定到特效的护盾对象。
/// </summary>
/// <returns></returns>
public Shield Copy()
@ -153,8 +201,30 @@ namespace Milimoe.FunGame.Core.Entity
Shadow = Shadow,
Element = Element,
Aster = Aster,
SpatioTemporal = SpatioTemporal
SpatioTemporal = SpatioTemporal,
Mix = Mix
};
}
}
/// <summary>
/// 绑定到特效的护盾对象。这个类没有 JSON 转换器支持。
/// </summary>
/// <param name="effect"></param>
/// <param name="shield"></param>
/// <param name="isMagic"></param>
/// <param name="type"></param>
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;
}
}
}

View File

@ -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<string> 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<string> 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<string> 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<string> 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<string> 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;

View File

@ -73,7 +73,7 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary>
/// 是否显示在状态栏
/// </summary>
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);
/// <summary>
/// 特效是否生效
@ -659,26 +659,50 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="isMagic"></param>
/// <param name="magicType"></param>
/// <param name="damage"></param>
/// <param name="shield"></param>
/// <param name="damageReduce"></param>
/// <param name="message"></param>
/// <returns>返回 false 可以阻止后续扣除角色护盾</returns>
public virtual bool BeforeShieldCalculation(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, double shield, ref string message)
/// <returns>返回 false 可以跳过护盾结算</returns>
public virtual bool BeforeShieldCalculation(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, ref double damageReduce, ref string message)
{
return true;
}
/// <summary>
/// 当角色护盾破碎时
/// 在角色护盾有效防御时 [ 破碎本身不会触发此钩子,但破碎后化解可触发 ]
/// </summary>
/// <param name="character"></param>
/// <param name="attacker"></param>
/// <param name="isMagic"></param>
/// <param name="magicType"></param>
/// <param name="damage"></param>
/// <param name="shield"></param>
/// <param name="shieldType"></param>
public virtual void OnShieldNeutralizeDamage(Character character, Character attacker, bool isMagic, MagicType magicType, double damage, ShieldType shieldType)
{
}
/// <summary>
/// 当角色护盾破碎时 [ 非绑定特效,只有同种类型的总护盾值小于等于 0 时触发 ]
/// </summary>
/// <param name="character"></param>
/// <param name="attacker"></param>
/// <param name="type"></param>
/// <param name="overFlowing"></param>
/// <returns>返回 false 可以阻止后续扣除角色生命值</returns>
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;
}
/// <summary>
/// 当角色护盾破碎时 [ 绑定特效的护盾值小于等于 0 时便会触发 ]
/// </summary>
/// <param name="character"></param>
/// <param name="attacker"></param>
/// <param name="effect"></param>
/// <param name="overFlowing"></param>
/// <returns>返回 false 可以阻止后续扣除角色生命值</returns>
public virtual bool OnShieldBroken(Character character, Character attacker, Effect effect, double overFlowing)
{
return true;
}

View File

@ -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;

View File

@ -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();
}

View File

@ -1030,4 +1030,13 @@ namespace Milimoe.FunGame.Core.Library.Constant
All,
Special
}
public enum ShieldType
{
None,
Physical,
Magical,
Mix,
Effect
}
}

View File

@ -591,6 +591,11 @@ namespace Milimoe.FunGame.Core.Model
List<Effect> 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);