Added a custom shockwave particle when an earth pony stomps

This commit is contained in:
Sollace 2023-10-11 13:54:23 +01:00
parent fcab76fd43
commit 309e39b583
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
9 changed files with 189 additions and 25 deletions

View file

@ -156,6 +156,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
spawnEffectAround(player, center, radius, rad); spawnEffectAround(player, center, radius, rad);
ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0); ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
ParticleUtils.spawnParticle(player.getWorld(), UParticles.SHOCKWAVE, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
iplayer.subtractEnergyCost(rad); iplayer.subtractEnergyCost(rad);
iplayer.asEntity().addExhaustion(3); iplayer.asEntity().addExhaustion(3);

View file

@ -13,6 +13,7 @@ import com.minelittlepony.unicopia.client.particle.RainboomParticle;
import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle; import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle;
import com.minelittlepony.unicopia.client.particle.RaindropsParticle; import com.minelittlepony.unicopia.client.particle.RaindropsParticle;
import com.minelittlepony.unicopia.client.particle.RunesParticle; import com.minelittlepony.unicopia.client.particle.RunesParticle;
import com.minelittlepony.unicopia.client.particle.ShockwaveParticle;
import com.minelittlepony.unicopia.client.particle.SphereParticle; import com.minelittlepony.unicopia.client.particle.SphereParticle;
import com.minelittlepony.unicopia.client.render.*; import com.minelittlepony.unicopia.client.render.*;
import com.minelittlepony.unicopia.client.render.entity.*; import com.minelittlepony.unicopia.client.render.entity.*;
@ -54,6 +55,7 @@ public interface URenderers {
ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create)); ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create));
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.SHOCKWAVE, ShockwaveParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.MAGIC_RUNES, RunesParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.MAGIC_RUNES, RunesParticle::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);

View file

@ -8,6 +8,7 @@ import org.joml.Vector3f;
import com.minelittlepony.unicopia.EntityConvertable; import com.minelittlepony.unicopia.EntityConvertable;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.render.bezier.BezierSegment;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
import com.minelittlepony.unicopia.particle.ParticleHandle.Link; import com.minelittlepony.unicopia.particle.ParticleHandle.Link;
@ -66,16 +67,15 @@ public class RainbowTrailParticle extends AbstractBillboardParticle implements A
float alpha = 1 - (float)age / maxAge; float alpha = 1 - (float)age / maxAge;
for (int i = 0; i < segments.size() - 1; i++) { for (int i = 0; i < segments.size() - 1; i++) {
Vector3f[] corners = segments.get(i).getPlane(segments.get(i + 1)); BezierSegment corners = segments.get(i).getPlane(segments.get(i + 1));
float scale = getScale(tickDelta); float scale = getScale(tickDelta);
for (int k = 0; k < 4; ++k) { corners.forEachCorner(corner -> {
Vector3f corner = corners[k]; corner.mul(scale);
corner.mul(scale); corner.add(x, y, z);
corner.add(x, y, z); });
}
renderQuad(te, buffer, corners, segments.get(i).getAlpha() * alpha, tickDelta); renderQuad(te, buffer, corners.corners(), segments.get(i).getAlpha() * alpha, tickDelta);
} }
} }
@ -132,24 +132,8 @@ public class RainbowTrailParticle extends AbstractBillboardParticle implements A
return segments.indexOf(this) < segments.size() - 1 && age++ >= maxAge; return segments.indexOf(this) < segments.size() - 1 && age++ >= maxAge;
} }
Vector3f[] getPlane(Segment to) { BezierSegment getPlane(Segment to) {
float fromX = offset.x; return new BezierSegment(offset, to.offset, 1);
float toX = to.offset.x;
float fromZ = offset.z;
float toZ = to.offset.z;
float fromTopY = offset.y + 1;
float fromBottomY = offset.y;
float toTopY = to.offset.y + 1;
float toBottomY = to.offset.y;
return new Vector3f[]{
new Vector3f(fromX, fromBottomY, fromZ), // bottom left
new Vector3f(fromX, fromTopY, fromZ), // top left
new Vector3f(toX, toTopY, toZ), // top right
new Vector3f(toX, toBottomY, toZ) // bottom right
};
} }
} }
} }

View file

@ -0,0 +1,61 @@
package com.minelittlepony.unicopia.client.particle;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.render.RenderUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
public class ShockwaveParticle extends AbstractBillboardParticle {
private static final Identifier TEXTURE = Unicopia.id("textures/particles/shockwave.png");
public ShockwaveParticle(DefaultParticleType effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY,
double velocityZ) {
super(world, x, y, z, 0, 0, 0);
maxAge = 20;
setVelocity(0, 0, 0);
}
@Override
protected Identifier getTexture() {
return TEXTURE;
}
@Override
protected void renderQuads(Tessellator te, BufferBuilder buffer, float x, float y, float z, float tickDelta) {
if (age < 5 || age % 6 == 0) {
BlockState state = world.getBlockState(BlockPos.ofFloored(this.x, this.y - 0.5, this.z));
if (!state.isAir()) {
world.playSound(this.x, this.y, this.z, state.getSoundGroup().getBreakSound(), SoundCategory.AMBIENT, 2.5F, 0.4F, true);
}
}
MatrixStack matrices = new MatrixStack();
matrices.translate(x, y, z);
for (int ring = -1; ring < 2; ring ++) {
float scaleH = (1.5F + (age + tickDelta)) + ring;
float scaleV = (2 + MathHelper.sin(age / 5F) * 2F) - Math.abs(ring);
matrices.push();
matrices.scale(scaleH, scaleV, scaleH);
matrices.translate(-0.5, 0, -0.5);
int sides = 5;
for (int i = 0; i < sides; i++) {
RenderUtil.renderFace(matrices, te, buffer, red, green, blue, 0.3F, LightmapTextureManager.MAX_LIGHT_COORDINATE);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(360 / sides));
matrices.translate(-1, 0, 0);
}
matrices.pop();
}
}
}

View file

@ -0,0 +1,41 @@
package com.minelittlepony.unicopia.client.render;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
public class RenderUtil {
private static final Vector4f TEMP_VECTOR = new Vector4f();
public static final Vertex[] UNIT_FACE = new Vertex[] {
new Vertex(new Vector3f(0, 0, 0), 1, 1),
new Vertex(new Vector3f(0, 1, 0), 1, 0),
new Vertex(new Vector3f(1, 1, 0), 0, 0),
new Vertex(new Vector3f(1, 0, 0), 0, 1)
};
public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) {
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
Vertex[] UNIT_FACE = new Vertex[] {
new Vertex(new Vector3f(0, 0, 0), 1, 1),
new Vertex(new Vector3f(0, 1, 0), 1, 0),
new Vertex(new Vector3f(1, 1, 0), 0, 0),
new Vertex(new Vector3f(1, 0, 0), 0, 1)
};
Matrix4f transformation = matrices.peek().getPositionMatrix();
for (Vertex vertex : UNIT_FACE) {
transformation.transform(TEMP_VECTOR.set(vertex.position(), 1));
buffer.vertex(TEMP_VECTOR.x, TEMP_VECTOR.y, TEMP_VECTOR.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next();
}
te.draw();
}
record Vertex(Vector3f position, float u, float v) {}
}

View file

@ -0,0 +1,25 @@
package com.minelittlepony.unicopia.client.render.bezier;
import java.util.function.Consumer;
import org.joml.Vector3f;
public record BezierSegment(
Vector3f[] corners
) {
public BezierSegment(Vector3f from, Vector3f to, float height) {
this(new Vector3f[] {
new Vector3f(from.x, from.y - height/2F, from.z), // bottom left
new Vector3f(from.x, from.y + height/2F, from.z), // top left
new Vector3f(to.x, to.y + height/2F, to.z), // top right
new Vector3f(to.x, to.y - height/2F, to.z) // bottom right
});
}
public void forEachCorner(Consumer<Vector3f> transformer) {
for (var corner : corners) {
transformer.accept(corner);
}
}
}

View file

@ -0,0 +1,49 @@
package com.minelittlepony.unicopia.client.render.bezier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.joml.Vector3f;
import net.minecraft.util.math.Vec3d;
public class Ribbon implements Iterable<BezierSegment> {
public float width;
public float angle;
private final List<Node> nodes = new ArrayList<>();
private final List<BezierSegment> segments = new ArrayList<>();
private Node lastNode;
public Ribbon(Vec3d position, Vector3f bottom, Vector3f top, float angle) {
this.angle = angle;
lastNode = new Node(position, position.toVector3f().add(bottom), position.toVector3f().add(top));
nodes.add(lastNode);
}
public void addNode(Vec3d position, float angle) {
Vector3f directionVector = position.subtract(lastNode.position()).toVector3f();
Vector3f bottom = lastNode.bottom().add(directionVector).rotateAxis(angle, directionVector.x, directionVector.y, directionVector.z);
Vector3f top = lastNode.top().add(directionVector).rotateAxis(angle, directionVector.x, directionVector.y, directionVector.z);
Node oldNode = lastNode;
lastNode = new Node(position, bottom, top);
nodes.add(lastNode);
segments.add(new BezierSegment(new Vector3f[] {
oldNode.bottom(),
oldNode.top(),
lastNode.bottom(),
lastNode.top()
}));
}
@Override
public Iterator<BezierSegment> iterator() {
return segments.iterator();
}
record Node(Vec3d position, Vector3f bottom, Vector3f top) {
}
}

View file

@ -29,6 +29,7 @@ public interface UParticles {
DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", FabricParticleTypes.simple(true)); DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", FabricParticleTypes.simple(true));
DefaultParticleType LIGHTNING_BOLT = register("lightning_bolt", FabricParticleTypes.simple(true)); DefaultParticleType LIGHTNING_BOLT = register("lightning_bolt", FabricParticleTypes.simple(true));
DefaultParticleType SHOCKWAVE = register("shockwave", FabricParticleTypes.simple(true));
static <T extends ParticleType<?>> T register(String name, T type) { static <T extends ParticleType<?>> T register(String name, T type) {
return Registry.register(Registries.PARTICLE_TYPE, Unicopia.id(name), type); return Registry.register(Registries.PARTICLE_TYPE, Unicopia.id(name), type);

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB