Surface spell attributes to the user in gemstone tooltips

This commit is contained in:
Sollace 2024-05-22 13:25:32 +01:00
parent 9e2135fde3
commit ca361049f5
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
7 changed files with 92 additions and 24 deletions

View file

@ -1,15 +1,24 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect; package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
import com.minelittlepony.unicopia.ability.magic.spell.Spell; 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.SpellTraits;
import com.minelittlepony.unicopia.client.TextHelper;
import com.minelittlepony.unicopia.entity.effect.EffectUtils;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound; 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; import net.minecraft.util.TypedActionResult;
public record CustomisedSpellType<T extends Spell> ( public record CustomisedSpellType<T extends Spell> (
@ -70,6 +79,27 @@ public record CustomisedSpellType<T extends Spell> (
return traits.applyTo(type.getDefualtStack()); return traits.applyTo(type.getDefualtStack());
} }
public void appendTooltip(List<Text> 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<Text> 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<CustomisedSpellType<?>> toAction() { public TypedActionResult<CustomisedSpellType<?>> toAction() {
return isEmpty() ? TypedActionResult.fail(this) : TypedActionResult.pass(this); return isEmpty() ? TypedActionResult.fail(this) : TypedActionResult.pass(this);
} }

View file

@ -1,5 +1,6 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect; package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.minelittlepony.unicopia.Affinity; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate; 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.entity.player.Pony;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.MagicParticleEffect; 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.player.PlayerEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity; import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.entity.vehicle.BoatEntity; 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.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -44,6 +48,27 @@ public class ShieldSpell extends AbstractSpell {
.with(Trait.AIR, 9) .with(Trait.AIR, 9)
.build(); .build();
static void appendTooltip(CustomisedSpellType<ShieldSpell> type, List<Text> 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); protected final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget);
private final Lerp radius = new Lerp(0); private final Lerp radius = new Lerp(0);

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect; package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.List;
import java.util.function.BiConsumer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.Affinity;
@ -34,7 +36,7 @@ import net.minecraft.server.command.ServerCommandSource;
public final class SpellType<T extends Spell> implements Affine, SpellPredicate<T> { public final class SpellType<T extends Spell> implements Affine, SpellPredicate<T> {
public static final Identifier EMPTY_ID = Unicopia.id("none"); 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<SpellType<?>> REGISTRY = RegistryUtils.createSimple(Unicopia.id("spells")); public static final Registry<SpellType<?>> REGISTRY = RegistryUtils.createSimple(Unicopia.id("spells"));
public static final RegistryKey<? extends Registry<SpellType<?>>> REGISTRY_KEY = REGISTRY.getKey(); public static final RegistryKey<? extends Registry<SpellType<?>>> REGISTRY_KEY = REGISTRY.getKey();
@ -55,7 +57,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
public static final SpellType<ScorchSpell> SCORCH = register("scorch", builder(ScorchSpell::new).affinity(Affinity.BAD).color(0xF8EC1F).stackable().shape(GemstoneItem.Shape.FLAME).traits(ScorchSpell.DEFAULT_TRAITS)); public static final SpellType<ScorchSpell> SCORCH = register("scorch", builder(ScorchSpell::new).affinity(Affinity.BAD).color(0xF8EC1F).stackable().shape(GemstoneItem.Shape.FLAME).traits(ScorchSpell.DEFAULT_TRAITS));
public static final SpellType<FireSpell> FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS)); public static final SpellType<FireSpell> FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS));
public static final SpellType<InfernoSpell> INFERNAL = register("infernal", builder(InfernoSpell::new).affinity(Affinity.BAD).color(0xFFAA00).shape(GemstoneItem.Shape.FLAME).traits(InfernoSpell.DEFAULT_TRAITS)); public static final SpellType<InfernoSpell> INFERNAL = register("infernal", builder(InfernoSpell::new).affinity(Affinity.BAD).color(0xFFAA00).shape(GemstoneItem.Shape.FLAME).traits(InfernoSpell.DEFAULT_TRAITS));
public static final SpellType<ShieldSpell> SHIELD = register("shield", builder(ShieldSpell::new).affinity(Affinity.NEUTRAL).color(0x66CDAA).shape(GemstoneItem.Shape.SHIELD).traits(ShieldSpell.DEFAULT_TRAITS)); public static final SpellType<ShieldSpell> 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<AreaProtectionSpell> 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<AreaProtectionSpell> 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<AttractiveSpell> VORTEX = register("vortex", builder(AttractiveSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEA88).shape(GemstoneItem.Shape.VORTEX).traits(AttractiveSpell.DEFAULT_TRAITS)); public static final SpellType<AttractiveSpell> VORTEX = register("vortex", builder(AttractiveSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEA88).shape(GemstoneItem.Shape.VORTEX).traits(AttractiveSpell.DEFAULT_TRAITS));
public static final SpellType<DarkVortexSpell> DARK_VORTEX = register("dark_vortex", builder(DarkVortexSpell::new).affinity(Affinity.BAD).color(0xA33333).stackable().shape(GemstoneItem.Shape.VORTEX).traits(DarkVortexSpell.DEFAULT_TRAITS)); public static final SpellType<DarkVortexSpell> 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<T extends Spell> implements Affine, SpellPredicate<
private final ItemStack defaultStack; private final ItemStack defaultStack;
private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, Factory<T> factory) { private final BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction;
private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction, Factory<T> factory) {
this.id = id; this.id = id;
this.affinity = affinity; this.affinity = affinity;
this.color = color; this.color = color;
this.obtainable = obtainable; this.obtainable = obtainable;
this.shape = shape; this.shape = shape;
this.tooltipFunction = tooltipFunction;
this.factory = factory; this.factory = factory;
this.traits = traits; this.traits = traits;
this.stackable = stackable; this.stackable = stackable;
@ -167,6 +172,10 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
return factory; return factory;
} }
public BiConsumer<CustomisedSpellType<T>, List<Text>> getTooltip() {
return tooltipFunction;
}
@Override @Override
public boolean test(@Nullable Spell spell) { public boolean test(@Nullable Spell spell) {
return spell != null && spell.getTypeAndTraits().type() == this; return spell != null && spell.getTypeAndTraits().type() == this;
@ -228,6 +237,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
private boolean stackable = false; private boolean stackable = false;
private GemstoneItem.Shape shape = GemstoneItem.Shape.ROUND; private GemstoneItem.Shape shape = GemstoneItem.Shape.ROUND;
private SpellTraits traits = SpellTraits.EMPTY; private SpellTraits traits = SpellTraits.EMPTY;
private BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction = (t, l) -> {};
Builder(Factory<T> factory) { Builder(Factory<T> factory) {
this.factory = factory; this.factory = factory;
@ -263,8 +273,13 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
return this; return this;
} }
public Builder<T> tooltip(BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction) {
this.tooltipFunction = tooltipFunction;
return this;
}
public SpellType<T> build(Identifier id) { public SpellType<T> 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);
} }
} }
} }

View file

@ -9,7 +9,6 @@ import com.minelittlepony.common.client.gui.GameGui;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.*; 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.client.render.model.SphereModel;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.UItems; 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)); tooltip.add(Text.translatable("gui.unicopia.dispell_screen.spell_type", name));
type.traits().appendTooltip(tooltip); type.traits().appendTooltip(tooltip);
tooltip.add(ScreenTexts.EMPTY); tooltip.add(ScreenTexts.EMPTY);
tooltip.add(Text.translatable("gui.unicopia.dispell_screen.affinity", affinity.getDisplayName())); type.appendTooltip(tooltip);
tooltip.add(ScreenTexts.EMPTY); tooltip.add(ScreenTexts.EMPTY);
tooltip.addAll(TextHelper.wrap(Text.translatable(type.type().getTranslationKey() + ".lore").formatted(affinity.getColor()), 180).toList());
if (spell instanceof TimedSpell timed) { if (spell instanceof TimedSpell timed) {
tooltip.add(ScreenTexts.EMPTY); tooltip.add(ScreenTexts.EMPTY);
tooltip.add(Text.translatable("gui.unicopia.dispell_screen.time_left", StringHelper.formatTicks(timed.getTimer().getTicksRemaining()))); tooltip.add(Text.translatable("gui.unicopia.dispell_screen.time_left", StringHelper.formatTicks(timed.getTimer().getTicksRemaining())));

View file

@ -3,6 +3,9 @@ package com.minelittlepony.unicopia.entity.effect;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
public interface EffectUtils { public interface EffectUtils {
static boolean isPoisoned(LivingEntity entity) { static boolean isPoisoned(LivingEntity entity) {
@ -46,4 +49,11 @@ public interface EffectUtils {
} }
return false; 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);
}
} }

View file

@ -8,7 +8,6 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; 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.PlayerCharmTracker;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.group.MultiItem; 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.entity.player.PlayerEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult; import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -80,20 +77,7 @@ public class GemstoneItem extends Item implements MultiItem, EnchantableItem {
super.appendTooltip(stack, world, lines, tooltipContext); super.appendTooltip(stack, world, lines, tooltipContext);
if (EnchantableItem.isEnchanted(stack)) { if (EnchantableItem.isEnchanted(stack)) {
CustomisedSpellType<?> type = getSpellEffect(stack); getSpellEffect(stack).appendTooltip(lines);
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));
}
} }
} }

View file

@ -548,6 +548,12 @@
"spell.unicopia.fire_bolt": "Fire Bolt", "spell.unicopia.fire_bolt": "Fire Bolt",
"spell.unicopia.fire_bolt.lore": "Produces several burning projectiles", "spell.unicopia.fire_bolt.lore": "Produces several burning projectiles",
"spell.unicopia.shield": "Protection", "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.shield.lore": "Casts a protective shield around the user",
"spell.unicopia.bubble": "Bubble", "spell.unicopia.bubble": "Bubble",
"spell.unicopia.bubble.lore": "Traps any creature it hits in a soap bubble", "spell.unicopia.bubble.lore": "Traps any creature it hits in a soap bubble",