From 5fd7c17cab75033224c546edaf948fd65ece993a Mon Sep 17 00:00:00 2001 From: Saereth Date: Thu, 7 May 2026 17:15:13 -0700 Subject: [PATCH 1/2] Add detailed tooltips for Sentient items These tooltips now display current Sentient level, Demon Will pool, bonus damage, and specific rider effects (such as, Wither duration, Absorption time, Movement Speed). Detailed stats are shown when holding Shift. --- .../assets/bloodmagic/lang/en_us.json | 9 ++ .../common/data/GeneratorLanguage.java | 10 ++ .../common/item/soul/ItemSentientAxe.java | 19 ++- .../common/item/soul/ItemSentientPickaxe.java | 20 ++- .../common/item/soul/ItemSentientScythe.java | 19 ++- .../common/item/soul/ItemSentientShovel.java | 20 ++- .../common/item/soul/ItemSentientSword.java | 20 ++- .../item/soul/SentientTooltipHelper.java | 140 ++++++++++++++++++ 8 files changed, 244 insertions(+), 13 deletions(-) create mode 100644 src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java diff --git a/src/generated/resources/assets/bloodmagic/lang/en_us.json b/src/generated/resources/assets/bloodmagic/lang/en_us.json index c3db05a64a..e335896365 100644 --- a/src/generated/resources/assets/bloodmagic/lang/en_us.json +++ b/src/generated/resources/assets/bloodmagic/lang/en_us.json @@ -871,6 +871,15 @@ "tooltip.bloodmagic.ritualReader.set_area": "Define Area", "tooltip.bloodmagic.ritualReader.set_will_types": "Set Will Consumed", "tooltip.bloodmagic.sacrificialdagger.desc": "Just a prick of the finger will suffice...", + "tooltip.bloodmagic.sentient.aoe": "AoE radius: %s", + "tooltip.bloodmagic.sentient.attuned": "Attuned: %s", + "tooltip.bloodmagic.sentient.bonusDamage": "%s bonus damage", + "tooltip.bloodmagic.sentient.inactive": "Inactive (gather more will)", + "tooltip.bloodmagic.sentient.levelPool": "Level %d (%s will)", + "tooltip.bloodmagic.sentient.rider.corrosive": "On hit: Wither %ss (Lv %d)", + "tooltip.bloodmagic.sentient.rider.digspeed": "Mining Speed: %s", + "tooltip.bloodmagic.sentient.rider.steadfast": "On kill: Absorption %ss", + "tooltip.bloodmagic.sentient.rider.vengeful": "Movement Speed: %s", "tooltip.bloodmagic.sentientAxe.desc": "Uses demon will to unleash its full potential.", "tooltip.bloodmagic.sentientPickaxe.desc": "Uses demon will to unleash its full potential.", "tooltip.bloodmagic.sentientScythe.desc": "Uses demon will to unleash its full potential.", diff --git a/src/main/java/wayoftime/bloodmagic/common/data/GeneratorLanguage.java b/src/main/java/wayoftime/bloodmagic/common/data/GeneratorLanguage.java index 78c6530589..b58071daa4 100644 --- a/src/main/java/wayoftime/bloodmagic/common/data/GeneratorLanguage.java +++ b/src/main/java/wayoftime/bloodmagic/common/data/GeneratorLanguage.java @@ -109,6 +109,16 @@ protected void addTranslations() add("tooltip.bloodmagic.currentBaseType.destructive", "Destructive"); add("tooltip.bloodmagic.currentBaseType.vengeful", "Vengeful"); add("tooltip.bloodmagic.currentBaseType.steadfast", "Steadfast"); + + add("tooltip.bloodmagic.sentient.attuned", "Attuned: %s"); + add("tooltip.bloodmagic.sentient.levelPool", "Level %d (%s will)"); + add("tooltip.bloodmagic.sentient.inactive", "Inactive (gather more will)"); + add("tooltip.bloodmagic.sentient.bonusDamage", "%s bonus damage"); + add("tooltip.bloodmagic.sentient.aoe", "AoE radius: %s"); + add("tooltip.bloodmagic.sentient.rider.corrosive", "On hit: Wither %ss (Lv %d)"); + add("tooltip.bloodmagic.sentient.rider.steadfast", "On kill: Absorption %ss"); + add("tooltip.bloodmagic.sentient.rider.vengeful", "Movement Speed: %s"); + add("tooltip.bloodmagic.sentient.rider.digspeed", "Mining Speed: %s"); add("tooltip.bloodmagic.sacrificialdagger.desc", "Just a prick of the finger will suffice..."); add("tooltip.bloodmagic.slate.desc", "Infused stone inside of a Blood Altar."); add("tooltip.bloodmagic.inscriber.desc", "The writing is on the wall..."); diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientAxe.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientAxe.java index 21e4df13d1..8e99392e74 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientAxe.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientAxe.java @@ -3,6 +3,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.Difficulty; @@ -300,8 +301,22 @@ public void appendHoverText(ItemStack stack, Level world, List toolti if (!stack.hasTag()) return; - tooltip.add(Component.translatable("tooltip.bloodmagic.sentientAxe.desc").withStyle(ChatFormatting.GRAY)); - tooltip.add(Component.translatable("tooltip.bloodmagic.currentType." + getCurrentType(stack).name().toLowerCase(Locale.ROOT)).withStyle(ChatFormatting.GRAY)); + EnumDemonWillType type = getCurrentType(stack); + Player player = Minecraft.getInstance().player; + double will = player != null ? PlayerDemonWillHandler.getTotalDemonWill(type, player) : 0; + int level = getLevel(stack, will); + + SentientTooltipHelper.appendSentientTooltip( + tooltip, + "tooltip.bloodmagic.sentientAxe.desc", + type, + level, + getExtraDamage(type, level), + null, + level >= 0 ? defaultDigSpeedAdded[level] : null, + poisonTime[Math.max(0, level)], poisonLevel[Math.max(0, level)], + absorptionTime[Math.max(0, level)], + type == EnumDemonWillType.VENGEFUL ? movementSpeed[Math.max(0, level)] : 0); } @Override diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientPickaxe.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientPickaxe.java index 1f75a561c9..69f03f9d8c 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientPickaxe.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientPickaxe.java @@ -3,6 +3,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.Difficulty; @@ -299,9 +300,22 @@ public void appendHoverText(ItemStack stack, Level world, List toolti if (!stack.hasTag()) return; -// tooltip.addAll(Arrays.asList(TextHelper.cutLongString(TextHelper.localizeEffect("tooltip.bloodmagic.sentientSword.desc")))); - tooltip.add(Component.translatable("tooltip.bloodmagic.sentientPickaxe.desc").withStyle(ChatFormatting.GRAY)); - tooltip.add(Component.translatable("tooltip.bloodmagic.currentType." + getCurrentType(stack).name().toLowerCase(Locale.ROOT)).withStyle(ChatFormatting.GRAY)); + EnumDemonWillType type = getCurrentType(stack); + Player player = Minecraft.getInstance().player; + double will = player != null ? PlayerDemonWillHandler.getTotalDemonWill(type, player) : 0; + int level = getLevel(stack, will); + + SentientTooltipHelper.appendSentientTooltip( + tooltip, + "tooltip.bloodmagic.sentientPickaxe.desc", + type, + level, + getExtraDamage(type, level), + null, + level >= 0 ? defaultDigSpeedAdded[level] : null, + poisonTime[Math.max(0, level)], poisonLevel[Math.max(0, level)], + absorptionTime[Math.max(0, level)], + type == EnumDemonWillType.VENGEFUL ? movementSpeed[Math.max(0, level)] : 0); } @Override diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientScythe.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientScythe.java index 7b7b9ed6be..929c5b8674 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientScythe.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientScythe.java @@ -3,6 +3,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -636,8 +637,22 @@ public void appendHoverText(ItemStack stack, Level world, List toolti if (!stack.hasTag()) return; - tooltip.add(Component.translatable("tooltip.bloodmagic.sentientScythe.desc").withStyle(ChatFormatting.GRAY)); - tooltip.add(Component.translatable("tooltip.bloodmagic.currentType." + getCurrentType(stack).name().toLowerCase(Locale.ROOT)).withStyle(ChatFormatting.GRAY)); + EnumDemonWillType type = getCurrentType(stack); + Player player = Minecraft.getInstance().player; + double will = player != null ? PlayerDemonWillHandler.getTotalDemonWill(type, player) : 0; + int level = getLevel(stack, will); + + SentientTooltipHelper.appendSentientTooltip( + tooltip, + "tooltip.bloodmagic.sentientScythe.desc", + type, + level, + getExtraDamage(type, level), + 2.0, + level >= 0 ? defaultDigSpeedAdded[level] : null, + poisonTime[Math.max(0, level)], poisonLevel[Math.max(0, level)], + absorptionTime[Math.max(0, level)], + type == EnumDemonWillType.VENGEFUL ? movementSpeed[Math.max(0, level)] : 0); } @Override diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientShovel.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientShovel.java index 6ea6a06bfb..946e1b5a11 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientShovel.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientShovel.java @@ -3,6 +3,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.Difficulty; @@ -300,9 +301,22 @@ public void appendHoverText(ItemStack stack, Level world, List toolti if (!stack.hasTag()) return; -// tooltip.addAll(Arrays.asList(TextHelper.cutLongString(TextHelper.localizeEffect("tooltip.bloodmagic.sentientSword.desc")))); - tooltip.add(Component.translatable("tooltip.bloodmagic.sentientShovel.desc").withStyle(ChatFormatting.GRAY)); - tooltip.add(Component.translatable("tooltip.bloodmagic.currentType." + getCurrentType(stack).name().toLowerCase(Locale.ROOT)).withStyle(ChatFormatting.GRAY)); + EnumDemonWillType type = getCurrentType(stack); + Player player = Minecraft.getInstance().player; + double will = player != null ? PlayerDemonWillHandler.getTotalDemonWill(type, player) : 0; + int level = getLevel(stack, will); + + SentientTooltipHelper.appendSentientTooltip( + tooltip, + "tooltip.bloodmagic.sentientShovel.desc", + type, + level, + getExtraDamage(type, level), + null, + level >= 0 ? defaultDigSpeedAdded[level] : null, + poisonTime[Math.max(0, level)], poisonLevel[Math.max(0, level)], + absorptionTime[Math.max(0, level)], + type == EnumDemonWillType.VENGEFUL ? movementSpeed[Math.max(0, level)] : 0); } @Override diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientSword.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientSword.java index 3143279e6e..0560bf9daa 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientSword.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/ItemSentientSword.java @@ -3,6 +3,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.Difficulty; @@ -293,9 +294,22 @@ public void appendHoverText(ItemStack stack, Level world, List toolti if (!stack.hasTag()) return; -// tooltip.addAll(Arrays.asList(TextHelper.cutLongString(TextHelper.localizeEffect("tooltip.bloodmagic.sentientSword.desc")))); - tooltip.add(Component.translatable("tooltip.bloodmagic.sentientSword.desc").withStyle(ChatFormatting.GRAY)); - tooltip.add(Component.translatable("tooltip.bloodmagic.currentType." + getCurrentType(stack).name().toLowerCase(Locale.ROOT)).withStyle(ChatFormatting.GRAY)); + EnumDemonWillType type = getCurrentType(stack); + Player player = Minecraft.getInstance().player; + double will = player != null ? PlayerDemonWillHandler.getTotalDemonWill(type, player) : 0; + int level = getLevel(stack, will); + + SentientTooltipHelper.appendSentientTooltip( + tooltip, + "tooltip.bloodmagic.sentientSword.desc", + type, + level, + getExtraDamage(type, level), + null, + null, + poisonTime[Math.max(0, level)], poisonLevel[Math.max(0, level)], + absorptionTime[Math.max(0, level)], + type == EnumDemonWillType.VENGEFUL ? movementSpeed[Math.max(0, level)] : 0); } @Override diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java new file mode 100644 index 0000000000..603da36611 --- /dev/null +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java @@ -0,0 +1,140 @@ +package wayoftime.bloodmagic.common.item.soul; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import wayoftime.bloodmagic.api.compat.EnumDemonWillType; +import wayoftime.bloodmagic.will.PlayerDemonWillHandler; + +import java.util.List; +import java.util.Locale; + +@OnlyIn(Dist.CLIENT) +public final class SentientTooltipHelper +{ + private SentientTooltipHelper() {} + + public static ChatFormatting colorFor(EnumDemonWillType type) + { + if (type == null) + return ChatFormatting.GRAY; + switch (type) + { + case CORROSIVE: + return ChatFormatting.GREEN; + case DESTRUCTIVE: + return ChatFormatting.GOLD; + case VENGEFUL: + return ChatFormatting.RED; + case STEADFAST: + return ChatFormatting.LIGHT_PURPLE; + case DEFAULT: + default: + return ChatFormatting.DARK_AQUA; + } + } + + public static void appendSentientTooltip( + List tooltip, + String flavourKey, + EnumDemonWillType type, + int level, + double bonusDamage, + Double aoeRadius, + Double digSpeedBonus, + int corrosiveWitherTimeTicks, + int corrosiveWitherAmplifier, + int steadfastAbsorptionTimeTicks, + double vengefulMovementSpeed) + { + tooltip.add(Component.translatable(flavourKey).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC)); + + ChatFormatting color = colorFor(type); + String typeKey = "tooltip.bloodmagic.currentBaseType." + type.name().toLowerCase(Locale.ROOT); + Component typeName = Component.translatable(typeKey).withStyle(color); + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.attuned", typeName).withStyle(ChatFormatting.GRAY)); + + if (!Screen.hasShiftDown()) + { + tooltip.add(Component.translatable("tooltip.bloodmagic.extraInfo").withStyle(ChatFormatting.DARK_GRAY)); + return; + } + + Player player = Minecraft.getInstance().player; + if (level >= 0 && type != EnumDemonWillType.DEFAULT && player != null) + { + double pool = PlayerDemonWillHandler.getTotalDemonWill(type, player); + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.levelPool", level + 1, formatNumber(pool)).withStyle(color)); + } else + { + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.inactive").withStyle(ChatFormatting.DARK_GRAY)); + return; + } + + if (bonusDamage > 0) + { + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.bonusDamage", formatSigned(bonusDamage)).withStyle(ChatFormatting.GRAY)); + } + if (aoeRadius != null) + { + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.aoe", formatNumber(aoeRadius)).withStyle(ChatFormatting.GRAY)); + } + + switch (type) + { + case CORROSIVE: + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.rider.corrosive", + formatNumber(corrosiveWitherTimeTicks / 20.0), + corrosiveWitherAmplifier + 1).withStyle(color)); + break; + case STEADFAST: + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.rider.steadfast", + formatNumber(steadfastAbsorptionTimeTicks / 20.0)).withStyle(color)); + break; + case VENGEFUL: + if (vengefulMovementSpeed > 0) + { + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.rider.vengeful", + formatPercent(vengefulMovementSpeed)).withStyle(color)); + } + break; + default: + break; + } + if (digSpeedBonus != null && digSpeedBonus > 0) + { + tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.rider.digspeed", formatSigned(digSpeedBonus)).withStyle(ChatFormatting.GRAY)); + } + } + + private static String formatNumber(double value) + { + if (value == Math.floor(value) && !Double.isInfinite(value)) + { + return String.format(Locale.ROOT, "%d", (long) value); + } + String s = String.format(Locale.ROOT, "%.2f", value); + if (s.contains(".")) + { + s = s.replaceAll("0+$", ""); + if (s.endsWith(".")) + s = s.substring(0, s.length() - 1); + } + return s; + } + + private static String formatSigned(double value) + { + String sign = value >= 0 ? "+" : ""; + return sign + formatNumber(value); + } + + private static String formatPercent(double value) + { + return formatNumber(value * 100) + "%"; + } +} From 41ed881d075ef525491298e5cb87dc3711cd1a7d Mon Sep 17 00:00:00 2001 From: Saereth Date: Fri, 8 May 2026 08:00:30 -0700 Subject: [PATCH 2/2] Fixed Vengeful Rider movement speed tooltip display --- .../bloodmagic/common/item/soul/SentientTooltipHelper.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java b/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java index 603da36611..04b38f744a 100644 --- a/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java +++ b/src/main/java/wayoftime/bloodmagic/common/item/soul/SentientTooltipHelper.java @@ -99,7 +99,7 @@ public static void appendSentientTooltip( if (vengefulMovementSpeed > 0) { tooltip.add(Component.translatable("tooltip.bloodmagic.sentient.rider.vengeful", - formatPercent(vengefulMovementSpeed)).withStyle(color)); + formatSigned(vengefulMovementSpeed)).withStyle(color)); } break; default: @@ -133,8 +133,4 @@ private static String formatSigned(double value) return sign + formatNumber(value); } - private static String formatPercent(double value) - { - return formatNumber(value * 100) + "%"; - } }