添加特效护盾、混合护盾值,优化类型护盾值的计算逻辑 (#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 = []; List<string> shield = [];
if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial: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)}" : "")); 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); 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 = []; List<string> shield = [];
if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial: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)}" : "")); 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); 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 = []; List<string> shield = [];
if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial: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)}" : "")); 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); 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 = []; List<string> shield = [];
if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial: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)}" : "")); 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); 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 = []; List<string> shield = [];
if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}"); if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
if (Shield.TotalMagicial > 0) shield.Add($"魔法:{Shield.TotalMagicial: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)}" : "")); 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); 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> /// </summary>
public class Shield public class Shield
{ {
/// <summary>
/// 绑定到特效的护盾对象。键为特效,值为对应的护盾对象。
/// </summary>
public Dictionary<Effect, ShieldOfEffect> ShieldOfEffects { get; } = [];
/// <summary> /// <summary>
/// 物理护盾 /// 物理护盾
/// </summary> /// </summary>
@ -57,15 +62,20 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary> /// </summary>
public double SpatioTemporal { get; set; } = 0; public double SpatioTemporal { get; set; } = 0;
/// <summary>
/// 混合护盾
/// </summary>
public double Mix { get; set; } = 0;
/// <summary> /// <summary>
/// 总计物理护盾 /// 总计物理护盾
/// </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>
/// 总计魔法护盾 /// 总计魔法护盾
/// </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> /// <summary>
/// 获取或设置护盾值 /// 获取或设置护盾值
@ -73,7 +83,7 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="isMagic"></param> /// <param name="isMagic"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <returns></returns> /// <returns></returns>
public double this[bool isMagic = false, MagicType type = MagicType.None] public double this[bool isMagic, MagicType type = MagicType.None]
{ {
get get
{ {
@ -137,7 +147,45 @@ namespace Milimoe.FunGame.Core.Entity
} }
/// <summary> /// <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> /// </summary>
/// <returns></returns> /// <returns></returns>
public Shield Copy() public Shield Copy()
@ -153,8 +201,30 @@ namespace Milimoe.FunGame.Core.Entity
Shadow = Shadow, Shadow = Shadow,
Element = Element, Element = Element,
Aster = Aster, 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(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser());
builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}"); builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}");
double exHP = ExHP + ExHP2 + ExHP3; 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
double exATK = ExATK + ExATK2 + ExATK3; double exATK = ExATK + ExATK2 + ExATK3;
@ -177,7 +181,11 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser());
builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}"); builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}");
double exHP = ExHP + ExHP2 + ExHP3; 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
double exATK = ExATK + ExATK2 + ExATK3; double exATK = ExATK + ExATK2 + ExATK3;
@ -274,7 +282,11 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine(ToStringWithLevel()); builder.AppendLine(ToStringWithLevel());
double exHP = ExHP + ExHP2 + ExHP3; 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
double exATK = ExATK + ExATK2 + ExATK3; double exATK = ExATK + ExATK2 + ExATK3;
@ -321,7 +333,11 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine(ToStringWithLevel()); builder.AppendLine(ToStringWithLevel());
double exHP = ExHP + ExHP2 + ExHP3; 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
double exATK = ExATK + ExATK2 + ExATK3; double exATK = ExATK + ExATK2 + ExATK3;
@ -399,7 +415,11 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser());
builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}"); builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}");
double exHP = ExHP + ExHP2 + ExHP3; 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; double exMP = ExMP + ExMP2 + ExMP3;
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
double exATK = ExATK + ExATK2 + ExATK3; double exATK = ExATK + ExATK2 + ExATK3;

View File

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

View File

@ -20,6 +20,8 @@
public double AvgTakenRealDamage { get; set; } = 0; public double AvgTakenRealDamage { get; set; } = 0;
public double TotalHeal { get; set; } = 0; public double TotalHeal { get; set; } = 0;
public double AvgHeal { 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 LiveRound { get; set; } = 0;
public int AvgLiveRound { get; set; } = 0; public int AvgLiveRound { get; set; } = 0;
public int ActionTurn { 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): case nameof(Shield.SpatioTemporal):
result.SpatioTemporal = reader.GetDouble(); result.SpatioTemporal = reader.GetDouble();
break; 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.Element), value.Element);
writer.WriteNumber(nameof(Shield.Aster), value.Aster); writer.WriteNumber(nameof(Shield.Aster), value.Aster);
writer.WriteNumber(nameof(Shield.SpatioTemporal), value.SpatioTemporal); writer.WriteNumber(nameof(Shield.SpatioTemporal), value.SpatioTemporal);
writer.WriteNumber(nameof(Shield.Mix), value.Mix);
writer.WriteEndObject(); writer.WriteEndObject();
} }

View File

@ -1030,4 +1030,13 @@ namespace Milimoe.FunGame.Core.Library.Constant
All, All,
Special 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]; List<Effect> effects = [.. character.Effects];
foreach (Effect effect in effects) foreach (Effect effect in effects)
{ {
if (!character.Shield.ShieldOfEffects.ContainsKey(effect))
{
character.Shield.RemoveShieldOfEffect(effect);
}
if (effect.Level == 0) if (effect.Level == 0)
{ {
character.Effects.Remove(effect); character.Effects.Remove(effect);
@ -1380,7 +1385,8 @@ namespace Milimoe.FunGame.Core.Model
// 闪避了就没伤害了 // 闪避了就没伤害了
if (damageResult != DamageResult.Evaded) if (damageResult != DamageResult.Evaded)
{ {
// 计算伤害免疫 // 开始计算伤害免疫
// 此变量为是否无视免疫
bool ignore = false; bool ignore = false;
// 技能免疫无法免疫普通攻击,但是魔法免疫和物理免疫可以 // 技能免疫无法免疫普通攻击,但是魔法免疫和物理免疫可以
bool isImmune = (isNormalAttack && (enemy.ImmuneType == ImmuneType.All || enemy.ImmuneType == ImmuneType.Physical || enemy.ImmuneType == ImmuneType.Magical)) || 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; damageResult = DamageResult.Immune;
LastRound.IsImmune[enemy] = true; LastRound.IsImmune[enemy] = true;
WriteLine($"[ {enemy} ] 免疫了此伤害!"); WriteLine($"[ {enemy} ] 免疫了此伤害!");
actualDamage = 0;
} }
else else
{ {
if (damage < 0) damage = 0; if (damage < 0) damage = 0;
// 检查护盾 string damageType = isMagicDamage ? CharacterSet.GetMagicDamageName(magicType) : "物理伤害";
double shield = enemy.Shield[isMagicDamage, magicType];
// 在护盾结算前,特效可以有自己的逻辑
bool change = false;
string shieldMsg = ""; 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)
{
ShieldOfEffect soe = enemy.Shield.ShieldOfEffects[effect];
if (soe.IsMagic == isMagicDamage && (!isMagicDamage || soe.MagicType == magicType) && soe.Shield > 0)
{
double effectShield = soe.Shield;
// 判断护盾余额
if (enemy.Shield.CalculateShieldOfEffect(effect, remain) > 0)
{
WriteLine($"[ {enemy} ] 发动了 [ {effect.Skill.Name} ] 的护盾效果,抵消了 {remain:0.##} 点{damageType}");
remain = 0;
}
else
{
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;
}
}
}
// 如果伤害仍然大于0继续检查护盾
if (remain > 0)
{
// 检查指定类型的护盾值
double shield = enemy.Shield[isMagicDamage, magicType];
if (shield > 0) if (shield > 0)
{ {
bool change = false; 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()]; effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
foreach (Effect effect in effects) foreach (Effect effect in effects)
{ {
if (!effect.BeforeShieldCalculation(enemy, actor, isMagicDamage, magicType, damage, shield, ref shieldMsg)) effect.OnShieldNeutralizeDamage(enemy, actor, isMagicDamage, magicType, damage, shieldType);
{
change = true;
} }
} }
else
if (!change)
{ {
double remain = shield - damage; WriteLine($"[ {enemy} ] 的{shieldTypeString}护盾抵消了 {enemy.Shield[isMagicDamage, magicType]:0.##} 点{damageType}并破碎!");
if (remain < 0) remain -= enemy.Shield[isMagicDamage, magicType];
{
remain = Math.Abs(remain);
enemy.Shield[isMagicDamage, magicType] = 0; enemy.Shield[isMagicDamage, magicType] = 0;
if (isMagicDamage && enemy.Shield.TotalMagicial <= 0 || !isMagicDamage && enemy.Shield.TotalPhysical <= 0)
change = false; {
effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
foreach (Effect effect in effects) foreach (Effect effect in effects)
{ {
if (!effect.OnShieldBroken(enemy, actor, isMagicDamage, magicType, damage, shield, remain)) if (!effect.OnShieldBroken(enemy, actor, shieldType, remain))
{ {
change = true; WriteLine($"[ {(enemy.Effects.Contains(effect) ? enemy : actor)} ] 因护盾破碎而发动了 [ {effect.Skill.Name} ],化解了本次伤害!");
remain = 0;
}
}
}
} }
} }
if (!change) // 检查混合护盾
if (remain > 0 && enemy.Shield.Mix > 0)
{ {
enemy.HP -= remain; shield = enemy.Shield.Mix;
shieldMsg = $"(护盾抵消了 {shield:0.##} 点并破碎,角色承受了 {remain:0.##} 点)"; 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; actualDamage = remain;
} }
else
{
shieldMsg = $"(护盾抵消了 {shield:0.##} 点并破碎,角色没有承受伤害)";
damageResult = DamageResult.Shield;
actualDamage = 0;
}
}
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) // 统计护盾
if (damage > actualDamage && _stats.TryGetValue(actor, out CharacterStatistics? stats) && stats != null)
{ {
string dmgType = CharacterSet.GetMagicDamageName(magicType); stats.TotalShield += damage - actualDamage;
WriteLine($"[ {enemy} ] 受到了 {damage:0.##} 点{dmgType}{shieldMsg}");
} }
else WriteLine($"[ {enemy} ] 受到了 {damage:0.##} 点物理伤害!{shieldMsg}");
enemy.HP -= actualDamage;
WriteLine($"[ {enemy} ] 受到了 {actualDamage:0.##} 点{damageType}{shieldMsg}");
// 生命偷取,攻击者为全额 // 生命偷取,攻击者为全额
double steal = damage * actor.Lifesteal; double steal = damage * actor.Lifesteal;
@ -1543,6 +1627,7 @@ namespace Milimoe.FunGame.Core.Model
else else
{ {
LastRound.IsEvaded[enemy] = true; LastRound.IsEvaded[enemy] = true;
actualDamage = 0;
} }
await OnDamageToEnemyAsync(actor, enemy, damage, actualDamage, isNormalAttack, isMagicDamage, magicType, damageResult); await OnDamageToEnemyAsync(actor, enemy, damage, actualDamage, isNormalAttack, isMagicDamage, magicType, damageResult);