mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 07:17:58 +01:00
Configure spell attributes for all the spell types
This commit is contained in:
parent
aaea2bfbc1
commit
92d2bc229f
23 changed files with 233 additions and 238 deletions
|
@ -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<Text> tooltip) {
|
||||
float addedRange = type.traits().get(Trait.POWER);
|
||||
if (addedRange != 0) {
|
||||
tooltip.add(SpellAttributes.ofRelative(SpellAttributes.RANGE, addedRange));
|
||||
}
|
||||
}
|
||||
protected static final SpellAttribute<Float> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<Integer> 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<Text> 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;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.attribute;
|
||||
|
||||
public enum CastOn {
|
||||
LOCATION,
|
||||
SELF
|
||||
}
|
|
@ -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<T> (
|
||||
Trait trait,
|
||||
Float2ObjectFunction<T> valueGetter,
|
||||
BiFunction<SpellTraits, Float, T> valueGetter,
|
||||
TooltipFactory tooltipFactory
|
||||
) implements TooltipFactory {
|
||||
@Override
|
||||
|
@ -27,7 +28,11 @@ public record SpellAttribute<T> (
|
|||
}
|
||||
|
||||
public T get(SpellTraits traits) {
|
||||
return valueGetter.get(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) {
|
||||
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) {
|
||||
|
@ -38,16 +43,24 @@ public record SpellAttribute<T> (
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
Text name = Text.translatable(Util.createTranslationKey("spell_attribute", id));
|
||||
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
|
||||
float traitAmount = type.traits().get(trait);
|
||||
float traitDifference = type.relativeTraits().get(trait);
|
||||
float value = valueGetter.get(traitAmount).floatValue();
|
||||
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<T> (
|
|||
}
|
||||
|
||||
public static SpellAttribute<Boolean> createConditional(Identifier id, Trait trait, Float2ObjectFunction<Boolean> valueGetter) {
|
||||
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) {
|
||||
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
|
||||
Text name = Text.translatable(Util.createTranslationKey("spell_attribute", id));
|
||||
float difference = type.relativeTraits().get(trait);
|
||||
Text value = AttributeFormat.formatAttributeLine(name);
|
||||
if (!valueGetter.get(type.traits().get(trait))) {
|
||||
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<T> (
|
|||
}
|
||||
|
||||
public static <T extends Enum<T>> SpellAttribute<T> createEnumerated(Identifier id, Trait trait, Float2ObjectFunction<T> valueGetter) {
|
||||
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) {
|
||||
Function<T, Text> cache = Util.memoize(t -> Text.translatable(Util.createTranslationKey("spell_attribute", id.withPath(id.getPath() + "." + t.name().toLowerCase(Locale.ROOT)))));
|
||||
return new SpellAttribute<>(trait, valueGetter, (CustomisedSpellType<?> type, List<Text> tooltip) -> {
|
||||
T t = valueGetter.get(type.traits().get(trait));
|
||||
T t = valueGetter.apply(type.traits(), type.traits().get(trait));
|
||||
|
||||
if (t != null) {
|
||||
int max = t.getClass().getEnumConstants().length;
|
||||
|
|
|
@ -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<SpellTraits> condition) {
|
||||
TooltipFactory self = this;
|
||||
return (type, tooltip) -> {
|
||||
if (condition.test(type.traits())) {
|
||||
self.appendTooltip(type, tooltip);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<AreaProtectionSpell> type, List<Text> 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);
|
||||
|
|
|
@ -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<Boolean> TARGET_FOCUSED_ENTITY = SpellAttribute.createConditional(SpellAttributes.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 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<Entity> target = new EntityReference<>();
|
||||
|
||||
private final Timer timer;
|
||||
|
||||
public static void appendTooltip2(CustomisedSpellType<AttractiveSpell> type, List<Text> 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));
|
||||
}
|
||||
|
|
|
@ -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<? extends BubbleSpell> type, List<Text> tooltip) {
|
||||
TimedSpell.appendDurationTooltip(type, tooltip);
|
||||
tooltip.add(SpellAttributes.of(SpellAttributes.SOAPINESS, (int)(type.traits().get(Trait.POWER) * 2)));
|
||||
}
|
||||
private static final SpellAttribute<Integer> 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
|
||||
|
|
|
@ -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<? extends DispellEvilSpell> type, List<Text> tooltip) {
|
||||
tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, (1 + type.relativeTraits().get(Trait.POWER)) * 10));
|
||||
}
|
||||
private static final SpellAttribute<Double> 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();
|
||||
|
|
|
@ -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<? extends DisperseIllusionSpell> type, List<Text> 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<Float> RANGE = SpellAttribute.create(SpellAttributes.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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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<? extends DisplacementSpell> type, List<Text> tooltip) {
|
||||
float damage = type.traits().get(Trait.BLOOD);
|
||||
if (damage > 0) {
|
||||
tooltip.add(SpellAttributes.ofRelative(SpellAttributes.DAMAGE_TO_TARGET, damage));
|
||||
}
|
||||
}
|
||||
private static final SpellAttribute<Float> 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<Entity> 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);
|
||||
}
|
||||
|
|
|
@ -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<? extends FireBoltSpell> type, List<Text> 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<Float> VELOCITY = SpellAttribute.create(SpellAttributes.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<Boolean> FOLLOWS_TARGET = SpellAttribute.createConditional(SpellAttributes.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> MAX_EXPLOSION_STRENGTH = SpellAttribute.create(SpellAttributes.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)));
|
||||
|
||||
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<Entity> 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;
|
||||
}
|
||||
|
|
|
@ -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<? extends FireSpell> type, List<Text> 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)
|
||||
|
|
|
@ -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<? extends HydrophobicSpell> type, List<Text> 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<Fluid> 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;
|
||||
|
|
|
@ -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<Float> 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);
|
||||
|
|
|
@ -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<? extends LightSpell> type, List<Text> 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<Integer> 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<>());
|
||||
}
|
||||
|
|
|
@ -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<? extends MimicSpell> type, List<Text> 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
|
||||
|
|
|
@ -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<? extends NecromancySpell> type, List<Text> 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<Integer> 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<EntityReference<LivingEntity>> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<? extends ShieldSpell> type, List<Text> tooltip) {
|
||||
AbstractAreaEffectSpell.appendRangeTooltip(type, tooltip);
|
||||
appendValidTargetsTooltip(type, tooltip);
|
||||
appendCastLocationTooltip(type, tooltip);
|
||||
}
|
||||
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<CastOn> CAST_ON = SpellAttribute.createEnumerated(SpellAttributes.CAST_ON, Trait.GENEROSITY, generosity -> generosity > 0 ? CastOn.LOCATION : CastOn.SELF);
|
||||
|
||||
static void appendValidTargetsTooltip(CustomisedSpellType<? extends ShieldSpell> type, List<Text> 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<Boolean> TARGET_ITEMS = SpellAttribute.createConditional(SpellAttributes.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_HOSTILE = SpellAttribute.createConditional(SpellAttributes.PERMIT_HOSTILE, Trait.BLOOD, l -> l > 0);
|
||||
static final SpellAttribute<Boolean> PERMIT_PLAYER = SpellAttribute.createConditional(SpellAttributes.PERMIT_PLAYER, Trait.ICE, l -> l > 0);
|
||||
|
||||
static void appendCastLocationTooltip(CustomisedSpellType<?> type, List<Text> 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;
|
||||
|
|
|
@ -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<Entity> TARGET_PREDICATE = EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_LIVING_ENTITY);
|
||||
|
||||
static void appendTooltip(CustomisedSpellType<? extends SiphoningSpell> type, List<Text> tooltip) {
|
||||
tooltip.add(SpellAttributes.of(SpellAttributes.RANGE, 4));
|
||||
}
|
||||
|
||||
private final DataTracker.Entry<Boolean> 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 -> {
|
||||
|
|
|
@ -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<T extends Spell> implements Affine, SpellPredicate<
|
|||
public static final SpellType<RageAbilitySpell> RAGE = register("rage", builder(RageAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.FLAME));
|
||||
public static final SpellType<TimeControlAbilitySpell> TIME_CONTROL = register("time_control", builder(TimeControlAbilitySpell::new).color(0xBDBDF9).unobtainable().shape(GemstoneItem.Shape.STAR));
|
||||
|
||||
public static final SpellType<IceSpell> FROST = register("frost", builder(IceSpell::new).color(0xEABBFF).shape(GemstoneItem.Shape.TRIANGLE).traits(IceSpell.DEFAULT_TRAITS));
|
||||
public static final SpellType<IceSpell> FROST = register("frost", builder(IceSpell::new).color(0xEABBFF).shape(GemstoneItem.Shape.TRIANGLE).traits(IceSpell.DEFAULT_TRAITS).tooltip(IceSpell.TOOLTIP));
|
||||
public static final SpellType<ChillingBreathSpell> 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<ScorchSpell> 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<FireSpell> FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS).tooltip(FireSpell::appendTooltip));
|
||||
public static final SpellType<InfernoSpell> 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<ShieldSpell> SHIELD = register("shield", builder(ShieldSpell::new).affinity(Affinity.NEUTRAL).color(0x66CDAA).shape(GemstoneItem.Shape.SHIELD).traits(ShieldSpell.DEFAULT_TRAITS).tooltip(ShieldSpell::appendTooltip));
|
||||
public static final SpellType<AreaProtectionSpell> ARCANE_PROTECTION = register("arcane_protection", builder(AreaProtectionSpell::new).affinity(Affinity.BAD).color(0x99CDAA).shape(GemstoneItem.Shape.SHIELD).traits(AreaProtectionSpell.DEFAULT_TRAITS).tooltip(AreaProtectionSpell::appendTooltip));
|
||||
public static final SpellType<AttractiveSpell> 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<ScorchSpell> 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<FireSpell> FLAME = register("flame", builder(FireSpell::new).color(0xFFBB99).shape(GemstoneItem.Shape.FLAME).traits(FireSpell.DEFAULT_TRAITS).tooltip(AbstractAreaEffectSpell.TOOLTIP));
|
||||
public static final SpellType<InfernoSpell> 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<ShieldSpell> 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<AreaProtectionSpell> 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<AttractiveSpell> 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<DarkVortexSpell> DARK_VORTEX = register("dark_vortex", builder(DarkVortexSpell::new).affinity(Affinity.BAD).color(0xA33333).stackable().shape(GemstoneItem.Shape.VORTEX).traits(DarkVortexSpell.DEFAULT_TRAITS));
|
||||
public static final SpellType<NecromancySpell> NECROMANCY = register("necromancy", builder(NecromancySpell::new).affinity(Affinity.BAD).color(0xFA3A3A).shape(GemstoneItem.Shape.SKULL).tooltip(NecromancySpell::appendTooltip));
|
||||
public static final SpellType<SiphoningSpell> SIPHONING = register("siphoning", builder(SiphoningSpell::new).affinity(Affinity.NEUTRAL).color(0xFFA3AA).shape(GemstoneItem.Shape.LAMBDA).tooltip(SiphoningSpell::appendTooltip));
|
||||
public static final SpellType<DisperseIllusionSpell> REVEALING = register("reveal", builder(DisperseIllusionSpell::new).color(0xFFFFAF).shape(GemstoneItem.Shape.CROSS).tooltip(DisperseIllusionSpell::appendTooltip));
|
||||
public static final SpellType<NecromancySpell> NECROMANCY = register("necromancy", builder(NecromancySpell::new).affinity(Affinity.BAD).color(0xFA3A3A).shape(GemstoneItem.Shape.SKULL).tooltip(NecromancySpell.TOOLTIP));
|
||||
public static final SpellType<SiphoningSpell> SIPHONING = register("siphoning", builder(SiphoningSpell::new).affinity(Affinity.NEUTRAL).color(0xFFA3AA).shape(GemstoneItem.Shape.LAMBDA).tooltip(AbstractAreaEffectSpell.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<TransformationSpell> TRANSFORMATION = register("transformation", builder(TransformationSpell::new).color(0x19E48E).shape(GemstoneItem.Shape.BRUSH));
|
||||
public static final SpellType<FeatherFallSpell> FEATHER_FALL = register("feather_fall", builder(FeatherFallSpell::new).color(0x00EEFF).shape(GemstoneItem.Shape.LAMBDA).traits(FeatherFallSpell.DEFAULT_TRAITS).tooltip(FeatherFallSpell::appendTooltip));
|
||||
public static final SpellType<CatapultSpell> CATAPULT = register("catapult", builder(CatapultSpell::new).color(0x22FF00).shape(GemstoneItem.Shape.ROCKET).traits(CatapultSpell.DEFAULT_TRAITS).tooltip(CatapultSpell.TOOLTIP::appendTooltip));
|
||||
public static final SpellType<FireBoltSpell> FIRE_BOLT = register("fire_bolt", builder(FireBoltSpell::new).color(0xFF8811).shape(GemstoneItem.Shape.FLAME).traits(FireBoltSpell.DEFAULT_TRAITS).tooltip(FireBoltSpell::appendTooltip));
|
||||
public static final SpellType<LightSpell> LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell::appendTooltip));
|
||||
public static final SpellType<DisplacementSpell> DISPLACEMENT = register("displacement", builder(DisplacementSpell::new).affinity(Affinity.NEUTRAL).color(0x9900FF).stackable().shape(GemstoneItem.Shape.BRUSH).traits(PortalSpell.DEFAULT_TRAITS).tooltip(DisplacementSpell::appendTooltip));
|
||||
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<LightSpell> LIGHT = register("light", builder(LightSpell::new).color(0xEEFFAA).shape(GemstoneItem.Shape.STAR).traits(LightSpell.DEFAULT_TRAITS).tooltip(LightSpell.TOOLTIP));
|
||||
public static final SpellType<DisplacementSpell> DISPLACEMENT = register("displacement", builder(DisplacementSpell::new).affinity(Affinity.NEUTRAL).color(0x9900FF).stackable().shape(GemstoneItem.Shape.BRUSH).traits(PortalSpell.DEFAULT_TRAITS).tooltip(DisplacementSpell.TOOLTIP));
|
||||
public static final SpellType<PortalSpell> PORTAL = register("portal", builder(PortalSpell::new).color(0x99FFFF).shape(GemstoneItem.Shape.RING).traits(PortalSpell.DEFAULT_TRAITS));
|
||||
public static final SpellType<MimicSpell> MIMIC = register("mimic", builder(MimicSpell::new).color(0xFFFF00).shape(GemstoneItem.Shape.ARROW).tooltip(MimicSpell::appendTooltip));
|
||||
public static final SpellType<MindSwapSpell> MIND_SWAP = register("mind_swap", builder(MindSwapSpell::new).affinity(Affinity.BAD).color(0xF9FF99).shape(GemstoneItem.Shape.WAVE).tooltip(MimicSpell::appendTooltip));
|
||||
public static final SpellType<HydrophobicSpell> HYDROPHOBIC = register("hydrophobic", SpellType.<HydrophobicSpell>builder(s -> new HydrophobicSpell(s, FluidTags.WATER)).affinity(Affinity.NEUTRAL).color(0xF999FF).stackable().shape(GemstoneItem.Shape.ROCKET).tooltip(HydrophobicSpell::appendTooltip));
|
||||
public static final SpellType<BubbleSpell> 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<DispellEvilSpell> 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<MimicSpell> MIMIC = register("mimic", builder(MimicSpell::new).color(0xFFFF00).shape(GemstoneItem.Shape.ARROW).tooltip(MimicSpell.TOOLTIP));
|
||||
public static final SpellType<MindSwapSpell> MIND_SWAP = register("mind_swap", builder(MindSwapSpell::new).affinity(Affinity.BAD).color(0xF9FF99).shape(GemstoneItem.Shape.WAVE).tooltip(MimicSpell.TOOLTIP));
|
||||
public static final SpellType<HydrophobicSpell> HYDROPHOBIC = register("hydrophobic", SpellType.<HydrophobicSpell>builder(s -> new HydrophobicSpell(s, FluidTags.WATER)).affinity(Affinity.NEUTRAL).color(0xF999FF).stackable().shape(GemstoneItem.Shape.ROCKET).tooltip(HydrophobicSpell.TOOLTIP));
|
||||
public static final SpellType<BubbleSpell> 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<DispellEvilSpell> 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<T extends Spell> implements Affine, SpellPredicate<
|
|||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
return this;
|
||||
|
|
Loading…
Reference in a new issue