From 8f68b6414f41dd2f7029ba69e8bf1dcce9fbd9d2 Mon Sep 17 00:00:00 2001 From: Sollace Date: Fri, 5 Feb 2021 21:19:41 +0200 Subject: [PATCH] Add a ground_pound particle and rework the ground pound ability to only trigger when you actually reach the ground --- .../ability/EarthPonyStompAbility.java | 121 ++++++------------ .../unicopia/client/URenderers.java | 2 + .../client/particle/GroundPoundParticle.java | 74 +++++++++++ .../unicopia/entity/player/Pony.java | 11 ++ .../unicopia/particle/UParticles.java | 2 + .../unicopia/particles/ground_pound.json | 2 + 6 files changed, 130 insertions(+), 82 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java create mode 100644 src/main/resources/assets/unicopia/particles/ground_pound.json diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index fae15b96..e96b397b 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -6,25 +6,18 @@ import com.minelittlepony.unicopia.BlockDestructionManager; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.particle.ParticleUtils; +import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.util.MagicalDamageSource; +import com.minelittlepony.unicopia.util.PosHelper; import com.minelittlepony.unicopia.util.WorldEvent; -import com.minelittlepony.unicopia.util.shape.Shape; -import com.minelittlepony.unicopia.util.shape.Sphere; - -import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.ShapeContext; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.particle.BlockStateParticleEffect; -import net.minecraft.particle.ParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; /** @@ -80,52 +73,54 @@ public class EarthPonyStompAbility implements Ability { PlayerEntity player = iplayer.getMaster(); BlockPos ppos = player.getBlockPos(); - BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld()); + BlockPos pos = PosHelper.findSolidGroundAt(player.getEntityWorld(), ppos); player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0); - iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { - double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos())); + iplayer.waitForFall(() -> { + BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos()); - if (dist <= rad + 3) { - double force = dist / 5; - i.addVelocity( - -(player.getX() - i.getX()) / force, - -(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0), - -(player.getZ() - i.getZ()) / force); + iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { + double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos())); - DamageSource damage = MagicalDamageSource.create("smash", player); + if (dist <= rad + 3) { + double force = dist / 5; + i.addVelocity( + -(player.getX() - i.getX()) / force, + -(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0), + -(player.getZ() - i.getZ()) / force); - double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist; + DamageSource damage = MagicalDamageSource.create("smash", player); - if (i instanceof PlayerEntity) { - Race race = Pony.of((PlayerEntity)i).getSpecies(); - if (race.canUseEarth()) { - amount /= 3; + double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist; + + if (i instanceof PlayerEntity) { + Race race = Pony.of((PlayerEntity)i).getSpecies(); + if (race.canUseEarth()) { + amount /= 3; + } + + if (race.canFly()) { + amount *= 4; + } } - if (race.canFly()) { - amount *= 4; - } + i.damage(damage, (float)amount); } + }); - i.damage(damage, (float)amount); - } + BlockPos.iterate(center.add(-rad, -rad, -rad), center.add(rad, rad, rad)).forEach(i -> { + double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true)); + + if (dist <= rad) { + spawnEffect(player.world, i, dist); + } + }); + + ParticleUtils.spawnParticle(player.world, UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0); + + iplayer.subtractEnergyCost(rad); }); - - BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> { - double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true)); - - if (dist <= rad) { - spawnEffect(player.world, i, dist); - } - }); - - for (int i = 1; i < 202; i+= 2) { - spawnParticleRing(player, i, 0); - } - - iplayer.subtractEnergyCost(rad); } private void spawnEffect(World w, BlockPos pos, double dist) { @@ -155,43 +150,5 @@ public class EarthPonyStompAbility implements Ability { @Override public void postApply(Pony player, AbilitySlot slot) { - int timeDiff = getCooldownTime(player) - player.getAbilities().getStat(slot).getRemainingCooldown(); - - if (player.getMaster().getEntityWorld().getTime() % 1 == 0 || timeDiff == 0) { - spawnParticleRing(player.getMaster(), timeDiff, 1); - } - } - - private void spawnParticleRing(PlayerEntity player, int timeDiff, double yVel) { - int animationTicks = timeDiff / 7; - if (animationTicks < 6) { - Shape shape = new Sphere(true, animationTicks, 1, 0, 1); - - double y = 0.5 + (Math.sin(animationTicks) * 1.5); - - yVel *= y * 5; - - for (int i = 0; i < shape.getVolumeOfSpawnableSpace(); i++) { - Vec3d point = shape.computePoint(player.getEntityWorld().random).add(player.getPos()); - player.world.addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, Blocks.DIRT.getDefaultState()), - point.x, - point.y, - point.z, - 0, yVel, 0 - ); - } - } - } - - private static BlockPos getSolidBlockBelow(BlockPos pos, World w) { - while (!World.isOutOfBuildLimitVertically(pos)) { - pos = pos.down(); - - if (Block.isFaceFullSquare(w.getBlockState(pos).getCollisionShape(w, pos, ShapeContext.absent()), Direction.UP)) { - return pos; - } - } - - return pos; } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index afdd1c3c..6d42b8d7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -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.GroundPoundParticle; import com.minelittlepony.unicopia.client.particle.HealthDrainParticle; import com.minelittlepony.unicopia.client.particle.MagicParticle; import com.minelittlepony.unicopia.client.particle.RainboomParticle; @@ -33,6 +34,7 @@ public interface URenderers { ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.SPHERE, SphereParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.DISK, DiskParticle::new); + ParticleFactoryRegistry.getInstance().register(UParticles.GROUND_POUND, GroundPoundParticle::new); EntityRendererRegistry.INSTANCE.register(UEntities.THROWN_ITEM, (manager, context) -> new FlyingItemEntityRenderer<>(manager, context.getItemRenderer())); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java new file mode 100644 index 00000000..2b804314 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/GroundPoundParticle.java @@ -0,0 +1,74 @@ +package com.minelittlepony.unicopia.client.particle; + +import com.minelittlepony.unicopia.util.shape.Shape; +import com.minelittlepony.unicopia.util.shape.Sphere; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleTextureSheet; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.BlockStateParticleEffect; +import net.minecraft.particle.DefaultParticleType; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class GroundPoundParticle extends Particle { + + public GroundPoundParticle(DefaultParticleType effect, ClientWorld world, double x, double y, double z, double dX, double dY, double dZ) { + super(world, x, y, z, dX, dY, dZ); + maxAge = 10; + } + + @Override + public ParticleTextureSheet getType() { + return ParticleTextureSheet.NO_RENDER; + } + + @Override + public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float f) { + } + + @Override + public void tick() { + super.tick(); + + spawnParticleRing(age, 1); + } + + + private void spawnParticleRing(int timeDiff, double yVel) { + + Shape shape = new Sphere(true, timeDiff, 1, 0, 1); + + double y = 0.5 + (Math.sin(timeDiff) * 2.5); + + yVel *= y * 5; + + Vec3d center = new Vec3d(x, this.y, z); + for (int i = 0; i < shape.getVolumeOfSpawnableSpace(); i++) { + Vec3d point = shape.computePoint(random).add(center); + + BlockPos pos = new BlockPos(point.x, center.y - 1, point.z); + + BlockState state = world.getBlockState(pos); + if (state.isAir()) { + state = world.getBlockState(pos.down()); + if (state.isAir()) { + state = Blocks.DIRT.getDefaultState(); + } + } + + world.addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, state), + point.x, + point.y, + point.z, + 0, yVel, 0 + ); + } + } + +} 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 5764f5cf..a01da91b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -99,6 +99,9 @@ public class Pony implements Caster, Equine, Transmi private boolean invisible = false; + @Nullable + private Runnable landEvent; + public Pony(PlayerEntity player) { this.entity = player; this.mana = new ManaContainer(this); @@ -325,6 +328,10 @@ public class Pony implements Caster, Equine, Transmi } } + public void waitForFall(Runnable action) { + landEvent = action; + } + public Optional onImpact(float distance, float damageMultiplier) { float g = gravity.getGravityModifier(); @@ -351,6 +358,10 @@ public class Pony implements Caster, Equine, Transmi } private void handleFall(float distance, float damageMultiplier) { + if (landEvent != null) { + landEvent.run(); + landEvent = null; + } getSpellOrEmpty(DisguiseSpell.class, false).ifPresent(spell -> { spell.getDisguise().onImpact(this, distance, damageMultiplier); }); diff --git a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java index 3f65546d..d3ec7d0a 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java @@ -21,6 +21,8 @@ public interface UParticles { ParticleType HEALTH_DRAIN = register("health_drain", FabricParticleTypes.complex(true, FollowingParticleEffect.FACTORY)); + DefaultParticleType GROUND_POUND = register("ground_pound", FabricParticleTypes.simple()); + static > T register(String name, T type) { return Registry.register(Registry.PARTICLE_TYPE, new Identifier("unicopia", name), type); } diff --git a/src/main/resources/assets/unicopia/particles/ground_pound.json b/src/main/resources/assets/unicopia/particles/ground_pound.json new file mode 100644 index 00000000..2c63c085 --- /dev/null +++ b/src/main/resources/assets/unicopia/particles/ground_pound.json @@ -0,0 +1,2 @@ +{ +}