伤害计算、生命回复可显示更多调试日志;修复一些单位影响的问题

This commit is contained in:
milimoe 2026-01-16 01:55:26 +08:00
parent a93f9a274e
commit 44d5ffd3f7
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
7 changed files with 145 additions and 55 deletions

View File

@ -557,11 +557,12 @@ namespace Milimoe.FunGame.Core.Entity
/// 在完成死亡结算后 [ 全体广播 ] /// 在完成死亡结算后 [ 全体广播 ]
/// </summary> /// </summary>
/// <param name="death"></param> /// <param name="death"></param>
/// <param name="hasMaster"></param>
/// <param name="killer"></param> /// <param name="killer"></param>
/// <param name="continuousKilling"></param> /// <param name="continuousKilling"></param>
/// <param name="earnedMoney"></param> /// <param name="earnedMoney"></param>
/// <param name="assists"></param> /// <param name="assists"></param>
public virtual void AfterDeathCalculation(Character death, Character? killer, Dictionary<Character, int> continuousKilling, Dictionary<Character, int> earnedMoney, Character[] assists) public virtual void AfterDeathCalculation(Character death, bool hasMaster, Character? killer, Dictionary<Character, int> continuousKilling, Dictionary<Character, int> earnedMoney, Character[] assists)
{ {
} }
@ -955,9 +956,10 @@ namespace Milimoe.FunGame.Core.Entity
DamageResult result = DamageResult.Normal; DamageResult result = DamageResult.Normal;
double damage = expectedDamage; double damage = expectedDamage;
options ??= new(); options ??= new();
if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage;
if (options.NeedCalculate && damageType != DamageType.True) if (options.NeedCalculate && damageType != DamageType.True)
{ {
result = damageType == DamageType.Physical ? GamingQueue.CalculatePhysicalDamage(actor, enemy, false, expectedDamage, out damage, ref changeCount, options) : GamingQueue.CalculateMagicalDamage(actor, enemy, false, MagicType, expectedDamage, out damage, ref changeCount, options); 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); GamingQueue.DamageToEnemy(actor, enemy, damage, false, damageType, magicType, result, options);
return result; return result;

View File

@ -352,7 +352,7 @@ namespace Milimoe.FunGame.Core.Entity
queue.WriteLine($"[ {Character} ] 对 [ {enemy} ] 发起了普通攻击!"); queue.WriteLine($"[ {Character} ] 对 [ {enemy} ] 发起了普通攻击!");
double expected = Damage; double expected = Damage;
int changeCount = 0; int changeCount = 0;
DamageResult result = IsMagic ? queue.CalculateMagicalDamage(attacker, enemy, true, MagicType, expected, out double damage, ref changeCount, options) : queue.CalculatePhysicalDamage(attacker, enemy, true, expected, out damage, ref changeCount, options); DamageResult result = IsMagic ? queue.CalculateMagicalDamage(attacker, enemy, true, MagicType, expected, out double damage, ref changeCount, ref options) : queue.CalculatePhysicalDamage(attacker, enemy, true, expected, out damage, ref changeCount, ref options);
queue.DamageToEnemy(attacker, enemy, damage, true, IsMagic ? DamageType.Magical : DamageType.Physical, MagicType, result, options); queue.DamageToEnemy(attacker, enemy, damage, true, IsMagic ? DamageType.Magical : DamageType.Physical, MagicType, result, options);
} }
} }

View File

@ -127,7 +127,7 @@ namespace Milimoe.FunGame.Core.Interface.Base
/// <param name="changeCount"></param> /// <param name="changeCount"></param>
/// <param name="options"></param> /// <param name="options"></param>
/// <returns></returns> /// <returns></returns>
public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage, ref int changeCount, DamageCalculationOptions? options = null); public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage, ref int changeCount, ref DamageCalculationOptions? options);
/// <summary> /// <summary>
/// 计算魔法伤害 /// 计算魔法伤害
@ -141,7 +141,7 @@ namespace Milimoe.FunGame.Core.Interface.Base
/// <param name="changeCount"></param> /// <param name="changeCount"></param>
/// <param name="options"></param> /// <param name="options"></param>
/// <returns></returns> /// <returns></returns>
public DamageResult CalculateMagicalDamage(Character actor, Character enemy, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage, ref int changeCount, DamageCalculationOptions? options = null); public DamageResult CalculateMagicalDamage(Character actor, Character enemy, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage, ref int changeCount, ref DamageCalculationOptions? options);
/// <summary> /// <summary>
/// 死亡结算 /// 死亡结算

View File

@ -1,4 +1,6 @@
namespace Milimoe.FunGame.Core.Model using Milimoe.FunGame.Core.Entity;
namespace Milimoe.FunGame.Core.Model
{ {
/// <summary> /// <summary>
/// 精准的分步控制伤害计算 /// 精准的分步控制伤害计算
@ -39,5 +41,45 @@
/// 无视免疫 /// 无视免疫
/// </summary> /// </summary>
public bool IgnoreImmune { get; set; } = false; public bool IgnoreImmune { get; set; } = false;
/// <summary>
/// 伤害基底(期望)
/// </summary>
internal double ExpectedDamage { get; set; } = 0;
/// <summary>
/// 特效伤害加成记录乘区1暴击和减伤计算前
/// </summary>
internal Dictionary<Effect, double> BeforeDamageBonus { get; set; } = [];
/// <summary>
/// 暴击伤害
/// </summary>
internal double CriticalDamage { get; set; } = 0;
/// <summary>
/// 伤害减免
/// </summary>
internal double DefenseReduction { get; set; } = 0;
/// <summary>
/// 特效伤害加成记录乘区2暴击和减伤计算后
/// </summary>
internal Dictionary<Effect, double> AfterDamageBonus { get; set; } = [];
/// <summary>
/// 最终伤害
/// </summary>
internal double FinalDamage { get; set; } = 0;
/// <summary>
/// 护盾减免
/// </summary>
internal double ShieldReduction { get; set; } = 0;
/// <summary>
/// 实际造成伤害
/// </summary>
internal double ActualDamage { get; set; } = 0;
} }
} }

View File

@ -2061,18 +2061,19 @@ namespace Milimoe.FunGame.Core.Model
bool isEvaded = damageResult == DamageResult.Evaded; bool isEvaded = damageResult == DamageResult.Evaded;
List<Effect> effects = []; List<Effect> effects = [];
options ??= new(); options ??= new();
if (options.ExpectedDamage == 0) options.ExpectedDamage = damage;
Dictionary<Effect, double> totalDamageBonus = [];
if (options.TriggerEffects) if (options.TriggerEffects)
{ {
// 真实伤害跳过伤害加成区间 // 真实伤害跳过伤害加成区间
if (damageType != DamageType.True) if (damageType != DamageType.True)
{ {
Dictionary<Effect, double> totalDamageBonus = [];
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)
{ {
double damageBonus = effect.AlterActualDamageAfterCalculation(actor, enemy, damage, isNormalAttack, damageType, magicType, damageResult, ref isEvaded, totalDamageBonus); double damageBonus = effect.AlterActualDamageAfterCalculation(actor, enemy, damage, isNormalAttack, damageType, magicType, damageResult, ref isEvaded, totalDamageBonus);
totalDamageBonus[effect] = damageBonus; if (damageBonus != 0) totalDamageBonus[effect] = damageBonus;
if (isEvaded) if (isEvaded)
{ {
damageResult = DamageResult.Evaded; damageResult = DamageResult.Evaded;
@ -2092,6 +2093,8 @@ namespace Milimoe.FunGame.Core.Model
} }
} }
} }
options.AfterDamageBonus = totalDamageBonus;
options.FinalDamage = damage;
double actualDamage = damage; double actualDamage = damage;
// 闪避了就没伤害了 // 闪避了就没伤害了
@ -2322,9 +2325,11 @@ namespace Milimoe.FunGame.Core.Model
{ {
stats.TotalShield += damage - actualDamage; stats.TotalShield += damage - actualDamage;
} }
options.ShieldReduction += damage - actualDamage;
} }
} }
options.ActualDamage = actualDamage;
enemy.HP -= actualDamage; enemy.HP -= actualDamage;
string strDamageMessage = $"[ {enemy} ] 受到了 {actualDamage:0.##} 点{damageTypeString}{shieldMsg}"; string strDamageMessage = $"[ {enemy} ] 受到了 {actualDamage:0.##} 点{damageTypeString}{shieldMsg}";
effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
@ -2332,6 +2337,23 @@ namespace Milimoe.FunGame.Core.Model
{ {
effect.OnApplyDamage(enemy, actor, damage, actualDamage, isNormalAttack, damageType, magicType, damageResult, shieldMsg, ref strDamageMessage); effect.OnApplyDamage(enemy, actor, damage, actualDamage, isNormalAttack, damageType, magicType, damageResult, shieldMsg, ref strDamageMessage);
} }
if (IsDebug)
{
string strBeforeBonus = "";
if (options.BeforeDamageBonus.Count > 0)
{
strBeforeBonus = string.Join("", options.BeforeDamageBonus.Select(kv => $"{(kv.Value >= 0 ? " + " : " - ")}{Math.Abs(kv.Value):0.##}{kv.Key.Name}"));
}
string strDefenseReduction = options.DefenseReduction == 0 ? "" : ($"{(options.DefenseReduction >= 0 ? " - " : " + ")}{Math.Abs(options.DefenseReduction):0.##}(减伤)");
string strCriticalDamage = options.CriticalDamage == 0 ? "" : ($"{(options.CriticalDamage >= 0 ? " + " : " - ")}{Math.Abs(options.CriticalDamage):0.##}(暴击)");
string strAfterBonus = "";
if (options.AfterDamageBonus.Count > 0)
{
strAfterBonus = string.Join("", options.AfterDamageBonus.Select(kv => $"{(kv.Value >= 0 ? " + " : " - ")}{Math.Abs(kv.Value):0.##}{kv.Key.Name}"));
}
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}】";
}
WriteLine(strDamageMessage); WriteLine(strDamageMessage);
// 生命偷取 // 生命偷取
@ -2371,17 +2393,18 @@ namespace Milimoe.FunGame.Core.Model
// 计算助攻 // 计算助攻
if (actor != enemy && !IsTeammate(actor, enemy)) if (actor != enemy && !IsTeammate(actor, enemy))
{ {
if (actor.Master != null) Character a = actor, e = enemy;
if (a.Master != null)
{ {
actor = actor.Master; a = a.Master;
} }
if (enemy.Master != null) if (e.Master != null)
{ {
enemy = enemy.Master; e = e.Master;
} }
if (actor != enemy) if (a != e)
{ {
_assistDetail[actor][enemy, TotalTime] += damage; _assistDetail[a][e, TotalTime] += damage;
} }
} }
} }
@ -2422,16 +2445,12 @@ namespace Milimoe.FunGame.Core.Model
if (killer == death) if (killer == death)
{ {
if (!OnDeathCalculationEvent(killer, death))
{
return;
}
if (killer.Master is null) if (killer.Master is null)
{ {
_stats[death].Deaths += 1; _stats[death].Deaths += 1;
} }
WriteLine($"[ {death} ] 自杀了!"); WriteLine($"[ {death} ] 自杀了!");
DealWithCharacterDied(killer, death); DealWithCharacterDied(killer, death, []);
return; return;
} }
@ -2446,13 +2465,9 @@ namespace Milimoe.FunGame.Core.Model
return; return;
} }
if (!OnDeathCalculationEvent(killer, death))
{
return;
}
if (death.Master != null) if (death.Master != null)
{ {
DealWithCharacterDied(killer, death, []);
return; return;
} }
@ -2610,18 +2625,7 @@ namespace Milimoe.FunGame.Core.Model
WriteLine(actorContinuousKilling); WriteLine(actorContinuousKilling);
} }
DealWithCharacterDied(killer, death); DealWithCharacterDied(killer, death, assists);
// 给所有角色的特效广播角色死亡结算
List<Effect> effects = [.. _queue.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Union(killer.Effects).Distinct()];
foreach (Effect effect in effects)
{
effect.AfterDeathCalculation(death, killer, _continuousKilling, _earnedMoney, assists);
}
// 将死者移出队列
_queue.Remove(death);
OnCharacterDeathEvent(death, killer, assists);
} }
/// <summary> /// <summary>
@ -2653,7 +2657,7 @@ namespace Milimoe.FunGame.Core.Model
WriteLine(msg); WriteLine(msg);
} }
DealWithCharacterDied(killer, death); DealWithCharacterDied(killer, death, []);
} }
/// <summary> /// <summary>
@ -2678,6 +2682,7 @@ namespace Milimoe.FunGame.Core.Model
} }
bool isDead = target.HP <= 0; bool isDead = target.HP <= 0;
string healString = $"【{heal:0.##}(基础)";
if (triggerEffects) if (triggerEffects)
{ {
@ -2691,9 +2696,16 @@ namespace Milimoe.FunGame.Core.Model
{ {
canRespawn = true; canRespawn = true;
} }
if (healBonus != 0)
{
totalHealBonus[effect]= healBonus;
healString += $"{(healBonus > 0 ? " + " : " - ")}{Math.Abs(healBonus):0.##}{effect.Name}";
}
} }
heal += totalHealBonus.Sum(kv => kv.Value); heal += totalHealBonus.Sum(kv => kv.Value);
} }
healString += $" = {heal:0.##} 点生命值】";
if (!IsDebug) healString = "";
if (target.HP > 0 || (isDead && canRespawn)) if (target.HP > 0 || (isDead && canRespawn))
{ {
@ -2719,11 +2731,11 @@ namespace Milimoe.FunGame.Core.Model
{ {
if (target != actor) if (target != actor)
{ {
WriteLine($"[ {target} ] 被 [ {actor} ] 复苏了,并回复了 {heal:0.##} 点生命值!!"); WriteLine($"[ {target} ] 被 [ {actor} ] 复苏了,并回复了 {heal:0.##} 点生命值!!{healString}");
} }
else else
{ {
WriteLine($"[ {target} ] 复苏了,并回复了 {heal:0.##} 点生命值!!"); WriteLine($"[ {target} ] 复苏了,并回复了 {heal:0.##} 点生命值!!{healString}");
} }
double hp = target.HP; double hp = target.HP;
double mp = target.MP; double mp = target.MP;
@ -2733,7 +2745,7 @@ namespace Milimoe.FunGame.Core.Model
} }
else else
{ {
WriteLine($"[ {target} ] 回复了 {heal:0.##} 点生命值!"); WriteLine($"[ {target} ] 回复了 {heal:0.##} 点生命值!{healString}");
} }
// 添加助攻 // 添加助攻
@ -2830,9 +2842,24 @@ namespace Milimoe.FunGame.Core.Model
/// </summary> /// </summary>
/// <param name="killer"></param> /// <param name="killer"></param>
/// <param name="death"></param> /// <param name="death"></param>
/// <param name="assists"></param>
/// <returns></returns> /// <returns></returns>
public void DealWithCharacterDied(Character killer, Character death) public void DealWithCharacterDied(Character killer, Character death, Character[] assists)
{ {
// 给所有角色的特效广播角色死亡结算
List<Effect> effects = [.. _queue.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Union(killer.Effects).Distinct()];
foreach (Effect effect in effects)
{
effect.AfterDeathCalculation(death, death.Master != null, killer, _continuousKilling, _earnedMoney, assists);
}
// 将死者移出队列
_queue.Remove(death);
if (!OnCharacterDeathEvent(death, killer, assists))
{
return;
}
OnDeathCalculation(death, killer); OnDeathCalculation(death, killer);
death.EP = 0; death.EP = 0;
@ -3239,13 +3266,15 @@ namespace Milimoe.FunGame.Core.Model
/// <param name="changeCount"></param> /// <param name="changeCount"></param>
/// <param name="options"></param> /// <param name="options"></param>
/// <returns></returns> /// <returns></returns>
public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage, ref int changeCount, DamageCalculationOptions? options = null) public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage, ref int changeCount, ref DamageCalculationOptions? options)
{ {
options ??= new(); options ??= new();
if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage;
List<Character> characters = [actor, enemy]; List<Character> characters = [actor, enemy];
DamageType damageType = DamageType.Physical; DamageType damageType = DamageType.Physical;
MagicType magicType = MagicType.None; MagicType magicType = MagicType.None;
List<Effect> effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; List<Effect> effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
Dictionary<Effect, double> totalDamageBonus = [];
if (options.TriggerEffects) if (options.TriggerEffects)
{ {
if (changeCount < 3) if (changeCount < 3)
@ -3257,19 +3286,19 @@ namespace Milimoe.FunGame.Core.Model
if (damageType == DamageType.Magical) if (damageType == DamageType.Magical)
{ {
changeCount++; changeCount++;
return CalculateMagicalDamage(actor, enemy, isNormalAttack, magicType, expectedDamage, out finalDamage, ref changeCount, options); return CalculateMagicalDamage(actor, enemy, isNormalAttack, magicType, expectedDamage, out finalDamage, ref changeCount, ref options);
} }
} }
Dictionary<Effect, double> totalDamageBonus = [];
effects = [.. actor.Effects.Union(enemy.Effects).Distinct().Where(e => e.IsInEffect)]; effects = [.. actor.Effects.Union(enemy.Effects).Distinct().Where(e => e.IsInEffect)];
foreach (Effect effect in effects) foreach (Effect effect in effects)
{ {
double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, DamageType.Physical, MagicType.None, totalDamageBonus); double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, DamageType.Physical, MagicType.None, totalDamageBonus);
totalDamageBonus[effect] = damageBonus; if (damageBonus != 0) totalDamageBonus[effect] = damageBonus;
} }
expectedDamage += totalDamageBonus.Sum(kv => kv.Value); expectedDamage += totalDamageBonus.Sum(kv => kv.Value);
} }
options.BeforeDamageBonus = totalDamageBonus;
double dice = Random.Shared.NextDouble(); double dice = Random.Shared.NextDouble();
double throwingBonus = 0; double throwingBonus = 0;
@ -3321,11 +3350,13 @@ namespace Milimoe.FunGame.Core.Model
{ {
penetratedDEF = (1 - actor.PhysicalPenetration) * enemy.DEF; penetratedDEF = (1 - actor.PhysicalPenetration) * enemy.DEF;
physicalDamageReduction = penetratedDEF / (penetratedDEF + GameplayEquilibriumConstant.DEFReductionFactor); physicalDamageReduction = penetratedDEF / (penetratedDEF + GameplayEquilibriumConstant.DEFReductionFactor);
finalDamage = expectedDamage * (1 - Calculation.PercentageCheck(physicalDamageReduction + enemy.ExPDR)); options.DefenseReduction = expectedDamage * Calculation.PercentageCheck(physicalDamageReduction + enemy.ExPDR);
finalDamage = expectedDamage - options.DefenseReduction;
} }
if (options.CalculateCritical) if (options.CalculateCritical)
{ // 暴击检定 {
// 暴击检定
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)
{ {
@ -3340,6 +3371,7 @@ namespace Milimoe.FunGame.Core.Model
dice = Random.Shared.NextDouble(); dice = Random.Shared.NextDouble();
if (dice < (actor.CritRate + throwingBonus)) if (dice < (actor.CritRate + throwingBonus))
{ {
options.CriticalDamage = finalDamage * (actor.CritDMG - 1);
finalDamage *= actor.CritDMG; // 暴击伤害倍率加成 finalDamage *= actor.CritDMG; // 暴击伤害倍率加成
WriteLine("暴击生效!!"); WriteLine("暴击生效!!");
effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
@ -3368,12 +3400,14 @@ namespace Milimoe.FunGame.Core.Model
/// <param name="changeCount"></param> /// <param name="changeCount"></param>
/// <param name="options"></param> /// <param name="options"></param>
/// <returns></returns> /// <returns></returns>
public DamageResult CalculateMagicalDamage(Character actor, Character enemy, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage, ref int changeCount, DamageCalculationOptions? options = null) 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();
if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage;
List<Character> characters = [actor, enemy]; List<Character> characters = [actor, enemy];
DamageType damageType = DamageType.Magical; DamageType damageType = DamageType.Magical;
List<Effect> effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; List<Effect> effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
Dictionary<Effect, double> totalDamageBonus = [];
if (options.TriggerEffects) if (options.TriggerEffects)
{ {
if (changeCount < 3) if (changeCount < 3)
@ -3385,19 +3419,19 @@ namespace Milimoe.FunGame.Core.Model
if (damageType == DamageType.Physical) if (damageType == DamageType.Physical)
{ {
changeCount++; changeCount++;
return CalculatePhysicalDamage(actor, enemy, isNormalAttack, expectedDamage, out finalDamage, ref changeCount, options); return CalculatePhysicalDamage(actor, enemy, isNormalAttack, expectedDamage, out finalDamage, ref changeCount, ref options);
} }
} }
Dictionary<Effect, double> totalDamageBonus = [];
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)
{ {
double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, DamageType.Magical, magicType, totalDamageBonus); double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, DamageType.Magical, magicType, totalDamageBonus);
totalDamageBonus[effect] = damageBonus; if (damageBonus != 0) totalDamageBonus[effect] = damageBonus;
} }
expectedDamage += totalDamageBonus.Sum(kv => kv.Value); expectedDamage += totalDamageBonus.Sum(kv => kv.Value);
} }
options.BeforeDamageBonus = totalDamageBonus;
double dice = Random.Shared.NextDouble(); double dice = Random.Shared.NextDouble();
double throwingBonus = 0; double throwingBonus = 0;
@ -3446,8 +3480,11 @@ namespace Milimoe.FunGame.Core.Model
// 魔法穿透后的魔法抗性 // 魔法穿透后的魔法抗性
MDF = (1 - actor.MagicalPenetration) * MDF; MDF = (1 - actor.MagicalPenetration) * MDF;
// 魔法抗性减伤
options.DefenseReduction = expectedDamage * MDF;
// 最终的魔法伤害 // 最终的魔法伤害
finalDamage = expectedDamage * (1 - MDF); finalDamage = expectedDamage - options.DefenseReduction;
} }
if (options.CalculateCritical) if (options.CalculateCritical)
@ -3467,6 +3504,7 @@ namespace Milimoe.FunGame.Core.Model
dice = Random.Shared.NextDouble(); dice = Random.Shared.NextDouble();
if (dice < (actor.CritRate + throwingBonus)) if (dice < (actor.CritRate + throwingBonus))
{ {
options.CriticalDamage = finalDamage * (actor.CritDMG - 1);
finalDamage *= actor.CritDMG; // 暴击伤害倍率加成 finalDamage *= actor.CritDMG; // 暴击伤害倍率加成
WriteLine("暴击生效!!"); WriteLine("暴击生效!!");
effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
@ -3524,7 +3562,7 @@ namespace Milimoe.FunGame.Core.Model
public bool IsTeammate(Character character, Character target) public bool IsTeammate(Character character, Character target)
{ {
List<Character> teammates = GetTeammates(character); List<Character> teammates = GetTeammates(character);
return teammates.Contains(target) && (character.Master == target || target == character.Master || (target.Master != null && character.Master != null && target.Master == character.Master)); return teammates.Contains(target) || character.Master == target || target == character.Master || (target.Master != null && character.Master != null && target.Master == character.Master);
} }
/// <summary> /// <summary>
@ -4225,6 +4263,10 @@ namespace Milimoe.FunGame.Core.Model
{ {
character = character.Master; character = character.Master;
} }
if (characterTaken.Master != null)
{
characterTaken = characterTaken.Master;
}
if (_stats.TryGetValue(character, out CharacterStatistics? stats) && stats != null) if (_stats.TryGetValue(character, out CharacterStatistics? stats) && stats != null)
{ {
if (damageType == DamageType.True) if (damageType == DamageType.True)

View File

@ -23,7 +23,7 @@ namespace Milimoe.FunGame.Core.Model
.Select(kv => $"[ {kv.Key} ] {kv.Value.Kills} 分"))}\r\n剩余存活人数{_queue.Count}"); .Select(kv => $"[ {kv.Key} ] {kv.Value.Kills} 分"))}\r\n剩余存活人数{_queue.Count}");
} }
if (!_queue.Any(c => c != killer && c.Master != killer && killer?.Master != c)) if (!_queue.Any(c => c != killer && c.Master != killer && killer?.Master != c && killer?.Master != c.Master))
{ {
// 没有其他的角色了,游戏结束 // 没有其他的角色了,游戏结束
EndGameInfo(killer); EndGameInfo(killer);
@ -66,6 +66,10 @@ namespace Milimoe.FunGame.Core.Model
WriteLine("游戏结束。"); WriteLine("游戏结束。");
return; return;
} }
if (winner.Master != null)
{
winner = winner.Master;
}
WriteLine("[ " + winner + " ] 是胜利者。"); WriteLine("[ " + winner + " ] 是胜利者。");
foreach (Character character in _stats.OrderBy(kv => kv.Value.Kills) foreach (Character character in _stats.OrderBy(kv => kv.Value.Kills)
.ThenByDescending(kv => kv.Value.Deaths) .ThenByDescending(kv => kv.Value.Deaths)

View File

@ -135,7 +135,7 @@ namespace Milimoe.FunGame.Core.Model
/// <returns></returns> /// <returns></returns>
protected override void OnDeathCalculation(Character death, Character killer) protected override void OnDeathCalculation(Character death, Character killer)
{ {
if (killer == death) if (killer == death || death.Master != null)
{ {
return; return;
} }