mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 11:36:43 +01:00
Added a custom shockwave particle when an earth pony stomps
This commit is contained in:
parent
fcab76fd43
commit
309e39b583
9 changed files with 189 additions and 25 deletions
|
@ -156,6 +156,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
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.SHOCKWAVE, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
|
||||
|
||||
iplayer.subtractEnergyCost(rad);
|
||||
iplayer.asEntity().addExhaustion(3);
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.minelittlepony.unicopia.client.particle.RainboomParticle;
|
|||
import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.RaindropsParticle;
|
||||
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.render.*;
|
||||
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.RAINBOOM_RING, RainboomParticle::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.SPHERE, SphereParticle::new);
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.DISK, DiskParticle::new);
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.joml.Vector3f;
|
|||
|
||||
import com.minelittlepony.unicopia.EntityConvertable;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.client.render.bezier.BezierSegment;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Link;
|
||||
|
@ -66,16 +67,15 @@ public class RainbowTrailParticle extends AbstractBillboardParticle implements A
|
|||
float alpha = 1 - (float)age / maxAge;
|
||||
|
||||
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);
|
||||
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
Vector3f corner = corners[k];
|
||||
corner.mul(scale);
|
||||
corner.add(x, y, z);
|
||||
}
|
||||
corners.forEachCorner(corner -> {
|
||||
corner.mul(scale);
|
||||
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;
|
||||
}
|
||||
|
||||
Vector3f[] getPlane(Segment to) {
|
||||
float fromX = offset.x;
|
||||
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
|
||||
};
|
||||
BezierSegment getPlane(Segment to) {
|
||||
return new BezierSegment(offset, to.offset, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ public interface UParticles {
|
|||
DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", 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) {
|
||||
return Registry.register(Registries.PARTICLE_TYPE, Unicopia.id(name), type);
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Loading…
Reference in a new issue