diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java index 304eb5b5..6adb2b04 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java @@ -17,6 +17,13 @@ public interface SpellPredicate extends Predicate { SpellPredicate IS_DISGUISE = s -> s instanceof AbstractDisguiseSpell; SpellPredicate IS_SHIELD_LIKE = spell -> spell instanceof ShieldSpell; + default SpellPredicate and(SpellPredicate predicate) { + SpellPredicate self = this; + return s -> { + return self.test(s) && predicate.test(s); + }; + } + default boolean isOn(Caster caster) { return caster.getSpellSlot().contains(this); } 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 new file mode 100644 index 00000000..d4d1c19d --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractionUtils.java @@ -0,0 +1,62 @@ +package com.minelittlepony.unicopia.ability.magic.spell.effect; + +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.item.enchantment.UEnchantments; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +public interface AttractionUtils { + + static double getAttractiveForce(double wellMass, Vec3d wellPosition, Entity target) { + return (wellMass * AttractionUtils.getMass(target)) / MathHelper.square(wellPosition.distanceTo(target.getPos())); + } + + static double getMass(Entity entity) { + return entity.getWidth() * entity.getHeight(); + } + + /** + * Applies a force to the given entity relative to a given center position + */ + static void applyForce(Vec3d center, Entity target, double force, double yChange, boolean clampVelocity) { + if (clampVelocity) { + target.setVelocity(target.getVelocity().multiply(Math.min(1, 1 - force))); + } + center = target.getPos().subtract(center).normalize().multiply(force); + + if (target instanceof LivingEntity) { + center = center.multiply(1 / (1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)target))); + } + + target.addVelocity( + center.x, + center.y + yChange, + center.z + ); + } + + /** + * Returns a force to apply based on the given player's given race. + */ + static double getForceAdjustment(Entity entity) { + return Pony.of(entity).map(pony -> { + double force = 0.75; + + if (pony.getSpecies().canUseEarth()) { + force /= 2; + + if (pony.getMaster().isSneaking()) { + force /= 6; + } + } else if (pony.getSpecies().canFly()) { + force *= 2; + } + + return force; + }).orElse(1D); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java index 3bc9df49..82f16e0e 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java @@ -4,7 +4,6 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; -import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.UParticles; @@ -13,7 +12,6 @@ import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -53,15 +51,15 @@ public class AttractiveSpell extends ShieldSpell implements ProjectileSpell { boolean isGood = isFriendlyTogether(source); - if (isGood && target instanceof PlayerEntity) { - force *= calculateAdjustedForce(Pony.of((PlayerEntity)target)); + if (isGood) { + force *= AttractionUtils.getForceAdjustment(target); } if (!isGood && source.getWorld().random.nextInt(4500) == 0) { source.getEntity().damage(MagicalDamageSource.create("vortex"), 4); } - applyForce(getOrigin(source), target, -force, 0); + AttractionUtils.applyForce(getOrigin(source), target, -force, 0, false); float maxVel = !isFriendlyTogether(source) ? 1 : 1.6f; 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 bdfaa35c..99bdf55b 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 @@ -189,7 +189,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell } private double getAttractiveForce(Caster source, Entity target) { - return (getMass() * getMass(target)) / Math.pow(getOrigin(source).distanceTo(target.getPos()), 2); + return AttractionUtils.getAttractiveForce(getMass(), getOrigin(source), target); } private double getMass() { @@ -197,10 +197,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse; } - private double getMass(Entity entity) { - return entity.getWidth() * entity.getHeight(); - } - @Override protected void applyRadialEffect(Caster source, Entity target, double distance, double radius) { @@ -227,20 +223,21 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell return; } - accumulatedMass += getMass(target); + double massOfTarget = AttractionUtils.getMass(target); + + accumulatedMass += massOfTarget; setDirty(); target.damage(MagicalDamageSource.create("black_hole"), Integer.MAX_VALUE); if (!(target instanceof PlayerEntity)) { target.discard(); } - source.subtractEnergyCost(-getMass(target) * 10); + source.subtractEnergyCost(-massOfTarget * 10); source.getWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F); } else { double force = getAttractiveForce(source, target); - target.setVelocity(target.getVelocity().multiply(Math.min(1, 1 - force))); - applyForce(getOrigin(source), target, -force, 0); + AttractionUtils.applyForce(getOrigin(source), target, -force, 0, true); source.subtractEnergyCost(-2); } 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 700f3f7e..f056c5cd 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 @@ -7,8 +7,6 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; -import com.minelittlepony.unicopia.entity.player.Pony; -import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.ParticleHandle; import com.minelittlepony.unicopia.particle.SphereParticleEffect; @@ -16,7 +14,6 @@ import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.util.shape.Sphere; -import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EyeOfEnderEntity; import net.minecraft.entity.FallingBlockEntity; @@ -24,7 +21,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.TntEntity; import net.minecraft.entity.Entity.RemovalReason; import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.vehicle.AbstractMinecartEntity; import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.util.math.Vec3d; @@ -160,50 +156,13 @@ public class ShieldSpell extends AbstractSpell { } else if (target instanceof LivingEntity) { double force = Math.max(0.1, radius / 4); - if (isFriendlyTogether(source) && target instanceof PlayerEntity) { - force *= calculateAdjustedForce(Pony.of((PlayerEntity)target)); + if (isFriendlyTogether(source)) { + force *= AttractionUtils.getForceAdjustment(target); } else { force *= 0.75; } - applyForce(pos, target, force, distance); + AttractionUtils.applyForce(pos, target, force, (distance < 1 ? distance : 0), false); } } - - /** - * Applies a force to the given entity based on distance from the source. - */ - protected void applyForce(Vec3d pos, Entity target, double force, double distance) { - pos = target.getPos().subtract(pos).normalize().multiply(force); - - if (target instanceof LivingEntity) { - pos = pos.multiply(1 / (1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)target))); - } - - target.addVelocity( - pos.x, - pos.y + (distance < 1 ? distance : 0), - pos.z - ); - } - - /** - * Returns a force to apply based on the given player's given race. - */ - protected double calculateAdjustedForce(Pony player) { - double force = 0.75; - - if (player.getSpecies().canUseEarth()) { - force /= 2; - - if (player.getMaster().isSneaking()) { - force /= 6; - } - } else if (player.getSpecies().canFly()) { - force *= 2; - } - - return force; - } - } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java index 55c29d05..b036bbc4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java @@ -62,6 +62,10 @@ public class EntityReference implements NbtSerialisable { return pos; } + public boolean referenceEquals(Entity entity) { + return entity != null && entity.getUuid().equals(uuid.orElse(null)); + } + public boolean isPresent(World world) { return getOrEmpty(world).isPresent(); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 7ecc9658..362d47a4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -598,6 +598,10 @@ public class Pony extends Living implements Transmittable, Copieab return player == null ? null : ((PonyContainer)player).get(); } + public static Optional of(Entity entity) { + return entity instanceof PlayerEntity ? PonyContainer.of(entity).map(a -> (Pony)a.get()) : Optional.empty(); + } + public static boolean equal(GameProfile one, GameProfile two) { return one == two || (one != null && two != null && one.getId().equals(two.getId())); }