diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java index 128323a0..edf19a17 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java @@ -1,20 +1,15 @@ package com.minelittlepony.unicopia.ability.magic.spell; -import java.util.List; - import com.minelittlepony.unicopia.ability.magic.Caster; +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.effect.*; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; -import net.minecraft.text.Text; public abstract class AbstractAreaEffectSpell extends AbstractSpell { - - public static void appendRangeTooltip(CustomisedSpellType type, List tooltip) { - float addedRange = type.traits().get(Trait.POWER); - if (addedRange != 0) { - tooltip.add(SpellAttributes.ofRelative(SpellAttributes.RANGE, addedRange)); - } - } + protected static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power)); + public static final TooltipFactory TOOLTIP = RANGE; protected AbstractAreaEffectSpell(CustomisedSpellType type) { super(type); @@ -24,8 +19,4 @@ public abstract class AbstractAreaEffectSpell extends AbstractSpell { public Spell prepareForCast(Caster caster, CastingMethod method) { return toPlaceable(); } - - protected final float getAdditionalRange() { - return (int)getTraits().get(Trait.POWER); - } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellAttributes.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellAttributes.java index df35b029..012cdc02 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellAttributes.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellAttributes.java @@ -13,14 +13,14 @@ import net.minecraft.util.Util; public interface SpellAttributes { Text CAST_ON_LOCATION = of(Unicopia.id("cast_on_location")); Text CAST_ON_PERSON = of(Unicopia.id("cast_on_person")); - Text TARGET_ENTITY = of(Unicopia.id("focused_entity")); - Text FOLLOWS_TARGET = of(Unicopia.id("follows_target")); + Identifier FOLLOWS_TARGET = Unicopia.id("follows_target"); - Text PERMIT_ITEMS = of(Unicopia.id("permit_items")); - Text PERMIT_PASSIVE = of(Unicopia.id("permit_passive")); - Text PERMIT_HOSTILE = of(Unicopia.id("permit_hostile")); - Text PERMIT_PLAYER = of(Unicopia.id("permit_player")); + Identifier PERMIT_ITEMS = Unicopia.id("permit_items"); + Identifier PERMIT_PASSIVE = Unicopia.id("permit_passive"); + Identifier PERMIT_HOSTILE = Unicopia.id("permit_hostile"); + Identifier PERMIT_PLAYER = Unicopia.id("permit_player"); + Identifier FOCUSED_ENTITY = Unicopia.id("focused_entity"); Identifier RANGE = Unicopia.id("range"); Identifier DURATION = Unicopia.id("duration"); Identifier STRENGTH = Unicopia.id("strength"); @@ -38,15 +38,20 @@ public interface SpellAttributes { Identifier ORB_COUNT = Unicopia.id("orb_count"); Identifier WAVE_SIZE = Unicopia.id("wave_size"); Identifier FOLLOW_RANGE = Unicopia.id("follow_range"); + Identifier LIGHT_TARGET = Unicopia.id("light_target"); + Identifier STICK_TO_TARGET = Unicopia.id("stick_to_target"); Identifier SOAPINESS = Unicopia.id("soapiness"); + Identifier CAST_ON = Unicopia.id("cast_on"); Identifier TARGET_PREFERENCE = Unicopia.id("target_preference"); Identifier CASTER_PREFERENCE = Unicopia.id("caster_preference"); + @Deprecated static Text of(Identifier id) { return Text.literal(" ").append(Text.translatable(Util.createTranslationKey("spell_attribute", id))).formatted(Formatting.LIGHT_PURPLE); } + @Deprecated static Text of(Identifier id, float value) { return Text.literal(" ").append( Text.translatable("attribute.modifier.equals.0", @@ -55,10 +60,12 @@ public interface SpellAttributes { ).formatted(Formatting.LIGHT_PURPLE); } + @Deprecated static Text ofRelative(Identifier id, float value) { return EffectUtils.formatModifierChange(Util.createTranslationKey("spell_attribute", id), value, false); } + @Deprecated static Text ofTime(Identifier id, long time) { return Text.literal(" ").append(Text.translatable("attribute.modifier.equals.0", StringHelper.formatTicks((int)Math.abs(time)), @@ -66,6 +73,7 @@ public interface SpellAttributes { ).formatted(Formatting.LIGHT_PURPLE)); } + @Deprecated public enum ValueType { REGULAR, TIME, diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/TimedSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/TimedSpell.java index 33b2b837..94e13b11 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/TimedSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/TimedSpell.java @@ -1,15 +1,12 @@ package com.minelittlepony.unicopia.ability.magic.spell; -import java.util.List; - -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.attribute.AttributeFormat; +import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.util.NbtSerialisable; import com.minelittlepony.unicopia.util.Tickable; import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; /** @@ -17,17 +14,10 @@ import net.minecraft.util.math.MathHelper; */ public interface TimedSpell extends Spell { int BASE_DURATION = 120 * 20; + SpellAttribute TIME = SpellAttribute.create(SpellAttributes.SOAPINESS, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> BASE_DURATION + (int)(MathHelper.clamp(focus, 0, 160) * 19) * 20); Timer getTimer(); - static void appendDurationTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.ofTime(SpellAttributes.DURATION, BASE_DURATION + getExtraDuration(type.traits()))); - } - - static int getExtraDuration(SpellTraits traits) { - return (int)(traits.get(Trait.FOCUS, 0, 160) * 19) * 20; - } - class Timer implements Tickable, NbtSerialisable { private int maxDuration; private int duration; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/CastOn.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/CastOn.java new file mode 100644 index 00000000..aded56d9 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/CastOn.java @@ -0,0 +1,6 @@ +package com.minelittlepony.unicopia.ability.magic.spell.attribute; + +public enum CastOn { + LOCATION, + SELF +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/SpellAttribute.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/SpellAttribute.java index e450568d..3da4f498 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/SpellAttribute.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/SpellAttribute.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.ability.magic.spell.attribute; import java.util.List; import java.util.Locale; +import java.util.function.BiFunction; import java.util.function.Function; import org.jetbrains.annotations.NotNull; @@ -18,7 +19,7 @@ import net.minecraft.util.Util; public record SpellAttribute ( Trait trait, - Float2ObjectFunction valueGetter, + BiFunction valueGetter, TooltipFactory tooltipFactory ) implements TooltipFactory { @Override @@ -27,7 +28,11 @@ public record SpellAttribute ( } public T get(SpellTraits traits) { - return valueGetter.get(traits.get(trait)); + return valueGetter.apply(traits, traits.get(trait)); + } + + public static SpellAttribute create(Identifier id, AttributeFormat format, Trait trait, BiFunction valueGetter) { + return create(id, format, format, trait, valueGetter, false); } public static SpellAttribute create(Identifier id, AttributeFormat format, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter) { @@ -38,16 +43,24 @@ public record SpellAttribute ( return create(id, baseFormat, relativeFormat, trait, valueGetter, false); } + public static SpellAttribute create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, BiFunction valueGetter) { + return create(id, baseFormat, relativeFormat, trait, valueGetter, false); + } + public static SpellAttribute create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter, boolean detrimental) { + return create(id, baseFormat, relativeFormat, trait, (traits, value) -> valueGetter.get(value.floatValue()), detrimental); + } + + public static SpellAttribute create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, BiFunction valueGetter, boolean detrimental) { Text name = Text.translatable(Util.createTranslationKey("spell_attribute", id)); return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType type, List tooltip) -> { float traitAmount = type.traits().get(trait); float traitDifference = type.relativeTraits().get(trait); - float value = valueGetter.get(traitAmount).floatValue(); + float value = valueGetter.apply(type.traits(), 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(b.append(relativeFormat.getRelative(Text.empty(), valueGetter.apply(type.traits(), traitAmount - traitDifference).floatValue(), value, detrimental))); tooltip.add(AttributeFormat.formatTraitDifference(trait, traitDifference)); } else { tooltip.add(b); @@ -56,11 +69,15 @@ public record SpellAttribute ( } public static SpellAttribute createConditional(Identifier id, Trait trait, Float2ObjectFunction valueGetter) { + return createConditional(id, trait, (traits, value) -> valueGetter.get(value.floatValue())); + } + + public static SpellAttribute createConditional(Identifier id, Trait trait, BiFunction valueGetter) { return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType type, List 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))) { + if (!valueGetter.apply(type.traits(), type.traits().get(trait))) { value = value.copy().formatted(Formatting.STRIKETHROUGH, Formatting.DARK_GRAY); } tooltip.add(value); @@ -71,9 +88,13 @@ public record SpellAttribute ( } public static > SpellAttribute createEnumerated(Identifier id, Trait trait, Float2ObjectFunction valueGetter) { + return createEnumerated(id, trait, (traits, value) -> valueGetter.get(value.floatValue())); + } + + public static > SpellAttribute createEnumerated(Identifier id, Trait trait, BiFunction valueGetter) { Function 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 tooltip) -> { - T t = valueGetter.get(type.traits().get(trait)); + T t = valueGetter.apply(type.traits(), type.traits().get(trait)); if (t != null) { int max = t.getClass().getEnumConstants().length; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/TooltipFactory.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/TooltipFactory.java index e4fd5db9..8b7e69dd 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/TooltipFactory.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/attribute/TooltipFactory.java @@ -1,8 +1,10 @@ package com.minelittlepony.unicopia.ability.magic.spell.attribute; import java.util.List; +import java.util.function.Predicate; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import net.minecraft.text.Text; @@ -16,4 +18,17 @@ public interface TooltipFactory { } }; } + + static TooltipFactory of(Text line) { + return (type, tooltip) -> tooltip.add(line); + } + + default TooltipFactory conditionally(Predicate condition) { + TooltipFactory self = this; + return (type, tooltip) -> { + if (condition.test(type.traits())) { + self.appendTooltip(type, tooltip); + } + }; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AreaProtectionSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AreaProtectionSpell.java index b239cad6..b44547a7 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AreaProtectionSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AreaProtectionSpell.java @@ -1,11 +1,10 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; +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.entity.mob.UEntities; @@ -16,7 +15,6 @@ import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.entity.Entity; -import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -26,11 +24,7 @@ public class AreaProtectionSpell extends AbstractAreaEffectSpell { .with(Trait.STRENGTH, 30) .build(); - - static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.CAST_ON_LOCATION); - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 4 + type.traits().get(Trait.POWER))); - } + static final TooltipFactory TOOLTIP = TooltipFactory.of(TooltipFactory.of(SpellAttributes.CAST_ON_LOCATION), RANGE); protected AreaProtectionSpell(CustomisedSpellType type) { super(type); @@ -71,7 +65,7 @@ public class AreaProtectionSpell extends AbstractAreaEffectSpell { private double getRange(Caster source) { float multiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2; - float min = 4 + getAdditionalRange(); + float min = RANGE.get(getTraits()); double range = (min + (source.getLevel().getScaled(4) * 2)) / multiplier; if (source instanceof Pony && range > 2) { range = Math.sqrt(range); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java index 04a0185d..5cabfa21 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java @@ -1,9 +1,9 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.*; +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.Trait; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.Living; @@ -17,31 +17,23 @@ import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.entity.Entity; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleTypes; -import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSpell, ProjectileDelegate.EntityHitListener { + static final SpellAttribute TARGET_FOCUSED_ENTITY = SpellAttribute.createConditional(SpellAttributes.FOCUSED_ENTITY, Trait.ORDER, order -> order >= 20); + static final SpellAttribute STICK_TO_TARGET = SpellAttribute.createConditional(SpellAttributes.STICK_TO_TARGET, Trait.CHAOS, chaos -> chaos > 0); + static final TooltipFactory TARGET = (type, tooltip) -> (TARGET_FOCUSED_ENTITY.get(type.traits()) ? TARGET_FOCUSED_ENTITY : ShieldSpell.TARGET).appendTooltip(type, tooltip); + static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, RANGE, TARGET, STICK_TO_TARGET, CAST_ON); private final EntityReference target = new EntityReference<>(); private final Timer timer; - public static void appendTooltip2(CustomisedSpellType type, List tooltip) { - TimedSpell.appendDurationTooltip(type, tooltip); - AbstractAreaEffectSpell.appendRangeTooltip(type, tooltip); - if (type.traits().get(Trait.ORDER) >= 20) { - tooltip.add(SpellAttributes.TARGET_ENTITY); - } else { - appendValidTargetsTooltip(type, tooltip); - } - appendCastLocationTooltip(type, tooltip); - } - protected AttractiveSpell(CustomisedSpellType type) { super(type); - timer = new Timer(BASE_DURATION + TimedSpell.getExtraDuration(getTraits())); + timer = new Timer(TIME.get(getTraits())); dataTracker.startTracking(target); } @@ -52,12 +44,10 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp @Override public boolean tick(Caster caster, Situation situation) { - if (getType() != SpellType.DARK_VORTEX) { - timer.tick(); + timer.tick(); - if (timer.getTicksRemaining() <= 0) { - return false; - } + if (timer.getTicksRemaining() <= 0) { + return false; } target.getOrEmpty(caster.asWorld()) @@ -87,10 +77,7 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp @Override protected boolean isValidTarget(Caster source, Entity entity) { - if (target.referenceEquals(entity)) { - return true; - } - return super.isValidTarget(source, entity); + return target.referenceEquals(entity) || super.isValidTarget(source, entity); } @Override @@ -140,7 +127,7 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp @Override public boolean setTarget(Entity target) { - if (getTraits().get(Trait.ORDER) >= 20) { + if (TARGET_FOCUSED_ENTITY.get(getTraits())) { this.target.set(target); target.setGlowing(true); return true; @@ -156,7 +143,7 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp @Override public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { - if (!isDead() && getTraits().get(Trait.CHAOS) > 0) { + if (!isDead() && STICK_TO_TARGET.get(getTraits())) { setDead(); Caster.of(hit.getEntity()).ifPresent(caster -> getTypeAndTraits().apply(caster, CastingMethod.INDIRECT)); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java index bd24dfae..f63f575c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java @@ -1,12 +1,14 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; import java.util.Map; import java.util.UUID; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.*; +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.entity.*; @@ -25,7 +27,6 @@ import net.minecraft.entity.attribute.*; import net.minecraft.entity.attribute.EntityAttributeModifier.Operation; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleTypes; -import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -50,10 +51,9 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell, .with(Trait.POWER, 1) .build(); - static void appendTooltip(CustomisedSpellType type, List tooltip) { - TimedSpell.appendDurationTooltip(type, tooltip); - tooltip.add(SpellAttributes.of(SpellAttributes.SOAPINESS, (int)(type.traits().get(Trait.POWER) * 2))); - } + private static final SpellAttribute SOAPINESS = SpellAttribute.create(SpellAttributes.SOAPINESS, AttributeFormat.REGULAR, Trait.POWER, power -> (int)(power * 2)); + + static final TooltipFactory TOOLTIP = TooltipFactory.of(TimedSpell.TIME, SOAPINESS); private final Timer timer; @@ -63,9 +63,9 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell, protected BubbleSpell(CustomisedSpellType type) { super(type); - timer = new Timer(BASE_DURATION + TimedSpell.getExtraDuration(getTraits())); + timer = new Timer(TIME.get(getTraits())); radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); - struggles = dataTracker.startTracking(TrackableDataType.INT, (int)(getTraits().get(Trait.POWER) * 2)); + struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java index 760f222f..ac3040f5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DispellEvilSpell.java @@ -1,9 +1,10 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.*; +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.particle.LightningBoltParticleEffect; @@ -13,7 +14,6 @@ import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; public class DispellEvilSpell extends AbstractSpell implements ProjectileDelegate.HitListener { @@ -21,9 +21,9 @@ public class DispellEvilSpell extends AbstractSpell implements ProjectileDelegat .with(Trait.POWER, 1) .build(); - static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, (1 + type.relativeTraits().get(Trait.POWER)) * 10)); - } + private static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.POWER, power -> (1 + power) * 10D); + + static final TooltipFactory TOOLTIP = RANGE; protected DispellEvilSpell(CustomisedSpellType type) { super(type); @@ -35,7 +35,7 @@ public class DispellEvilSpell extends AbstractSpell implements ProjectileDelegat return !isDead(); } - source.findAllEntitiesInRange((1 + getTraits().get(Trait.POWER)) * 10, e -> e.getType() == EntityType.PHANTOM).forEach(entity -> { + source.findAllEntitiesInRange(RANGE.get(getTraits()), e -> e.getType() == EntityType.PHANTOM).forEach(entity -> { entity.damage(entity.getDamageSources().magic(), 50); if (entity instanceof LivingEntity l) { double d = source.getOriginVector().getX() - entity.getX(); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisperseIllusionSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisperseIllusionSpell.java index f67ceb2b..1e4bc8b6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisperseIllusionSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisperseIllusionSpell.java @@ -1,28 +1,27 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; +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.Trait; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.util.shape.Sphere; -import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; /** * An area-effect spell that disperses illusions. */ public class DisperseIllusionSpell extends AbstractAreaEffectSpell { - public static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 15 + type.traits().get(Trait.POWER))); - tooltip.add(SpellAttributes.ofTime(SpellAttributes.DURATION, (1 + (long)type.traits().get(Trait.STRENGTH)) * 100)); - } + private static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 15 + power)); + private static final SpellAttribute DURATION = SpellAttribute.create(SpellAttributes.DURATION, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> (1 + (long)strength) * 100); + static final TooltipFactory TOOLTIP = TooltipFactory.of(RANGE, DURATION); protected DisperseIllusionSpell(CustomisedSpellType type) { super(type); @@ -31,7 +30,7 @@ public class DisperseIllusionSpell extends AbstractAreaEffectSpell { @Override public boolean tick(Caster source, Situation situation) { - float range = Math.max(0, 15 + getAdditionalRange()); + float range = RANGE.get(getTraits()); if (range == 0) { return false; @@ -50,7 +49,7 @@ public class DisperseIllusionSpell extends AbstractAreaEffectSpell { e.getSpellSlot().get(SpellPredicate.CAN_SUPPRESS) .filter(spell -> spell.isVulnerable(source, this)) .ifPresent(spell -> { - spell.onSuppressed(source, 100 * (1 + getTraits().get(Trait.STRENGTH))); + spell.onSuppressed(source, DURATION.get(getTraits())); e.playSound(USounds.SPELL_ILLUSION_DISPERSE, 0.2F, 0.5F); }); }); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index 923701ce..3ea6df59 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -1,10 +1,11 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.*; +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.Trait; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; @@ -13,18 +14,14 @@ import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import net.minecraft.entity.Entity; import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.Vec3d; public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener { - static void appendTooltip(CustomisedSpellType type, List tooltip) { - float damage = type.traits().get(Trait.BLOOD); - if (damage > 0) { - tooltip.add(SpellAttributes.ofRelative(SpellAttributes.DAMAGE_TO_TARGET, damage)); - } - } + private static final SpellAttribute DAMAGE_TO_TARGET = SpellAttribute.create(SpellAttributes.DAMAGE_TO_TARGET, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.BLOOD, blood -> blood); + + static final TooltipFactory TOOLTIP = DAMAGE_TO_TARGET; private final EntityReference target = new EntityReference<>(); @@ -81,7 +78,7 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro entity.setGlowing(false); entity.playSound(USounds.SPELL_DISPLACEMENT_TELEPORT, 1, 1); - float damage = getTraits().get(Trait.BLOOD); + float damage = DAMAGE_TO_TARGET.get(getTraits()); if (damage > 0) { entity.damage(source.damageOf(UDamageTypes.EXHAUSTION, source), damage); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java index 47bdf918..0821e0f3 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java @@ -1,12 +1,13 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; +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.entity.EntityReference; @@ -17,8 +18,8 @@ import net.minecraft.entity.Entity; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; import net.minecraft.predicate.entity.EntityPredicates; -import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.math.MathHelper; public class FireBoltSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.ConfigurationListener, ProjectileDelegate.EntityHitListener { @@ -35,18 +36,14 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, .with(Trait.FIRE, 60) .build(); - public static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.of(SpellAttributes.EXPLOSION_STRENGTH, type.traits().get(Trait.POWER, 0, type.traits().get(Trait.FOCUS) >= 50 ? 500 : 50) / 10F)); - tooltip.add(SpellAttributes.of(SpellAttributes.VELOCITY, 1.3F + type.traits().get(Trait.STRENGTH) / 11F)); - tooltip.add(SpellAttributes.of(SpellAttributes.PROJECTILE_COUNT, 1 + (int)type.traits().get(Trait.EARTH) * 3)); + private static final SpellAttribute VELOCITY = SpellAttribute.create(SpellAttributes.VELOCITY, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> 1.3F + (strength / 11F)); + private static final SpellAttribute PROJECTILE_COUNT = SpellAttribute.create(SpellAttributes.PROJECTILE_COUNT, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.EARTH, earth -> 11 + (int)earth * 3); + private static final SpellAttribute FOLLOWS_TARGET = SpellAttribute.createConditional(SpellAttributes.FOLLOWS_TARGET, Trait.FOCUS, focus -> focus >= 50); + private static final SpellAttribute FOLLOW_RANGE = SpellAttribute.create(SpellAttributes.FOLLOW_RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> Math.max(0F, focus - 49)); + private static final SpellAttribute MAX_EXPLOSION_STRENGTH = SpellAttribute.create(SpellAttributes.EXPLOSION_STRENGTH, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> focus >= 50 ? 10F : 1F); + private static final SpellAttribute EXPLOSION_STRENGTH = SpellAttribute.create(SpellAttributes.EXPLOSION_STRENGTH, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, (traits, focus) -> MathHelper.clamp(focus / 50, 0, MAX_EXPLOSION_STRENGTH.get(traits))); - float homingRange = type.traits().get(Trait.FOCUS); - - if (homingRange >= 50) { - tooltip.add(SpellAttributes.FOLLOWS_TARGET); - tooltip.add(SpellAttributes.of(SpellAttributes.FOLLOW_RANGE, homingRange - 50)); - } - } + static final TooltipFactory TOOLTIP = TooltipFactory.of(MAX_EXPLOSION_STRENGTH, EXPLOSION_STRENGTH, VELOCITY, PROJECTILE_COUNT, FOLLOWS_TARGET, FOLLOW_RANGE.conditionally(FOLLOWS_TARGET::get)); private final EntityReference target = new EntityReference<>(); @@ -61,10 +58,12 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, @Override public boolean tick(Caster caster, Situation situation) { + boolean followTarget = FOLLOWS_TARGET.get(getTraits()); + float followRage = FOLLOW_RANGE.get(getTraits()); if (situation == Situation.PROJECTILE) { - if (caster instanceof MagicProjectileEntity projectile && getTraits().get(Trait.FOCUS) >= 50) { + if (caster instanceof MagicProjectileEntity projectile && followTarget) { caster.findAllEntitiesInRange( - getTraits().get(Trait.FOCUS) - 49, + followRage, EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.validTarget(this, caster)) ).findFirst().ifPresent(target -> projectile.setHomingTarget(target)); } @@ -72,9 +71,9 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, return true; } - if (getTraits().get(Trait.FOCUS) >= 50 && target.getOrEmpty(caster.asWorld()).isEmpty()) { + if (followTarget && target.getOrEmpty(caster.asWorld()).isEmpty()) { target.set(caster.findAllEntitiesInRange( - getTraits().get(Trait.FOCUS) - 49, + followRage, EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.validTarget(this, caster)) ).findFirst().orElse(null)); } @@ -92,18 +91,18 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, @Override public void configureProjectile(MagicProjectileEntity projectile, Caster caster) { projectile.setItem(Items.FIRE_CHARGE.getDefaultStack()); - projectile.addThrowDamage(getTraits().get(Trait.POWER, 0, getTraits().get(Trait.FOCUS) >= 50 ? 500 : 50) / 10F); + projectile.addThrowDamage(EXPLOSION_STRENGTH.get(getTraits())); projectile.setFireTicks(900000); - projectile.setVelocity(projectile.getVelocity().multiply(1.3 + getTraits().get(Trait.STRENGTH) / 11F)); + projectile.setVelocity(projectile.getVelocity().multiply(VELOCITY.get(getTraits()))); } protected int getNumberOfBalls(Caster caster) { - return 1 + caster.asWorld().random.nextInt(3) + (int)getTraits().get(Trait.EARTH) * 3; + return PROJECTILE_COUNT.get(getTraits()) + caster.asWorld().random.nextInt(3); } @Override public boolean setTarget(Entity target) { - if (getTraits().get(Trait.FOCUS) >= 50) { + if (FOLLOWS_TARGET.get(getTraits())) { this.target.set(target); return true; } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java index f633c952..d7b9568c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java @@ -1,12 +1,9 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.USounds; 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.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; @@ -28,7 +25,6 @@ import net.minecraft.entity.damage.DamageTypes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.particle.ParticleTypes; import net.minecraft.sound.SoundCategory; -import net.minecraft.text.Text; import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.EntityHitResult; @@ -45,10 +41,6 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileDele .with(Trait.FIRE, 15) .build(); - public static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 4 + type.traits().get(Trait.POWER))); - } - protected FireSpell(CustomisedSpellType type) { super(type); } @@ -75,14 +67,14 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileDele generateParticles(source); } - return new Sphere(false, Math.max(0, 4 + getAdditionalRange())).translate(source.getOrigin()).getBlockPositions().reduce(false, + return new Sphere(false, RANGE.get(getTraits())).translate(source.getOrigin()).getBlockPositions().reduce(false, (r, i) -> source.canModifyAt(i) && applyBlocks(source.asWorld(), i), (a, b) -> a || b) || applyEntities(source, source.getOriginVector()); } protected void generateParticles(Caster source) { - source.spawnParticles(new Sphere(false, Math.max(0, 4 + getAdditionalRange())), (int)(1 + source.getLevel().getScaled(8)) * 6, pos -> { + source.spawnParticles(new Sphere(false, RANGE.get(getTraits())), (int)(1 + source.getLevel().getScaled(8)) * 6, pos -> { source.addParticle(ParticleTypes.LARGE_SMOKE, pos, Vec3d.ZERO); }); } @@ -129,8 +121,12 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileDele return false; } + protected float getEntityEffectRange() { + return Math.max(0, RANGE.get(getTraits()) - 1); + } + protected boolean applyEntities(Caster source, Vec3d pos) { - return source.findAllEntitiesInRange(Math.max(0, 3 + getAdditionalRange()), e -> { + return source.findAllEntitiesInRange(getEntityEffectRange(), e -> { LivingEntity master = source.getMaster(); return (!(e.equals(source.asEntity()) || e.equals(master)) || (master instanceof PlayerEntity && !EquinePredicates.PLAYER_UNICORN.test(master))) && !(e instanceof ItemEntity) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java index 6ec3554e..cd6a198c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/HydrophobicSpell.java @@ -1,7 +1,6 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; import java.util.HashSet; -import java.util.List; import java.util.Set; import com.minelittlepony.unicopia.USounds; @@ -9,7 +8,8 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.Spell; -import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; +import com.minelittlepony.unicopia.ability.magic.spell.attribute.CastOn; +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.advancement.UCriteria; @@ -24,7 +24,6 @@ import net.minecraft.block.*; import net.minecraft.fluid.*; import net.minecraft.nbt.*; import net.minecraft.state.property.Properties; -import net.minecraft.text.Text; import net.minecraft.registry.tag.TagKey; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; @@ -37,10 +36,8 @@ public class HydrophobicSpell extends AbstractSpell { .with(Trait.FOCUS, 5) .with(Trait.KNOWLEDGE, 1) .build(); - static void appendTooltip(CustomisedSpellType type, List tooltip) { - ShieldSpell.appendCastLocationTooltip(type, tooltip); - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 4 + type.traits().get(Trait.POWER))); - } + + static final TooltipFactory TOOLTIP = TooltipFactory.of(ShieldSpell.CAST_ON, ShieldSpell.RANGE); private final TagKey affectedFluid; @@ -53,7 +50,7 @@ public class HydrophobicSpell extends AbstractSpell { @Override public Spell prepareForCast(Caster caster, CastingMethod method) { - if ((method == CastingMethod.DIRECT || method == CastingMethod.STAFF) && getTraits().get(Trait.GENEROSITY) > 0) { + if ((method == CastingMethod.DIRECT || method == CastingMethod.STAFF) && ShieldSpell.CAST_ON.get(getTraits()) == CastOn.LOCATION) { return toPlaceable(); } return this; @@ -148,7 +145,7 @@ public class HydrophobicSpell extends AbstractSpell { */ public double getRange(Caster source) { float multiplier = 1; - float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER); + float min = (source instanceof Pony ? 0 : 2) + ShieldSpell.RANGE.get(getTraits()); boolean isLimitedRange = source instanceof Pony || source instanceof MagicProjectileEntity; double range = (min + (source.getLevel().getScaled(isLimitedRange ? 4 : 40) * (isLimitedRange ? 2 : 10))) / multiplier; return range; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java index f5065ff2..ae4cf7d7 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java @@ -5,6 +5,10 @@ import java.util.List; import com.minelittlepony.unicopia.Owned; 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.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.block.state.StateMaps; @@ -12,7 +16,6 @@ import com.minelittlepony.unicopia.block.state.StatePredicate; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.util.PosHelper; import com.minelittlepony.unicopia.util.VecHelper; -import com.minelittlepony.unicopia.util.shape.Shape; import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.block.*; @@ -33,8 +36,9 @@ public class IceSpell extends AbstractSpell { .with(Trait.ICE, 15) .build(); - private static final int RADIUS = 3; - private static final Shape OUTER_RANGE = new Sphere(false, RADIUS); + private static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 3 + power)); + + static final TooltipFactory TOOLTIP = RANGE; protected IceSpell(CustomisedSpellType type) { super(type); @@ -43,11 +47,12 @@ public class IceSpell extends AbstractSpell { @Override public boolean tick(Caster source, Situation situation) { boolean submerged = source.asEntity().isSubmergedInWater() || source.asEntity().isSubmergedIn(FluidTags.LAVA); + float radius = RANGE.get(getTraits()); - long blocksAffected = OUTER_RANGE.translate(source.getOrigin()).getBlockPositions().filter(i -> { + long blocksAffected = new Sphere(false, radius).translate(source.getOrigin()).getBlockPositions().filter(i -> { if (source.canModifyAt(i) && applyBlockSingle(source.asEntity(), source.asWorld(), i, situation)) { - if (submerged & source.getOrigin().isWithinDistance(i, RADIUS - 1)) { + if (submerged & source.getOrigin().isWithinDistance(i, RANGE.get(getTraits()) - 1)) { BlockState state = source.asWorld().getBlockState(i); if (state.isIn(BlockTags.ICE) || state.isOf(Blocks.OBSIDIAN)) { source.asWorld().setBlockState(i, Blocks.AIR.getDefaultState(), Block.NOTIFY_NEIGHBORS); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java index 6825df24..0d96a52b 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java @@ -8,6 +8,9 @@ import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell; +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.entity.EntityReference; @@ -21,7 +24,7 @@ import com.minelittlepony.unicopia.util.VecHelper; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtList; -import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileDelegate.HitListener { public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder() @@ -31,10 +34,9 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD .with(Trait.ORDER, 25) .build(); - public static void appendTooltip(CustomisedSpellType type, List tooltip) { - TimedSpell.appendDurationTooltip(type, tooltip); - tooltip.add(SpellAttributes.of(SpellAttributes.ORB_COUNT, 2 + (int)(type.relativeTraits().get(Trait.LIFE, 10, 20) / 10F))); - } + private static final SpellAttribute ORB_COUNT = SpellAttribute.create(SpellAttributes.ORB_COUNT, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.LIFE, life -> 2 + (int)(MathHelper.clamp(life, 10, 20) / 10F)); + + static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, ORB_COUNT); private final Timer timer; @@ -42,7 +44,7 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD protected LightSpell(CustomisedSpellType type) { super(type); - timer = new Timer(BASE_DURATION + TimedSpell.getExtraDuration(getTraits())); + timer = new Timer(TIME.get(getTraits())); } @Override @@ -65,7 +67,7 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD if (!caster.isClient()) { if (lights.isEmpty()) { - int size = 2 + caster.asWorld().random.nextInt(2) + (int)(getTraits().get(Trait.LIFE, 10, 20) - 10)/10; + int size = caster.asWorld().random.nextInt(2) + ORB_COUNT.get(getTraits()); while (lights.size() < size) { lights.add(new EntityReference<>()); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java index 0e599e8d..57b984c1 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java @@ -1,25 +1,21 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; - import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.*; +import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; + import net.minecraft.entity.Entity; import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.Text; public class MimicSpell extends AbstractDisguiseSpell implements HomingSpell, TimedSpell { - static final int BASE_DURATION = 120 * 20; - public static void appendTooltip(CustomisedSpellType type, List tooltip) { - TimedSpell.appendDurationTooltip(type, tooltip); - } + static final TooltipFactory TOOLTIP = TimedSpell.TIME; private final Timer timer; protected MimicSpell(CustomisedSpellType type) { super(type); - timer = new Timer(BASE_DURATION + TimedSpell.getExtraDuration(getTraits())); + timer = new Timer(TIME.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java index c2063211..00401bdb 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java @@ -9,6 +9,9 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; +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.Trait; import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.EntityReference; @@ -32,7 +35,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtList; import net.minecraft.particle.ParticleTypes; -import net.minecraft.text.Text; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.BlockPos; @@ -81,10 +83,8 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti return e -> e.getType() == type; } - static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 4 + type.traits().get(Trait.POWER))); - tooltip.add(SpellAttributes.of(SpellAttributes.WAVE_SIZE, 10 + (int)type.traits().get(Trait.CHAOS, 0, 10))); - } + static final SpellAttribute WAVE_SIZE = SpellAttribute.create(SpellAttributes.WAVE_SIZE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.CHAOS, chaos -> 10 + (int)MathHelper.clamp(chaos, 0, 10)); + static final TooltipFactory TOOLTIP = TooltipFactory.of(RANGE, WAVE_SIZE); private final List> summonedEntities = new ArrayList<>(); @@ -97,7 +97,7 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti @Override public boolean tick(Caster source, Situation situation) { - float radius = 4 + source.getLevel().getScaled(4) * 4 + getAdditionalRange(); + float radius = source.getLevel().getScaled(4) * 4 + RANGE.get(getTraits()); if (radius <= 0) { return false; @@ -129,14 +129,16 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti return true; }).isEmpty()); - float additional = source.asWorld().getLocalDifficulty(source.getOrigin()).getLocalDifficulty() + getTraits().get(Trait.CHAOS, 0, 10); - if (--spawnCountdown > 0 && !summonedEntities.isEmpty()) { return true; } + // TODO: refactory speed attribute + // TODO: weather resistant attribute spawnCountdown = 1200 + source.asWorld().random.nextInt(rainy ? 2000 : 1000); - if (summonedEntities.size() > 10 + additional) { + float additional = source.asWorld().getLocalDifficulty(source.getOrigin()).getLocalDifficulty() + WAVE_SIZE.get(getTraits()); + + if (summonedEntities.size() > additional) { return true; } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java index e64aa6fa..d4292c7c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java @@ -36,7 +36,7 @@ public class ScorchSpell extends FireSpell implements ProjectileDelegate.Configu BlockPos pos = PosHelper.findSolidGroundAt(source.asWorld(), source.getOrigin(), source.getPhysics().getGravitySignum()); if (source.canModifyAt(pos) && StateMaps.FIRE_AFFECTED.convert(source.asWorld(), pos)) { - source.spawnParticles(new Sphere(false, Math.max(1, getAdditionalRange())), 5, p -> { + source.spawnParticles(new Sphere(false, RANGE.get(getTraits())), 5, p -> { source.addParticle(ParticleTypes.SMOKE, PosHelper.offset(p, pos), Vec3d.ZERO); }); } 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 705fb4b0..b95f344a 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,17 +1,19 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import java.util.List; import java.util.Optional; import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Caster; -import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; +import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; +import com.minelittlepony.unicopia.ability.magic.spell.attribute.CastOn; +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.client.minelittlepony.MineLPDelegate; @@ -38,7 +40,6 @@ 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.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -50,31 +51,18 @@ public class ShieldSpell extends AbstractSpell { .with(Trait.AIR, 9) .build(); - static void appendTooltip(CustomisedSpellType type, List tooltip) { - AbstractAreaEffectSpell.appendRangeTooltip(type, tooltip); - appendValidTargetsTooltip(type, tooltip); - appendCastLocationTooltip(type, tooltip); - } + static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power)); + protected static final SpellAttribute CAST_ON = SpellAttribute.createEnumerated(SpellAttributes.CAST_ON, Trait.GENEROSITY, generosity -> generosity > 0 ? CastOn.LOCATION : CastOn.SELF); - static void appendValidTargetsTooltip(CustomisedSpellType type, List tooltip) { - if (type.traits().get(Trait.KNOWLEDGE) > 10) { - tooltip.add(SpellAttributes.PERMIT_ITEMS); - } else { - if (type.traits().get(Trait.LIFE) > 0) { - tooltip.add(SpellAttributes.PERMIT_PASSIVE); - } - if (type.traits().get(Trait.BLOOD) > 0) { - tooltip.add(SpellAttributes.PERMIT_HOSTILE); - } - if (type.traits().get(Trait.ICE) > 0) { - tooltip.add(SpellAttributes.PERMIT_PLAYER); - } - } - } + static final SpellAttribute TARGET_ITEMS = SpellAttribute.createConditional(SpellAttributes.PERMIT_ITEMS, Trait.KNOWLEDGE, knowledge -> knowledge > 10); + static final SpellAttribute PERMIT_PASSIVE = SpellAttribute.createConditional(SpellAttributes.PERMIT_PASSIVE, Trait.LIFE, l -> l > 0); + static final SpellAttribute PERMIT_HOSTILE = SpellAttribute.createConditional(SpellAttributes.PERMIT_HOSTILE, Trait.BLOOD, l -> l > 0); + static final SpellAttribute PERMIT_PLAYER = SpellAttribute.createConditional(SpellAttributes.PERMIT_PLAYER, Trait.ICE, l -> l > 0); - static void appendCastLocationTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(type.traits().get(Trait.GENEROSITY) > 0 ? SpellAttributes.CAST_ON_LOCATION : SpellAttributes.CAST_ON_PERSON); - } + static final TooltipFactory PERMIT_ENTITY = TooltipFactory.of(PERMIT_PASSIVE, PERMIT_HOSTILE, PERMIT_PLAYER); + static final TooltipFactory TARGET = (type, tooltip) -> (TARGET_ITEMS.get(type.traits()) ? TARGET_ITEMS : PERMIT_ENTITY).appendTooltip(type, tooltip); + + static final TooltipFactory TOOLTIP = TooltipFactory.of(RANGE, TARGET, CAST_ON); protected final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget); @@ -90,7 +78,7 @@ public class ShieldSpell extends AbstractSpell { @Override public Spell prepareForCast(Caster caster, CastingMethod method) { - return method == CastingMethod.STAFF || getTraits().get(Trait.GENEROSITY) > 0 ? toPlaceable() : this; + return method == CastingMethod.STAFF || CAST_ON.get(getTraits()) == CastOn.LOCATION ? toPlaceable() : this; } @Override @@ -176,7 +164,7 @@ public class ShieldSpell extends AbstractSpell { * Calculates the maximum radius of the shield. aka The area of effect. */ public double getDrawDropOffRange(Caster source) { - float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER); + float min = (source instanceof Pony ? 0 : 2) + RANGE.get(getTraits()); double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier.getValue(); return range; @@ -184,7 +172,7 @@ public class ShieldSpell extends AbstractSpell { protected boolean isValidTarget(Caster source, Entity entity) { - if (getTraits().get(Trait.KNOWLEDGE) > 10) { + if (TARGET_ITEMS.get(getTraits())) { return entity instanceof ItemEntity; } @@ -198,13 +186,13 @@ public class ShieldSpell extends AbstractSpell { || entity instanceof BoatEntity ); - if (getTraits().get(Trait.LIFE) > 0) { + if (PERMIT_PASSIVE.get(getTraits())) { valid &= !(entity instanceof PassiveEntity); } - if (getTraits().get(Trait.BLOOD) > 0) { + if (PERMIT_HOSTILE.get(getTraits())) { valid &= !(entity instanceof HostileEntity); } - if (getTraits().get(Trait.ICE) > 0) { + if (PERMIT_PLAYER.get(getTraits())) { valid &= !(entity instanceof PlayerEntity); } return valid; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SiphoningSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SiphoningSpell.java index a7e1cbfd..d844c066 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SiphoningSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SiphoningSpell.java @@ -12,7 +12,6 @@ import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import com.minelittlepony.unicopia.entity.player.Pony; @@ -31,7 +30,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleTypes; import net.minecraft.predicate.entity.EntityPredicates; -import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -41,10 +39,6 @@ import net.minecraft.util.math.Vec3d; public class SiphoningSpell extends AbstractAreaEffectSpell { static final Predicate TARGET_PREDICATE = EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_LIVING_ENTITY); - static void appendTooltip(CustomisedSpellType type, List tooltip) { - tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 4)); - } - private final DataTracker.Entry upset = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private int ticksUpset; @@ -65,7 +59,7 @@ public class SiphoningSpell extends AbstractAreaEffectSpell { } if (source.isClient()) { - float radius = 4 + source.getLevel().getScaled(5) + getAdditionalRange(); + float radius = source.getLevel().getScaled(5) + RANGE.get(getTraits()); int direction = isFriendlyTogether(source) ? 1 : -1; source.spawnParticles(new Sphere(true, radius, 1, 0, 1), 1, pos -> { 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 9ae37a33..0ca190f8 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 @@ -9,6 +9,7 @@ import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Affine; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; +import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.ChangelingFeedingSpell; import com.minelittlepony.unicopia.ability.magic.spell.DispersableDisguiseSpell; import com.minelittlepony.unicopia.ability.magic.spell.RainboomAbilitySpell; @@ -17,6 +18,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.RageAbilitySpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.ThrowableSpell; import com.minelittlepony.unicopia.ability.magic.spell.TimeControlAbilitySpell; +import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.item.GemstoneItem; import com.minelittlepony.unicopia.item.UItems; @@ -53,31 +55,31 @@ public final class SpellType implements Affine, SpellPredicate< public static final SpellType RAGE = register("rage", builder(RageAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.FLAME)); public static final SpellType TIME_CONTROL = register("time_control", builder(TimeControlAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.STAR)); - public static final SpellType FROST = register("frost", builder(IceSpell::new).color(0xEABBFF).shape(GemstoneItem.Shape.TRIANGLE).traits(IceSpell.DEFAULT_TRAITS)); + public static final SpellType FROST = register("frost", builder(IceSpell::new).color(0xEABBFF).shape(GemstoneItem.Shape.TRIANGLE).traits(IceSpell.DEFAULT_TRAITS).tooltip(IceSpell.TOOLTIP)); public static final SpellType CHILLING_BREATH = register("chilling_breath", builder(ChillingBreathSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEAFF).shape(GemstoneItem.Shape.TRIANGLE).traits(ChillingBreathSpell.DEFAULT_TRAITS)); - public static final SpellType SCORCH = register("scorch", builder(ScorchSpell::new).affinity(Affinity.BAD).color(0xF8EC1F).stackable().shape(GemstoneItem.Shape.FLAME).traits(ScorchSpell.DEFAULT_TRAITS).tooltip(FireSpell::appendTooltip)); - public static final SpellType FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS).tooltip(FireSpell::appendTooltip)); - public static final SpellType INFERNAL = register("infernal", builder(InfernoSpell::new).affinity(Affinity.BAD).color(0xFFAA00).shape(GemstoneItem.Shape.FLAME).traits(InfernoSpell.DEFAULT_TRAITS).tooltip(FireSpell::appendTooltip)); - 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).tooltip(AreaProtectionSpell::appendTooltip)); - public static final SpellType VORTEX = register("vortex", builder(AttractiveSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEA88).shape(GemstoneItem.Shape.VORTEX).traits(AttractiveSpell.DEFAULT_TRAITS).tooltip(AttractiveSpell::appendTooltip2)); + public static final SpellType SCORCH = register("scorch", builder(ScorchSpell::new).affinity(Affinity.BAD).color(0xF8EC1F).stackable().shape(GemstoneItem.Shape.FLAME).traits(ScorchSpell.DEFAULT_TRAITS).tooltip(AbstractAreaEffectSpell.TOOLTIP)); + public static final SpellType FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS).tooltip(AbstractAreaEffectSpell.TOOLTIP)); + public static final SpellType INFERNAL = register("infernal", builder(InfernoSpell::new).affinity(Affinity.BAD).color(0xFFAA00).shape(GemstoneItem.Shape.FLAME).traits(InfernoSpell.DEFAULT_TRAITS).tooltip(AbstractAreaEffectSpell.TOOLTIP)); + 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.TOOLTIP)); + 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).tooltip(AreaProtectionSpell.TOOLTIP)); + public static final SpellType VORTEX = register("vortex", builder(AttractiveSpell::new).affinity(Affinity.NEUTRAL).color(0xFFEA88).shape(GemstoneItem.Shape.VORTEX).traits(AttractiveSpell.DEFAULT_TRAITS).tooltip(AttractiveSpell.TOOLTIP)); 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)); - public static final SpellType NECROMANCY = register("necromancy", builder(NecromancySpell::new).affinity(Affinity.BAD).color(0xFA3A3A).shape(GemstoneItem.Shape.SKULL).tooltip(NecromancySpell::appendTooltip)); - public static final SpellType SIPHONING = register("siphoning", builder(SiphoningSpell::new).affinity(Affinity.NEUTRAL).color(0xFFA3AA).shape(GemstoneItem.Shape.LAMBDA).tooltip(SiphoningSpell::appendTooltip)); - public static final SpellType REVEALING = register("reveal", builder(DisperseIllusionSpell::new).color(0xFFFFAF).shape(GemstoneItem.Shape.CROSS).tooltip(DisperseIllusionSpell::appendTooltip)); + public static final SpellType NECROMANCY = register("necromancy", builder(NecromancySpell::new).affinity(Affinity.BAD).color(0xFA3A3A).shape(GemstoneItem.Shape.SKULL).tooltip(NecromancySpell.TOOLTIP)); + public static final SpellType SIPHONING = register("siphoning", builder(SiphoningSpell::new).affinity(Affinity.NEUTRAL).color(0xFFA3AA).shape(GemstoneItem.Shape.LAMBDA).tooltip(AbstractAreaEffectSpell.TOOLTIP)); + public static final SpellType REVEALING = register("reveal", builder(DisperseIllusionSpell::new).color(0xFFFFAF).shape(GemstoneItem.Shape.CROSS).tooltip(DisperseIllusionSpell.TOOLTIP)); public static final SpellType AWKWARD = register("awkward", builder(AwkwardSpell::new).affinity(Affinity.NEUTRAL).color(0x3A59FF).shape(GemstoneItem.Shape.ICE)); public static final SpellType TRANSFORMATION = register("transformation", builder(TransformationSpell::new).color(0x19E48E).shape(GemstoneItem.Shape.BRUSH)); public static final SpellType 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 CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell.TOOLTIP::appendTooltip)); - public static final SpellType 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 LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell::appendTooltip)); - public static final SpellType DISPLACEMENT = register("displacement", builder(DisplacementSpell::new).affinity(Affinity.NEUTRAL).color(0x9900FF).stackable().shape(GemstoneItem.Shape.BRUSH).traits(PortalSpell.DEFAULT_TRAITS).tooltip(DisplacementSpell::appendTooltip)); + public static final SpellType CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell.TOOLTIP)); + public static final SpellType FIRE_BOLT = register("fire_bolt", builder(FireBoltSpell::new).color(0xFF8811).shape(GemstoneItem.Shape.FLAME).traits(FireBoltSpell.DEFAULT_TRAITS).tooltip(FireBoltSpell.TOOLTIP)); + public static final SpellType LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell.TOOLTIP)); + public static final SpellType DISPLACEMENT = register("displacement", builder(DisplacementSpell::new).affinity(Affinity.NEUTRAL).color(0x9900FF).stackable().shape(GemstoneItem.Shape.BRUSH).traits(PortalSpell.DEFAULT_TRAITS).tooltip(DisplacementSpell.TOOLTIP)); public static final SpellType PORTAL = register("portal", builder(PortalSpell::new).color(0x99FFFF).shape(GemstoneItem.Shape.RING).traits(PortalSpell.DEFAULT_TRAITS)); - public static final SpellType MIMIC = register("mimic", builder(MimicSpell::new).color(0xFFFF00).shape(GemstoneItem.Shape.ARROW).tooltip(MimicSpell::appendTooltip)); - public static final SpellType MIND_SWAP = register("mind_swap", builder(MindSwapSpell::new).affinity(Affinity.BAD).color(0xF9FF99).shape(GemstoneItem.Shape.WAVE).tooltip(MimicSpell::appendTooltip)); - public static final SpellType HYDROPHOBIC = register("hydrophobic", SpellType.builder(s -> new HydrophobicSpell(s, FluidTags.WATER)).affinity(Affinity.NEUTRAL).color(0xF999FF).stackable().shape(GemstoneItem.Shape.ROCKET).tooltip(HydrophobicSpell::appendTooltip)); - public static final SpellType BUBBLE = register("bubble", builder(BubbleSpell::new).affinity(Affinity.NEUTRAL).color(0xF999FF).shape(GemstoneItem.Shape.DONUT).traits(BubbleSpell.DEFAULT_TRAITS).tooltip(BubbleSpell::appendTooltip)); - public static final SpellType DISPEL_EVIL = register("dispel_evil", builder(DispellEvilSpell::new).color(0x00FF00).shape(GemstoneItem.Shape.CROSS).traits(DispellEvilSpell.DEFAULT_TRAITS).tooltip(DispellEvilSpell::appendTooltip)); + public static final SpellType MIMIC = register("mimic", builder(MimicSpell::new).color(0xFFFF00).shape(GemstoneItem.Shape.ARROW).tooltip(MimicSpell.TOOLTIP)); + public static final SpellType MIND_SWAP = register("mind_swap", builder(MindSwapSpell::new).affinity(Affinity.BAD).color(0xF9FF99).shape(GemstoneItem.Shape.WAVE).tooltip(MimicSpell.TOOLTIP)); + public static final SpellType HYDROPHOBIC = register("hydrophobic", SpellType.builder(s -> new HydrophobicSpell(s, FluidTags.WATER)).affinity(Affinity.NEUTRAL).color(0xF999FF).stackable().shape(GemstoneItem.Shape.ROCKET).tooltip(HydrophobicSpell.TOOLTIP)); + public static final SpellType BUBBLE = register("bubble", builder(BubbleSpell::new).affinity(Affinity.NEUTRAL).color(0xF999FF).shape(GemstoneItem.Shape.DONUT).traits(BubbleSpell.DEFAULT_TRAITS).tooltip(BubbleSpell.TOOLTIP)); + public static final SpellType DISPEL_EVIL = register("dispel_evil", builder(DispellEvilSpell::new).color(0x00FF00).shape(GemstoneItem.Shape.CROSS).traits(DispellEvilSpell.DEFAULT_TRAITS).tooltip(DispellEvilSpell.TOOLTIP)); public static void bootstrap() {} @@ -274,6 +276,12 @@ public final class SpellType implements Affine, SpellPredicate< return this; } + public Builder tooltip(TooltipFactory tooltipFunction) { + this.tooltipFunction = tooltipFunction::appendTooltip; + return this; + } + + @Deprecated public Builder tooltip(BiConsumer, List> tooltipFunction) { this.tooltipFunction = tooltipFunction; return this;