mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-08 06:26:43 +01:00
Tooltip details version 2
This commit is contained in:
parent
5207f7fefb
commit
1f714b3ed0
10 changed files with 261 additions and 13 deletions
|
@ -26,6 +26,10 @@ public interface SpellAttributes {
|
|||
Identifier STRENGTH = Unicopia.id("strength");
|
||||
Identifier VELOCITY = Unicopia.id("velocity");
|
||||
Identifier VERTICAL_VELOCITY = Unicopia.id("vertical_velocity");
|
||||
Identifier HANG_TIME = Unicopia.id("hang_time");
|
||||
Identifier PUSHING_POWER = Unicopia.id("pushing_power");
|
||||
Identifier CAUSES_LEVITATION = Unicopia.id("causes_levitation");
|
||||
Identifier AFFECTS = Unicopia.id("affects");
|
||||
Identifier DAMAGE_TO_TARGET = Unicopia.id("damage_to_target");
|
||||
Identifier SIMULTANIOUS_TARGETS = Unicopia.id("simultanious_targets");
|
||||
Identifier COST_PER_INDIVIDUAL = Unicopia.id("cost_per_individual");
|
||||
|
@ -61,4 +65,11 @@ public interface SpellAttributes {
|
|||
Text.translatable(Util.createTranslationKey("spell_attribute", id))
|
||||
).formatted(Formatting.LIGHT_PURPLE));
|
||||
}
|
||||
|
||||
public enum ValueType {
|
||||
REGULAR,
|
||||
TIME,
|
||||
PERCENTAGE,
|
||||
CONDITIONAL
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
|
||||
|
||||
public enum Affects {
|
||||
BOTH,
|
||||
ENTITIES,
|
||||
BLOCKS;
|
||||
|
||||
public boolean allowsBlocks() {
|
||||
return this == BOTH || this == BLOCKS;
|
||||
}
|
||||
|
||||
public boolean allowsEntities() {
|
||||
return this == BOTH || this == ENTITIES;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.client.UnicopiaClient;
|
||||
import com.minelittlepony.unicopia.client.gui.ItemTraitsTooltipRenderer;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.StringHelper;
|
||||
|
||||
public enum AttributeFormat {
|
||||
REGULAR {
|
||||
@Override
|
||||
public String formatValue(float value) {
|
||||
return ItemStack.MODIFIER_FORMAT.format(value);
|
||||
}
|
||||
},
|
||||
TIME {
|
||||
@Override
|
||||
public String formatValue(float value) {
|
||||
return StringHelper.formatTicks((int)Math.abs(value));
|
||||
}
|
||||
},
|
||||
PERCENTAGE {
|
||||
@Override
|
||||
public String formatValue(float value) {
|
||||
return ItemStack.MODIFIER_FORMAT.format((int)(Math.abs(value) * 100)) + "%";
|
||||
}
|
||||
};
|
||||
|
||||
public abstract String formatValue(float value);
|
||||
|
||||
public MutableText getBase(Text attributeName, float value, String comparison, Formatting color) {
|
||||
return formatAttributeLine(Text.translatable("attribute.modifier." + comparison + ".0", formatValue(value), attributeName).formatted(color));
|
||||
}
|
||||
|
||||
public Text get(Text attributeName, float value) {
|
||||
return getBase(attributeName, value, "equals", Formatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
public Text getRelative(Text attributeName, float baseValue, float currentValue, boolean detrimental) {
|
||||
float difference = currentValue - baseValue;
|
||||
return Text.literal(" (" + (difference > 0 ? "+" : "-") + formatValue(this == PERCENTAGE ? difference / baseValue : difference) + ")").formatted((detrimental ? difference : -difference) < 0 ? Formatting.DARK_GREEN : Formatting.RED);
|
||||
}
|
||||
|
||||
static Text formatTraitDifference(Trait trait, float value) {
|
||||
boolean known = ItemTraitsTooltipRenderer.isKnown(trait);
|
||||
boolean canCast = UnicopiaClient.getClientPony() != null && UnicopiaClient.getClientPony().getObservedSpecies().canCast();
|
||||
Text name = canCast ? known
|
||||
? trait.getName()
|
||||
: Text.translatable("spell_attribute.unicopia.added_trait.unknown").formatted(Formatting.YELLOW)
|
||||
: trait.getName().copy().formatted(Formatting.OBFUSCATED, Formatting.YELLOW);
|
||||
Text count = Text.literal(ItemStack.MODIFIER_FORMAT.format(value));
|
||||
return Text.translatable("spell_attribute.unicopia.added_trait." + ((value > 0) ? "plus" : "take"), name, count).formatted(Formatting.DARK_AQUA);
|
||||
}
|
||||
|
||||
static MutableText formatAttributeLine(Text attributeName) {
|
||||
return Text.literal(" ").append(attributeName).formatted(Formatting.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
|
||||
|
||||
public enum Permits {
|
||||
ITEMS,
|
||||
PASSIVE,
|
||||
HOSTILE,
|
||||
PLAYER
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
|
||||
import it.unimi.dsi.fastutil.floats.Float2ObjectFunction;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
public record SpellAttribute<T> (
|
||||
Trait trait,
|
||||
Float2ObjectFunction<T> valueGetter,
|
||||
TooltipFactory tooltipFactory
|
||||
) implements TooltipFactory {
|
||||
@Override
|
||||
public void appendTooltip(CustomisedSpellType<?> type, List<Text> tooltip) {
|
||||
tooltipFactory.appendTooltip(type, tooltip);
|
||||
}
|
||||
|
||||
public T get(SpellTraits traits) {
|
||||
return valueGetter.get(traits.get(trait));
|
||||
}
|
||||
|
||||
public static <T extends Number> SpellAttribute<T> create(Identifier id, AttributeFormat format, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter) {
|
||||
return create(id, format, format, trait, valueGetter, false);
|
||||
}
|
||||
|
||||
public static <T extends Number> SpellAttribute<T> create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter) {
|
||||
return create(id, baseFormat, relativeFormat, trait, valueGetter, false);
|
||||
}
|
||||
|
||||
public static <T extends @NotNull Number> SpellAttribute<T> create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter, boolean detrimental) {
|
||||
Text name = Text.translatable(Util.createTranslationKey("spell_attribute", id));
|
||||
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
|
||||
float traitAmount = type.traits().get(trait);
|
||||
float traitDifference = type.relativeTraits().get(trait);
|
||||
float value = valueGetter.get(traitAmount).floatValue();
|
||||
|
||||
var b = baseFormat.getBase(name, value, "equals", Formatting.LIGHT_PURPLE);
|
||||
if (traitDifference != 0) {
|
||||
tooltip.add(b.append(relativeFormat.getRelative(Text.empty(), valueGetter.get(traitAmount - traitDifference).floatValue(), value, detrimental)));
|
||||
tooltip.add(AttributeFormat.formatTraitDifference(trait, traitDifference));
|
||||
} else {
|
||||
tooltip.add(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static SpellAttribute<Boolean> createConditional(Identifier id, Trait trait, Float2ObjectFunction<Boolean> valueGetter) {
|
||||
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
|
||||
Text name = Text.translatable(Util.createTranslationKey("spell_attribute", id));
|
||||
float difference = type.relativeTraits().get(trait);
|
||||
Text value = AttributeFormat.formatAttributeLine(name);
|
||||
if (!valueGetter.get(type.traits().get(trait))) {
|
||||
value = value.copy().formatted(Formatting.STRIKETHROUGH, Formatting.DARK_GRAY);
|
||||
}
|
||||
tooltip.add(value);
|
||||
if (difference != 0) {
|
||||
tooltip.add(AttributeFormat.formatTraitDifference(trait, difference));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> SpellAttribute<T> createEnumerated(Identifier id, Trait trait, Float2ObjectFunction<T> valueGetter) {
|
||||
Function<T, Text> cache = Util.memoize(t -> Text.translatable(Util.createTranslationKey("spell_attribute", id.withPath(id.getPath() + "." + t.name().toLowerCase(Locale.ROOT)))));
|
||||
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
|
||||
T t = valueGetter.get(type.traits().get(trait));
|
||||
|
||||
if (t != null) {
|
||||
int max = t.getClass().getEnumConstants().length;
|
||||
tooltip.add(Text.translatable(" %s (%s/%s)", cache.apply(t), Text.literal("" + (t.ordinal() + 1)).formatted(Formatting.LIGHT_PURPLE), max).formatted(Formatting.DARK_PURPLE));
|
||||
}
|
||||
float difference = type.relativeTraits().get(trait);
|
||||
if (difference != 0) {
|
||||
tooltip.add(AttributeFormat.formatTraitDifference(trait, difference));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public interface TooltipFactory {
|
||||
void appendTooltip(CustomisedSpellType<?> type, List<Text> tooltip);
|
||||
|
||||
static TooltipFactory of(TooltipFactory...lines) {
|
||||
return (type, tooltip) -> {
|
||||
for (var line : lines) {
|
||||
line.appendTooltip(type, tooltip);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -6,10 +6,13 @@ import java.util.function.Consumer;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.attribute.Affects;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity;
|
||||
|
@ -27,6 +30,7 @@ import net.minecraft.text.Text;
|
|||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -45,13 +49,22 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B
|
|||
private static final float HORIZONTAL_VARIANCE = 0.25F;
|
||||
private static final float MAX_STRENGTH = 120;
|
||||
|
||||
private static final SpellAttribute<Float> LAUNCH_SPEED = SpellAttribute.create(SpellAttributes.VERTICAL_VELOCITY, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> 0.1F + (MathHelper.clamp(strength, -MAX_STRENGTH, MAX_STRENGTH) - 40) / 16F);
|
||||
private static final SpellAttribute<Float> HANG_TIME = SpellAttribute.create(SpellAttributes.HANG_TIME, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.AIR, air -> 50 + (int)MathHelper.clamp(air, 0, 10) * 20F);
|
||||
private static final SpellAttribute<Float> PUSHING_POWER = SpellAttribute.create(SpellAttributes.PUSHING_POWER, AttributeFormat.REGULAR, Trait.POWER, power -> 1 + MathHelper.clamp(power, 0, 10) / 10F);
|
||||
private static final SpellAttribute<Boolean> CAUSES_LEVITATION = SpellAttribute.createConditional(SpellAttributes.CAUSES_LEVITATION, Trait.FOCUS, focus -> focus > 50);
|
||||
private static final SpellAttribute<Affects> AFFECTS = SpellAttribute.createEnumerated(SpellAttributes.AFFECTS, Trait.ORDER, order -> {
|
||||
if (order <= 0) {
|
||||
return Affects.BOTH;
|
||||
} else if (order <= 10) {
|
||||
return Affects.ENTITIES;
|
||||
}
|
||||
return Affects.BLOCKS;
|
||||
});
|
||||
static final TooltipFactory TOOLTIP = TooltipFactory.of(LAUNCH_SPEED, HANG_TIME, PUSHING_POWER, CAUSES_LEVITATION, AFFECTS);
|
||||
|
||||
static void appendTooltip(CustomisedSpellType<? extends CatapultSpell> type, List<Text> tooltip) {
|
||||
float velocity = (float)(0.1F + (type.traits().get(Trait.STRENGTH, -MAX_STRENGTH, MAX_STRENGTH) - 40) / 16D);
|
||||
tooltip.add(SpellAttributes.of(SpellAttributes.VERTICAL_VELOCITY, velocity));
|
||||
int hoverDuration = 50 + (int)type.traits().get(Trait.AIR, 0, 10) * 20;
|
||||
tooltip.add(SpellAttributes.ofTime(Unicopia.id("hang_time"), hoverDuration));
|
||||
float power = 1 + type.traits().get(Trait.POWER, 0, 10) / 10F;
|
||||
tooltip.add(SpellAttributes.of(Unicopia.id("pushing_power"), power));
|
||||
TOOLTIP.appendTooltip(type, tooltip);
|
||||
}
|
||||
|
||||
protected CatapultSpell(CustomisedSpellType<?> type) {
|
||||
|
@ -60,6 +73,10 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B
|
|||
|
||||
@Override
|
||||
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
|
||||
if (!AFFECTS.get(getTraits()).allowsBlocks()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!projectile.isClient() && projectile instanceof MagicBeamEntity source && source.canModifyAt(hit.getBlockPos())) {
|
||||
createBlockEntity(projectile.getWorld(), hit.getBlockPos(), e -> {
|
||||
e.setOnGround(true);
|
||||
|
@ -72,6 +89,11 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B
|
|||
@Override
|
||||
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
|
||||
if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) {
|
||||
Entity e = hit.getEntity();
|
||||
if (!(e instanceof FallingBlockEntity) && !AFFECTS.get(getTraits()).allowsEntities()) {
|
||||
return;
|
||||
}
|
||||
|
||||
apply(source, hit.getEntity());
|
||||
}
|
||||
}
|
||||
|
@ -95,21 +117,29 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B
|
|||
e.setVelocity(caster.asEntity().getVelocity().multiply(power));
|
||||
} else {
|
||||
Random rng = caster.asWorld().random;
|
||||
double launchSpeed = 0.1F + (getTraits().get(Trait.STRENGTH, -MAX_STRENGTH, MAX_STRENGTH) - 40) / 16D;
|
||||
e.addVelocity(
|
||||
rng.nextTriangular(0, HORIZONTAL_VARIANCE) * 0.1F,
|
||||
launchSpeed,
|
||||
LAUNCH_SPEED.get(getTraits()),
|
||||
rng.nextTriangular(0, HORIZONTAL_VARIANCE) * 0.1F
|
||||
);
|
||||
|
||||
if (e instanceof LivingEntity l) {
|
||||
int hoverDuration = 50 + (int)getTraits().get(Trait.AIR, 0, 10) * 20;
|
||||
int hoverDuration = HANG_TIME.get(getTraits()).intValue();
|
||||
boolean noGravity = CAUSES_LEVITATION.get(getTraits());
|
||||
|
||||
if (e instanceof LivingEntity l) {
|
||||
if (l.hasStatusEffect(StatusEffects.SLOW_FALLING)) {
|
||||
l.removeStatusEffect(StatusEffects.SLOW_FALLING);
|
||||
}
|
||||
l.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOW_FALLING, hoverDuration, 1));
|
||||
}
|
||||
|
||||
if (noGravity || e instanceof FallingBlockEntity && (!e.getWorld().getBlockState(e.getBlockPos().up()).isReplaceable())) {
|
||||
if (e instanceof LivingEntity l) {
|
||||
l.addStatusEffect(new StatusEffectInstance(StatusEffects.LEVITATION, 200, 1));
|
||||
} else {
|
||||
e.setNoGravity(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.velocityDirty = true;
|
||||
|
|
|
@ -68,7 +68,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
|
|||
public static final SpellType<AwkwardSpell> AWKWARD = register("awkward", builder(AwkwardSpell::new).affinity(Affinity.NEUTRAL).color(0x3A59FF).shape(GemstoneItem.Shape.ICE));
|
||||
public static final SpellType<TransformationSpell> TRANSFORMATION = register("transformation", builder(TransformationSpell::new).color(0x19E48E).shape(GemstoneItem.Shape.BRUSH));
|
||||
public static final SpellType<FeatherFallSpell> FEATHER_FALL = register("feather_fall", builder(FeatherFallSpell::new).color(0x00EEFF).shape(GemstoneItem.Shape.LAMBDA).traits(FeatherFallSpell.DEFAULT_TRAITS).tooltip(FeatherFallSpell::appendTooltip));
|
||||
public static final SpellType<CatapultSpell> CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell::appendTooltip));
|
||||
public static final SpellType<CatapultSpell> CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell.TOOLTIP::appendTooltip));
|
||||
public static final SpellType<FireBoltSpell> FIRE_BOLT = register("fire_bolt", builder(FireBoltSpell::new).color(0xFF8811).shape(GemstoneItem.Shape.FLAME).traits(FireBoltSpell.DEFAULT_TRAITS).tooltip(FireBoltSpell::appendTooltip));
|
||||
public static final SpellType<LightSpell> LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell::appendTooltip));
|
||||
public static final SpellType<DisplacementSpell> DISPLACEMENT = register("displacement", builder(DisplacementSpell::new).affinity(Affinity.NEUTRAL).color(0x9900FF).stackable().shape(GemstoneItem.Shape.BRUSH).traits(PortalSpell.DEFAULT_TRAITS).tooltip(DisplacementSpell::appendTooltip));
|
||||
|
|
|
@ -52,7 +52,7 @@ public interface EffectUtils {
|
|||
}
|
||||
|
||||
static Text formatModifierChange(String modifierName, int time, boolean isDetrimental) {
|
||||
return Text.literal(" ").append(Text.translatable("attribute.modifier.equals.0",
|
||||
return Text.literal(" ").append(Text.translatable("attribute.modifier." + (time > 0 ? "plus" : "take") + ".0",
|
||||
StringHelper.formatTicks(Math.abs(time)),
|
||||
Text.translatable(modifierName)
|
||||
).formatted((isDetrimental ? time : -time) < 0 ? Formatting.DARK_GREEN : Formatting.RED));
|
||||
|
@ -64,4 +64,11 @@ public interface EffectUtils {
|
|||
Text.translatable(modifierName)
|
||||
).formatted((isDetrimental ? change : -change) < 0 ? Formatting.DARK_GREEN : Formatting.RED));
|
||||
}
|
||||
|
||||
static Text formatModifierChange(Text modifierName, float change, boolean isDetrimental) {
|
||||
return Text.literal(" ").append(Text.translatable("attribute.modifier." + (change > 0 ? "plus" : "take") + ".0",
|
||||
ItemStack.MODIFIER_FORMAT.format(Math.abs(change)),
|
||||
modifierName
|
||||
).formatted((isDetrimental ? change : -change) < 0 ? Formatting.DARK_GREEN : Formatting.RED));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -584,10 +584,17 @@
|
|||
"spell.unicopia.dispel_evil": "Dispel Evil",
|
||||
"spell.unicopia.dispel_evil.lore": "Casts away any nearby unearthly forces",
|
||||
|
||||
"spell_attribute.unicopia.added_trait.plus": " + %s x%s",
|
||||
"spell_attribute.unicopia.added_trait.take": " - %s x%s",
|
||||
"spell_attribute.unicopia.added_trait.unknown": "Undiscovered Trait",
|
||||
"spell_attribute.unicopia.cast_on_location": "Applies to location",
|
||||
"spell_attribute.unicopia.cast_on_person": "Applies to self",
|
||||
"spell_attribute.unicopia.focused_entity": "Applies to focused entity",
|
||||
"spell_attribute.unicopia.affects.both": "Affects blocks and entities",
|
||||
"spell_attribute.unicopia.affects.entities": "Affects only entities",
|
||||
"spell_attribute.unicopia.affects.blocks": "Affects only blocks",
|
||||
"spell_attribute.unicopia.follows_target": "Follows target",
|
||||
"spell_attribute.unicopia.causes_levitation": "Causes Levitation",
|
||||
|
||||
"spell_attribute.unicopia.permit_items": " Permits Items",
|
||||
"spell_attribute.unicopia.permit_passive": "Permits Passive Mobs",
|
||||
|
|
Loading…
Reference in a new issue