From ca361049f5e9ef89adf5e848c7f48dd924396e54 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 22 May 2024 13:25:32 +0100 Subject: [PATCH] Surface spell attributes to the user in gemstone tooltips --- .../spell/effect/CustomisedSpellType.java | 30 +++++++++++++++++++ .../magic/spell/effect/ShieldSpell.java | 25 ++++++++++++++++ .../ability/magic/spell/effect/SpellType.java | 23 +++++++++++--- .../client/gui/DismissSpellScreen.java | 4 +-- .../unicopia/entity/effect/EffectUtils.java | 10 +++++++ .../unicopia/item/GemstoneItem.java | 18 +---------- .../resources/assets/unicopia/lang/en_us.json | 6 ++++ 7 files changed, 92 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java index bd0e73e8..9a62d4db 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java @@ -1,15 +1,24 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; +import java.util.ArrayList; +import java.util.List; + import org.jetbrains.annotations.Nullable; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.client.TextHelper; +import com.minelittlepony.unicopia.entity.effect.EffectUtils; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.TypedActionResult; public record CustomisedSpellType ( @@ -70,6 +79,27 @@ public record CustomisedSpellType ( return traits.applyTo(type.getDefualtStack()); } + public void appendTooltip(List lines) { + MutableText lore = Text.translatable(type().getTranslationKey() + ".lore").formatted(type().getAffinity().getColor()); + + if (!InteractionManager.getInstance().getClientSpecies().canCast()) { + lore = lore.formatted(Formatting.OBFUSCATED); + } + lines.addAll(TextHelper.wrap(lore, 180).toList()); + float corruption = ((int)traits().getCorruption() * 10) + type().getAffinity().getCorruption(); + List modifiers = new ArrayList<>(); + type.getTooltip().accept(this, modifiers); + if (corruption != 0) { + modifiers.add(EffectUtils.formatModifierChange("affinity.unicopia.corruption", corruption, true)); + } + if (!modifiers.isEmpty()) { + lines.add(Text.empty()); + lines.add(Text.translatable("affinity.unicopia.when_cast").formatted(Formatting.GRAY)); + lines.addAll(modifiers); + } + + } + public TypedActionResult> toAction() { return isEmpty() ? TypedActionResult.fail(this) : TypedActionResult.pass(this); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java index 23ceb121..da5e5dc2 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; +import java.util.List; import java.util.Optional; import com.minelittlepony.unicopia.Affinity; @@ -12,6 +13,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate; +import com.minelittlepony.unicopia.entity.effect.EffectUtils; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect; @@ -33,6 +35,8 @@ import net.minecraft.entity.passive.PassiveEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.vehicle.AbstractMinecartEntity; import net.minecraft.entity.vehicle.BoatEntity; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -44,6 +48,27 @@ public class ShieldSpell extends AbstractSpell { .with(Trait.AIR, 9) .build(); + static void appendTooltip(CustomisedSpellType type, List tooltip) { + float addedRange = type.traits().get(Trait.POWER); + if (addedRange != 0) { + tooltip.add(EffectUtils.formatModifierChange("spell.unicopia.shield.additional_range", addedRange, false)); + } + if (type.traits().get(Trait.LIFE) > 0) { + tooltip.add(Text.literal(" ").append(Text.translatable("spell.unicopia.shield.permit.passive")).formatted(Formatting.GRAY)); + } + if (type.traits().get(Trait.BLOOD) > 0) { + tooltip.add(Text.literal(" ").append(Text.translatable("spell.unicopia.shield.permit.hostile")).formatted(Formatting.GRAY)); + } + if (type.traits().get(Trait.ICE) > 0) { + tooltip.add(Text.literal(" ").append(Text.translatable("spell.unicopia.shield.permit.player")).formatted(Formatting.GRAY)); + } + if (type.traits().get(Trait.GENEROSITY) > 0) { + tooltip.add(Text.literal(" ").append(Text.translatable("spell.unicopia.shield.caston.location")).formatted(Formatting.GRAY)); + } else { + tooltip.add(Text.literal(" ").append(Text.translatable("spell.unicopia.shield.caston.person")).formatted(Formatting.GRAY)); + } + } + protected final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget); private final Lerp radius = new Lerp(0); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java index d3efed08..6bbf0219 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java @@ -1,5 +1,7 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; +import java.util.List; +import java.util.function.BiConsumer; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.Affinity; @@ -34,7 +36,7 @@ import net.minecraft.server.command.ServerCommandSource; public final class SpellType implements Affine, SpellPredicate { public static final Identifier EMPTY_ID = Unicopia.id("none"); - public static final SpellType EMPTY_KEY = new SpellType<>(EMPTY_ID, Affinity.NEUTRAL, 0xFFFFFF, false, false, GemstoneItem.Shape.ROUND, SpellTraits.EMPTY, t -> null); + public static final SpellType EMPTY_KEY = builder(t -> null).affinity(Affinity.NEUTRAL).color(0xFFFFFF).unobtainable().build(EMPTY_ID); public static final Registry> REGISTRY = RegistryUtils.createSimple(Unicopia.id("spells")); public static final RegistryKey>> REGISTRY_KEY = REGISTRY.getKey(); @@ -55,7 +57,7 @@ public final class SpellType implements Affine, SpellPredicate< public static final SpellType SCORCH = register("scorch", builder(ScorchSpell::new).affinity(Affinity.BAD).color(0xF8EC1F).stackable().shape(GemstoneItem.Shape.FLAME).traits(ScorchSpell.DEFAULT_TRAITS)); public static final SpellType FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS)); public static final SpellType INFERNAL = register("infernal", builder(InfernoSpell::new).affinity(Affinity.BAD).color(0xFFAA00).shape(GemstoneItem.Shape.FLAME).traits(InfernoSpell.DEFAULT_TRAITS)); - public static final SpellType SHIELD = register("shield", builder(ShieldSpell::new).affinity(Affinity.NEUTRAL).color(0x66CDAA).shape(GemstoneItem.Shape.SHIELD).traits(ShieldSpell.DEFAULT_TRAITS)); + public static final SpellType SHIELD = register("shield", builder(ShieldSpell::new).affinity(Affinity.NEUTRAL).color(0x66CDAA).shape(GemstoneItem.Shape.SHIELD).traits(ShieldSpell.DEFAULT_TRAITS).tooltip(ShieldSpell::appendTooltip)); public static final SpellType ARCANE_PROTECTION = register("arcane_protection", builder(AreaProtectionSpell::new).affinity(Affinity.BAD).color(0x99CDAA).shape(GemstoneItem.Shape.SHIELD).traits(AreaProtectionSpell.DEFAULT_TRAITS)); public static final SpellType VORTEX = register("vortex", builder(AttractiveSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEA88).shape(GemstoneItem.Shape.VORTEX).traits(AttractiveSpell.DEFAULT_TRAITS)); public static final SpellType DARK_VORTEX = register("dark_vortex", builder(DarkVortexSpell::new).affinity(Affinity.BAD).color(0xA33333).stackable().shape(GemstoneItem.Shape.VORTEX).traits(DarkVortexSpell.DEFAULT_TRAITS)); @@ -95,12 +97,15 @@ public final class SpellType implements Affine, SpellPredicate< private final ItemStack defaultStack; - private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, Factory factory) { + private final BiConsumer, List> tooltipFunction; + + private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, BiConsumer, List> tooltipFunction, Factory factory) { this.id = id; this.affinity = affinity; this.color = color; this.obtainable = obtainable; this.shape = shape; + this.tooltipFunction = tooltipFunction; this.factory = factory; this.traits = traits; this.stackable = stackable; @@ -167,6 +172,10 @@ public final class SpellType implements Affine, SpellPredicate< return factory; } + public BiConsumer, List> getTooltip() { + return tooltipFunction; + } + @Override public boolean test(@Nullable Spell spell) { return spell != null && spell.getTypeAndTraits().type() == this; @@ -228,6 +237,7 @@ public final class SpellType implements Affine, SpellPredicate< private boolean stackable = false; private GemstoneItem.Shape shape = GemstoneItem.Shape.ROUND; private SpellTraits traits = SpellTraits.EMPTY; + private BiConsumer, List> tooltipFunction = (t, l) -> {}; Builder(Factory factory) { this.factory = factory; @@ -263,8 +273,13 @@ public final class SpellType implements Affine, SpellPredicate< return this; } + public Builder tooltip(BiConsumer, List> tooltipFunction) { + this.tooltipFunction = tooltipFunction; + return this; + } + public SpellType build(Identifier id) { - return new SpellType<>(id, affinity, color, obtainable, stackable, shape, traits, factory); + return new SpellType<>(id, affinity, color, obtainable, stackable, shape, traits, tooltipFunction, factory); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index 85028253..873f7d10 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -9,7 +9,6 @@ import com.minelittlepony.common.client.gui.GameGui; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.*; -import com.minelittlepony.unicopia.client.TextHelper; import com.minelittlepony.unicopia.client.render.model.SphereModel; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.UItems; @@ -191,9 +190,8 @@ public class DismissSpellScreen extends GameGui { tooltip.add(Text.translatable("gui.unicopia.dispell_screen.spell_type", name)); type.traits().appendTooltip(tooltip); tooltip.add(ScreenTexts.EMPTY); - tooltip.add(Text.translatable("gui.unicopia.dispell_screen.affinity", affinity.getDisplayName())); + type.appendTooltip(tooltip); tooltip.add(ScreenTexts.EMPTY); - tooltip.addAll(TextHelper.wrap(Text.translatable(type.type().getTranslationKey() + ".lore").formatted(affinity.getColor()), 180).toList()); if (spell instanceof TimedSpell timed) { tooltip.add(ScreenTexts.EMPTY); tooltip.add(Text.translatable("gui.unicopia.dispell_screen.time_left", StringHelper.formatTicks(timed.getTimer().getTicksRemaining()))); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/EffectUtils.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/EffectUtils.java index 208ccf04..f60e6876 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/EffectUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/EffectUtils.java @@ -3,6 +3,9 @@ package com.minelittlepony.unicopia.entity.effect; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; public interface EffectUtils { static boolean isPoisoned(LivingEntity entity) { @@ -46,4 +49,11 @@ public interface EffectUtils { } return false; } + + static Text formatModifierChange(String modifierName, float change, boolean isDetrimental) { + return Text.translatable("attribute.modifier." + (change > 0 ? "plus" : "take") + ".addition", + ItemStack.MODIFIER_FORMAT.format(Math.abs(change)), + Text.translatable(modifierName) + ).formatted((isDetrimental ? change : -change) < 0 ? Formatting.DARK_GREEN : Formatting.RED); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java b/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java index 3ccf6cae..c554972c 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java @@ -8,7 +8,6 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; -import com.minelittlepony.unicopia.client.TextHelper; import com.minelittlepony.unicopia.entity.player.PlayerCharmTracker; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.group.MultiItem; @@ -17,9 +16,7 @@ import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.TypedActionResult; import net.minecraft.world.World; @@ -80,20 +77,7 @@ public class GemstoneItem extends Item implements MultiItem, EnchantableItem { super.appendTooltip(stack, world, lines, tooltipContext); if (EnchantableItem.isEnchanted(stack)) { - CustomisedSpellType type = getSpellEffect(stack); - - MutableText line = Text.translatable(type.type().getTranslationKey() + ".lore").formatted(type.type().getAffinity().getColor()); - - if (!InteractionManager.getInstance().getClientSpecies().canCast()) { - line = line.formatted(Formatting.OBFUSCATED); - } - lines.addAll(TextHelper.wrap(line, 180).toList()); - lines.add(Text.empty()); - float corruption = ((int)type.traits().getCorruption() * 10) + type.type().getAffinity().getCorruption(); - if (corruption != 0) { - lines.add(Text.translatable("affinity.unicopia.when_cast").formatted(Formatting.GRAY)); - lines.add(Text.translatable("affinity.unicopia.corruption", corruption > 0 ? "+" : "-", ItemStack.MODIFIER_FORMAT.format(Math.abs(corruption))).formatted(corruption < 0 ? Formatting.DARK_GREEN : Formatting.RED)); - } + getSpellEffect(stack).appendTooltip(lines); } } diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index fa43ed75..91ec6e3c 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -548,6 +548,12 @@ "spell.unicopia.fire_bolt": "Fire Bolt", "spell.unicopia.fire_bolt.lore": "Produces several burning projectiles", "spell.unicopia.shield": "Protection", + "spell.unicopia.shield.additional_range": "Additional Range", + "spell.unicopia.shield.permit.passive": "Permits Passive Mobs", + "spell.unicopia.shield.permit.hostile": "Permits Hostile Mobs", + "spell.unicopia.shield.permit.player": " Permits Other Players", + "spell.unicopia.shield.caston.location": "Applies to location", + "spell.unicopia.shield.caston.person": "Applies to self", "spell.unicopia.shield.lore": "Casts a protective shield around the user", "spell.unicopia.bubble": "Bubble", "spell.unicopia.bubble.lore": "Traps any creature it hits in a soap bubble",