From c240c0a24b0288997f160987031ebaf46870fb0b Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sat, 20 Feb 2021 20:25:35 +0100 Subject: [PATCH] Only apply non-100 damage modifiers in InflictDamage Profiling has shown that filtering them out early is cheaper than applying those percentage modifiers anyway. Additionally, profiling shows foreach loops to be cheaper than LINQ here as well. --- OpenRA.Mods.Common/Traits/Health.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Health.cs b/OpenRA.Mods.Common/Traits/Health.cs index 45ff73dc09..048f323fea 100644 --- a/OpenRA.Mods.Common/Traits/Health.cs +++ b/OpenRA.Mods.Common/Traits/Health.cs @@ -168,11 +168,24 @@ namespace OpenRA.Mods.Common.Traits // Apply any damage modifiers if (!ignoreModifiers && damage.Value > 0) { - var modifiers = damageModifiers - .Concat(damageModifiersPlayer) - .Select(t => t.GetDamageModifier(attacker, damage)); + // PERF: Util.ApplyPercentageModifiers has been manually inlined to + // avoid unnecessary loop enumerations and allocations + var appliedDamage = (decimal)damage.Value; + foreach (var dm in damageModifiers) + { + var modifier = dm.GetDamageModifier(attacker, damage); + if (modifier != 100) + appliedDamage *= modifier / 100m; + } - damage = new Damage(Util.ApplyPercentageModifiers(damage.Value, modifiers), damage.DamageTypes); + foreach (var dm in damageModifiersPlayer) + { + var modifier = dm.GetDamageModifier(attacker, damage); + if (modifier != 100) + appliedDamage *= modifier / 100m; + } + + damage = new Damage((int)appliedDamage, damage.DamageTypes); } hp = (hp - damage.Value).Clamp(0, MaxHP);