Add a ground_pound particle and rework the ground pound ability to only trigger when you actually reach the ground

This commit is contained in:
Sollace 2021-02-05 21:19:41 +02:00
parent 120fd6eb38
commit 8f68b6414f
6 changed files with 130 additions and 82 deletions

View file

@ -6,25 +6,18 @@ import com.minelittlepony.unicopia.BlockDestructionManager;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony; 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.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper;
import com.minelittlepony.unicopia.util.WorldEvent; 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.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ShapeContext;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity; 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.BlockPos;
import net.minecraft.util.math.Box; import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
/** /**
@ -80,12 +73,15 @@ public class EarthPonyStompAbility implements Ability<Hit> {
PlayerEntity player = iplayer.getMaster(); PlayerEntity player = iplayer.getMaster();
BlockPos ppos = player.getBlockPos(); BlockPos ppos = player.getBlockPos();
BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld()); BlockPos pos = PosHelper.findSolidGroundAt(player.getEntityWorld(), ppos);
player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0); player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0);
iplayer.waitForFall(() -> {
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos());
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> { iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos())); double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
if (dist <= rad + 3) { if (dist <= rad + 3) {
double force = dist / 5; double force = dist / 5;
@ -113,7 +109,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
} }
}); });
BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> { 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)); double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true));
if (dist <= rad) { if (dist <= rad) {
@ -121,11 +117,10 @@ public class EarthPonyStompAbility implements Ability<Hit> {
} }
}); });
for (int i = 1; i < 202; i+= 2) { ParticleUtils.spawnParticle(player.world, UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
spawnParticleRing(player, i, 0);
}
iplayer.subtractEnergyCost(rad); iplayer.subtractEnergyCost(rad);
});
} }
private void spawnEffect(World w, BlockPos pos, double dist) { private void spawnEffect(World w, BlockPos pos, double dist) {
@ -155,43 +150,5 @@ public class EarthPonyStompAbility implements Ability<Hit> {
@Override @Override
public void postApply(Pony player, AbilitySlot slot) { 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;
} }
} }

View file

@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.client;
import com.minelittlepony.unicopia.UEntities; import com.minelittlepony.unicopia.UEntities;
import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle; import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle;
import com.minelittlepony.unicopia.client.particle.DiskParticle; 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.HealthDrainParticle;
import com.minelittlepony.unicopia.client.particle.MagicParticle; import com.minelittlepony.unicopia.client.particle.MagicParticle;
import com.minelittlepony.unicopia.client.particle.RainboomParticle; 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.RAINBOOM_TRAIL, RainbowTrailParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.SPHERE, SphereParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.SPHERE, SphereParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.DISK, DiskParticle::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())); EntityRendererRegistry.INSTANCE.register(UEntities.THROWN_ITEM, (manager, context) -> new FlyingItemEntityRenderer<>(manager, context.getItemRenderer()));

View file

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

View file

@ -99,6 +99,9 @@ public class Pony implements Caster<PlayerEntity>, Equine<PlayerEntity>, Transmi
private boolean invisible = false; private boolean invisible = false;
@Nullable
private Runnable landEvent;
public Pony(PlayerEntity player) { public Pony(PlayerEntity player) {
this.entity = player; this.entity = player;
this.mana = new ManaContainer(this); this.mana = new ManaContainer(this);
@ -325,6 +328,10 @@ public class Pony implements Caster<PlayerEntity>, Equine<PlayerEntity>, Transmi
} }
} }
public void waitForFall(Runnable action) {
landEvent = action;
}
public Optional<Float> onImpact(float distance, float damageMultiplier) { public Optional<Float> onImpact(float distance, float damageMultiplier) {
float g = gravity.getGravityModifier(); float g = gravity.getGravityModifier();
@ -351,6 +358,10 @@ public class Pony implements Caster<PlayerEntity>, Equine<PlayerEntity>, Transmi
} }
private void handleFall(float distance, float damageMultiplier) { private void handleFall(float distance, float damageMultiplier) {
if (landEvent != null) {
landEvent.run();
landEvent = null;
}
getSpellOrEmpty(DisguiseSpell.class, false).ifPresent(spell -> { getSpellOrEmpty(DisguiseSpell.class, false).ifPresent(spell -> {
spell.getDisguise().onImpact(this, distance, damageMultiplier); spell.getDisguise().onImpact(this, distance, damageMultiplier);
}); });

View file

@ -21,6 +21,8 @@ public interface UParticles {
ParticleType<FollowingParticleEffect> HEALTH_DRAIN = register("health_drain", FabricParticleTypes.complex(true, FollowingParticleEffect.FACTORY)); ParticleType<FollowingParticleEffect> HEALTH_DRAIN = register("health_drain", FabricParticleTypes.complex(true, FollowingParticleEffect.FACTORY));
DefaultParticleType GROUND_POUND = register("ground_pound", FabricParticleTypes.simple());
static <T extends ParticleType<?>> T register(String name, T type) { static <T extends ParticleType<?>> T register(String name, T type) {
return Registry.register(Registry.PARTICLE_TYPE, new Identifier("unicopia", name), type); return Registry.register(Registry.PARTICLE_TYPE, new Identifier("unicopia", name), type);
} }

View file

@ -0,0 +1,2 @@
{
}