mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-08 06:26:43 +01:00
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:
parent
120fd6eb38
commit
8f68b6414f
6 changed files with 130 additions and 82 deletions
|
@ -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,52 +73,54 @@ 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.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
iplayer.waitForFall(() -> {
|
||||||
double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos()));
|
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos());
|
||||||
|
|
||||||
if (dist <= rad + 3) {
|
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
||||||
double force = dist / 5;
|
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
|
||||||
i.addVelocity(
|
|
||||||
-(player.getX() - i.getX()) / force,
|
|
||||||
-(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0),
|
|
||||||
-(player.getZ() - i.getZ()) / force);
|
|
||||||
|
|
||||||
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) {
|
double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist;
|
||||||
Race race = Pony.of((PlayerEntity)i).getSpecies();
|
|
||||||
if (race.canUseEarth()) {
|
if (i instanceof PlayerEntity) {
|
||||||
amount /= 3;
|
Race race = Pony.of((PlayerEntity)i).getSpecies();
|
||||||
|
if (race.canUseEarth()) {
|
||||||
|
amount /= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (race.canFly()) {
|
||||||
|
amount *= 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (race.canFly()) {
|
i.damage(damage, (float)amount);
|
||||||
amount *= 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
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) {
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
{
|
||||||
|
}
|
Loading…
Reference in a new issue