From 1363004eef4fee80e8262ec2724523f2aa8aa17f Mon Sep 17 00:00:00 2001 From: jneb802 <73610029+jneb802@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:01:50 -0700 Subject: [PATCH] fix: show boss shard scaling in tooltips --- EpicLoot/EpicLoot.cs | 5 +++ EpicLoot/localizations/English.json | 12 +++--- .../Shards/BonemassCorpseRot.cs | 19 +++++++-- .../Shards/ElderForestsAid.cs | 27 ++++++++---- .../Shards/FaderNecroticFire.cs | 5 +++ .../Shards/ModerIcyRetribution.cs | 42 ++++++++++++++++--- .../MagicItemEffects/Shards/QueenEverflow.cs | 5 +++ 7 files changed, 93 insertions(+), 22 deletions(-) diff --git a/EpicLoot/EpicLoot.cs b/EpicLoot/EpicLoot.cs index 252ab1f7..f291a7cd 100644 --- a/EpicLoot/EpicLoot.cs +++ b/EpicLoot/EpicLoot.cs @@ -151,6 +151,11 @@ private static void RegisterMagicEffectEvents() { MagicItemEffects.Shards.LuckyLoot.RegisterDisplayValues(); MagicItemEffects.Shards.Bloodrage.RegisterDisplayValues(); MagicItemEffects.Shards.MeteorSummoner.RegisterDisplayValues(); + MagicItemEffects.Shards.ElderForestsAid.RegisterDisplayValues(); + MagicItemEffects.Shards.BonemassCorpseRot.RegisterDisplayValues(); + MagicItemEffects.Shards.ModerIcyRetribution.RegisterDisplayValues(); + MagicItemEffects.Shards.QueenEverflow.RegisterDisplayValues(); + MagicItemEffects.Shards.NecroticFire.RegisterDisplayValues(); MagicItemEffects.Shards.BlockAsDodgeAsBlock.RegisterDisplayValues(); MagicItemEffects.Shards.BlockAsWoodCuttingAndPickaxes.RegisterDisplayValues(); diff --git a/EpicLoot/localizations/English.json b/EpicLoot/localizations/English.json index 3dc4100e..8153ff39 100644 --- a/EpicLoot/localizations/English.json +++ b/EpicLoot/localizations/English.json @@ -658,17 +658,17 @@ "mod_epicloot_me_shockingcharge_display": "Shocking Charge", "mod_epicloot_me_shockingcharge_desc": "Your combat hits build charges. At max charge, the next hit unleashes a forward lightning shockwave that deals a portion of your previous hits' damage.", - "mod_epicloot_me_forestsaid_display": "Forest's Aid", + "mod_epicloot_me_forestsaid_display": "Forest's Aid: {0:0.#}m Radius, {1:0.#}s Cooldown", "mod_epicloot_me_forestsaid_desc": "When you are hit, ensnaring roots erupt and immobilize nearby enemies.", - "mod_epicloot_me_corpserot_display": "Corpse Rot", + "mod_epicloot_me_corpserot_display": "Corpse Rot: {0:0.#} Poison, {1:0.#}s Cooldown, {2:0.#}m Radius", "mod_epicloot_me_corpserot_desc": "Enemies you kill can burst in a cloud of venom, poisoning nearby foes.", - "mod_epicloot_me_icyretribution_display": "Icy Retribution", + "mod_epicloot_me_icyretribution_display": "Icy Retribution: {0:0.#} Frost, {1:0.#}s Cooldown", "mod_epicloot_me_icyretribution_desc": "When you are hit, detonate a frost nova around you. Cooldown scales with rarity.", "mod_epicloot_me_meteorsummoner_display": "Meteor Summoner: {0}x Hit Damage", "mod_epicloot_me_meteorsummoner_desc": "Every {1} weapon hits, your next hit calls down a fiery meteor on the target that deals {0}x that hit's damage as fire.", - "mod_epicloot_me_everflow_display": "Queen's Everflow", + "mod_epicloot_me_everflow_display": "Queen's Everflow: +{0:0.#}% Regen per Stack (max {1}, {2:0.#}s)", "mod_epicloot_me_everflow_desc": "Killing a creature grants a stacking buff that boosts your health, stamina and eitr regeneration.", - "mod_epicloot_me_necroticfire_display": "Necrotic Fire", + "mod_epicloot_me_necroticfire_display": "Necrotic Fire: {0:0.#}% Physical as Fire and Poison", "mod_epicloot_me_necroticfire_desc": "Strips all physical damage from your weapon and adds that full amount as both fire and poison damage.", @@ -2179,4 +2179,4 @@ "mod_epicloot_criticalsuccess": "Critical Success", "mod_epicloot_criticalfail": "Critical Fail", "mod_epicloot_temper": "Temper" -} \ No newline at end of file +} diff --git a/EpicLoot/src/Magic/MagicItemEffects/Shards/BonemassCorpseRot.cs b/EpicLoot/src/Magic/MagicItemEffects/Shards/BonemassCorpseRot.cs index e8a74124..94cb622d 100644 --- a/EpicLoot/src/Magic/MagicItemEffects/Shards/BonemassCorpseRot.cs +++ b/EpicLoot/src/Magic/MagicItemEffects/Shards/BonemassCorpseRot.cs @@ -24,6 +24,20 @@ public static class BonemassCorpseRot { { PoisonPerTierKey, DefaultPoisonPerTier }, }; + public static void RegisterDisplayValues() { + MagicItem.RegisterDisplayValues(MagicEffectType.CorpseRot, + value => new object[] { GetPoisonDamage(value), GetCooldown(), GetRadius() }); + } + + private static float GetPoisonDamage(float value) { + return value * EffectConfig.Get(MagicEffectType.CorpseRot, + PoisonPerTierKey, DefaultPoisonPerTier); + } + + private static float GetRadius() { + return EffectConfig.Get(MagicEffectType.CorpseRot, RadiusKey, DefaultRadius); + } + // Floored just above zero: a ttl of 0 is "no timeout" to vanilla, which would gate the shard // permanently rather than removing the cooldown. private static float GetCooldown() { @@ -66,10 +80,9 @@ private static void Postfix(Character __instance) { var center = __instance.GetCenterPoint(); SpawnExplosionFx(__instance.transform.position); DamageInRadius.DamageEnemiesInRadius(player, center, - EffectConfig.Get(MagicEffectType.CorpseRot, RadiusKey, DefaultRadius), + GetRadius(), new HitData.DamageTypes { - m_poison = value * EffectConfig.Get(MagicEffectType.CorpseRot, - PoisonPerTierKey, DefaultPoisonPerTier) + m_poison = GetPoisonDamage(value) }); ShowCooldown(player); } diff --git a/EpicLoot/src/Magic/MagicItemEffects/Shards/ElderForestsAid.cs b/EpicLoot/src/Magic/MagicItemEffects/Shards/ElderForestsAid.cs index 439f1cd2..17416349 100644 --- a/EpicLoot/src/Magic/MagicItemEffects/Shards/ElderForestsAid.cs +++ b/EpicLoot/src/Magic/MagicItemEffects/Shards/ElderForestsAid.cs @@ -27,6 +27,23 @@ public static class ElderForestsAid { { RadiusPerTierKey, DefaultRadiusPerTier }, }; + public static void RegisterDisplayValues() { + MagicItem.RegisterDisplayValues(MagicEffectType.ForestsAid, + value => new object[] { GetRadius(value), GetCooldown(value) }); + } + + private static float GetRadius(float value) { + return EffectConfig.Get(MagicEffectType.ForestsAid, BaseRadiusKey, DefaultBaseRadius) + + value * EffectConfig.Get(MagicEffectType.ForestsAid, RadiusPerTierKey, DefaultRadiusPerTier); + } + + private static float GetCooldown(float value) { + return Mathf.Max(0.1f, + EffectConfig.Get(MagicEffectType.ForestsAid, CooldownKey, DefaultCooldown) + + value * EffectConfig.Get(MagicEffectType.ForestsAid, + CooldownPerValueKey, DefaultCooldownPerValue)); + } + private const string ImmobilizeSE = "ImmobilizedAshlands"; private const string HitFxPrefab = "fx_natureweapon_hit"; private static readonly int ImmobilizeHash = ImmobilizeSE.GetStableHashCode(); @@ -55,14 +72,8 @@ public static void OnDamageTaken(Character __instance, HitData hit) { return; } - var radius = EffectConfig.Get(MagicEffectType.ForestsAid, BaseRadiusKey, DefaultBaseRadius) - + value * EffectConfig.Get(MagicEffectType.ForestsAid, RadiusPerTierKey, DefaultRadiusPerTier); - // Cooldown floored just above zero: a ttl of 0 is "no timeout" to vanilla, which would gate the - // shard permanently rather than removing the cooldown. - var cooldown = Mathf.Max(0.1f, - EffectConfig.Get(MagicEffectType.ForestsAid, CooldownKey, DefaultCooldown) - + value * EffectConfig.Get(MagicEffectType.ForestsAid, - CooldownPerValueKey, DefaultCooldownPerValue)); + float radius = GetRadius(value); + float cooldown = GetCooldown(value); Immobilize(player, radius); ShowCooldown(player, cooldown); diff --git a/EpicLoot/src/Magic/MagicItemEffects/Shards/FaderNecroticFire.cs b/EpicLoot/src/Magic/MagicItemEffects/Shards/FaderNecroticFire.cs index 2e97e1eb..95c33b2e 100644 --- a/EpicLoot/src/Magic/MagicItemEffects/Shards/FaderNecroticFire.cs +++ b/EpicLoot/src/Magic/MagicItemEffects/Shards/FaderNecroticFire.cs @@ -3,6 +3,11 @@ namespace EpicLoot.MagicItemEffects.Shards { // Provides a conversion of physical damage to fire and poison damage based on the player's Necrotic Fire effect value. public static class NecroticFire { + public static void RegisterDisplayValues() { + MagicItem.RegisterDisplayValues(MagicEffectType.NecroticFire, + value => new object[] { value * 100f }); + } + // GetDamage postfix handler invoked by ModifyDamage (per-weapon modifier). public static void ModifyWeaponDamage(ItemDrop.ItemData __instance, ref HitData.DamageTypes __result) { // Only when the local player has this weapon equipped (also gates the weapon tooltip). diff --git a/EpicLoot/src/Magic/MagicItemEffects/Shards/ModerIcyRetribution.cs b/EpicLoot/src/Magic/MagicItemEffects/Shards/ModerIcyRetribution.cs index 591ff1ec..09929bf9 100644 --- a/EpicLoot/src/Magic/MagicItemEffects/Shards/ModerIcyRetribution.cs +++ b/EpicLoot/src/Magic/MagicItemEffects/Shards/ModerIcyRetribution.cs @@ -23,6 +23,35 @@ public static class ModerIcyRetribution { { CooldownPerRarityKey, DefaultCooldownPerRarity }, }; + public static void RegisterDisplayValues() { + MagicItem.RegisterDisplayValues(MagicEffectType.IcyRetribution, + value => new object[] { GetFrostDamage(value), GetCooldownFromValue(value) }); + } + + private static float GetFrostDamage(float value) { + return value * EffectConfig.Get(MagicEffectType.IcyRetribution, + FrostPerTierKey, DefaultFrostPerTier); + } + + // The display provider receives the stored shard value but not its source rarity. Select the closest + // configured value so custom rarity ramps still show the cooldown used by that rarity. + private static float GetCooldownFromValue(float value) { + ItemRarity closestRarity = ItemRarity.Epic; + float closestDifference = float.MaxValue; + ShardStones.ShardEffectDefinition effect = + ShardStones.Shards.ShardDefinitions.Get(ShardStones.ShardType.Moder)?.UniformEffect; + if (effect != null) { + foreach (KeyValuePair entry in effect.ValuesPerRarity) { + float difference = Mathf.Abs(entry.Value - value); + if (difference < closestDifference) { + closestDifference = difference; + closestRarity = entry.Key; + } + } + } + return GetCooldown(closestRarity); + } + // Visual: our own trimmed copy of the fenring's ice nova, built and cached by FrostNovaFx so the // fenring's full-length nova is left untouched. Played at the helper's default speed. private const string NovaTemplateName = "EL_ModerIcyRetributionNova"; @@ -58,8 +87,7 @@ public static void OnDamageTaken(Character __instance, HitData hit) { DamageInRadius.DamageEnemiesInRadius(player, player.GetCenterPoint(), EffectConfig.Get(MagicEffectType.IcyRetribution, RadiusKey, DefaultRadius), new HitData.DamageTypes { - m_frost = value * EffectConfig.Get(MagicEffectType.IcyRetribution, - FrostPerTierKey, DefaultFrostPerTier) + m_frost = GetFrostDamage(value) }); ShowCooldown(player, GetCooldown(player)); } @@ -68,10 +96,14 @@ public static void OnDamageTaken(Character __instance, HitData hit) { // 140s at Epic, +20s for each rarity above it (Legendary 160s, Mythic 180s). Floored just above zero: // a ttl of 0 is "no timeout" to vanilla, which would gate the shard permanently. private static float GetCooldown(Player player) { - var stepsAboveEpic = Mathf.Max(0, (int)GetEffectRarity(player) - (int)ItemRarity.Epic); - var baseCooldown = EffectConfig.Get(MagicEffectType.IcyRetribution, + return GetCooldown(GetEffectRarity(player)); + } + + private static float GetCooldown(ItemRarity rarity) { + int stepsAboveEpic = Mathf.Max(0, (int)rarity - (int)ItemRarity.Epic); + float baseCooldown = EffectConfig.Get(MagicEffectType.IcyRetribution, BaseCooldownKey, DefaultBaseCooldown); - var perRarity = EffectConfig.Get(MagicEffectType.IcyRetribution, + float perRarity = EffectConfig.Get(MagicEffectType.IcyRetribution, CooldownPerRarityKey, DefaultCooldownPerRarity); return Mathf.Max(0.1f, baseCooldown + stepsAboveEpic * perRarity); } diff --git a/EpicLoot/src/Magic/MagicItemEffects/Shards/QueenEverflow.cs b/EpicLoot/src/Magic/MagicItemEffects/Shards/QueenEverflow.cs index ba450bb5..fddc21ec 100644 --- a/EpicLoot/src/Magic/MagicItemEffects/Shards/QueenEverflow.cs +++ b/EpicLoot/src/Magic/MagicItemEffects/Shards/QueenEverflow.cs @@ -23,6 +23,11 @@ public static class QueenEverflow { { BuffDurationKey, DefaultBuffDuration }, }; + public static void RegisterDisplayValues() { + MagicItem.RegisterDisplayValues(MagicEffectType.Everflow, + value => new object[] { value, (float)GetMaxStacks(), GetBuffDuration() }); + } + private const string BuffName = "EL_QueenEverflow"; private static readonly int BuffHash = BuffName.GetStableHashCode(); private static SE_QueenEverflow _buffPrototype;