Move various gravitation/force/physics stuff to a utility class

This commit is contained in:
Sollace 2022-02-23 20:03:14 +02:00
parent ca7ff47451
commit ddbf75a44f
7 changed files with 89 additions and 58 deletions

View file

@ -17,6 +17,13 @@ public interface SpellPredicate<T extends Spell> extends Predicate<Spell> {
SpellPredicate<AbstractDisguiseSpell> IS_DISGUISE = s -> s instanceof AbstractDisguiseSpell;
SpellPredicate<ShieldSpell> IS_SHIELD_LIKE = spell -> spell instanceof ShieldSpell;
default SpellPredicate<T> and(SpellPredicate<T> predicate) {
SpellPredicate<T> self = this;
return s -> {
return self.test(s) && predicate.test(s);
};
}
default boolean isOn(Caster<?> caster) {
return caster.getSpellSlot().contains(this);
}

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -62,6 +62,10 @@ public class EntityReference<T extends Entity> 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();
}

View file

@ -598,6 +598,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
return player == null ? null : ((PonyContainer<Pony>)player).get();
}
public static Optional<Pony> 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()));
}