diff --git a/EpicLoot/MagicItemComponent.cs b/EpicLoot/MagicItemComponent.cs index e1c5a1af6..801fd83d2 100644 --- a/EpicLoot/MagicItemComponent.cs +++ b/EpicLoot/MagicItemComponent.cs @@ -653,19 +653,66 @@ public static HashSet GetEquippedSets(this Player player) return sets; } - public static float GetTotalActiveMagicEffectValue(this Player player, string effectType, float scale = 1.0f, ItemDrop.ItemData ignoreThisItem = null) + public static float GetEffectDiminishingReturnsTotalValue(List effectValues, string effectType = null) { - var totalValue = scale * (EquipmentEffectCache.Get(player, effectType, () => + var LIMITED_EFFECTS = new List() { + MagicEffectType.AddPhysicalResistancePercentage, + MagicEffectType.AddBluntResistancePercentage, + MagicEffectType.AddSlashingResistancePercentage, + MagicEffectType.AddPiercingResistancePercentage, + MagicEffectType.AddChoppingResistancePercentage, + MagicEffectType.AddFireResistancePercentage, + MagicEffectType.AddFrostResistancePercentage, + MagicEffectType.AddLightningResistancePercentage, + MagicEffectType.AddPoisonResistancePercentage, + MagicEffectType.AddSpiritResistancePercentage, + MagicEffectType.AddElementalResistancePercentage, + MagicEffectType.AvoidDamageTaken, + MagicEffectType.AvoidDamageTakenLowHealth, + MagicEffectType.ModifyAttackStaminaUse, + MagicEffectType.ModifyBlockStaminaUse, + MagicEffectType.ModifyJumpStaminaUse, + MagicEffectType.ModifySprintStaminaUse, + MagicEffectType.Slow + }; + + if (effectType == null || LIMITED_EFFECTS.Contains(effectType)) { - var allEffects = player.GetAllActiveMagicEffects(effectType); - return allEffects.Count > 0 ? allEffects.Select(x => x.EffectValue).Sum() : null; - }) ?? 0); + var limitedValues = effectValues.Select(x => Math.Min(x, 90.0f)).ToList(); + limitedValues.Sort((float a, float b) => { if (a > b) return -1; return 1; }); + + var result = limitedValues[0]; + for (var i = 1; i < limitedValues.Count; i++) + { + result = result + (100.0f - result) * (limitedValues[i] * 0.01f); + } + + return result; + } + + return effectValues.Sum(); + } + + public static float GetTotalActiveMagicEffectValue(this Player player, string effectType, float scale = 1.0f, ItemDrop.ItemData ignoreThisItem = null) + { + var allValues = player.GetAllActiveMagicEffects(effectType).Select(x => x.EffectValue).ToList(); if (ignoreThisItem != null && player.IsItemEquiped(ignoreThisItem) && ignoreThisItem.IsMagic(out var magicItem)) { - totalValue -= magicItem.GetTotalEffectValue(effectType, scale); + var ignoredValue = magicItem.GetEffects(effectType).Sum(x => x.EffectValue); + allValues.Remove(ignoredValue); } + var totalValue = scale * (EquipmentEffectCache.Get(player, effectType, () => + { + if (allValues.Count == 0) + { + return null; + } + + return GetEffectDiminishingReturnsTotalValue(allValues, effectType); + }) ?? 0); + return totalValue; } diff --git a/EpicLoot/MagicItemEffects/AvoidDamageTaken.cs b/EpicLoot/MagicItemEffects/AvoidDamageTaken.cs index f6b519bc3..a89f8216a 100644 --- a/EpicLoot/MagicItemEffects/AvoidDamageTaken.cs +++ b/EpicLoot/MagicItemEffects/AvoidDamageTaken.cs @@ -13,13 +13,24 @@ private static bool Prefix(Character __instance, HitData hit) var attacker = hit.GetAttacker(); if (__instance is Player player && attacker != null && attacker != __instance) { - var avoidanceChance = 0f; - ModifyWithLowHealth.Apply(player, MagicEffectType.AvoidDamageTaken, effect => + var avoidancePercent = player.GetTotalActiveMagicEffectValue(MagicEffectType.AvoidDamageTaken, 1.0f); + var avoidancePercentLowHealth = ModifyWithLowHealth.PlayerHasLowHealth(player) ? player.GetTotalActiveMagicEffectValue(MagicEffectType.AvoidDamageTakenLowHealth, 1.0f) : 0.0f; + + float min, max; + if(avoidancePercent > avoidancePercentLowHealth) + { + min = avoidancePercentLowHealth; + max = avoidancePercent; + } + else { - avoidanceChance += player.GetTotalActiveMagicEffectValue(effect, 0.01f); - }); + min = avoidancePercent; + max = avoidancePercentLowHealth; + } + + float avoidanceChance = (max + (100.0f - max) * min * 0.01f) * 0.01f; - return !(Random.Range(0f, 1f) < avoidanceChance); + return !(Random.Range(0f, 1f) < avoidanceChance); } return true; diff --git a/EpicLoot/MagicItemEffects/ModifyResistance.cs b/EpicLoot/MagicItemEffects/ModifyResistance.cs index 856c169b4..22769ffea 100644 --- a/EpicLoot/MagicItemEffects/ModifyResistance.cs +++ b/EpicLoot/MagicItemEffects/ModifyResistance.cs @@ -47,29 +47,29 @@ public static void Prefix(Character __instance, HitData hit) return; } - float sum(params string[] effects) - { - float value = 1; - foreach (var effect in effects) - { - value -= player.GetTotalActiveMagicEffectValue(effect, 0.01f); - } + float resultingDamageCoeff(string eff1, string eff2) + { + float totalSum = PlayerExtensions.GetEffectDiminishingReturnsTotalValue(new List() + { + player.GetTotalActiveMagicEffectValue(eff1, 0.01f), + player.GetTotalActiveMagicEffectValue(eff2, 0.01f) + }); - return Math.Max(value, 0); - } + return 1.0f - totalSum; + } - // elemental resistances - hit.m_damage.m_fire *= sum(MagicEffectType.AddFireResistancePercentage, MagicEffectType.AddElementalResistancePercentage); - hit.m_damage.m_frost *= sum(MagicEffectType.AddFrostResistancePercentage, MagicEffectType.AddElementalResistancePercentage); - hit.m_damage.m_lightning *= sum(MagicEffectType.AddLightningResistancePercentage, MagicEffectType.AddElementalResistancePercentage); - hit.m_damage.m_poison *= sum(MagicEffectType.AddPoisonResistancePercentage, MagicEffectType.AddElementalResistancePercentage); - hit.m_damage.m_spirit *= sum(MagicEffectType.AddSpiritResistancePercentage, MagicEffectType.AddElementalResistancePercentage); + // elemental resistances + hit.m_damage.m_fire *= resultingDamageCoeff(MagicEffectType.AddFireResistancePercentage, MagicEffectType.AddElementalResistancePercentage); + hit.m_damage.m_frost *= resultingDamageCoeff(MagicEffectType.AddFrostResistancePercentage, MagicEffectType.AddElementalResistancePercentage); + hit.m_damage.m_lightning *= resultingDamageCoeff(MagicEffectType.AddLightningResistancePercentage, MagicEffectType.AddElementalResistancePercentage); + hit.m_damage.m_poison *= resultingDamageCoeff(MagicEffectType.AddPoisonResistancePercentage, MagicEffectType.AddElementalResistancePercentage); + hit.m_damage.m_spirit *= resultingDamageCoeff(MagicEffectType.AddSpiritResistancePercentage, MagicEffectType.AddElementalResistancePercentage); // physical resistances - hit.m_damage.m_blunt *= sum(MagicEffectType.AddBluntResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); - hit.m_damage.m_slash *= sum(MagicEffectType.AddSlashingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); - hit.m_damage.m_pierce *= sum(MagicEffectType.AddPiercingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); - hit.m_damage.m_chop *= sum(MagicEffectType.AddChoppingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); + hit.m_damage.m_blunt *= resultingDamageCoeff(MagicEffectType.AddBluntResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); + hit.m_damage.m_slash *= resultingDamageCoeff(MagicEffectType.AddSlashingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); + hit.m_damage.m_pierce *= resultingDamageCoeff(MagicEffectType.AddPiercingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); + hit.m_damage.m_chop *= resultingDamageCoeff(MagicEffectType.AddChoppingResistancePercentage, MagicEffectType.AddPhysicalResistancePercentage); } } } diff --git a/EpicLoot/MagicItemEffects/ReduceWeight.cs b/EpicLoot/MagicItemEffects/ReduceWeight.cs index 848cf05bc..966cd3439 100644 --- a/EpicLoot/MagicItemEffects/ReduceWeight.cs +++ b/EpicLoot/MagicItemEffects/ReduceWeight.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using System; namespace EpicLoot.MagicItemEffects { @@ -14,7 +15,7 @@ public static void Postfix(ItemDrop.ItemData __instance, ref float __result) } else if (__instance.HasMagicEffect(MagicEffectType.ReduceWeight)) { - var totalWeightReduction = __instance.GetMagicItem().GetTotalEffectValue(MagicEffectType.ReduceWeight, 0.01f); + var totalWeightReduction = Math.Min(__instance.GetMagicItem().GetTotalEffectValue(MagicEffectType.ReduceWeight, 0.01f), 1.0f); __result *= 1.0f - totalWeightReduction; } } diff --git a/EpicLoot/TextsDialog_Patch.cs b/EpicLoot/TextsDialog_Patch.cs index 195a7159a..92c07b274 100644 --- a/EpicLoot/TextsDialog_Patch.cs +++ b/EpicLoot/TextsDialog_Patch.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Text; using EpicLoot.Adventure; @@ -55,7 +56,7 @@ public static void AddMagicEffectsPage(TextsDialog textsDialog, Player player) { var effectType = entry.Key; var effectDef = MagicItemEffectDefinitions.Get(effectType); - var sum = entry.Value.Sum(x => x.Key.EffectValue); + float sum = (float)Math.Round(PlayerExtensions.GetEffectDiminishingReturnsTotalValue(entry.Value.Select(x => x.Key.EffectValue).ToList(), effectType)); var totalEffectText = MagicItem.GetEffectText(effectDef, sum); var highestRarity = (ItemRarity) entry.Value.Max(x => (int) x.Value.GetRarity());