mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Added a health drain particle for changelings, fixed changeling feed having too wide of a radius, and fixed particles not spawning on the clients
This commit is contained in:
parent
d02cd4226f
commit
6ffff32718
11 changed files with 180 additions and 24 deletions
|
@ -8,6 +8,7 @@ import javax.annotation.Nullable;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||
|
@ -79,7 +80,7 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
protected List<LivingEntity> getTargets(Pony player) {
|
||||
List<Entity> list = VecHelper.findInReach(player.getMaster(), 3, this::canDrain);
|
||||
List<Entity> list = VecHelper.findInRange(player.getMaster(), player.getWorld(), player.getOriginVector(), 3, this::canDrain);
|
||||
|
||||
RayTraceHelper.<LivingEntity>findEntity(player.getMaster(), 17, 1,
|
||||
looked -> looked instanceof LivingEntity && !list.contains(looked) && canDrain(looked))
|
||||
|
@ -122,6 +123,7 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
public float drainFrom(PlayerEntity changeling, LivingEntity living) {
|
||||
|
||||
DamageSource d = MagicalDamageSource.create("feed", changeling);
|
||||
|
||||
float damage = living.getHealth()/2;
|
||||
|
@ -131,6 +133,7 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
ParticleUtils.spawnParticles(UParticles.CHANGELING_MAGIC, living, 7);
|
||||
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, changeling, 0.2F), living, 1);
|
||||
|
||||
if (changeling.hasStatusEffect(StatusEffects.NAUSEA)) {
|
||||
StatusEffectInstance effect = changeling.getStatusEffect(StatusEffects.NAUSEA);
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.client;
|
|||
import com.minelittlepony.unicopia.UEntities;
|
||||
import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.DiskParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.HealthDrainParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.MagicParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.RainboomParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle;
|
||||
|
@ -24,6 +25,7 @@ public interface URenderers {
|
|||
ParticleFactoryRegistry.getInstance().register(UParticles.UNICORN_MAGIC, createFactory(MagicParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.CHANGELING_MAGIC, createFactory(ChangelingMagicParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new);
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.SPHERE, SphereParticle::new);
|
||||
|
@ -33,10 +35,10 @@ public interface URenderers {
|
|||
}
|
||||
|
||||
static <T extends ParticleEffect> PendingParticleFactory<T> createFactory(ParticleSupplier<T> supplier) {
|
||||
return provider -> (effect, world, x, y, z, dx, dy, dz) -> supplier.get(provider, world, x, y, z, dx, dy, dz);
|
||||
return provider -> (effect, world, x, y, z, dx, dy, dz) -> supplier.get(effect, provider, world, x, y, z, dx, dy, dz);
|
||||
}
|
||||
|
||||
interface ParticleSupplier<T extends ParticleEffect> {
|
||||
Particle get(SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz);
|
||||
Particle get(T effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ package com.minelittlepony.unicopia.client.particle;
|
|||
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
|
||||
public class ChangelingMagicParticle extends MagicParticle {
|
||||
|
||||
private final SpriteProvider provider;
|
||||
|
||||
public ChangelingMagicParticle(SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) {
|
||||
super(provider, world, x, y, z, dx, dy, dz, 1, 1, 1);
|
||||
public ChangelingMagicParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) {
|
||||
super(effect, provider, world, x, y, z, dx, dy, dz, 1, 1, 1);
|
||||
this.provider = provider;
|
||||
|
||||
float intensity = random.nextFloat() * 0.6F + 0.4F;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.minelittlepony.unicopia.client.particle;
|
||||
|
||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||
|
||||
import net.minecraft.client.particle.ParticleTextureSheet;
|
||||
import net.minecraft.client.particle.SpriteBillboardParticle;
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class HealthDrainParticle extends SpriteBillboardParticle {
|
||||
|
||||
private final FollowingParticleEffect effect;
|
||||
|
||||
public HealthDrainParticle(FollowingParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
|
||||
super(world, x, y, z, velocityX, velocityY, velocityZ);
|
||||
setSprite(provider);
|
||||
setMaxAge(3);
|
||||
scale(0.125F);
|
||||
this.effect = effect;
|
||||
this.collidesWithWorld = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleTextureSheet getType() {
|
||||
return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
Vec3d target = effect.getTarget(world);
|
||||
Vec3d pos = new Vec3d(x, y, z);
|
||||
|
||||
if (this.scale * 1.5F < 0.5F) {
|
||||
scale(1.5F);
|
||||
}
|
||||
|
||||
double distance = pos.distanceTo(target);
|
||||
if (distance > 1) {
|
||||
age = 0;
|
||||
}
|
||||
|
||||
Vec3d motion = target.subtract(pos).normalize().multiply(Math.min(distance, effect.getSpeed()));
|
||||
move(motion.x, motion.y, motion.z);
|
||||
}
|
||||
}
|
|
@ -4,13 +4,14 @@ import net.minecraft.client.particle.ParticleTextureSheet;
|
|||
import net.minecraft.client.particle.SpriteBillboardParticle;
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
|
||||
public class MagicParticle extends SpriteBillboardParticle {
|
||||
private double startX;
|
||||
private double startY;
|
||||
private double startZ;
|
||||
|
||||
MagicParticle(SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ, float r, float g, float b) {
|
||||
MagicParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ, float r, float g, float b) {
|
||||
super(w, x, y, z);
|
||||
setSprite(provider);
|
||||
|
||||
|
@ -28,8 +29,8 @@ public class MagicParticle extends SpriteBillboardParticle {
|
|||
colorBlue = b;
|
||||
}
|
||||
|
||||
public MagicParticle(SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ) {
|
||||
this(provider, w, x, y, z, vX, vY, vZ, 1, 1, 1);
|
||||
public MagicParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ) {
|
||||
this(effect, provider, w, x, y, z, vX, vY, vZ, 1, 1, 1);
|
||||
|
||||
colorAlpha = 0.7F;
|
||||
colorGreen *= 0.3F;
|
||||
|
|
|
@ -3,10 +3,11 @@ package com.minelittlepony.unicopia.client.particle;
|
|||
import net.minecraft.client.particle.RainSplashParticle;
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
|
||||
public class RaindropsParticle extends RainSplashParticle {
|
||||
|
||||
public RaindropsParticle(SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) {
|
||||
public RaindropsParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) {
|
||||
super(world, x, y, z);
|
||||
velocityY = -0.1;
|
||||
maxAge += 19;
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package com.minelittlepony.unicopia.particle;
|
||||
|
||||
import java.util.Locale;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
import net.minecraft.particle.ParticleType;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class FollowingParticleEffect implements ParticleEffect {
|
||||
public static final ParticleEffect.Factory<FollowingParticleEffect> FACTORY = new ParticleEffect.Factory<FollowingParticleEffect>() {
|
||||
@Override
|
||||
public FollowingParticleEffect read(ParticleType<FollowingParticleEffect> type, StringReader reader) throws CommandSyntaxException {
|
||||
reader.expect(' ');
|
||||
double x = reader.readDouble();
|
||||
reader.expect(' ');
|
||||
double y = reader.readDouble();
|
||||
reader.expect(' ');
|
||||
double z = reader.readDouble();
|
||||
reader.expect(' ');
|
||||
float speed = reader.readFloat();
|
||||
return new FollowingParticleEffect(type, -1, new Vec3d(x, y, z), speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FollowingParticleEffect read(ParticleType<FollowingParticleEffect> particleType, PacketByteBuf buf) {
|
||||
return new FollowingParticleEffect(particleType, buf.readInt(), new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
};
|
||||
|
||||
private final ParticleType<FollowingParticleEffect> type;
|
||||
|
||||
private Vec3d fixedTarget;
|
||||
|
||||
private int movingTarget;
|
||||
|
||||
private final float followSpeed;
|
||||
|
||||
public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Vec3d target, float followSpeed) {
|
||||
this.type = type;
|
||||
this.fixedTarget = target;
|
||||
this.movingTarget = -1;
|
||||
this.followSpeed = followSpeed;
|
||||
}
|
||||
|
||||
public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Entity target, float followSpeed) {
|
||||
this(type, target.getEntityId(), target.getCameraPosVec(1), followSpeed);
|
||||
}
|
||||
|
||||
private FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, int movingTarget, Vec3d fixedTarget, float followSpeed) {
|
||||
this.type = type;
|
||||
this.movingTarget = movingTarget;
|
||||
this.fixedTarget = fixedTarget;
|
||||
this.followSpeed = followSpeed;
|
||||
}
|
||||
|
||||
public Vec3d getTarget(World world) {
|
||||
if (movingTarget > -1) {
|
||||
Entity e = world.getEntityById(movingTarget);
|
||||
if (e != null) {
|
||||
fixedTarget = e.getCameraPosVec(1);
|
||||
} else {
|
||||
movingTarget = -1;
|
||||
}
|
||||
}
|
||||
return fixedTarget;
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return followSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleType<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf buf) {
|
||||
buf.writeInt(movingTarget);
|
||||
buf.writeDouble(fixedTarget.x);
|
||||
buf.writeDouble(fixedTarget.y);
|
||||
buf.writeDouble(fixedTarget.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f", Registry.PARTICLE_TYPE.getId(getType()), fixedTarget.x, fixedTarget.y, fixedTarget.z, followSpeed);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,8 @@ import com.minelittlepony.unicopia.util.shape.Sphere;
|
|||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Utility for spawning particles.
|
||||
|
@ -18,11 +20,20 @@ public final class ParticleUtils {
|
|||
Shape shape = new Sphere(false, Math.abs((float)halfDist + entity.getWidth()));
|
||||
|
||||
shape.randomPoints(count, entity.world.random).forEach(point -> {
|
||||
entity.world.addParticle(particleId,
|
||||
spawnParticle(entity.world, particleId,
|
||||
entity.getX() + point.x,
|
||||
middle + point.y,
|
||||
entity.getZ() + point.z,
|
||||
0, 0, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public static void spawnParticle(World world, ParticleEffect effect, double x, double y, double z, double vX, double vY, double vZ) {
|
||||
if (world instanceof ServerWorld) {
|
||||
((ServerWorld)world).spawnParticles(effect, x, y, z, 1, vX, vY, vZ, 0);
|
||||
} else {
|
||||
world.addParticle(effect, x, y, z, vX, vY, vZ);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ public interface UParticles {
|
|||
ParticleType<SphereParticleEffect> SPHERE = register("sphere", FabricParticleTypes.complex(true, SphereParticleEffect.FACTORY));
|
||||
ParticleType<DiskParticleEffect> DISK = register("disk", FabricParticleTypes.complex(true, DiskParticleEffect.FACTORY));
|
||||
|
||||
ParticleType<FollowingParticleEffect> HEALTH_DRAIN = register("health_drain", FabricParticleTypes.complex(true, FollowingParticleEffect.FACTORY));
|
||||
|
||||
static <T extends ParticleType<?>> T register(String name, T type) {
|
||||
return Registry.register(Registry.PARTICLE_TYPE, new Identifier("unicopia", name), type);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.function.Predicate;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -23,17 +22,4 @@ public interface VecHelper {
|
|||
static List<Entity> findInRange(@Nullable Entity origin, World w, Vec3d pos, double radius, @Nullable Predicate<Entity> predicate) {
|
||||
return w.getOtherEntities(origin, Box.method_29968(pos).expand(radius), predicate == null ? inRange(pos, radius) : inRange(pos, radius).and(predicate));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all entities within a given range from the player.
|
||||
*/
|
||||
static List<Entity> findInReach(PlayerEntity player, double reach, @Nullable Predicate<? super Entity> predicate) {
|
||||
Vec3d look = player.getCameraPosVec(1).multiply(reach);
|
||||
|
||||
return player.world.getOtherEntities(player, player
|
||||
.getBoundingBox()
|
||||
.expand(look.x, look.y, look.z)
|
||||
.expand(1, 1, 1), predicate);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"textures": [
|
||||
"minecraft:heart"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue