Finish porting spell attributes to the new system

This commit is contained in:
Sollace 2024-06-22 19:40:49 +01:00
parent b30e9c5f1f
commit 9ee81c961c
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
23 changed files with 172 additions and 198 deletions

View file

@ -3,12 +3,13 @@ package com.minelittlepony.unicopia.ability.magic.spell;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory;
import com.minelittlepony.unicopia.ability.magic.spell.effect.*; import com.minelittlepony.unicopia.ability.magic.spell.effect.*;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
public abstract class AbstractAreaEffectSpell extends AbstractSpell { public abstract class AbstractAreaEffectSpell extends AbstractSpell {
protected static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power)); protected static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power));
public static final TooltipFactory TOOLTIP = RANGE; public static final TooltipFactory TOOLTIP = RANGE;
protected AbstractAreaEffectSpell(CustomisedSpellType<?> type) { protected AbstractAreaEffectSpell(CustomisedSpellType<?> type) {

View file

@ -1,83 +0,0 @@
package com.minelittlepony.unicopia.ability.magic.spell;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.entity.effect.EffectUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.StringHelper;
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"));
Identifier FOLLOWS_TARGET = Unicopia.id("follows_target");
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");
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");
Identifier EXPLOSION_STRENGTH = Unicopia.id("explosion_strength");
Identifier PROJECTILE_COUNT = Unicopia.id("projectile_count");
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",
ItemStack.MODIFIER_FORMAT.format(value),
Text.translatable(Util.createTranslationKey("spell_attribute", id)))
).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)),
Text.translatable(Util.createTranslationKey("spell_attribute", id))
).formatted(Formatting.LIGHT_PURPLE));
}
@Deprecated
public enum ValueType {
REGULAR,
TIME,
PERCENTAGE,
CONDITIONAL
}
}

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.ability.magic.spell;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.util.NbtSerialisable; import com.minelittlepony.unicopia.util.NbtSerialisable;
import com.minelittlepony.unicopia.util.Tickable; import com.minelittlepony.unicopia.util.Tickable;
@ -14,7 +15,7 @@ import net.minecraft.util.math.MathHelper;
*/ */
public interface TimedSpell extends Spell { public interface TimedSpell extends Spell {
int BASE_DURATION = 120 * 20; int BASE_DURATION = 120 * 20;
SpellAttribute<Integer> TIME = SpellAttribute.create(SpellAttributes.SOAPINESS, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> BASE_DURATION + (int)(MathHelper.clamp(focus, 0, 160) * 19) * 20); SpellAttribute<Integer> TIME = SpellAttribute.create(SpellAttributeType.SOAPINESS, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> BASE_DURATION + (int)(MathHelper.clamp(focus, 0, 160) * 19) * 20);
Timer getTimer(); Timer getTimer();

View file

@ -56,7 +56,7 @@ public enum AttributeFormat {
return Text.translatable("spell_attribute.unicopia.added_trait." + ((value > 0) ? "plus" : "take"), name, count).formatted(Formatting.DARK_AQUA); return Text.translatable("spell_attribute.unicopia.added_trait." + ((value > 0) ? "plus" : "take"), name, count).formatted(Formatting.DARK_AQUA);
} }
static MutableText formatAttributeLine(Text attributeName) { public static MutableText formatAttributeLine(Text attributeName) {
return Text.literal(" ").append(attributeName).formatted(Formatting.LIGHT_PURPLE); return Text.literal(" ").append(attributeName).formatted(Formatting.LIGHT_PURPLE);
} }

View file

@ -14,7 +14,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import it.unimi.dsi.fastutil.floats.Float2ObjectFunction; import it.unimi.dsi.fastutil.floats.Float2ObjectFunction;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util; import net.minecraft.util.Util;
public record SpellAttribute<T> ( public record SpellAttribute<T> (
@ -31,34 +30,33 @@ public record SpellAttribute<T> (
return valueGetter.apply(traits, traits.get(trait)); return valueGetter.apply(traits, traits.get(trait));
} }
public static <T extends Number> SpellAttribute<T> create(Identifier id, AttributeFormat format, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter) { public static <T extends Number> SpellAttribute<T> create(SpellAttributeType id, AttributeFormat format, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter) {
return create(id, format, format, trait, valueGetter, false); return create(id, format, format, trait, valueGetter, false);
} }
public static <T extends Number> SpellAttribute<T> create(Identifier id, AttributeFormat format, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter) { public static <T extends Number> SpellAttribute<T> create(SpellAttributeType id, AttributeFormat format, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter) {
return create(id, format, format, trait, valueGetter, false); 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) { public static <T extends Number> SpellAttribute<T> create(SpellAttributeType id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, Float2ObjectFunction<@NotNull T> valueGetter) {
return create(id, baseFormat, relativeFormat, trait, valueGetter, false); return create(id, baseFormat, relativeFormat, trait, valueGetter, false);
} }
public static <T extends Number> SpellAttribute<T> create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter) { public static <T extends Number> SpellAttribute<T> create(SpellAttributeType id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter) {
return create(id, baseFormat, relativeFormat, trait, valueGetter, false); 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) { public static <T extends @NotNull Number> SpellAttribute<T> create(SpellAttributeType 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); return create(id, baseFormat, relativeFormat, trait, (traits, value) -> valueGetter.get(value.floatValue()), detrimental);
} }
public static <T extends @NotNull Number> SpellAttribute<T> create(Identifier id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter, boolean detrimental) { public static <T extends @NotNull Number> SpellAttribute<T> create(SpellAttributeType id, AttributeFormat baseFormat, AttributeFormat relativeFormat, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter, boolean detrimental) {
Text name = Text.translatable(Util.createTranslationKey("spell_attribute", id));
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> { return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
float traitAmount = type.traits().get(trait); float traitAmount = type.traits().get(trait);
float traitDifference = type.relativeTraits().get(trait); float traitDifference = type.relativeTraits().get(trait);
float value = valueGetter.apply(type.traits(), traitAmount).floatValue(); float value = valueGetter.apply(type.traits(), traitAmount).floatValue();
var b = baseFormat.getBase(name, value, "equals", Formatting.LIGHT_PURPLE); var b = baseFormat.getBase(id.name(), value, "equals", Formatting.LIGHT_PURPLE);
if (traitDifference != 0) { if (traitDifference != 0) {
tooltip.add(b.append(relativeFormat.getRelative(Text.empty(), valueGetter.apply(type.traits(), 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)); tooltip.add(AttributeFormat.formatTraitDifference(trait, traitDifference));
@ -68,15 +66,14 @@ public record SpellAttribute<T> (
}); });
} }
public static SpellAttribute<Boolean> createConditional(Identifier id, Trait trait, Float2ObjectFunction<Boolean> valueGetter) { public static SpellAttribute<Boolean> createConditional(SpellAttributeType id, Trait trait, Float2ObjectFunction<Boolean> valueGetter) {
return createConditional(id, trait, (traits, value) -> valueGetter.get(value.floatValue())); return createConditional(id, trait, (traits, value) -> valueGetter.get(value.floatValue()));
} }
public static SpellAttribute<Boolean> createConditional(Identifier id, Trait trait, BiFunction<SpellTraits, Float, @NotNull Boolean> valueGetter) { public static SpellAttribute<Boolean> createConditional(SpellAttributeType id, Trait trait, BiFunction<SpellTraits, Float, @NotNull Boolean> valueGetter) {
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> { 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); float difference = type.relativeTraits().get(trait);
Text value = AttributeFormat.formatAttributeLine(name); Text value = AttributeFormat.formatAttributeLine(id.name());
if (!valueGetter.apply(type.traits(), type.traits().get(trait))) { if (!valueGetter.apply(type.traits(), type.traits().get(trait))) {
value = value.copy().formatted(Formatting.STRIKETHROUGH, Formatting.DARK_GRAY); value = value.copy().formatted(Formatting.STRIKETHROUGH, Formatting.DARK_GRAY);
} }
@ -87,12 +84,12 @@ public record SpellAttribute<T> (
}); });
} }
public static <T extends Enum<T>> SpellAttribute<T> createEnumerated(Identifier id, Trait trait, Float2ObjectFunction<T> valueGetter) { public static <T extends Enum<T>> SpellAttribute<T> createEnumerated(SpellAttributeType id, Trait trait, Float2ObjectFunction<T> valueGetter) {
return createEnumerated(id, trait, (traits, value) -> valueGetter.get(value.floatValue())); return createEnumerated(id, trait, (traits, value) -> valueGetter.get(value.floatValue()));
} }
public static <T extends Enum<T>> SpellAttribute<T> createEnumerated(Identifier id, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter) { public static <T extends Enum<T>> SpellAttribute<T> createEnumerated(SpellAttributeType id, Trait trait, BiFunction<SpellTraits, Float, @NotNull T> valueGetter) {
Function<T, Text> cache = Util.memoize(t -> Text.translatable(Util.createTranslationKey("spell_attribute", id.withPath(id.getPath() + "." + t.name().toLowerCase(Locale.ROOT))))); Function<T, Text> cache = Util.memoize(t -> Text.translatable(Util.createTranslationKey("spell_attribute", id.id().withPath(p -> p + "." + t.name().toLowerCase(Locale.ROOT)))));
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> { return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
T t = valueGetter.apply(type.traits(), type.traits().get(trait)); T t = valueGetter.apply(type.traits(), type.traits().get(trait));

View file

@ -0,0 +1,59 @@
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
import java.util.ArrayList;
import java.util.List;
import com.minelittlepony.unicopia.Unicopia;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
public record SpellAttributeType(Identifier id, Text name) {
public static final List<SpellAttributeType> REGISTRY = new ArrayList<>();
@Deprecated
public static final SpellAttributeType CAST_ON_LOCATION = register("cast_on.location");
public static final SpellAttributeType FOLLOWS_TARGET = register("follows_target");
public static final SpellAttributeType PERMIT_ITEMS = register("permit_items");
public static final SpellAttributeType PERMIT_PASSIVE = register("permit_passive");
public static final SpellAttributeType PERMIT_HOSTILE = register("permit_hostile");
public static final SpellAttributeType PERMIT_PLAYER = register("permit_player");
public static final SpellAttributeType FOCUSED_ENTITY = register("focused_entity");
public static final SpellAttributeType RANGE = register("range");
public static final SpellAttributeType DURATION = register("duration");
public static final SpellAttributeType STRENGTH = register("strength");
public static final SpellAttributeType VELOCITY = register("velocity");
public static final SpellAttributeType VERTICAL_VELOCITY = register("vertical_velocity");
public static final SpellAttributeType HANG_TIME = register("hang_time");
public static final SpellAttributeType PUSHING_POWER = register("pushing_power");
public static final SpellAttributeType CAUSES_LEVITATION = register("causes_levitation");
public static final SpellAttributeType AFFECTS = register("affects");
public static final SpellAttributeType DAMAGE_TO_TARGET = register("damage_to_target");
public static final SpellAttributeType SIMULTANIOUS_TARGETS = register("simultanious_targets");
public static final SpellAttributeType COST_PER_INDIVIDUAL = register("cost_per_individual");
public static final SpellAttributeType EXPLOSION_STRENGTH = register("explosion_strength");
public static final SpellAttributeType PROJECTILE_COUNT = register("projectile_count");
public static final SpellAttributeType ORB_COUNT = register("orb_count");
public static final SpellAttributeType WAVE_SIZE = register("wave_size");
public static final SpellAttributeType FOLLOW_RANGE = register("follow_range");
public static final SpellAttributeType LIGHT_TARGET = register("light_target");
public static final SpellAttributeType STICK_TO_TARGET = register("stick_to_target");
public static final SpellAttributeType SOAPINESS = register("soapiness");
public static final SpellAttributeType CAST_ON = register("cast_on");
public static final SpellAttributeType TARGET_PREFERENCE = register("target_preference");
public static final SpellAttributeType CASTER_PREFERENCE = register("caster_preference");
public static final SpellAttributeType NEGATES_FALL_DAMAGE = register("negates_fall_damage");
public SpellAttributeType(Identifier id) {
this(id, Text.translatable(Util.createTranslationKey("spell_attribute", id)));
}
public static SpellAttributeType register(String name) {
SpellAttributeType type = new SpellAttributeType(Unicopia.id(name));
REGISTRY.add(type);
return type;
}
}

View file

@ -9,6 +9,8 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import net.minecraft.text.Text; import net.minecraft.text.Text;
public interface TooltipFactory { public interface TooltipFactory {
TooltipFactory EMPTY = (type, tooltip) -> {};
void appendTooltip(CustomisedSpellType<?> type, List<Text> tooltip); void appendTooltip(CustomisedSpellType<?> type, List<Text> tooltip);
static TooltipFactory of(TooltipFactory...lines) { static TooltipFactory of(TooltipFactory...lines) {

View file

@ -2,8 +2,12 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; 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.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.SpellAttributes; import com.minelittlepony.unicopia.ability.magic.spell.Spell;
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.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -24,16 +28,18 @@ public class AreaProtectionSpell extends AbstractAreaEffectSpell {
.with(Trait.STRENGTH, 30) .with(Trait.STRENGTH, 30)
.build(); .build();
static final TooltipFactory TOOLTIP = TooltipFactory.of(TooltipFactory.of(SpellAttributes.CAST_ON_LOCATION), RANGE); private static final SpellAttribute<CastOn> CAST_ON = SpellAttribute.createEnumerated(SpellAttributeType.CAST_ON, Trait.FOCUS, focus -> focus > 0 ? CastOn.SELF : CastOn.LOCATION);
static final TooltipFactory TOOLTIP = TooltipFactory.of(CAST_ON, RANGE);
protected AreaProtectionSpell(CustomisedSpellType<?> type) { protected AreaProtectionSpell(CustomisedSpellType<?> type) {
super(type); super(type);
} }
/*@Override @Override
public Spell prepareForCast(Caster<?> caster, CastingMethod method) { 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 @Override
public boolean tick(Caster<?> source, Situation situation) { public boolean tick(Caster<?> source, Situation situation) {

View file

@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.*;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute; import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.EntityReference;
@ -22,8 +23,8 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSpell, ProjectileDelegate.EntityHitListener { public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSpell, ProjectileDelegate.EntityHitListener {
static final SpellAttribute<Boolean> TARGET_FOCUSED_ENTITY = SpellAttribute.createConditional(SpellAttributes.FOCUSED_ENTITY, Trait.ORDER, order -> order >= 20); static final SpellAttribute<Boolean> TARGET_FOCUSED_ENTITY = SpellAttribute.createConditional(SpellAttributeType.FOCUSED_ENTITY, Trait.ORDER, order -> order >= 20);
static final SpellAttribute<Boolean> STICK_TO_TARGET = SpellAttribute.createConditional(SpellAttributes.STICK_TO_TARGET, Trait.CHAOS, chaos -> chaos > 0); static final SpellAttribute<Boolean> STICK_TO_TARGET = SpellAttribute.createConditional(SpellAttributeType.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 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); static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, RANGE, TARGET, STICK_TO_TARGET, CAST_ON);

View file

@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.*;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -51,7 +52,7 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
.with(Trait.POWER, 1) .with(Trait.POWER, 1)
.build(); .build();
private static final SpellAttribute<Integer> SOAPINESS = SpellAttribute.create(SpellAttributes.SOAPINESS, AttributeFormat.REGULAR, Trait.POWER, power -> (int)(power * 2)); private static final SpellAttribute<Integer> SOAPINESS = SpellAttribute.create(SpellAttributeType.SOAPINESS, AttributeFormat.REGULAR, Trait.POWER, power -> (int)(power * 2));
static final TooltipFactory TOOLTIP = TooltipFactory.of(TimedSpell.TIME, SOAPINESS); static final TooltipFactory TOOLTIP = TooltipFactory.of(TimedSpell.TIME, SOAPINESS);

View file

@ -8,10 +8,10 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.Affects;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -49,11 +49,11 @@ public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.B
private static final float HORIZONTAL_VARIANCE = 0.25F; private static final float HORIZONTAL_VARIANCE = 0.25F;
private static final float MAX_STRENGTH = 120; 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> LAUNCH_SPEED = SpellAttribute.create(SpellAttributeType.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> HANG_TIME = SpellAttribute.create(SpellAttributeType.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<Float> PUSHING_POWER = SpellAttribute.create(SpellAttributeType.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<Boolean> CAUSES_LEVITATION = SpellAttribute.createConditional(SpellAttributeType.CAUSES_LEVITATION, Trait.FOCUS, focus -> focus > 50);
private static final SpellAttribute<Affects> AFFECTS = SpellAttribute.createEnumerated(SpellAttributes.AFFECTS, Trait.ORDER, order -> { private static final SpellAttribute<Affects> AFFECTS = SpellAttribute.createEnumerated(SpellAttributeType.AFFECTS, Trait.ORDER, order -> {
if (order <= 0) { if (order <= 0) {
return Affects.BOTH; return Affects.BOTH;
} else if (order <= 10) { } else if (order <= 10) {

View file

@ -94,7 +94,7 @@ public record CustomisedSpellType<T extends Spell> (
lines.addAll(TextHelper.wrap(lore, 180).toList()); lines.addAll(TextHelper.wrap(lore, 180).toList());
float corruption = ((int)traits().getCorruption() * 10) + type().getAffinity().getCorruption(); float corruption = ((int)traits().getCorruption() * 10) + type().getAffinity().getCorruption();
List<Text> modifiers = new ArrayList<>(); List<Text> modifiers = new ArrayList<>();
type.getTooltip().accept(this, modifiers); type.getTooltip().appendTooltip(this, modifiers);
if (corruption != 0) { if (corruption != 0) {
modifiers.add(EffectUtils.formatModifierChange("affinity.unicopia.corruption", corruption, true)); modifiers.add(EffectUtils.formatModifierChange("affinity.unicopia.corruption", corruption, true));
} }

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.*;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -21,7 +22,7 @@ public class DispellEvilSpell extends AbstractSpell implements ProjectileDelegat
.with(Trait.POWER, 1) .with(Trait.POWER, 1)
.build(); .build();
private static final SpellAttribute<Double> RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.POWER, power -> (1 + power) * 10D); private static final SpellAttribute<Double> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.TIME, AttributeFormat.PERCENTAGE, Trait.POWER, power -> (1 + power) * 10D);
static final TooltipFactory TOOLTIP = RANGE; static final TooltipFactory TOOLTIP = RANGE;

View file

@ -5,9 +5,9 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.AttributeFormat;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute; import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect;
@ -19,8 +19,8 @@ import net.minecraft.util.math.Vec3d;
* An area-effect spell that disperses illusions. * An area-effect spell that disperses illusions.
*/ */
public class DisperseIllusionSpell extends AbstractAreaEffectSpell { public class DisperseIllusionSpell extends AbstractAreaEffectSpell {
private static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 15 + power)); private static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 15 + power));
private static final SpellAttribute<Long> DURATION = SpellAttribute.create(SpellAttributes.DURATION, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> (1 + (long)strength) * 100); private static final SpellAttribute<Long> DURATION = SpellAttribute.create(SpellAttributeType.DURATION, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> (1 + (long)strength) * 100);
static final TooltipFactory TOOLTIP = TooltipFactory.of(RANGE, DURATION); static final TooltipFactory TOOLTIP = TooltipFactory.of(RANGE, DURATION);
protected DisperseIllusionSpell(CustomisedSpellType<?> type) { protected DisperseIllusionSpell(CustomisedSpellType<?> type) {

View file

@ -5,6 +5,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.*;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.EntityReference;
@ -19,7 +20,7 @@ import net.minecraft.util.math.Vec3d;
public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener { public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener {
private static final SpellAttribute<Float> DAMAGE_TO_TARGET = SpellAttribute.create(SpellAttributes.DAMAGE_TO_TARGET, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.BLOOD, blood -> blood); private static final SpellAttribute<Float> DAMAGE_TO_TARGET = SpellAttribute.create(SpellAttributeType.DAMAGE_TO_TARGET, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.BLOOD, blood -> blood);
static final TooltipFactory TOOLTIP = DAMAGE_TO_TARGET; static final TooltipFactory TOOLTIP = DAMAGE_TO_TARGET;

View file

@ -5,8 +5,11 @@ import java.util.stream.Stream;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.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.SpellAttributeType;
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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.item.FriendshipBraceletItem; import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
@ -16,7 +19,6 @@ import com.minelittlepony.unicopia.particle.ParticleUtils;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -30,6 +32,25 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell {
private static final float POWERS_RANGE_WEIGHT = 0.3F; private static final float POWERS_RANGE_WEIGHT = 0.3F;
private static final float MAX_GENEROSITY_FACTOR = 19F; private static final float MAX_GENEROSITY_FACTOR = 19F;
private static final SpellAttribute<Integer> DURATION = SpellAttribute.create(SpellAttributeType.DURATION, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> 10 + (int)(MathHelper.clamp(focus, 0, 160)));
private static final SpellAttribute<Float> STRENGTH = SpellAttribute.create(SpellAttributeType.STRENGTH, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> MathHelper.clamp(strength, 2, 9));
private static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> MathHelper.clamp((power - 10) * POWERS_RANGE_WEIGHT, MIN_RANGE, MAX_RANGE));
private static final SpellAttribute<Long> SIMULTANIOUS_TARGETS = SpellAttribute.create(SpellAttributeType.SIMULTANIOUS_TARGETS, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.GENEROSITY, (traits, generosity) -> {
return (long)(generosity + traits.get(Trait.FOCUS, MIN_TARGETS, MAX_TARGETS) * 2);
});
private static final SpellAttribute<Float> COST_PER_INDIVIDUAL = SpellAttribute.create(SpellAttributeType.COST_PER_INDIVIDUAL, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, (traits, power) -> {
return MathHelper.clamp(((Math.max(power, 10) - 10) * POWERS_RANGE_WEIGHT) - ((Math.max(traits.get(Trait.FOCUS), 80) - 80) * FOCUS_RANGE_WEIGHT), 1, 7);
});
private static final SpellAttribute<Float> TARGET_PREFERENCE = SpellAttribute.create(SpellAttributeType.TARGET_PREFERENCE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.GENEROSITY, generosity -> {
return MathHelper.clamp(generosity, 1, MAX_GENEROSITY_FACTOR) / MAX_GENEROSITY_FACTOR;
});
private static final SpellAttribute<Float> CASTER_PREFERENCE = SpellAttribute.create(SpellAttributeType.CASTER_PREFERENCE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.GENEROSITY, (traits, generosity) -> {
return 1 - TARGET_PREFERENCE.get(traits);
});
private static final SpellAttribute<Boolean> NEGATES_FALL_DAMAGE = SpellAttribute.createConditional(SpellAttributeType.NEGATES_FALL_DAMAGE, Trait.GENEROSITY, (generosity) -> generosity > 0.5F);
static final TooltipFactory TOOLTIP = TooltipFactory.of(DURATION, STRENGTH, RANGE, SIMULTANIOUS_TARGETS, COST_PER_INDIVIDUAL, TARGET_PREFERENCE, CASTER_PREFERENCE, NEGATES_FALL_DAMAGE);
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder() public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.FOCUS, 80) .with(Trait.FOCUS, 80)
.with(Trait.POWER, 10) .with(Trait.POWER, 10)
@ -38,22 +59,11 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell {
.with(Trait.ORDER, 15) .with(Trait.ORDER, 15)
.build(); .build();
public static void appendTooltip(CustomisedSpellType<FeatherFallSpell> type, List<Text> tooltip) {
tooltip.add(SpellAttributes.ofTime(SpellAttributes.DURATION, 10 + (int)(type.traits().get(Trait.FOCUS, 0, 160))));
tooltip.add(SpellAttributes.of(SpellAttributes.STRENGTH, type.traits().get(Trait.STRENGTH, 2, 9)));
tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, (float)getEffectRange(type.traits())));
tooltip.add(SpellAttributes.of(SpellAttributes.SIMULTANIOUS_TARGETS, getMaxTargets(type.traits())));
tooltip.add(SpellAttributes.of(SpellAttributes.COST_PER_INDIVIDUAL, (float)getCostPerEntity(type.traits())));
float generosity = type.traits().get(Trait.GENEROSITY, 1, MAX_GENEROSITY_FACTOR) / MAX_GENEROSITY_FACTOR;
tooltip.add(SpellAttributes.of(SpellAttributes.TARGET_PREFERENCE, (int)(generosity * 100)));
tooltip.add(SpellAttributes.of(SpellAttributes.CASTER_PREFERENCE, (int)((1 - generosity) * 100)));
}
private final Timer timer; private final Timer timer;
protected FeatherFallSpell(CustomisedSpellType<?> type) { protected FeatherFallSpell(CustomisedSpellType<?> type) {
super(type); super(type);
timer = new Timer(10 + (int)(getTraits().get(Trait.FOCUS, 0, 160))); timer = new Timer(DURATION.get(getTraits()));
} }
@Override @Override
@ -75,18 +85,16 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell {
return true; return true;
} }
final float strength = 1F / (getTraits().get(Trait.STRENGTH, 2, 9) / targets.size()); final float strength = 1F / (STRENGTH.get(getTraits()) / targets.size());
final float generosity = getTraits().get(Trait.GENEROSITY, 1, MAX_GENEROSITY_FACTOR) / MAX_GENEROSITY_FACTOR; final float targetPreference = TARGET_PREFERENCE.get(getTraits());
final float casterPreference = 1 - targetPreference;
final boolean negateFallDamage = NEGATES_FALL_DAMAGE.get(getTraits());
Entity entity = caster.asEntity(); Entity entity = caster.asEntity();
Vec3d masterVelocity = entity.getVelocity().multiply(0.1); Vec3d masterVelocity = entity.getVelocity().multiply(0.1);
targets.forEach(target -> { targets.forEach(target -> {
if (target.getVelocity().y < 0) { if (target.getVelocity().y < 0) {
if (negateFallDamage) {
boolean isSelf = caster.isOwnedBy(target) || target == entity;
float delta = strength * (isSelf ? (1F - generosity) : generosity);
if (!isSelf || generosity < 0.5F) {
target.verticalCollision = true; target.verticalCollision = true;
target.setOnGround(true); target.setOnGround(true);
target.fallDistance = 0; target.fallDistance = 0;
@ -94,6 +102,8 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell {
if (target instanceof PlayerEntity) { if (target instanceof PlayerEntity) {
((PlayerEntity)target).getAbilities().flying = false; ((PlayerEntity)target).getAbilities().flying = false;
} }
float delta = strength * ((caster.isOwnedBy(target) || target == entity) ? casterPreference : targetPreference);
target.setVelocity(target.getVelocity().multiply(1, delta, 1)); target.setVelocity(target.getVelocity().multiply(1, delta, 1));
if (situation == Situation.PROJECTILE && target != entity) { if (situation == Situation.PROJECTILE && target != entity) {
target.addVelocity(masterVelocity.x, 0, masterVelocity.z); target.addVelocity(masterVelocity.x, 0, masterVelocity.z);
@ -102,33 +112,16 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell {
ParticleUtils.spawnParticles(new MagicParticleEffect(getType().getColor()), target, 7); ParticleUtils.spawnParticles(new MagicParticleEffect(getType().getColor()), target, 7);
}); });
return caster.subtractEnergyCost(timer.getTicksRemaining() % 50 == 0 ? getCostPerEntity(getTraits()) * targets.size() : 0); return caster.subtractEnergyCost(timer.getTicksRemaining() % 50 == 0 ? COST_PER_INDIVIDUAL.get(getTraits()) * targets.size() : 0);
}
protected static double getCostPerEntity(SpellTraits traits) {
float focus = Math.max(traits.get(Trait.FOCUS), 80) - 80;
float power = Math.max(traits.get(Trait.POWER), 10) - 10;
return MathHelper.clamp((power * POWERS_RANGE_WEIGHT) - (focus * FOCUS_RANGE_WEIGHT), 1, 7);
}
protected static double getEffectRange(SpellTraits traits) {
return MathHelper.clamp((traits.get(Trait.POWER) - 10) * POWERS_RANGE_WEIGHT, MIN_RANGE, MAX_RANGE);
}
protected static long getMaxTargets(SpellTraits traits) {
long generosity = (long)traits.get(Trait.GENEROSITY) * 2L;
long focus = (long)traits.get(Trait.FOCUS, MIN_TARGETS, MAX_TARGETS) * 2L;
return generosity + focus;
} }
protected Stream<Entity> getTargets(Caster<?> caster) { protected Stream<Entity> getTargets(Caster<?> caster) {
return Stream.concat(Stream.of(caster.asEntity()), caster.findAllEntitiesInRange(getEffectRange(getTraits())).sorted((a, b) -> { return Stream.concat(Stream.of(caster.asEntity()), caster.findAllEntitiesInRange(RANGE.get(getTraits())).sorted((a, b) -> {
return Integer.compare( return Integer.compare(
FriendshipBraceletItem.isComrade(caster, a) ? 1 : 0, FriendshipBraceletItem.isComrade(caster, a) ? 1 : 0,
FriendshipBraceletItem.isComrade(caster, b) ? 1 : 0 FriendshipBraceletItem.isComrade(caster, b) ? 1 : 0
); );
}).distinct()).limit(getMaxTargets(getTraits())); }).distinct()).limit(SIMULTANIOUS_TARGETS.get(getTraits()));
} }
@Override @Override

View file

@ -4,9 +4,9 @@ import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell; import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.AttributeFormat;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute; import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -36,12 +36,12 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell,
.with(Trait.FIRE, 60) .with(Trait.FIRE, 60)
.build(); .build();
private static final SpellAttribute<Float> VELOCITY = SpellAttribute.create(SpellAttributes.VELOCITY, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> 1.3F + (strength / 11F)); private static final SpellAttribute<Float> VELOCITY = SpellAttribute.create(SpellAttributeType.VELOCITY, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.STRENGTH, strength -> 1.3F + (strength / 11F));
private static final SpellAttribute<Integer> PROJECTILE_COUNT = SpellAttribute.create(SpellAttributes.PROJECTILE_COUNT, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.EARTH, earth -> 11 + (int)earth * 3); private static final SpellAttribute<Integer> PROJECTILE_COUNT = SpellAttribute.create(SpellAttributeType.PROJECTILE_COUNT, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.EARTH, earth -> 11 + (int)earth * 3);
private static final SpellAttribute<Boolean> FOLLOWS_TARGET = SpellAttribute.createConditional(SpellAttributes.FOLLOWS_TARGET, Trait.FOCUS, focus -> focus >= 50); private static final SpellAttribute<Boolean> FOLLOWS_TARGET = SpellAttribute.createConditional(SpellAttributeType.FOLLOWS_TARGET, Trait.FOCUS, focus -> focus >= 50);
private static final SpellAttribute<Float> FOLLOW_RANGE = SpellAttribute.create(SpellAttributes.FOLLOW_RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> Math.max(0F, focus - 49)); private static final SpellAttribute<Float> FOLLOW_RANGE = SpellAttribute.create(SpellAttributeType.FOLLOW_RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> Math.max(0F, focus - 49));
private static final SpellAttribute<Float> MAX_EXPLOSION_STRENGTH = SpellAttribute.create(SpellAttributes.EXPLOSION_STRENGTH, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> focus >= 50 ? 10F : 1F); private static final SpellAttribute<Float> MAX_EXPLOSION_STRENGTH = SpellAttribute.create(SpellAttributeType.EXPLOSION_STRENGTH, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.FOCUS, focus -> focus >= 50 ? 10F : 1F);
private static final SpellAttribute<Float> 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))); private static final SpellAttribute<Float> EXPLOSION_STRENGTH = SpellAttribute.create(SpellAttributeType.EXPLOSION_STRENGTH, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, (traits, focus) -> MathHelper.clamp(focus / 50, 0, MAX_EXPLOSION_STRENGTH.get(traits)));
static final TooltipFactory TOOLTIP = TooltipFactory.of(MAX_EXPLOSION_STRENGTH, EXPLOSION_STRENGTH, VELOCITY, PROJECTILE_COUNT, FOLLOWS_TARGET, FOLLOW_RANGE.conditionally(FOLLOWS_TARGET::get)); static final TooltipFactory TOOLTIP = TooltipFactory.of(MAX_EXPLOSION_STRENGTH, EXPLOSION_STRENGTH, VELOCITY, PROJECTILE_COUNT, FOLLOWS_TARGET, FOLLOW_RANGE.conditionally(FOLLOWS_TARGET::get));

View file

@ -5,9 +5,9 @@ import java.util.List;
import com.minelittlepony.unicopia.Owned; import com.minelittlepony.unicopia.Owned;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.AttributeFormat;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute; import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -36,7 +36,7 @@ public class IceSpell extends AbstractSpell {
.with(Trait.ICE, 15) .with(Trait.ICE, 15)
.build(); .build();
private static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 3 + power)); private static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 3 + power));
static final TooltipFactory TOOLTIP = RANGE; static final TooltipFactory TOOLTIP = RANGE;

View file

@ -6,10 +6,10 @@ import java.util.List;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.TimedSpell;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.AttributeFormat; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -34,7 +34,7 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD
.with(Trait.ORDER, 25) .with(Trait.ORDER, 25)
.build(); .build();
private static final SpellAttribute<Integer> ORB_COUNT = SpellAttribute.create(SpellAttributes.ORB_COUNT, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.LIFE, life -> 2 + (int)(MathHelper.clamp(life, 10, 20) / 10F)); private static final SpellAttribute<Integer> ORB_COUNT = SpellAttribute.create(SpellAttributeType.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); static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, ORB_COUNT);

View file

@ -8,9 +8,9 @@ import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell; import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; 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.AttributeFormat;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute; import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.Creature;
@ -83,7 +83,7 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti
return e -> e.getType() == type; return e -> e.getType() == type;
} }
static final SpellAttribute<Integer> WAVE_SIZE = SpellAttribute.create(SpellAttributes.WAVE_SIZE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.CHAOS, chaos -> 10 + (int)MathHelper.clamp(chaos, 0, 10)); static final SpellAttribute<Integer> WAVE_SIZE = SpellAttribute.create(SpellAttributeType.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); static final TooltipFactory TOOLTIP = TooltipFactory.of(RANGE, WAVE_SIZE);
private final List<EntityReference<LivingEntity>> summonedEntities = new ArrayList<>(); private final List<EntityReference<LivingEntity>> summonedEntities = new ArrayList<>();

View file

@ -9,10 +9,10 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.Spell; 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.AttributeFormat;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.CastOn; 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.SpellAttribute;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.SpellAttributeType;
import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; 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.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -51,13 +51,13 @@ public class ShieldSpell extends AbstractSpell {
.with(Trait.AIR, 9) .with(Trait.AIR, 9)
.build(); .build();
static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributes.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power)); static final SpellAttribute<Float> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power));
protected static final SpellAttribute<CastOn> CAST_ON = SpellAttribute.createEnumerated(SpellAttributes.CAST_ON, Trait.GENEROSITY, generosity -> generosity > 0 ? CastOn.LOCATION : CastOn.SELF); protected static final SpellAttribute<CastOn> CAST_ON = SpellAttribute.createEnumerated(SpellAttributeType.CAST_ON, Trait.GENEROSITY, generosity -> generosity > 0 ? CastOn.LOCATION : CastOn.SELF);
static final SpellAttribute<Boolean> TARGET_ITEMS = SpellAttribute.createConditional(SpellAttributes.PERMIT_ITEMS, Trait.KNOWLEDGE, knowledge -> knowledge > 10); static final SpellAttribute<Boolean> TARGET_ITEMS = SpellAttribute.createConditional(SpellAttributeType.PERMIT_ITEMS, Trait.KNOWLEDGE, knowledge -> knowledge > 10);
static final SpellAttribute<Boolean> PERMIT_PASSIVE = SpellAttribute.createConditional(SpellAttributes.PERMIT_PASSIVE, Trait.LIFE, l -> l > 0); static final SpellAttribute<Boolean> PERMIT_PASSIVE = SpellAttribute.createConditional(SpellAttributeType.PERMIT_PASSIVE, Trait.LIFE, l -> l > 0);
static final SpellAttribute<Boolean> PERMIT_HOSTILE = SpellAttribute.createConditional(SpellAttributes.PERMIT_HOSTILE, Trait.BLOOD, l -> l > 0); static final SpellAttribute<Boolean> PERMIT_HOSTILE = SpellAttribute.createConditional(SpellAttributeType.PERMIT_HOSTILE, Trait.BLOOD, l -> l > 0);
static final SpellAttribute<Boolean> PERMIT_PLAYER = SpellAttribute.createConditional(SpellAttributes.PERMIT_PLAYER, Trait.ICE, l -> l > 0); static final SpellAttribute<Boolean> PERMIT_PLAYER = SpellAttribute.createConditional(SpellAttributeType.PERMIT_PLAYER, Trait.ICE, l -> l > 0);
static final TooltipFactory PERMIT_ENTITY = TooltipFactory.of(PERMIT_PASSIVE, PERMIT_HOSTILE, PERMIT_PLAYER); 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 TARGET = (type, tooltip) -> (TARGET_ITEMS.get(type.traits()) ? TARGET_ITEMS : PERMIT_ENTITY).appendTooltip(type, tooltip);

View file

@ -1,7 +1,5 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect; package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.List;
import java.util.function.BiConsumer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
@ -69,7 +67,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
public static final SpellType<DisperseIllusionSpell> REVEALING = register("reveal", builder(DisperseIllusionSpell::new).color(0xFFFFAF).shape(GemstoneItem.Shape.CROSS).tooltip(DisperseIllusionSpell.TOOLTIP)); public static final SpellType<DisperseIllusionSpell> REVEALING = register("reveal", builder(DisperseIllusionSpell::new).color(0xFFFFAF).shape(GemstoneItem.Shape.CROSS).tooltip(DisperseIllusionSpell.TOOLTIP));
public static final SpellType<AwkwardSpell> AWKWARD = register("awkward", builder(AwkwardSpell::new).affinity(Affinity.NEUTRAL).color(0x3A59FF).shape(GemstoneItem.Shape.ICE)); 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<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<FeatherFallSpell> FEATHER_FALL = register("feather_fall", builder(FeatherFallSpell::new).color(0x00EEFF).shape(GemstoneItem.Shape.LAMBDA).traits(FeatherFallSpell.DEFAULT_TRAITS).tooltip(FeatherFallSpell.TOOLTIP));
public static final SpellType<CatapultSpell> CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell.TOOLTIP)); public static final SpellType<CatapultSpell> CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell.TOOLTIP));
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.TOOLTIP)); 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.TOOLTIP));
public static final SpellType<LightSpell> LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell.TOOLTIP)); public static final SpellType<LightSpell> LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell.TOOLTIP));
@ -100,9 +98,9 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
private final ItemStack defaultStack; private final ItemStack defaultStack;
private final BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction; private final TooltipFactory tooltipFunction;
private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction, Factory<T> factory) { private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, boolean stackable, GemstoneItem.Shape shape, SpellTraits traits, TooltipFactory tooltipFunction, Factory<T> factory) {
this.id = id; this.id = id;
this.affinity = affinity; this.affinity = affinity;
this.color = color; this.color = color;
@ -175,7 +173,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
return factory; return factory;
} }
public BiConsumer<CustomisedSpellType<T>, List<Text>> getTooltip() { public TooltipFactory getTooltip() {
return tooltipFunction; return tooltipFunction;
} }
@ -240,7 +238,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
private boolean stackable = false; private boolean stackable = false;
private GemstoneItem.Shape shape = GemstoneItem.Shape.ROUND; private GemstoneItem.Shape shape = GemstoneItem.Shape.ROUND;
private SpellTraits traits = SpellTraits.EMPTY; private SpellTraits traits = SpellTraits.EMPTY;
private BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction = (t, l) -> {}; private TooltipFactory tooltipFunction = TooltipFactory.EMPTY;
Builder(Factory<T> factory) { Builder(Factory<T> factory) {
this.factory = factory; this.factory = factory;
@ -277,12 +275,6 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
} }
public Builder<T> tooltip(TooltipFactory tooltipFunction) { public Builder<T> tooltip(TooltipFactory tooltipFunction) {
this.tooltipFunction = tooltipFunction::appendTooltip;
return this;
}
@Deprecated
public Builder<T> tooltip(BiConsumer<CustomisedSpellType<T>, List<Text>> tooltipFunction) {
this.tooltipFunction = tooltipFunction; this.tooltipFunction = tooltipFunction;
return this; return this;
} }

View file

@ -587,8 +587,8 @@
"spell_attribute.unicopia.added_trait.plus": " + %s x%s", "spell_attribute.unicopia.added_trait.plus": " + %s x%s",
"spell_attribute.unicopia.added_trait.take": " - %s x%s", "spell_attribute.unicopia.added_trait.take": " - %s x%s",
"spell_attribute.unicopia.added_trait.unknown": "Undiscovered Trait", "spell_attribute.unicopia.added_trait.unknown": "Undiscovered Trait",
"spell_attribute.unicopia.cast_on_location": "Applies to location", "spell_attribute.unicopia.cast_on.location": "Applies to location",
"spell_attribute.unicopia.cast_on_person": "Applies to self", "spell_attribute.unicopia.cast_on.self": "Applies to self",
"spell_attribute.unicopia.focused_entity": "Applies to focused entity", "spell_attribute.unicopia.focused_entity": "Applies to focused entity",
"spell_attribute.unicopia.affects.both": "Affects blocks and entities", "spell_attribute.unicopia.affects.both": "Affects blocks and entities",
"spell_attribute.unicopia.affects.entities": "Affects only entities", "spell_attribute.unicopia.affects.entities": "Affects only entities",
@ -615,10 +615,12 @@
"spell_attribute.unicopia.explosion_strength": "Blast Strength", "spell_attribute.unicopia.explosion_strength": "Blast Strength",
"spell_attribute.unicopia.projectile_count": "Projectile Count", "spell_attribute.unicopia.projectile_count": "Projectile Count",
"spell_attribute.unicopia.follow_range": "Following Range", "spell_attribute.unicopia.follow_range": "Following Range",
"spell_attribute.unicopia.stick_to_target": "Attaches to Target",
"spell_attribute.unicopia.orb_count": "Orb Count", "spell_attribute.unicopia.orb_count": "Orb Count",
"spell_attribute.unicopia.wave_size": "Wave Size", "spell_attribute.unicopia.wave_size": "Wave Size",
"spell_attribute.unicopia.target_preference": "Target Preference", "spell_attribute.unicopia.target_preference": "Target Preference",
"spell_attribute.unicopia.caster_preference": "Caster Preference", "spell_attribute.unicopia.caster_preference": "Caster Preference",
"spell_attribute.unicopia.negates_fall_damage": "Negates Fall Damage",
"trait.unicopia.strength.name": "Strength", "trait.unicopia.strength.name": "Strength",
"trait.unicopia.strength.description": "Imparts physical strength or enhances endurance.\nSpells with more of the strength trait hit harder and last longer.", "trait.unicopia.strength.description": "Imparts physical strength or enhances endurance.\nSpells with more of the strength trait hit harder and last longer.",