mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Fixed various issues with shields
This commit is contained in:
parent
6e071b9113
commit
634ab607bf
4 changed files with 92 additions and 58 deletions
|
@ -42,6 +42,11 @@ public class Particles<Particle> {
|
||||||
return -id - 1;
|
return -id - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public void spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, Vec3d vel, int ...pars) {
|
||||||
|
spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, pars);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public void spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, double speedX, double speedY, double speedZ, int ...pars) {
|
public void spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, double speedX, double speedY, double speedZ, int ...pars) {
|
||||||
spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, speedX, speedY, speedZ, pars);
|
spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, speedX, speedY, speedZ, pars);
|
||||||
|
|
|
@ -46,6 +46,10 @@ public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelle
|
||||||
return getEntity().getPosition();
|
return getEntity().getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Vec3d getOriginVector() {
|
||||||
|
return getEntity().getPositionVector();
|
||||||
|
}
|
||||||
|
|
||||||
default void spawnParticles(IShape area, int count, Consumer<Vec3d> particleSpawner) {
|
default void spawnParticles(IShape area, int count, Consumer<Vec3d> particleSpawner) {
|
||||||
Random rand = getWorld().rand;
|
Random rand = getWorld().rand;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package com.minelittlepony.unicopia.spell;
|
package com.minelittlepony.unicopia.spell;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Predicates;
|
import com.minelittlepony.unicopia.Predicates;
|
||||||
import com.minelittlepony.unicopia.Race;
|
|
||||||
import com.minelittlepony.unicopia.UParticles;
|
import com.minelittlepony.unicopia.UParticles;
|
||||||
import com.minelittlepony.unicopia.particle.Particles;
|
import com.minelittlepony.unicopia.particle.Particles;
|
||||||
|
import com.minelittlepony.unicopia.player.IPlayer;
|
||||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||||
import com.minelittlepony.unicopia.power.IPower;
|
import com.minelittlepony.unicopia.power.IPower;
|
||||||
import com.minelittlepony.util.ProjectileUtil;
|
import com.minelittlepony.util.ProjectileUtil;
|
||||||
|
@ -14,7 +14,6 @@ import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.init.SoundEvents;
|
import net.minecraft.init.SoundEvents;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class SpellShield extends AbstractSpell {
|
public class SpellShield extends AbstractSpell {
|
||||||
|
@ -76,66 +75,87 @@ public class SpellShield extends AbstractSpell {
|
||||||
double radius = 4 + (level * 2);
|
double radius = 4 + (level * 2);
|
||||||
|
|
||||||
Entity owner = source.getOwner();
|
Entity owner = source.getOwner();
|
||||||
BlockPos pos = source.getOrigin();
|
|
||||||
|
|
||||||
int x = pos.getX(), y = pos.getY(), z = pos.getZ();
|
boolean ownerIsValid = source.getAffinity() != SpellAffinity.BAD && Predicates.MAGI.test(owner);
|
||||||
|
|
||||||
boolean ownerIsValid = Predicates.MAGI.test(owner);
|
source.findAllEntitiesInRange(radius)
|
||||||
|
.filter(entity -> !(ownerIsValid && entity.equals(owner)))
|
||||||
|
.forEach(i -> {
|
||||||
|
double dist = Math.sqrt(i.getDistanceSq(source.getOrigin()));
|
||||||
|
|
||||||
source.findAllEntitiesInRange(radius).filter(entity -> !(ownerIsValid && entity.equals(owner))).forEach(i -> {
|
applyRadialEffect(source, i, dist, radius);
|
||||||
double dist = i.getDistance(x, y, z);
|
});
|
||||||
|
|
||||||
if (ProjectileUtil.isProjectile(i)) {
|
|
||||||
if (!ProjectileUtil.isProjectileThrownBy(i, owner)) {
|
|
||||||
if (dist < radius/2) {
|
|
||||||
i.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1F, 1);
|
|
||||||
i.setDead();
|
|
||||||
} else {
|
|
||||||
ricochet(i, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (i instanceof EntityLivingBase) {
|
|
||||||
double force = Math.min(0.25F, dist);
|
|
||||||
|
|
||||||
if (i instanceof EntityPlayer) {
|
|
||||||
force = calculateForce((EntityPlayer)i);
|
|
||||||
}
|
|
||||||
|
|
||||||
i.addVelocity(
|
|
||||||
-(x - i.posX) / force,
|
|
||||||
-(y - i.posY) / force + (dist < 1 ? dist : 0),
|
|
||||||
-(z - i.posZ) / force);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double calculateForce(EntityPlayer player) {
|
protected void applyRadialEffect(ICaster<?> source, Entity target, double distance, double radius) {
|
||||||
Race race = PlayerSpeciesList.instance().getPlayer(player).getPlayerSpecies();
|
Vec3d pos = source.getOriginVector();
|
||||||
|
|
||||||
double force = 4 * 8;
|
if (ProjectileUtil.isProjectile(target)) {
|
||||||
|
if (!ProjectileUtil.isProjectileThrownBy(target, source.getOwner())) {
|
||||||
|
if (distance < radius/2) {
|
||||||
|
target.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1F, 1);
|
||||||
|
target.setDead();
|
||||||
|
} else {
|
||||||
|
ricochet(target, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (target instanceof EntityLivingBase) {
|
||||||
|
double force = Math.min(0.25F, distance);
|
||||||
|
|
||||||
if (race.canUseEarth()) {
|
if (source.getAffinity() != SpellAffinity.BAD && target instanceof EntityPlayer) {
|
||||||
if (player.isSneaking()) {
|
force *= calculateAdjustedForce(PlayerSpeciesList.instance().getPlayer((EntityPlayer)target));
|
||||||
force *= 16;
|
}
|
||||||
|
|
||||||
|
applyForce(pos, target, force, distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.getPositionVector().subtract(pos);
|
||||||
|
|
||||||
|
target.addVelocity(
|
||||||
|
force / pos.x,
|
||||||
|
force / pos.y + (distance < 1 ? distance : 0),
|
||||||
|
force / pos.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a force to apply based on the given player's given race.
|
||||||
|
*/
|
||||||
|
protected double calculateAdjustedForce(IPlayer player) {
|
||||||
|
double force = 0.75;
|
||||||
|
|
||||||
|
if (player.getPlayerSpecies().canUseEarth()) {
|
||||||
|
force /= 2;
|
||||||
|
|
||||||
|
if (player.getOwner().isSneaking()) {
|
||||||
|
force /= 6;
|
||||||
}
|
}
|
||||||
} else if (race.canFly()) {
|
} else if (player.getPlayerSpecies().canFly()) {
|
||||||
force /= 2;
|
force *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ricochet(Entity projectile, BlockPos pos) {
|
/**
|
||||||
Vec3d position = new Vec3d(projectile.posX, projectile.posY, projectile.posZ);
|
* Reverses a projectiles direction to deflect it off the shield's surface.
|
||||||
|
*/
|
||||||
|
protected void ricochet(Entity projectile, Vec3d pos) {
|
||||||
|
Vec3d position = projectile.getPositionVector();
|
||||||
Vec3d motion = new Vec3d(projectile.motionX, projectile.motionY, projectile.motionZ);
|
Vec3d motion = new Vec3d(projectile.motionX, projectile.motionY, projectile.motionZ);
|
||||||
|
|
||||||
Vec3d normal = position.subtract(pos.getX(), pos.getY(), pos.getZ()).normalize();
|
Vec3d normal = position.subtract(pos).normalize();
|
||||||
Vec3d approach = motion.subtract(normal);
|
Vec3d approach = motion.subtract(normal);
|
||||||
|
|
||||||
if (approach.length() >= motion.length()) {
|
if (approach.length() >= motion.length()) {
|
||||||
ProjectileUtil.setThrowableHeading(projectile, normal.x, normal.y, normal.z, (float)motion.length(), 0);
|
ProjectileUtil.setThrowableHeading(projectile, normal, (float)motion.length(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package com.minelittlepony.util;
|
package com.minelittlepony.util;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.IProjectile;
|
import net.minecraft.entity.IProjectile;
|
||||||
import net.minecraft.entity.projectile.EntityArrow;
|
import net.minecraft.entity.projectile.EntityArrow;
|
||||||
import net.minecraft.entity.projectile.EntityFireball;
|
import net.minecraft.entity.projectile.EntityFireball;
|
||||||
import net.minecraft.entity.projectile.EntityLlamaSpit;
|
import net.minecraft.entity.projectile.EntityLlamaSpit;
|
||||||
import net.minecraft.entity.projectile.EntityThrowable;
|
import net.minecraft.entity.projectile.EntityThrowable;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class ProjectileUtil {
|
public class ProjectileUtil {
|
||||||
|
|
||||||
|
@ -30,8 +33,8 @@ public class ProjectileUtil {
|
||||||
* Checks if the given projectile was thrown by the given entity
|
* Checks if the given projectile was thrown by the given entity
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends Entity> boolean isProjectileThrownBy(Entity throwable, T e) {
|
public static <T extends Entity> boolean isProjectileThrownBy(Entity throwable, @Nullable T e) {
|
||||||
if (e == null || !isProjectile(throwable)) {
|
if (e == null || !isThrowable(throwable)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +44,7 @@ public class ProjectileUtil {
|
||||||
/**
|
/**
|
||||||
* Gets the thrower for a projectile or null
|
* Gets the thrower for a projectile or null
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends Entity> T getThrowingEntity(Entity throwable) {
|
public static <T extends Entity> T getThrowingEntity(Entity throwable) {
|
||||||
|
|
||||||
|
@ -63,22 +67,23 @@ public class ProjectileUtil {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the velocity and heading for a projectile.
|
* Sets the velocity and heading for a projectile.
|
||||||
*
|
*
|
||||||
* @param throwable The projectile
|
* @param throwable The projectile
|
||||||
* @param x X Direction component
|
* @param heading The directional heaving vector
|
||||||
* @param y Y Direction component
|
* @param velocity Velocity
|
||||||
* @param z Z Direction component
|
* @param inaccuracy Inaccuracy
|
||||||
* @param velocity Velocity
|
* @return True the projectile's heading was set, false otherwise
|
||||||
* @param inaccuracy Inaccuracy
|
*/
|
||||||
* @return True the projectile's heading was set, false otherwise
|
public static void setThrowableHeading(Entity throwable, Vec3d heading, float velocity, float inaccuracy) {
|
||||||
*/
|
|
||||||
public static void setThrowableHeading(Entity throwable, double x, double y, double z, float velocity, float inaccuracy) {
|
|
||||||
if (throwable instanceof IProjectile) {
|
if (throwable instanceof IProjectile) {
|
||||||
((IProjectile)throwable).shoot(x, y, z, velocity, inaccuracy);
|
((IProjectile)throwable).shoot(heading.x, heading.y, heading.z, velocity, inaccuracy);
|
||||||
} else {
|
} else {
|
||||||
((Entity)throwable).setVelocity(x, y, z);
|
heading = heading.normalize().scale(velocity);
|
||||||
|
|
||||||
|
throwable.addVelocity(heading.x - throwable.motionX, heading.y - throwable.motionY, heading.z - throwable.motionZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue