diff --git a/src/main/java/com/minelittlepony/unicopia/Owned.java b/src/main/java/com/minelittlepony/unicopia/Owned.java index 337a59ed..47c5403c 100644 --- a/src/main/java/com/minelittlepony/unicopia/Owned.java +++ b/src/main/java/com/minelittlepony/unicopia/Owned.java @@ -32,7 +32,11 @@ public interface Owned { Optional getMasterId(); default boolean isOwnerOrFriend(Entity target) { - return FriendshipBraceletItem.isComrade(this, target) || isOwnerOrVehicle(target); + return isFriend(target) || isOwnerOrVehicle(target); + } + + default boolean isFriend(Entity target) { + return FriendshipBraceletItem.isComrade(this, target); } default boolean isOwnerOrVehicle(@Nullable Entity target) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java index ed03506d..408b345d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java @@ -160,7 +160,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS private void spawnPlacedEntity(Caster source) { CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld()); - Vec3d pos = getPosition().orElse(position.orElse(source.getOriginVector())); + Vec3d pos = getPosition().orElse(position.orElse(source.asEntity().getPos())); entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.asEntity().getYaw(), source.asEntity().getPitch()); PlaceableSpell copy = spell.toPlaceable(); if (spell instanceof PlacementDelegate delegate) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractionUtils.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractionUtils.java index 248b87ca..76b2d29e 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractionUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractionUtils.java @@ -1,11 +1,15 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; +import org.jetbrains.annotations.Nullable; + import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; +import net.minecraft.block.Block; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -17,7 +21,16 @@ public interface AttractionUtils { } static double getMass(Entity entity) { - return entity.getWidth() * entity.getHeight(); + double baseMass = entity.getWidth() * entity.getHeight(); + if (entity instanceof ItemEntity item) { + baseMass *= item.getStack().getCount(); + @Nullable + Block block = Block.getBlockFromItem(item.getStack().getItem()); + if (block != null) { + baseMass *= MathHelper.clamp(1 + block.getHardness(), 1, 5); + } + } + return baseMass; } /** diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java index 02eb96d3..d21a9c3e 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java @@ -46,12 +46,11 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega .with(Trait.DARKNESS, 100) .build(); - private static final Vec3d SPHERE_OFFSET = new Vec3d(0, 2, 0); - private float accumulatedMass = 0; protected DarkVortexSpell(CustomisedSpellType type) { super(type); + targetSelecter.setTargetowner(true).setTargetAllies(true); } @Override @@ -87,7 +86,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO); } - return super.tick(source, situation); + super.tick(source, situation); + return true; } @Override @@ -134,7 +134,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega @Override protected Vec3d getOrigin(Caster source) { - return source.getOriginVector().add(SPHERE_OFFSET); + return source.getOriginVector().add(0, getEventHorizonRadius() / 2D, 0); } @Override @@ -182,7 +182,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega } private double getMass() { - return Math.min(15, 0.1F + accumulatedMass / 10F); + return 0.1F + accumulatedMass / 10F; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java index 04831ef6..5107f3d9 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java @@ -16,6 +16,7 @@ import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.projectile.ProjectileUtil; +import com.minelittlepony.unicopia.util.Lerp; import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.entity.Entity; @@ -41,13 +42,10 @@ public class ShieldSpell extends AbstractSpell { .with(Trait.AIR, 9) .build(); - private final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget); + protected final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget); - private float prevRadius; - private float radius; - - private float rangeMultiplier; - private float targetRangeMultiplier; + private final Lerp radius = new Lerp(0); + private final Lerp rangeMultiplier = new Lerp(1); private int prevTicksDying; private int ticksDying; @@ -69,7 +67,7 @@ public class ShieldSpell extends AbstractSpell { protected void generateParticles(Caster source) { Vec3d origin = getOrigin(source); - source.spawnParticles(origin, new Sphere(true, radius), (int)(radius * 6), pos -> { + source.spawnParticles(origin, new Sphere(true, radius.getValue()), (int)(radius.getValue() * 6), pos -> { source.addParticle(new MagicParticleEffect(getType().getColor()), pos, Vec3d.ZERO); if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) { @@ -80,8 +78,7 @@ public class ShieldSpell extends AbstractSpell { @Override public boolean tick(Caster source, Situation situation) { - prevRadius = radius; - radius = (float)getDrawDropOffRange(source); + radius.update((float)getDrawDropOffRange(source), 200L); if (source.isClient()) { generateParticles(source); @@ -118,7 +115,7 @@ public class ShieldSpell extends AbstractSpell { cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F); cost /= knowledge; - cost += radius / 10F; + cost += radius.getValue() / 10F; if (!source.subtractEnergyCost(cost)) { setDead(); @@ -126,8 +123,8 @@ public class ShieldSpell extends AbstractSpell { } public float getRadius(float tickDelta) { - float base = MathHelper.lerp(tickDelta, prevRadius, radius); - float scale = MathHelper.clamp(MathHelper.lerp(tickDelta, prevTicksDying, ticksDying), 0, 1); + float base = radius.getValue(); + float scale = 1 - MathHelper.clamp(MathHelper.lerp(tickDelta, (float)prevTicksDying, ticksDying), 0, 1); return base * scale; } @@ -135,17 +132,10 @@ public class ShieldSpell extends AbstractSpell { * Calculates the maximum radius of the shield. aka The area of effect. */ public double getDrawDropOffRange(Caster source) { - targetRangeMultiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2; - if (rangeMultiplier < targetRangeMultiplier - 0.1F) { - rangeMultiplier += 0.1F; - } else if (rangeMultiplier > targetRangeMultiplier + 0.1) { - rangeMultiplier -= 0.1F; - } else { - rangeMultiplier = targetRangeMultiplier; - } + rangeMultiplier.update(source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2, 500L); float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER); - double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier; + double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier.getValue(); return range; } @@ -175,9 +165,9 @@ public class ShieldSpell extends AbstractSpell { protected long applyEntities(Caster source) { Vec3d origin = getOrigin(source); - targetSelecter.getEntities(source, radius).forEach(i -> { + targetSelecter.getEntities(source, radius.getValue()).forEach(i -> { try { - applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius); + applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius.getValue()); } catch (Throwable e) { Unicopia.LOGGER.error("Error updating radial effect", e); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java index 87119eab..a6a3724c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java @@ -21,6 +21,9 @@ public class TargetSelecter { private BiPredicate, Entity> filter = (a, b) -> true; + private boolean targetOwner; + private boolean targetAllies; + public TargetSelecter(Spell spell) { this.spell = spell; } @@ -30,18 +33,34 @@ public class TargetSelecter { return this; } + public TargetSelecter setTargetowner(boolean targetOwner) { + this.targetOwner = targetOwner; + return this; + } + + public TargetSelecter setTargetAllies(boolean targetAllies) { + this.targetAllies = targetAllies; + return this; + } + public Stream getEntities(Caster source, double radius) { targets.values().removeIf(Target::tick); return source.findAllEntitiesInRange(radius) .filter(EntityPredicates.VALID_ENTITY) .filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE) - .filter(entity -> entity != source.asEntity() && validTarget(spell, source, entity) && filter.test(source, entity)) + .filter(entity -> entity != source.asEntity() && checkAlliegance(spell, source, entity) && filter.test(source, entity)) .map(i -> { targets.computeIfAbsent(i.getUuid(), Target::new); return i; }); } + private boolean checkAlliegance(Affine affine, Caster source, Entity target) { + boolean isOwner = !targetOwner && source.isOwnerOrVehicle(target); + boolean isFriend = !targetAllies && affine.applyInversion(source, source.isFriend(target)); + return !(isOwner || isFriend); + } + public long getTotalDamaged() { return targets.values().stream().filter(Target::canHurt).count(); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java index 2c03bc11..aec3d2d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/DarkVortexSpellRenderer.java @@ -77,7 +77,7 @@ public class DarkVortexSpellRenderer extends SpellRenderer { SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getEndPortal()), light, 1, radius * 0.5F, 1, 0.5F, 0, 1); if (radius > 0.3F && absDistance > radius) { - radius *= 3 + radius; + radius *= Math.min(2, 3 + radius); matrices.scale(radius, radius, radius); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90)); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java index 260b322c..a006f77d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/ShieldSpellRenderer.java @@ -43,9 +43,9 @@ public class ShieldSpellRenderer extends SpellRenderer { model.render(matrices, buffer, light, 1, radius, colors[0], colors[1], colors[2], alpha * 0.2F); } else { matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180)); - model.render(matrices, buffer, light, 1, radius + thickness, colors[0], colors[1], colors[2], alpha * 0.08F); - model.render(matrices, buffer, light, 1, radius - thickness, colors[0], colors[1], colors[2], alpha * 0.05F); - model.render(matrices, buffer, light, 1, radius + thickness * 2, colors[0], colors[1], colors[2], alpha * 0.05F); + SphereModel.SPHERE.render(matrices, buffer, light, 1, radius + thickness, colors[0], colors[1], colors[2], alpha * 0.08F); + SphereModel.SPHERE.render(matrices, buffer, light, 1, radius - thickness, colors[0], colors[1], colors[2], alpha * 0.05F); + SphereModel.SPHERE.render(matrices, buffer, light, 1, radius + thickness * 2, colors[0], colors[1], colors[2], alpha * 0.05F); } matrices.pop(); diff --git a/src/main/java/com/minelittlepony/unicopia/network/datasync/EffectSync.java b/src/main/java/com/minelittlepony/unicopia/network/datasync/EffectSync.java index 83507e6b..724c5660 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/datasync/EffectSync.java +++ b/src/main/java/com/minelittlepony/unicopia/network/datasync/EffectSync.java @@ -105,11 +105,15 @@ public class EffectSync implements SpellContainer, NbtSerialisable { @Override public boolean removeWhere(Predicate test, boolean update) { - return reduce(update, (initial, effect) -> { - if (!test.test(effect)) { + return reduce(update, (initial, spell) -> { + if (!test.test(spell)) { return initial; } - spells.removeReference(effect); + spell.setDead(); + spell.tickDying(owner); + if (spell.isDead()) { + spells.removeReference(spell); + } return true; }); }